]> git.lizzy.rs Git - irrlicht.git/blob - tools/GUIEditor/CGUIPanel.cpp
Merging r6196 through r6248 from trunk to ogl-es branch
[irrlicht.git] / tools / GUIEditor / CGUIPanel.cpp
1 // Copyright 2006-2012 Asger Feldthaus\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 /*\r
6         Originally Klasker's but I've messed around with it lots - Gaz\r
7 */\r
8 \r
9 #include "CGUIPanel.h"\r
10 #include "IGUIEnvironment.h"\r
11 #include "IGUIScrollBar.h"\r
12 #include "IGUITabControl.h"\r
13 #include "IVideoDriver.h"\r
14 \r
15 const int SCROLL_BAR_SIZE = 16; // Scroll bars are 16 pixels wide\r
16 const int BORDER_WIDTH = 2;\r
17 \r
18 namespace irr\r
19 {\r
20 namespace gui\r
21 {\r
22 \r
23 CGUIPanel::CGUIPanel(IGUIEnvironment* environment, IGUIElement* parent, s32 id, const core::rect<s32>& rectangle,\r
24                         bool border, E_SCROLL_BAR_MODE vMode, E_SCROLL_BAR_MODE hMode)\r
25         : IGUIElement(EGUIET_ELEMENT, environment, parent, id, rectangle),\r
26         VScrollBar(0), HScrollBar(0), ClipPane(0), InnerPane(0),\r
27         VScrollBarMode(vMode), HScrollBarMode(hMode), NeedsUpdate(true), Border(border)\r
28 {\r
29         #ifdef _DEBUG\r
30         setDebugName("CGUIPanel");\r
31         #endif\r
32 \r
33         s32 width = rectangle.getWidth();\r
34         s32 height = rectangle.getHeight();\r
35 \r
36         core::rect<s32> rct = core::rect<s32>(width - SCROLL_BAR_SIZE,0, width, height);\r
37 \r
38         VScrollBar = environment->addScrollBar(false, rct, 0, id);\r
39         VScrollBar->setSubElement(true);\r
40         VScrollBar->setTabStop(false);\r
41         VScrollBar->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);\r
42         VScrollBar->grab();\r
43         IGUIElement::addChild(VScrollBar);\r
44 \r
45         rct = core::rect<s32>(0, height - SCROLL_BAR_SIZE, width - SCROLL_BAR_SIZE,height );\r
46 \r
47         HScrollBar = environment->addScrollBar(true, rct, 0, id);\r
48         HScrollBar->setSubElement(true);\r
49         HScrollBar->setTabStop(false);\r
50         HScrollBar->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT);\r
51         HScrollBar->grab();\r
52         IGUIElement::addChild(HScrollBar);\r
53 \r
54         rct = core::rect<s32>(0,0, width - SCROLL_BAR_SIZE, height - SCROLL_BAR_SIZE);\r
55 \r
56         ClipPane = environment->addTab( rct, 0, -1);\r
57         ClipPane->setSubElement(true);\r
58         ClipPane->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);\r
59         ClipPane->grab();\r
60         IGUIElement::addChild(ClipPane);\r
61 \r
62         InnerPane = environment->addTab(rct, ClipPane, -1);\r
63         InnerPane->setSubElement(true);\r
64         InnerPane->grab();\r
65 \r
66         calculateClientArea();\r
67         resizeInnerPane();\r
68 }\r
69 \r
70 CGUIPanel::~CGUIPanel()\r
71 {\r
72         // because the inner pane has the list of children, we need to remove the outer ones manually\r
73         IGUIElement::removeChild(VScrollBar);\r
74         IGUIElement::removeChild(HScrollBar);\r
75         IGUIElement::removeChild(ClipPane);\r
76 \r
77         // now we can drop the others\r
78         VScrollBar->drop();\r
79         HScrollBar->drop();\r
80         ClipPane->drop();\r
81         InnerPane->drop();\r
82 }\r
83 \r
84 \r
85 void CGUIPanel::draw()\r
86 {\r
87         if (NeedsUpdate)\r
88         {\r
89                 calculateClientArea();\r
90                 resizeInnerPane();\r
91                 NeedsUpdate = false;\r
92         }\r
93 \r
94         IGUISkin* skin = Environment->getSkin();\r
95         if (Border && skin)\r
96         {\r
97                 skin->draw3DSunkenPane( this, skin->getColor( EGDC_APP_WORKSPACE), false, true, AbsoluteRect, &AbsoluteClippingRect );\r
98         }\r
99 \r
100         IGUIElement::draw();\r
101 }\r
102 \r
103 void CGUIPanel::addChild(IGUIElement *child)\r
104 {\r
105         // add the child to the inner pane\r
106         InnerPane->addChild(child);\r
107 \r
108         NeedsUpdate = true;\r
109 }\r
110 \r
111 void CGUIPanel::removeChild(IGUIElement *child)\r
112 {\r
113         InnerPane->removeChild(child);\r
114 \r
115         NeedsUpdate = true;\r
116 }\r
117 \r
118 //! returns children of the inner pane\r
119 const core::list<IGUIElement*>& CGUIPanel::getChildren()\r
120 {\r
121         return InnerPane->getChildren();\r
122 }\r
123 \r
124 bool CGUIPanel::hasBorder() const\r
125 {\r
126         return Border;\r
127 }\r
128 \r
129 void CGUIPanel::setBorder( bool enabled )\r
130 {\r
131         Border = enabled;\r
132 }\r
133 \r
134 IGUIScrollBar* CGUIPanel::getVScrollBar() const\r
135 {\r
136         return VScrollBar;\r
137 }\r
138 \r
139 IGUIScrollBar* CGUIPanel::getHScrollBar() const\r
140 {\r
141         return HScrollBar;\r
142 }\r
143 \r
144 E_SCROLL_BAR_MODE CGUIPanel::getVScrollBarMode() const\r
145 {\r
146         return VScrollBarMode;\r
147 }\r
148 \r
149 void CGUIPanel::setVScrollBarMode( E_SCROLL_BAR_MODE mode )\r
150 {\r
151         VScrollBarMode = mode;\r
152         NeedsUpdate = true;\r
153 }\r
154 \r
155 E_SCROLL_BAR_MODE CGUIPanel::getHScrollBarMode() const\r
156 {\r
157         return HScrollBarMode;\r
158 }\r
159 \r
160 void CGUIPanel::setHScrollBarMode(E_SCROLL_BAR_MODE mode)\r
161 {\r
162         HScrollBarMode = mode;\r
163         NeedsUpdate = true;\r
164 }\r
165 \r
166 bool CGUIPanel::OnEvent(const SEvent &event)\r
167 {\r
168         // Redirect mouse wheel to scrollbar\r
169         if (event.EventType == EET_MOUSE_INPUT_EVENT && event.MouseInput.Event == EMIE_MOUSE_WHEEL)\r
170         {\r
171                 if (VScrollBar->isVisible())\r
172                 {\r
173                         Environment->setFocus(VScrollBar);\r
174                         VScrollBar->OnEvent(event);\r
175                         return true;\r
176                 }\r
177                 else if (VScrollBar->isVisible())\r
178                 {\r
179                         Environment->setFocus(HScrollBar);\r
180                         HScrollBar->OnEvent(event);\r
181                         return true;\r
182                 }\r
183         }\r
184         else\r
185         {\r
186                 if (event.EventType == EET_GUI_EVENT && event.GUIEvent.EventType == EGET_SCROLL_BAR_CHANGED &&\r
187                         (event.GUIEvent.Caller == HScrollBar || event.GUIEvent.Caller == VScrollBar) )\r
188                 {\r
189                         moveInnerPane();\r
190 \r
191                         return true;\r
192                 }\r
193         }\r
194 \r
195         return IGUIElement::OnEvent(event);\r
196 }\r
197 \r
198 void CGUIPanel::moveInnerPane()\r
199 {\r
200         core::dimension2d<s32> dim = InnerPane->getAbsolutePosition().getSize();\r
201         core::position2d<s32> newpos(HScrollBar->isVisible() ? -HScrollBar->getPos() : 0 , VScrollBar->isVisible() ? -VScrollBar->getPos() : 0);\r
202         core::rect<s32> r(newpos, newpos + dim);\r
203         InnerPane->setRelativePosition(r);\r
204 }\r
205 \r
206 \r
207 void CGUIPanel::updateAbsolutePosition()\r
208 {\r
209         IGUIElement::updateAbsolutePosition();\r
210         calculateClientArea();\r
211         resizeInnerPane();\r
212 }\r
213 \r
214 \r
215 void CGUIPanel::resizeInnerPane()\r
216 {\r
217         if (!HScrollBar || !VScrollBar || !InnerPane || !ClipPane)\r
218                 return;\r
219 \r
220         // get outer pane size\r
221         core::rect<s32> outerRect = ClipPane->getRelativePosition();\r
222 \r
223         // resize flexible children depending on outer pane\r
224         InnerPane->setRelativePosition(outerRect);\r
225 \r
226         // get desired size (total size of all children)\r
227         core::rect<s32> totalRect(0, 0, 0, 0);\r
228 \r
229         core::list<IGUIElement*>::ConstIterator it;\r
230 \r
231         for (it  = InnerPane->getChildren().begin();\r
232          it != InnerPane->getChildren().end(); ++it)\r
233         {\r
234                 core::rect<s32> rct = (*it)->getRelativePosition();\r
235                 totalRect.addInternalPoint(rct.UpperLeftCorner);\r
236                 totalRect.addInternalPoint(rct.LowerRightCorner);\r
237         }\r
238 \r
239         // move children if pane needs to grow\r
240         core::position2di adjustedMovement(0,0);\r
241 \r
242         if (totalRect.UpperLeftCorner.X < 0)\r
243                 adjustedMovement.X = -totalRect.UpperLeftCorner.X;\r
244         if (totalRect.UpperLeftCorner.Y < 0)\r
245                 adjustedMovement.Y = -totalRect.UpperLeftCorner.Y;\r
246 \r
247         if (adjustedMovement.X > 0 || adjustedMovement.Y > 0)\r
248         {\r
249                 totalRect += adjustedMovement;\r
250 \r
251                 for (it = InnerPane->getChildren().begin();\r
252                         it != InnerPane->getChildren().end(); ++it )\r
253                 {\r
254                         (*it)->move(adjustedMovement);\r
255                 }\r
256         }\r
257 \r
258         // make sure the inner pane is at least as big as the outer\r
259         if (totalRect.getWidth() < outerRect.getWidth())\r
260         {\r
261                 totalRect.UpperLeftCorner.X = 0;\r
262                 totalRect.LowerRightCorner.X = outerRect.getWidth();\r
263         }\r
264         if (totalRect.getHeight() < outerRect.getHeight())\r
265         {\r
266                 totalRect.UpperLeftCorner.Y = 0;\r
267                 totalRect.LowerRightCorner.Y = outerRect.getHeight();\r
268         }\r
269 \r
270         InnerPane->setRelativePosition(totalRect);\r
271 \r
272         // scrollbars\r
273         if ( HScrollBarMode != ESBM_ALWAYS_INVISIBLE &&\r
274                 (totalRect.getWidth() > outerRect.getWidth() || HScrollBarMode == ESBM_ALWAYS_VISIBLE) )\r
275         {\r
276                 HScrollBar->setVisible(true);\r
277                 HScrollBar->setMax(totalRect.getWidth() - outerRect.getWidth());\r
278                 bringToFront(HScrollBar);\r
279         }\r
280         else\r
281                 HScrollBar->setVisible(false);\r
282 \r
283         if ( VScrollBarMode != ESBM_ALWAYS_INVISIBLE &&\r
284                 (totalRect.getHeight() > outerRect.getHeight() || VScrollBarMode == ESBM_ALWAYS_VISIBLE) )\r
285         {\r
286                 VScrollBar->setVisible(true);\r
287                 VScrollBar->setMax(totalRect.getHeight() - outerRect.getHeight());\r
288                 bringToFront(VScrollBar);\r
289         }\r
290         else\r
291                 VScrollBar->setVisible(false);\r
292 \r
293         // move to adjust for scrollbar pos\r
294         moveInnerPane();\r
295 }\r
296 \r
297 void CGUIPanel::calculateClientArea()\r
298 {\r
299         core::rect<s32> ClientArea(0,0, AbsoluteRect.getWidth(),AbsoluteRect.getHeight());\r
300 \r
301         if (VScrollBar->isVisible())\r
302                 ClientArea.LowerRightCorner.X -= VScrollBar->getRelativePosition().getWidth();\r
303 \r
304         if (HScrollBar->isVisible())\r
305                 ClientArea.LowerRightCorner.Y -= HScrollBar->getRelativePosition().getHeight();\r
306 \r
307         if (Border)\r
308         {\r
309                 ClientArea.UpperLeftCorner += core::position2d<s32>( BORDER_WIDTH, BORDER_WIDTH );\r
310                 ClientArea.LowerRightCorner -= core::position2d<s32>( BORDER_WIDTH, BORDER_WIDTH );\r
311         }\r
312 \r
313         ClipPane->setRelativePosition(ClientArea);\r
314 }\r
315 \r
316 core::rect<s32> CGUIPanel::getClientArea() const\r
317 {\r
318         return ClipPane->getRelativePosition();\r
319 }\r
320 \r
321 void CGUIPanel::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options)\r
322 {\r
323         IGUIElement::serializeAttributes(out, options);\r
324 \r
325         out->addBool("border", Border);\r
326         out->addEnum("horizontalScrollBar", HScrollBarMode, GUIScrollBarModeNames );\r
327         out->addEnum("verticalScrollBar", VScrollBarMode, GUIScrollBarModeNames );\r
328 }\r
329 \r
330 void CGUIPanel::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)\r
331 {\r
332         IGUIElement::deserializeAttributes(in, options);\r
333 \r
334         setBorder(in->getAttributeAsBool("border"));\r
335         setHScrollBarMode((E_SCROLL_BAR_MODE)in->getAttributeAsEnumeration("horizontalScrollBar", GUIScrollBarModeNames));\r
336         setVScrollBarMode((E_SCROLL_BAR_MODE)in->getAttributeAsEnumeration("verticalScrollBar", GUIScrollBarModeNames));\r
337 }\r
338 \r
339 } // namespace gui\r
340 } // namespace irr\r