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.

286 lines
6.9 KiB

8 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2013-2017 CERN
  5. * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
  6. * @author Maciej Suminski <maciej.suminski@cern.ch>
  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. #ifndef SELECTION_H
  26. #define SELECTION_H
  27. #include <core/optional.h>
  28. #include <deque>
  29. #include <eda_rect.h>
  30. #include <base_struct.h>
  31. #include <view/view_group.h>
  32. class SELECTION : public KIGFX::VIEW_GROUP
  33. {
  34. public:
  35. SELECTION() : KIGFX::VIEW_GROUP::VIEW_GROUP()
  36. {
  37. m_isHover = false;
  38. }
  39. SELECTION( const SELECTION& aOther ) : KIGFX::VIEW_GROUP::VIEW_GROUP()
  40. {
  41. m_items = aOther.m_items;
  42. m_isHover = aOther.m_isHover;
  43. }
  44. SELECTION& operator= ( const SELECTION& aOther )
  45. {
  46. m_items = aOther.m_items;
  47. m_isHover = aOther.m_isHover;
  48. return *this;
  49. }
  50. using ITER = std::deque<EDA_ITEM*>::iterator;
  51. using CITER = std::deque<EDA_ITEM*>::const_iterator;
  52. ITER begin() { return m_items.begin(); }
  53. ITER end() { return m_items.end(); }
  54. CITER begin() const { return m_items.cbegin(); }
  55. CITER end() const { return m_items.cend(); }
  56. void SetIsHover( bool aIsHover )
  57. {
  58. m_isHover = aIsHover;
  59. }
  60. bool IsHover() const
  61. {
  62. return m_isHover;
  63. }
  64. virtual void Add( EDA_ITEM* aItem )
  65. {
  66. // We're not sorting here; this is just a time-optimized way to do an
  67. // inclusion check. std::lower_bound will return the first i >= aItem
  68. // and the second i > aItem check rules out i == aItem.
  69. ITER i = std::lower_bound( m_items.begin(), m_items.end(), aItem );
  70. if( i == m_items.end() || *i > aItem )
  71. m_items.insert( i, aItem );
  72. }
  73. virtual void Remove( EDA_ITEM *aItem )
  74. {
  75. ITER i = std::lower_bound( m_items.begin(), m_items.end(), aItem );
  76. if( !( i == m_items.end() || *i > aItem ) )
  77. m_items.erase( i );
  78. }
  79. virtual void Clear() override
  80. {
  81. m_items.clear();
  82. }
  83. virtual unsigned int GetSize() const override
  84. {
  85. return m_items.size();
  86. }
  87. virtual KIGFX::VIEW_ITEM* GetItem( unsigned int aIdx ) const override
  88. {
  89. if( aIdx < m_items.size() )
  90. return m_items[ aIdx ];
  91. return nullptr;
  92. }
  93. bool Contains( EDA_ITEM* aItem ) const
  94. {
  95. CITER i = std::lower_bound( m_items.begin(), m_items.end(), aItem );
  96. return !( i == m_items.end() || *i > aItem );
  97. }
  98. /// Checks if there is anything selected
  99. bool Empty() const
  100. {
  101. return m_items.empty();
  102. }
  103. /// Returns the number of selected parts
  104. int Size() const
  105. {
  106. return m_items.size();
  107. }
  108. const std::deque<EDA_ITEM*> GetItems() const
  109. {
  110. return m_items;
  111. }
  112. /// Returns the center point of the selection area bounding box.
  113. virtual VECTOR2I GetCenter() const
  114. {
  115. return static_cast<VECTOR2I>( GetBoundingBox().Centre() );
  116. }
  117. virtual const BOX2I ViewBBox() const override
  118. {
  119. BOX2I r;
  120. r.SetMaximum();
  121. return r;
  122. }
  123. /// Returns the top left point of the selection area bounding box.
  124. VECTOR2I GetPosition() const
  125. {
  126. return static_cast<VECTOR2I>( GetBoundingBox().GetPosition() );
  127. }
  128. EDA_RECT GetBoundingBox() const
  129. {
  130. EDA_RECT bbox;
  131. if( Front() )
  132. {
  133. bbox = Front()->GetBoundingBox();
  134. for( auto i = m_items.begin() + 1; i != m_items.end(); ++i )
  135. bbox.Merge( (*i)->GetBoundingBox() );
  136. }
  137. return bbox;
  138. }
  139. virtual EDA_ITEM* GetTopLeftItem( bool onlyModules = false ) const
  140. {
  141. return nullptr;
  142. }
  143. EDA_ITEM* operator[]( const size_t aIdx ) const
  144. {
  145. if( aIdx < m_items.size() )
  146. return m_items[ aIdx ];
  147. return nullptr;
  148. }
  149. EDA_ITEM* Front() const
  150. {
  151. return m_items.size() ? m_items.front() : nullptr;
  152. }
  153. std::deque<EDA_ITEM*>& Items()
  154. {
  155. return m_items;
  156. }
  157. template<class T>
  158. T* FirstOfKind() const
  159. {
  160. auto refType = T( nullptr ).Type();
  161. for( auto item : m_items )
  162. {
  163. if( item->Type() == refType )
  164. return static_cast<T*> ( item );
  165. }
  166. return nullptr;
  167. }
  168. /**
  169. * Checks if there is at least one item of requested kind.
  170. *
  171. * @param aType is the type to check for.
  172. * @return True if there is at least one item of such kind.
  173. */
  174. bool HasType( KICAD_T aType ) const
  175. {
  176. for( auto item : m_items )
  177. {
  178. if( item->Type() == aType )
  179. return true;
  180. }
  181. return false;
  182. }
  183. virtual const VIEW_GROUP::ITEMS updateDrawList() const override
  184. {
  185. std::vector<VIEW_ITEM*> items;
  186. for( auto item : m_items )
  187. items.push_back( item );
  188. return items;
  189. }
  190. bool HasReferencePoint() const
  191. {
  192. return m_referencePoint != NULLOPT;
  193. }
  194. VECTOR2I GetReferencePoint() const
  195. {
  196. return *m_referencePoint;
  197. }
  198. void SetReferencePoint( const VECTOR2I& aP )
  199. {
  200. m_referencePoint = aP;
  201. }
  202. void ClearReferencePoint()
  203. {
  204. m_referencePoint = NULLOPT;
  205. }
  206. /**
  207. * Checks if all items in the selection are the same KICAD_T type
  208. *
  209. * @return True if all items are the same type, this includes zero or single items
  210. */
  211. bool AreAllItemsIdentical() const
  212. {
  213. return ( std::all_of( m_items.begin() + 1, m_items.end(),
  214. [&]( const EDA_ITEM* r )
  215. {
  216. return r->Type() == m_items.front()->Type();
  217. } ) );
  218. }
  219. protected:
  220. OPT<VECTOR2I> m_referencePoint;
  221. std::deque<EDA_ITEM*> m_items;
  222. bool m_isHover;
  223. // mute hidden overloaded virtual function warnings
  224. using VIEW_GROUP::Add;
  225. using VIEW_GROUP::Remove;
  226. };
  227. enum SELECTION_LOCK_FLAGS
  228. {
  229. SELECTION_UNLOCKED = 0,
  230. SELECTION_LOCK_OVERRIDE = 1,
  231. SELECTION_LOCKED = 2
  232. };
  233. #endif