1 /* _______ __ __ __ ______ __ __ _______ __ __ 2 * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\ 3 * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / / 4 * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / / 5 * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / / 6 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ / 7 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/ 8 * 9 * Copyright (c) 2004, 2005 darkbits Js_./ 10 * Per Larsson a.k.a finalman _RqZ{a<^_aa 11 * Olof Naess�n a.k.a jansem/yakslem _asww7!uY`> )\a// 12 * _Qhm`] _f "'c 1!5m 13 * Visit: http://guichan.darkbits.org )Qk<P ` _: :+' .' "{[ 14 * .)j(] .d_/ '-( P . S 15 * License: (BSD) <Td/Z <fP"5(\"??"\a. .L 16 * Redistribution and use in source and _dV>ws?a-?' ._/L #' 17 * binary forms, with or without )4d[#7r, . ' )d`)[ 18 * modification, are permitted provided _Q-5'5W..j/?' -?!\)cam' 19 * that the following conditions are met: j<<WP+k/);. _W=j f 20 * 1. Redistributions of source code must .$%w\/]Q . ."' . mj$ 21 * retain the above copyright notice, ]E.pYY(Q]>. a J@\ 22 * this list of conditions and the j(]1u<sE"L,. . ./^ ]{a 23 * following disclaimer. 4'_uomm\. )L);-4 (3= 24 * 2. Redistributions in binary form must )_]X{Z('a_"a7'<a"a, ]"[ 25 * reproduce the above copyright notice, #}<]m7`Za??4,P-"'7. ).m 26 * this list of conditions and the ]d2e)Q(<Q( ?94 b- LQ/ 27 * following disclaimer in the <B!</]C)d_, '(<' .f. =C+m 28 * documentation and/or other materials .Z!=J ]e []('-4f _ ) -.)m]' 29 * provided with the distribution. .w[5]' _[ /.)_-"+? _/ <W" 30 * 3. Neither the name of Guichan nor the :$we` _! + _/ . j? 31 * names of its contributors may be used =3)= _f (_yQmWW$#( " 32 * to endorse or promote products derived - W, sQQQQmZQ#Wwa].. 33 * from this software without specific (js, \[QQW$QWW#?!V"". 34 * prior written permission. ]y:.<\.. . 35 * -]n w/ ' [. 36 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT )/ )/ ! 37 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY < (; sac , ' 38 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, ]^ .- % 39 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF c < r 40 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR aga< <La 41 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 5% )P'-3L 42 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR _bQf` y`..)a 43 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ,J?4P'.P"_(\?d'., 44 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES _Pa,)!f/<[]/ ?" 45 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT _2-..:. .r+_,.. . 46 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ?a.<%"' " -'.a_ _, 47 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ^ 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 49 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 50 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 51 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 52 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 53 */ 54 55 /* 56 * For comments regarding functions please see the header file. 57 */ 58 #include <assert.h> 59 #include "guichan/exception.h" 60 #include "guichan/focushandler.h" 61 #include "guichan/gui.h" 62 #include "guichan/key.h" 63 64 namespace gcn 65 { Gui()66 Gui::Gui() 67 { 68 mTop = NULL; 69 mInput = NULL; 70 mGraphics = NULL; 71 mFocusHandler = new FocusHandler(); 72 mTopHasMouse = false; 73 mTabbing = true; 74 mUseDirtyDrawing = true; 75 } 76 ~Gui()77 Gui::~Gui() 78 { 79 if (Widget::widgetExists(mTop)) 80 { 81 setTop(NULL); 82 } 83 84 delete mFocusHandler; 85 } 86 setTop(Widget * top)87 void Gui::setTop(Widget* top) 88 { 89 if (mTop) 90 { 91 mTop->_setFocusHandler(NULL); 92 } 93 if (top) 94 { 95 top->_setFocusHandler(mFocusHandler); 96 top->setDirty(true); 97 } 98 99 mTop = top; 100 } 101 getTop() const102 Widget* Gui::getTop() const 103 { 104 return mTop; 105 } 106 setGraphics(Graphics * graphics)107 void Gui::setGraphics(Graphics* graphics) 108 { 109 mGraphics = graphics; 110 } 111 getGraphics() const112 Graphics* Gui::getGraphics() const 113 { 114 return mGraphics; 115 } 116 setInput(Input * input)117 void Gui::setInput(Input* input) 118 { 119 mInput = input; 120 } 121 getInput() const122 Input* Gui::getInput() const 123 { 124 return mInput; 125 } 126 logic()127 void Gui::logic() 128 { 129 if (!mTop) 130 { 131 assert(!"No top widget set"); 132 //throw GCN_EXCEPTION("No top widget set"); 133 } 134 135 if (mInput) 136 { 137 mInput->_pollInput(); 138 139 while (!mInput->isMouseQueueEmpty()) 140 { 141 MouseInput mi = mInput->dequeueMouseInput(); 142 143 // Send mouse input to every widget that has the mouse. 144 if (mi.x > 0 && mi.y > 0 145 && mTop->getDimension().isPointInRect(mi.x, mi.y)) 146 { 147 if (!mTop->hasMouse()) 148 { 149 mTop->_mouseInMessage(); 150 } 151 152 MouseInput mio = mi; 153 mio.x -= mTop->getX(); 154 mio.y -= mTop->getY(); 155 mTop->_mouseInputMessage(mio); 156 } 157 else if (mTop->hasMouse()) 158 { 159 mTop->_mouseOutMessage(); 160 } 161 162 Widget* f = mFocusHandler->getFocused(); 163 Widget* d = mFocusHandler->getDragged(); 164 165 // If the focused widget doesn't have the mouse, 166 // send the mouse input to the focused widget. 167 if (f != NULL && !f->hasMouse()) 168 { 169 int xOffset, yOffset; 170 f->getAbsolutePosition(xOffset, yOffset); 171 172 MouseInput mio = mi; 173 mio.x -= xOffset; 174 mio.y -= yOffset; 175 176 f->_mouseInputMessage(mio); 177 } 178 179 // If the dragged widget is different from the focused 180 // widget, send the mouse input to the dragged widget. 181 if (d != NULL && d != f && !d->hasMouse()) 182 { 183 int xOffset, yOffset; 184 d->getAbsolutePosition(xOffset, yOffset); 185 186 MouseInput mio = mi; 187 mio.x -= xOffset; 188 mio.y -= yOffset; 189 190 d->_mouseInputMessage(mio); 191 } 192 193 mFocusHandler->applyChanges(); 194 195 } // end while 196 197 while (!mInput->isKeyQueueEmpty()) 198 { 199 KeyInput ki = mInput->dequeueKeyInput(); 200 201 if (mTabbing 202 && ki.getKey().getValue() == Key::K_TAB 203 && ki.getType() == KeyInput::PRESS) 204 { 205 if (ki.getKey().isShiftPressed()) 206 { 207 mFocusHandler->tabPrevious(); 208 } 209 else 210 { 211 mFocusHandler->tabNext(); 212 } 213 } 214 else 215 { 216 bool keyProcessed = false; 217 218 // Send key inputs to the focused widgets 219 if (mFocusHandler->getFocused()) 220 { 221 if (mFocusHandler->getFocused()->isFocusable()) 222 { 223 keyProcessed = mFocusHandler->getFocused()->_keyInputMessage(ki); 224 } 225 else 226 { 227 mFocusHandler->focusNone(); 228 } 229 } 230 231 if (!keyProcessed) 232 { 233 mFocusHandler->checkHotKey(ki); 234 } 235 } 236 237 mFocusHandler->applyChanges(); 238 239 } // end while 240 241 } // end if 242 243 mTop->logic(); 244 } 245 draw(Widget * top)246 void Gui::draw(Widget* top) 247 { 248 if (!top) 249 { 250 assert(!"No top widget set"); 251 //throw GCN_EXCEPTION("No top widget set"); 252 } 253 if (!mGraphics) 254 { 255 assert(!"No graphics set"); 256 //throw GCN_EXCEPTION("No graphics set"); 257 } 258 259 if (!mUseDirtyDrawing || top->getDirty()) 260 { 261 mGraphics->_beginDraw(); 262 263 // If top has a border, 264 // draw it before drawing top 265 if (top->getBorderSize() > 0) 266 { 267 Rectangle rec = top->getDimension(); 268 rec.x -= top->getBorderSize(); 269 rec.y -= top->getBorderSize(); 270 rec.width += 2 * top->getBorderSize(); 271 rec.height += 2 * top->getBorderSize(); 272 mGraphics->pushClipArea(rec); 273 top->drawBorder(mGraphics); 274 mGraphics->popClipArea(); 275 } 276 277 mGraphics->pushClipArea(top->getDimension()); 278 top->draw(mGraphics); 279 top->setDirty(false); 280 mGraphics->popClipArea(); 281 282 mGraphics->_endDraw(); 283 } 284 } 285 draw()286 void Gui::draw() 287 { 288 draw(mTop); 289 } 290 focusNone()291 void Gui::focusNone() 292 { 293 mFocusHandler->focusNone(); 294 } 295 setTabbingEnabled(bool tabbing)296 void Gui::setTabbingEnabled(bool tabbing) 297 { 298 mTabbing = tabbing; 299 } 300 isTabbingEnabled()301 bool Gui::isTabbingEnabled() 302 { 303 return mTabbing; 304 } 305 setUseDirtyDrawing(bool useDirtyDrawing)306 void Gui::setUseDirtyDrawing(bool useDirtyDrawing) 307 { 308 mUseDirtyDrawing = useDirtyDrawing; 309 } 310 } 311