2 Copyright (C) 2001-2006, William Joseph.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #if !defined ( INCLUDED_SELECTIONLIB_H )
23 #define INCLUDED_SELECTIONLIB_H
25 #include "iselection.h"
26 #include "generic/callback.h"
30 class SelectableBool : public Selectable
38 void setSelected( bool select = true ){
41 bool isSelected() const {
46 class ObservedSelectable : public Selectable
48 SelectionChangeCallback m_onchanged;
51 ObservedSelectable( const SelectionChangeCallback& onchanged ) : m_onchanged( onchanged ), m_selected( false ){
53 ObservedSelectable( const ObservedSelectable& other ) : Selectable( other ), m_onchanged( other.m_onchanged ), m_selected( false ){
54 setSelected( other.isSelected() );
56 ObservedSelectable& operator=( const ObservedSelectable& other ){
57 setSelected( other.isSelected() );
60 ~ObservedSelectable(){
64 void setSelected( bool select ){
65 if ( select ^ m_selected ) {
71 bool isSelected() const {
76 class SelectableInstance : public scene::Instance
80 InstanceTypeCastTable m_casts;
83 InstanceContainedCast<SelectableInstance, Selectable>::install( m_casts );
85 InstanceTypeCastTable& get(){
90 ObservedSelectable m_selectable;
93 typedef LazyStatic<TypeCasts> StaticTypeCasts;
95 SelectableInstance( const scene::Path& path, scene::Instance* parent, void* instance = 0, InstanceTypeCastTable& casts = StaticTypeCasts::instance().get() ) :
96 Instance( path, parent, instance != 0 ? instance : this, casts ),
97 m_selectable( SelectedChangedCaller( *this ) ){
100 Selectable& get( NullType<Selectable>){
104 Selectable& getSelectable(){
107 const Selectable& getSelectable() const {
111 void selectedChanged( const Selectable& selectable ){
112 GlobalSelectionSystem().getObserver ( SelectionSystem::ePrimitive )( selectable );
113 GlobalSelectionSystem().onSelectedChanged( *this, selectable );
115 Instance::selectedChanged();
117 typedef MemberCaller1<SelectableInstance, const Selectable&, &SelectableInstance::selectedChanged> SelectedChangedCaller;
121 template<typename Iterator>
122 inline bool range_check( Iterator start, Iterator finish, Iterator iter ){
123 for (; start != finish; ++start )
125 if ( start == iter ) {
134 template<typename Selected>
137 typedef std::list<Selected*> List;
140 typedef typename List::iterator iterator;
141 typedef typename List::const_iterator const_iterator;
144 return m_selection.begin();
146 const_iterator begin() const {
147 return m_selection.begin();
150 return m_selection.end();
152 const_iterator end() const {
153 return m_selection.end();
156 return m_selection.empty();
158 std::size_t size() const {
159 return m_selection.size();
162 return *m_selection.back();
164 Selected& back() const {
165 return *m_selection.back();
167 void append( Selected& selected ){
168 m_selection.push_back( &selected );
170 void erase( Selected& selected ){
171 typename List::reverse_iterator i = std::find( m_selection.rbegin(), m_selection.rend(), &selected );
172 ASSERT_MESSAGE( i != m_selection.rend(), "selection-tracking error" );
173 ASSERT_MESSAGE( range_check( m_selection.begin(), m_selection.end(), --i.base() ), "selection-tracking error" );
174 m_selection.erase( --i.base() );