draw_frame.cpp 36.6 KB
Newer Older
1 2 3
/*
 * This program source code file is part of KiCad, a free EDA CAD application.
 *
4
 * Copyright (C) 2004 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.fr
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 * Copyright (C) 2008-2011 Wayne Stambaugh <stambaughw@verizon.net>
 * Copyright (C) 2004-2011 KiCad Developers, see change_log.txt for contributors.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you may find one here:
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * or you may search the http://www.gnu.org website for the version 2 license,
 * or you may write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 */
plyatov's avatar
plyatov committed
25

26 27 28
/**
 * @file drawframe.cpp
 */
plyatov's avatar
plyatov committed
29

30
#include <fctsys.h>
31 32
#include <pgm_base.h>
#include <kiface_i.h>
33 34 35 36 37 38
#include <gr_basic.h>
#include <common.h>
#include <bitmaps.h>
#include <macros.h>
#include <id.h>
#include <class_drawpanel.h>
39
#include <class_draw_panel_gal.h>
40
#include <class_base_screen.h>
41
#include <msgpanel.h>
42
#include <draw_frame.h>
43 44 45
#include <confirm.h>
#include <kicad_device_context.h>
#include <dialog_helpers.h>
46
#include <base_units.h>
47
#include <math/box2.h>
plyatov's avatar
plyatov committed
48

49
#include <wx/fontdlg.h>
50
#include <view/view.h>
51
#include <view/view_controls.h>
52
#include <gal/graphics_abstraction_layer.h>
plyatov's avatar
plyatov committed
53

54 55 56
/**
 * Definition for enabling and disabling scroll bar setting trace output.  See the
 * wxWidgets documentation on useing the WXTRACE environment variable.
57
 */
58
static const wxString traceScrollSettings( wxT( "KicadScrollSettings" ) );
59 60


61
// Configuration entry names.
charras's avatar
charras committed
62 63 64
static const wxString CursorShapeEntryKeyword( wxT( "CursorShape" ) );
static const wxString ShowGridEntryKeyword( wxT( "ShowGrid" ) );
static const wxString GridColorEntryKeyword( wxT( "GridColor" ) );
65
static const wxString LastGridSizeIdKeyword( wxT( "_LastGridSize" ) );
66 67


Dick Hollenbeck's avatar
Dick Hollenbeck committed
68
BEGIN_EVENT_TABLE( EDA_DRAW_FRAME, KIWAY_PLAYER )
69 70 71
    EVT_MOUSEWHEEL( EDA_DRAW_FRAME::OnMouseEvent )
    EVT_MENU_OPEN( EDA_DRAW_FRAME::OnMenuOpen )
    EVT_ACTIVATE( EDA_DRAW_FRAME::OnActivate )
72
    EVT_MENU_RANGE( ID_ZOOM_IN, ID_ZOOM_REDRAW, EDA_DRAW_FRAME::OnZoom )
73
    EVT_MENU_RANGE( ID_OFFCENTER_ZOOM_IN, ID_OFFCENTER_ZOOM_OUT, EDA_DRAW_FRAME::OnZoom )
74
    EVT_MENU_RANGE( ID_POPUP_ZOOM_START_RANGE, ID_POPUP_ZOOM_END_RANGE,
75
                    EDA_DRAW_FRAME::OnZoom )
76
    EVT_MENU_RANGE( ID_POPUP_GRID_LEVEL_1000, ID_POPUP_GRID_USER,
77
                    EDA_DRAW_FRAME::OnSelectGrid )
78 79 80 81 82 83 84 85 86 87 88 89

    EVT_TOOL( ID_TB_OPTIONS_SHOW_GRID, EDA_DRAW_FRAME::OnToggleGridState )
    EVT_TOOL_RANGE( ID_TB_OPTIONS_SELECT_UNIT_MM, ID_TB_OPTIONS_SELECT_UNIT_INCH,
                    EDA_DRAW_FRAME::OnSelectUnits )
    EVT_TOOL( ID_TB_OPTIONS_SELECT_CURSOR, EDA_DRAW_FRAME::OnToggleCrossHairStyle )

    EVT_UPDATE_UI( wxID_UNDO, EDA_DRAW_FRAME::OnUpdateUndo )
    EVT_UPDATE_UI( wxID_REDO, EDA_DRAW_FRAME::OnUpdateRedo )
    EVT_UPDATE_UI( ID_TB_OPTIONS_SHOW_GRID, EDA_DRAW_FRAME::OnUpdateGrid )
    EVT_UPDATE_UI( ID_TB_OPTIONS_SELECT_CURSOR, EDA_DRAW_FRAME::OnUpdateCrossHairStyle )
    EVT_UPDATE_UI_RANGE( ID_TB_OPTIONS_SELECT_UNIT_MM, ID_TB_OPTIONS_SELECT_UNIT_INCH,
                         EDA_DRAW_FRAME::OnUpdateUnits )
90 91 92
END_EVENT_TABLE()


93
EDA_DRAW_FRAME::EDA_DRAW_FRAME( KIWAY* aKiway, wxWindow* aParent,
94
                                FRAME_T aFrameType,
95 96 97
                                const wxString& aTitle,
                                const wxPoint& aPos, const wxSize& aSize,
                                long aStyle, const wxString & aFrameName ) :
98
    KIWAY_PLAYER( aKiway, aParent, aFrameType, aTitle, aPos, aSize, aStyle, aFrameName )
dickelbeck's avatar
dickelbeck committed
99
{
100 101 102 103
    m_drawToolBar         = NULL;
    m_optionsToolBar      = NULL;
    m_gridSelectBox       = NULL;
    m_zoomSelectBox       = NULL;
104
    m_HotkeysZoomAndGridList = NULL;
105

106
    m_canvas              = NULL;
107 108
    m_galCanvas           = NULL;
    m_galCanvasActive     = false;
109
    m_messagePanel        = NULL;
110
    m_currentScreen       = NULL;
111
    m_toolId              = ID_NO_TOOL_SELECTED;
112 113 114 115 116
    m_lastDrawToolId      = ID_NO_TOOL_SELECTED;
    m_showAxis            = false;      // true to draw axis.
    m_showBorderAndTitleBlock = false;  // true to display reference sheet.
    m_showGridAxis        = false;      // true to draw the grid axis
    m_cursorShape         = 0;
117
    m_LastGridSizeId      = 0;
118
    m_DrawGrid            = true;       // hide/Show grid. default = show
charras's avatar
charras committed
119
    m_GridColor           = DARKGRAY;   // Grid color
120 121
    m_showPageLimits      = false;
    m_drawBgColor         = BLACK;      // the background color of the draw canvas:
122
                                        // BLACK for Pcbnew, BLACK or WHITE for eeschema
123
    m_snapToGrid          = true;
124
    m_MsgFrameHeight      = EDA_MSG_PANEL::GetRequiredHeight();
Lorenzo Marcantonio's avatar
Lorenzo Marcantonio committed
125
    m_movingCursorWithKeyboard = false;
126

127 128
    m_auimgr.SetFlags(wxAUI_MGR_DEFAULT|wxAUI_MGR_LIVE_RESIZE);

dickelbeck's avatar
dickelbeck committed
129
    CreateStatusBar( 6 );
130 131 132 133 134 135 136

    // set the size of the status bar subwindows:

    wxWindow* stsbar = GetStatusBar();

    int dims[] = {

137
        // remainder of status bar on far left is set to a default or whatever is left over.
138 139
        -1,

140
        // When using GetTextSize() remember the width of character '1' is not the same
141 142 143 144 145 146 147 148 149 150 151 152
        // as the width of '0' unless the font is fixed width, and it usually won't be.

        // zoom:
        GetTextSize( wxT( "Z 762000" ), stsbar ).x + 10,

        // cursor coords
        GetTextSize( wxT( "X 0234.567890  Y 0234.567890" ), stsbar ).x + 10,

        // delta distances
        GetTextSize( wxT( "dx 0234.567890  dx 0234.567890  d 0234.567890" ), stsbar ).x + 10,

        // units display, Inches is bigger than mm
jean-pierre charras's avatar
jean-pierre charras committed
153
        GetTextSize( _( "Inches" ), stsbar ).x + 10,
154

155 156 157
        // Size for the panel used as "Current tool in play": will take longest string from
        // void PCB_EDIT_FRAME::OnSelectTool( wxCommandEvent& aEvent ) in pcbnew/edit.cpp
        GetTextSize( wxT( "Add layer alignment target" ), stsbar ).x + 10,
158 159 160
    };

    SetStatusWidths( DIM( dims ), dims );
dickelbeck's avatar
dickelbeck committed
161 162

    // Create child subwindows.
163
    GetClientSize( &m_FrameSize.x, &m_FrameSize.y );
dickelbeck's avatar
dickelbeck committed
164 165 166
    m_FramePos.x   = m_FramePos.y = 0;
    m_FrameSize.y -= m_MsgFrameHeight;

167
    m_canvas = new EDA_DRAW_PANEL( this, -1, wxPoint( 0, 0 ), m_FrameSize );
168 169
    m_messagePanel  = new EDA_MSG_PANEL( this, -1, wxPoint( 0, m_FrameSize.y ),
                                         wxSize( m_FrameSize.x, m_MsgFrameHeight ) );
170

171
    m_messagePanel->SetBackgroundColour( MakeColour( LIGHTGRAY ) );
plyatov's avatar
plyatov committed
172 173
}

dickelbeck's avatar
dickelbeck committed
174

175
EDA_DRAW_FRAME::~EDA_DRAW_FRAME()
plyatov's avatar
plyatov committed
176
{
177 178
    delete m_currentScreen;
    m_currentScreen = NULL;
179

180
    m_auimgr.UnInit();
plyatov's avatar
plyatov committed
181 182 183
}


184 185 186 187 188 189 190
void EDA_DRAW_FRAME::unitsChangeRefresh()
{
    UpdateStatusBar();

    EDA_ITEM* item = GetScreen()->GetCurItem();

    if( item )
191
        SetMsgPanel( item );
192 193 194
}


195
void EDA_DRAW_FRAME::EraseMsgBox()
plyatov's avatar
plyatov committed
196
{
197 198
    if( m_messagePanel )
        m_messagePanel->EraseMsgBox();
plyatov's avatar
plyatov committed
199 200 201
}


202
void EDA_DRAW_FRAME::OnActivate( wxActivateEvent& event )
plyatov's avatar
plyatov committed
203
{
dickelbeck's avatar
dickelbeck committed
204
    m_FrameIsActive = event.GetActive();
205

206
    if( m_canvas )
207
        m_canvas->SetCanStartBlock( -1 );
plyatov's avatar
plyatov committed
208

dickelbeck's avatar
dickelbeck committed
209
    event.Skip();   // required under wxMAC
plyatov's avatar
plyatov committed
210 211 212
}


213
void EDA_DRAW_FRAME::OnMenuOpen( wxMenuEvent& event )
plyatov's avatar
plyatov committed
214
{
215
    if( m_canvas )
216
        m_canvas->SetCanStartBlock( -1 );
217

dickelbeck's avatar
dickelbeck committed
218
    event.Skip();
plyatov's avatar
plyatov committed
219 220
}

221 222 223 224 225 226 227 228 229
/* function SkipNextLeftButtonReleaseEvent
 * after calling this function, if the left mouse button
 * is down, the next left mouse button release event will be ignored.
 * It is is usefull for instance when closing a dialog on a mouse click,
 * to skip the next mouse left button release event
 * by the parent window, because the mouse button
 * clicked on the dialog is often released in the parent frame,
 * and therefore creates a left button released mouse event
 * which can be unwanted in some cases
230
 */
231
void EDA_DRAW_FRAME::SkipNextLeftButtonReleaseEvent()
232 233 234
{
   m_canvas->SetIgnoreLeftButtonReleaseEvent( true );
}
plyatov's avatar
plyatov committed
235

236 237 238
void EDA_DRAW_FRAME::OnToggleGridState( wxCommandEvent& aEvent )
{
    SetGridVisibility( !IsGridVisible() );
239
    if( IsGalCanvasActive() )
240
    {
241 242
        GetGalCanvas()->GetGAL()->SetGridVisibility( IsGridVisible() );
        GetGalCanvas()->GetView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
243
    }
244

245
    m_canvas->Refresh();
246 247 248 249 250 251 252 253
}


void EDA_DRAW_FRAME::OnSelectUnits( wxCommandEvent& aEvent )
{
    if( aEvent.GetId() == ID_TB_OPTIONS_SELECT_UNIT_MM && g_UserUnit != MILLIMETRES )
    {
        g_UserUnit = MILLIMETRES;
254
        unitsChangeRefresh();
255 256 257 258
    }
    else if( aEvent.GetId() == ID_TB_OPTIONS_SELECT_UNIT_INCH && g_UserUnit != INCHES )
    {
        g_UserUnit = INCHES;
259
        unitsChangeRefresh();
260 261 262 263 264 265
    }
}


void EDA_DRAW_FRAME::OnToggleCrossHairStyle( wxCommandEvent& aEvent )
{
266 267
    INSTALL_UNBUFFERED_DC( dc, m_canvas );
    m_canvas->CrossHairOff( &dc );
268
    m_cursorShape = !m_cursorShape;
269
    m_canvas->CrossHairOn( &dc );
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
}


void EDA_DRAW_FRAME::OnUpdateUndo( wxUpdateUIEvent& aEvent )
{
    if( GetScreen() )
        aEvent.Enable( GetScreen()->GetUndoCommandCount() > 0 );
}


void EDA_DRAW_FRAME::OnUpdateRedo( wxUpdateUIEvent& aEvent )
{
    if( GetScreen() )
        aEvent.Enable( GetScreen()->GetRedoCommandCount() > 0 );
}


void EDA_DRAW_FRAME::OnUpdateUnits( wxUpdateUIEvent& aEvent )
{
    bool enable;

    enable = ( ((aEvent.GetId() == ID_TB_OPTIONS_SELECT_UNIT_MM) && (g_UserUnit == MILLIMETRES))
            || ((aEvent.GetId() == ID_TB_OPTIONS_SELECT_UNIT_INCH) && (g_UserUnit == INCHES)) );

    aEvent.Check( enable );
    DisplayUnitsMsg();
}


void EDA_DRAW_FRAME::OnUpdateGrid( wxUpdateUIEvent& aEvent )
{
    wxString tool_tip = IsGridVisible() ? _( "Hide grid" ) : _( "Show grid" );

    aEvent.Check( IsGridVisible() );
304
    m_optionsToolBar->SetToolShortHelp( ID_TB_OPTIONS_SHOW_GRID, tool_tip );
305 306 307 308 309
}


void EDA_DRAW_FRAME::OnUpdateCrossHairStyle( wxUpdateUIEvent& aEvent )
{
310
    aEvent.Check( m_cursorShape );
311 312 313
}


314
void EDA_DRAW_FRAME::ReCreateAuxiliaryToolbar()
plyatov's avatar
plyatov committed
315 316 317
{
}

dickelbeck's avatar
dickelbeck committed
318

319
void EDA_DRAW_FRAME::ReCreateMenuBar()
plyatov's avatar
plyatov committed
320 321 322
{
}

dickelbeck's avatar
dickelbeck committed
323

324
void EDA_DRAW_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition, EDA_ITEM* aItem )
plyatov's avatar
plyatov committed
325 326 327 328
{
}


329
void EDA_DRAW_FRAME::ToolOnRightClick( wxCommandEvent& event )
plyatov's avatar
plyatov committed
330 331 332
{
}

333

Dick Hollenbeck's avatar
Dick Hollenbeck committed
334
void EDA_DRAW_FRAME::PrintPage( wxDC* aDC, LSET aPrintMask, bool aPrintMirrorMode, void* aData )
charras's avatar
charras committed
335
{
336
    wxMessageBox( wxT("EDA_DRAW_FRAME::PrintPage() error") );
charras's avatar
charras committed
337
}
dickelbeck's avatar
dickelbeck committed
338

339

340
void EDA_DRAW_FRAME::OnSelectGrid( wxCommandEvent& event )
plyatov's avatar
plyatov committed
341
{
342
    int* clientData;
343
    int  eventId = ID_POPUP_GRID_LEVEL_100;
344 345 346

    if( event.GetEventType() == wxEVT_COMMAND_COMBOBOX_SELECTED )
    {
347
        if( m_gridSelectBox == NULL )
348 349 350 351 352 353 354
            return;

        /*
         * Don't use wxCommandEvent::GetClientData() here.  It always
         * returns NULL in GTK.  This solution is not as elegant but
         * it works.
         */
355
        int index = m_gridSelectBox->GetSelection();
356
        wxASSERT( index != wxNOT_FOUND );
357
        clientData = (int*) m_gridSelectBox->wxItemContainer::GetClientData( index );
358 359

        if( clientData != NULL )
360
            eventId = *clientData;
361 362 363
    }
    else
    {
364
        eventId = event.GetId();
365 366 367 368

        /* Update the grid select combobox if the grid size was changed
         * by menu event.
         */
369
        if( m_gridSelectBox != NULL )
370
        {
371
            for( size_t i = 0; i < m_gridSelectBox->GetCount(); i++ )
372
            {
373
                clientData = (int*) m_gridSelectBox->wxItemContainer::GetClientData( i );
374

375
                if( clientData && eventId == *clientData )
376
                {
377
                    m_gridSelectBox->SetSelection( i );
378 379 380 381 382
                    break;
                }
            }
        }
    }
plyatov's avatar
plyatov committed
383

384 385 386
    // Be sure m_LastGridSizeId is up to date.
    m_LastGridSizeId = eventId - ID_POPUP_GRID_LEVEL_1000;

387
    BASE_SCREEN* screen = GetScreen();
388

389
    if( screen->GetGridId() == eventId )
390
        return;
391

392 393 394 395 396
    /*
     * This allows for saving non-sequential command ID offsets used that
     * may be used in the grid size combobox.  Do not use the selection
     * index returned by GetSelection().
     */
397
    screen->SetGrid( eventId );
398
    SetCrossHairPosition( RefPos( true ) );
399

400
    if( IsGalCanvasActive() )
401
    {
402
        GetGalCanvas()->GetGAL()->SetGridSize( VECTOR2D( screen->GetGrid().m_Size.x,
403
                                                         screen->GetGrid().m_Size.y ) );
404
        GetGalCanvas()->GetView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
405 406
    }

407
    m_canvas->Refresh();
plyatov's avatar
plyatov committed
408 409 410
}


411
void EDA_DRAW_FRAME::OnSelectZoom( wxCommandEvent& event )
dickelbeck's avatar
dickelbeck committed
412
{
413
    if( m_zoomSelectBox == NULL )
414
        return;                        // Should not happen!
dickelbeck's avatar
dickelbeck committed
415

416
    int id = m_zoomSelectBox->GetCurrentSelection();
dickelbeck's avatar
dickelbeck committed
417

418
    if( id < 0 || !( id < (int)m_zoomSelectBox->GetCount() ) )
419
        return;
dickelbeck's avatar
dickelbeck committed
420

421
    if( id == 0 )                      // Auto zoom (Fit in Page)
dickelbeck's avatar
dickelbeck committed
422
    {
423
        Zoom_Automatique( true );
dickelbeck's avatar
dickelbeck committed
424
    }
425
    else
dickelbeck's avatar
dickelbeck committed
426 427
    {
        id--;
428
        double selectedZoom = GetScreen()->m_ZoomList[id];
429

430
        if( GetScreen()->GetZoom() == selectedZoom )
dickelbeck's avatar
dickelbeck committed
431
            return;
432

433
        GetScreen()->SetZoom( selectedZoom );
434

435
        if( IsGalCanvasActive() )
436 437
        {
            // Apply computed view settings to GAL
438 439
            KIGFX::VIEW* view = GetGalCanvas()->GetView();
            KIGFX::GAL* gal = GetGalCanvas()->GetGAL();
440 441 442 443 444

            double zoomFactor = gal->GetWorldScale() / gal->GetZoomFactor();
            double zoom = 1.0 / ( zoomFactor * GetZoom() );

            view->SetScale( zoom );
445
            GetGalCanvas()->Refresh();
446 447
        }
        else
Maciej Suminski's avatar
Maciej Suminski committed
448
            RedrawScreen( GetScrollCenterPosition(), false );
dickelbeck's avatar
dickelbeck committed
449
    }
plyatov's avatar
plyatov committed
450 451
}

452

453
double EDA_DRAW_FRAME::GetZoom()
454
{
455
    return GetScreen()->GetZoom();
456 457
}

dickelbeck's avatar
dickelbeck committed
458

459
void EDA_DRAW_FRAME::OnMouseEvent( wxMouseEvent& event )
plyatov's avatar
plyatov committed
460
{
dickelbeck's avatar
dickelbeck committed
461
    event.Skip();
plyatov's avatar
plyatov committed
462 463 464
}


465
void EDA_DRAW_FRAME::OnLeftDClick( wxDC* DC, const wxPoint& MousePos )
plyatov's avatar
plyatov committed
466 467 468
{
}

dickelbeck's avatar
dickelbeck committed
469

470
void EDA_DRAW_FRAME::DisplayToolMsg( const wxString& msg )
plyatov's avatar
plyatov committed
471
{
dickelbeck's avatar
dickelbeck committed
472
    SetStatusText( msg, 5 );
plyatov's avatar
plyatov committed
473 474
}

dickelbeck's avatar
dickelbeck committed
475

476
void EDA_DRAW_FRAME::DisplayUnitsMsg()
plyatov's avatar
plyatov committed
477
{
dickelbeck's avatar
dickelbeck committed
478 479
    wxString msg;

480
    switch( g_UserUnit )
dickelbeck's avatar
dickelbeck committed
481 482
    {
    case INCHES:
483
        msg = _( "Inches" );
dickelbeck's avatar
dickelbeck committed
484
        break;
plyatov's avatar
plyatov committed
485

486
    case MILLIMETRES:
jean-pierre charras's avatar
jean-pierre charras committed
487
        msg = _( "mm" );
dickelbeck's avatar
dickelbeck committed
488
        break;
plyatov's avatar
plyatov committed
489

dickelbeck's avatar
dickelbeck committed
490
    default:
jean-pierre charras's avatar
jean-pierre charras committed
491
        msg = _( "Units" );
dickelbeck's avatar
dickelbeck committed
492 493 494 495
        break;
    }

    SetStatusText( msg, 4 );
plyatov's avatar
plyatov committed
496 497
}

dickelbeck's avatar
dickelbeck committed
498 499


500
void EDA_DRAW_FRAME::OnSize( wxSizeEvent& SizeEv )
dickelbeck's avatar
dickelbeck committed
501
{
502
    m_FrameSize = GetClientSize( );
dickelbeck's avatar
dickelbeck committed
503 504

    SizeEv.Skip();
plyatov's avatar
plyatov committed
505 506
}

dickelbeck's avatar
dickelbeck committed
507

508
void EDA_DRAW_FRAME::SetToolID( int aId, int aCursor, const wxString& aToolMsg )
dickelbeck's avatar
dickelbeck committed
509
{
510 511
    // Keep default cursor in toolbars
    SetCursor( wxNullCursor );
512

513 514 515
    // Change m_canvas cursor if requested.
    if( m_canvas && aCursor >= 0 )
        m_canvas->SetCurrentCursor( aCursor );
516

517
    DisplayToolMsg( aToolMsg );
dickelbeck's avatar
dickelbeck committed
518

519
    if( aId < 0 )
dickelbeck's avatar
dickelbeck committed
520 521
        return;

522 523 524 525
    wxCHECK2_MSG( aId >= ID_NO_TOOL_SELECTED, aId = ID_NO_TOOL_SELECTED,
                  wxString::Format( wxT( "Current tool ID cannot be set to %d." ), aId ) );

    m_toolId = aId;
plyatov's avatar
plyatov committed
526 527 528
}


529
wxPoint EDA_DRAW_FRAME::GetGridPosition( const wxPoint& aPosition ) const
530 531 532
{
    wxPoint pos = aPosition;

533
    if( m_currentScreen != NULL && m_snapToGrid )
534
        pos = GetNearestGridPosition( aPosition );
535 536 537 538 539

    return pos;
}


540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571
void EDA_DRAW_FRAME::SetNextGrid()
{
    if( m_gridSelectBox )
    {
        m_gridSelectBox->SetSelection( ( m_gridSelectBox->GetSelection() + 1 ) %
                                       m_gridSelectBox->GetCount() );

        wxCommandEvent cmd( wxEVT_COMMAND_COMBOBOX_SELECTED );
        //        cmd.SetEventObject( this );
        OnSelectGrid( cmd );
    }
}


void EDA_DRAW_FRAME::SetPrevGrid()
{
    if( m_gridSelectBox )
    {
        int cnt = m_gridSelectBox->GetSelection();

        if( --cnt < 0 )
            cnt = m_gridSelectBox->GetCount() - 1;

        m_gridSelectBox->SetSelection( cnt );

        wxCommandEvent cmd( wxEVT_COMMAND_COMBOBOX_SELECTED );
        //        cmd.SetEventObject( this );
        OnSelectGrid( cmd );
    }
}


572
int EDA_DRAW_FRAME::BlockCommand( int key )
plyatov's avatar
plyatov committed
573
{
dickelbeck's avatar
dickelbeck committed
574
    return 0;
plyatov's avatar
plyatov committed
575 576
}

dickelbeck's avatar
dickelbeck committed
577

578
void EDA_DRAW_FRAME::InitBlockPasteInfos()
plyatov's avatar
plyatov committed
579
{
580
    GetScreen()->m_BlockLocate.ClearItemsList();
581
    m_canvas->SetMouseCaptureCallback( NULL );
plyatov's avatar
plyatov committed
582 583 584
}


585
void EDA_DRAW_FRAME::HandleBlockPlace( wxDC* DC )
plyatov's avatar
plyatov committed
586 587 588 589
{
}


590
bool EDA_DRAW_FRAME::HandleBlockEnd( wxDC* DC )
dickelbeck's avatar
dickelbeck committed
591
{
592
    return false;
dickelbeck's avatar
dickelbeck committed
593
}
plyatov's avatar
plyatov committed
594 595


596
void EDA_DRAW_FRAME::UpdateStatusBar()
plyatov's avatar
plyatov committed
597
{
598
    wxString        Line;
599
    BASE_SCREEN*    screen = GetScreen();
plyatov's avatar
plyatov committed
600

601
    if( !screen )
dickelbeck's avatar
dickelbeck committed
602
        return;
plyatov's avatar
plyatov committed
603

604
    // Display Zoom level: zoom = zoom_coeff/ZoomScalar
605
    Line.Printf( wxT( "Z %g" ), screen->GetZoom() );
606

dickelbeck's avatar
dickelbeck committed
607
    SetStatusText( Line, 1 );
plyatov's avatar
plyatov committed
608

609 610
    // Absolute and relative cursor positions are handled by overloading this function and
    // handling the internal to user units conversion at the appropriate level.
611 612 613

    // refresh units display
    DisplayUnitsMsg();
plyatov's avatar
plyatov committed
614
}
615

616

617
void EDA_DRAW_FRAME::LoadSettings( wxConfigBase* aCfg )
618
{
619
    EDA_BASE_FRAME::LoadSettings( aCfg );
620

621
    aCfg->Read( m_FrameName + CursorShapeEntryKeyword, &m_cursorShape, ( long )0 );
622

charras's avatar
charras committed
623
    bool btmp;
624
    if( aCfg->Read( m_FrameName + ShowGridEntryKeyword, &btmp ) )
625
        SetGridVisibility( btmp );
626

charras's avatar
charras committed
627
    int itmp;
628
    if( aCfg->Read( m_FrameName + GridColorEntryKeyword, &itmp ) )
629
        SetGridColor( ColorFromInt( itmp ) );
630

631
    aCfg->Read( m_FrameName + LastGridSizeIdKeyword, &m_LastGridSizeId, 0L );
632 633 634 635

    // m_LastGridSizeId is an offset, expected to be >= 0
    if( m_LastGridSizeId < 0 )
        m_LastGridSizeId = 0;
636 637 638
}


639
void EDA_DRAW_FRAME::SaveSettings( wxConfigBase* aCfg )
640
{
641
    EDA_BASE_FRAME::SaveSettings( aCfg );
642

643 644 645 646
    aCfg->Write( m_FrameName + CursorShapeEntryKeyword, m_cursorShape );
    aCfg->Write( m_FrameName + ShowGridEntryKeyword, IsGridVisible() );
    aCfg->Write( m_FrameName + GridColorEntryKeyword, ( long ) GetGridColor() );
    aCfg->Write( m_FrameName + LastGridSizeIdKeyword, ( long ) m_LastGridSizeId );
647 648 649
}


650 651
void EDA_DRAW_FRAME::AppendMsgPanel( const wxString& textUpper,
                                     const wxString& textLower,
652
                                     EDA_COLOR_T color, int pad )
653
{
654
    if( m_messagePanel == NULL )
655 656
        return;

657
    m_messagePanel->AppendMessage( textUpper, textLower, color, pad );
658 659 660
}


661
void EDA_DRAW_FRAME::ClearMsgPanel( void )
662
{
663
    if( m_messagePanel == NULL )
664 665
        return;

666
    m_messagePanel->EraseMsgBox();
667
}
668 669


670 671
void EDA_DRAW_FRAME::SetMsgPanel( const MSG_PANEL_ITEMS& aList )
{
672
    if( m_messagePanel == NULL )
673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691
        return;

    ClearMsgPanel();

    for( unsigned i = 0;  i < aList.size();  i++ )
        m_messagePanel->AppendMessage( aList[i] );
}


void EDA_DRAW_FRAME::SetMsgPanel( EDA_ITEM* aItem )
{
    wxCHECK_RET( aItem != NULL, wxT( "Invalid EDA_ITEM pointer.  Bad programmer." ) );

    MSG_PANEL_ITEMS items;
    aItem->GetMsgPanelInfo( items );
    SetMsgPanel( items );
}


692
wxString EDA_DRAW_FRAME::CoordinateToString( int aValue, bool aConvertToMils ) const
693
{
694
    return ::CoordinateToString( aValue, aConvertToMils );
695
}
696

697
wxString EDA_DRAW_FRAME::LengthDoubleToString( double aValue, bool aConvertToMils ) const
698 699 700 701
{
    return ::LengthDoubleToString( aValue, aConvertToMils );
}

702 703 704 705 706 707 708 709

bool EDA_DRAW_FRAME::HandleBlockBegin( wxDC* aDC, int aKey, const wxPoint& aPosition )
{
    BLOCK_SELECTOR* Block = &GetScreen()->m_BlockLocate;

    if( ( Block->GetCommand() != BLOCK_IDLE ) || ( Block->GetState() != STATE_NO_BLOCK ) )
        return false;

710
    Block->SetCommand( (BLOCK_COMMAND_T) BlockCommand( aKey ) );
711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759

    if( Block->GetCommand() == 0 )
        return false;

    switch( Block->GetCommand() )
    {
    case BLOCK_IDLE:
        break;

    case BLOCK_MOVE:                /* Move */
    case BLOCK_DRAG:                /* Drag */
    case BLOCK_COPY:                /* Copy */
    case BLOCK_DELETE:              /* Delete */
    case BLOCK_SAVE:                /* Save */
    case BLOCK_ROTATE:              /* Rotate 90 deg */
    case BLOCK_FLIP:                /* Flip */
    case BLOCK_ZOOM:                /* Window Zoom */
    case BLOCK_MIRROR_X:
    case BLOCK_MIRROR_Y:            /* mirror */
    case BLOCK_PRESELECT_MOVE:      /* Move with preselection list*/
        Block->InitData( m_canvas, aPosition );
        break;

    case BLOCK_PASTE:
        Block->InitData( m_canvas, aPosition );
        Block->SetLastCursorPosition( wxPoint( 0, 0 ) );
        InitBlockPasteInfos();

        if( Block->GetCount() == 0 )      /* No data to paste */
        {
            DisplayError( this, wxT( "No Block to paste" ), 20 );
            GetScreen()->m_BlockLocate.SetCommand( BLOCK_IDLE );
            m_canvas->SetMouseCaptureCallback( NULL );
            return true;
        }

        if( !m_canvas->IsMouseCaptured() )
        {
            Block->ClearItemsList();
            DisplayError( this,
                          wxT( "EDA_DRAW_FRAME::HandleBlockBegin() Err: m_mouseCaptureCallback NULL" ) );
            return true;
        }

        Block->SetState( STATE_BLOCK_MOVE );
        m_canvas->CallMouseCapture( aDC, aPosition, false );
        break;

    default:
Dick Hollenbeck's avatar
Dick Hollenbeck committed
760 761 762 763 764 765 766
        {
            wxString msg;
            msg << wxT( "EDA_DRAW_FRAME::HandleBlockBegin() error: Unknown command " ) <<
            Block->GetCommand();
            DisplayError( this, msg );
        }
        break;
767 768 769 770 771
    }

    Block->SetMessageBlock( this );
    return true;
}
772 773


774 775 776 777 778
// See comment in classpcb.cpp near line 66
//static const double MAX_AXIS = 1518500251;

// However I am not seeing a problem with this size yet:
static const double MAX_AXIS = INT_MAX - 100;
779 780 781

#define VIRT_MIN    (-MAX_AXIS/2.0)     ///< min X or Y coordinate in virtual space
#define VIRT_MAX    (MAX_AXIS/2.0)      ///< max X or Y coordinate in virtual space
782 783


784 785 786 787
void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU )
{
    BASE_SCREEN* screen = GetScreen();

788
    if( !screen || !m_canvas )
789 790 791 792
        return;

    double scale = screen->GetScalingFactor();

793
    wxLogTrace( traceScrollSettings, wxT( "Center Position = ( %d, %d ), scale = %.10g" ),
794 795 796 797 798 799
                aCenterPositionIU.x, aCenterPositionIU.y, scale );

    // Calculate the portion of the drawing that can be displayed in the
    // client area at the current zoom level.

    // visible viewport in device units ~ pixels
800
    wxSize  clientSizeDU = m_canvas->GetClientSize();
801 802

    // Size of the client window in IU
803
    DSIZE   clientSizeIU( clientSizeDU.x / scale, clientSizeDU.y / scale );
804 805

    // Full drawing or "page" rectangle in internal units
806
    DBOX    pageRectIU( wxPoint( 0, 0 ), wxSize( GetPageSizeIU().x, GetPageSizeIU().y ) );
807 808 809 810 811 812 813 814 815

    // The upper left corner of the client rectangle in internal units.
    double xIU = aCenterPositionIU.x - clientSizeIU.x / 2.0;
    double yIU = aCenterPositionIU.y - clientSizeIU.y / 2.0;

    // If drawn around the center, adjust the client rectangle accordingly.
    if( screen->m_Center )
    {
        // half page offset.
816 817
        xIU += pageRectIU.GetWidth()  / 2.0;
        yIU += pageRectIU.GetHeight() / 2.0;
818 819
    }

820
    DBOX    clientRectIU( wxPoint( xIU, yIU ), wxSize( clientSizeIU.x, clientSizeIU.y ) );
821 822 823
    wxPoint centerPositionIU;

    // put "int" limits on the clientRect
824 825 826 827 828 829 830 831 832
    if( clientRectIU.GetLeft() < VIRT_MIN )
        clientRectIU.MoveLeftTo( VIRT_MIN );
    if( clientRectIU.GetTop() < VIRT_MIN )
        clientRectIU.MoveTopTo( VIRT_MIN );
    if( clientRectIU.GetRight() > VIRT_MAX )
        clientRectIU.MoveRightTo( VIRT_MAX );
    if( clientRectIU.GetBottom() > VIRT_MAX )
        clientRectIU.MoveBottomTo( VIRT_MAX );

833 834
    centerPositionIU.x = KiROUND( clientRectIU.GetX() + clientRectIU.GetWidth() / 2 );
    centerPositionIU.y = KiROUND( clientRectIU.GetY() + clientRectIU.GetHeight() / 2 );
835

836 837
    if( screen->m_Center )
    {
838 839
        centerPositionIU.x -= KiROUND( pageRectIU.GetWidth() / 2.0 );
        centerPositionIU.y -= KiROUND( pageRectIU.GetHeight() / 2.0 );
840 841
    }

842
    DSIZE   virtualSizeIU;
843 844 845 846 847 848 849

    if( pageRectIU.GetLeft() < clientRectIU.GetLeft() && pageRectIU.GetRight() > clientRectIU.GetRight() )
    {
        virtualSizeIU.x = pageRectIU.GetSize().x;
    }
    else
    {
850 851
        double pageCenterX    = pageRectIU.GetX()   + ( pageRectIU.GetWidth() / 2 );
        double clientCenterX  = clientRectIU.GetX() + ( clientRectIU.GetWidth() / 2 );
852

853
        if( clientRectIU.GetWidth() > pageRectIU.GetWidth() )
854
        {
855 856 857 858
            if( pageCenterX > clientCenterX )
                virtualSizeIU.x = ( pageCenterX - clientRectIU.GetLeft() ) * 2;
            else if( pageCenterX < clientCenterX )
                virtualSizeIU.x = ( clientRectIU.GetRight() - pageCenterX ) * 2;
859
            else
860
                virtualSizeIU.x = clientRectIU.GetWidth();
861 862 863
        }
        else
        {
864
            if( pageCenterX > clientCenterX )
865
                virtualSizeIU.x = pageRectIU.GetWidth() + ( (pageRectIU.GetLeft() - clientRectIU.GetLeft() ) * 2 );
866
            else if( pageCenterX < clientCenterX )
867
                virtualSizeIU.x = pageRectIU.GetWidth() + ( (clientRectIU.GetRight() - pageRectIU.GetRight() ) * 2 );
868
            else
869
                virtualSizeIU.x = pageRectIU.GetWidth();
870 871 872 873 874 875 876 877 878
        }
    }

    if( pageRectIU.GetTop() < clientRectIU.GetTop() && pageRectIU.GetBottom() > clientRectIU.GetBottom() )
    {
        virtualSizeIU.y = pageRectIU.GetSize().y;
    }
    else
    {
879 880
        double pageCenterY   = pageRectIU.GetY()   + ( pageRectIU.GetHeight() / 2 );
        double clientCenterY = clientRectIU.GetY() + ( clientRectIU.GetHeight() / 2 );
881

882
        if( clientRectIU.GetHeight() > pageRectIU.GetHeight() )
883
        {
884 885 886 887
            if( pageCenterY > clientCenterY )
                virtualSizeIU.y = ( pageCenterY - clientRectIU.GetTop() ) * 2;
            else if( pageCenterY < clientCenterY )
                virtualSizeIU.y = ( clientRectIU.GetBottom() - pageCenterY ) * 2;
888
            else
889
                virtualSizeIU.y = clientRectIU.GetHeight();
890 891 892
        }
        else
        {
893
            if( pageCenterY > clientCenterY )
894
                virtualSizeIU.y = pageRectIU.GetHeight() +
895
                                ( ( pageRectIU.GetTop() - clientRectIU.GetTop() ) * 2 );
896
            else if( pageCenterY < clientCenterY )
897
                virtualSizeIU.y = pageRectIU.GetHeight() +
898 899
                                ( ( clientRectIU.GetBottom() - pageRectIU.GetBottom() ) * 2 );
            else
900
                virtualSizeIU.y = pageRectIU.GetHeight();
901 902 903
        }
    }

904 905 906 907
    // put "int" limits on the virtualSizeIU
    virtualSizeIU.x = std::min( virtualSizeIU.x, MAX_AXIS );
    virtualSizeIU.y = std::min( virtualSizeIU.y, MAX_AXIS );

908 909 910 911 912 913 914
    if( screen->m_Center )
    {
        screen->m_DrawOrg.x = -KiROUND( virtualSizeIU.x / 2.0 );
        screen->m_DrawOrg.y = -KiROUND( virtualSizeIU.y / 2.0 );
    }
    else
    {
915 916
        screen->m_DrawOrg.x = -KiROUND( ( virtualSizeIU.x - pageRectIU.GetWidth() )  / 2.0 );
        screen->m_DrawOrg.y = -KiROUND( ( virtualSizeIU.y - pageRectIU.GetHeight() ) / 2.0 );
917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932
    }

    /* Always set scrollbar pixels per unit to 1 unless you want the zoom
     * around cursor to jump around.  This reported problem occurs when the
     * zoom point is not on a pixel per unit increment.  If you set the
     * pixels per unit to 10, you have potential for the zoom point to
     * jump around +/-5 pixels from the nearest grid point.
     */
    screen->m_ScrollPixelsPerUnitX = screen->m_ScrollPixelsPerUnitY = 1;

    // Number of scroll bar units for the given zoom level in device units.
    double unitsX = virtualSizeIU.x * scale;
    double unitsY = virtualSizeIU.y * scale;

    // Calculate the scroll bar position in internal units to place the
    // center position at the center of client rectangle.
933
    SetScrollCenterPosition( centerPositionIU );
934

935 936
    double posX = centerPositionIU.x - clientRectIU.GetWidth()  / 2.0 - screen->m_DrawOrg.x;
    double posY = centerPositionIU.y - clientRectIU.GetHeight() / 2.0 - screen->m_DrawOrg.y;
937 938 939 940 941 942 943

    // Convert scroll bar position to device units.
    posX = KiROUND( posX * scale );
    posY = KiROUND( posY * scale );

    if( posX < 0 )
    {
944
        wxLogTrace( traceScrollSettings, wxT( "Required scroll bar X position %.10g" ), posX );
945 946 947 948 949
        posX = 0;
    }

    if( posX > unitsX )
    {
950
        wxLogTrace( traceScrollSettings, wxT( "Required scroll bar X position %.10g" ), posX );
951 952 953 954 955
        posX = unitsX;
    }

    if( posY < 0 )
    {
956
        wxLogTrace( traceScrollSettings, wxT( "Required scroll bar Y position %.10g" ), posY );
957 958 959 960 961
        posY = 0;
    }

    if( posY > unitsY )
    {
962
        wxLogTrace( traceScrollSettings, wxT( "Required scroll bar Y position %.10g" ), posY );
963 964 965 966 967 968 969
        posY = unitsY;
    }

    screen->m_ScrollbarPos    = wxPoint( KiROUND( posX ),  KiROUND( posY ) );
    screen->m_ScrollbarNumber = wxSize( KiROUND( unitsX ), KiROUND( unitsY ) );

    wxLogTrace( traceScrollSettings,
970
                wxT( "Drawing = (%.10g, %.10g), Client = (%.10g, %.10g), Offset = (%d, %d), SetScrollbars(%d, %d, %d, %d, %d, %d)" ),
971 972 973 974 975 976 977 978 979 980 981 982 983 984 985
                virtualSizeIU.x, virtualSizeIU.y, clientSizeIU.x, clientSizeIU.y,
                screen->m_DrawOrg.x, screen->m_DrawOrg.y,
                screen->m_ScrollPixelsPerUnitX, screen->m_ScrollPixelsPerUnitY,
                screen->m_ScrollbarNumber.x, screen->m_ScrollbarNumber.y,
                screen->m_ScrollbarPos.x, screen->m_ScrollbarPos.y );

    bool            noRefresh = true;

    m_canvas->SetScrollbars( screen->m_ScrollPixelsPerUnitX,
                             screen->m_ScrollPixelsPerUnitY,
                             screen->m_ScrollbarNumber.x,
                             screen->m_ScrollbarNumber.y,
                             screen->m_ScrollbarPos.x,
                             screen->m_ScrollbarPos.y, noRefresh );
}
986 987 988 989


void EDA_DRAW_FRAME::UseGalCanvas( bool aEnable )
{
990 991
    KIGFX::VIEW* view = GetGalCanvas()->GetView();
    KIGFX::GAL* gal = GetGalCanvas()->GetGAL();
992

993 994 995
    double zoomFactor = gal->GetWorldScale() / gal->GetZoomFactor();

    // Display the same view after canvas switching
996 997
    if( aEnable )
    {
998
        BASE_SCREEN* screen = GetScreen();
999

1000
        // Switch to GAL rendering
1001
        if( !IsGalCanvasActive() )
1002
        {
1003
            // Set up viewport
1004 1005 1006 1007
            double zoom = 1.0 / ( zoomFactor * m_canvas->GetZoom() );
            view->SetScale( zoom );
            view->SetCenter( VECTOR2D( m_canvas->GetScreenCenterLogicalPosition() ) );
        }
1008 1009 1010 1011

        // Set up grid settings
        gal->SetGridVisibility( IsGridVisible() );
        gal->SetGridSize( VECTOR2D( screen->GetGridSize().x, screen->GetGridSize().y ) );
Maciej Suminski's avatar
Maciej Suminski committed
1012
        gal->SetGridOrigin( VECTOR2D( GetGridOrigin() ) );
1013 1014 1015
    }
    else
    {
1016
        // Switch to standard rendering
1017
        if( IsGalCanvasActive() )
1018 1019 1020 1021
        {
            // Change view settings only if GAL was active previously
            double zoom = 1.0 / ( zoomFactor * view->GetScale() );
            m_canvas->SetZoom( zoom );
1022

1023 1024 1025
            VECTOR2D center = view->GetCenter();
            RedrawScreen( wxPoint( center.x, center.y ), false );
        }
1026 1027
    }

1028
    m_canvas->SetEvtHandlerEnabled( !aEnable );
1029
    GetGalCanvas()->SetEvtHandlerEnabled( aEnable );
1030 1031 1032 1033 1034 1035

    // Switch panes
    m_auimgr.GetPane( wxT( "DrawFrame" ) ).Show( !aEnable );
    m_auimgr.GetPane( wxT( "DrawFrameGal" ) ).Show( aEnable );
    m_auimgr.Update();

1036 1037 1038
    // Reset current tool on switch();
    SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString );

1039
    m_galCanvasActive = aEnable;
1040
}
Maciej Suminski's avatar
Maciej Suminski committed
1041

1042 1043 1044 1045
//-----< BASE_SCREEN API moved here >--------------------------------------------

wxPoint EDA_DRAW_FRAME::GetCrossHairPosition( bool aInvertY ) const
{
1046
    // subject to change, borrow from old BASE_SCREEN for now.
1047 1048 1049
    if( IsGalCanvasActive() )
    {
        VECTOR2I cursor = GetGalCanvas()->GetViewControls()->GetCursorPosition();
1050

1051 1052 1053 1054 1055 1056 1057
        return wxPoint( cursor.x, cursor.y );
    }
    else
    {
        BASE_SCREEN* screen = GetScreen();  // virtual call
        return screen->getCrossHairPosition( aInvertY );
    }
1058 1059 1060 1061 1062
}


void EDA_DRAW_FRAME::SetCrossHairPosition( const wxPoint& aPosition, bool aSnapToGrid )
{
1063 1064
    BASE_SCREEN* screen = GetScreen();  // virtual call
    screen->setCrossHairPosition( aPosition, GetGridOrigin(), aSnapToGrid );
1065 1066 1067 1068 1069
}


wxPoint EDA_DRAW_FRAME::GetCursorPosition( bool aOnGrid, wxRealPoint* aGridSize ) const
{
1070 1071
    BASE_SCREEN* screen = GetScreen();  // virtual call
    return screen->getCursorPosition( aOnGrid, GetGridOrigin(), aGridSize );
1072 1073 1074 1075 1076
}


wxPoint EDA_DRAW_FRAME::GetNearestGridPosition( const wxPoint& aPosition, wxRealPoint* aGridSize ) const
{
1077 1078
    BASE_SCREEN* screen = GetScreen();  // virtual call
    return screen->getNearestGridPosition( aPosition, GetGridOrigin(), aGridSize );
1079 1080 1081 1082 1083
}


wxPoint EDA_DRAW_FRAME::GetCrossHairScreenPosition() const
{
1084 1085
    BASE_SCREEN* screen = GetScreen();  // virtual call
    return screen->getCrossHairScreenPosition();
1086 1087 1088 1089 1090
}


void EDA_DRAW_FRAME::SetMousePosition( const wxPoint& aPosition )
{
1091 1092
    BASE_SCREEN* screen = GetScreen();  // virtual call
    screen->setMousePosition( aPosition );
1093 1094 1095 1096 1097
}


wxPoint EDA_DRAW_FRAME::RefPos( bool useMouse ) const
{
1098 1099
    BASE_SCREEN* screen = GetScreen();  // virtual call
    return screen->refPos( useMouse );
1100 1101 1102 1103 1104
}


const wxPoint& EDA_DRAW_FRAME::GetScrollCenterPosition() const
{
1105 1106
    BASE_SCREEN* screen = GetScreen();  // virtual call
    return screen->getScrollCenterPosition();
1107 1108 1109 1110 1111
}


void EDA_DRAW_FRAME::SetScrollCenterPosition( const wxPoint& aPoint )
{
1112 1113
    BASE_SCREEN* screen = GetScreen();  // virtual call
    screen->setScrollCenterPosition( aPoint );
1114 1115 1116
}

//-----</BASE_SCREEN API moved here >--------------------------------------------
Lorenzo Marcantonio's avatar
Lorenzo Marcantonio committed
1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232

void EDA_DRAW_FRAME::RefreshCrossHair( const wxPoint &aOldPos,
                                       const wxPoint &aEvtPos,
                                       wxDC* aDC )
{
    wxPoint newpos = GetCrossHairPosition();

    // Redraw the crosshair if it moved
    if( aOldPos != newpos )
    {
        SetCrossHairPosition( aOldPos, false );
        m_canvas->CrossHairOff( aDC );
        SetCrossHairPosition( newpos, false );
        m_canvas->CrossHairOn( aDC );

        if( m_canvas->IsMouseCaptured() )
        {
#ifdef USE_WX_OVERLAY
            wxDCOverlay oDC( m_overlay, (wxWindowDC*)aDC );
            oDC.Clear();
            m_canvas->CallMouseCapture( aDC, aEvtPos, false );
#else
            m_canvas->CallMouseCapture( aDC, aEvtPos, true );
#endif
        }
#ifdef USE_WX_OVERLAY
        else
        {
            m_overlay.Reset();
        }
#endif
    }
}

void EDA_DRAW_FRAME::GeneralControlKeyMovement( int aHotKey, wxPoint *aPos,
                                                bool aSnapToGrid )
{

    // If requested snap the current position to the grid
    if( aSnapToGrid )
        *aPos = GetNearestGridPosition( *aPos );

    switch( aHotKey )
    {
        // All these keys have almost the same treatment
    case GR_KB_CTRL | WXK_NUMPAD8: case GR_KB_CTRL | WXK_UP:
    case GR_KB_CTRL | WXK_NUMPAD2: case GR_KB_CTRL | WXK_DOWN:
    case GR_KB_CTRL | WXK_NUMPAD4: case GR_KB_CTRL | WXK_LEFT:
    case GR_KB_CTRL | WXK_NUMPAD6: case GR_KB_CTRL | WXK_RIGHT:
    case WXK_NUMPAD8: case WXK_UP: case WXK_NUMPAD2: case WXK_DOWN:
    case WXK_NUMPAD4: case WXK_LEFT: case WXK_NUMPAD6: case WXK_RIGHT:
        {
            /* Here's a tricky part: when doing cursor key movement, the
             * 'previous' point should be taken from memory, *not* from the
             * freshly computed position in the event. Otherwise you can't do
             * sub-pixel movement. The m_movingCursorWithKeyboard oneshot 'eats'
             * the automatic motion event generated by cursor warping */
            wxRealPoint gridSize = GetScreen()->GetGridSize();
            *aPos = GetCrossHairPosition();

            // Bonus: ^key moves faster (x10)
            switch( aHotKey )
            {
            case GR_KB_CTRL|WXK_NUMPAD8:
            case GR_KB_CTRL|WXK_UP:
                aPos->y -= KiROUND( 10 * gridSize.y );
                break;

            case GR_KB_CTRL|WXK_NUMPAD2:
            case GR_KB_CTRL|WXK_DOWN:
                aPos->y += KiROUND( 10 * gridSize.y );
                break;

            case GR_KB_CTRL|WXK_NUMPAD4:
            case GR_KB_CTRL|WXK_LEFT:
                aPos->x -= KiROUND( 10 * gridSize.x );
                break;

            case GR_KB_CTRL|WXK_NUMPAD6:
            case GR_KB_CTRL|WXK_RIGHT:
                aPos->x += KiROUND( 10 * gridSize.x );
                break;

            case WXK_NUMPAD8:
            case WXK_UP:
                aPos->y -= KiROUND( gridSize.y );
                break;

            case WXK_NUMPAD2:
            case WXK_DOWN:
                aPos->y += KiROUND( gridSize.y );
                break;

            case WXK_NUMPAD4:
            case WXK_LEFT:
                aPos->x -= KiROUND( gridSize.x );
                break;

            case WXK_NUMPAD6:
            case WXK_RIGHT:
                aPos->x += KiROUND( gridSize.x );
                break;

            default: /* Can't happen since we entered the statement */
                break;
            }
            m_canvas->MoveCursor( *aPos );
            m_movingCursorWithKeyboard = true;
        }
        break;

    default:
        break;
    }
}