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) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
5  * Copyright (C) 2008-2011 Wayne Stambaugh <stambaughw@verizon.net>
6  * Copyright (C) 2004-2016 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 
51 
52 SCH_ITEM* SCH_EDIT_FRAME::LocateAndShowItem( const wxPoint& aPosition, const KICAD_T aFilterList[],
53  int aHotKeyCommandId,
54  bool* aClarificationMenuCancelled )
55 {
56  SCH_ITEM* item;
57  LIB_PIN* Pin = NULL;
58  SCH_COMPONENT* component = NULL;
59  wxPoint gridPosition = GetNearestGridPosition( aPosition );
60 
61  // Check the on grid position first. There is more likely to be multiple items on
62  // grid than off grid.
63  m_canvas->SetAbortRequest( false ); // be sure a old abort request in not pending
64  item = LocateItem( gridPosition, aFilterList, aHotKeyCommandId );
65 
66  // If the user aborted the clarification context menu, don't show it again at the
67  // off grid position.
68  if( !item && m_canvas->GetAbortRequest() )
69  {
70  if( aClarificationMenuCancelled )
71  *aClarificationMenuCancelled = true;
72 
73  m_canvas->SetAbortRequest( false );
74  return NULL;
75  }
76 
77  if( !item && (aPosition != gridPosition) )
78  item = LocateItem( aPosition, aFilterList, aHotKeyCommandId );
79 
80  if( !item )
81  {
82  if( aClarificationMenuCancelled )
83  *aClarificationMenuCancelled = m_canvas->GetAbortRequest();
84 
85  m_canvas->SetAbortRequest( false ); // Just in case the user aborted the context menu.
86  return NULL;
87  }
88 
89  // Cross probing to Pcbnew if a pin or a component is found
90  switch( item->Type() )
91  {
92  case SCH_FIELD_T:
93  case LIB_FIELD_T:
94  component = (SCH_COMPONENT*) item->GetParent();
95  SendMessageToPCBNEW( item, component );
96  break;
97 
98  case SCH_COMPONENT_T:
99  component = (SCH_COMPONENT*) item;
100  SendMessageToPCBNEW( item, component );
101  break;
102 
103  case LIB_PIN_T:
104  Pin = (LIB_PIN*) item;
105  component = (SCH_COMPONENT*) LocateItem( aPosition, SCH_COLLECTOR::ComponentsOnly );
106  break;
107 
108  /* case SCH_SHEET_T: */
109  /* // This may lag on larger projects */
110  /* SendMessageToPCBNEW( item, nullptr ); */
111  /* break; */
112  default:
113  ;
114  }
115 
116  if( Pin )
117  {
118  // Force display pin information (the previous display could be a component info)
119  MSG_PANEL_ITEMS items;
120 
121  Pin->GetMsgPanelInfo( m_UserUnits, items, component );
122 
123  SetMsgPanel( items );
124 
125  // Cross probing:2 - pin found, and send a locate pin command to Pcbnew (highlight net)
126  SendMessageToPCBNEW( Pin, component );
127  }
128 
129  return item;
130 }
131 
132 
133 SCH_ITEM* SCH_EDIT_FRAME::LocateItem( const wxPoint& aPosition, const KICAD_T aFilterList[],
134  int aHotKeyCommandId )
135 {
136  SCH_ITEM* item = NULL;
137 
138  m_collectedItems.Collect( GetScreen()->GetDrawItems(), aFilterList, aPosition );
139 
140  if( m_collectedItems.GetCount() == 0 )
141  {
142  ClearMsgPanel();
143  }
144  else if( m_collectedItems.GetCount() == 1 )
145  {
146  item = m_collectedItems[0];
147  }
148  else
149  {
150  // There are certain parent/child and enclosure combinations that can be handled
151  // automatically. Since schematics are meant to be human-readable we don't have
152  // all the various overlap and coverage issues that we do in Pcbnew.
153  if( m_collectedItems.GetCount() == 2 )
154  {
155  SCH_ITEM* a = m_collectedItems[ 0 ];
156  SCH_ITEM* b = m_collectedItems[ 1 ];
157 
158  if( a->GetParent() == b )
159  item = a;
160  else if( a == b->GetParent() )
161  item = b;
162  else if( a->Type() == SCH_SHEET_T && b->Type() != SCH_SHEET_T )
163  item = b;
164  else if( b->Type() == SCH_SHEET_T && a->Type() != SCH_SHEET_T )
165  item = a;
166  }
167 
168  // There are certain combinations of items that do not need clarification such as
169  // a corner were two lines meet or all the items form a junction.
170  if( aHotKeyCommandId )
171  {
172  switch( aHotKeyCommandId )
173  {
174  case HK_DRAG:
177  {
178  item = m_collectedItems[0];
179  }
180  break;
181 
183  if( m_collectedItems.GetCount() == 2 &&
184  dynamic_cast< SCH_SHEET_PIN * >( m_collectedItems[0] ) &&
185  dynamic_cast< SCH_SHEET * >( m_collectedItems[1] ) )
186  {
187  item = m_collectedItems[0];
188  }
189  break;
190 
191  default:
192  ;
193  }
194  }
195 
196  if( item == NULL )
197  {
198  wxASSERT_MSG( m_collectedItems.GetCount() <= MAX_SELECT_ITEM_IDS,
199  wxT( "Select item clarification context menu size limit exceeded." ) );
200 
201  wxMenu selectMenu;
202 
203  AddMenuItem( &selectMenu, wxID_NONE, _( "Clarify Selection" ), KiBitmap( info_xpm ) );
204  selectMenu.AppendSeparator();
205 
206  for( int i = 0; i < m_collectedItems.GetCount() && i < MAX_SELECT_ITEM_IDS; i++ )
207  {
208  wxString text = m_collectedItems[i]->GetSelectMenuText( m_UserUnits );
209  BITMAP_DEF xpm = m_collectedItems[i]->GetMenuImage();
210  AddMenuItem( &selectMenu, ID_SELECT_ITEM_START + i, text, KiBitmap( xpm ) );
211  }
212 
213  // Set to NULL in case the user aborts the clarification context menu.
214  GetScreen()->SetCurItem( NULL );
215  m_canvas->SetAbortRequest( true ); // Changed to false if an item is selected
216  PopupMenu( &selectMenu );
217 
218  if( !m_canvas->GetAbortRequest() )
219  {
221  item = GetScreen()->GetCurItem();
222  }
223  }
224  }
225 
226  GetScreen()->SetCurItem( item );
227 
228  if( item )
229  {
230  if( item->Type() == SCH_COMPONENT_T )
231  ( (SCH_COMPONENT*) item )->SetCurrentSheetPath( &GetCurrentSheet() );
232 
233  MSG_PANEL_ITEMS items;
234  item->GetMsgPanelInfo( m_UserUnits, items );
235  SetMsgPanel( items );
236  }
237  else
238  {
239  ClearMsgPanel();
240  }
241 
242  return item;
243 }
244 
245 
246 bool SCH_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, EDA_KEY aHotKey )
247 {
248  // Filter out the 'fake' mouse motion after a keyboard movement
249  if( !aHotKey && m_movingCursorWithKeyboard )
250  {
252  return false;
253  }
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  SetCrossHairPosition( pos, snapToGrid );
277 
278  if( m_canvas->IsMouseCaptured() )
279  m_canvas->CallMouseCapture( aDC, aPosition, true );
280 
281  if( aHotKey )
282  {
283  SCH_SCREEN* screen = GetScreen();
284  bool hk_handled;
285 
286  if( screen->GetCurItem() && screen->GetCurItem()->GetFlags() )
287  hk_handled = OnHotKey( aDC, aHotKey, aPosition, screen->GetCurItem() );
288  else
289  hk_handled = OnHotKey( aDC, aHotKey, aPosition, NULL );
290 
291  if( hk_handled )
292  keyHandled = true;
293  }
294 
295  UpdateStatusBar(); /* Display cursor coordinates info */
296 
297  return keyHandled;
298 }
299 
300 
301 
302 bool LIB_VIEW_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, EDA_KEY aHotKey )
303 {
304  bool eventHandled = true;
305 
306  // Filter out the 'fake' mouse motion after a keyboard movement
307  if( !aHotKey && m_movingCursorWithKeyboard )
308  {
310  return false;
311  }
312 
313  wxPoint pos = aPosition;
314  GeneralControlKeyMovement( aHotKey, &pos, true );
315 
316  // Update cursor position.
317  m_canvas->CrossHairOn( aDC );
318  SetCrossHairPosition( pos, true );
319 
320  if( aHotKey )
321  {
322  SCH_SCREEN* screen = GetScreen();
323 
324  if( screen->GetCurItem() && screen->GetCurItem()->GetFlags() )
325  eventHandled = OnHotKey( aDC, aHotKey, aPosition, screen->GetCurItem() );
326  else
327  eventHandled = OnHotKey( aDC, aHotKey, aPosition, NULL );
328  }
329 
330  UpdateStatusBar(); // Display cursor coordinates info.
331 
332  return eventHandled;
333 }
Definition of the SCH_SHEET class for Eeschema.
int GetCount() const
Function GetCount returns the number of objects in the list.
Definition: collector.h:114
KICAD_T Type() const
Function Type()
Definition: base_struct.h:201
STATUS_FLAGS GetFlags() const
Definition: base_struct.h:258
DDE server & client.
PNG memory record (file in memory).
Definition: bitmap_types.h:43
#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.
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
void Collect(SCH_ITEM *aItem, const KICAD_T aFilterList[], const wxPoint &aPosition)
Function Collect scans a SCH_ITEM using this class&#39;s Inspector method, which does the collection...
EDA_ITEM * GetParent() const
Definition: base_struct.h:211
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.
int GetState(int type) const
Definition: base_struct.h:240
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
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.
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.
bool IsDraggableJunction() const
Function IsDraggableJunction tests to see if the collected items form a draggable junction...
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
bool IsCorner() const
Function IsCorner tests if the collected items forms as corner of two line segments.
SCH_ITEM * GetCurItem() const
Return the currently selected SCH_ITEM, overriding BASE_SCREEN::GetCurItem().
Definition: sch_screen.h:196
virtual void CrossHairOn(wxDC *DC=nullptr)
SCH_SHEET_PATH & GetCurrentSheet()
virtual void CallMouseCapture(wxDC *aDC, const wxPoint &aPosition, bool aErase)
Function CallMouseCapture calls the mouse capture callback.
virtual void CrossHairOff(wxDC *DC=nullptr)
uint32_t EDA_KEY
Definition: common.h:73
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.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet.h:61
virtual void GetMsgPanelInfo(EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM > &aList)
Function GetMsgPanelInfo populates aList of MSG_PANEL_ITEM objects with it&#39;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.
bool IsNode(bool aIncludePins=true) const
Function IsNode tests if the collected items form a node.
EDA_DRAW_PANEL * m_canvas
The area to draw on.
Definition: draw_frame.h:123
Definition the SCH_COMPONENT class for Eeschema.
wxPoint GetNearestGridPosition(const wxPoint &aPosition, wxRealPoint *aGridSize=NULL) const
Return the nearest aGridSize location to aPosition.
int GetToolId() const
Definition: draw_frame.h:519
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:69
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.
EDA_UNITS_T m_UserUnits
Definition: draw_frame.h:120
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:173
void ClearMsgPanel(void)
Clear all messages from the message panel.
bool GeneralControl(wxDC *aDC, const wxPoint &aPosition, EDA_KEY aHotKey) override
Perform application specific control using aDC at aPosition in logical units.