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.

439 lines
13 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) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
  5. * Copyright (C) 2015-2020 KiCad Developers, see change_log.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. #include <base_units.h>
  25. #include <kiway.h>
  26. #include <pgm_base.h>
  27. #include <eeschema_settings.h>
  28. #include <symbol_editor/symbol_editor_settings.h>
  29. #include <sch_draw_panel.h>
  30. #include <sch_view.h>
  31. #include <sch_painter.h>
  32. #include <settings/settings_manager.h>
  33. #include <confirm.h>
  34. #include <preview_items/selection_area.h>
  35. #include <class_library.h>
  36. #include <sch_base_frame.h>
  37. #include <symbol_lib_table.h>
  38. #include <tool/action_toolbar.h>
  39. #include <tool/tool_manager.h>
  40. #include <tool/tool_dispatcher.h>
  41. #include <tools/ee_actions.h>
  42. #include <tools/ee_selection_tool.h>
  43. LIB_PART* SchGetLibPart( const LIB_ID& aLibId, SYMBOL_LIB_TABLE* aLibTable, PART_LIB* aCacheLib,
  44. wxWindow* aParent, bool aShowErrorMsg )
  45. {
  46. wxCHECK_MSG( aLibTable, nullptr, "Invalid symbol library table." );
  47. LIB_PART* symbol = nullptr;
  48. try
  49. {
  50. symbol = aLibTable->LoadSymbol( aLibId );
  51. if( !symbol && aCacheLib )
  52. {
  53. wxCHECK_MSG( aCacheLib->IsCache(), nullptr, "Invalid cache library." );
  54. wxString cacheName = aLibId.GetLibNickname().wx_str();
  55. cacheName += "_" + aLibId.GetLibItemName();
  56. symbol = aCacheLib->FindPart( cacheName );
  57. }
  58. }
  59. catch( const IO_ERROR& ioe )
  60. {
  61. if( aShowErrorMsg )
  62. {
  63. wxString msg = wxString::Format( _( "Error loading symbol '%s' from library '%s'." ),
  64. aLibId.GetLibItemName().wx_str(),
  65. aLibId.GetLibNickname().wx_str() );
  66. DisplayErrorMessage( aParent, msg, ioe.What() );
  67. }
  68. }
  69. return symbol;
  70. }
  71. SCH_BASE_FRAME::SCH_BASE_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aWindowType,
  72. const wxString& aTitle, const wxPoint& aPosition,
  73. const wxSize& aSize, long aStyle, const wxString& aFrameName ) :
  74. EDA_DRAW_FRAME( aKiway, aParent, aWindowType, aTitle, aPosition, aSize, aStyle, aFrameName ),
  75. m_base_frame_defaults( nullptr, "base_Frame_defaults" ),
  76. m_defaults( &m_base_frame_defaults )
  77. {
  78. createCanvas();
  79. Bind( wxEVT_IDLE,
  80. [this]( wxIdleEvent& aEvent )
  81. {
  82. // Handle cursor adjustments. While we can get motion and key events through
  83. // wxWidgets, we can't get modifier-key-up events.
  84. if( m_toolManager )
  85. {
  86. EE_SELECTION_TOOL* selTool = m_toolManager->GetTool<EE_SELECTION_TOOL>();
  87. if( selTool )
  88. selTool->OnIdle( aEvent );
  89. }
  90. } );
  91. }
  92. SCH_BASE_FRAME::~SCH_BASE_FRAME()
  93. {
  94. }
  95. SCH_SCREEN* SCH_BASE_FRAME::GetScreen() const
  96. {
  97. return (SCH_SCREEN*) EDA_DRAW_FRAME::GetScreen();
  98. }
  99. EESCHEMA_SETTINGS* SCH_BASE_FRAME::eeconfig() const
  100. {
  101. return dynamic_cast<EESCHEMA_SETTINGS*>( config() );
  102. }
  103. SYMBOL_EDITOR_SETTINGS* SCH_BASE_FRAME::libeditconfig() const
  104. {
  105. return dynamic_cast<SYMBOL_EDITOR_SETTINGS*>( config() );
  106. }
  107. void SCH_BASE_FRAME::SetPageSettings( const PAGE_INFO& aPageSettings )
  108. {
  109. GetScreen()->SetPageSettings( aPageSettings );
  110. }
  111. const PAGE_INFO& SCH_BASE_FRAME::GetPageSettings () const
  112. {
  113. return GetScreen()->GetPageSettings();
  114. }
  115. const wxSize SCH_BASE_FRAME::GetPageSizeIU() const
  116. {
  117. // GetSizeIU is compile time dependent:
  118. return GetScreen()->GetPageSettings().GetSizeIU();
  119. }
  120. const TITLE_BLOCK& SCH_BASE_FRAME::GetTitleBlock() const
  121. {
  122. wxASSERT( GetScreen() );
  123. return GetScreen()->GetTitleBlock();
  124. }
  125. void SCH_BASE_FRAME::SetTitleBlock( const TITLE_BLOCK& aTitleBlock )
  126. {
  127. wxASSERT( GetScreen() );
  128. GetScreen()->SetTitleBlock( aTitleBlock );
  129. }
  130. void SCH_BASE_FRAME::UpdateStatusBar()
  131. {
  132. wxString line;
  133. BASE_SCREEN* screen = GetScreen();
  134. if( !screen )
  135. return;
  136. EDA_DRAW_FRAME::UpdateStatusBar();
  137. // Display absolute and relative coordinates
  138. VECTOR2D cursorPos = GetCanvas()->GetViewControls()->GetCursorPosition();
  139. VECTOR2D d = cursorPos - screen->m_LocalOrigin;
  140. line.Printf( "X %s Y %s",
  141. MessageTextFromValue( GetUserUnits(), cursorPos.x, false ),
  142. MessageTextFromValue( GetUserUnits(), cursorPos.y, false ) );
  143. SetStatusText( line, 2 );
  144. line.Printf( "dx %s dy %s dist %s",
  145. MessageTextFromValue( GetUserUnits(), d.x, false ),
  146. MessageTextFromValue( GetUserUnits(), d.y, false ),
  147. MessageTextFromValue( GetUserUnits(), hypot( d.x, d.y ), false ) );
  148. SetStatusText( line, 3 );
  149. // refresh grid display
  150. DisplayGridMsg();
  151. // refresh units display
  152. DisplayUnitsMsg();
  153. }
  154. LIB_PART* SCH_BASE_FRAME::GetLibPart( const LIB_ID& aLibId, bool aUseCacheLib, bool aShowErrorMsg )
  155. {
  156. PART_LIB* cache = ( aUseCacheLib ) ? Prj().SchLibs()->GetCacheLibrary() : NULL;
  157. return SchGetLibPart( aLibId, Prj().SchSymbolLibTable(), cache, this, aShowErrorMsg );
  158. }
  159. bool SCH_BASE_FRAME::saveSymbolLibTables( bool aGlobal, bool aProject )
  160. {
  161. wxString msg;
  162. bool success = true;
  163. if( aGlobal )
  164. {
  165. try
  166. {
  167. SYMBOL_LIB_TABLE::GetGlobalLibTable().Save( SYMBOL_LIB_TABLE::GetGlobalTableFileName() );
  168. }
  169. catch( const IO_ERROR& ioe )
  170. {
  171. success = false;
  172. msg.Printf( _( "Error saving global symbol library table:\n%s" ), ioe.What() );
  173. wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR );
  174. }
  175. }
  176. if( aProject && !Prj().GetProjectName().IsEmpty() )
  177. {
  178. wxFileName fn( Prj().GetProjectPath(), SYMBOL_LIB_TABLE::GetSymbolLibTableFileName() );
  179. try
  180. {
  181. Prj().SchSymbolLibTable()->Save( fn.GetFullPath() );
  182. }
  183. catch( const IO_ERROR& ioe )
  184. {
  185. success = false;
  186. msg.Printf( _( "Error saving project-specific symbol library table:\n%s" ), ioe.What() );
  187. wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR );
  188. }
  189. }
  190. return success;
  191. }
  192. void SCH_BASE_FRAME::RedrawScreen( const wxPoint& aCenterPoint, bool aWarpPointer )
  193. {
  194. GetCanvas()->GetView()->SetCenter( aCenterPoint );
  195. if( aWarpPointer )
  196. GetCanvas()->GetViewControls()->CenterOnCursor();
  197. GetCanvas()->Refresh();
  198. }
  199. void SCH_BASE_FRAME::CenterScreen( const wxPoint& aCenterPoint, bool aWarpPointer )
  200. {
  201. GetCanvas()->GetView()->SetCenter( aCenterPoint );
  202. if( aWarpPointer )
  203. GetCanvas()->GetViewControls()->WarpCursor( aCenterPoint, true );
  204. GetCanvas()->Refresh();
  205. }
  206. void SCH_BASE_FRAME::HardRedraw()
  207. {
  208. GetCanvas()->GetView()->UpdateAllItems( KIGFX::ALL );
  209. GetCanvas()->ForceRefresh();
  210. }
  211. SCH_DRAW_PANEL* SCH_BASE_FRAME::GetCanvas() const
  212. {
  213. return static_cast<SCH_DRAW_PANEL*>( EDA_DRAW_FRAME::GetCanvas() );
  214. }
  215. KIGFX::SCH_RENDER_SETTINGS* SCH_BASE_FRAME::GetRenderSettings()
  216. {
  217. KIGFX::PAINTER* painter = GetCanvas()->GetView()->GetPainter();
  218. return static_cast<KIGFX::SCH_RENDER_SETTINGS*>( painter->GetSettings() );
  219. }
  220. void SCH_BASE_FRAME::createCanvas()
  221. {
  222. m_canvasType = loadCanvasTypeSetting();
  223. // Allows only a CAIRO or OPENGL canvas:
  224. if( m_canvasType != EDA_DRAW_PANEL_GAL::GAL_TYPE_OPENGL
  225. && m_canvasType != EDA_DRAW_PANEL_GAL::GAL_FALLBACK )
  226. {
  227. m_canvasType = EDA_DRAW_PANEL_GAL::GAL_TYPE_OPENGL;
  228. }
  229. SetCanvas( new SCH_DRAW_PANEL( this, wxID_ANY, wxPoint( 0, 0 ), m_frameSize,
  230. GetGalDisplayOptions(), m_canvasType ) );
  231. ActivateGalCanvas();
  232. }
  233. void SCH_BASE_FRAME::UpdateItem( EDA_ITEM* aItem, bool isAddOrDelete )
  234. {
  235. EDA_ITEM* parent = aItem->GetParent();
  236. if( aItem->Type() == SCH_SHEET_PIN_T )
  237. {
  238. // Sheet pins aren't in the view. Refresh their parent.
  239. if( parent )
  240. GetCanvas()->GetView()->Update( parent );
  241. }
  242. else
  243. {
  244. if( !isAddOrDelete )
  245. GetCanvas()->GetView()->Update( aItem );
  246. // Some children are drawn from their parents. Mark them for re-paint.
  247. static KICAD_T parentTypes[] = { SCH_COMPONENT_T, SCH_SHEET_T, SCH_GLOBAL_LABEL_T, EOT };
  248. if( parent && parent->IsType( parentTypes ) )
  249. GetCanvas()->GetView()->Update( parent, KIGFX::REPAINT );
  250. }
  251. // Calling Refresh() here introduces a bi-stable state: when doing operations on a
  252. // large number of items if at some point the refresh timer times out and does a
  253. // refresh it will take long enough that the next item will also time out, and the
  254. // next, and the next, etc.
  255. // GetCanvas()->Refresh();
  256. }
  257. void SCH_BASE_FRAME::RefreshSelection()
  258. {
  259. if( m_toolManager )
  260. {
  261. EE_SELECTION_TOOL* selectionTool = m_toolManager->GetTool<EE_SELECTION_TOOL>();
  262. SELECTION& selection = selectionTool->GetSelection();
  263. KIGFX::SCH_VIEW* view = GetCanvas()->GetView();
  264. for( EDA_ITEM* item : selection )
  265. {
  266. EDA_ITEM* parent = item->GetParent();
  267. if( item->Type() == SCH_SHEET_PIN_T )
  268. {
  269. // Sheet pins aren't in the view. Refresh their parent.
  270. if( parent )
  271. GetCanvas()->GetView()->Update( parent );
  272. }
  273. else
  274. {
  275. view->Update( item, KIGFX::REPAINT );
  276. // Component children are drawn from their parents. Mark them for re-paint.
  277. if( parent && parent->Type() == SCH_COMPONENT_T )
  278. GetCanvas()->GetView()->Update( parent, KIGFX::REPAINT );
  279. }
  280. }
  281. }
  282. }
  283. void SCH_BASE_FRAME::AddToScreen( EDA_ITEM* aItem, SCH_SCREEN* aScreen )
  284. {
  285. auto screen = aScreen;
  286. if( aScreen == nullptr )
  287. screen = GetScreen();
  288. screen->Append( (SCH_ITEM*) aItem );
  289. if( screen == GetScreen() )
  290. {
  291. GetCanvas()->GetView()->Add( aItem );
  292. UpdateItem( aItem, true ); // handle any additional parent semantics
  293. }
  294. }
  295. void SCH_BASE_FRAME::RemoveFromScreen( EDA_ITEM* aItem, SCH_SCREEN* aScreen )
  296. {
  297. auto screen = aScreen;
  298. if( aScreen == nullptr )
  299. screen = GetScreen();
  300. if( screen == GetScreen() )
  301. GetCanvas()->GetView()->Remove( aItem );
  302. screen->Remove( (SCH_ITEM*) aItem );
  303. if( screen == GetScreen() )
  304. UpdateItem( aItem, true ); // handle any additional parent semantics
  305. }
  306. void SCH_BASE_FRAME::SyncView()
  307. {
  308. GetCanvas()->GetView()->UpdateAllItems( KIGFX::ALL );
  309. }
  310. COLOR4D SCH_BASE_FRAME::GetLayerColor( SCH_LAYER_ID aLayer )
  311. {
  312. return GetColorSettings()->GetColor( aLayer );
  313. }
  314. void SCH_BASE_FRAME::CommonSettingsChanged( bool aEnvVarsChanged, bool aTextVarsChanged )
  315. {
  316. EDA_DRAW_FRAME::CommonSettingsChanged( aEnvVarsChanged, aTextVarsChanged );
  317. EESCHEMA_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<EESCHEMA_SETTINGS>();
  318. m_colorSettings = Pgm().GetSettingsManager().GetColorSettings( cfg->m_ColorTheme );
  319. GetCanvas()->GetView()->UpdateAllItems( KIGFX::ALL );
  320. GetCanvas()->Refresh();
  321. }
  322. COLOR_SETTINGS* SCH_BASE_FRAME::GetColorSettings() const
  323. {
  324. if( !m_colorSettings )
  325. {
  326. SETTINGS_MANAGER& settingsManager = Pgm().GetSettingsManager();
  327. EESCHEMA_SETTINGS* cfg = settingsManager.GetAppSettings<EESCHEMA_SETTINGS>();
  328. COLOR_SETTINGS* colorSettings = settingsManager.GetColorSettings( cfg->m_ColorTheme );
  329. const_cast<SCH_BASE_FRAME*>( this )->m_colorSettings = colorSettings;
  330. }
  331. return m_colorSettings;
  332. }
  333. COLOR4D SCH_BASE_FRAME::GetDrawBgColor() const
  334. {
  335. return GetColorSettings()->GetColor( LAYER_SCHEMATIC_BACKGROUND );
  336. }