Fix MSYS2 issues
[xonotic/netradiant.git] / libs / selectionlib.h
1 /*
2    Copyright (C) 2001-2006, William Joseph.
3    All Rights Reserved.
4
5    This file is part of GtkRadiant.
6
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.
11
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.
16
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
20  */
21
22 #if !defined ( INCLUDED_SELECTIONLIB_H )
23 #define INCLUDED_SELECTIONLIB_H
24
25 #include "iselection.h"
26 #include "generic/callback.h"
27 #include "scenelib.h"
28 #include <stdlib.h>
29
30 class SelectableBool : public Selectable
31 {
32 bool m_selected;
33 public:
34 SelectableBool()
35         : m_selected( false )
36 {}
37
38 void setSelected( bool select = true ){
39         m_selected = select;
40 }
41 bool isSelected() const {
42         return m_selected;
43 }
44 };
45
46 class ObservedSelectable : public Selectable
47 {
48 SelectionChangeCallback m_onchanged;
49 bool m_selected;
50 public:
51 ObservedSelectable( const SelectionChangeCallback& onchanged ) : m_onchanged( onchanged ), m_selected( false ){
52 }
53 ObservedSelectable( const ObservedSelectable& other ) : Selectable( other ), m_onchanged( other.m_onchanged ), m_selected( false ){
54         setSelected( other.isSelected() );
55 }
56 ObservedSelectable& operator=( const ObservedSelectable& other ){
57         setSelected( other.isSelected() );
58         return *this;
59 }
60 ~ObservedSelectable(){
61         setSelected( false );
62 }
63
64 void setSelected( bool select ){
65         if ( select ^ m_selected ) {
66                 m_selected = select;
67
68                 m_onchanged( *this );
69         }
70 }
71 bool isSelected() const {
72         return m_selected;
73 }
74 };
75
76 class SelectableInstance : public scene::Instance
77 {
78 class TypeCasts
79 {
80 InstanceTypeCastTable m_casts;
81 public:
82 TypeCasts(){
83         InstanceContainedCast<SelectableInstance, Selectable>::install( m_casts );
84 }
85 InstanceTypeCastTable& get(){
86         return m_casts;
87 }
88 };
89
90 ObservedSelectable m_selectable;
91 public:
92
93 typedef LazyStatic<TypeCasts> StaticTypeCasts;
94
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 ) ){
98 }
99
100 Selectable& get( NullType<Selectable>){
101         return m_selectable;
102 }
103
104 Selectable& getSelectable(){
105         return m_selectable;
106 }
107 const Selectable& getSelectable() const {
108         return m_selectable;
109 }
110
111 void selectedChanged( const Selectable& selectable ){
112         GlobalSelectionSystem().getObserver ( SelectionSystem::ePrimitive )( selectable );
113         GlobalSelectionSystem().onSelectedChanged( *this, selectable );
114
115         Instance::selectedChanged();
116 }
117 typedef MemberCaller1<SelectableInstance, const Selectable&, &SelectableInstance::selectedChanged> SelectedChangedCaller;
118 };
119
120
121 template<typename Iterator>
122 inline bool range_check( Iterator start, Iterator finish, Iterator iter ){
123         for (; start != finish; ++start )
124         {
125                 if ( start == iter ) {
126                         return true;
127                 }
128         }
129         return false;
130 }
131
132 #include <list>
133
134 template<typename Selected>
135 class SelectionList
136 {
137 typedef std::list<Selected*> List;
138 List m_selection;
139 public:
140 typedef typename List::iterator iterator;
141 typedef typename List::const_iterator const_iterator;
142
143 iterator begin(){
144         return m_selection.begin();
145 }
146 const_iterator begin() const {
147         return m_selection.begin();
148 }
149 iterator end(){
150         return m_selection.end();
151 }
152 const_iterator end() const {
153         return m_selection.end();
154 }
155 bool empty() const {
156         return m_selection.empty();
157 }
158 std::size_t size() const {
159         return m_selection.size();
160 }
161 Selected& back(){
162         return *m_selection.back();
163 }
164 Selected& back() const {
165         return *m_selection.back();
166 }
167 void append( Selected& selected ){
168         m_selection.push_back( &selected );
169 }
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() );
175 }
176 };
177
178
179 #endif