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