container.h (6625B)
1 // Copyright (c) 2003 - 2009 Anselm R Garbe <anselm@garbe.us> 2 // See LICENSE for license details. 3 4 #ifndef __CONTAINER_H 5 #define __CONTAINER_H 6 7 #include "kernel.h" 8 #include "util.h" // also includes wmi.h 9 10 /** 11 * A Container object keeps a parent reference and may contain a list of 12 * child objects. 13 * 14 * A Container is a class template that creates an object that contains a list 15 * of other objects and also keeps a reference to a parent object. 16 * A container can be configured with for stacked tabbing at compile time. 17 * 18 * @param P the parent class 19 * @param LT the child list class 20 * @param LTI the iterator class for the child list 21 * @param T the child class 22 */ 23 template <class P, class LT, class LTI, class T> 24 class Container 25 { 26 public: 27 28 /** 29 * Constructs a container with a parent and a focused child. 30 * 31 * @param parent the original parent. 32 * @param child the original focused child which is optional. 33 */ 34 Container(P *parent, T *child = 0) { 35 parent_ = parent; 36 child_ = child; 37 }; 38 39 /** 40 * The destructor. 41 * 42 * When the destructor is destoryed it will also destroys 43 * all of the children in the container. 44 */ 45 ~Container() { 46 Util::destroy<LT, LTI, T *> 47 (&childs_, childs_.begin(), childs_.end()); 48 }; 49 50 /** 51 * Checks if the child is contained in this container. 52 * 53 * @param child the child to search for. 54 */ 55 bool contains(T *child) { 56 return Util::contains<LT, LTI, T>(&childs_, child); 57 }; 58 59 /** 60 * Get the number of children in this container. 61 * 62 * @return the the number of children 63 */ 64 unsigned int size() { 65 return childs_.size(); 66 }; 67 68 /** 69 * Get the list iterator to the first child. 70 * 71 * @return the list iterator to first child. 72 */ 73 LTI begin() { 74 return childs_.begin(); 75 }; 76 77 /** 78 * Get the list iterator to end of child list. 79 * 80 * @return the list iterator to the last child. 81 */ 82 LTI end() { 83 return childs_.end(); 84 }; 85 86 /** 87 * Get the parent that the container is attached to. 88 * 89 * @return the parent. 90 */ 91 P *attached() const { 92 return parent_; 93 }; 94 95 /** 96 * Attach the container to a new parent. 97 * 98 * @param parent the parent. 99 */ 100 void setAttached(P *parent) { 101 parent_ = parent; 102 }; 103 104 /** 105 * Get the currently focused child in the container. 106 * 107 * @return the focused child, if any. 108 */ 109 T *focused() const { 110 return child_; 111 }; 112 113 /** 114 * Gives a child focus. 115 * 116 * In normal mode the child simply receives focus. In stacked 117 * tabbing mode the currently focused child will be placed at 118 * the end of the list and the newly focused child will be placed 119 * at the front. 120 * 121 * @param child the child to receive focus. 122 */ 123 void focus(T *child) { 124 if (child && KERNEL->isStackedTabbing()) { 125 if (childs_.size()) { 126 T *foc = childs_.front(); 127 if (foc != child) { 128 childs_.remove(foc); 129 childs_.push_back(foc); 130 } 131 } 132 childs_.remove(child); 133 childs_.push_front(child); 134 } 135 child_ = child; 136 }; 137 138 /** 139 * Attaches a child to the container. 140 * 141 * This attaches a new child to the container. 142 * When a child is attached it receives focus. 143 * <code>attach()</code> will not add a duplicate child to the container. 144 * 145 * @param child the child to attach. 146 */ 147 void attach(T *child) { 148 if (child && !contains(child)) { 149 childs_.push_back(child); 150 focus(child); 151 } 152 }; 153 154 /** 155 * Detach a child from the container. 156 * 157 * Detaches the child from the container. If the child being detached 158 * currently has focus then the focus will switch to the previous child. 159 * If this was the last child left in the container than there will be no 160 * child with focus. 161 * 162 * @param child the child to detach. 163 * @return the current child with focus. 164 */ 165 T *detach(T *child) { 166 167 if (child_ == child) { 168 // cycle to prev child 169 focus(prev()); 170 } 171 childs_.remove(child); 172 173 if (childs_.size() < 1) { 174 child_ = 0; 175 } 176 return child_; 177 }; 178 179 /** 180 * Get the previous child in the list. 181 * 182 * In stacked tabbing mode this is the last child. In regular 183 * mode this is the child before the currently focused child. 184 * 185 * @return the previous child. 186 */ 187 T *prev() { 188 189 if (childs_.size() < 1) { 190 return 0; 191 } 192 else if (childs_.size() < 2) { 193 return child_; 194 } 195 196 if (KERNEL->isStackedTabbing()) { 197 return childs_.back(); 198 } 199 else { 200 for (LTI it = childs_.begin(); 201 it != childs_.end(); it++) 202 { 203 if (child_ == *it) { 204 if (it != childs_.begin()) { 205 it--; 206 return *it; 207 } 208 else { 209 break; 210 } 211 } 212 } 213 return childs_.back(); 214 } 215 } 216 217 218 /** 219 * Get the next child in the list. 220 * 221 * In stacked tabbing mode this is the second child in the list. 222 * In regular mode it is the child after the currently focused child. 223 * 224 * @return the next child. 225 */ 226 T *next() { 227 if (childs_.size() < 1) { 228 return 0; 229 } 230 else if (childs_.size() < 2) { 231 return child_; 232 } 233 234 if (KERNEL->isStackedTabbing()) { 235 LTI it = childs_.begin(); 236 it++; 237 return *it; 238 } 239 else { 240 for (LTI it = childs_.begin(); 241 it != childs_.end(); it++) 242 { 243 if (child_ == *it) { 244 it++; 245 if (it != childs_.end()) { 246 return *it; 247 } 248 else { 249 break; 250 } 251 } 252 } 253 return childs_.front(); 254 } 255 }; 256 257 /** Used for direct manipulation, use with care! */ 258 LT *childs() { 259 return &childs_; 260 } 261 262 263 private: 264 265 P *parent_; 266 T *child_; 267 LT childs_; 268 }; 269 270 #endif // __CONTAINER_H