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.

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