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