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.

1110 lines
28 KiB

12 years ago
12 years ago
12 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2009 Jean-Pierre Charras, jp.charras@wanadoo.fr
  5. * Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 2
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, you may find one here:
  19. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  20. * or you may search the http://www.gnu.org website for the version 2 license,
  21. * or you may write to the Free Software Foundation, Inc.,
  22. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  23. */
  24. /**
  25. * @file hotkeys_board_editor.cpp
  26. */
  27. #include <fctsys.h>
  28. #include <wxPcbStruct.h>
  29. #include <class_drawpanel.h>
  30. #include <confirm.h>
  31. #include <class_board.h>
  32. #include <class_module.h>
  33. #include <class_track.h>
  34. #include <class_pcb_text.h>
  35. #include <class_mire.h>
  36. #include <class_drawsegment.h>
  37. #include <pcbnew.h>
  38. #include <pcbnew_id.h>
  39. #include <hotkeys.h>
  40. #include <class_zone.h>
  41. #include <tool/tool_manager.h>
  42. /* How to add a new hotkey:
  43. * see hotkeys.cpp
  44. */
  45. EDA_HOTKEY* PCB_EDIT_FRAME::GetHotKeyDescription( int aCommand ) const
  46. {
  47. EDA_HOTKEY* HK_Descr = GetDescriptorFromCommand( aCommand, common_Hotkey_List );
  48. if( HK_Descr == NULL )
  49. HK_Descr = GetDescriptorFromCommand( aCommand, board_edit_Hotkey_List );
  50. return HK_Descr;
  51. }
  52. bool PCB_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotkeyCode, const wxPoint& aPosition,
  53. EDA_ITEM* aItem )
  54. {
  55. if( aHotkeyCode == 0 )
  56. return false;
  57. bool itemCurrentlyEdited = GetCurItem() && GetCurItem()->GetFlags();
  58. MODULE* module = NULL;
  59. int evt_type = 0; //Used to post a wxCommandEvent on demand
  60. PCB_SCREEN* screen = GetScreen();
  61. DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)GetDisplayOptions();
  62. /* Convert lower to upper case
  63. * (the usual toupper function has problem with non ascii codes like function keys
  64. */
  65. if( (aHotkeyCode >= 'a') && (aHotkeyCode <= 'z') )
  66. aHotkeyCode += 'A' - 'a';
  67. EDA_HOTKEY* HK_Descr = GetDescriptorFromHotkey( aHotkeyCode, common_Hotkey_List );
  68. if( HK_Descr == NULL )
  69. HK_Descr = GetDescriptorFromHotkey( aHotkeyCode, board_edit_Hotkey_List );
  70. if( HK_Descr == NULL )
  71. return false;
  72. int hk_id = HK_Descr->m_Idcommand;
  73. // Create a wxCommandEvent that will be posted in some hot keys functions
  74. wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED );
  75. cmd.SetEventObject( this );
  76. LAYER_NUM ll;
  77. switch( hk_id )
  78. {
  79. default:
  80. case HK_NOT_FOUND:
  81. return false;
  82. case HK_LEFT_CLICK:
  83. OnLeftClick( aDC, aPosition );
  84. break;
  85. case HK_LEFT_DCLICK: // Simulate a double left click: generate 2 events
  86. OnLeftClick( aDC, aPosition );
  87. OnLeftDClick( aDC, aPosition );
  88. break;
  89. case HK_SWITCH_TRACK_WIDTH_TO_NEXT:
  90. if( GetCanvas()->IsMouseCaptured() )
  91. GetCanvas()->CallMouseCapture( aDC, wxDefaultPosition, false );
  92. if( GetDesignSettings().GetTrackWidthIndex() < GetDesignSettings().m_TrackWidthList.size() - 1 )
  93. GetDesignSettings().SetTrackWidthIndex( GetDesignSettings().GetTrackWidthIndex() + 1 );
  94. else
  95. GetDesignSettings().SetTrackWidthIndex( 0 );
  96. if( GetCanvas()->IsMouseCaptured() )
  97. GetCanvas()->CallMouseCapture( aDC, wxDefaultPosition, false );
  98. break;
  99. case HK_SWITCH_TRACK_WIDTH_TO_PREVIOUS:
  100. if( GetCanvas()->IsMouseCaptured() )
  101. GetCanvas()->CallMouseCapture( aDC, wxDefaultPosition, false );
  102. if( GetDesignSettings().GetTrackWidthIndex() <= 0 )
  103. GetDesignSettings().SetTrackWidthIndex( GetDesignSettings().m_TrackWidthList.size() -1 );
  104. else
  105. GetDesignSettings().SetTrackWidthIndex( GetDesignSettings().GetTrackWidthIndex() - 1 );
  106. if( GetCanvas()->IsMouseCaptured() )
  107. GetCanvas()->CallMouseCapture( aDC, wxDefaultPosition, false );
  108. break;
  109. case HK_SWITCH_GRID_TO_FASTGRID1:
  110. SetFastGrid1();
  111. break;
  112. case HK_SWITCH_GRID_TO_FASTGRID2:
  113. SetFastGrid2();
  114. break;
  115. case HK_SWITCH_GRID_TO_NEXT:
  116. SetNextGrid();
  117. break;
  118. case HK_SWITCH_GRID_TO_PREVIOUS:
  119. SetPrevGrid();
  120. break;
  121. case HK_SWITCH_LAYER_TO_PREVIOUS:
  122. ll = GetActiveLayer();
  123. if( !IsCopperLayer( ll ) )
  124. break;
  125. if( ll == F_Cu )
  126. ll = B_Cu;
  127. else if( ll == B_Cu )
  128. ll = ToLAYER_ID( GetBoard()->GetCopperLayerCount() - 2 );
  129. else
  130. ll = ll - 1;
  131. SwitchLayer( aDC, ToLAYER_ID( ll ) );
  132. break;
  133. case HK_SWITCH_LAYER_TO_NEXT:
  134. ll = GetActiveLayer();
  135. if( !IsCopperLayer( ll ) )
  136. break;
  137. if( ll == B_Cu )
  138. ll = F_Cu;
  139. else if( ++ll >= GetBoard()->GetCopperLayerCount() - 1 )
  140. ll = B_Cu;
  141. SwitchLayer( aDC, ToLAYER_ID( ll ) );
  142. break;
  143. case HK_SWITCH_LAYER_TO_COMPONENT:
  144. SwitchLayer( aDC, F_Cu );
  145. break;
  146. case HK_SWITCH_LAYER_TO_COPPER:
  147. SwitchLayer( aDC, B_Cu );
  148. break;
  149. case HK_SWITCH_LAYER_TO_INNER1:
  150. SwitchLayer( aDC, In1_Cu );
  151. break;
  152. case HK_SWITCH_LAYER_TO_INNER2:
  153. SwitchLayer( aDC, In2_Cu );
  154. break;
  155. case HK_SWITCH_LAYER_TO_INNER3:
  156. SwitchLayer( aDC, In3_Cu );
  157. break;
  158. case HK_SWITCH_LAYER_TO_INNER4:
  159. SwitchLayer( aDC, In4_Cu );
  160. break;
  161. case HK_SWITCH_LAYER_TO_INNER5:
  162. SwitchLayer( aDC, In5_Cu );
  163. break;
  164. case HK_SWITCH_LAYER_TO_INNER6:
  165. SwitchLayer( aDC, In6_Cu );
  166. break;
  167. case HK_HELP: // Display Current hotkey list
  168. DisplayHotkeyList( this, g_Board_Editor_Hokeys_Descr );
  169. break;
  170. case HK_ZOOM_IN:
  171. evt_type = ID_POPUP_ZOOM_IN;
  172. break;
  173. case HK_ZOOM_OUT:
  174. evt_type = ID_POPUP_ZOOM_OUT;
  175. break;
  176. case HK_ZOOM_REDRAW:
  177. evt_type = ID_ZOOM_REDRAW;
  178. break;
  179. case HK_ZOOM_AUTO:
  180. evt_type = ID_ZOOM_PAGE;
  181. break;
  182. case HK_ZOOM_CENTER:
  183. evt_type = ID_POPUP_ZOOM_CENTER;
  184. break;
  185. case HK_ZOOM_SELECTION:
  186. evt_type = ID_ZOOM_SELECTION;
  187. break;
  188. case HK_ADD_MODULE:
  189. evt_type = ID_PCB_MODULE_BUTT;
  190. break;
  191. case HK_UNDO:
  192. case HK_REDO:
  193. if( !itemCurrentlyEdited )
  194. {
  195. wxCommandEvent event( wxEVT_COMMAND_TOOL_CLICKED, HK_Descr->m_IdMenuEvent );
  196. wxPostEvent( this, event );
  197. }
  198. break;
  199. case HK_RESET_LOCAL_COORD: // Set the relative coord
  200. GetScreen()->m_O_Curseur = GetCrossHairPosition();
  201. break;
  202. case HK_SET_GRID_ORIGIN:
  203. SetGridOrigin( GetCrossHairPosition() );
  204. OnModify(); // because grid origin is saved in board, show as modified
  205. m_canvas->Refresh();
  206. break;
  207. case HK_RESET_GRID_ORIGIN:
  208. SetGridOrigin( wxPoint( 0,0 ) );
  209. OnModify(); // because grid origin is saved in board, show as modified
  210. m_canvas->Refresh();
  211. break;
  212. case HK_SWITCH_UNITS:
  213. evt_type = (g_UserUnit == INCHES) ?
  214. ID_TB_OPTIONS_SELECT_UNIT_MM : ID_TB_OPTIONS_SELECT_UNIT_INCH;
  215. break;
  216. case HK_SWITCH_TRACK_DISPLAY_MODE:
  217. displ_opts->m_DisplayPcbTrackFill = !displ_opts->m_DisplayPcbTrackFill;
  218. m_canvas->Refresh();
  219. break;
  220. case HK_DELETE:
  221. OnHotkeyDeleteItem( aDC );
  222. break;
  223. case HK_BACK_SPACE:
  224. if( IsCopperLayer( GetActiveLayer() ) )
  225. {
  226. if( !itemCurrentlyEdited )
  227. {
  228. // no track is currently being edited - select a segment and remove it.
  229. // @todo: possibly? pass the HK command code to PcbGeneralLocateAndDisplay()
  230. // so it can restrict its search to specific item types.
  231. BOARD_ITEM * item = PcbGeneralLocateAndDisplay();
  232. // don't let backspace delete modules!!
  233. if( item && item->IsTrack() )
  234. {
  235. Delete_Segment( aDC, (TRACK*) item );
  236. SetCurItem( NULL );
  237. }
  238. OnModify();
  239. }
  240. else if( GetCurItem()->IsTrack() )
  241. {
  242. // then an element is being edited - remove the last segment.
  243. // simple lines for debugger:
  244. TRACK* track = (TRACK*) GetCurItem();
  245. track = Delete_Segment( aDC, track );
  246. SetCurItem( track );
  247. OnModify();
  248. }
  249. }
  250. break;
  251. case HK_GET_AND_MOVE_FOOTPRINT:
  252. if( !itemCurrentlyEdited )
  253. evt_type = ID_POPUP_PCB_GET_AND_MOVE_MODULE_REQUEST;
  254. break;
  255. case HK_FIND_ITEM:
  256. if( !itemCurrentlyEdited )
  257. evt_type = ID_FIND_ITEMS;
  258. break;
  259. case HK_LOAD_BOARD:
  260. if( !itemCurrentlyEdited )
  261. evt_type = ID_LOAD_FILE ;
  262. break;
  263. case HK_SAVE_BOARD:
  264. if( !itemCurrentlyEdited )
  265. evt_type = ID_SAVE_BOARD;
  266. break;
  267. case HK_ADD_MICROVIA: // Place a micro via if a track is in progress
  268. if( GetToolId() != ID_TRACK_BUTT )
  269. return true;
  270. if( !itemCurrentlyEdited ) // no track in progress: nothing to do
  271. break;
  272. if( GetCurItem()->Type() != PCB_TRACE_T ) // Should not occur
  273. return true;
  274. if( !GetCurItem()->IsNew() )
  275. return true;
  276. // place micro via and switch layer
  277. if( IsMicroViaAcceptable() )
  278. evt_type = ID_POPUP_PCB_PLACE_MICROVIA;
  279. break;
  280. case HK_ADD_BLIND_BURIED_VIA:
  281. case HK_ADD_THROUGH_VIA: // Switch to alternate layer and Place a via if a track is in progress
  282. if( GetBoard()->GetDesignSettings().m_BlindBuriedViaAllowed &&
  283. hk_id == HK_ADD_BLIND_BURIED_VIA )
  284. GetBoard()->GetDesignSettings().m_CurrentViaType = VIA_BLIND_BURIED;
  285. else
  286. GetBoard()->GetDesignSettings().m_CurrentViaType = VIA_THROUGH;
  287. if( !itemCurrentlyEdited ) // no track in progress: switch layer only
  288. {
  289. Other_Layer_Route( NULL, aDC );
  290. if( displ_opts->m_ContrastModeDisplay )
  291. m_canvas->Refresh();
  292. break;
  293. }
  294. if( GetToolId() != ID_TRACK_BUTT )
  295. return true;
  296. if( GetCurItem()->Type() != PCB_TRACE_T )
  297. return true;
  298. if( !GetCurItem()->IsNew() )
  299. return true;
  300. evt_type = hk_id == HK_ADD_BLIND_BURIED_VIA ?
  301. ID_POPUP_PCB_PLACE_BLIND_BURIED_VIA : ID_POPUP_PCB_PLACE_THROUGH_VIA;
  302. break;
  303. case HK_SEL_LAYER_AND_ADD_THROUGH_VIA:
  304. case HK_SEL_LAYER_AND_ADD_BLIND_BURIED_VIA:
  305. if( GetCurItem() == NULL || !GetCurItem()->IsNew() ||
  306. GetCurItem()->Type() != PCB_TRACE_T )
  307. break;
  308. evt_type = hk_id == HK_SEL_LAYER_AND_ADD_BLIND_BURIED_VIA ?
  309. ID_POPUP_PCB_SELECT_CU_LAYER_AND_PLACE_BLIND_BURIED_VIA :
  310. ID_POPUP_PCB_SELECT_CU_LAYER_AND_PLACE_THROUGH_VIA;
  311. break;
  312. case HK_SWITCH_TRACK_POSTURE:
  313. /* change the position of initial segment when creating new tracks
  314. * switch from _/ to -\ .
  315. */
  316. evt_type = ID_POPUP_PCB_SWITCH_TRACK_POSTURE ;
  317. break;
  318. case HK_DRAG_TRACK_KEEP_SLOPE:
  319. OnHotkeyMoveItem( HK_DRAG_TRACK_KEEP_SLOPE );
  320. break;
  321. case HK_PLACE_ITEM:
  322. OnHotkeyPlaceItem( aDC );
  323. break;
  324. case HK_ADD_NEW_TRACK: // Start new track, if possible
  325. OnHotkeyBeginRoute( aDC );
  326. break;
  327. case HK_EDIT_ITEM: // Edit board item
  328. OnHotkeyEditItem( HK_EDIT_ITEM );
  329. break;
  330. case HK_EDIT_MODULE_WITH_MODEDIT: // Edit module with module editor
  331. OnHotkeyEditItem( HK_EDIT_MODULE_WITH_MODEDIT );
  332. break;
  333. // Footprint edition:
  334. case HK_LOCK_UNLOCK_FOOTPRINT: // toggle module "MODULE_is_LOCKED" status:
  335. // get any module, locked or not locked and toggle its locked status
  336. if( !itemCurrentlyEdited )
  337. {
  338. wxPoint pos = RefPos( true );
  339. module = GetBoard()->GetFootprint( pos, screen->m_Active_Layer, true );
  340. }
  341. else if( GetCurItem()->Type() == PCB_MODULE_T )
  342. {
  343. module = (MODULE*) GetCurItem();
  344. }
  345. if( module )
  346. {
  347. SetCurItem( module );
  348. module->SetLocked( !module->IsLocked() );
  349. OnModify();
  350. SetMsgPanel( module );
  351. }
  352. break;
  353. case HK_DRAG_ITEM: // Start drag module or track segment
  354. OnHotkeyMoveItem( HK_DRAG_ITEM );
  355. break;
  356. case HK_MOVE_ITEM: // Start move item
  357. OnHotkeyMoveItem( HK_MOVE_ITEM );
  358. break;
  359. case HK_COPY_ITEM:
  360. evt_type = OnHotkeyCopyItem();
  361. break;
  362. case HK_ROTATE_ITEM: // Rotation
  363. OnHotkeyRotateItem( HK_ROTATE_ITEM );
  364. break;
  365. case HK_FLIP_ITEM:
  366. OnHotkeyFlipItem( HK_FLIP_ITEM );
  367. break;
  368. case HK_MOVE_ITEM_EXACT:
  369. case HK_DUPLICATE_ITEM:
  370. case HK_DUPLICATE_ITEM_AND_INCREMENT:
  371. case HK_CREATE_ARRAY:
  372. OnHotkeyDuplicateOrArrayItem( HK_Descr->m_Idcommand );
  373. break;
  374. case HK_SWITCH_HIGHCONTRAST_MODE: // switch to high contrast mode and refresh the canvas
  375. displ_opts->m_ContrastModeDisplay = !displ_opts->m_ContrastModeDisplay;
  376. m_canvas->Refresh();
  377. break;
  378. case HK_CANVAS_CAIRO:
  379. evt_type = ID_MENU_CANVAS_CAIRO;
  380. break;
  381. case HK_CANVAS_OPENGL:
  382. evt_type = ID_MENU_CANVAS_OPENGL;
  383. break;
  384. case HK_CANVAS_LEGACY:
  385. evt_type = ID_MENU_CANVAS_LEGACY;
  386. break;
  387. case HK_ZONE_FILL_OR_REFILL:
  388. evt_type = ID_POPUP_PCB_FILL_ALL_ZONES;
  389. break;
  390. case HK_ZONE_REMOVE_FILLED:
  391. evt_type = ID_POPUP_PCB_REMOVE_FILLED_AREAS_IN_ALL_ZONES;
  392. break;
  393. }
  394. if( evt_type != 0 )
  395. {
  396. wxCommandEvent evt( wxEVT_COMMAND_MENU_SELECTED );
  397. evt.SetEventObject( this );
  398. evt.SetId( evt_type );
  399. GetEventHandler()->ProcessEvent( evt );
  400. }
  401. return true;
  402. }
  403. bool PCB_EDIT_FRAME::OnHotkeyDeleteItem( wxDC* aDC )
  404. {
  405. BOARD_ITEM* item = GetCurItem();
  406. bool ItemFree = (item == NULL) || (item->GetFlags() == 0);
  407. switch( GetToolId() )
  408. {
  409. case ID_TRACK_BUTT:
  410. if( !IsCopperLayer ( GetActiveLayer() ) )
  411. return false;
  412. if( ItemFree )
  413. {
  414. item = PcbGeneralLocateAndDisplay();
  415. if( item && !item->IsTrack() )
  416. return false;
  417. Delete_Track( aDC, (TRACK*) item );
  418. }
  419. else if( item->IsTrack( ) )
  420. {
  421. // simple lines for debugger:
  422. TRACK* track = (TRACK*) item;
  423. track = Delete_Segment( aDC, track );
  424. SetCurItem( track );
  425. OnModify();
  426. return true;
  427. }
  428. break;
  429. case ID_PCB_MODULE_BUTT:
  430. if( ItemFree )
  431. {
  432. wxPoint pos = RefPos( false );
  433. MODULE* module = GetBoard()->GetFootprint( pos, UNDEFINED_LAYER, false );
  434. if( module == NULL || module->IsLocked() )
  435. return false;
  436. RemoveStruct( module, aDC );
  437. }
  438. else
  439. return false;
  440. break;
  441. default:
  442. if( ItemFree )
  443. {
  444. item = PcbGeneralLocateAndDisplay();
  445. // Shouldn't there be a check for locked tracks and vias here?
  446. if( item == NULL || (item->Type() == PCB_MODULE_T && (MODULE*)item->IsLocked()) )
  447. return false;
  448. RemoveStruct( item, aDC );
  449. }
  450. else
  451. return false;
  452. }
  453. OnModify();
  454. SetCurItem( NULL );
  455. return true;
  456. }
  457. bool PCB_EDIT_FRAME::OnHotkeyEditItem( int aIdCommand )
  458. {
  459. BOARD_ITEM* item = GetCurItem();
  460. bool itemCurrentlyEdited = item && item->GetFlags();
  461. if( itemCurrentlyEdited )
  462. return false;
  463. item = PcbGeneralLocateAndDisplay();
  464. if( item == NULL )
  465. return false;
  466. SetCurItem( item );
  467. int evt_type = 0; //Used to post a wxCommandEvent on demand
  468. switch( item->Type() )
  469. {
  470. case PCB_TRACE_T:
  471. case PCB_VIA_T:
  472. if( aIdCommand == HK_EDIT_ITEM )
  473. {
  474. // Be sure the corresponding netclass is selected before edit:
  475. SetCurrentNetClass( ( (BOARD_CONNECTED_ITEM*)item )->GetNetClassName() );
  476. evt_type = ID_POPUP_PCB_EDIT_TRACKSEG;
  477. }
  478. break;
  479. case PCB_TEXT_T:
  480. if( aIdCommand == HK_EDIT_ITEM )
  481. evt_type = ID_POPUP_PCB_EDIT_TEXTEPCB;
  482. break;
  483. case PCB_MODULE_T:
  484. if( aIdCommand == HK_EDIT_ITEM )
  485. evt_type = ID_POPUP_PCB_EDIT_MODULE_PRMS;
  486. else if( aIdCommand == HK_EDIT_MODULE_WITH_MODEDIT )
  487. evt_type = ID_POPUP_PCB_EDIT_MODULE_WITH_MODEDIT;
  488. break;
  489. case PCB_PAD_T:
  490. // Until dec 2012 a EDIT_MODULE event is posted here to prevent pads
  491. // from being edited by hotkeys.
  492. // Process_Special_Functions takes care of finding the parent.
  493. // After dec 2012 a EDIT_PAD event is posted, because there is no
  494. // reason to not allow pad edit by hotkey
  495. // (pad coordinates are no more modified by rounding, in nanometer version
  496. // when using inches or mm in dialog)
  497. if( aIdCommand == HK_EDIT_ITEM )
  498. evt_type = ID_POPUP_PCB_EDIT_PAD;
  499. break;
  500. case PCB_TARGET_T:
  501. if( aIdCommand == HK_EDIT_ITEM )
  502. evt_type = ID_POPUP_PCB_EDIT_MIRE;
  503. break;
  504. case PCB_DIMENSION_T:
  505. if( aIdCommand == HK_EDIT_ITEM )
  506. evt_type = ID_POPUP_PCB_EDIT_DIMENSION;
  507. break;
  508. case PCB_MODULE_TEXT_T:
  509. if( aIdCommand == HK_EDIT_ITEM )
  510. evt_type = ID_POPUP_PCB_EDIT_TEXTMODULE;
  511. break;
  512. case PCB_LINE_T:
  513. if( aIdCommand == HK_EDIT_ITEM )
  514. evt_type = ID_POPUP_PCB_EDIT_DRAWING;
  515. break;
  516. case PCB_ZONE_AREA_T:
  517. if( aIdCommand == HK_EDIT_ITEM )
  518. evt_type = ID_POPUP_PCB_EDIT_ZONE_PARAMS;
  519. break;
  520. default:
  521. break;
  522. }
  523. if( evt_type != 0 )
  524. {
  525. wxCommandEvent evt( wxEVT_COMMAND_MENU_SELECTED );
  526. evt.SetEventObject( this );
  527. evt.SetId( evt_type );
  528. GetEventHandler()->ProcessEvent( evt );
  529. return true;
  530. }
  531. return false;
  532. }
  533. int PCB_EDIT_FRAME::OnHotkeyCopyItem()
  534. {
  535. BOARD_ITEM* item = GetCurItem();
  536. bool itemCurrentlyEdited = item && item->GetFlags();
  537. if( itemCurrentlyEdited )
  538. return 0;
  539. item = PcbGeneralLocateAndDisplay();
  540. if( item == NULL )
  541. return 0;
  542. SetCurItem( item );
  543. int eventId = 0;
  544. switch( item->Type() )
  545. {
  546. case PCB_TEXT_T:
  547. eventId = ID_POPUP_PCB_COPY_TEXTEPCB;
  548. break;
  549. default:
  550. eventId = 0;
  551. break;
  552. }
  553. return eventId;
  554. }
  555. bool PCB_EDIT_FRAME::OnHotkeyMoveItem( int aIdCommand )
  556. {
  557. BOARD_ITEM* item = GetCurItem();
  558. bool itemCurrentlyEdited = item && item->GetFlags();
  559. if( itemCurrentlyEdited )
  560. return false;
  561. item = PcbGeneralLocateAndDisplay();
  562. if( item == NULL )
  563. return false;
  564. SetCurItem( item );
  565. int evt_type = 0; // Used to post a wxCommandEvent on demand
  566. switch( item->Type() )
  567. {
  568. case PCB_TRACE_T:
  569. case PCB_VIA_T:
  570. if( aIdCommand == HK_MOVE_ITEM )
  571. evt_type = ID_POPUP_PCB_MOVE_TRACK_NODE;
  572. if( aIdCommand == HK_DRAG_ITEM )
  573. evt_type = ID_POPUP_PCB_DRAG_TRACK_SEGMENT;
  574. if( aIdCommand == HK_DRAG_TRACK_KEEP_SLOPE )
  575. evt_type = ID_POPUP_PCB_DRAG_TRACK_SEGMENT_KEEP_SLOPE;
  576. break;
  577. case PCB_MODULE_T:
  578. {
  579. if( aIdCommand == HK_MOVE_ITEM )
  580. evt_type = ID_POPUP_PCB_MOVE_MODULE_REQUEST;
  581. if( aIdCommand == HK_DRAG_ITEM )
  582. evt_type = ID_POPUP_PCB_DRAG_MODULE_REQUEST;
  583. }
  584. break;
  585. case PCB_PAD_T:
  586. // Post MODULE_REQUEST events here to prevent pads
  587. // from being moved or dragged by hotkeys.
  588. // Process_Special_Functions takes care of finding
  589. // the parent.
  590. if( aIdCommand == HK_MOVE_ITEM )
  591. evt_type = ID_POPUP_PCB_MOVE_MODULE_REQUEST;
  592. if( aIdCommand == HK_DRAG_ITEM )
  593. evt_type = ID_POPUP_PCB_DRAG_MODULE_REQUEST;
  594. break;
  595. case PCB_TEXT_T:
  596. if( aIdCommand == HK_MOVE_ITEM )
  597. evt_type = ID_POPUP_PCB_MOVE_TEXTEPCB_REQUEST;
  598. break;
  599. case PCB_TARGET_T:
  600. if( aIdCommand == HK_MOVE_ITEM )
  601. evt_type = ID_POPUP_PCB_MOVE_MIRE_REQUEST;
  602. break;
  603. case PCB_ZONE_AREA_T:
  604. if( aIdCommand == HK_MOVE_ITEM )
  605. evt_type = ID_POPUP_PCB_MOVE_ZONE_OUTLINES;
  606. if( aIdCommand == HK_DRAG_ITEM )
  607. evt_type = ID_POPUP_PCB_DRAG_ZONE_OUTLINE_SEGMENT;
  608. break;
  609. case PCB_MODULE_TEXT_T:
  610. if( aIdCommand == HK_MOVE_ITEM )
  611. evt_type = ID_POPUP_PCB_MOVE_TEXTMODULE_REQUEST;
  612. break;
  613. case PCB_LINE_T:
  614. if( aIdCommand == HK_MOVE_ITEM )
  615. evt_type = ID_POPUP_PCB_MOVE_DRAWING_REQUEST;
  616. break;
  617. case PCB_DIMENSION_T:
  618. if( aIdCommand == HK_MOVE_ITEM )
  619. evt_type = ID_POPUP_PCB_MOVE_TEXT_DIMENSION_REQUEST;
  620. break;
  621. default:
  622. break;
  623. }
  624. if( evt_type != 0 )
  625. {
  626. wxCommandEvent evt( wxEVT_COMMAND_MENU_SELECTED );
  627. evt.SetEventObject( this );
  628. evt.SetId( evt_type );
  629. GetEventHandler()->ProcessEvent( evt );
  630. return true;
  631. }
  632. return false;
  633. }
  634. bool PCB_EDIT_FRAME::OnHotkeyPlaceItem( wxDC* aDC )
  635. {
  636. BOARD_ITEM* item = GetCurItem();
  637. bool no_tool = GetToolId() == ID_NO_TOOL_SELECTED;
  638. bool itemCurrentlyEdited = item && item->GetFlags();
  639. m_canvas->SetAutoPanRequest( false );
  640. if( itemCurrentlyEdited )
  641. {
  642. m_canvas->SetIgnoreMouseEvents( true );
  643. m_canvas->CrossHairOff( aDC );
  644. switch( item->Type() )
  645. {
  646. case PCB_TRACE_T:
  647. case PCB_VIA_T:
  648. if( item->IsDragging() )
  649. PlaceDraggedOrMovedTrackSegment( static_cast<TRACK*>( item ), aDC );
  650. break;
  651. case PCB_TEXT_T:
  652. Place_Texte_Pcb( static_cast<TEXTE_PCB*>( item ), aDC );
  653. break;
  654. case PCB_MODULE_TEXT_T:
  655. PlaceTexteModule( static_cast<TEXTE_MODULE*>( item ), aDC );
  656. break;
  657. case PCB_PAD_T:
  658. PlacePad( static_cast<D_PAD*>( item ), aDC );
  659. break;
  660. case PCB_MODULE_T:
  661. PlaceModule( static_cast<MODULE*>( item ), aDC );
  662. break;
  663. case PCB_TARGET_T:
  664. PlaceTarget( static_cast<PCB_TARGET*>( item ), aDC );
  665. break;
  666. case PCB_LINE_T:
  667. if( no_tool ) // when no tools: existing item moving.
  668. Place_DrawItem( static_cast<DRAWSEGMENT*>( item ), aDC );
  669. break;
  670. default:
  671. break;
  672. }
  673. m_canvas->SetIgnoreMouseEvents( false );
  674. m_canvas->CrossHairOn( aDC );
  675. return true;
  676. }
  677. return false;
  678. }
  679. TRACK * PCB_EDIT_FRAME::OnHotkeyBeginRoute( wxDC* aDC )
  680. {
  681. if( !IsCopperLayer( GetActiveLayer() ) )
  682. return NULL;
  683. bool itemCurrentlyEdited = GetCurItem() && GetCurItem()->GetFlags();
  684. // Ensure the track tool is active
  685. if( GetToolId() != ID_TRACK_BUTT && !itemCurrentlyEdited )
  686. {
  687. wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED );
  688. cmd.SetEventObject( this );
  689. cmd.SetId( ID_TRACK_BUTT );
  690. GetEventHandler()->ProcessEvent( cmd );
  691. }
  692. if( GetToolId() != ID_TRACK_BUTT )
  693. return NULL;
  694. TRACK* track = NULL;
  695. if( !itemCurrentlyEdited ) // no track in progress:
  696. {
  697. track = Begin_Route( NULL, aDC );
  698. SetCurItem( track );
  699. if( track )
  700. m_canvas->SetAutoPanRequest( true );
  701. }
  702. else if( GetCurItem()->IsNew() )
  703. {
  704. track = Begin_Route( (TRACK*) GetCurItem(), aDC );
  705. // SetCurItem() must not write to the msg panel
  706. // because a track info is displayed while moving the mouse cursor
  707. if( track ) // A new segment was created
  708. SetCurItem( track, false );
  709. m_canvas->SetAutoPanRequest( true );
  710. }
  711. return track;
  712. }
  713. bool PCB_EDIT_FRAME::OnHotkeyFlipItem( int aIdCommand )
  714. {
  715. BOARD_ITEM* item = GetCurItem();
  716. bool itemCurrentlyEdited = item && item->GetFlags();
  717. int evt_type = 0; // Used to post a wxCommandEvent on demand
  718. wxASSERT( aIdCommand == HK_FLIP_ITEM );
  719. if( GetScreen()->m_BlockLocate.GetState() != STATE_NO_BLOCK )
  720. {
  721. evt_type = ID_POPUP_FLIP_BLOCK;
  722. }
  723. else
  724. {
  725. if( !itemCurrentlyEdited )
  726. item = PcbGeneralLocateAndDisplay();
  727. if( item == NULL )
  728. return false;
  729. SetCurItem( item );
  730. switch( item->Type() )
  731. {
  732. case PCB_MODULE_T:
  733. evt_type = ID_POPUP_PCB_CHANGE_SIDE_MODULE;
  734. break;
  735. case PCB_TEXT_T:
  736. evt_type = ID_POPUP_PCB_FLIP_TEXTEPCB;
  737. break;
  738. default:
  739. break;
  740. }
  741. }
  742. if( evt_type != 0 )
  743. {
  744. wxCommandEvent evt( wxEVT_COMMAND_MENU_SELECTED );
  745. evt.SetEventObject( this );
  746. evt.SetId( evt_type );
  747. GetEventHandler()->ProcessEvent( evt );
  748. return true;
  749. }
  750. else
  751. {
  752. return false;
  753. }
  754. }
  755. bool PCB_EDIT_FRAME::OnHotkeyRotateItem( int aIdCommand )
  756. {
  757. BOARD_ITEM* item = GetCurItem();
  758. bool itemCurrentlyEdited = item && item->GetFlags();
  759. int evt_type = 0; // Used to post a wxCommandEvent on demand
  760. wxASSERT( aIdCommand == HK_ROTATE_ITEM );
  761. // Allows block rotate operation on hot key.
  762. if( GetScreen()->m_BlockLocate.GetState() != STATE_NO_BLOCK )
  763. {
  764. evt_type = ID_POPUP_ROTATE_BLOCK;
  765. }
  766. else
  767. {
  768. if( !itemCurrentlyEdited )
  769. item = PcbGeneralLocateAndDisplay();
  770. if( item == NULL )
  771. return false;
  772. SetCurItem( item );
  773. switch( item->Type() )
  774. {
  775. case PCB_MODULE_T:
  776. evt_type = ID_POPUP_PCB_ROTATE_MODULE_COUNTERCLOCKWISE;
  777. break;
  778. case PCB_TEXT_T:
  779. evt_type = ID_POPUP_PCB_ROTATE_TEXTEPCB;
  780. break;
  781. case PCB_MODULE_TEXT_T:
  782. evt_type = ID_POPUP_PCB_ROTATE_TEXTMODULE;
  783. break;
  784. default:
  785. break;
  786. }
  787. }
  788. if( evt_type != 0 )
  789. {
  790. wxCommandEvent evt( wxEVT_COMMAND_MENU_SELECTED );
  791. evt.SetEventObject( this );
  792. evt.SetId( evt_type );
  793. GetEventHandler()->ProcessEvent( evt );
  794. return true;
  795. }
  796. return false;
  797. }
  798. bool PCB_EDIT_FRAME::OnHotkeyDuplicateOrArrayItem( int aIdCommand )
  799. {
  800. BOARD_ITEM* item = GetCurItem();
  801. bool itemCurrentlyEdited = item && item->GetFlags();
  802. if( itemCurrentlyEdited )
  803. return false;
  804. item = PcbGeneralLocateAndDisplay();
  805. if( item == NULL )
  806. return false;
  807. SetCurItem( item );
  808. int evt_type = 0; // Used to post a wxCommandEvent on demand
  809. bool canDuplicate = true;
  810. switch( item->Type() )
  811. {
  812. // Only handle items we know we can handle
  813. case PCB_PAD_T:
  814. canDuplicate = false;
  815. // no break
  816. case PCB_MODULE_T:
  817. case PCB_LINE_T:
  818. case PCB_TEXT_T:
  819. case PCB_TRACE_T:
  820. case PCB_ZONE_AREA_T:
  821. case PCB_TARGET_T:
  822. case PCB_DIMENSION_T:
  823. switch( aIdCommand )
  824. {
  825. case HK_CREATE_ARRAY:
  826. if( canDuplicate )
  827. evt_type = ID_POPUP_PCB_CREATE_ARRAY;
  828. break;
  829. case HK_DUPLICATE_ITEM_AND_INCREMENT:
  830. if( canDuplicate )
  831. evt_type = ID_POPUP_PCB_DUPLICATE_ITEM_AND_INCREMENT;
  832. break;
  833. case HK_DUPLICATE_ITEM:
  834. if( canDuplicate )
  835. evt_type = ID_POPUP_PCB_DUPLICATE_ITEM;
  836. break;
  837. case HK_MOVE_ITEM_EXACT:
  838. evt_type = ID_POPUP_PCB_MOVE_EXACT;
  839. break;
  840. default:
  841. // We don't handle other commands here
  842. break;
  843. }
  844. break;
  845. default:
  846. evt_type = 0;
  847. break;
  848. }
  849. return PostCommandMenuEvent( evt_type );
  850. }