You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

333 lines
10 KiB

18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
  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. /**
  26. * eeschema/controle.cpp
  27. */
  28. #include <fctsys.h>
  29. #include <gr_basic.h>
  30. #include <sch_draw_panel.h>
  31. #include <eda_dde.h>
  32. #include <sch_edit_frame.h>
  33. #include <menus_helpers.h>
  34. #include <msgpanel.h>
  35. #include <bitmaps.h>
  36. #include <eeschema_id.h>
  37. #include <general.h>
  38. #include <hotkeys.h>
  39. #include <lib_edit_frame.h>
  40. #include <viewlib_frame.h>
  41. #include <lib_draw_item.h>
  42. #include <lib_pin.h>
  43. #include <sch_sheet.h>
  44. #include <sch_sheet_path.h>
  45. #include <sch_marker.h>
  46. #include <sch_component.h>
  47. SCH_ITEM* SCH_EDIT_FRAME::LocateAndShowItem( const wxPoint& aPosition, const KICAD_T aFilterList[],
  48. int aHotKeyCommandId,
  49. bool* aClarificationMenuCancelled )
  50. {
  51. SCH_ITEM* item;
  52. LIB_PIN* Pin = NULL;
  53. SCH_COMPONENT* component = NULL;
  54. wxPoint gridPosition = GetNearestGridPosition( aPosition );
  55. // Check the on grid position first. There is more likely to be multiple items on
  56. // grid than off grid.
  57. m_canvas->SetAbortRequest( false ); // be sure a old abort request in not pending
  58. item = LocateItem( gridPosition, aFilterList, aHotKeyCommandId );
  59. // If the user aborted the clarification context menu, don't show it again at the
  60. // off grid position.
  61. if( !item && m_canvas->GetAbortRequest() )
  62. {
  63. if( aClarificationMenuCancelled )
  64. *aClarificationMenuCancelled = true;
  65. m_canvas->SetAbortRequest( false );
  66. return NULL;
  67. }
  68. if( !item && (aPosition != gridPosition) )
  69. item = LocateItem( aPosition, aFilterList, aHotKeyCommandId );
  70. if( !item )
  71. {
  72. if( aClarificationMenuCancelled )
  73. *aClarificationMenuCancelled = m_canvas->GetAbortRequest();
  74. m_canvas->SetAbortRequest( false ); // Just in case the user aborted the context menu.
  75. return NULL;
  76. }
  77. // Cross probing to Pcbnew if a pin or a component is found
  78. switch( item->Type() )
  79. {
  80. case SCH_FIELD_T:
  81. case LIB_FIELD_T:
  82. component = (SCH_COMPONENT*) item->GetParent();
  83. SendMessageToPCBNEW( item, component );
  84. break;
  85. case SCH_COMPONENT_T:
  86. component = (SCH_COMPONENT*) item;
  87. SendMessageToPCBNEW( item, component );
  88. break;
  89. case LIB_PIN_T:
  90. Pin = (LIB_PIN*) item;
  91. component = (SCH_COMPONENT*) LocateItem( aPosition, SCH_COLLECTOR::ComponentsOnly );
  92. break;
  93. /* case SCH_SHEET_T: */
  94. /* // This may lag on larger projects */
  95. /* SendMessageToPCBNEW( item, nullptr ); */
  96. /* break; */
  97. default:
  98. ;
  99. }
  100. if( Pin )
  101. {
  102. // Force display pin information (the previous display could be a component info)
  103. MSG_PANEL_ITEMS items;
  104. Pin->GetMsgPanelInfo( m_UserUnits, items, component );
  105. SetMsgPanel( items );
  106. // Cross probing:2 - pin found, and send a locate pin command to Pcbnew (highlight net)
  107. SendMessageToPCBNEW( Pin, component );
  108. }
  109. return item;
  110. }
  111. SCH_ITEM* SCH_EDIT_FRAME::LocateItem( const wxPoint& aPosition, const KICAD_T aFilterList[],
  112. int aHotKeyCommandId )
  113. {
  114. SCH_ITEM* item = NULL;
  115. m_collectedItems.Collect( GetScreen()->GetDrawItems(), aFilterList, aPosition );
  116. if( m_collectedItems.GetCount() == 0 )
  117. {
  118. ClearMsgPanel();
  119. }
  120. else if( m_collectedItems.GetCount() == 1 )
  121. {
  122. item = m_collectedItems[0];
  123. }
  124. else
  125. {
  126. // There are certain parent/child and enclosure combinations that can be handled
  127. // automatically. Since schematics are meant to be human-readable we don't have
  128. // all the various overlap and coverage issues that we do in Pcbnew.
  129. if( m_collectedItems.GetCount() == 2 )
  130. {
  131. SCH_ITEM* a = m_collectedItems[ 0 ];
  132. SCH_ITEM* b = m_collectedItems[ 1 ];
  133. if( a->GetParent() == b )
  134. item = a;
  135. else if( a == b->GetParent() )
  136. item = b;
  137. else if( a->Type() == SCH_SHEET_T && b->Type() != SCH_SHEET_T )
  138. item = b;
  139. else if( b->Type() == SCH_SHEET_T && a->Type() != SCH_SHEET_T )
  140. item = a;
  141. }
  142. // There are certain combinations of items that do not need clarification such as
  143. // a corner were two lines meet or all the items form a junction.
  144. if( aHotKeyCommandId )
  145. {
  146. switch( aHotKeyCommandId )
  147. {
  148. case HK_DRAG:
  149. if( m_collectedItems.IsCorner() || m_collectedItems.IsNode( false )
  150. || m_collectedItems.IsDraggableJunction() )
  151. {
  152. item = m_collectedItems[0];
  153. }
  154. break;
  155. case HK_MOVE_COMPONENT_OR_ITEM:
  156. if( m_collectedItems.GetCount() == 2 &&
  157. dynamic_cast< SCH_SHEET_PIN * >( m_collectedItems[0] ) &&
  158. dynamic_cast< SCH_SHEET * >( m_collectedItems[1] ) )
  159. {
  160. item = m_collectedItems[0];
  161. }
  162. break;
  163. default:
  164. ;
  165. }
  166. }
  167. if( item == NULL )
  168. {
  169. wxASSERT_MSG( m_collectedItems.GetCount() <= MAX_SELECT_ITEM_IDS,
  170. wxT( "Select item clarification context menu size limit exceeded." ) );
  171. wxMenu selectMenu;
  172. AddMenuItem( &selectMenu, wxID_NONE, _( "Clarify Selection" ), KiBitmap( info_xpm ) );
  173. selectMenu.AppendSeparator();
  174. for( int i = 0; i < m_collectedItems.GetCount() && i < MAX_SELECT_ITEM_IDS; i++ )
  175. {
  176. wxString text = m_collectedItems[i]->GetSelectMenuText( m_UserUnits );
  177. BITMAP_DEF xpm = m_collectedItems[i]->GetMenuImage();
  178. AddMenuItem( &selectMenu, ID_SELECT_ITEM_START + i, text, KiBitmap( xpm ) );
  179. }
  180. // Set to NULL in case the user aborts the clarification context menu.
  181. GetScreen()->SetCurItem( NULL );
  182. m_canvas->SetAbortRequest( true ); // Changed to false if an item is selected
  183. PopupMenu( &selectMenu );
  184. if( !m_canvas->GetAbortRequest() )
  185. {
  186. m_canvas->MoveCursorToCrossHair();
  187. item = GetScreen()->GetCurItem();
  188. }
  189. }
  190. }
  191. GetScreen()->SetCurItem( item );
  192. if( item )
  193. {
  194. if( item->Type() == SCH_COMPONENT_T )
  195. ( (SCH_COMPONENT*) item )->SetCurrentSheetPath( &GetCurrentSheet() );
  196. MSG_PANEL_ITEMS items;
  197. item->GetMsgPanelInfo( m_UserUnits, items );
  198. SetMsgPanel( items );
  199. }
  200. else
  201. {
  202. ClearMsgPanel();
  203. }
  204. return item;
  205. }
  206. bool SCH_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, EDA_KEY aHotKey )
  207. {
  208. // Filter out the 'fake' mouse motion after a keyboard movement
  209. if( !aHotKey && m_movingCursorWithKeyboard )
  210. {
  211. m_movingCursorWithKeyboard = false;
  212. return false;
  213. }
  214. // when moving mouse, use the "magnetic" grid, unless the shift+ctrl keys is pressed
  215. // for next cursor position
  216. // ( shift or ctrl key down are PAN command with mouse wheel)
  217. bool snapToGrid = true;
  218. if( !aHotKey && wxGetKeyState( WXK_SHIFT ) && wxGetKeyState( WXK_CONTROL ) )
  219. snapToGrid = false;
  220. // Cursor is left off grid only if no block in progress
  221. if( GetScreen()->m_BlockLocate.GetState() != STATE_NO_BLOCK )
  222. snapToGrid = true;
  223. wxPoint pos = aPosition;
  224. bool keyHandled = GeneralControlKeyMovement( aHotKey, &pos, snapToGrid );
  225. if( GetToolId() == ID_NO_TOOL_SELECTED )
  226. m_canvas->CrossHairOff( aDC );
  227. else
  228. m_canvas->CrossHairOn( aDC );
  229. SetCrossHairPosition( pos, snapToGrid );
  230. if( m_canvas->IsMouseCaptured() )
  231. m_canvas->CallMouseCapture( aDC, aPosition, true );
  232. if( aHotKey )
  233. {
  234. SCH_SCREEN* screen = GetScreen();
  235. bool hk_handled;
  236. if( screen->GetCurItem() && screen->GetCurItem()->GetFlags() )
  237. hk_handled = OnHotKey( aDC, aHotKey, aPosition, screen->GetCurItem() );
  238. else
  239. hk_handled = OnHotKey( aDC, aHotKey, aPosition, NULL );
  240. if( hk_handled )
  241. keyHandled = true;
  242. }
  243. UpdateStatusBar(); /* Display cursor coordinates info */
  244. return keyHandled;
  245. }
  246. bool LIB_VIEW_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, EDA_KEY aHotKey )
  247. {
  248. bool eventHandled = true;
  249. // Filter out the 'fake' mouse motion after a keyboard movement
  250. if( !aHotKey && m_movingCursorWithKeyboard )
  251. {
  252. m_movingCursorWithKeyboard = false;
  253. return false;
  254. }
  255. wxPoint pos = aPosition;
  256. GeneralControlKeyMovement( aHotKey, &pos, true );
  257. // Update cursor position.
  258. m_canvas->CrossHairOn( aDC );
  259. SetCrossHairPosition( pos, true );
  260. if( aHotKey )
  261. {
  262. SCH_SCREEN* screen = GetScreen();
  263. if( screen->GetCurItem() && screen->GetCurItem()->GetFlags() )
  264. eventHandled = OnHotKey( aDC, aHotKey, aPosition, screen->GetCurItem() );
  265. else
  266. eventHandled = OnHotKey( aDC, aHotKey, aPosition, NULL );
  267. }
  268. UpdateStatusBar(); // Display cursor coordinates info.
  269. return eventHandled;
  270. }