CGUIWindow.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. // Copyright (C) 2002-2012 Nikolaus Gebhardt
  2. // This file is part of the "Irrlicht Engine".
  3. // For conditions of distribution and use, see copyright notice in irrlicht.h
  4. #include "CGUIWindow.h"
  5. #ifdef _IRR_COMPILE_WITH_GUI_
  6. #include "IGUISkin.h"
  7. #include "IGUIEnvironment.h"
  8. #include "IVideoDriver.h"
  9. #include "IGUIButton.h"
  10. #include "IGUIFont.h"
  11. #include "IGUIFontBitmap.h"
  12. namespace irr
  13. {
  14. namespace gui
  15. {
  16. //! constructor
  17. CGUIWindow::CGUIWindow(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle)
  18. : IGUIWindow(environment, parent, id, rectangle), Dragging(false), IsDraggable(true), DrawBackground(true), DrawTitlebar(true), IsActive(false)
  19. {
  20. #ifdef _DEBUG
  21. setDebugName("CGUIWindow");
  22. #endif
  23. IGUISkin* skin = 0;
  24. if (environment)
  25. skin = environment->getSkin();
  26. CurrentIconColor = video::SColor(255,255,255,255);
  27. s32 buttonw = 15;
  28. if (skin)
  29. {
  30. buttonw = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH);
  31. }
  32. s32 posx = RelativeRect.getWidth() - buttonw - 4;
  33. CloseButton = Environment->addButton(core::rect<s32>(posx, 3, posx + buttonw, 3 + buttonw), this, -1,
  34. L"", skin ? skin->getDefaultText(EGDT_WINDOW_CLOSE) : L"Close" );
  35. CloseButton->setSubElement(true);
  36. CloseButton->setTabStop(false);
  37. CloseButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
  38. posx -= buttonw + 2;
  39. RestoreButton = Environment->addButton(core::rect<s32>(posx, 3, posx + buttonw, 3 + buttonw), this, -1,
  40. L"", skin ? skin->getDefaultText(EGDT_WINDOW_RESTORE) : L"Restore" );
  41. RestoreButton->setVisible(false);
  42. RestoreButton->setSubElement(true);
  43. RestoreButton->setTabStop(false);
  44. RestoreButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
  45. posx -= buttonw + 2;
  46. MinButton = Environment->addButton(core::rect<s32>(posx, 3, posx + buttonw, 3 + buttonw), this, -1,
  47. L"", skin ? skin->getDefaultText(EGDT_WINDOW_MINIMIZE) : L"Minimize" );
  48. MinButton->setVisible(false);
  49. MinButton->setSubElement(true);
  50. MinButton->setTabStop(false);
  51. MinButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
  52. MinButton->grab();
  53. RestoreButton->grab();
  54. CloseButton->grab();
  55. // this element is a tab group
  56. setTabGroup(true);
  57. setTabStop(true);
  58. setTabOrder(-1);
  59. refreshSprites();
  60. updateClientRect();
  61. }
  62. //! destructor
  63. CGUIWindow::~CGUIWindow()
  64. {
  65. if (MinButton)
  66. MinButton->drop();
  67. if (RestoreButton)
  68. RestoreButton->drop();
  69. if (CloseButton)
  70. CloseButton->drop();
  71. }
  72. void CGUIWindow::refreshSprites()
  73. {
  74. if (!Environment)
  75. return;
  76. IGUISkin* skin = Environment->getSkin();
  77. if ( !skin )
  78. return;
  79. IGUISpriteBank* sprites = skin->getSpriteBank();
  80. if ( !sprites )
  81. return;
  82. CurrentIconColor = skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL);
  83. if (sprites)
  84. {
  85. CloseButton->setSpriteBank(sprites);
  86. CloseButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_CLOSE), CurrentIconColor);
  87. CloseButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_CLOSE), CurrentIconColor);
  88. RestoreButton->setSpriteBank(sprites);
  89. RestoreButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_RESTORE), CurrentIconColor);
  90. RestoreButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_RESTORE), CurrentIconColor);
  91. MinButton->setSpriteBank(sprites);
  92. MinButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_MINIMIZE), CurrentIconColor);
  93. MinButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_MINIMIZE), CurrentIconColor);
  94. }
  95. }
  96. //! called if an event happened.
  97. bool CGUIWindow::OnEvent(const SEvent& event)
  98. {
  99. if (isEnabled())
  100. {
  101. switch(event.EventType)
  102. {
  103. case EET_GUI_EVENT:
  104. if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST)
  105. {
  106. Dragging = false;
  107. IsActive = false;
  108. }
  109. else
  110. if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUSED)
  111. {
  112. if (Parent && ((event.GUIEvent.Caller == this) || isMyChild(event.GUIEvent.Caller)))
  113. {
  114. Parent->bringToFront(this);
  115. IsActive = true;
  116. }
  117. else
  118. {
  119. IsActive = false;
  120. }
  121. }
  122. else
  123. if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED)
  124. {
  125. if (event.GUIEvent.Caller == CloseButton)
  126. {
  127. if (Parent)
  128. {
  129. // send close event to parent
  130. SEvent e;
  131. e.EventType = EET_GUI_EVENT;
  132. e.GUIEvent.Caller = this;
  133. e.GUIEvent.Element = 0;
  134. e.GUIEvent.EventType = EGET_ELEMENT_CLOSED;
  135. // if the event was not absorbed
  136. if (!Parent->OnEvent(e))
  137. remove();
  138. return true;
  139. }
  140. else
  141. {
  142. remove();
  143. return true;
  144. }
  145. }
  146. }
  147. break;
  148. case EET_MOUSE_INPUT_EVENT:
  149. switch(event.MouseInput.Event)
  150. {
  151. case EMIE_LMOUSE_PRESSED_DOWN:
  152. DragStart.X = event.MouseInput.X;
  153. DragStart.Y = event.MouseInput.Y;
  154. Dragging = IsDraggable;
  155. if (Parent)
  156. Parent->bringToFront(this);
  157. return true;
  158. case EMIE_LMOUSE_LEFT_UP:
  159. Dragging = false;
  160. return true;
  161. case EMIE_MOUSE_MOVED:
  162. if (!event.MouseInput.isLeftPressed())
  163. Dragging = false;
  164. if (Dragging)
  165. {
  166. // gui window should not be dragged outside its parent
  167. if (Parent &&
  168. (event.MouseInput.X < Parent->getAbsolutePosition().UpperLeftCorner.X +1 ||
  169. event.MouseInput.Y < Parent->getAbsolutePosition().UpperLeftCorner.Y +1 ||
  170. event.MouseInput.X > Parent->getAbsolutePosition().LowerRightCorner.X -1 ||
  171. event.MouseInput.Y > Parent->getAbsolutePosition().LowerRightCorner.Y -1))
  172. return true;
  173. move(core::position2d<s32>(event.MouseInput.X - DragStart.X, event.MouseInput.Y - DragStart.Y));
  174. DragStart.X = event.MouseInput.X;
  175. DragStart.Y = event.MouseInput.Y;
  176. return true;
  177. }
  178. break;
  179. default:
  180. break;
  181. }
  182. default:
  183. break;
  184. }
  185. }
  186. return IGUIElement::OnEvent(event);
  187. }
  188. //! Updates the absolute position.
  189. void CGUIWindow::updateAbsolutePosition()
  190. {
  191. IGUIElement::updateAbsolutePosition();
  192. }
  193. //! draws the element and its children
  194. void CGUIWindow::draw()
  195. {
  196. if (IsVisible)
  197. {
  198. IGUISkin* skin = Environment->getSkin();
  199. // update each time because the skin is allowed to change this always.
  200. updateClientRect();
  201. if ( CurrentIconColor != skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL) )
  202. refreshSprites();
  203. core::rect<s32> rect = AbsoluteRect;
  204. // draw body fast
  205. if (DrawBackground)
  206. {
  207. rect = skin->draw3DWindowBackground(this, DrawTitlebar,
  208. skin->getColor(IsActive ? EGDC_ACTIVE_BORDER : EGDC_INACTIVE_BORDER),
  209. AbsoluteRect, &AbsoluteClippingRect);
  210. if (DrawTitlebar && Text.size())
  211. {
  212. rect.UpperLeftCorner.X += skin->getSize(EGDS_TITLEBARTEXT_DISTANCE_X);
  213. rect.UpperLeftCorner.Y += skin->getSize(EGDS_TITLEBARTEXT_DISTANCE_Y);
  214. rect.LowerRightCorner.X -= skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) + 5;
  215. IGUIFont* font = skin->getFont(EGDF_WINDOW);
  216. if (font)
  217. {
  218. font->draw(Text.c_str(), rect,
  219. skin->getColor(IsActive ? EGDC_ACTIVE_CAPTION:EGDC_INACTIVE_CAPTION),
  220. false, true, &AbsoluteClippingRect);
  221. }
  222. }
  223. }
  224. }
  225. IGUIElement::draw();
  226. }
  227. //! Returns pointer to the close button
  228. IGUIButton* CGUIWindow::getCloseButton() const
  229. {
  230. return CloseButton;
  231. }
  232. //! Returns pointer to the minimize button
  233. IGUIButton* CGUIWindow::getMinimizeButton() const
  234. {
  235. return MinButton;
  236. }
  237. //! Returns pointer to the maximize button
  238. IGUIButton* CGUIWindow::getMaximizeButton() const
  239. {
  240. return RestoreButton;
  241. }
  242. //! Returns true if the window is draggable, false if not
  243. bool CGUIWindow::isDraggable() const
  244. {
  245. return IsDraggable;
  246. }
  247. //! Sets whether the window is draggable
  248. void CGUIWindow::setDraggable(bool draggable)
  249. {
  250. IsDraggable = draggable;
  251. if (Dragging && !IsDraggable)
  252. Dragging = false;
  253. }
  254. //! Set if the window background will be drawn
  255. void CGUIWindow::setDrawBackground(bool draw)
  256. {
  257. DrawBackground = draw;
  258. }
  259. //! Get if the window background will be drawn
  260. bool CGUIWindow::getDrawBackground() const
  261. {
  262. return DrawBackground;
  263. }
  264. //! Set if the window titlebar will be drawn
  265. void CGUIWindow::setDrawTitlebar(bool draw)
  266. {
  267. DrawTitlebar = draw;
  268. }
  269. //! Get if the window titlebar will be drawn
  270. bool CGUIWindow::getDrawTitlebar() const
  271. {
  272. return DrawTitlebar;
  273. }
  274. void CGUIWindow::updateClientRect()
  275. {
  276. if (! DrawBackground )
  277. {
  278. ClientRect = core::rect<s32>(0,0, AbsoluteRect.getWidth(), AbsoluteRect.getHeight());
  279. return;
  280. }
  281. IGUISkin* skin = Environment->getSkin();
  282. skin->draw3DWindowBackground(this, DrawTitlebar,
  283. skin->getColor(IsActive ? EGDC_ACTIVE_BORDER : EGDC_INACTIVE_BORDER),
  284. AbsoluteRect, &AbsoluteClippingRect, &ClientRect);
  285. ClientRect -= AbsoluteRect.UpperLeftCorner;
  286. }
  287. //! Returns the rectangle of the drawable area (without border, without titlebar and without scrollbars)
  288. core::rect<s32> CGUIWindow::getClientRect() const
  289. {
  290. return ClientRect;
  291. }
  292. //! Writes attributes of the element.
  293. void CGUIWindow::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
  294. {
  295. IGUIWindow::serializeAttributes(out,options);
  296. out->addBool("IsDraggable", IsDraggable);
  297. out->addBool("DrawBackground", DrawBackground);
  298. out->addBool("DrawTitlebar", DrawTitlebar);
  299. // Currently we can't just serialize attributes of sub-elements.
  300. // To do this we either
  301. // a) allow further serialization after attribute serialiation (second function, callback or event)
  302. // b) add an IGUIElement attribute
  303. // c) extend the attribute system to allow attributes to have sub-attributes
  304. // We just serialize the most important info for now until we can do one of the above solutions.
  305. out->addBool("IsCloseVisible", CloseButton->isVisible());
  306. out->addBool("IsMinVisible", MinButton->isVisible());
  307. out->addBool("IsRestoreVisible", RestoreButton->isVisible());
  308. }
  309. //! Reads attributes of the element
  310. void CGUIWindow::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
  311. {
  312. IGUIWindow::deserializeAttributes(in,options);
  313. Dragging = false;
  314. IsActive = false;
  315. IsDraggable = in->getAttributeAsBool("IsDraggable");
  316. DrawBackground = in->getAttributeAsBool("DrawBackground");
  317. DrawTitlebar = in->getAttributeAsBool("DrawTitlebar");
  318. CloseButton->setVisible(in->getAttributeAsBool("IsCloseVisible"));
  319. MinButton->setVisible(in->getAttributeAsBool("IsMinVisible"));
  320. RestoreButton->setVisible(in->getAttributeAsBool("IsRestoreVisible"));
  321. updateClientRect();
  322. }
  323. } // end namespace gui
  324. } // end namespace irr
  325. #endif // _IRR_COMPILE_WITH_GUI_