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.

363 lines
11 KiB

Modular-Kicad milestone B), major portions: *) Rework the set language support, simplify it by using KIWAY. Now any major frame with a "change language" menu can change the language for all KIWAY_PLAYERs in the whole KIWAY. Multiple KIWAYs are not supported yet. *) Simplify "modal wxFrame" support, and add that support exclusively to KIWAY_PLAYER where it is inherited by all derivatives. The function KIWAY_PLAYER::ShowModal() is in the vtable and so is cross module capable. *) Remove the requirements and assumptions that the wxFrame hierarchy always had PCB_EDIT_FRAME and SCH_EDIT_FRAME as immediate parents of their viewers and editors. This is no longer the case, nor required. *) Use KIWAY::Player() everywhere to make KIWAY_PLAYERs, this registers the KIWAY_PLAYER within the KIWAY and makes it very easy to find an open frame quickly. It also gives control to the KIWAY as to frame hierarchical relationships. *) Change single_top to use the KIWAY for loading a KIFACE and instantiating the single KIWAY_PLAYER, see bullet immediately above. *) Add KIWAY::OnKiwayEnd() and call it from PGM_BASE at program termination, this gives the KIFACEs a chance to save their final configuration dope to disk. *) Add dedicated FRAME_T's for the modal frames, so m_Ident can be tested and these modal frames are distinctly different than their non-modal equivalents. KIWAY_PLAYER::IsModal() is !not! a valid test during the wxFrame's constructor, so this is another important reason for having a dedicated FRAME_T for each modal wxFrame. On balance, more lines were deleted than were added to achieve all this.
12 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-2017 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. * @file block_libedit.cpp
  27. */
  28. #include <fctsys.h>
  29. #include <gr_basic.h>
  30. #include <class_drawpanel.h>
  31. #include <confirm.h>
  32. #include <general.h>
  33. #include <class_library.h>
  34. #include <libeditframe.h>
  35. static void DrawMovingBlockOutlines( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition,
  36. bool aErase );
  37. int LIB_EDIT_FRAME::BlockCommand( EDA_KEY key )
  38. {
  39. int cmd = BLOCK_IDLE;
  40. switch( key )
  41. {
  42. default:
  43. cmd = key & 0xFF;
  44. break;
  45. case EDA_KEY_C( 0xffffffff ): // -1
  46. // Historically, -1 has been used as a key, which can cause bit flag
  47. // clashes with unaware code. On debug builds, catch any old code that
  48. // might still be doing this. TODO: remove if sure all this old code is gone.
  49. wxFAIL_MSG( "negative EDA_KEY value should be converted to GR_KEY_INVALID" );
  50. // fall through on release builds
  51. case GR_KEY_INVALID:
  52. cmd = BLOCK_PRESELECT_MOVE;
  53. break;
  54. case GR_KEY_NONE:
  55. cmd = BLOCK_MOVE;
  56. break;
  57. case GR_KB_SHIFT:
  58. cmd = BLOCK_COPY;
  59. break;
  60. case GR_KB_ALT:
  61. cmd = BLOCK_ROTATE;
  62. break;
  63. case GR_KB_SHIFTCTRL:
  64. cmd = BLOCK_DELETE;
  65. break;
  66. case GR_KB_CTRL:
  67. cmd = BLOCK_MIRROR_Y;
  68. break;
  69. case MOUSE_MIDDLE:
  70. cmd = BLOCK_ZOOM;
  71. break;
  72. }
  73. return cmd;
  74. }
  75. bool LIB_EDIT_FRAME::HandleBlockEnd( wxDC* DC )
  76. {
  77. int ItemCount = 0;
  78. bool nextCmd = false;
  79. wxPoint pt;
  80. if( GetScreen()->m_BlockLocate.GetCount() )
  81. {
  82. BLOCK_STATE_T state = GetScreen()->m_BlockLocate.GetState();
  83. BLOCK_COMMAND_T command = GetScreen()->m_BlockLocate.GetCommand();
  84. m_canvas->CallEndMouseCapture( DC );
  85. GetScreen()->m_BlockLocate.SetState( state );
  86. GetScreen()->m_BlockLocate.SetCommand( command );
  87. m_canvas->SetMouseCapture( DrawAndSizingBlockOutlines, AbortBlockCurrentCommand );
  88. SetCrossHairPosition( wxPoint( GetScreen()->m_BlockLocate.GetRight(),
  89. GetScreen()->m_BlockLocate.GetBottom() ) );
  90. m_canvas->MoveCursorToCrossHair();
  91. }
  92. switch( GetScreen()->m_BlockLocate.GetCommand() )
  93. {
  94. case BLOCK_IDLE:
  95. DisplayError( this, wxT( "Error in HandleBlockPLace" ) );
  96. break;
  97. case BLOCK_DRAG: // Drag
  98. case BLOCK_DRAG_ITEM:
  99. case BLOCK_MOVE: // Move
  100. case BLOCK_COPY: // Copy
  101. if( GetCurPart() )
  102. ItemCount = GetCurPart()->SelectItems( GetScreen()->m_BlockLocate,
  103. m_unit, m_convert,
  104. m_editPinsPerPartOrConvert );
  105. if( ItemCount )
  106. {
  107. nextCmd = true;
  108. if( m_canvas->IsMouseCaptured() )
  109. {
  110. m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
  111. m_canvas->SetMouseCaptureCallback( DrawMovingBlockOutlines );
  112. m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
  113. }
  114. GetScreen()->m_BlockLocate.SetState( STATE_BLOCK_MOVE );
  115. m_canvas->Refresh( true );
  116. }
  117. break;
  118. case BLOCK_PRESELECT_MOVE: // Move with preselection list
  119. nextCmd = true;
  120. m_canvas->SetMouseCaptureCallback( DrawMovingBlockOutlines );
  121. GetScreen()->m_BlockLocate.SetState( STATE_BLOCK_MOVE );
  122. break;
  123. case BLOCK_DELETE: // Delete
  124. if( GetCurPart() )
  125. ItemCount = GetCurPart()->SelectItems( GetScreen()->m_BlockLocate,
  126. m_unit, m_convert,
  127. m_editPinsPerPartOrConvert );
  128. if( ItemCount )
  129. SaveCopyInUndoList( GetCurPart() );
  130. if( GetCurPart() )
  131. {
  132. GetCurPart()->DeleteSelectedItems();
  133. OnModify();
  134. }
  135. break;
  136. case BLOCK_SAVE: // Save
  137. case BLOCK_PASTE:
  138. case BLOCK_FLIP:
  139. break;
  140. case BLOCK_ROTATE:
  141. case BLOCK_MIRROR_X:
  142. case BLOCK_MIRROR_Y:
  143. if( GetCurPart() )
  144. ItemCount = GetCurPart()->SelectItems( GetScreen()->m_BlockLocate,
  145. m_unit, m_convert,
  146. m_editPinsPerPartOrConvert );
  147. if( ItemCount )
  148. SaveCopyInUndoList( GetCurPart() );
  149. pt = GetScreen()->m_BlockLocate.Centre();
  150. pt = GetNearestGridPosition( pt );
  151. pt.y = -pt.y;
  152. if( GetCurPart() )
  153. {
  154. OnModify();
  155. int block_cmd = GetScreen()->m_BlockLocate.GetCommand();
  156. if( block_cmd == BLOCK_MIRROR_Y)
  157. GetCurPart()->MirrorSelectedItemsH( pt );
  158. else if( block_cmd == BLOCK_MIRROR_X)
  159. GetCurPart()->MirrorSelectedItemsV( pt );
  160. else if( block_cmd == BLOCK_ROTATE )
  161. GetCurPart()->RotateSelectedItems( pt );
  162. }
  163. break;
  164. case BLOCK_ZOOM: // Window Zoom
  165. Window_Zoom( GetScreen()->m_BlockLocate );
  166. break;
  167. case BLOCK_ABORT:
  168. break;
  169. case BLOCK_SELECT_ITEMS_ONLY:
  170. break;
  171. case BLOCK_COPY_AND_INCREMENT: // not used in Eeschema
  172. case BLOCK_MOVE_EXACT: // not used in Eeschema
  173. break;
  174. }
  175. if( !nextCmd )
  176. {
  177. if( GetScreen()->m_BlockLocate.GetCommand() != BLOCK_SELECT_ITEMS_ONLY && GetCurPart() )
  178. GetCurPart()->ClearSelectedItems();
  179. GetScreen()->m_BlockLocate.SetState( STATE_NO_BLOCK );
  180. GetScreen()->m_BlockLocate.SetCommand( BLOCK_IDLE );
  181. GetScreen()->SetCurItem( NULL );
  182. m_canvas->EndMouseCapture( GetToolId(), m_canvas->GetCurrentCursor(), wxEmptyString,
  183. false );
  184. m_canvas->Refresh( true );
  185. }
  186. return nextCmd;
  187. }
  188. void LIB_EDIT_FRAME::HandleBlockPlace( wxDC* DC )
  189. {
  190. wxPoint pt;
  191. if( !m_canvas->IsMouseCaptured() )
  192. {
  193. DisplayError( this, wxT( "HandleBlockPLace : m_mouseCaptureCallback = NULL" ) );
  194. }
  195. GetScreen()->m_BlockLocate.SetState( STATE_BLOCK_STOP );
  196. switch( GetScreen()->m_BlockLocate.GetCommand() )
  197. {
  198. case BLOCK_IDLE:
  199. break;
  200. case BLOCK_DRAG: // Drag
  201. case BLOCK_DRAG_ITEM:
  202. case BLOCK_MOVE: // Move
  203. case BLOCK_PRESELECT_MOVE: // Move with preselection list
  204. GetScreen()->m_BlockLocate.ClearItemsList();
  205. if( GetCurPart() )
  206. SaveCopyInUndoList( GetCurPart() );
  207. pt = GetScreen()->m_BlockLocate.GetMoveVector();
  208. pt.y *= -1;
  209. if( GetCurPart() )
  210. GetCurPart()->MoveSelectedItems( pt );
  211. m_canvas->Refresh( true );
  212. break;
  213. case BLOCK_COPY: // Copy
  214. GetScreen()->m_BlockLocate.ClearItemsList();
  215. if( GetCurPart() )
  216. SaveCopyInUndoList( GetCurPart() );
  217. pt = GetScreen()->m_BlockLocate.GetMoveVector();
  218. pt.y = -pt.y;
  219. if( GetCurPart() )
  220. GetCurPart()->CopySelectedItems( pt );
  221. break;
  222. case BLOCK_PASTE: // Paste (recopy the last block saved)
  223. GetScreen()->m_BlockLocate.ClearItemsList();
  224. break;
  225. case BLOCK_ROTATE: // Invert by popup menu, from block move
  226. case BLOCK_MIRROR_X: // Invert by popup menu, from block move
  227. case BLOCK_MIRROR_Y: // Invert by popup menu, from block move
  228. if( GetCurPart() )
  229. SaveCopyInUndoList( GetCurPart() );
  230. pt = GetScreen()->m_BlockLocate.Centre();
  231. pt = GetNearestGridPosition( pt );
  232. pt.y = -pt.y;
  233. if( GetCurPart() )
  234. {
  235. int block_cmd = GetScreen()->m_BlockLocate.GetCommand();
  236. if( block_cmd == BLOCK_MIRROR_Y)
  237. GetCurPart()->MirrorSelectedItemsH( pt );
  238. else if( block_cmd == BLOCK_MIRROR_X)
  239. GetCurPart()->MirrorSelectedItemsV( pt );
  240. else if( block_cmd == BLOCK_ROTATE )
  241. GetCurPart()->RotateSelectedItems( pt );
  242. }
  243. break;
  244. case BLOCK_ZOOM: // Handled by HandleBlockEnd
  245. case BLOCK_DELETE:
  246. case BLOCK_SAVE:
  247. case BLOCK_ABORT:
  248. default:
  249. break;
  250. }
  251. OnModify();
  252. GetScreen()->m_BlockLocate.SetState( STATE_NO_BLOCK );
  253. GetScreen()->m_BlockLocate.SetCommand( BLOCK_IDLE );
  254. GetScreen()->SetCurItem( NULL );
  255. m_canvas->EndMouseCapture( GetToolId(), m_canvas->GetCurrentCursor(), wxEmptyString, false );
  256. m_canvas->Refresh( true );
  257. }
  258. /*
  259. * Traces the outline of the search block structures
  260. * The entire block follows the cursor
  261. */
  262. void DrawMovingBlockOutlines( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition,
  263. bool aErase )
  264. {
  265. BLOCK_SELECTOR* block;
  266. BASE_SCREEN* screen = aPanel->GetScreen();
  267. block = &screen->m_BlockLocate;
  268. LIB_EDIT_FRAME* parent = (LIB_EDIT_FRAME*) aPanel->GetParent();
  269. wxASSERT( parent != NULL );
  270. LIB_PART* component = parent->GetCurPart();
  271. if( component == NULL )
  272. return;
  273. int unit = parent->GetUnit();
  274. int convert = parent->GetConvert();
  275. auto opts = PART_DRAW_OPTIONS::Default();
  276. opts.draw_mode = g_XorMode;
  277. opts.only_selected = true;
  278. if( aErase )
  279. {
  280. block->Draw( aPanel, aDC, block->GetMoveVector(), g_XorMode, block->GetColor() );
  281. component->Draw( aPanel, aDC, block->GetMoveVector(), unit, convert, opts );
  282. }
  283. // Repaint new view
  284. block->SetMoveVector( parent->GetCrossHairPosition() - block->GetLastCursorPosition() );
  285. GRSetDrawMode( aDC, g_XorMode );
  286. block->Draw( aPanel, aDC, block->GetMoveVector(), g_XorMode, block->GetColor() );
  287. component->Draw( aPanel, aDC, block->GetMoveVector(), unit, convert, opts );
  288. }