diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index f2d9a2c2b3..c26101d77c 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -440,6 +440,7 @@ set( COMMON_SRCS tool/grid_helper.cpp tool/grid_menu.cpp tool/picker_tool.cpp + tool/selection.cpp tool/selection_conditions.cpp tool/tool_action.cpp tool/tool_base.cpp diff --git a/common/tool/selection.cpp b/common/tool/selection.cpp new file mode 100644 index 0000000000..1a99f015cc --- /dev/null +++ b/common/tool/selection.cpp @@ -0,0 +1,140 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013-2017 CERN + * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> + * @author Maciej Suminski <maciej.suminski@cern.ch> + * + * 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 2 + * 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, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <algorithm> +#include <eda_item.h> +#include <tool/selection.h> + + +void SELECTION::Add( EDA_ITEM* aItem ) +{ + // We're not sorting here; this is just a time-optimized way to do an + // inclusion check. std::lower_bound will return the first i >= aItem + // and the second i > aItem check rules out i == aItem. + ITER i = std::lower_bound( m_items.begin(), m_items.end(), aItem ); + + if( i == m_items.end() || *i > aItem ) + m_items.insert( i, aItem ); +} + + +void SELECTION::Remove( EDA_ITEM* aItem ) +{ + ITER i = std::lower_bound( m_items.begin(), m_items.end(), aItem ); + + if( !( i == m_items.end() || *i > aItem ) ) + m_items.erase( i ); +} + + +KIGFX::VIEW_ITEM* SELECTION::GetItem( unsigned int aIdx ) const +{ + if( aIdx < m_items.size() ) + return m_items[aIdx]; + + return nullptr; +} + + +bool SELECTION::Contains( EDA_ITEM* aItem ) const +{ + CITER i = std::lower_bound( m_items.begin(), m_items.end(), aItem ); + + return !( i == m_items.end() || *i > aItem ); +} + + +/// Returns the center point of the selection area bounding box. +VECTOR2I SELECTION::GetCenter() const +{ + KICAD_T labelTypes[] = { SCH_LABEL_T, SCH_GLOBAL_LABEL_T, SCH_HIER_LABEL_T, EOT }; + bool includeLabels = true; + + // If the selection contains at least one non-label then don't include labels when + // calculating the centerpoint. + + for( EDA_ITEM* item : m_items ) + { + if( !item->IsType( labelTypes ) ) + { + includeLabels = false; + break; + } + } + + EDA_RECT bbox; + + for( EDA_ITEM* item : m_items ) + { + if( !item->IsType( labelTypes ) || includeLabels ) + bbox.Merge( item->GetBoundingBox() ); + } + + return static_cast<VECTOR2I>( bbox.Centre() ); +} + + +EDA_RECT SELECTION::GetBoundingBox() const +{ + EDA_RECT bbox; + + for( EDA_ITEM* item : m_items ) + bbox.Merge( item->GetBoundingBox() ); + + return bbox; +} + + +bool SELECTION::HasType( KICAD_T aType ) const +{ + for( auto item : m_items ) + { + if( item->Type() == aType ) + return true; + } + + return false; +} + + +const KIGFX::VIEW_GROUP::ITEMS SELECTION::updateDrawList() const +{ + std::vector<VIEW_ITEM*> items; + + for( auto item : m_items ) + items.push_back( item ); + + return items; +} + + +bool SELECTION::AreAllItemsIdentical() const +{ + return ( std::all_of( m_items.begin() + 1, m_items.end(), + [&]( const EDA_ITEM* r ) + { + return r->Type() == m_items.front()->Type(); + } ) ); +} \ No newline at end of file diff --git a/common/tool/selection_conditions.cpp b/common/tool/selection_conditions.cpp index 71a5406747..2314493abe 100644 --- a/common/tool/selection_conditions.cpp +++ b/common/tool/selection_conditions.cpp @@ -27,6 +27,7 @@ #include <tool/selection_conditions.h> #include <functional> +#include <eda_item.h> using namespace std::placeholders; diff --git a/include/tool/selection.h b/include/tool/selection.h index 25950975e3..315f1f815a 100644 --- a/include/tool/selection.h +++ b/include/tool/selection.h @@ -26,13 +26,14 @@ #ifndef SELECTION_H #define SELECTION_H -#include <algorithm> #include <core/optional.h> +#include <core/typeinfo.h> #include <deque> #include <eda_rect.h> -#include <eda_item.h> #include <view/view_group.h> +class EDA_ITEM; + class SELECTION : public KIGFX::VIEW_GROUP { public: @@ -74,24 +75,9 @@ public: return m_isHover; } - virtual void Add( EDA_ITEM* aItem ) - { - // We're not sorting here; this is just a time-optimized way to do an - // inclusion check. std::lower_bound will return the first i >= aItem - // and the second i > aItem check rules out i == aItem. - ITER i = std::lower_bound( m_items.begin(), m_items.end(), aItem ); + virtual void Add( EDA_ITEM* aItem ); - if( i == m_items.end() || *i > aItem ) - m_items.insert( i, aItem ); - } - - virtual void Remove( EDA_ITEM *aItem ) - { - ITER i = std::lower_bound( m_items.begin(), m_items.end(), aItem ); - - if( !( i == m_items.end() || *i > aItem ) ) - m_items.erase( i ); - } + virtual void Remove( EDA_ITEM *aItem ); virtual void Clear() override { @@ -103,20 +89,9 @@ public: return m_items.size(); } - virtual KIGFX::VIEW_ITEM* GetItem( unsigned int aIdx ) const override - { - if( aIdx < m_items.size() ) - return m_items[ aIdx ]; + virtual KIGFX::VIEW_ITEM* GetItem( unsigned int aIdx ) const override; - return nullptr; - } - - bool Contains( EDA_ITEM* aItem ) const - { - CITER i = std::lower_bound( m_items.begin(), m_items.end(), aItem ); - - return !( i == m_items.end() || *i > aItem ); - } + bool Contains( EDA_ITEM* aItem ) const; /// Checks if there is anything selected bool Empty() const @@ -136,33 +111,7 @@ public: } /// Returns the center point of the selection area bounding box. - virtual VECTOR2I GetCenter() const - { - KICAD_T labelTypes[] = { SCH_LABEL_T, SCH_GLOBAL_LABEL_T, SCH_HIER_LABEL_T, EOT }; - bool includeLabels = true; - - // If the selection contains at least one non-label then don't include labels when - // calculating the centerpoint. - - for( EDA_ITEM* item : m_items ) - { - if( !item->IsType( labelTypes ) ) - { - includeLabels = false; - break; - } - } - - EDA_RECT bbox; - - for( EDA_ITEM* item : m_items ) - { - if( !item->IsType( labelTypes ) || includeLabels ) - bbox.Merge( item->GetBoundingBox() ); - } - - return static_cast<VECTOR2I>( bbox.Centre() ); - } + virtual VECTOR2I GetCenter() const; virtual const BOX2I ViewBBox() const override { @@ -177,15 +126,7 @@ public: return static_cast<VECTOR2I>( GetBoundingBox().GetPosition() ); } - virtual EDA_RECT GetBoundingBox() const - { - EDA_RECT bbox; - - for( EDA_ITEM* item : m_items ) - bbox.Merge( item->GetBoundingBox() ); - - return bbox; - } + virtual EDA_RECT GetBoundingBox() const; virtual EDA_ITEM* GetTopLeftItem( bool onlyModules = false ) const { @@ -230,26 +171,9 @@ public: * @param aType is the type to check for. * @return True if there is at least one item of such kind. */ - bool HasType( KICAD_T aType ) const - { - for( auto item : m_items ) - { - if( item->Type() == aType ) - return true; - } + bool HasType( KICAD_T aType ) const; - return false; - } - - virtual const VIEW_GROUP::ITEMS updateDrawList() const override - { - std::vector<VIEW_ITEM*> items; - - for( auto item : m_items ) - items.push_back( item ); - - return items; - } + virtual const VIEW_GROUP::ITEMS updateDrawList() const override; bool HasReferencePoint() const { @@ -276,14 +200,7 @@ public: * * @return True if all items are the same type, this includes zero or single items */ - bool AreAllItemsIdentical() const - { - return ( std::all_of( m_items.begin() + 1, m_items.end(), - [&]( const EDA_ITEM* r ) - { - return r->Type() == m_items.front()->Type(); - } ) ); - } + bool AreAllItemsIdentical() const; protected: OPT<VECTOR2I> m_referencePoint; diff --git a/pagelayout_editor/tools/pl_selection.cpp b/pagelayout_editor/tools/pl_selection.cpp index 35199f49fa..b569a096f9 100644 --- a/pagelayout_editor/tools/pl_selection.cpp +++ b/pagelayout_editor/tools/pl_selection.cpp @@ -22,6 +22,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +#include <eda_item.h> #include "tools/pl_selection.h"