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.

400 lines
13 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2017 Chris Pavlina <pavlina.chris@gmail.com>
  5. * Copyright (C) 2014 Henner Zeller <h.zeller@acm.org>
  6. * Copyright (C) 2014-2019 KiCad Developers, see AUTHORS.txt for contributors.
  7. *
  8. * This program is free software: you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License as published by the
  10. * Free Software Foundation, either version 3 of the License, or (at your
  11. * option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along
  19. * with this program. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. #ifndef LIB_TREE_MODEL_ADAPTER_H
  22. #define LIB_TREE_MODEL_ADAPTER_H
  23. #include <lib_id.h>
  24. #include <lib_tree_model.h>
  25. #include <wx/hashmap.h>
  26. #include <wx/dataview.h>
  27. #include <wx/headerctrl.h>
  28. #include <vector>
  29. #include <functional>
  30. #include <set>
  31. /**
  32. * Adapter class in the component selector Model-View-Adapter (mediated MVC)
  33. * architecture. The other pieces are in:
  34. *
  35. * - Model: CMP_TREE_NODE and descendants in eeschema/cmp_tree_model.h
  36. * - View:
  37. * - DIALOG_CHOOSE_COMPONENT in eeschema/dialogs/dialog_choose_component.h
  38. * - wxDataViewCtrl
  39. *
  40. * This adapter presents the interface specified by wxDataViewModel to the
  41. * wxDataViewCtrl:
  42. *
  43. * +---+ +------------------+
  44. * +---+ Generates | A | | VIEW |
  45. * | M | from libs | D | wxDataViewModel |------------------|
  46. * | O | <---------- | A | <------------------> | wxDataViewCtrl |
  47. * | D | | P | |------------------|
  48. * | E | <---------> | T | <------------------- | wxTextCtrl |
  49. * | L | UpdateScore | E | UpdateSearchString() |------------------|
  50. * +---+ | R | | |
  51. * +---+ +------------------+
  52. *
  53. * Because this adapter is a wxDataViewModel, it is reference-counted by
  54. * wxObject. To ensure this interface is used correctly, the constructor
  55. * is private; LIB_TREE_MODEL_ADAPTER should be created by the static
  56. * factory method LIB_TREE_MODEL_ADAPTER::Create().
  57. *
  58. * Quick summary of methods used to drive this class:
  59. *
  60. * - `SetFilter()` - set whether the view is restricted to power parts
  61. * - `ShowUnits()` - set whether units are displayed
  62. * - `SetPreselectNode()` - set a node to highlight when not searching
  63. * - `AddLibrary()` - populate the model with all aliases in a library
  64. * - `AddAliasList()` - populate the model with a specific list of aliases
  65. *
  66. * Quick summary of methods used by the View:
  67. *
  68. * - `UpdateSearchString()` - pass in the user's search text
  69. * - `AttachTo()` - pass in the wxDataViewCtrl
  70. * - `GetAliasFor()` - get the LIB_ALIAS* for a selected item
  71. * - `GetUnitFor()` - get the unit for a selected item
  72. * - `GetComponentsCount()` - count the aliases loaded
  73. *
  74. * Methods implemented as part of wxDataViewModel:
  75. *
  76. * - `HasContainerColumns()` - whether a parent item has more than one column
  77. * - `IsContainer()` - whether an item is a parent
  78. * - `GetParent()` - return the parent of an item, or invalid if root
  79. * - `GetChildren()` - get the children of an item
  80. * - `GetColumnCount()` - get the number of columns in the view
  81. * - `GetColumnType()` - get the data type shown in each column
  82. * - `GetValue()` - get the data shown in a cell
  83. * - `SetValue()` - edit the data in a cell (does nothing)
  84. * - `GetAttr()` - get any per-item formatting
  85. * - `Compare()` - compare two rows, for sorting
  86. * - `HasDefaultCompare()` - whether sorted by default
  87. */
  88. class APP_SETTINGS_BASE;
  89. class TOOL_INTERACTIVE;
  90. class PARAM_CFG;
  91. class EDA_BASE_FRAME;
  92. class LIB_TREE_MODEL_ADAPTER: public wxDataViewModel
  93. {
  94. public:
  95. /**
  96. * Reference-counting container for a pointer to CMP_TREE_MODEL_ADAPTER_BASE.
  97. */
  98. typedef wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER> PTR;
  99. /**
  100. * Destructor. Do NOT delete this class manually; it is reference-counted
  101. * by wxObject.
  102. */
  103. ~LIB_TREE_MODEL_ADAPTER();
  104. /**
  105. * This enum allows a selective filtering of components to list
  106. */
  107. enum CMP_FILTER_TYPE
  108. {
  109. CMP_FILTER_NONE, ///< no filtering
  110. CMP_FILTER_POWER, ///< list components flagged PWR
  111. };
  112. /**
  113. * This enum defines the order of the columns in the tree view
  114. */
  115. enum TREE_COLS
  116. {
  117. PART_COL = 0, ///< Part name column
  118. DESC_COL, ///< Part description column
  119. NUM_COLS ///< The number of tree columns
  120. };
  121. /**
  122. * Save the column widths to the config file. This requires the tree view to still be
  123. * valid.
  124. */
  125. void SaveColWidths();
  126. void SavePinnedItems();
  127. /**
  128. * Set the component filter type. Must be set before adding libraries
  129. *
  130. * @param aFilter if CMP_FILTER_POWER, only power parts are loaded
  131. */
  132. void SetFilter( CMP_FILTER_TYPE aFilter );
  133. /**
  134. * Return the active filter.
  135. */
  136. CMP_FILTER_TYPE GetFilter() const { return m_filter; }
  137. /**
  138. * Whether or not to show units. May be set at any time; updates at the next
  139. * UpdateSearchString()
  140. *
  141. * @param aShow if true, units are displayed
  142. */
  143. void ShowUnits( bool aShow );
  144. /**
  145. * Set the component name to be selected if there are no search results.
  146. * May be set at any time; updates at the next UpdateSearchString().
  147. *
  148. * @param aLibId symbol #LIB_ID to be selected
  149. * @param aUnit unit to be selected, if > 0 (0 selects the alias itself)
  150. */
  151. void SetPreselectNode( LIB_ID const& aLibId, int aUnit );
  152. /**
  153. * Add the given list of components by alias. To be called in the setup
  154. * phase.
  155. *
  156. * @param aNodeName the parent node the components will appear under
  157. * @param aDesc the description field of the parent node
  158. * @param aItemList list of components
  159. */
  160. void DoAddLibrary( wxString const& aNodeName, wxString const& aDesc,
  161. std::vector<LIB_TREE_ITEM*> const& aItemList, bool presorted );
  162. /**
  163. * Sort the tree and assign ranks after adding libraries.
  164. */
  165. void AssignIntrinsicRanks() { m_tree.AssignIntrinsicRanks(); }
  166. /**
  167. * Set the search string provided by the user.
  168. *
  169. * @param aSearch full, unprocessed search text
  170. */
  171. void UpdateSearchString( wxString const& aSearch );
  172. /**
  173. * Attach to a wxDataViewCtrl and initialize it. This will set up columns
  174. * and associate the model via the adapter.
  175. *
  176. * @param aDataViewCtrl the view component in the dialog
  177. */
  178. void AttachTo( wxDataViewCtrl* aDataViewCtrl );
  179. /**
  180. * Return the alias for the given item.
  181. *
  182. * @param aSelection item from the wxDataViewCtrl
  183. * (see wxDataViewCtrl::GetSelection())
  184. *
  185. * @return alias, or nullptr if none is selected
  186. */
  187. LIB_ID GetAliasFor( const wxDataViewItem& aSelection ) const;
  188. /**
  189. * Return the unit for the given item.
  190. *
  191. * @param aSelection item from the wxDataViewCtrl
  192. * (see wxDataViewCtrl::GetSelection())
  193. *
  194. * @return Unit, or zero if the alias itself is selected. Return valid is
  195. * invalid if GetAliasFor() returns nullptr.
  196. */
  197. int GetUnitFor( const wxDataViewItem& aSelection ) const;
  198. /**
  199. * Return node type for the given item.
  200. *
  201. * @param aSelection item from the wxDataViewCtrl
  202. * (see wxDataViewCtrl::GetSelection())
  203. *
  204. * @return Type of the selected node, might be INVALID.
  205. */
  206. LIB_TREE_NODE::TYPE GetTypeFor( const wxDataViewItem& aSelection ) const;
  207. LIB_TREE_NODE* GetTreeNodeFor( const wxDataViewItem& aSelection ) const;
  208. virtual wxString GenerateInfo( LIB_ID const& aLibId, int aUnit ) { return wxEmptyString; };
  209. /**
  210. * Return the number of components loaded in the tree.
  211. */
  212. int GetItemCount() const;
  213. /**
  214. * Return the number of libraries loaded in the tree.
  215. */
  216. virtual int GetLibrariesCount() const
  217. {
  218. return m_tree.m_Children.size();
  219. }
  220. /**
  221. * Returns tree item corresponding to part.
  222. *
  223. * @param aLibId specifies the part and library name to be searched for.
  224. * @return Tree data item representing the part. Might be invalid if nothings was found.
  225. */
  226. wxDataViewItem FindItem( const LIB_ID& aLibId );
  227. /**
  228. * Populate a list of all the children of an item
  229. *
  230. * @return number of children
  231. */
  232. unsigned int GetChildren( wxDataViewItem const& aItem,
  233. wxDataViewItemArray& aChildren ) const override;
  234. // Freezing/Thawing. Used when updating the table model so that we don't try and fetch
  235. // values during updating. Primarily a problem on OSX which doesn't pay attention to the
  236. // wxDataViewCtrl's freeze count when updating the keyWindow.
  237. void Freeze() { m_freeze++; }
  238. void Thaw() { m_freeze--; }
  239. bool IsFrozen() const { return m_freeze; }
  240. void RefreshTree();
  241. // Allows subclasses to nominate a context menu handler.
  242. virtual TOOL_INTERACTIVE* GetContextMenuTool() { return nullptr; }
  243. protected:
  244. static wxDataViewItem ToItem( LIB_TREE_NODE const* aNode );
  245. static LIB_TREE_NODE* ToNode( wxDataViewItem aItem );
  246. static unsigned int IntoArray( LIB_TREE_NODE const& aNode, wxDataViewItemArray& aChildren );
  247. LIB_TREE_NODE_ROOT m_tree;
  248. /**
  249. * Creates the adapter
  250. * @param aParent is the parent frame
  251. * @param aPinnedKey is the key to load the pinned libraries list from the project file
  252. */
  253. LIB_TREE_MODEL_ADAPTER( EDA_BASE_FRAME* aParent, wxString aPinnedKey );
  254. LIB_TREE_NODE_LIB& DoAddLibraryNode( wxString const& aNodeName, wxString const& aDesc );
  255. /**
  256. * Check whether a container has columns too
  257. */
  258. bool HasContainerColumns( wxDataViewItem const& aItem ) const override;
  259. /**
  260. * Check whether an item can have children.
  261. */
  262. bool IsContainer( wxDataViewItem const& aItem ) const override;
  263. /**
  264. * Get the parent of an item.
  265. *
  266. * @return parent of aItem, or an invalid wxDataViewItem if parent is root
  267. */
  268. wxDataViewItem GetParent( wxDataViewItem const& aItem ) const override;
  269. unsigned int GetColumnCount() const override { return NUM_COLS; }
  270. /**
  271. * Return the type of data stored in the column as indicated by wxVariant::GetType()
  272. */
  273. wxString GetColumnType( unsigned int aCol ) const override { return "string"; }
  274. /**
  275. * Get the value of an item.
  276. *
  277. * @param aVariant wxVariant to receive the data
  278. * @param aItem item whose data will be placed into aVariant
  279. * @param aCol column number of the data
  280. */
  281. void GetValue( wxVariant& aVariant,
  282. wxDataViewItem const& aItem,
  283. unsigned int aCol ) const override;
  284. /**
  285. * Set the value of an item. Does nothing - this model doesn't support
  286. * editing.
  287. */
  288. bool SetValue( wxVariant const& aVariant,
  289. wxDataViewItem const& aItem,
  290. unsigned int aCol ) override { return false; }
  291. /**
  292. * Get any formatting for an item.
  293. *
  294. * @param aItem item to get formatting for
  295. * @param aCol column number of interest
  296. * @param aAttr receiver for attributes
  297. * @return true iff the item has non-default attributes
  298. */
  299. bool GetAttr( wxDataViewItem const& aItem,
  300. unsigned int aCol,
  301. wxDataViewItemAttr& aAttr ) const override;
  302. /**
  303. * @return a unicode string to mark a node name like
  304. * a pinned library name
  305. * This is not an ascii7 char, but a unicode char
  306. */
  307. const wxString GetPinningSymbol() const
  308. {
  309. return wxString::FromUTF8( "" );
  310. }
  311. private:
  312. EDA_BASE_FRAME* m_parent;
  313. CMP_FILTER_TYPE m_filter;
  314. bool m_show_units;
  315. LIB_ID m_preselect_lib_id;
  316. int m_preselect_unit;
  317. int m_freeze;
  318. wxDataViewColumn* m_col_part;
  319. wxDataViewColumn* m_col_desc;
  320. wxDataViewCtrl* m_widget;
  321. std::vector<PARAM_CFG*> m_projectFileParams;
  322. int m_colWidths[NUM_COLS];
  323. wxArrayString m_pinnedLibs;
  324. wxString m_pinnedKey;
  325. /**
  326. * Find any results worth highlighting and expand them, according to given criteria
  327. * The highest-scoring node is written to aHighScore
  328. */
  329. void FindAndExpand( LIB_TREE_NODE& aNode, std::function<bool( LIB_TREE_NODE const* )> aFunc,
  330. LIB_TREE_NODE** aHighScore );
  331. /**
  332. * Find and expand successful search results. Return the best match (if any).
  333. */
  334. LIB_TREE_NODE* ShowResults();
  335. /**
  336. * Find and expand preselected node. Return the best match (if any).
  337. */
  338. LIB_TREE_NODE* ShowPreselect();
  339. /**
  340. * Find and expand a library if there is only one. Return the best match (if any).
  341. */
  342. LIB_TREE_NODE* ShowSingleLibrary();
  343. };
  344. #endif // LIB_TREE_MODEL_ADAPTER_H