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.
		
		
		
		
		
			
		
			
				
					
					
						
							444 lines
						
					
					
						
							15 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							444 lines
						
					
					
						
							15 KiB
						
					
					
				| /* | |
|  * This program source code file is part of KiCad, a free EDA CAD application. | |
|  * | |
|  * Copyright (C) 2017 Chris Pavlina <pavlina.chris@gmail.com> | |
|  * Copyright (C) 2014 Henner Zeller <h.zeller@acm.org> | |
|  * Copyright (C) 2014-2021 KiCad Developers, see AUTHORS.txt for contributors. | |
|  * | |
|  * This program is free software: you can redistribute it and/or modify it | |
|  * under the terms of the GNU General Public License as published by the | |
|  * Free Software Foundation, either version 3 of the License, or (at your | |
|  * option) any later version. | |
|  * | |
|  * This program is distributed in the hope that it will be useful, but | |
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | |
|  * General Public License for more details. | |
|  * | |
|  * You should have received a copy of the GNU General Public License along | |
|  * with this program.  If not, see <http://www.gnu.org/licenses/>. | |
|  */ | |
| 
 | |
| #ifndef LIB_TREE_MODEL_ADAPTER_H | |
| #define LIB_TREE_MODEL_ADAPTER_H | |
|  | |
| #include <lib_id.h> | |
| #include <lib_tree_model.h> | |
| #include <wx/hashmap.h> | |
| #include <wx/dataview.h> | |
| #include <wx/headerctrl.h> | |
| #include <vector> | |
| #include <functional> | |
| #include <set> | |
| #include <map> | |
|  | |
| /** | |
|  * Adapter class in the symbol selector Model-View-Adapter (mediated MVC) | |
|  * architecture. The other pieces are in: | |
|  * | |
|  * - Model: SYM_TREE_NODE and descendants in eeschema/cmp_tree_model.h | |
|  * - View: | |
|  *   - DIALOG_CHOOSE_COMPONENT in eeschema/dialogs/dialog_choose_component.h | |
|  *   - wxDataViewCtrl | |
|  * | |
|  * This adapter presents the interface specified by wxDataViewModel to the | |
|  * wxDataViewCtrl: | |
|  * | |
|  *                       +---+                      +------------------+ | |
|  *     +---+  Generates  | A |                      |       VIEW       | | |
|  *     | M |  from libs  | D |   wxDataViewModel    |------------------| | |
|  *     | O | <---------- | A | <------------------> |  wxDataViewCtrl  | | |
|  *     | D |             | P |                      |------------------| | |
|  *     | E | <---------> | T | <------------------- |    wxTextCtrl    | | |
|  *     | L | UpdateScore | E | UpdateSearchString() |------------------| | |
|  *     +---+             | R |                      |                  | | |
|  *                       +---+                      +------------------+ | |
|  * | |
|  * Because this adapter is a wxDataViewModel, it is reference-counted by | |
|  * wxObject. To ensure this interface is used correctly, the constructor | |
|  * is private; LIB_TREE_MODEL_ADAPTER should be created by the static | |
|  * factory method LIB_TREE_MODEL_ADAPTER::Create(). | |
|  * | |
|  * Quick summary of methods used to drive this class: | |
|  * | |
|  * - `SetFilter()` - set whether the view is restricted to power parts | |
|  * - `ShowUnits()` - set whether units are displayed | |
|  * - `SetPreselectNode()` - set a node to highlight when not searching | |
|  * - `AddLibrary()` - populate the model with all aliases in a library | |
|  * - `AddAliasList()` - populate the model with a specific list of aliases | |
|  * | |
|  * Quick summary of methods used by the View: | |
|  * | |
|  * - `UpdateSearchString()` - pass in the user's search text | |
|  * - `AttachTo()` - pass in the wxDataViewCtrl | |
|  * - `GetAliasFor()` - get the LIB_ALIAS* for a selected item | |
|  * - `GetUnitFor()` - get the unit for a selected item | |
|  * - `GetComponentsCount()` - count the aliases loaded | |
|  * | |
|  * Methods implemented as part of wxDataViewModel: | |
|  * | |
|  * - `HasContainerColumns()` - whether a parent item has more than one column | |
|  * - `IsContainer()` - whether an item is a parent | |
|  * - `GetParent()` - return the parent of an item, or invalid if root | |
|  * - `GetChildren()` - get the children of an item | |
|  * - `GetColumnCount()` - get the number of columns in the view | |
|  * - `GetColumnType()` - get the data type shown in each column | |
|  * - `GetValue()` - get the data shown in a cell | |
|  * - `SetValue()` - edit the data in a cell (does nothing) | |
|  * - `GetAttr()` - get any per-item formatting | |
|  * - `Compare()` - compare two rows, for sorting | |
|  * - `HasDefaultCompare()` - whether sorted by default | |
|  */ | |
| 
 | |
| class APP_SETTINGS_BASE; | |
| class TOOL_INTERACTIVE; | |
| class EDA_BASE_FRAME; | |
| 
 | |
| 
 | |
| class LIB_TREE_MODEL_ADAPTER: public wxDataViewModel | |
| { | |
| public: | |
|     /** | |
|      * @return a unicode string to mark a node name like a pinned library name. | |
|      * This is not an ASCII7 char, but a unicode char. | |
|      */ | |
|     static const wxString GetPinningSymbol() | |
|     { | |
|         return wxString::FromUTF8( "☆ " ); | |
|     } | |
| 
 | |
| public: | |
|     /** | |
|      * Destructor. Do NOT delete this class manually; it is reference-counted | |
|      * by wxObject. | |
|      */ | |
|     ~LIB_TREE_MODEL_ADAPTER(); | |
| 
 | |
|     /** | |
|      * This enum allows a selective filtering of symbols to list | |
|      */ | |
|     enum SYM_FILTER_TYPE | |
|     { | |
|         SYM_FILTER_NONE,        ///< no filtering | |
|         SYM_FILTER_POWER,       ///< list symbols flagged PWR | |
|     }; | |
| 
 | |
|     /** | |
|      * This enum defines the order of the default columns in the tree view | |
|      */ | |
|     enum TREE_COLS | |
|     { | |
|         NAME_COL = 0,   ///< Library or library item name column | |
|         DESC_COL,       ///< Library or library description column | |
|         NUM_COLS        ///< The number of default tree columns | |
|     }; | |
| 
 | |
| 
 | |
|     /** | |
|      * Save the column widths to the config file. This requires the tree view to still be | |
|      * valid. | |
|      */ | |
|     void SaveSettings(); | |
| 
 | |
|     /** | |
|      * Set the symbol filter type. Must be set before adding libraries | |
|      * | |
|      * @param aFilter   if SYM_FILTER_POWER, only power parts are loaded | |
|      */ | |
|     void SetFilter( SYM_FILTER_TYPE aFilter ); | |
| 
 | |
|     /** | |
|      * Return the active filter. | |
|      */ | |
|     SYM_FILTER_TYPE GetFilter() const { return m_filter; } | |
| 
 | |
|     /** | |
|      * Whether or not to show units. May be set at any time; updates at the next | |
|      * UpdateSearchString() | |
|      * | |
|      * @param aShow if true, units are displayed | |
|      */ | |
|     void ShowUnits( bool aShow ); | |
| 
 | |
|     /** | |
|      * Set the symbol name to be selected if there are no search results. | |
|      * May be set at any time; updates at the next UpdateSearchString(). | |
|      * | |
|      * @param aLibId    symbol #LIB_ID to be selected | |
|      * @param aUnit     unit to be selected, if > 0 (0 selects the alias itself) | |
|      */ | |
|     void SetPreselectNode( const LIB_ID& aLibId, int aUnit ); | |
| 
 | |
|     /** | |
|      * Add the given list of symbols by alias. To be called in the setup | |
|      * phase. | |
|      * | |
|      * @param aNodeName    the parent node the symbols will appear under | |
|      * @param aDesc        the description field of the parent node | |
|      * @param aItemList    list of symbols | |
|      */ | |
|     void DoAddLibrary( const wxString& aNodeName, const wxString& aDesc, | |
|                        const std::vector<LIB_TREE_ITEM*>& aItemList, | |
|                        bool pinned, bool presorted ); | |
| 
 | |
|     std::vector<wxString> GetAvailableColumns() const { return m_availableColumns; } | |
| 
 | |
|     std::vector<wxString> GetShownColumns() const { return m_shownColumns; } | |
| 
 | |
|     /** | |
|      * Sets which columns are shown in the widget.  Invalid column names are discarded. | |
|      * @param aColumnNames is an ordered list of column names to show | |
|      */ | |
|     void SetShownColumns( const std::vector<wxString>& aColumnNames ); | |
| 
 | |
|     /** | |
|      * Sort the tree and assign ranks after adding libraries. | |
|      */ | |
|     void AssignIntrinsicRanks() { m_tree.AssignIntrinsicRanks(); } | |
| 
 | |
|     /** | |
|      * Set the search string provided by the user. | |
|      * | |
|      * @param aSearch   full, unprocessed search text | |
|      * @param aState    if true, we are keeping the state and so we shouldn't collapse the tree | |
|      */ | |
|     void UpdateSearchString( const wxString& aSearch, bool aState ); | |
| 
 | |
|     /** | |
|      * Attach to a wxDataViewCtrl and initialize it. This will set up columns | |
|      * and associate the model via the adapter. | |
|      * | |
|      * @param aDataViewCtrl the view symbol in the dialog | |
|      */ | |
|     void AttachTo( wxDataViewCtrl* aDataViewCtrl ); | |
| 
 | |
|     /** | |
|      * A final-stage initialization to be called after the window hierarchy has been realized | |
|      * and the window sizes set. | |
|      */ | |
|     void FinishTreeInitialization(); | |
| 
 | |
|     void OnSize( wxSizeEvent& aEvent ); | |
|     /** | |
|      * Return the alias for the given item. | |
|      * | |
|      * @param aSelection    item from the wxDataViewCtrl | |
|      *                      (see wxDataViewCtrl::GetSelection()) | |
|      * | |
|      * @return alias, or nullptr if none is selected | |
|      */ | |
|     LIB_ID GetAliasFor( const wxDataViewItem& aSelection ) const; | |
| 
 | |
|     /** | |
|      * Return the unit for the given item. | |
|      * | |
|      * @param aSelection    item from the wxDataViewCtrl | |
|      *                      (see wxDataViewCtrl::GetSelection()) | |
|      * | |
|      * @return Unit, or zero if the alias itself is selected. Return valid is | |
|      *         invalid if GetAliasFor() returns nullptr. | |
|      */ | |
|     int GetUnitFor( const wxDataViewItem& aSelection ) const; | |
| 
 | |
|     /** | |
|      * Return node type for the given item. | |
|      * | |
|      * @param aSelection    item from the wxDataViewCtrl | |
|      *                      (see wxDataViewCtrl::GetSelection()) | |
|      * | |
|      * @return Type of the selected node, might be INVALID. | |
|      */ | |
|     LIB_TREE_NODE::TYPE GetTypeFor( const wxDataViewItem& aSelection ) const; | |
| 
 | |
|     LIB_TREE_NODE* GetTreeNodeFor( const wxDataViewItem& aSelection ) const; | |
| 
 | |
|     virtual wxString GenerateInfo( const LIB_ID& aLibId, int aUnit ) { return wxEmptyString; }; | |
| 
 | |
|     /** | |
|      * Return the number of symbols loaded in the tree. | |
|      */ | |
|     int GetItemCount() const; | |
| 
 | |
|     /** | |
|      * Return the number of libraries loaded in the tree. | |
|      */ | |
|     virtual int GetLibrariesCount() const | |
|     { | |
|         return m_tree.m_Children.size(); | |
|     } | |
| 
 | |
|     /** | |
|      * Returns tree item corresponding to part. | |
|      * | |
|      * @param aLibId specifies the part and library name to be searched for. | |
|      * @return Tree data item representing the part. Might be invalid if nothings was found. | |
|      */ | |
|     wxDataViewItem FindItem( const LIB_ID& aLibId ); | |
| 
 | |
|     /** | |
|      * Populate a list of all the children of an item | |
|      * | |
|      * @return number of children | |
|      */ | |
|     unsigned int GetChildren( const wxDataViewItem& aItem, | |
|                               wxDataViewItemArray& aChildren ) const override; | |
| 
 | |
|     // Freezing/Thawing.  Used when updating the table model so that we don't try and fetch | |
|     // values during updating.  Primarily a problem on OSX which doesn't pay attention to the | |
|     // wxDataViewCtrl's freeze count when updating the keyWindow. | |
|     void Freeze() { m_freeze++; } | |
|     void Thaw() { m_freeze--; } | |
|     bool IsFrozen() const { return m_freeze; } | |
| 
 | |
|     void RefreshTree(); | |
| 
 | |
|     // Allows subclasses to nominate a context menu handler. | |
|     virtual TOOL_INTERACTIVE* GetContextMenuTool() { return nullptr; } | |
| 
 | |
|     void PinLibrary( LIB_TREE_NODE* aTreeNode ); | |
|     void UnpinLibrary( LIB_TREE_NODE* aTreeNode ); | |
| 
 | |
|     void ShowChangedLanguage() | |
|     { | |
|         recreateColumns(); | |
|     } | |
| 
 | |
| protected: | |
|     /** | |
|      * Convert #SYM_TREE_NODE -> wxDataViewItem. | |
|      */ | |
|     static wxDataViewItem ToItem( const LIB_TREE_NODE* aNode ); | |
| 
 | |
|     /** | |
|      * Convert wxDataViewItem -> #SYM_TREE_NODE. | |
|      */ | |
|     static LIB_TREE_NODE* ToNode( wxDataViewItem aItem ); | |
| 
 | |
|     /** | |
|      * Convert SYM_TREE_NODE's children to wxDataViewItemArray. | |
|      */ | |
|     static unsigned int IntoArray( const LIB_TREE_NODE& aNode, wxDataViewItemArray& aChildren ); | |
| 
 | |
|     /** | |
|      * Create the adapter. | |
|      * | |
|      * @param aParent is the parent frame | |
|      * @param aPinnedKey is the key to load the pinned libraries list from the project file | |
|      */ | |
|     LIB_TREE_MODEL_ADAPTER( EDA_BASE_FRAME* aParent, const wxString& aPinnedKey ); | |
| 
 | |
|     LIB_TREE_NODE_LIB& DoAddLibraryNode( const wxString& aNodeName, const wxString& aDesc, | |
|                                          bool pinned ); | |
| 
 | |
|     /** | |
|      * Check whether a container has columns too | |
|      */ | |
|     bool HasContainerColumns( const wxDataViewItem& aItem ) const override; | |
| 
 | |
|     /** | |
|      * Check whether an item can have children. | |
|      */ | |
|     bool IsContainer( const wxDataViewItem& aItem ) const override; | |
| 
 | |
|     /** | |
|      * Get the parent of an item. | |
|      * | |
|      * @return parent of aItem, or an invalid wxDataViewItem if parent is root | |
|      */ | |
|     wxDataViewItem GetParent( const wxDataViewItem& aItem ) const override; | |
| 
 | |
|     unsigned int GetColumnCount() const override { return m_columns.size(); } | |
| 
 | |
|     /** | |
|      * Return the type of data stored in the column as indicated by wxVariant::GetType() | |
|      */ | |
|     wxString GetColumnType( unsigned int aCol ) const override { return "string"; } | |
| 
 | |
|     /** | |
|      * Get the value of an item. | |
|      * | |
|      * @param aVariant  wxVariant to receive the data | |
|      * @param aItem     item whose data will be placed into aVariant | |
|      * @param aCol      column number of the data | |
|      */ | |
|     void GetValue( wxVariant&              aVariant, | |
|                    const wxDataViewItem&   aItem, | |
|                    unsigned int            aCol ) const override; | |
| 
 | |
|     /** | |
|      * Set the value of an item. Does nothing - this model doesn't support | |
|      * editing. | |
|      */ | |
|     bool SetValue( const wxVariant&        aVariant, | |
|                    const wxDataViewItem&   aItem, | |
|                    unsigned int            aCol ) override { return false; } | |
| 
 | |
|     /** | |
|      * Get any formatting for an item. | |
|      * | |
|      * @param aItem     item to get formatting for | |
|      * @param aCol      column number of interest | |
|      * @param aAttr     receiver for attributes | |
|      * @return          true if the item has non-default attributes | |
|      */ | |
|     bool GetAttr( const wxDataViewItem&   aItem, | |
|                   unsigned int            aCol, | |
|                   wxDataViewItemAttr&     aAttr ) const override; | |
| 
 | |
|     virtual bool isSymbolModel() = 0; | |
| 
 | |
|     void resortTree(); | |
| 
 | |
| private: | |
|     /** | |
|      * Find any results worth highlighting and expand them, according to given criteria | |
|      * The highest-scoring node is written to aHighScore | |
|      */ | |
|     void Find( LIB_TREE_NODE& aNode, std::function<bool( const LIB_TREE_NODE* )> aFunc, | |
|                LIB_TREE_NODE** aHighScore ); | |
| 
 | |
|     /** | |
|      * Find and expand successful search results.  Return the best match (if any). | |
|      */ | |
|     LIB_TREE_NODE* ShowResults(); | |
| 
 | |
|     /** | |
|      * Find and expand preselected node.  Return the best match (if any). | |
|      */ | |
|     LIB_TREE_NODE* ShowPreselect(); | |
| 
 | |
|     /** | |
|      * Find and expand a library if there is only one.  Return the best match (if any). | |
|      */ | |
|     LIB_TREE_NODE* ShowSingleLibrary(); | |
| 
 | |
|     wxDataViewColumn* doAddColumn( const wxString& aHeader, bool aTranslate = true ); | |
| 
 | |
| protected: | |
|     void addColumnIfNecessary( const wxString& aHeader ); | |
| 
 | |
|     void recreateColumns(); | |
| 
 | |
|     LIB_TREE_NODE_ROOT           m_tree; | |
|     std::map<unsigned, wxString> m_colIdxMap; | |
|     std::vector<wxString>        m_availableColumns; | |
| 
 | |
| private: | |
|     EDA_BASE_FRAME*         m_parent; | |
| 
 | |
|     SYM_FILTER_TYPE         m_filter; | |
|     bool                    m_show_units; | |
|     LIB_ID                  m_preselect_lib_id; | |
|     int                     m_preselect_unit; | |
|     int                     m_freeze; | |
| 
 | |
|     wxDataViewCtrl*         m_widget; | |
| 
 | |
|     std::vector<wxDataViewColumn*>        m_columns; | |
|     std::map<wxString, wxDataViewColumn*> m_colNameMap; | |
|     std::map<wxString, int>               m_colWidths; | |
|     std::vector<wxString>                 m_shownColumns;   // Stored in display order | |
| }; | |
| 
 | |
| #endif // LIB_TREE_MODEL_ADAPTER_H | |
| 
 |