KiCad PCB EDA Suite
hierarch.cpp
Go to the documentation of this file.
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 Wayne Stambaugh <[email protected]>
6  * Copyright (C) 2004-2021 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 #include <sch_draw_panel.h>
27 #include <confirm.h>
28 #include <id.h>
29 #include <bitmaps.h>
30 #include <dialog_shim.h>
31 #include <sch_edit_frame.h>
32 #include <sch_sheet.h>
33 #include <sch_sheet_path.h>
34 #include <schematic.h>
35 #include <tool/tool_manager.h>
36 #include <tools/ee_actions.h>
38 #include <sch_sheet_path.h>
39 
40 #include <hierarch.h>
41 #include <view/view.h>
42 #include <kiface_base.h>
43 #include "eeschema_settings.h"
44 
45 #include <wx/object.h>
46 
48 
49 
53 class TreeItemData : public wxTreeItemData
54 {
55 public:
57 
58  TreeItemData( SCH_SHEET_PATH& sheet ) : wxTreeItemData()
59  {
60  m_SheetPath = sheet;
61  }
62 };
63 
64 // Need to use wxRTTI macros in order for OnCompareItems to work properly
65 // See: https://docs.wxwidgets.org/3.1/classwx_tree_ctrl.html#ab90a465793c291ca7aa827a576b7d146
67 
68 
70  wxTreeCtrl( (wxWindow*) parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
71  wxTR_HAS_BUTTONS, wxDefaultValidator, wxT( "HierachyTreeCtrl" ) )
72 {
73  m_parent = parent;
74 
75  // Make an image list containing small icons
76  // All icons are expected having the same size.
77  wxBitmap tree_nosel_bm( KiBitmap( BITMAPS::tree_nosel ) );
78  imageList = new wxImageList( tree_nosel_bm.GetWidth(), tree_nosel_bm.GetHeight(), true, 2 );
79 
80  imageList->Add( tree_nosel_bm );
82 
83  AssignImageList( imageList );
84 }
85 
86 
88  DIALOG_SHIM( aParent, wxID_ANY, _( "Navigator" ), wxDefaultPosition, wxDefaultSize,
89  wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER, HIERARCHY_NAVIG_DLG_WNAME )
90 {
91  wxASSERT( dynamic_cast< SCH_EDIT_FRAME* >( aParent ) );
92 
93  m_SchFrameEditor = aParent;
94  m_currSheet = aParent->GetCurrentSheet();
95  m_Tree = new HIERARCHY_TREE( this );
96  m_nbsheets = 1;
97 
98  // root is the link to the main sheet.
99  wxTreeItemId root = m_Tree->AddRoot( getRootString(), 0, 1 );
100  m_Tree->SetItemBold( root, true );
101 
103  m_Tree->SetItemData( root, new TreeItemData( m_list ) );
104 
106  m_Tree->SelectItem( root );
107 
108  buildHierarchyTree( &m_list, &root );
109 
110  m_Tree->ExpandAll();
111 
112  // This bloc gives a good size to the dialog, better than the default "best" size,
113  // the first time the dialog is opened, during a session
114  wxRect itemrect;
115  wxSize tree_size;
116 
117  m_Tree->GetBoundingRect( root, itemrect );
118 
119  // Set dialog window size to be large enough
120  tree_size.x = itemrect.GetWidth() + 20;
121  tree_size.x = std::max( tree_size.x, 250 );
122 
123  // Readjust the size of the frame to an optimal value.
124  tree_size.y = m_nbsheets * itemrect.GetHeight();
125 
126  if( m_nbsheets < 2 )
127  tree_size.y += 10; // gives a better look for small trees
128 
129  SetClientSize( tree_size );
130 
131  // manage the ESC key to close the dialog, because there is no Cancel button
132  // in dialog
133  m_Tree->Connect( wxEVT_CHAR, wxKeyEventHandler( HIERARCHY_TREE::onChar ) );
134 
135  // Manage double click on a selection, or the enter key:
136  Bind( wxEVT_TREE_ITEM_ACTIVATED, &HIERARCHY_NAVIG_DLG::onSelectSheetPath, this );
137  // Manage a simple click on a selection, if the selection changes
138  Bind( wxEVT_TREE_SEL_CHANGED, &HIERARCHY_NAVIG_DLG::onSelectSheetPath, this );
139 
140  // Connect close event for the dialog:
141  this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( HIERARCHY_NAVIG_DLG::OnCloseNav ) );
142 }
143 
144 
146 {
147  Unbind( wxEVT_TREE_ITEM_ACTIVATED, &HIERARCHY_NAVIG_DLG::onSelectSheetPath, this );
148  Unbind( wxEVT_TREE_SEL_CHANGED, &HIERARCHY_NAVIG_DLG::onSelectSheetPath, this );
149  m_Tree->Disconnect( wxEVT_CHAR, wxKeyEventHandler( HIERARCHY_TREE::onChar ) );
150  Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( HIERARCHY_NAVIG_DLG::OnCloseNav ) );
151 }
152 
153 
154 void HIERARCHY_TREE::onChar( wxKeyEvent& event )
155 {
156  if( event.GetKeyCode() == WXK_ESCAPE )
157  m_parent->Close( true );
158  else
159  event.Skip();
160 }
161 
162 
163 int HIERARCHY_TREE::OnCompareItems( const wxTreeItemId& item1, const wxTreeItemId& item2 )
164 {
165  SCH_SHEET_PATH* item1Path = &static_cast<TreeItemData*>( GetItemData( item1 ) )->m_SheetPath;
166  SCH_SHEET_PATH* item2Path = &static_cast<TreeItemData*>( GetItemData( item2 ) )->m_SheetPath;
167 
168  return item1Path->ComparePageNum( *item2Path );
169 }
170 
171 
172 void HIERARCHY_NAVIG_DLG::buildHierarchyTree( SCH_SHEET_PATH* aList, wxTreeItemId* aPreviousmenu )
173 {
174  wxCHECK_RET( m_nbsheets < NB_MAX_SHEET, wxT( "Maximum number of sheets exceeded." ) );
175 
176  std::vector<SCH_ITEM*> sheetChildren;
177  aList->LastScreen()->GetSheets( &sheetChildren );
178 
179  for( SCH_ITEM* aItem : sheetChildren )
180  {
181  SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem );
182  aList->push_back( sheet );
183 
184  wxString sheetName = formatPageString( sheet->GetFields()[SHEETNAME].GetShownText(),
185  sheet->GetPageNumber( *aList ) );
186  m_nbsheets++;
187  wxTreeItemId menu;
188  menu = m_Tree->AppendItem( *aPreviousmenu, sheetName, 0, 1 );
189  m_Tree->SetItemData( menu, new TreeItemData( *aList ) );
190 
191  if( *aList == m_currSheet )
192  {
193  m_Tree->EnsureVisible( menu );
194  m_Tree->SelectItem( menu );
195  }
196 
197  buildHierarchyTree( aList, &menu );
198  aList->pop_back();
199 
200  if( m_nbsheets >= NB_MAX_SHEET )
201  break;
202  }
203 
204  m_Tree->SortChildren( *aPreviousmenu );
205 }
206 
207 
209 {
211 
212  std::function<void( const wxTreeItemId& )> selectSheet = [&]( const wxTreeItemId& id )
213  {
214  wxCHECK_RET( id.IsOk(), wxT( "Invalid tree item" ) );
215 
216  TreeItemData* itemData = static_cast<TreeItemData*>( m_Tree->GetItemData( id ) );
217  if( itemData->m_SheetPath == m_currSheet )
218  {
219  m_Tree->EnsureVisible( id );
220  m_Tree->SelectItem( id );
221  }
222 
223  wxTreeItemIdValue cookie = id;
224  wxTreeItemId child = m_Tree->GetFirstChild( id, cookie );
225  while( child.IsOk() )
226  {
227  selectSheet( child );
228  child = m_Tree->GetNextChild( child, cookie );
229  }
230  };
231 
232  selectSheet( m_Tree->GetRootItem() );
233 }
234 
235 
237 {
238  Freeze();
239 
240  // Disable selection events
241  Unbind( wxEVT_TREE_ITEM_ACTIVATED, &HIERARCHY_NAVIG_DLG::onSelectSheetPath, this );
242  Unbind( wxEVT_TREE_SEL_CHANGED, &HIERARCHY_NAVIG_DLG::onSelectSheetPath, this );
243 
245  m_Tree->DeleteAllItems();
246  m_nbsheets = 1;
247 
248  wxTreeItemId root = m_Tree->AddRoot( getRootString(), 0, 1 );
249  m_Tree->SetItemBold( root, true );
250 
251  m_list.clear();
253  m_Tree->SetItemData( root, new TreeItemData( m_list ) );
254 
256  m_Tree->SelectItem( root );
257 
258  buildHierarchyTree( &m_list, &root );
259  m_Tree->ExpandAll();
260 
261  // Enable selection events
262  Bind( wxEVT_TREE_ITEM_ACTIVATED, &HIERARCHY_NAVIG_DLG::onSelectSheetPath, this );
263  Bind( wxEVT_TREE_SEL_CHANGED, &HIERARCHY_NAVIG_DLG::onSelectSheetPath, this );
264 
265  Thaw();
266 }
267 
268 
269 void HIERARCHY_NAVIG_DLG::onSelectSheetPath( wxTreeEvent& event )
270 {
273 
274  wxTreeItemId itemSel = m_Tree->GetSelection();
275  TreeItemData* itemData = static_cast<TreeItemData*>( m_Tree->GetItemData( itemSel ) );
276 
277  // Store the current zoom level into the current screen before switching
280 
283 
284  EESCHEMA_SETTINGS* appSettings = static_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
285 
286  if( !appSettings->m_Appearance.navigator_stays_open )
287  Close( true );
288 }
289 
290 
292 {
293  SCH_SHEET* rootSheet = &m_SchFrameEditor->Schematic().Root();
294  SCH_SHEET_PATH rootPath;
295  rootPath.push_back( rootSheet );
296 
297  return formatPageString ( _( "Root" ), rootSheet->GetPageNumber( rootPath ) );
298 }
299 
300 
301 wxString HIERARCHY_NAVIG_DLG::formatPageString( const wxString& aName, const wxString& aPage )
302 {
303  return aName + wxT( " " ) + wxString::Format( _( "(page %s)" ), aPage );
304 }
305 
306 
307 void HIERARCHY_NAVIG_DLG::OnCloseNav( wxCloseEvent& event )
308 {
309  Destroy();
310 }
311 
312 
314 {
317  SCH_SCREEN* screen = GetCurrentSheet().LastScreen();
318 
319  wxASSERT( screen );
320 
321  SetScreen( screen );
322 
323  // update the References
326 
327  if( !screen->m_zoomInitialized )
328  {
329  initScreenZoom();
330  }
331  else
332  {
333  // Set zoom to last used in this screen
334  GetCanvas()->GetView()->SetScale( GetScreen()->m_LastZoomLevel );
335  RedrawScreen( (wxPoint) GetScreen()->m_ScrollCenter, false );
336  }
337 
338  UpdateTitle();
339 
340  HardRedraw(); // Ensure all items are redrawn (especially the drawing-sheet items)
341 
344  editTool->UpdateNetHighlighting( dummy );
345 
346  if( FindHierarchyNavigator() )
348 }
void SetCurrentSheet(const SCH_SHEET_PATH &aSheet)
void onSelectSheetPath(wxTreeEvent &event)
Open the selected sheet and display the corresponding screen when a tree item is selected.
Definition: hierarch.cpp:269
KIGFX::SCH_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
#define NB_MAX_SHEET
Max number of sheets in a hierarchy project.
Definition: sch_screen.h:78
HIERARCHY_NAVIG_DLG * FindHierarchyNavigator()
virtual void RedrawScreen(const wxPoint &aCenterPoint, bool aWarpPointer)
int ComparePageNum(const SCH_SHEET_PATH &aSheetPathToTest) const
Compare sheets by their page number.
wxImageList * imageList
Definition: hierarch.h:62
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
This file is part of the common library.
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
void SetScreen(BASE_SCREEN *aScreen) override
void GetSheets(std::vector< SCH_ITEM * > *aItems) const
Similar to Items().OfType( SCH_SHEET_T ), but return the sheets in a deterministic order (L-R,...
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
double m_LastZoomLevel
last value for the zoom level, useful in Eeschema when changing the current displayed sheet to reuse ...
Definition: sch_screen.h:508
static TOOL_ACTION cancelInteractive
Definition: actions.h:62
Store an SCH_SHEET_PATH of each sheet in hierarchy.
Definition: hierarch.cpp:53
void UpdateTitle()
Set the main window title bar text.
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:143
int OnCompareItems(const wxTreeItemId &item1, const wxTreeItemId &item2) override
Definition: hierarch.cpp:163
HIERARCHY_TREE * m_Tree
Definition: hierarch.h:114
Schematic editor (Eeschema) main window.
Handle hierarchy tree control.
Definition: hierarch.h:46
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition: dialog_shim.h:82
wxString getRootString()
Definition: hierarch.cpp:291
void DisplayCurrentSheet()
Draw the current sheet on the display.
Definition: hierarch.cpp:313
void UpdateAllScreenReferences()
Update all the symbol references for this sheet path.
SCH_EDIT_FRAME * m_SchFrameEditor
Definition: hierarch.h:113
wxIMPLEMENT_ABSTRACT_CLASS(HIERARCHY_TREE, wxTreeCtrl)
TreeItemData(SCH_SHEET_PATH &sheet)
Definition: hierarch.cpp:58
void pop_back()
Forwarded method from std::vector.
SCH_SHEET_PATH m_currSheet
Definition: hierarch.h:111
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:72
std::vector< SCH_FIELD > & GetFields()
Definition: sch_sheet.h:90
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
Handle actions specific to the schematic editor.
void UpdateHierarchyTree()
Update the hierarchical tree of the schematic.
Definition: hierarch.cpp:236
void HardRedraw() override
Rebuild the GAL and redraw the screen.
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
Generic, UI-independent tool event.
Definition: tool_event.h:152
void initScreenZoom()
Initialize the zoom value of the current screen and mark the screen as zoom-initialized.
void onChar(wxKeyEvent &event)
Definition: hierarch.cpp:154
SCHEMATIC & Schematic() const
HIERARCHY_NAVIG_DLG(SCH_EDIT_FRAME *aParent)
Definition: hierarch.cpp:87
#define _(s)
#define HIERARCHY_NAVIG_DLG_WNAME
Definition: hierarch.h:36
static TOOL_ACTION clearSelection
Clears the current selection.
Definition: ee_actions.h:56
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
int UpdateNetHighlighting(const TOOL_EVENT &aEvent)
Launch a tool to highlight nets.
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:105
void UpdateHierarchySelection()
Updates the tree's selection to match current page.
Definition: hierarch.cpp:208
void clear()
Forwarded method from std::vector.
HIERARCHY_TREE(HIERARCHY_NAVIG_DLG *parent)
Definition: hierarch.cpp:69
void buildHierarchyTree(SCH_SHEET_PATH *aList, wxTreeItemId *aPreviousmenu)
Create the hierarchical tree of the schematic.
Definition: hierarch.cpp:172
void SetScale(double aScale, VECTOR2D aAnchor={ 0, 0 }) override
Set the scaling factor, zooming around a given anchor point.
Definition: sch_view.cpp:72
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:54
SCH_SHEET_PATH m_list
Definition: hierarch.h:112
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
SCH_SHEET & Root() const
Definition: schematic.h:92
TOOL_MANAGER * m_toolManager
Definition: tools_holder.h:158
SCH_SCREEN * LastScreen()
bool m_zoomInitialized
Definition: sch_screen.h:543
wxString formatPageString(const wxString &aName, const wxString &aPage)
Definition: hierarch.cpp:301
void SetSheetNumberAndCount()
Set the m_ScreenNumber and m_NumberOfScreens members for screens.
HIERARCHY_NAVIG_DLG * m_parent
Definition: hierarch.h:61
void OnCloseNav(wxCloseEvent &event)
Definition: hierarch.cpp:307
SCH_SHEET_PATH & GetCurrentSheet() const
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:54
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
double GetScale() const
Definition: view.h:264
SCH_SHEET_PATH m_SheetPath
Definition: hierarch.cpp:56
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:182
wxString GetPageNumber(const SCH_SHEET_PATH &aInstance) const
Return the sheet page number for aInstance.
Definition: sch_sheet.cpp:1190