]> git.lizzy.rs Git - irrlicht.git/blob - source/Irrlicht/CGUIFileOpenDialog.cpp
Drop _IRR_COMPILE_WITH_GUI_
[irrlicht.git] / source / Irrlicht / CGUIFileOpenDialog.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 "CGUIFileOpenDialog.h"\r
6 \r
7 #include "IGUISkin.h"\r
8 #include "IGUIEnvironment.h"\r
9 #include "IVideoDriver.h"\r
10 #include "IGUIButton.h"\r
11 #include "IGUIStaticText.h"\r
12 #include "IGUIFont.h"\r
13 #include "IGUIFontBitmap.h"\r
14 #include "IFileList.h"\r
15 #include "os.h"\r
16 \r
17 namespace irr\r
18 {\r
19 namespace gui\r
20 {\r
21 \r
22 const s32 FOD_WIDTH = 350;\r
23 const s32 FOD_HEIGHT = 250;\r
24 \r
25 \r
26 //! constructor\r
27 CGUIFileOpenDialog::CGUIFileOpenDialog(const wchar_t* title,\r
28                 IGUIEnvironment* environment, IGUIElement* parent, s32 id,\r
29                 bool restoreCWD, io::path::char_type* startDir)\r
30 : IGUIFileOpenDialog(environment, parent, id,\r
31                 core::rect<s32>((parent->getAbsolutePosition().getWidth()-FOD_WIDTH)/2,\r
32                                         (parent->getAbsolutePosition().getHeight()-FOD_HEIGHT)/2,\r
33                                         (parent->getAbsolutePosition().getWidth()-FOD_WIDTH)/2+FOD_WIDTH,\r
34                                         (parent->getAbsolutePosition().getHeight()-FOD_HEIGHT)/2+FOD_HEIGHT)),\r
35         FileNameText(0), FileList(0), Dragging(false)\r
36 {\r
37         #ifdef _DEBUG\r
38         IGUIElement::setDebugName("CGUIFileOpenDialog");\r
39         #endif\r
40 \r
41         Text = title;\r
42 \r
43         FileSystem = Environment?Environment->getFileSystem():0;\r
44 \r
45         if (FileSystem)\r
46         {\r
47                 FileSystem->grab();\r
48 \r
49                 if (restoreCWD)\r
50                         RestoreDirectory = FileSystem->getWorkingDirectory();\r
51                 if (startDir)\r
52                 {\r
53                         StartDirectory = startDir;\r
54                         FileSystem->changeWorkingDirectoryTo(startDir);\r
55                 }\r
56         }\r
57         else\r
58                 return;\r
59 \r
60         IGUISpriteBank* sprites = 0;\r
61         video::SColor color(255,255,255,255);\r
62         IGUISkin* skin = Environment->getSkin();\r
63         if (skin)\r
64         {\r
65                 sprites = skin->getSpriteBank();\r
66                 color = skin->getColor(EGDC_WINDOW_SYMBOL);\r
67         }\r
68 \r
69         const s32 buttonw = skin ? skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) : 2;\r
70         const s32 posx = RelativeRect.getWidth() - buttonw - 4;\r
71 \r
72         CloseButton = Environment->addButton(core::rect<s32>(posx, 3, posx + buttonw, 3 + buttonw), this, -1,\r
73                 L"", skin ? skin->getDefaultText(EGDT_WINDOW_CLOSE) : L"Close");\r
74         CloseButton->setSubElement(true);\r
75         CloseButton->setTabStop(false);\r
76         if (sprites && skin)\r
77         {\r
78                 CloseButton->setSpriteBank(sprites);\r
79                 CloseButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_CLOSE), color);\r
80                 CloseButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_CLOSE), color);\r
81         }\r
82         CloseButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);\r
83         CloseButton->grab();\r
84 \r
85         OKButton = Environment->addButton(\r
86                 core::rect<s32>(RelativeRect.getWidth()-80, 30, RelativeRect.getWidth()-10, 50),\r
87                 this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_OK) : L"OK");\r
88         OKButton->setSubElement(true);\r
89         OKButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);\r
90         OKButton->grab();\r
91 \r
92         CancelButton = Environment->addButton(\r
93                 core::rect<s32>(RelativeRect.getWidth()-80, 55, RelativeRect.getWidth()-10, 75),\r
94                 this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_CANCEL) : L"Cancel");\r
95         CancelButton->setSubElement(true);\r
96         CancelButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);\r
97         CancelButton->grab();\r
98 \r
99         FileBox = Environment->addListBox(core::rect<s32>(10, 55, RelativeRect.getWidth()-90, 230), this, -1, true);\r
100         FileBox->setSubElement(true);\r
101         FileBox->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);\r
102         FileBox->grab();\r
103 \r
104         FileNameText = Environment->addEditBox(0, core::rect<s32>(10, 30, RelativeRect.getWidth()-90, 50), true, this);\r
105         FileNameText->setSubElement(true);\r
106         FileNameText->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);\r
107         FileNameText->grab();\r
108 \r
109         setTabGroup(true);\r
110 \r
111         fillListBox();\r
112 }\r
113 \r
114 \r
115 //! destructor\r
116 CGUIFileOpenDialog::~CGUIFileOpenDialog()\r
117 {\r
118         if (CloseButton)\r
119                 CloseButton->drop();\r
120 \r
121         if (OKButton)\r
122                 OKButton->drop();\r
123 \r
124         if (CancelButton)\r
125                 CancelButton->drop();\r
126 \r
127         if (FileBox)\r
128                 FileBox->drop();\r
129 \r
130         if (FileNameText)\r
131                 FileNameText->drop();\r
132 \r
133         if (FileSystem)\r
134         {\r
135                 // revert to original CWD if path was set in constructor\r
136                 if (RestoreDirectory.size())\r
137                         FileSystem->changeWorkingDirectoryTo(RestoreDirectory);\r
138                 FileSystem->drop();\r
139         }\r
140 \r
141         if (FileList)\r
142                 FileList->drop();\r
143 }\r
144 \r
145 \r
146 //! returns the filename of the selected file. Returns NULL, if no file was selected.\r
147 const wchar_t* CGUIFileOpenDialog::getFileName() const\r
148 {\r
149         return FileNameW.c_str();\r
150 }\r
151 \r
152 const io::path& CGUIFileOpenDialog::getFileNameP() const\r
153 {\r
154         return FileName;\r
155 }\r
156 \r
157 //! Returns the directory of the selected file. Returns NULL, if no directory was selected.\r
158 const io::path& CGUIFileOpenDialog::getDirectoryName() const\r
159 {\r
160         return FileDirectoryFlat;\r
161 }\r
162 \r
163 const wchar_t* CGUIFileOpenDialog::getDirectoryNameW() const\r
164 {\r
165         return FileDirectoryFlatW.c_str();\r
166 }\r
167 \r
168 void CGUIFileOpenDialog::setFileName(const irr::io::path& name)\r
169 {\r
170         FileName = name;\r
171         pathToStringW(FileNameW, FileName);\r
172 }\r
173 \r
174 void CGUIFileOpenDialog::setDirectoryName(const irr::io::path& name)\r
175 {\r
176         FileDirectory = name;\r
177         FileDirectoryFlat = name;\r
178         FileSystem->flattenFilename (FileDirectoryFlat );\r
179         pathToStringW(FileDirectoryFlatW, FileDirectoryFlat);\r
180 }\r
181 \r
182 //! called if an event happened.\r
183 bool CGUIFileOpenDialog::OnEvent(const SEvent& event)\r
184 {\r
185         if (isEnabled())\r
186         {\r
187                 switch(event.EventType)\r
188                 {\r
189                 case EET_GUI_EVENT:\r
190                         switch(event.GUIEvent.EventType)\r
191                         {\r
192                         case EGET_ELEMENT_FOCUS_LOST:\r
193                                 Dragging = false;\r
194                                 break;\r
195                         case EGET_BUTTON_CLICKED:\r
196                                 if (event.GUIEvent.Caller == CloseButton ||\r
197                                         event.GUIEvent.Caller == CancelButton)\r
198                                 {\r
199                                         sendCancelEvent();\r
200                                         remove();\r
201                                         return true;\r
202                                 }\r
203                                 else\r
204                                 if (event.GUIEvent.Caller == OKButton )\r
205                                 {\r
206                                         if ( FileDirectory != L"" )\r
207                                         {\r
208                                                 sendSelectedEvent( EGET_DIRECTORY_SELECTED );\r
209                                         }\r
210                                         if ( FileName != L"" )\r
211                                         {\r
212                                                 sendSelectedEvent( EGET_FILE_SELECTED );\r
213                                                 remove();\r
214                                                 return true;\r
215                                         }\r
216                                 }\r
217                                 break;\r
218 \r
219                         case EGET_LISTBOX_CHANGED:\r
220                                 {\r
221                                         s32 selected = FileBox->getSelected();\r
222                                         if (FileList && FileSystem)\r
223                                         {\r
224                                                 if (FileList->isDirectory(selected))\r
225                                                 {\r
226                                                         setFileName("");\r
227                                                         setDirectoryName(FileList->getFullFileName(selected));\r
228                                                 }\r
229                                                 else\r
230                                                 {\r
231                                                         setDirectoryName("");\r
232                                                         setFileName(FileList->getFullFileName(selected));\r
233                                                 }\r
234                                                 return true;\r
235                                         }\r
236                                 }\r
237                                 break;\r
238 \r
239                         case EGET_LISTBOX_SELECTED_AGAIN:\r
240                                 {\r
241                                         const s32 selected = FileBox->getSelected();\r
242                                         if (FileList && FileSystem)\r
243                                         {\r
244                                                 if (FileList->isDirectory(selected))\r
245                                                 {\r
246                                                         setDirectoryName(FileList->getFullFileName(selected));\r
247                                                         FileSystem->changeWorkingDirectoryTo(FileDirectory );\r
248                                                         fillListBox();\r
249                                                         setFileName("");\r
250                                                 }\r
251                                                 else\r
252                                                 {\r
253                                                         setFileName(FileList->getFullFileName(selected));\r
254                                                 }\r
255                                                 return true;\r
256                                         }\r
257                                 }\r
258                                 break;\r
259                         case EGET_EDITBOX_ENTER:\r
260                                 if (event.GUIEvent.Caller == FileNameText)\r
261                                 {\r
262                                         io::path dir( FileNameText->getText () );\r
263                                         if ( FileSystem->changeWorkingDirectoryTo( dir ) )\r
264                                         {\r
265                                                 fillListBox();\r
266                                                 setFileName("");\r
267                                         }\r
268                                         return true;\r
269                                 }\r
270                         break;\r
271                         default:\r
272                                 break;\r
273                         }\r
274                         break;\r
275                 case EET_MOUSE_INPUT_EVENT:\r
276                         switch(event.MouseInput.Event)\r
277                         {\r
278                         case EMIE_MOUSE_WHEEL:\r
279                                 return FileBox->OnEvent(event);\r
280                         case EMIE_LMOUSE_PRESSED_DOWN:\r
281                                 DragStart.X = event.MouseInput.X;\r
282                                 DragStart.Y = event.MouseInput.Y;\r
283                                 Dragging = true;\r
284                                 return true;\r
285                         case EMIE_LMOUSE_LEFT_UP:\r
286                                 Dragging = false;\r
287                                 return true;\r
288                         case EMIE_MOUSE_MOVED:\r
289 \r
290                                 if ( !event.MouseInput.isLeftPressed () )\r
291                                         Dragging = false;\r
292 \r
293                                 if (Dragging)\r
294                                 {\r
295                                         // gui window should not be dragged outside its parent\r
296                                         if (Parent)\r
297                                                 if (event.MouseInput.X < Parent->getAbsolutePosition().UpperLeftCorner.X +1 ||\r
298                                                         event.MouseInput.Y < Parent->getAbsolutePosition().UpperLeftCorner.Y +1 ||\r
299                                                         event.MouseInput.X > Parent->getAbsolutePosition().LowerRightCorner.X -1 ||\r
300                                                         event.MouseInput.Y > Parent->getAbsolutePosition().LowerRightCorner.Y -1)\r
301 \r
302                                                         return true;\r
303 \r
304                                         move(core::position2d<s32>(event.MouseInput.X - DragStart.X, event.MouseInput.Y - DragStart.Y));\r
305                                         DragStart.X = event.MouseInput.X;\r
306                                         DragStart.Y = event.MouseInput.Y;\r
307                                         return true;\r
308                                 }\r
309                                 break;\r
310                         default:\r
311                                 break;\r
312                         }\r
313                 default:\r
314                         break;\r
315                 }\r
316         }\r
317 \r
318         return IGUIElement::OnEvent(event);\r
319 }\r
320 \r
321 \r
322 //! draws the element and its children\r
323 void CGUIFileOpenDialog::draw()\r
324 {\r
325         if (!IsVisible)\r
326                 return;\r
327 \r
328         IGUISkin* skin = Environment->getSkin();\r
329 \r
330         core::rect<s32> rect = AbsoluteRect;\r
331 \r
332         rect = skin->draw3DWindowBackground(this, true, skin->getColor(EGDC_ACTIVE_BORDER),\r
333                 rect, &AbsoluteClippingRect);\r
334 \r
335         if (Text.size())\r
336         {\r
337                 rect.UpperLeftCorner.X += 2;\r
338                 rect.LowerRightCorner.X -= skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) + 5;\r
339 \r
340                 IGUIFont* font = skin->getFont(EGDF_WINDOW);\r
341                 if (font)\r
342                         font->draw(Text.c_str(), rect,\r
343                                         skin->getColor(EGDC_ACTIVE_CAPTION),\r
344                                         false, true, &AbsoluteClippingRect);\r
345         }\r
346 \r
347         IGUIElement::draw();\r
348 }\r
349 \r
350 void CGUIFileOpenDialog::pathToStringW(irr::core::stringw& result, const irr::io::path& p)\r
351 {\r
352         core::multibyteToWString(result, p);\r
353 }\r
354 \r
355 //! fills the listbox with files.\r
356 void CGUIFileOpenDialog::fillListBox()\r
357 {\r
358         IGUISkin *skin = Environment->getSkin();\r
359 \r
360         if (!FileSystem || !FileBox || !skin)\r
361                 return;\r
362 \r
363         if (FileList)\r
364                 FileList->drop();\r
365 \r
366         FileBox->clear();\r
367 \r
368         FileList = FileSystem->createFileList();\r
369         core::stringw s;\r
370 \r
371         if (FileList)\r
372         {\r
373                 for (u32 i=0; i < FileList->getFileCount(); ++i)\r
374                 {\r
375                         pathToStringW(s, FileList->getFileName(i));\r
376                         FileBox->addItem(s.c_str(), skin->getIcon(FileList->isDirectory(i) ? EGDI_DIRECTORY : EGDI_FILE));\r
377                 }\r
378         }\r
379 \r
380         if (FileNameText)\r
381         {\r
382                 setDirectoryName(FileSystem->getWorkingDirectory());\r
383                 pathToStringW(s, FileDirectory);\r
384                 FileNameText->setText(s.c_str());\r
385         }\r
386 }\r
387 \r
388 //! sends the event that the file has been selected.\r
389 void CGUIFileOpenDialog::sendSelectedEvent( EGUI_EVENT_TYPE type)\r
390 {\r
391         SEvent event;\r
392         event.EventType = EET_GUI_EVENT;\r
393         event.GUIEvent.Caller = this;\r
394         event.GUIEvent.Element = 0;\r
395         event.GUIEvent.EventType = type;\r
396         Parent->OnEvent(event);\r
397 }\r
398 \r
399 \r
400 //! sends the event that the file choose process has been cancelled\r
401 void CGUIFileOpenDialog::sendCancelEvent()\r
402 {\r
403         SEvent event;\r
404         event.EventType = EET_GUI_EVENT;\r
405         event.GUIEvent.Caller = this;\r
406         event.GUIEvent.Element = 0;\r
407         event.GUIEvent.EventType = EGET_FILE_CHOOSE_DIALOG_CANCELLED;\r
408         Parent->OnEvent(event);\r
409 }\r
410 \r
411 } // end namespace gui\r
412 } // end namespace irr\r