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_i.h>
43 #include "eeschema_settings.h"
44 
45 #include <wx/object.h>
46 #include <wx/wx.h>
47 
49 
50 
54 class TreeItemData : public wxTreeItemData
55 {
56 public:
58 
59  TreeItemData( SCH_SHEET_PATH& sheet ) : wxTreeItemData()
60  {
61  m_SheetPath = sheet;
62  }
63 };
64 
65 // Need to use wxRTTI macros in order for OnCompareItems to work properly
66 // See: https://docs.wxwidgets.org/3.1/classwx_tree_ctrl.html#ab90a465793c291ca7aa827a576b7d146
68 
69 
71  wxTreeCtrl( (wxWindow*) parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
72  wxTR_HAS_BUTTONS, wxDefaultValidator, wxT( "HierachyTreeCtrl" ) )
73 {
74  m_parent = parent;
75 
76  // Make an image list containing small icons
77  // All icons are expected having the same size.
78  wxBitmap tree_nosel_bm( KiBitmap( tree_nosel_xpm ) );
79  imageList = new wxImageList( tree_nosel_bm.GetWidth(), tree_nosel_bm.GetHeight(), true, 2 );
80 
81  imageList->Add( tree_nosel_bm );
82  imageList->Add( KiBitmap( tree_sel_xpm ) );
83 
84  AssignImageList( imageList );
85 }
86 
87 
89  DIALOG_SHIM( aParent, wxID_ANY, _( "Navigator" ), wxDefaultPosition, wxDefaultSize,
90  wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER, HIERARCHY_NAVIG_DLG_WNAME )
91 {
92  wxASSERT( dynamic_cast< SCH_EDIT_FRAME* >( aParent ) );
93 
94  m_SchFrameEditor = aParent;
95  m_currSheet = aParent->GetCurrentSheet();
96  m_Tree = new HIERARCHY_TREE( this );
97  m_nbsheets = 1;
98 
99  // root is the link to the main sheet.
100  wxTreeItemId root = m_Tree->AddRoot( getRootString(), 0, 1 );
101  m_Tree->SetItemBold( root, true );
102 
104  m_Tree->SetItemData( root, new TreeItemData( m_list ) );
105 
107  m_Tree->SelectItem( root );
108 
109  buildHierarchyTree( &m_list, &root );
110 
111  m_Tree->ExpandAll();
112 
113  // This bloc gives a good size to the dialog, better than the default "best" size,
114  // the first time the dialog is opened, during a session
115  wxRect itemrect;
116  wxSize tree_size;
117 
118  m_Tree->GetBoundingRect( root, itemrect );
119 
120  // Set dialog window size to be large enough
121  tree_size.x = itemrect.GetWidth() + 20;
122  tree_size.x = std::max( tree_size.x, 250 );
123 
124  // Readjust the size of the frame to an optimal value.
125  tree_size.y = m_nbsheets * itemrect.GetHeight();
126 
127  if( m_nbsheets < 2 )
128  tree_size.y += 10; // gives a better look for small trees
129 
130  SetClientSize( tree_size );
131 
132  // manage the ESC key to close the dialog, because thre is no Cancel button
133  // in dialog
134  m_Tree->Connect( wxEVT_CHAR, wxKeyEventHandler( HIERARCHY_TREE::onChar ) );
135 
136  // Manage double click on a selection, or the enter key:
137  Bind( wxEVT_TREE_ITEM_ACTIVATED, &HIERARCHY_NAVIG_DLG::onSelectSheetPath, this );
138  // Manage a simple click on a selection, if the selection changes
139  Bind( wxEVT_TREE_SEL_CHANGED, &HIERARCHY_NAVIG_DLG::onSelectSheetPath, this );
140 
141  // Connect close event for the dialog:
142  this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( HIERARCHY_NAVIG_DLG::OnCloseNav ) );
143 }
144 
145 
147 {
148  Unbind( wxEVT_TREE_ITEM_ACTIVATED, &HIERARCHY_NAVIG_DLG::onSelectSheetPath, this );
149  Unbind( wxEVT_TREE_SEL_CHANGED, &HIERARCHY_NAVIG_DLG::onSelectSheetPath, this );
150  m_Tree->Disconnect( wxEVT_CHAR, wxKeyEventHandler( HIERARCHY_TREE::onChar ) );
151  Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( HIERARCHY_NAVIG_DLG::OnCloseNav ) );
152 }
153 
154 
155 void HIERARCHY_TREE::onChar( wxKeyEvent& event )
156 {
157  if( event.GetKeyCode() == WXK_ESCAPE )
158  m_parent->Close( true );
159  else
160  event.Skip();
161 }
162 
163 
164 int HIERARCHY_TREE::OnCompareItems( const wxTreeItemId& item1, const wxTreeItemId& item2 )
165 {
166  SCH_SHEET_PATH* item1Path = &static_cast<TreeItemData*>( GetItemData( item1 ) )->m_SheetPath;
167  SCH_SHEET_PATH* item2Path = &static_cast<TreeItemData*>( GetItemData( item2 ) )->m_SheetPath;
168 
169  wxString item1PageNo = item1Path->Last()->GetPageNumber( *item1Path );
170  wxString item2PageNo = item2Path->Last()->GetPageNumber( *item2Path );
171 
172  return SCH_SHEET::ComparePageNum( item1PageNo, item2PageNo );
173 }
174 
175 
176 void HIERARCHY_NAVIG_DLG::buildHierarchyTree( SCH_SHEET_PATH* aList, wxTreeItemId* aPreviousmenu )
177 {
178  wxCHECK_RET( m_nbsheets < NB_MAX_SHEET, "Maximum number of sheets exceeded." );
179 
180  std::vector<SCH_ITEM*> sheetChildren;
181  aList->LastScreen()->GetSheets( &sheetChildren );
182 
183  for( SCH_ITEM* aItem : sheetChildren )
184  {
185  SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem );
186  aList->push_back( sheet );
187 
188  wxString sheetName = formatPageString( sheet->GetFields()[SHEETNAME].GetShownText(),
189  sheet->GetPageNumber( *aList ) );
190  m_nbsheets++;
191  wxTreeItemId menu;
192  menu = m_Tree->AppendItem( *aPreviousmenu, sheetName, 0, 1 );
193  m_Tree->SetItemData( menu, new TreeItemData( *aList ) );
194 
195  if( *aList == m_currSheet )
196  {
197  m_Tree->EnsureVisible( menu );
198  m_Tree->SelectItem( menu );
199  }
200 
201  buildHierarchyTree( aList, &menu );
202  aList->pop_back();
203 
204  if( m_nbsheets >= NB_MAX_SHEET )
205  break;
206  }
207 
208  m_Tree->SortChildren( *aPreviousmenu );
209 }
210 
211 
213 {
214  Freeze();
215 
216  // Disable selection events
217  Unbind( wxEVT_TREE_ITEM_ACTIVATED, &HIERARCHY_NAVIG_DLG::onSelectSheetPath, this );
218  Unbind( wxEVT_TREE_SEL_CHANGED, &HIERARCHY_NAVIG_DLG::onSelectSheetPath, this );
219 
221  m_Tree->DeleteAllItems();
222  m_nbsheets = 1;
223 
224  wxTreeItemId root = m_Tree->AddRoot( getRootString(), 0, 1 );
225  m_Tree->SetItemBold( root, true );
226 
227  m_list.clear();
229  m_Tree->SetItemData( root, new TreeItemData( m_list ) );
230 
232  m_Tree->SelectItem( root );
233 
234  buildHierarchyTree( &m_list, &root );
235  m_Tree->ExpandAll();
236 
237  // Enable selection events
238  Bind( wxEVT_TREE_ITEM_ACTIVATED, &HIERARCHY_NAVIG_DLG::onSelectSheetPath, this );
239  Bind( wxEVT_TREE_SEL_CHANGED, &HIERARCHY_NAVIG_DLG::onSelectSheetPath, this );
240 
241  Thaw();
242 }
243 
244 
245 void HIERARCHY_NAVIG_DLG::onSelectSheetPath( wxTreeEvent& event )
246 {
249 
250  wxTreeItemId itemSel = m_Tree->GetSelection();
251  TreeItemData* itemData = static_cast<TreeItemData*>( m_Tree->GetItemData( itemSel ) );
252 
253  // Store the current zoom level into the current screen before switching
256 
259 
260  EESCHEMA_SETTINGS* appSettings = static_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
261 
262  if( !appSettings->m_Appearance.navigator_stays_open )
263  Close( true );
264 }
265 
266 
268 {
269  SCH_SHEET* rootSheet = &m_SchFrameEditor->Schematic().Root();
270  SCH_SHEET_PATH rootPath;
271  rootPath.push_back( rootSheet );
272 
273  return formatPageString ( _( "Root" ), rootSheet->GetPageNumber( rootPath ) );
274 }
275 
276 
277 wxString HIERARCHY_NAVIG_DLG::formatPageString( wxString aName, wxString aPage )
278 {
279  return aName + wxT( " " ) + wxString::Format( _( "(page %s)" ), aPage );
280 }
281 
282 
283 void HIERARCHY_NAVIG_DLG::OnCloseNav( wxCloseEvent& event )
284 {
285  Destroy();
286 }
287 
288 
290 {
293  SCH_SCREEN* screen = GetCurrentSheet().LastScreen();
294 
295  wxASSERT( screen );
296 
297  SetScreen( screen );
298 
299  // update the References
302 
303  if( !screen->m_zoomInitialized )
304  {
305  initScreenZoom();
306  }
307  else
308  {
309  // Set zoom to last used in this screen
310  GetCanvas()->GetView()->SetScale( GetScreen()->m_LastZoomLevel );
311  RedrawScreen( (wxPoint) GetScreen()->m_ScrollCenter, false );
312  }
313 
314  UpdateTitle();
315 
318  editTool->UpdateNetHighlighting( dummy );
319 
320  HardRedraw(); // Ensure all items are redrawn (especially the drawing-sheet items)
321 }
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:245
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:54
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
This file is part of the common library.
void SetScreen(BASE_SCREEN *aScreen) override
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
double m_LastZoomLevel
last value for the zoom level, usefull in Eeschema when changing the current displayed sheet to reuse...
Definition: sch_screen.h:521
static TOOL_ACTION cancelInteractive
Definition: actions.h:65
Store an SCH_SHEET_PATH of each sheet in hierarchy.
Definition: hierarch.cpp:54
void GetSheets(std::vector< SCH_ITEM * > *aItems)
Similar to Items().OfType( SCH_SHEET_T ), but return the sheets in a deterministic order (L-R,...
Definition: sch_screen.cpp:964
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:141
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
Definition: sch_symbol.cpp:69
int OnCompareItems(const wxTreeItemId &item1, const wxTreeItemId &item2) override
Definition: hierarch.cpp:164
HIERARCHY_TREE * m_Tree
Definition: hierarch.h:71
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:83
static int ComparePageNum(const wxString &aPageNumberA, const wxString aPageNumberB)
Compares page numbers of schematic sheets.
Definition: sch_sheet.cpp:1139
wxString getRootString()
getRootString
Definition: hierarch.cpp:267
void DisplayCurrentSheet()
Draw the current sheet on the display.
Definition: hierarch.cpp:289
void UpdateAllScreenReferences()
Update all the symbol references for this sheet path.
SCH_EDIT_FRAME * m_SchFrameEditor
Definition: hierarch.h:70
wxIMPLEMENT_ABSTRACT_CLASS(HIERARCHY_TREE, wxTreeCtrl)
TreeItemData(SCH_SHEET_PATH &sheet)
Definition: hierarch.cpp:59
void pop_back()
Forwarded method from std::vector.
SCH_SHEET_PATH m_currSheet
Definition: hierarch.h:68
std::vector< SCH_FIELD > & GetFields()
Definition: sch_sheet.h:270
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
Handle actions specific to the schematic editor.
wxBitmap KiBitmap(BITMAP_DEF aBitmap)
Construct a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:82
void UpdateHierarchyTree()
Update the hierarchical tree of the schematic.
Definition: hierarch.cpp:212
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.
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
Generic, UI-independent tool event.
Definition: tool_event.h:173
void initScreenZoom()
Initialize the zoom value of the current screen and mark the screen as zoom-initialized.
void onChar(wxKeyEvent &event)
Definition: hierarch.cpp:155
SCHEMATIC & Schematic() const
HIERARCHY_NAVIG_DLG(SCH_EDIT_FRAME *aParent)
Definition: hierarch.cpp:88
#define HIERARCHY_NAVIG_DLG_WNAME
Definition: hierarch.h:36
const BITMAP_OPAQUE tree_sel_xpm[1]
Definition: tree_sel.cpp:27
static TOOL_ACTION clearSelection
Clears the current selection.
Definition: ee_actions.h:54
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.
void clear()
Forwarded method from std::vector.
HIERARCHY_TREE(HIERARCHY_NAVIG_DLG *parent)
Definition: hierarch.cpp:70
void buildHierarchyTree(SCH_SHEET_PATH *aList, wxTreeItemId *aPreviousmenu)
Create the hierarchical tree of the schematic.
Definition: hierarch.cpp:176
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:219
SCH_SHEET_PATH m_list
Definition: hierarch.h:69
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:116
TOOL_MANAGER * m_toolManager
Definition: tools_holder.h:157
SCH_SCREEN * LastScreen()
bool m_zoomInitialized
Definition: sch_screen.h:119
const BITMAP_OPAQUE tree_nosel_xpm[1]
Definition: tree_nosel.cpp:24
void SetSheetNumberAndCount()
Set the m_ScreenNumber and m_NumberOfScreens members for screens.
#define _(s)
Definition: 3d_actions.cpp:33
HIERARCHY_NAVIG_DLG * m_parent
Definition: hierarch.h:53
void OnCloseNav(wxCloseEvent &event)
Definition: hierarch.cpp:283
wxString formatPageString(wxString aName, wxString aPage)
formatPageString
Definition: hierarch.cpp:277
SCH_SHEET_PATH & GetCurrentSheet() const
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
double GetScale() const
Definition: view.h:263
SCH_SHEET_PATH m_SheetPath
Definition: hierarch.cpp:57
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:196
wxString GetPageNumber(const SCH_SHEET_PATH &aInstance) const
Return the sheet page number for aInstance.
Definition: sch_sheet.cpp:1106