KiCad PCB EDA Suite
eeschema/controle.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2008-2011 Wayne Stambaugh <stambaughw@verizon.net>
6  * Copyright (C) 2004-2019 KiCad Developers, see AUTHORS.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
30 #include <fctsys.h>
31 #include <gr_basic.h>
32 #include <sch_draw_panel.h>
33 #include <eda_dde.h>
34 #include <sch_edit_frame.h>
35 #include <menus_helpers.h>
36 #include <msgpanel.h>
37 #include <bitmaps.h>
38 
39 #include <eeschema_id.h>
40 #include <general.h>
41 #include <hotkeys.h>
42 #include <lib_edit_frame.h>
43 #include <viewlib_frame.h>
44 #include <lib_draw_item.h>
45 #include <lib_pin.h>
46 #include <sch_sheet.h>
47 #include <sch_sheet_path.h>
48 #include <sch_marker.h>
49 #include <sch_component.h>
50 #include <sch_view.h>
51 
52 
53 SCH_ITEM* SCH_EDIT_FRAME::LocateAndShowItem( const wxPoint& aPosition, const KICAD_T aFilterList[],
54  int aHotKeyCommandId,
55  bool* aClarificationMenuCancelled )
56 {
57  SCH_ITEM* item;
58  LIB_PIN* Pin = NULL;
59  SCH_COMPONENT* component = NULL;
60  wxPoint gridPosition = GetNearestGridPosition( aPosition );
61 
62  // Check the on grid position first. There is more likely to be multiple items on
63  // grid than off grid.
64  m_canvas->SetAbortRequest( false ); // be sure a old abort request in not pending
65  item = LocateItem( gridPosition, aFilterList, aHotKeyCommandId );
66 
67  // If the user aborted the clarification context menu, don't show it again at the
68  // off grid position.
69  if( !item && m_canvas->GetAbortRequest() )
70  {
71  if( aClarificationMenuCancelled )
72  *aClarificationMenuCancelled = true;
73 
74  m_canvas->SetAbortRequest( false );
75  return NULL;
76  }
77 
78  if( !item && (aPosition != gridPosition) )
79  item = LocateItem( aPosition, aFilterList, aHotKeyCommandId );
80 
81  if( !item )
82  {
83  if( aClarificationMenuCancelled )
84  *aClarificationMenuCancelled = m_canvas->GetAbortRequest();
85 
86  m_canvas->SetAbortRequest( false ); // Just in case the user aborted the context menu.
87  return NULL;
88  }
89 
90  // Cross probing to Pcbnew if a pin or a component is found
91  switch( item->Type() )
92  {
93  case SCH_FIELD_T:
94  case LIB_FIELD_T:
95  component = (SCH_COMPONENT*) item->GetParent();
96  SendMessageToPCBNEW( item, component );
97  break;
98 
99  case SCH_COMPONENT_T:
100  component = (SCH_COMPONENT*) item;
101  SendMessageToPCBNEW( item, component );
102  break;
103 
104  case LIB_PIN_T:
105  Pin = (LIB_PIN*) item;
106  component = (SCH_COMPONENT*) LocateItem( aPosition, SCH_COLLECTOR::ComponentsOnly );
107  break;
108 
109  /* case SCH_SHEET_T: */
110  /* // This may lag on larger projects */
111  /* SendMessageToPCBNEW( item, nullptr ); */
112  /* break; */
113  default:
114  ;
115  }
116 
117  if( Pin )
118  {
119  // Force display pin information (the previous display could be a component info)
120  MSG_PANEL_ITEMS items;
121 
122  Pin->GetMsgPanelInfo( m_UserUnits, items, component );
123 
124  SetMsgPanel( items );
125 
126  // Cross probing:2 - pin found, and send a locate pin command to Pcbnew (highlight net)
127  SendMessageToPCBNEW( Pin, component );
128  }
129 
130  return item;
131 }
132 
133 
134 SCH_ITEM* SCH_EDIT_FRAME::LocateItem( const wxPoint& aPosition, const KICAD_T aFilterList[],
135  int aHotKeyCommandId )
136 {
137  SCH_ITEM* item = NULL;
138 
139  m_collectedItems.Collect( GetScreen()->GetDrawItems(), aFilterList, aPosition );
140 
141  if( m_collectedItems.GetCount() == 0 )
142  {
143  ClearMsgPanel();
144  }
145  else if( m_collectedItems.GetCount() == 1 )
146  {
147  item = m_collectedItems[0];
148  }
149  else
150  {
151  // There are certain parent/child and enclosure combinations that can be handled
152  // automatically. Since schematics are meant to be human-readable we don't have
153  // all the various overlap and coverage issues that we do in Pcbnew.
154  if( m_collectedItems.GetCount() == 2 )
155  {
156  SCH_ITEM* a = m_collectedItems[ 0 ];
157  SCH_ITEM* b = m_collectedItems[ 1 ];
158 
159  if( a->GetParent() == b )
160  item = a;
161  else if( a == b->GetParent() )
162  item = b;
163  else if( a->Type() == SCH_SHEET_T && b->Type() != SCH_SHEET_T )
164  item = b;
165  else if( b->Type() == SCH_SHEET_T && a->Type() != SCH_SHEET_T )
166  item = a;
167  }
168 
169  // There are certain combinations of items that do not need clarification such as
170  // a corner were two lines meet or all the items form a junction.
171  if( aHotKeyCommandId )
172  {
173  switch( aHotKeyCommandId )
174  {
175  case HK_DRAG:
178  {
179  item = m_collectedItems[0];
180  }
181  break;
182 
184  if( m_collectedItems.GetCount() == 2 &&
185  dynamic_cast< SCH_SHEET_PIN * >( m_collectedItems[0] ) &&
186  dynamic_cast< SCH_SHEET * >( m_collectedItems[1] ) )
187  {
188  item = m_collectedItems[0];
189  }
190  break;
191 
192  default:
193  ;
194  }
195  }
196 
197  if( item == NULL )
198  {
199  wxASSERT_MSG( m_collectedItems.GetCount() <= MAX_SELECT_ITEM_IDS,
200  wxT( "Select item clarification context menu size limit exceeded." ) );
201 
202  wxMenu selectMenu;
203 
204  AddMenuItem( &selectMenu, wxID_NONE, _( "Clarify Selection" ), KiBitmap( info_xpm ) );
205  selectMenu.AppendSeparator();
206 
207  for( int i = 0; i < m_collectedItems.GetCount() && i < MAX_SELECT_ITEM_IDS; i++ )
208  {
209  wxString text = m_collectedItems[i]->GetSelectMenuText( m_UserUnits );
210  BITMAP_DEF xpm = m_collectedItems[i]->GetMenuImage();
211  AddMenuItem( &selectMenu, ID_SELECT_ITEM_START + i, text, KiBitmap( xpm ) );
212  }
213 
214  // Set to NULL in case the user aborts the clarification context menu.
215  GetScreen()->SetCurItem( NULL );
216  m_canvas->SetAbortRequest( true ); // Changed to false if an item is selected
217  PopupMenu( &selectMenu );
218 
219  if( !m_canvas->GetAbortRequest() )
220  {
222  item = GetScreen()->GetCurItem();
223  }
224  }
225  }
226 
227  GetScreen()->SetCurItem( item );
228 
229  if( item )
230  {
231  if( item->Type() == SCH_COMPONENT_T )
232  ( (SCH_COMPONENT*) item )->SetCurrentSheetPath( &GetCurrentSheet() );
233 
234  MSG_PANEL_ITEMS items;
235  item->GetMsgPanelInfo( m_UserUnits, items );
236  SetMsgPanel( items );
237  }
238  else
239  {
240  ClearMsgPanel();
241  }
242 
243  return item;
244 }
245 
246 
247 bool SCH_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, EDA_KEY aHotKey )
248 {
249  // Filter out the 'fake' mouse motion after a keyboard movement
250  if( !aHotKey && m_movingCursorWithKeyboard )
251  {
253  return false;
254  }
255 
256  // when moving mouse, use the "magnetic" grid, unless the shift+ctrl keys is pressed
257  // for next cursor position
258  // ( shift or ctrl key down are PAN command with mouse wheel)
259  bool snapToGrid = true;
260 
261  if( !aHotKey && wxGetKeyState( WXK_SHIFT ) && wxGetKeyState( WXK_CONTROL ) )
262  snapToGrid = false;
263 
264  // Cursor is left off grid only if no block in progress
265  if( GetScreen()->m_BlockLocate.GetState() != STATE_NO_BLOCK )
266  snapToGrid = true;
267 
268  wxPoint pos = aPosition;
269  bool keyHandled = GeneralControlKeyMovement( aHotKey, &pos, snapToGrid );
270 
271  if( GetToolId() == ID_NO_TOOL_SELECTED )
272  m_canvas->CrossHairOff( aDC );
273  else
274  m_canvas->CrossHairOn( aDC );
275 
276  GetGalCanvas()->GetViewControls()->SetSnapping( snapToGrid );
277  SetCrossHairPosition( pos, snapToGrid );
278 
279  if( m_canvas->IsMouseCaptured() )
280  m_canvas->CallMouseCapture( aDC, aPosition, true );
281 
282  if( aHotKey )
283  {
284  if( m_movingCursorWithKeyboard ) // The hotkey was a move crossahir cursor command
285  {
286  // The crossair was moved. move the mouse cursor to the new crosshair position:
289  }
290  else
291  {
292  SCH_SCREEN* screen = GetScreen();
293  bool hk_handled;
294 
295  if( screen->GetCurItem() && screen->GetCurItem()->GetFlags() )
296  hk_handled = OnHotKey( aDC, aHotKey, aPosition, screen->GetCurItem() );
297  else
298  hk_handled = OnHotKey( aDC, aHotKey, aPosition, NULL );
299 
300  if( hk_handled )
301  keyHandled = true;
302  }
303  }
304 
305  UpdateStatusBar(); /* Display cursor coordinates info */
306 
307  return keyHandled;
308 }
309 
310 
311 
312 bool LIB_VIEW_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, EDA_KEY aHotKey )
313 {
314  bool eventHandled = true;
315 
316  // Filter out the 'fake' mouse motion after a keyboard movement
317  if( !aHotKey && m_movingCursorWithKeyboard )
318  {
320  return false;
321  }
322 
323  wxPoint pos = aPosition;
324  GeneralControlKeyMovement( aHotKey, &pos, true );
325 
326  // Update cursor position.
327  m_canvas->CrossHairOn( aDC );
328  SetCrossHairPosition( pos, true );
329 
330  if( aHotKey )
331  {
332  SCH_SCREEN* screen = GetScreen();
333 
334  if( screen->GetCurItem() && screen->GetCurItem()->GetFlags() )
335  eventHandled = OnHotKey( aDC, aHotKey, aPosition, screen->GetCurItem() );
336  else
337  eventHandled = OnHotKey( aDC, aHotKey, aPosition, NULL );
338  }
339 
340  UpdateStatusBar(); // Display cursor coordinates info.
341 
342  return eventHandled;
343 }
Definition of the SCH_SHEET class for Eeschema.
DDE server & client.
KIGFX::VIEW_CONTROLS * GetViewControls() const
Function GetViewControls() Returns a pointer to the VIEW_CONTROLS instance used in the panel.
#define MAX_SELECT_ITEM_IDS
The maximum number of items in the clarify selection context menu.
Definition: eeschema_id.h:42
bool GeneralControl(wxDC *aDC, const wxPoint &aPosition, EDA_KEY aHotKey) override
Perform application specific control using aDC at aPosition in logical units.
bool IsDraggableJunction() const
Function IsDraggableJunction tests to see if the collected items form a draggable junction.
wxMenuItem * AddMenuItem(wxMenu *aMenu, int aId, const wxString &aText, const wxBitmap &aImage, wxItemKind aType=wxITEM_NORMAL)
Function AddMenuItem is an inline helper function to create and insert a menu item with an icon into ...
Definition: bitmap.cpp:223
bool OnHotKey(wxDC *aDC, int aHotKey, const wxPoint &aPosition, EDA_ITEM *aItem) override
EDA_DRAW_PANEL_GAL * GetGalCanvas() const
Return a pointer to GAL-based canvas of given EDA draw frame.
Definition: draw_frame.h:935
SCH_MARKER class definition.
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
void Collect(SCH_ITEM *aItem, const KICAD_T aFilterList[], const wxPoint &aPosition)
Function Collect scans a SCH_ITEM using this class's Inspector method, which does the collection.
virtual void SetSnapping(bool aEnabled)
Function SetSnapping() Enables/disables snapping cursor to grid.
static const KICAD_T ComponentsOnly[]
A scan list for schematic component items only.
SCH_COLLECTOR m_collectedItems
List of collected items.
virtual void MoveCursorToCrossHair()
Function MoveCursorToCrossHair warps the cursor to the current cross hair position.
SCH_ITEM * LocateItem(const wxPoint &aPosition, const KICAD_T aFilterList[]=SCH_COLLECTOR::AllItems, int aHotKeyCommandId=0)
Check for items at aPosition matching the types in aFilterList.
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:78
SCH_ITEM * GetCurItem() const
Return the currently selected SCH_ITEM, overriding BASE_SCREEN::GetCurItem().
Definition: sch_screen.h:196
bool GeneralControlKeyMovement(int aHotKey, wxPoint *aPos, bool aSnapToGrid)
Handle the common part of GeneralControl dedicated to global cursor keys (i.e.
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
int GetCount() const
Function GetCount returns the number of objects in the list.
Definition: collector.h:114
wxBitmap KiBitmap(BITMAP_DEF aBitmap)
Construct a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:79
void SendMessageToPCBNEW(EDA_ITEM *aObjectToSync, SCH_COMPONENT *aPart)
Send a message to Pcbnew via a socket connection.
virtual void WarpCursor(const VECTOR2D &aPosition, bool aWorldCoordinates=false, bool aWarpView=false)=0
Function WarpCursor() If enabled (.
bool IsCorner() const
Function IsCorner tests if the collected items forms as corner of two line segments.
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
virtual void CrossHairOn(wxDC *DC=nullptr)
bool OnHotKey(wxDC *aDC, int aHotKey, const wxPoint &aPosition, EDA_ITEM *aItem) override
Handle hot key events.
SCH_SHEET_PATH & GetCurrentSheet()
virtual void CallMouseCapture(wxDC *aDC, const wxPoint &aPosition, bool aErase)
Function CallMouseCapture calls the mouse capture callback.
EDA_ITEM * GetParent() const
Definition: base_struct.h:211
virtual void CrossHairOff(wxDC *DC=nullptr)
uint32_t EDA_KEY
Definition: common.h:74
void GetMsgPanelInfo(EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM > &aList) override
Display basic info (type, part and convert) about the current item in message panel.
virtual void GetMsgPanelInfo(EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM > &aList)
Function GetMsgPanelInfo populates aList of MSG_PANEL_ITEM objects with it's internal state for displ...
Definition: base_struct.h:297
SCH_ITEM * LocateAndShowItem(const wxPoint &aPosition, const KICAD_T aFilterList[]=SCH_COLLECTOR::AllItems, int aHotKeyCommandId=0, bool *aClarifySelectionMenuCancelled=nullptr)
Check the schematic at aPosition in logical (drawing) units for a item matching the types in aFilterL...
void SetAbortRequest(bool aAbortRequest)
void UpdateStatusBar() override
Update the status bar information.
wxPoint GetNearestGridPosition(const wxPoint &aPosition, wxRealPoint *aGridSize=NULL) const
Return the nearest aGridSize location to aPosition.
EDA_DRAW_PANEL * m_canvas
The area to draw on.
Definition: draw_frame.h:126
Definition the SCH_COMPONENT class for Eeschema.
bool IsNode(bool aIncludePins=true) const
Function IsNode tests if the collected items form a node.
void SetCurItem(SCH_ITEM *aItem)
Sets the currently selected object, m_CurrentItem.
Definition: sch_screen.h:204
size_t i
Definition: json11.cpp:597
Class SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:70
std::vector< MSG_PANEL_ITEM > MSG_PANEL_ITEMS
Definition: msgpanel.h:102
Definition of class LIB_EDIT_FRAME.
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
void SetCrossHairPosition(const wxPoint &aPosition, bool aSnapToGrid=true)
Set the screen cross hair position to aPosition in logical (drawing) units.
Message panel definition file.
STATUS_FLAGS GetFlags() const
Definition: base_struct.h:258
EDA_UNITS_T m_UserUnits
Definition: draw_frame.h:123
int GetState(int type) const
Definition: base_struct.h:240
Class SCH_ITEM is a base class for any item which can be embedded within the SCHEMATIC container clas...
bool m_movingCursorWithKeyboard
One-shot to avoid a recursive mouse event during hotkey movement.
Definition: draw_frame.h:176
void ClearMsgPanel(void)
Clear all messages from the message panel.
int GetToolId() const
Definition: draw_frame.h:526
wxPoint GetCrossHairPosition(bool aInvertY=false) const
Return the current cross hair position in logical (drawing) coordinates.
KICAD_T Type() const
Function Type()
Definition: base_struct.h:201
bool GeneralControl(wxDC *aDC, const wxPoint &aPosition, EDA_KEY aHotKey) override
Perform application specific control using aDC at aPosition in logical units.