controle.cpp 12.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/*
 * This program source code file is part of KiCad, a free EDA CAD application.
 *
 * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
 * 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
 */

/**
 * eeschema/controle.cpp
 */
29

30 31 32 33 34
#include <fctsys.h>
#include <gr_basic.h>
#include <class_drawpanel.h>
#include <eda_dde.h>
#include <wxEeschemaStruct.h>
35
#include <menus_helpers.h>
36
#include <msgpanel.h>
37

38 39 40 41 42 43 44 45 46 47 48
#include <eeschema_id.h>
#include <general.h>
#include <hotkeys.h>
#include <libeditframe.h>
#include <viewlib_frame.h>
#include <lib_draw_item.h>
#include <lib_pin.h>
#include <sch_sheet.h>
#include <sch_sheet_path.h>
#include <sch_marker.h>
#include <sch_component.h>
49

50

51 52
SCH_ITEM* SCH_EDIT_FRAME::LocateAndShowItem( const wxPoint& aPosition, const KICAD_T aFilterList[],
                                             int aHotKeyCommandId )
53
{
54
    SCH_ITEM*      item;
55
    wxString       msg;
56
    LIB_PIN*       Pin     = NULL;
57
    SCH_COMPONENT* LibItem = NULL;
58
    wxPoint        gridPosition = GetNearestGridPosition( aPosition );
59

60
    // Check the on grid position first.  There is more likely to be multiple items on
61 62
    // grid than off grid.
    item = LocateItem( gridPosition, aFilterList, aHotKeyCommandId );
63

64 65
    // If the user aborted the clarification context menu, don't show it again at the
    // off grid position.
66
    if( !item && m_canvas->GetAbortRequest() )
67
    {
68
        m_canvas->SetAbortRequest( false );
69 70 71 72 73
        return NULL;
    }

    if( !item && (aPosition != gridPosition) )
        item = LocateItem( aPosition, aFilterList, aHotKeyCommandId );
74

75
    if( !item )
76
    {
77
        m_canvas->SetAbortRequest( false );  // Just in case the user aborted the context menu.
78
        return NULL;
79
    }
80

81
    /* Cross probing to Pcbnew if a pin or a component is found */
82
    switch( item->Type() )
83
    {
84 85
    case SCH_FIELD_T:
    case LIB_FIELD_T:
86 87
        LibItem = (SCH_COMPONENT*) item->GetParent();
        SendMessageToPCBNEW( item, LibItem );
88 89
        break;

90
    case SCH_COMPONENT_T:
91 92
        LibItem = (SCH_COMPONENT*) item;
        SendMessageToPCBNEW( item, LibItem );
93 94
        break;

95
    case LIB_PIN_T:
96
        Pin = (LIB_PIN*) item;
97
        LibItem = (SCH_COMPONENT*) LocateItem( aPosition, SCH_COLLECTOR::ComponentsOnly );
98
        break;
99 100 101

    default:
        ;
102 103 104 105
    }

    if( Pin )
    {
106
        // Force display pin information (the previous display could be a component info)
107 108
        MSG_PANEL_ITEMS items;
        Pin->GetMsgPanelInfo( items );
109

110
        if( LibItem )
111
            items.push_back( MSG_PANEL_ITEM( LibItem->GetRef( m_CurrentSheet ),
112
                                             LibItem->GetField( VALUE )->GetText(), DARKCYAN ) );
113 114

        SetMsgPanel( items );
115

116
        // Cross probing:2 - pin found, and send a locate pin command to Pcbnew (highlight net)
117
        SendMessageToPCBNEW( Pin, LibItem );
118
    }
119 120

    return item;
121 122 123
}


124 125
SCH_ITEM* SCH_EDIT_FRAME::LocateItem( const wxPoint& aPosition, const KICAD_T aFilterList[],
                                      int aHotKeyCommandId )
126
{
127
    SCH_ITEM* item = NULL;
128

129
    m_collectedItems.Collect( GetScreen()->GetDrawItems(), aFilterList, aPosition );
130

131
    if( m_collectedItems.GetCount() == 0 )
132
    {
133
        ClearMsgPanel();
134
    }
135
    else if( m_collectedItems.GetCount() == 1 )
136
    {
137
        item = m_collectedItems[0];
138
    }
139
    else
140
    {
141 142 143
        // There are certain combinations of items that do not need clarification such as
        // a corner were two lines meet or all the items form a junction.
        if( aHotKeyCommandId )
144
        {
145 146 147
            switch( aHotKeyCommandId )
            {
            case HK_DRAG:
148 149
                if( m_collectedItems.IsCorner() || m_collectedItems.IsNode( false )
                    || m_collectedItems.IsDraggableJunction() )
150 151 152 153 154 155
                {
                    item = m_collectedItems[0];
                }
            default:
                ;
            }
156
        }
157

158 159 160 161 162 163 164 165 166 167 168 169 170 171
        if( item == NULL )
        {
            wxASSERT_MSG( m_collectedItems.GetCount() <= MAX_SELECT_ITEM_IDS,
                          wxT( "Select item clarification context menu size limit exceeded." ) );

            wxMenu selectMenu;
            wxMenuItem* title = new wxMenuItem( &selectMenu, wxID_NONE, _( "Clarify Selection" ) );

            selectMenu.Append( title );
            selectMenu.AppendSeparator();

            for( int i = 0;  i < m_collectedItems.GetCount() && i < MAX_SELECT_ITEM_IDS;  i++ )
            {
                wxString text = m_collectedItems[i]->GetSelectMenuText();
172
                BITMAP_DEF xpm = m_collectedItems[i]->GetMenuImage();
173
                AddMenuItem( &selectMenu, ID_SELECT_ITEM_START + i, text, KiBitmap( xpm ) );
174 175 176 177
            }

            // Set to NULL in case user aborts the clarification context menu.
            GetScreen()->SetCurItem( NULL );
178
            m_canvas->SetAbortRequest( true );   // Changed to false if an item is selected
179
            PopupMenu( &selectMenu );
180
            m_canvas->MoveCursorToCrossHair();
181 182
            item = GetScreen()->GetCurItem();
        }
183 184
    }

185 186
    GetScreen()->SetCurItem( item );

187
    if( item )
188 189 190 191 192 193 194 195
    {
        if( item->Type() == SCH_COMPONENT_T )
            ( (SCH_COMPONENT*) item )->SetCurrentSheetPath( &GetCurrentSheet() );

        MSG_PANEL_ITEMS items;
        item->GetMsgPanelInfo( items );
        SetMsgPanel( items );
    }
196
    else
197
    {
198
        ClearMsgPanel();
199
    }
200

201
    return item;
202 203 204
}


205
void SCH_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aHotKey )
charras's avatar
charras committed
206
{
207
    wxRealPoint gridSize;
208
    SCH_SCREEN* screen = GetScreen();
209 210
    wxPoint     oldpos;
    wxPoint     pos = aPosition;
charras's avatar
charras committed
211

212 213 214 215 216 217 218
    // when moving mouse, use the "magnetic" grid, unless the shift+ctrl keys is pressed
    // for next cursor position
    // ( shift or ctrl key down are PAN command with mouse wheel)
    bool snapToGrid = true;
    if( !aHotKey && wxGetKeyState( WXK_SHIFT ) && wxGetKeyState( WXK_CONTROL ) )
        snapToGrid = false;

219 220 221 222
    // Cursor is left off grid only if no block in progress
    if( GetScreen()->m_BlockLocate.GetState() != STATE_NO_BLOCK )
        snapToGrid = true;

223
    if( snapToGrid )
224
        pos = GetNearestGridPosition( pos );
225

226
    oldpos   = GetCrossHairPosition();
227
    gridSize = screen->GetGridSize();
charras's avatar
charras committed
228

229
    switch( aHotKey )
charras's avatar
charras committed
230 231 232 233
    {
    case 0:
        break;

234
    case WXK_NUMPAD8:
charras's avatar
charras committed
235
    case WXK_UP:
236
        pos.y -= KiROUND( gridSize.y );
237
        m_canvas->MoveCursor( pos );
charras's avatar
charras committed
238 239
        break;

240
    case WXK_NUMPAD2:
charras's avatar
charras committed
241
    case WXK_DOWN:
242
        pos.y += KiROUND( gridSize.y );
243
        m_canvas->MoveCursor( pos );
charras's avatar
charras committed
244 245
        break;

246
    case WXK_NUMPAD4:
charras's avatar
charras committed
247
    case WXK_LEFT:
248
        pos.x -= KiROUND( gridSize.x );
249
        m_canvas->MoveCursor( pos );
charras's avatar
charras committed
250 251
        break;

252
    case WXK_NUMPAD6:
charras's avatar
charras committed
253
    case WXK_RIGHT:
254
        pos.x += KiROUND( gridSize.x );
255
        m_canvas->MoveCursor( pos );
charras's avatar
charras committed
256 257 258 259 260 261
        break;

    default:
        break;
    }

262
    // Update cursor position.
263
    SetCrossHairPosition( pos, snapToGrid );
charras's avatar
charras committed
264

265
    if( oldpos != GetCrossHairPosition() )
charras's avatar
charras committed
266
    {
267 268
        pos = GetCrossHairPosition();
        SetCrossHairPosition( oldpos, false);
269
        m_canvas->CrossHairOff( aDC );
270
        SetCrossHairPosition( pos, snapToGrid );
271
        m_canvas->CrossHairOn( aDC );
charras's avatar
charras committed
272

273
        if( m_canvas->IsMouseCaptured() )
charras's avatar
charras committed
274
        {
275
#ifdef USE_WX_OVERLAY
276
            wxDCOverlay oDC( m_overlay, (wxWindowDC*)aDC );
277
            oDC.Clear();
278
            m_canvas->CallMouseCapture( aDC, aPosition, false );
279
#else
280
            m_canvas->CallMouseCapture( aDC, aPosition, true );
281
#endif
charras's avatar
charras committed
282
        }
283 284
#ifdef USE_WX_OVERLAY
        else
285 286 287
        {
            m_overlay.Reset();
        }
288
#endif
charras's avatar
charras committed
289 290
    }

291
    if( aHotKey )
charras's avatar
charras committed
292
    {
293
        if( screen->GetCurItem() && screen->GetCurItem()->GetFlags() )
294
            OnHotKey( aDC, aHotKey, aPosition, screen->GetCurItem() );
charras's avatar
charras committed
295
        else
296
            OnHotKey( aDC, aHotKey, aPosition, NULL );
charras's avatar
charras committed
297 298
    }

299
    UpdateStatusBar();    /* Display cursor coordinates info */
charras's avatar
charras committed
300 301 302
}


303
void LIB_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aHotKey )
charras's avatar
charras committed
304
{
305 306 307
    wxRealPoint gridSize;
    wxPoint     oldpos;
    wxPoint     pos = aPosition;
charras's avatar
charras committed
308

309 310 311 312 313 314 315
    // when moving mouse, use the "magnetic" grid, unless the shift+ctrl keys is pressed
    // for next cursor position
    // ( shift or ctrl key down are PAN command with mouse wheel)
    bool snapToGrid = true;
    if( !aHotKey && wxGetKeyState( WXK_SHIFT ) && wxGetKeyState( WXK_CONTROL ) )
        snapToGrid = false;

316 317 318 319
    // Cursor is left off grid only if no block in progress
    if( GetScreen()->m_BlockLocate.GetState() != STATE_NO_BLOCK )
        snapToGrid = true;

320
    if( snapToGrid )
321
        pos = GetNearestGridPosition( pos );
322

323 324
    oldpos   = GetCrossHairPosition();
    gridSize = GetScreen()->GetGridSize();
charras's avatar
charras committed
325

326
    switch( aHotKey )
charras's avatar
charras committed
327 328 329 330
    {
    case 0:
        break;

331
    case WXK_NUMPAD8:
charras's avatar
charras committed
332
    case WXK_UP:
333
        pos.y -= KiROUND( gridSize.y );
334
        m_canvas->MoveCursor( pos );
charras's avatar
charras committed
335 336
        break;

337
    case WXK_NUMPAD2:
charras's avatar
charras committed
338
    case WXK_DOWN:
339
        pos.y += KiROUND( gridSize.y );
340
        m_canvas->MoveCursor( pos );
charras's avatar
charras committed
341 342
        break;

343
    case WXK_NUMPAD4:
charras's avatar
charras committed
344
    case WXK_LEFT:
345
        pos.x -= KiROUND( gridSize.x );
346
        m_canvas->MoveCursor( pos );
charras's avatar
charras committed
347 348
        break;

349
    case WXK_NUMPAD6:
charras's avatar
charras committed
350
    case WXK_RIGHT:
351
        pos.x += KiROUND( gridSize.x );
352
        m_canvas->MoveCursor( pos );
charras's avatar
charras committed
353 354 355 356 357 358
        break;

    default:
        break;
    }

359
    // Update the cursor position.
360
    SetCrossHairPosition( pos, snapToGrid );
charras's avatar
charras committed
361

362
    if( oldpos != GetCrossHairPosition() )
charras's avatar
charras committed
363
    {
364 365
        pos = GetCrossHairPosition();
        SetCrossHairPosition( oldpos, false );
366
        m_canvas->CrossHairOff( aDC );
367
        SetCrossHairPosition( pos, snapToGrid );
368
        m_canvas->CrossHairOn( aDC );
charras's avatar
charras committed
369

370
        if( m_canvas->IsMouseCaptured() )
charras's avatar
charras committed
371
        {
372
#ifdef USE_WX_OVERLAY
373
            wxDCOverlay oDC( m_overlay, (wxWindowDC*)aDC );
374
            oDC.Clear();
375
            m_canvas->CallMouseCapture( aDC, aPosition, false );
376
#else
377
            m_canvas->CallMouseCapture( aDC, aPosition, true );
378
#endif
charras's avatar
charras committed
379
        }
380 381
#ifdef USE_WX_OVERLAY
        else
382 383 384
        {
            m_overlay.Reset();
        }
385
#endif
charras's avatar
charras committed
386 387
    }

388
    if( aHotKey )
charras's avatar
charras committed
389
    {
390
        OnHotKey( aDC, aHotKey, aPosition, NULL );
charras's avatar
charras committed
391 392
    }

393
    UpdateStatusBar();
charras's avatar
charras committed
394 395
}

396

397
void LIB_VIEW_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aHotKey )
398
{
399
    wxRealPoint gridSize;
400
    SCH_SCREEN* screen = GetScreen();
401 402
    wxPoint     oldpos;
    wxPoint     pos = aPosition;
403

404 405
    pos    = GetNearestGridPosition( pos );
    oldpos = GetCrossHairPosition();
406
    gridSize = screen->GetGridSize();
407

408
    switch( aHotKey )
409
    {
410 411 412
    case 0:
        break;

413
    case WXK_NUMPAD8:
414
    case WXK_UP:
415
        pos.y -= KiROUND( gridSize.y );
416
        m_canvas->MoveCursor( pos );
417 418
        break;

419
    case WXK_NUMPAD2:
420
    case WXK_DOWN:
421
        pos.y += KiROUND( gridSize.y );
422
        m_canvas->MoveCursor( pos );
423 424
        break;

425
    case WXK_NUMPAD4:
426
    case WXK_LEFT:
427
        pos.x -= KiROUND( gridSize.x );
428
        m_canvas->MoveCursor( pos );
429 430
        break;

431
    case WXK_NUMPAD6:
432
    case WXK_RIGHT:
433
        pos.x += KiROUND( gridSize.x );
434
        m_canvas->MoveCursor( pos );
435 436 437 438 439 440
        break;

    default:
        break;
    }

441
    // Update cursor position.
442
    SetCrossHairPosition( pos );
443

444
    if( oldpos != GetCrossHairPosition() )
445
    {
446 447
        pos = GetCrossHairPosition();
        SetCrossHairPosition( oldpos );
448
        m_canvas->CrossHairOff( aDC );
449
        SetCrossHairPosition( pos );
450
        m_canvas->CrossHairOn( aDC );
451

452
        if( m_canvas->IsMouseCaptured() )
453
        {
454
            m_canvas->CallMouseCapture( aDC, aPosition, true );
455 456 457
        }
    }

458
    if( aHotKey )
459
    {
460
        if( screen->GetCurItem() && screen->GetCurItem()->GetFlags() )
461
            OnHotKey( aDC, aHotKey, aPosition, screen->GetCurItem() );
462
        else
463
            OnHotKey( aDC, aHotKey, aPosition, NULL );
464
    }
465

466
    UpdateStatusBar();
467
}