00001 #ifndef CONFIRM_CONTROLLER_H
00002 #define CONFIRM_CONTROLLER_H
00003
00004 #include <iostream>
00005 #include <UniSetTypes.h>
00006 #include <sigc++/sigc++.h>
00007 #include <map>
00008 #include <cassert>
00009
00010 namespace ConfirmCtl
00011 {
00012
00013 struct def_StateKey
00014 {
00015 UniSetTypes::ObjectId id;
00016 long value;
00017
00018 bool operator<(const def_StateKey& y) const
00019 { return (id < y.id || (id == y.id && value < y.value)); }
00020 };
00021
00022 struct StateInfo
00023 {
00024 StateInfo () : on(false), confirmed(true), priority(0),
00025 need_confirm(false), blinkable(false) {}
00026
00027 bool on;
00028 bool confirmed;
00029
00030 int priority;
00031 bool need_confirm;
00032 bool blinkable;
00033
00034 sigc::slot<void> start_blink;
00035 sigc::slot<void> stop_blink;
00036 sigc::slot<void> switch_on;
00037 sigc::slot<void, sigc::slot<void> > connect_confirm;
00038 };
00039
00046 template <class T = def_StateKey, class Compare = std::less<T> >
00047 class ConfirmController
00048 {
00049 public:
00050 typedef T StateKey;
00051 typedef std::map<StateKey, StateInfo, Compare> StatesMap;
00052
00053 ConfirmController() : current_it_(states_map_.end()), undefined_(false) {}
00054 ~ConfirmController() {}
00055
00056 void update(StateKey state_key, bool on);
00057 void confirm(StateKey state_key);
00058 void add(StateKey state_key, StateInfo& state_info);
00059 void remove(const StateKey& state_key);
00060 void reset();
00061
00062 void setBlinkable(const StateKey& state_key, bool blinkable);
00063 void setPriority(const StateKey& state_key, int priority);
00064 void setNeedConfirm(const StateKey& state_key, bool need_confirm);
00065
00066 StateInfo copyStateInfo(const StateKey& state_key) const;
00067 bool hasState(const StateKey& state_key) const;
00068 const StatesMap& getStatesMap() const { return states_map_; }
00069 const StateInfo* getStateInfo(const StateKey& state_key) const;
00070 bool undefined() const;
00071
00072 sigc::signal<void> signal_switch_to_undefined;
00073
00074 protected:
00075 void Error(const char* message) {}
00076
00077 private:
00078 StatesMap states_map_;
00079
00080 typename StatesMap::iterator current_it_;
00081
00082 bool undefined_;
00083
00084 void switch_to_next();
00085 void switch_to(StateKey new_state);
00086 bool is_state_to_show(const StateInfo& si) const;
00087 };
00088
00089 template<class T,class C>
00090 void ConfirmController<T,C>::update(StateKey sk, bool on)
00091 {
00092 typename StatesMap::iterator it = states_map_.find(sk);
00093 if (it == states_map_.end()) {
00094 Error("State not found. Can't update\n");
00095 return;
00096 }
00097
00098 StateInfo* si = &it->second;
00099
00100
00101 if (on == true && si->on == false) {
00102
00103
00104
00105
00106
00107
00108
00109 si->on = true;
00110 if (current_it_ == states_map_.end() || si->priority > current_it_->second.priority)
00111 switch_to(sk);
00112 }
00113 else if (on == false && si->on == true) {
00114 si->on = false;
00115 if (it == current_it_)
00116 switch_to_next();
00117 }
00118 }
00119
00120 template<class T, class C>
00121 void ConfirmController<T,C>::switch_to(StateKey sk)
00122 {
00123 typename StatesMap::iterator it = states_map_.find(sk);
00124
00125 if (it == states_map_.end()) {
00126 Error("(!INTERNAL ERROR!): Trying to switch to unknown state.\n");
00127 return;
00128 }
00129
00130
00131
00132
00133
00134
00135 if (current_it_ != states_map_.end() &&
00136 current_it_->second.blinkable)
00137 current_it_->second.stop_blink();
00138
00139 current_it_ = it;
00140 it->second.switch_on();
00141
00142 if (it->second.blinkable)
00143 it->second.start_blink();
00144
00145
00146
00147
00148
00149
00150 }
00151
00152 template<class T, class C>
00153 void ConfirmController<T,C>::switch_to_next()
00154 {
00155 int max_priority = INT_MIN;
00156 StateKey next_state;
00157 for (typename StatesMap::iterator it = states_map_.begin();
00158 it != states_map_.end(); ++it)
00159 {
00160 StateInfo* si= &(*it).second;
00161 assert( si->priority != INT_MIN );
00162
00163
00164
00165 if ( si->on && max_priority <= si->priority) {
00166 max_priority = si->priority;
00167 next_state = (*it).first;
00168 }
00169 }
00170 if ( max_priority != INT_MIN )
00171 switch_to( next_state );
00172 else if ( current_it_ != states_map_.end() ) {
00173 if ( current_it_->second.blinkable )
00174 current_it_->second.stop_blink();
00175 current_it_ = states_map_.end();
00176 undefined_ = true;
00177 signal_switch_to_undefined.emit();
00178 }
00179 }
00180
00181 template<class T, class C>
00182 void ConfirmController<T,C>::confirm(StateKey sk)
00183 {
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 }
00194
00195 template<class T, class C>
00196 void ConfirmController<T,C>::add(StateKey sk, StateInfo& si)
00197 {
00198 if (states_map_.count(sk) > 0) {
00199 Error("Trying to add existing state.\n");
00200 return;
00201 }
00202
00203 states_map_[sk] = si;
00204
00205
00206 if (si.on && is_state_to_show(si))
00207 switch_to(sk);
00208 }
00209
00210 template<class T, class C>
00211 void ConfirmController<T,C>::remove(const StateKey& sk)
00212 {
00213 typename StatesMap::iterator it = states_map_.find(sk);
00214 if (it == states_map_.end()) {
00215 Error("Trying to remove unknown state.\n");
00216 return;
00217 }
00218
00219 if (current_it_ == it)
00220 update(sk, false);
00221
00222 states_map_.erase(it);
00223 }
00224
00225 template<class T, class C>
00226 StateInfo ConfirmController<T,C>::copyStateInfo( const StateKey& sk) const
00227 {
00228 if (states_map_.count(sk) <= 0) {
00229 Error("Trying to get information from unknown state.\n");
00230 throw std::exception();
00231 }
00232
00233 return states_map_[sk];
00234 }
00235
00236 template<class T, class C>
00237 const StateInfo* ConfirmController<T,C>::getStateInfo( const StateKey& sk ) const
00238 {
00239 typename StatesMap::iterator it = states_map_.find(sk);
00240 if (it == states_map_.end())
00241 return NULL;
00242
00243 return &(*it).second;
00244 }
00245
00246 template<class T, class C>
00247 void ConfirmController<T,C>::setPriority( const StateKey& sk, int priority )
00248 {
00249 typename StatesMap::iterator it = states_map_.find(sk);
00250 assert( it != states_map_.end() );
00251
00252 it->second.priority = priority;
00253 switch_to_next();
00254 }
00255
00256 template<class T, class C>
00257 void ConfirmController<T,C>::setBlinkable( const StateKey& sk, bool blinkable )
00258 {
00259 typename StatesMap::iterator it = states_map_.find(sk);
00260 assert(it != states_map_.end());
00261
00262 std::swap(it->second.blinkable, blinkable);
00263 if (it == current_it_) {
00264 if (!it->second.blinkable && blinkable)
00265 it->second.stop_blink();
00266 else if (it->second.blinkable && !blinkable)
00267 it->second.start_blink();
00268 }
00269 return;
00270 }
00271
00272 template<class T, class C>
00273 void ConfirmController<T,C>::setNeedConfirm( const StateKey& sk, bool need_confirm )
00274 {
00275 typename StatesMap::iterator it = states_map_.find(sk);
00276 assert( it != states_map_.end() );
00277
00278 std::swap(it->second.need_confirm, need_confirm);
00279 if (it != current_it_)
00280 return;
00281
00282 if (it->second.need_confirm && !need_confirm)
00283 update( it->first, true );
00284 return;
00285 }
00286
00287 template<class T, class C>
00288 bool ConfirmController<T,C>::hasState(const StateKey& sk) const
00289 {
00290 return states_map_.count(sk);
00291 }
00292
00293 template<class T, class C>
00294 bool ConfirmController<T,C>::undefined() const
00295 {
00296 return current_it_ == states_map_.end();
00297 }
00298
00299 template<class T, class C>
00300 bool ConfirmController<T,C>::is_state_to_show(const StateInfo& si) const
00301 {
00302 return current_it_ == states_map_.end() || current_it_->second.priority < si.priority;
00303 }
00304
00305 template<class T, class C>
00306 void ConfirmController<T,C>::reset()
00307 {
00308 for (typename StatesMap::iterator it = states_map_.begin();
00309 it != states_map_.end(); ++it)
00310 {
00311 it->second.on = false;
00312 it->second.confirmed = true;
00313 }
00314
00315 current_it_ = states_map_.end();
00316 signal_switch_to_undefined.emit();
00317 }
00318
00319 }
00320 #endif