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 <stambaughw@gmail.com>
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->ComparePageNumAndName( *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, "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 {
210  Freeze();
211 
212  // Disable selection events
213  Unbind( wxEVT_TREE_ITEM_ACTIVATED, &HIERARCHY_NAVIG_DLG::onSelectSheetPath, this );
214  Unbind( wxEVT_TREE_SEL_CHANGED, &HIERARCHY_NAVIG_DLG::onSelectSheetPath, this );
215 
217  m_Tree->DeleteAllItems();
218  m_nbsheets = 1;
219 
220  wxTreeItemId root = m_Tree->AddRoot( getRootString(), 0, 1 );
221  m_Tree->SetItemBold( root, true );
222 
223  m_list.clear();
225  m_Tree->SetItemData( root, new TreeItemData( m_list ) );
226 
228  m_Tree->SelectItem( root );
229 
230  buildHierarchyTree( &m_list, &root );
231  m_Tree->ExpandAll();
232 
233  // Enable selection events
234  Bind( wxEVT_TREE_ITEM_ACTIVATED, &HIERARCHY_NAVIG_DLG::onSelectSheetPath, this );
235  Bind( wxEVT_TREE_SEL_CHANGED, &HIERARCHY_NAVIG_DLG::onSelectSheetPath, this );
236 
237  Thaw();
238 }
239 
240 
241 void HIERARCHY_NAVIG_DLG::onSelectSheetPath( wxTreeEvent& event )
242 {
245 
246  wxTreeItemId itemSel = m_Tree->GetSelection();
247  TreeItemData* itemData = static_cast<TreeItemData*>( m_Tree->GetItemData( itemSel ) );
248 
249  // Store the current zoom level into the current screen before switching
252 
255 
256  EESCHEMA_SETTINGS* appSettings = static_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
257 
258  if( !appSettings->m_Appearance.navigator_stays_open )
259  Close( true );
260 }
261 
262 
264 {
265  SCH_SHEET* rootSheet = &m_SchFrameEditor->Schematic().Root();
266  SCH_SHEET_PATH rootPath;
267  rootPath.push_back( rootSheet );
268 
269  return formatPageString ( _( "Root" ), rootSheet->GetPageNumber( rootPath ) );
270 }
271 
272 
273 wxString HIERARCHY_NAVIG_DLG::formatPageString( const wxString& aName, const wxString& aPage )
274 {
275  return aName + wxT( " " ) + wxString::Format( _( "(page %s)" ), aPage );
276 }
277 
278 
279 void HIERARCHY_NAVIG_DLG::OnCloseNav( wxCloseEvent& event )
280 {
281  Destroy();
282 }
283 
284 
286 {
289  SCH_SCREEN* screen = GetCurrentSheet().LastScreen();
290 
291  wxASSERT( screen );
292 
293  SetScreen( screen );
294 
295  // update the References
298 
299  if( !screen->m_zoomInitialized )
300  {
301  initScreenZoom();
302  }
303  else
304  {
305  // Set zoom to last used in this screen
306  GetCanvas()->GetView()->SetScale( GetScreen()->m_LastZoomLevel );
307  RedrawScreen( (wxPoint) GetScreen()->m_ScrollCenter, false );
308  }
309 
310  UpdateTitle();
311 
314  editTool->UpdateNetHighlighting( dummy );
315 
316  HardRedraw(); // Ensure all items are redrawn (especially the drawing-sheet items)
317 }
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:241
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
virtual void RedrawScreen(const wxPoint &aCenterPoint, bool aWarpPointer)
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,...
Definition: sch_screen.cpp:956
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:481
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:109
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:263
void DisplayCurrentSheet()
Draw the current sheet on the display.
Definition: hierarch.cpp:285
void UpdateAllScreenReferences()
Update all the symbol references for this sheet path.
SCH_EDIT_FRAME * m_SchFrameEditor
Definition: hierarch.h:108
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:106
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:88
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:208
void HardRedraw() override
Rebuild the GAL and redraw the screen.
int ComparePageNumAndName(const SCH_SHEET_PATH &aSheetPathToTest) const
Compare sheets by their page number and then by their name.
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:53
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 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:107
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:512
wxString formatPageString(const wxString &aName, const wxString &aPage)
Definition: hierarch.cpp:273
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:279
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:193
wxString GetPageNumber(const SCH_SHEET_PATH &aInstance) const
Return the sheet page number for aInstance.
Definition: sch_sheet.cpp:1111