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.

319 lines
8.5 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2004 Jean-Pierre Charras, jp.charras at wanadoo.fr
  5. * Copyright (C) 2008-2016 Wayne Stambaugh <stambaughw@verizon.net>
  6. * Copyright (C) 2004-2016 KiCad Developers, see change_log.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 hierarch.cpp
  27. */
  28. #include <fctsys.h>
  29. #include <class_drawpanel.h>
  30. #include <confirm.h>
  31. #include <id.h>
  32. #include <schframe.h>
  33. #include <general.h>
  34. #include <sch_sheet.h>
  35. #include <sch_sheet_path.h>
  36. #include <wx/imaglist.h>
  37. #include <wx/treectrl.h>
  38. #include <class_netlist_object.h>
  39. #include <sch_sheet_path.h>
  40. enum
  41. {
  42. ID_TREECTRL_HIERARCHY = 1600
  43. };
  44. class HIERARCHY_NAVIG_DLG;
  45. /* This class derived from wxTreeItemData stores the SCH_SHEET_PATH of each
  46. * sheet in hierarchy in each TreeItem, in its associated data buffer
  47. */
  48. class TreeItemData : public wxTreeItemData
  49. {
  50. public:
  51. SCH_SHEET_PATH m_SheetPath;
  52. TreeItemData( SCH_SHEET_PATH& sheet ) : wxTreeItemData()
  53. {
  54. m_SheetPath = sheet;
  55. }
  56. };
  57. /* Class to handle hierarchy tree. */
  58. class HIERARCHY_TREE : public wxTreeCtrl
  59. {
  60. private:
  61. HIERARCHY_NAVIG_DLG* m_Parent;
  62. wxImageList* imageList;
  63. public:
  64. HIERARCHY_TREE()
  65. {
  66. m_Parent = NULL;
  67. imageList = NULL;
  68. }
  69. HIERARCHY_TREE( HIERARCHY_NAVIG_DLG* parent );
  70. DECLARE_DYNAMIC_CLASS( HIERARCHY_TREE )
  71. };
  72. IMPLEMENT_DYNAMIC_CLASS( HIERARCHY_TREE, wxTreeCtrl )
  73. HIERARCHY_TREE::HIERARCHY_TREE( HIERARCHY_NAVIG_DLG* parent ) :
  74. wxTreeCtrl( (wxWindow*)parent, ID_TREECTRL_HIERARCHY, wxDefaultPosition, wxDefaultSize,
  75. wxTR_HAS_BUTTONS, wxDefaultValidator, wxT( "HierachyTreeCtrl" ) )
  76. {
  77. m_Parent = parent;
  78. // Make an image list containing small icons
  79. // All icons are expected having the same size.
  80. wxBitmap tree_nosel_bm( KiBitmap( tree_nosel_xpm ) );
  81. imageList = new wxImageList( tree_nosel_bm.GetWidth(),
  82. tree_nosel_bm.GetHeight(), true, 2 );
  83. imageList->Add( tree_nosel_bm );
  84. imageList->Add( KiBitmap( tree_sel_xpm ) );
  85. AssignImageList( imageList );
  86. }
  87. class HIERARCHY_NAVIG_DLG : public wxDialog
  88. {
  89. public:
  90. SCH_EDIT_FRAME* m_Parent;
  91. HIERARCHY_TREE* m_Tree;
  92. int m_nbsheets;
  93. private:
  94. wxSize m_TreeSize;
  95. int maxposx;
  96. public:
  97. HIERARCHY_NAVIG_DLG( SCH_EDIT_FRAME* aParent, const wxPoint& aPos );
  98. void BuildSheetsTree( SCH_SHEET_PATH* list, wxTreeItemId* previousmenu );
  99. ~HIERARCHY_NAVIG_DLG();
  100. void OnSelect( wxTreeEvent& event );
  101. private:
  102. void OnQuit( wxCommandEvent& event );
  103. DECLARE_EVENT_TABLE()
  104. };
  105. BEGIN_EVENT_TABLE( HIERARCHY_NAVIG_DLG, wxDialog )
  106. EVT_TREE_ITEM_ACTIVATED( ID_TREECTRL_HIERARCHY, HIERARCHY_NAVIG_DLG::OnSelect )
  107. END_EVENT_TABLE()
  108. void SCH_EDIT_FRAME::InstallHierarchyFrame( wxPoint& pos )
  109. {
  110. HIERARCHY_NAVIG_DLG* treeframe = new HIERARCHY_NAVIG_DLG( this, pos );
  111. treeframe->ShowModal();
  112. treeframe->Destroy();
  113. }
  114. HIERARCHY_NAVIG_DLG::HIERARCHY_NAVIG_DLG( SCH_EDIT_FRAME* aParent, const wxPoint& aPos ) :
  115. wxDialog( aParent, wxID_ANY, _( "Navigator" ), aPos, wxSize( 110, 50 ),
  116. wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER )
  117. {
  118. wxTreeItemId cellule;
  119. m_Parent = aParent;
  120. m_Tree = new HIERARCHY_TREE( this );
  121. m_nbsheets = 1;
  122. cellule = m_Tree->AddRoot( _( "Root" ), 0, 1 );
  123. m_Tree->SetItemBold( cellule, true );
  124. SCH_SHEET_PATH list;
  125. list.push_back( g_RootSheet );
  126. m_Tree->SetItemData( cellule, new TreeItemData( list ) );
  127. if( m_Parent->GetCurrentSheet().Last() == g_RootSheet )
  128. m_Tree->SelectItem( cellule ); //root.
  129. maxposx = 15;
  130. BuildSheetsTree( &list, &cellule );
  131. m_Tree->Expand( cellule );
  132. wxRect itemrect;
  133. m_Tree->GetBoundingRect( cellule, itemrect );
  134. // Set dialog window size to be large enough
  135. m_TreeSize.x = itemrect.GetWidth() + 20;
  136. m_TreeSize.x = std::max( m_TreeSize.x, 250 );
  137. // Readjust the size of the frame to an optimal value.
  138. m_TreeSize.y = m_nbsheets * itemrect.GetHeight();
  139. m_TreeSize.y += 10;
  140. SetClientSize( m_TreeSize );
  141. }
  142. HIERARCHY_NAVIG_DLG::~HIERARCHY_NAVIG_DLG()
  143. {
  144. }
  145. void HIERARCHY_NAVIG_DLG::OnQuit( wxCommandEvent& event )
  146. {
  147. // true is to force the frame to close
  148. Close( true );
  149. }
  150. /* Routine to create the hierarchical tree of the schematic
  151. * This routine is re-entrant!
  152. */
  153. void HIERARCHY_NAVIG_DLG::BuildSheetsTree( SCH_SHEET_PATH* list, wxTreeItemId* previousmenu )
  154. {
  155. wxTreeItemId menu;
  156. if( m_nbsheets > NB_MAX_SHEET )
  157. {
  158. if( m_nbsheets == (NB_MAX_SHEET + 1) )
  159. {
  160. wxString msg;
  161. msg << wxT( "BuildSheetsTree: Error: nbsheets > " ) << NB_MAX_SHEET;
  162. DisplayError( this, msg );
  163. m_nbsheets++;
  164. }
  165. return;
  166. }
  167. maxposx += m_Tree->GetIndent();
  168. SCH_ITEM* schitem = list->LastDrawList();
  169. while( schitem && m_nbsheets < NB_MAX_SHEET )
  170. {
  171. if( schitem->Type() == SCH_SHEET_T )
  172. {
  173. SCH_SHEET* sheet = (SCH_SHEET*) schitem;
  174. m_nbsheets++;
  175. menu = m_Tree->AppendItem( *previousmenu, sheet->GetName(), 0, 1 );
  176. list->push_back( sheet );
  177. m_Tree->SetItemData( menu, new TreeItemData( *list ) );
  178. int ll = m_Tree->GetItemText( menu ).Len();
  179. #ifdef __WINDOWS__
  180. ll *= 9; // * char width
  181. #else
  182. ll *= 12; // * char width
  183. #endif
  184. ll += maxposx + 20;
  185. m_TreeSize.x = std::max( m_TreeSize.x, ll );
  186. m_TreeSize.y += 1;
  187. if( *list == m_Parent->GetCurrentSheet() )
  188. {
  189. m_Tree->EnsureVisible( menu );
  190. m_Tree->SelectItem( menu );
  191. }
  192. BuildSheetsTree( list, &menu );
  193. m_Tree->Expand( menu );
  194. list->pop_back();
  195. }
  196. schitem = schitem->Next();
  197. }
  198. maxposx -= m_Tree->GetIndent();
  199. }
  200. /* Called on a double-click on a tree item:
  201. * Open the selected sheet, and display the corresponding screen
  202. */
  203. void HIERARCHY_NAVIG_DLG::OnSelect( wxTreeEvent& event )
  204. {
  205. wxTreeItemId ItemSel = m_Tree->GetSelection();
  206. m_Parent->SetCurrentSheet(( (TreeItemData*) m_Tree->GetItemData( ItemSel ) )->m_SheetPath );
  207. m_Parent->DisplayCurrentSheet();
  208. Close( true );
  209. }
  210. void SCH_EDIT_FRAME::DisplayCurrentSheet()
  211. {
  212. SetRepeatItem( NULL );
  213. ClearMsgPanel();
  214. SCH_SCREEN* screen = m_CurrentSheet->LastScreen();
  215. // Switch to current sheet,
  216. // and update the grid size, because it can be modified in latest screen
  217. SetScreen( screen );
  218. GetScreen()->SetGrid( m_LastGridSizeId + ID_POPUP_GRID_LEVEL_1000 );
  219. // update the References
  220. m_CurrentSheet->UpdateAllScreenReferences();
  221. SetSheetNumberAndCount();
  222. m_canvas->SetCanStartBlock( -1 );
  223. if( screen->m_FirstRedraw )
  224. {
  225. Zoom_Automatique( false );
  226. screen->m_FirstRedraw = false;
  227. SetCrossHairPosition( GetScrollCenterPosition() );
  228. m_canvas->MoveCursorToCrossHair();
  229. screen->SchematicCleanUp();
  230. }
  231. else
  232. {
  233. RedrawScreen( GetScrollCenterPosition(), true );
  234. }
  235. // Some items (wires, labels) can be highlighted. So prepare the highlight flag:
  236. SetCurrentSheetHighlightFlags();
  237. // Now refresh m_canvas. Should be not necessary, but because screen has changed
  238. // the previous refresh has set all new draw parameters (scroll position ..)
  239. // but most of time there were some inconsitencies about cursor parameters
  240. // ( previous position of cursor ...) and artefacts can happen
  241. // mainly when sheet size has changed
  242. // This second refresh clears artefacts because at this point,
  243. // all parameters are now updated
  244. m_canvas->Refresh();
  245. }