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.

352 lines
9.6 KiB

18 years ago
  1. /************************************************************************/
  2. /* hierarch.cpp: Gestion de la hierarchie: navigation dans les feuilles */
  3. /************************************************************************/
  4. #include "fctsys.h"
  5. #include "gr_basic.h"
  6. #include "common.h"
  7. #include "program.h"
  8. #include "libcmp.h"
  9. #include "general.h"
  10. //#include "protos.h"
  11. #include "wx/image.h"
  12. #include "wx/imaglist.h"
  13. #include "wx/treectrl.h"
  14. #include "bitmaps.h"
  15. static bool UpdateScreenFromSheet( WinEDA_SchematicFrame* frame );
  16. enum {
  17. ID_TREECTRL_HIERARCHY = 1600
  18. };
  19. class WinEDA_HierFrame;
  20. /* This class derived from wxTreeItemData stores the DrawSheetPath of each sheet in hierarcy
  21. * in each TreeItem, in its associated data buffer
  22. */
  23. class TreeItemData : public wxTreeItemData
  24. {
  25. public:
  26. DrawSheetPath m_SheetPath;
  27. TreeItemData( DrawSheetPath sheet ) : wxTreeItemData()
  28. {
  29. m_SheetPath = sheet;
  30. }
  31. };
  32. /* Classe de l'arbre de hierarchie */
  33. class WinEDA_Tree : public wxTreeCtrl
  34. {
  35. private:
  36. WinEDA_HierFrame* m_Parent;
  37. wxImageList* imageList;
  38. public:
  39. WinEDA_Tree() { }
  40. WinEDA_Tree( WinEDA_HierFrame* parent );
  41. DECLARE_DYNAMIC_CLASS( WinEDA_Tree )
  42. };
  43. IMPLEMENT_DYNAMIC_CLASS( WinEDA_Tree, wxTreeCtrl )
  44. WinEDA_Tree::WinEDA_Tree( WinEDA_HierFrame* parent ) :
  45. wxTreeCtrl( (wxWindow*)parent, ID_TREECTRL_HIERARCHY,
  46. wxDefaultPosition, wxDefaultSize,
  47. wxTR_HAS_BUTTONS, wxDefaultValidator, wxT( "HierachyTreeCtrl" ) )
  48. {
  49. m_Parent = parent;
  50. // Make an image list containing small icons
  51. imageList = new wxImageList( 16, 15, TRUE, 2 );
  52. imageList->Add( wxBitmap( tree_nosel_xpm ) );
  53. imageList->Add( wxBitmap( tree_sel_xpm ) );
  54. AssignImageList( imageList );
  55. }
  56. /* Classe definissant la fenetre d'affichage de la hierarchie */
  57. class WinEDA_HierFrame : public wxDialog
  58. {
  59. public:
  60. WinEDA_SchematicFrame* m_Parent;
  61. WinEDA_Tree* m_Tree;
  62. int m_nbsheets;
  63. wxDC* m_DC;
  64. private:
  65. wxSize m_TreeSize; // Taille de l'arbre de hierarchie
  66. int maxposx;
  67. public:
  68. WinEDA_HierFrame( WinEDA_SchematicFrame* parent, wxDC* DC, const wxPoint& pos );
  69. void BuildSheetsTree( DrawSheetPath* list, wxTreeItemId* previousmenu );
  70. ~WinEDA_HierFrame();
  71. void OnSelect( wxTreeEvent& event );
  72. private:
  73. void OnQuit( wxCommandEvent& event );
  74. DECLARE_EVENT_TABLE()
  75. };
  76. BEGIN_EVENT_TABLE( WinEDA_HierFrame, wxDialog )
  77. EVT_TREE_ITEM_ACTIVATED( ID_TREECTRL_HIERARCHY,
  78. WinEDA_HierFrame::OnSelect )
  79. END_EVENT_TABLE()
  80. /*************************************************************************/
  81. void WinEDA_SchematicFrame::InstallHierarchyFrame( wxDC* DC, wxPoint& pos )
  82. /*************************************************************************/
  83. {
  84. WinEDA_HierFrame* treeframe = new WinEDA_HierFrame( this, DC, pos );
  85. treeframe->ShowModal(); treeframe->Destroy();
  86. }
  87. WinEDA_HierFrame::WinEDA_HierFrame( WinEDA_SchematicFrame* parent, wxDC* DC,
  88. const wxPoint& pos ) :
  89. wxDialog( parent, -1, _( "Navigator" ), pos, wxSize( 110, 50 ),
  90. DIALOG_STYLE )
  91. {
  92. wxTreeItemId cellule;
  93. m_Parent = parent;
  94. m_DC = DC;
  95. m_Tree = new WinEDA_Tree( this );
  96. m_nbsheets = 1;
  97. cellule = m_Tree->AddRoot( _( "Root" ), 0, 1 );
  98. m_Tree->SetItemBold( cellule, TRUE );
  99. DrawSheetPath list;
  100. list.Push( g_RootSheet );
  101. m_Tree->SetItemData( cellule, new TreeItemData( list ) );
  102. wxRect itemrect;
  103. #ifdef __UNIX__
  104. itemrect.SetWidth( 100 );
  105. itemrect.SetHeight( 20 );
  106. #else
  107. m_Tree->GetBoundingRect( cellule, itemrect );
  108. #endif
  109. m_TreeSize.x = itemrect.GetWidth() + 10;
  110. m_TreeSize.y = 20;
  111. if( m_Parent->GetSheet()->Last() == g_RootSheet )
  112. m_Tree->SelectItem( cellule ); //root.
  113. maxposx = 15;
  114. BuildSheetsTree( &list, &cellule );
  115. if( m_nbsheets > 1 )
  116. {
  117. m_Tree->Expand( cellule );
  118. // Reajustage de la taille de la frame a une valeur optimale
  119. m_TreeSize.y += m_nbsheets * itemrect.GetHeight();
  120. m_TreeSize.x = MIN( m_TreeSize.x, 250 );
  121. m_TreeSize.y = MIN( m_TreeSize.y, 350 );
  122. SetClientSize( m_TreeSize );
  123. }
  124. }
  125. WinEDA_HierFrame::~WinEDA_HierFrame()
  126. {
  127. }
  128. /************************************************************************/
  129. void WinEDA_HierFrame::OnQuit( wxCommandEvent& WXUNUSED (event) )
  130. /************************************************************************/
  131. {
  132. // true is to force the frame to close
  133. Close( true );
  134. }
  135. /********************************************************************/
  136. void WinEDA_HierFrame::BuildSheetsTree( DrawSheetPath* list,
  137. wxTreeItemId* previousmenu )
  138. /********************************************************************/
  139. /* Routine de creation de l'arbre de navigation dans la hierarchy
  140. * schematique
  141. * Cette routine est Reentrante !
  142. */
  143. {
  144. wxTreeItemId menu;
  145. if( m_nbsheets > NB_MAX_SHEET )
  146. {
  147. if( m_nbsheets == (NB_MAX_SHEET + 1) )
  148. {
  149. wxString msg;
  150. msg << wxT( "BuildSheetsTree: Error: nbsheets > " ) << NB_MAX_SHEET;
  151. DisplayError( this, msg );
  152. m_nbsheets++;
  153. }
  154. return;
  155. }
  156. maxposx += m_Tree->GetIndent();
  157. SCH_ITEM* schitem = list->LastDrawList();
  158. while( schitem && m_nbsheets < NB_MAX_SHEET )
  159. {
  160. if( schitem->Type() == DRAW_SHEET_STRUCT_TYPE )
  161. {
  162. DrawSheetStruct* sheet = (DrawSheetStruct*) schitem;
  163. m_nbsheets++;
  164. menu = m_Tree->AppendItem( *previousmenu, sheet->m_SheetName, 0, 1 );
  165. list->Push( sheet );
  166. m_Tree->SetItemData( menu, new TreeItemData( *list ) );
  167. int ll = m_Tree->GetItemText( menu ).Len();
  168. #ifdef __WINDOWS__
  169. ll *= 9; // * char width
  170. #else
  171. ll *= 12; // * char width
  172. #endif
  173. ll += maxposx + 20;
  174. m_TreeSize.x = MAX( m_TreeSize.x, ll );
  175. m_TreeSize.y += 1;
  176. if( *list == *( m_Parent->GetSheet() ) )
  177. {
  178. m_Tree->EnsureVisible( menu );
  179. m_Tree->SelectItem( menu );
  180. }
  181. BuildSheetsTree( list, &menu );
  182. m_Tree->Expand( menu );
  183. list->Pop();
  184. }
  185. schitem = schitem->Next();
  186. }
  187. maxposx -= m_Tree->GetIndent();
  188. }
  189. /***************************************************/
  190. void WinEDA_HierFrame::OnSelect( wxTreeEvent& event )
  191. /***************************************************/
  192. /* Called on a double-click on a tree item:
  193. * Open the selected sheet, and display the corresponding screen
  194. */
  195. {
  196. wxTreeItemId ItemSel = m_Tree->GetSelection();
  197. *(m_Parent->m_CurrentSheet) =
  198. ( (TreeItemData*) m_Tree->GetItemData( ItemSel ) )->m_SheetPath;
  199. UpdateScreenFromSheet( m_Parent );
  200. Close( TRUE );
  201. }
  202. /******************************************************/
  203. void WinEDA_SchematicFrame::InstallPreviousSheet()
  204. /******************************************************/
  205. /* Set the current screen to display the parent sheet of the current displayed sheet
  206. */
  207. {
  208. if( m_CurrentSheet->Last() == g_RootSheet )
  209. return;
  210. g_ItemToRepeat = NULL;
  211. MsgPanel->EraseMsgBox();
  212. //make a copy for testing purposes.
  213. DrawSheetPath listtemp = *m_CurrentSheet;
  214. listtemp.Pop();
  215. if( listtemp.LastScreen() == NULL )
  216. {
  217. DisplayError( this, wxT( "InstallPreviousScreen() Error: Sheet not found" ) );
  218. return;
  219. }
  220. m_CurrentSheet->Pop();
  221. UpdateScreenFromSheet( this );
  222. }
  223. /*********************************************************************/
  224. void WinEDA_SchematicFrame::InstallNextScreen( DrawSheetStruct* Sheet )
  225. /*********************************************************************/
  226. /* Routine d'installation de l'ecran correspondant au symbole Sheet pointe
  227. * par la souris
  228. * have to be careful here because the DrawSheetStructs within the EEDrawList
  229. * don't actually have a valid m_AssociatedScreen (on purpose -- you need the m_SubSheet hierarchy
  230. * to maintain path info (well, this is but one way to maintain path info..)
  231. */
  232. {
  233. if( Sheet == NULL )
  234. {
  235. DisplayError( this, wxT( "InstallNextScreen() error" ) ); return;
  236. }
  237. m_CurrentSheet->Push( Sheet );
  238. g_ItemToRepeat = NULL;
  239. MsgPanel->EraseMsgBox();
  240. UpdateScreenFromSheet( this );
  241. }
  242. /**************************************************************/
  243. static bool UpdateScreenFromSheet( WinEDA_SchematicFrame* frame )
  244. /**************************************************************/
  245. /* Recherche et installe de l'ecran relatif au sheet symbole Sheet.
  246. * Si Sheet == NULL installation de l'ecran de base ( Root ).
  247. */
  248. {
  249. SCH_SCREEN* NewScreen;
  250. NewScreen = frame->m_CurrentSheet->LastScreen();
  251. if( !NewScreen )
  252. {
  253. DisplayError( frame, wxT( "Screen not found for this sheet" ) );
  254. return false;
  255. }
  256. // Reinit des parametres d'affichage du nouvel ecran
  257. // assumes m_CurrentSheet has already been updated.
  258. frame->MsgPanel->EraseMsgBox();
  259. frame->DrawPanel->SetScrollbars( frame->DrawPanel->m_Scroll_unit,
  260. frame->DrawPanel->m_Scroll_unit,
  261. NewScreen->m_ScrollbarNumber.x,
  262. NewScreen->m_ScrollbarNumber.y,
  263. NewScreen->m_ScrollbarPos.x,
  264. NewScreen->m_ScrollbarPos.y, TRUE );
  265. //update the References
  266. frame->m_CurrentSheet->UpdateAllScreenReferences();
  267. frame->SetSheetNumberAndCount();
  268. frame->DrawPanel->m_CanStartBlock = -1;
  269. ActiveScreen = frame->m_CurrentSheet->LastScreen();
  270. if( NewScreen->m_FirstRedraw )
  271. {
  272. NewScreen->m_FirstRedraw = FALSE;
  273. frame->Zoom_Automatique( TRUE );
  274. }
  275. else
  276. {
  277. frame->DrawPanel->Refresh();
  278. frame->DrawPanel->MouseToCursorSchema();
  279. }
  280. return true;
  281. }