el h / SimpleGUI

Fork of SimpleGUI by Duncan McIntyre

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Widget.cpp Source File

Widget.cpp

00001 #include "Widget.h"
00002 #include <algorithm>
00003 Widget::Widget(GraphicsContext* context) 
00004 :   _handledEvents(0),
00005     _parent(NULL), _context(context), 
00006     _fg(White), _bg(Black), 
00007     _offset(0,0), _outer(0,0,0,0), _inner(0,0,0,0),
00008     _hidden(false), 
00009     _padding(0), _borderWidth(0), _borderColour(Black),
00010     _adjusting(false), 
00011     _dirtied(true), _dirtying(false), 
00012     _damaged(true), _damaging(false)
00013 {
00014 }
00015 
00016 void Widget::setParent(Widget* parent) {
00017     _parent = parent;
00018 }
00019 
00020 Widget *Widget::getParent() {
00021     return _parent;
00022 }
00023 
00024 // Location is referred to the offset
00025 void Widget::setLocation(int x, int y)
00026 {
00027     if( (_outer.x != (x+_offset.x())) || (_outer.y != y+_offset.y()) ) {
00028         _outer.x = x + _offset.x();
00029         _outer.y = y + _offset.y();
00030         damage();
00031         adjust();
00032     }
00033 }
00034 
00035 void Widget::setSize(int width, int height)
00036 {
00037     if(_outer.width != width || _outer.height != height) {
00038         _outer.width = width;
00039         _outer.height = height;
00040         damage();
00041         adjust();
00042     }
00043 }
00044 
00045 void Widget::setWidth(int width) {
00046     if(_outer.width != width) {
00047         _outer.width = width;
00048         damage();
00049         adjust();
00050     }
00051 }
00052 
00053 void Widget::setHeight(int height) {
00054     if(_outer.height != height) {
00055         _outer.height = height;
00056         damage();
00057         adjust();
00058     }
00059 }
00060 
00061 int Widget::x()
00062 {
00063     return _outer.x;
00064 }
00065 
00066 int Widget::y()
00067 {
00068     return _outer.y;
00069 }
00070 
00071 int Widget::height()
00072 {
00073     return _outer.height;
00074 }
00075 
00076 int Widget::width()
00077 {
00078     return _outer.width;
00079 }
00080 /**
00081 const Rectangle &Widget::outer() {
00082     return _outer;
00083 }
00084 
00085 const Rectangle &Widget::inner() {
00086     return _inner;
00087 }
00088 **/
00089     void Widget::setOffset(int x, int y) {
00090         _outer.x = _outer.x - _offset.x() + x;
00091         _outer.y = _outer.y - _offset.y() + y;
00092         _offset.x(x);
00093         _offset.y(y);
00094         damage();
00095         adjust();
00096     }
00097     
00098     int Widget::offsetX() {
00099         return _offset.x();
00100     }
00101     
00102     int Widget::offsetY() {
00103         return _offset.y();
00104     }
00105 
00106 
00107 void Widget::setForeground(uint16_t color)
00108 {
00109     if(_fg != color) {
00110         _fg = color;
00111         dirty();
00112     }
00113 }
00114 
00115 void Widget::setBackground(uint16_t color)
00116 {
00117     if(_bg != color) {
00118         _bg = color;
00119         dirty();
00120     }
00121 }
00122 
00123 
00124 /**
00125 * Set the amount of padding between the border and a widget edge
00126 **/
00127 void Widget::setPadding(int pixels)
00128 {
00129     if(_padding != pixels) {
00130         _padding = pixels;
00131         dirty();
00132     }
00133 }
00134 
00135 void Widget::setBorder(int width, uint16_t colour)
00136 {
00137     if(_borderWidth != width || _borderColour != colour) {
00138         _borderColour = colour;
00139         _borderWidth = width;
00140         dirty();
00141     }
00142 }
00143 
00144 void Widget::draw()
00145 {
00146     if(!_hidden && (_dirtied | _damaged)) {
00147         _draw();
00148         _dirtied = false;
00149         _damaged = false;
00150     }
00151 }
00152 
00153 void Widget::clear()
00154 {
00155     if(!_hidden) _clear();
00156 }
00157 
00158 void Widget::show()
00159 {
00160     _hidden = false;
00161     dirty();
00162     damage();
00163 }
00164 
00165 void Widget::hide()
00166 {
00167     _clear();
00168     _hidden = true;
00169 }
00170 
00171 bool Widget::isHidden()
00172 {
00173     return _hidden;
00174 }
00175 
00176 void Widget::setEventHandler(EventHandler* handler)
00177 {
00178     _handlers.appendOnce(handler);
00179     _reenumerateEvents();
00180 }
00181 
00182 void Widget::unsetEventHandler(EventHandler *handler)
00183 {
00184     _handlers.remove(handler);
00185     _reenumerateEvents();
00186 }
00187 
00188 bool Widget::_isEventTarget(Event e)
00189 {
00190     return !_hidden 
00191         && e.screenX >= _outer.x 
00192         && e.screenX <= (_outer.x+_outer.width) 
00193         && e.screenY >= _outer.y 
00194         && e.screenY <= (_outer.y+_outer.height);
00195 }
00196 
00197 void Widget::handleEvent(Event e) {
00198     e.target = this;
00199     if(_isEventTarget(e)) {
00200         _handlers.reset();
00201         EventHandler *h;
00202         while((h = _handlers.next()) != NULL) {
00203             if(h->type == e.type) {
00204                 h->handle(e);
00205             }
00206         }
00207     }
00208 }
00209 
00210 void Widget::_reenumerateEvents() {
00211         _reenumerateHandledEvents();
00212         if(_parent != NULL) {
00213             _parent->_reenumerateEvents();
00214         }
00215 }
00216 
00217 void Widget::_reenumerateHandledEvents() {
00218         _handledEvents = 0;
00219         EventHandler *h;
00220         LinkedListIterator<EventHandler> eit = _handlers.getIterator();
00221         while((h = eit.next()) != NULL) {
00222             _handledEvents |= h->type;
00223         }
00224 }
00225 
00226 uint16_t Widget::_getHandledEvents() {
00227     return _handledEvents;
00228 }   
00229 
00230 bool Widget::intersects(Widget *w)
00231 {
00232     return _outer.intersects(w->_outer);
00233 }
00234 
00235 void Widget::dirty()
00236 {
00237     if(!_dirtying) {
00238         _dirtying = true;
00239         _dirty();
00240         _dirtying = false;
00241     }
00242 }
00243 
00244 bool Widget::isDirty() {
00245     return _dirtied;
00246 }
00247 
00248 void Widget::dirtyAll()
00249 {
00250     _dirtied = true;
00251 }
00252 
00253 void Widget::damage() {
00254     if(!_damaging) {
00255         _damaging = true;
00256         _damage();
00257         _damaging = false;
00258     }
00259 }
00260 
00261 bool Widget::isDamaged() {
00262     return _damaged;
00263 }
00264 
00265 void Widget::adjust()
00266 {
00267     if(!_adjusting) {
00268         _adjusting = true;
00269         _adjust();
00270         _adjusting = false;
00271     }
00272 }
00273 
00274 GraphicsDisplay* Widget::display()
00275 {
00276     return _context->display();
00277 }
00278 
00279 /**********************************************************
00280 * Protected methods
00281 **********************************************************/
00282 void Widget::_draw() {
00283     GraphicsDisplay *d = display();
00284     //_clear();
00285     // Draw the border
00286     // Top
00287     d->fillrect(_outer.x, _outer.y, _outer.x+_outer.width, _outer.y+_borderWidth, _borderColour);
00288     // Bottom
00289     d->fillrect(_outer.x, _outer.y + _outer.height - _borderWidth, _outer.x + _outer.width, _outer.y+_outer.height, _borderColour);
00290     // Left
00291     d->fillrect(_outer.x, _outer.y, _outer.x+_borderWidth, _outer.y+_outer.height, _borderColour);
00292     // Right
00293     d->fillrect(_outer.x+_outer.width-_borderWidth, _outer.y, _outer.x+_outer.width, _outer.y+_outer.height, _borderColour);
00294 }
00295 
00296 void Widget::_clear() {
00297     display()->fillrect(_outer.x, _outer.y, _outer.x+_outer.width, _outer.y+_outer.height, display()->getBackground());
00298 }
00299 
00300 void Widget::_dirty()
00301 {
00302     _dirtied = true;
00303     if(_parent != NULL) {
00304         _parent->dirty();
00305     }
00306 }
00307 
00308 void Widget::_damage()
00309 {
00310     _damaged = true;
00311     if(_parent != NULL) {
00312         _parent->dirty();
00313     }
00314 }
00315 
00316 void Widget::_adjust() {
00317     // Recalculate size of inner Rect
00318     _inner.resize(_outer, _borderWidth + _padding);
00319 }