remove RSA's md4.c, replace by DP's
[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   {
40     m_selected = select;
41   }
42   bool isSelected() const
43   {
44     return m_selected;
45   }
46 };
47
48 class ObservedSelectable : public Selectable
49 {
50   SelectionChangeCallback m_onchanged;
51   bool m_selected;
52 public:
53   ObservedSelectable(const SelectionChangeCallback& onchanged) : m_onchanged(onchanged), m_selected(false)
54   {
55   }
56   ObservedSelectable(const ObservedSelectable& other) : Selectable(other), m_onchanged(other.m_onchanged), m_selected(false)
57   {
58     setSelected(other.isSelected());
59   }
60   ObservedSelectable& operator=(const ObservedSelectable& other)
61   {
62     setSelected(other.isSelected());
63     return *this;
64   }
65   ~ObservedSelectable()
66   {
67     setSelected(false);
68   }
69
70   void setSelected(bool select)
71   {
72     if(select ^ m_selected)
73     {
74       m_selected = select;
75
76       m_onchanged(*this);
77     }
78   }
79   bool isSelected() const
80   {
81     return m_selected;
82   }
83 };
84
85 class SelectableInstance : public scene::Instance
86 {
87   class TypeCasts
88   {
89     InstanceTypeCastTable m_casts;
90   public:
91     TypeCasts()
92     {
93       InstanceContainedCast<SelectableInstance, Selectable>::install(m_casts);
94     }
95     InstanceTypeCastTable& get()
96     {
97       return m_casts;
98     }
99   };
100
101   ObservedSelectable m_selectable;
102 public:
103
104   typedef LazyStatic<TypeCasts> StaticTypeCasts;
105
106   SelectableInstance(const scene::Path& path, scene::Instance* parent, void* instance = 0, InstanceTypeCastTable& casts = StaticTypeCasts::instance().get()) :
107   Instance(path, parent, instance != 0 ? instance : this, casts),
108     m_selectable(SelectedChangedCaller(*this))
109   {
110   }
111
112   Selectable& get(NullType<Selectable>)
113   {
114     return m_selectable;
115   }
116
117   Selectable& getSelectable()
118   {
119     return m_selectable;
120   }
121   const Selectable& getSelectable() const
122   {
123     return m_selectable;
124   }
125
126   void selectedChanged(const Selectable& selectable)
127   {
128     GlobalSelectionSystem().getObserver(SelectionSystem::ePrimitive)(selectable);
129     GlobalSelectionSystem().onSelectedChanged(*this, selectable);
130
131     Instance::selectedChanged();
132   }
133   typedef MemberCaller1<SelectableInstance, const Selectable&, &SelectableInstance::selectedChanged> SelectedChangedCaller;
134 };
135
136
137 template<typename Iterator>
138 inline bool range_check(Iterator start, Iterator finish, Iterator iter)
139 {
140   for(;start != finish; ++start)
141   {
142     if(start == iter)
143     {
144       return true;
145     }
146   }
147   return false;
148 }
149
150 #include <list>
151
152 template<typename Selected>
153 class SelectionList
154 {
155   typedef std::list<Selected*> List;
156   List m_selection;
157 public:
158   typedef typename List::iterator iterator;
159   typedef typename List::const_iterator const_iterator;
160
161   iterator begin()
162   {
163     return m_selection.begin();
164   }
165   const_iterator begin() const
166   {
167     return m_selection.begin();
168   }
169   iterator end()
170   {
171     return m_selection.end();
172   }
173   const_iterator end() const
174   {
175     return m_selection.end();
176   }
177   bool empty() const
178   {
179     return m_selection.empty();
180   }
181   std::size_t size() const
182   {
183     return m_selection.size();
184   }
185   Selected& back()
186   {
187     return *m_selection.back();
188   }
189   Selected& back() const
190   {
191     return *m_selection.back();
192   }
193   void append(Selected& selected)
194   {
195     m_selection.push_back(&selected);
196   }
197   void erase(Selected& selected)
198   {
199     typename List::reverse_iterator i = std::find(m_selection.rbegin(), m_selection.rend(), &selected);
200     ASSERT_MESSAGE(i != m_selection.rend(), "selection-tracking error");
201     ASSERT_MESSAGE(range_check(m_selection.begin(), m_selection.end(), --i.base()), "selection-tracking error");
202     m_selection.erase(--i.base());
203   }
204 };
205
206
207 #endif