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.

288 lines
9.1 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-2018 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_H
  22. #define LIB_TREE_MODEL_H
  23. #include <vector>
  24. #include <memory>
  25. #include <wx/string.h>
  26. #include <lib_tree_item.h>
  27. class EDA_COMBINED_MATCHER;
  28. /**
  29. * Model class in the component selector Model-View-Adapter (mediated MVC)
  30. * architecture. The other pieces are in:
  31. *
  32. * - Adapter: LIB_TREE_MODEL_ADAPTER in common/lib_tree_model_adapter.h
  33. * - View:
  34. * - DIALOG_CHOOSE_COMPONENT in eeschema/dialogs/dialog_choose_component.h
  35. * - wxDataViewCtrl
  36. *
  37. * This model is populated from LIB_ALIASes; helper methods in the adapter
  38. * can accept entire libraries.
  39. *
  40. * Quick summary of methods used to populate this class:
  41. * - `CMP_TREE_NODE_ROOT::AddLib()` - add a new, empty library to the root
  42. * - `CMP_TREE_NODE_LIB::AddAlias()` - add an alias and its units from a
  43. * given LIB_ALIAS*
  44. *
  45. * Quick summary of methods used to drive this class:
  46. *
  47. * - `UpdateScore()` - accumulate scores recursively given a new search token
  48. * - `ResetScore()` - reset scores recursively for a new search string
  49. * - `AssignIntrinsicRanks()` - calculate and cache the initial sort order
  50. * - `SortNodes()` - recursively sort the tree by score
  51. * - `Compare()` - compare two nodes; used by `SortNodes()`
  52. *
  53. * The data in the model is meant to be accessed directly. Quick summary of
  54. * data members:
  55. *
  56. * - `Parent` - parent node, or nullptr if root
  57. * - `Children` - vector of unique_ptrs to children
  58. * - `Type` - ROOT, LIB, ALIAS, or UNIT
  59. * - `IntrinsicRank` - cached initial sort order
  60. * - `Score` - score taking into account search terms. Zero means irrelevant and
  61. * should be hidden.
  62. * - `Name` - name of the library/alias/unit, to be displayed
  63. * - `Desc` - description of the alias, to be displayed
  64. * - `MatchName` - Name, normalized to lowercase for matching
  65. * - `SearchText` - normalized composite of keywords and description
  66. * - `LibId` - the #LIB_ID this alias or unit is from, or not valid
  67. * - `Unit` - the unit number, or zero for non-units
  68. */
  69. class LIB_TREE_NODE {
  70. public:
  71. enum TYPE {
  72. ROOT, LIB, LIBID, UNIT, INVALID
  73. };
  74. typedef std::vector<std::unique_ptr<LIB_TREE_NODE>> PTR_VECTOR;
  75. LIB_TREE_NODE* Parent; ///< Parent node or null
  76. PTR_VECTOR Children; ///< List of child nodes
  77. enum TYPE Type; ///< Node type
  78. /**
  79. * The rank of the item before any search terms are applied. This is
  80. * a fairly expensive sort (involving string compares) so it helps to
  81. * store the result of that sort.
  82. */
  83. int IntrinsicRank;
  84. /// The score of an item resulting from the search algorithm.
  85. int Score;
  86. wxString Name; ///< Actual name of the part
  87. wxString Desc; ///< Description to be displayed
  88. wxString MatchName; ///< Normalized name for matching
  89. wxString SearchText; ///< Descriptive text to search
  90. bool Normalized; ///< Support for lazy normalization.
  91. LIB_ID LibId; ///< LIB_ID determined by the parent library nickname and alias name.
  92. int Unit; ///< Actual unit, or zero
  93. bool IsRoot; ///< Indicates if the symbol is a root symbol instead of an alias.
  94. int VisLen; ///< Length of the string as shown on screen
  95. /**
  96. * Update the score for this part. This is accumulative - it will be
  97. * called once per search term.
  98. *
  99. * @param aMatcher an EDA_COMBINED_MATCHER initialized with the search term
  100. */
  101. virtual void UpdateScore( EDA_COMBINED_MATCHER& aMatcher ) = 0;
  102. /**
  103. * Initialize score to kLowestDefaultScore, recursively.
  104. */
  105. void ResetScore();
  106. /**
  107. * Store intrinsic ranks on all children of this node. See IntrinsicRank
  108. * member doc for more information.
  109. */
  110. void AssignIntrinsicRanks( bool presorted = false );
  111. /**
  112. * Sort child nodes quickly and recursively (IntrinsicRanks must have been set).
  113. */
  114. void SortNodes();
  115. /**
  116. * Compare two nodes. Returns negative if aNode1 < aNode2, zero if aNode1 ==
  117. * aNode2, or positive if aNode1 > aNode2.
  118. */
  119. static int Compare( LIB_TREE_NODE const& aNode1, LIB_TREE_NODE const& aNode2 );
  120. LIB_TREE_NODE();
  121. virtual ~LIB_TREE_NODE() {}
  122. };
  123. /**
  124. * Node type: unit of component.
  125. */
  126. class LIB_TREE_NODE_UNIT: public LIB_TREE_NODE
  127. {
  128. public:
  129. /**
  130. * The addresses of CMP_TREE_NODEs are used as unique IDs for the
  131. * wxDataViewModel, so don't let them be copied around.
  132. */
  133. LIB_TREE_NODE_UNIT( LIB_TREE_NODE_UNIT const& _ ) = delete;
  134. void operator=( LIB_TREE_NODE_UNIT const& _ ) = delete;
  135. /**
  136. * Construct a unit node.
  137. *
  138. * The name of the unit will be "Unit %s", where %s is aUnit formatted
  139. * by LIB_PART::SubReference.
  140. *
  141. * @param aParent parent node, should be a CMP_TREE_NODE_ALIAS
  142. * @param aItem parent item
  143. * @param aUnit unit number
  144. */
  145. LIB_TREE_NODE_UNIT( LIB_TREE_NODE* aParent, LIB_TREE_ITEM* aItem, int aUnit );
  146. /**
  147. * Do nothing, units just take the parent's score
  148. */
  149. virtual void UpdateScore( EDA_COMBINED_MATCHER& aMatcher ) override {}
  150. };
  151. /**
  152. * Node type: #LIB_ID.
  153. */
  154. class LIB_TREE_NODE_LIB_ID: public LIB_TREE_NODE
  155. {
  156. public:
  157. /**
  158. * The addresses of CMP_TREE_NODEs are used as unique IDs for the
  159. * wxDataViewModel, so don't let them be copied around.
  160. */
  161. LIB_TREE_NODE_LIB_ID( LIB_TREE_NODE_LIB_ID const& _ ) = delete;
  162. void operator=( LIB_TREE_NODE_LIB_ID const& _ ) = delete;
  163. /**
  164. * Construct a #LIB_ID node.
  165. *
  166. * All fields will be populated from the LIB_ALIAS, including children
  167. * (unit nodes will be generated automatically). This does not keep
  168. * the pointer to the #LIB_ALIAS object because at any time, a #LIB_ALIAS
  169. * can be remove from a libray which will result in an invalid pointer.
  170. * The alias must be resolved at the time of use. Anything else is a bug.
  171. *
  172. * @param aParent parent node, should be a CMP_TREE_NODE_LIB
  173. * @param aItem LIB_COMPONENT to populate the node.
  174. */
  175. LIB_TREE_NODE_LIB_ID( LIB_TREE_NODE* aParent, LIB_TREE_ITEM* aItem );
  176. /**
  177. * Update the node using data from a LIB_ALIAS object.
  178. */
  179. void Update( LIB_TREE_ITEM* aItem );
  180. /**
  181. * Perform the actual search.
  182. */
  183. virtual void UpdateScore( EDA_COMBINED_MATCHER& aMatcher ) override;
  184. protected:
  185. /**
  186. * Add a new unit to the component and return it.
  187. *
  188. * This should not be used directly, as the constructor adds all units.
  189. */
  190. LIB_TREE_NODE_UNIT& AddUnit( LIB_TREE_ITEM* aItem, int aUnit );
  191. };
  192. /**
  193. * Node type: library
  194. */
  195. class LIB_TREE_NODE_LIB: public LIB_TREE_NODE
  196. {
  197. public:
  198. /**
  199. * The addresses of CMP_TREE_NODEs are used as unique IDs for the
  200. * wxDataViewModel, so don't let them be copied around.
  201. */
  202. LIB_TREE_NODE_LIB( LIB_TREE_NODE_LIB const& _ ) = delete;
  203. void operator=( LIB_TREE_NODE_LIB const& _ ) = delete;
  204. /**
  205. * Construct an empty library node.
  206. *
  207. * @param aParent parent node, should be a CMP_TREE_NODE_ROOT
  208. * @param aName display name of the library
  209. * @param aDesc a description of the library
  210. */
  211. LIB_TREE_NODE_LIB( LIB_TREE_NODE* aParent, wxString const& aName, wxString const& aDesc );
  212. /**
  213. * Construct a new alias node, add it to this library, and return it.
  214. *
  215. * @param aItem LIB_COMPONENT to provide data
  216. */
  217. LIB_TREE_NODE_LIB_ID& AddItem( LIB_TREE_ITEM* aItem );
  218. virtual void UpdateScore( EDA_COMBINED_MATCHER& aMatcher ) override;
  219. };
  220. /**
  221. * Node type: root
  222. */
  223. class LIB_TREE_NODE_ROOT: public LIB_TREE_NODE
  224. {
  225. public:
  226. /**
  227. * The addresses of CMP_TREE_NODEs are used as unique IDs for the
  228. * wxDataViewModel, so don't let them be copied around.
  229. */
  230. LIB_TREE_NODE_ROOT( LIB_TREE_NODE_ROOT const& _ ) = delete;
  231. void operator=( LIB_TREE_NODE_ROOT const& _ ) = delete;
  232. /**
  233. * Construct the root node. Root nodes have no properties.
  234. */
  235. LIB_TREE_NODE_ROOT();
  236. /**
  237. * Construct an empty library node, add it to the root, and return it.
  238. */
  239. LIB_TREE_NODE_LIB& AddLib( wxString const& aName, wxString const& aDesc );
  240. virtual void UpdateScore( EDA_COMBINED_MATCHER& aMatcher ) override;
  241. };
  242. #endif // LIB_TREE_MODEL_H