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/widgets/window.h" 60 #include "guichan/exception.h" 61 #include "guichan/mouseinput.h" 62 63 namespace gcn 64 { Window()65 Window::Window() 66 { 67 mContent = nullptr; 68 mMouseDrag = false; 69 setBorderSize(1); 70 setPadding(2); 71 setTitleBarHeight(16); 72 setAlignment(Graphics::CENTER); 73 addMouseListener(this); 74 setMovable(true); 75 setOpaque(true); 76 } 77 Window(const std::string & caption)78 Window::Window(const std::string& caption) 79 { 80 mContent = nullptr; 81 mMouseDrag = false; 82 setCaption(caption); 83 setBorderSize(1); 84 setPadding(2); 85 setTitleBarHeight(16); 86 setAlignment(Graphics::CENTER); 87 addMouseListener(this); 88 setMovable(true); 89 setOpaque(true); 90 } 91 Window(Widget * content,const std::string & caption)92 Window::Window(Widget* content, const std::string& caption) 93 { 94 mContent = nullptr; 95 mMouseDrag = false; 96 setContent(content); 97 setCaption(caption); 98 setBorderSize(1); 99 setPadding(2); 100 setTitleBarHeight(16); 101 setAlignment(Graphics::CENTER); 102 addMouseListener(this); 103 setMovable(true); 104 setOpaque(true); 105 } 106 ~Window()107 Window::~Window() 108 { 109 setContent(nullptr); 110 } 111 setPadding(unsigned int padding)112 void Window::setPadding(unsigned int padding) 113 { 114 mPadding = padding; 115 repositionContent(); 116 } 117 getPadding() const118 unsigned int Window::getPadding() const 119 { 120 return mPadding; 121 } 122 setTitleBarHeight(unsigned int height)123 void Window::setTitleBarHeight(unsigned int height) 124 { 125 mTitleBarHeight = height; 126 repositionContent(); 127 } 128 getTitleBarHeight()129 unsigned int Window::getTitleBarHeight() 130 { 131 return mTitleBarHeight; 132 } 133 _announceDeath(Widget *)134 void Window:: _announceDeath(Widget *) 135 { 136 mContent = nullptr; 137 } 138 setContent(Widget * widget)139 void Window::setContent(Widget* widget) 140 { 141 if (getContent() != nullptr) 142 { 143 getContent()->_setParent(nullptr); 144 getContent()->_setFocusHandler(nullptr); 145 } 146 147 if (widget != nullptr) 148 { 149 widget->_setParent(this); 150 widget->_setFocusHandler(_getFocusHandler()); 151 } 152 153 mContent = widget; 154 repositionContent(); 155 } 156 getContent() const157 Widget* Window::getContent() const 158 { 159 return mContent; 160 } 161 setCaption(const std::string & caption)162 void Window::setCaption(const std::string& caption) 163 { 164 mCaption = caption; 165 setDirty(true); 166 } 167 getCaption() const168 const std::string& Window::getCaption() const 169 { 170 return mCaption; 171 } 172 setAlignment(unsigned int alignment)173 void Window::setAlignment(unsigned int alignment) 174 { 175 mAlignment = alignment; 176 } 177 getAlignment() const178 unsigned int Window::getAlignment() const 179 { 180 return mAlignment; 181 } 182 draw(Graphics * graphics)183 void Window::draw(Graphics* graphics) 184 { 185 Color faceColor = getBaseColor(); 186 Color highlightColor, shadowColor; 187 int alpha = getBaseColor().a; 188 189 highlightColor = faceColor + 0x303030; 190 highlightColor.a = alpha; 191 shadowColor = faceColor - 0x303030; 192 shadowColor.a = alpha; 193 194 Rectangle d = getContentDimension(); 195 196 // Fill the background around the content 197 graphics->setColor(faceColor); 198 // Fill top 199 graphics->fillRectangle(Rectangle(0,0,getWidth(),d.y - 1)); 200 // Fill left 201 graphics->fillRectangle(Rectangle(0,d.y - 1, d.x - 1, getHeight() - d.y + 1)); 202 // Fill right 203 graphics->fillRectangle(Rectangle(d.x + d.width + 1, 204 d.y - 1, 205 getWidth() - d.x - d.width - 1, 206 getHeight() - d.y + 1)); 207 // Fill bottom 208 graphics->fillRectangle(Rectangle(d.x - 1, 209 d.y + d.height + 1, 210 d.width + 2, 211 getHeight() - d.height - d.y - 1)); 212 213 if (isOpaque()) 214 { 215 graphics->fillRectangle(d); 216 } 217 218 // Construct a rectangle one pixel bigger than the content 219 d.x -= 1; 220 d.y -= 1; 221 d.width += 2; 222 d.height += 2; 223 224 // Draw a border around the content 225 graphics->setColor(shadowColor); 226 // Top line 227 graphics->drawLine(d.x, 228 d.y, 229 d.x + d.width - 2, 230 d.y); 231 232 // Left line 233 graphics->drawLine(d.x, 234 d.y + 1, 235 d.x, 236 d.y + d.height - 1); 237 238 graphics->setColor(highlightColor); 239 // Right line 240 graphics->drawLine(d.x + d.width - 1, 241 d.y, 242 d.x + d.width - 1, 243 d.y + d.height - 2); 244 // Bottom line 245 graphics->drawLine(d.x + 1, 246 d.y + d.height - 1, 247 d.x + d.width - 1, 248 d.y + d.height - 1); 249 250 drawContent(graphics); 251 252 int textX = 0; 253 int textY; 254 textY = ((int)getTitleBarHeight() - getFont()->getHeight()) / 2; 255 switch (getAlignment()) 256 { 257 case Graphics::LEFT: 258 textX = 4; 259 break; 260 case Graphics::CENTER: 261 textX = getWidth() / 2; 262 break; 263 case Graphics::RIGHT: 264 textX = getWidth() - 4; 265 break; 266 default: 267 //throw GCN_EXCEPTION("Unknown alignment."); 268 assert(!"Unknown alignment."); 269 } 270 271 graphics->setColor(getForegroundColor()); 272 graphics->setFont(getFont()); 273 graphics->drawText(getCaption(), textX, textY, getAlignment()); 274 } 275 drawBorder(Graphics * graphics)276 void Window::drawBorder(Graphics* graphics) 277 { 278 Color faceColor = getBaseColor(); 279 Color highlightColor, shadowColor; 280 int alpha = getBaseColor().a; 281 int width = getWidth() + getBorderSize() * 2 - 1; 282 int height = getHeight() + getBorderSize() * 2 - 1; 283 highlightColor = faceColor + 0x303030; 284 highlightColor.a = alpha; 285 shadowColor = faceColor - 0x303030; 286 shadowColor.a = alpha; 287 288 unsigned int i; 289 for (i = 0; i < getBorderSize(); ++i) 290 { 291 graphics->setColor(highlightColor); 292 graphics->drawLine(i,i, width - i, i); 293 graphics->drawLine(i,i + 1, i, height - i - 1); 294 graphics->setColor(shadowColor); 295 graphics->drawLine(width - i,i + 1, width - i, height - i); 296 graphics->drawLine(i,height - i, width - i - 1, height - i); 297 } 298 } 299 drawContent(Graphics * graphics)300 void Window::drawContent(Graphics* graphics) 301 { 302 if (getContent() != nullptr) 303 { 304 graphics->pushClipArea(getContentDimension()); 305 graphics->pushClipArea(Rectangle(0, 0, getContent()->getWidth(), 306 getContent()->getHeight())); 307 getContent()->draw(graphics); 308 graphics->popClipArea(); 309 graphics->popClipArea(); 310 } 311 } 312 mousePress(int x,int y,int button)313 void Window::mousePress(int x, int y, int button) 314 { 315 if (getParent() != nullptr) 316 { 317 getParent()->moveToTop(this); 318 } 319 320 if (isMovable() && hasMouse() 321 && y < (int)(getTitleBarHeight() + getPadding()) && button == 1) 322 { 323 mMouseDrag = true; 324 mMouseXOffset = x; 325 mMouseYOffset = y; 326 } 327 } 328 mouseRelease(int,int,int button)329 void Window::mouseRelease(int, int, int button) 330 { 331 if (button == 1) 332 { 333 mMouseDrag = false; 334 } 335 } 336 mouseMotion(int x,int y)337 void Window::mouseMotion(int x, int y) 338 { 339 if (mMouseDrag && isMovable()) 340 { 341 setPosition(x - mMouseXOffset + getX(), 342 y - mMouseYOffset + getY()); 343 setDirty(true); 344 } 345 } 346 moveToTop(Widget * widget)347 void Window::moveToTop(Widget* widget) 348 { 349 if (widget != getContent()) 350 { 351 //throw GCN_EXCEPTION("Widget is not content of window."); 352 assert(!"Widget is not content of window."); 353 } 354 } 355 moveToBottom(Widget * widget)356 void Window::moveToBottom(Widget* widget) 357 { 358 if (widget != getContent()) 359 { 360 //throw GCN_EXCEPTION("Widget is not content of window"); 361 assert(!"Widget is not content of window."); 362 } 363 } 364 getDrawSize(int & width,int & height,Widget * widget)365 void Window::getDrawSize(int& width, int& height, Widget* widget) 366 { 367 if (widget != getContent()) 368 { 369 //throw GCN_EXCEPTION("Widget is not content of window"); 370 assert(!"Widget is not content of window."); 371 } 372 373 Rectangle d = getContentDimension(); 374 width = d.width; 375 height = d.height; 376 } 377 repositionContent()378 void Window::repositionContent() 379 { 380 if (getContent() == nullptr) 381 { 382 return; 383 } 384 385 Rectangle d = getContentDimension(); 386 mContent->setPosition(d.x, d.y); 387 } 388 getContentDimension()389 Rectangle Window::getContentDimension() 390 { 391 return Rectangle(getPadding(), 392 getTitleBarHeight(), 393 getWidth() - getPadding() * 2, 394 getHeight() - getPadding() - getTitleBarHeight()); 395 } 396 setMovable(bool movable)397 void Window::setMovable(bool movable) 398 { 399 mMovable = movable; 400 } 401 isMovable() const402 bool Window::isMovable() const 403 { 404 return mMovable; 405 } 406 resizeToContent()407 void Window::resizeToContent() 408 { 409 if (getContent() != nullptr) 410 { 411 setSize(getContent()->getWidth() + 2*getPadding(), 412 getContent()->getHeight() + getPadding() 413 + getTitleBarHeight()); 414 } 415 } 416 _mouseInputMessage(const MouseInput & mouseInput)417 void Window::_mouseInputMessage(const MouseInput &mouseInput) 418 { 419 BasicContainer::_mouseInputMessage(mouseInput); 420 421 if (getContent() != nullptr) 422 { 423 if (getContentDimension().isPointInRect(mouseInput.x, mouseInput.y) && 424 getContent()->getDimension().isPointInRect(mouseInput.x, mouseInput.y)) 425 { 426 if (!getContent()->hasMouse()) 427 { 428 getContent()->_mouseInMessage(); 429 } 430 431 MouseInput mi = mouseInput; 432 mi.x -= getContent()->getX(); 433 mi.y -= getContent()->getY(); 434 getContent()->_mouseInputMessage(mi); 435 } 436 else if (getContent()->hasMouse()) 437 { 438 getContent()->_mouseOutMessage(); 439 } 440 } 441 } 442 _mouseOutMessage()443 void Window::_mouseOutMessage() 444 { 445 BasicContainer::_mouseOutMessage(); 446 447 if (getContent() != nullptr && getContent()->hasMouse()) 448 { 449 getContent()->_mouseOutMessage(); 450 } 451 } 452 _setFocusHandler(FocusHandler * focusHandler)453 void Window::_setFocusHandler(FocusHandler *focusHandler) 454 { 455 if (getContent() != nullptr) 456 { 457 getContent()->_setFocusHandler(focusHandler); 458 } 459 460 BasicContainer::_setFocusHandler(focusHandler); 461 } 462 setOpaque(bool opaque)463 void Window::setOpaque(bool opaque) 464 { 465 mOpaque = opaque; 466 } 467 isOpaque()468 bool Window::isOpaque() 469 { 470 return mOpaque; 471 } 472 logic()473 void Window::logic() 474 { 475 if (getContent() != nullptr) 476 { 477 getContent()->logic(); 478 } 479 } 480 setDirty(bool dirty)481 void Window::setDirty(bool dirty) 482 { 483 if (mContent != nullptr) 484 { 485 mContent->setDirty(dirty); 486 } 487 mDirty = dirty; 488 } 489 getDirty() const490 bool Window::getDirty() const 491 { 492 if (mDirty == true) 493 { 494 return true; 495 } 496 497 if (mContent != nullptr && mContent->getDirty()) 498 { 499 return true; 500 } 501 502 return false; 503 } 504 } 505