Răsfoiți Sursa

added UIFileDialog, IDE on Linux uses UIFileDialog, added Linux file manipulation methods to SDLCore, fixed OSBasics to properly display root folder on Linux

Ivan Safrin 13 ani în urmă
părinte
comite
0cbace3e56

+ 8 - 2
Core/Contents/Source/OSBasics.cpp

@@ -82,7 +82,12 @@ OSFileEntry::OSFileEntry(const String& path, const String& name, int type) {
 
 
 void OSFileEntry::init(const Polycode::String& path, const Polycode::String& name, int type) {
 void OSFileEntry::init(const Polycode::String& path, const Polycode::String& name, int type) {
 	this->basePath = path;
 	this->basePath = path;
-	this->fullPath = path + "/" + name;
+
+	if(path == "/") {
+		this->fullPath = "/" + name;
+	} else {
+		this->fullPath = path + "/" + name;
+	}
 	this->name = name;
 	this->name = name;
 	this->type = type;
 	this->type = type;
 
 
@@ -255,6 +260,7 @@ vector<OSFileEntry> OSBasics::parsePhysFSFolder(const String& pathString, bool s
 vector<OSFileEntry> OSBasics::parseFolder(const String& pathString, bool showHidden) {
 vector<OSFileEntry> OSBasics::parseFolder(const String& pathString, bool showHidden) {
 	vector<OSFileEntry> returnVector;
 	vector<OSFileEntry> returnVector;
 	
 	
+	if(pathString != "/") {
 	if(pathString.size() < 128) {
 	if(pathString.size() < 128) {
 		if(PHYSFS_exists(pathString.c_str())) {
 		if(PHYSFS_exists(pathString.c_str())) {
 			if(PHYSFS_isDirectory(pathString.c_str())) {
 			if(PHYSFS_isDirectory(pathString.c_str())) {
@@ -262,7 +268,7 @@ vector<OSFileEntry> OSBasics::parseFolder(const String& pathString, bool showHid
 			}
 			}
 		}
 		}
 	}
 	}
-	
+	}
 	
 	
 #ifdef _WINDOWS
 #ifdef _WINDOWS
 
 

+ 24 - 3
Core/Contents/Source/PolySDLCore.cpp

@@ -36,6 +36,8 @@
 
 
 #include <unistd.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
 #include <pwd.h>
 #include <pwd.h>
 
 
 using namespace Polycode;
 using namespace Polycode;
@@ -292,18 +294,37 @@ String SDLCore::getClipboardString() {
 }
 }
 
 
 void SDLCore::createFolder(const String& folderPath) {
 void SDLCore::createFolder(const String& folderPath) {
-
+	mkdir(folderPath.c_str(), 0700);
 }
 }
 
 
 void SDLCore::copyDiskItem(const String& itemPath, const String& destItemPath) {
 void SDLCore::copyDiskItem(const String& itemPath, const String& destItemPath) {
-
+    int childExitStatus;
+    pid_t pid = fork();
+    if (pid == 0) {
+        execl("/bin/cp", "/bin/cp", itemPath.c_str(), destItemPath.c_str(), (char *)0);
+    } else {
+        pid_t ws = waitpid( pid, &childExitStatus, WNOHANG);
+    }
 }
 }
 
 
 void SDLCore::moveDiskItem(const String& itemPath, const String& destItemPath) {
 void SDLCore::moveDiskItem(const String& itemPath, const String& destItemPath) {
-
+    int childExitStatus;
+    pid_t pid = fork();
+    if (pid == 0) {
+        execl("/bin/mv", "/bin/mv", itemPath.c_str(), destItemPath.c_str(), (char *)0);
+    } else {
+        pid_t ws = waitpid( pid, &childExitStatus, WNOHANG);
+    }
 }
 }
 
 
 void SDLCore::removeDiskItem(const String& itemPath) {
 void SDLCore::removeDiskItem(const String& itemPath) {
+    int childExitStatus;
+    pid_t pid = fork();
+    if (pid == 0) {
+        execl("/bin/rm", "/bin/rm", "-rf", itemPath.c_str(), (char *)0);
+    } else {
+        pid_t ws = waitpid( pid, &childExitStatus, WNOHANG);
+    }
 }
 }
 
 
 String SDLCore::openFolderPicker() {
 String SDLCore::openFolderPicker() {

+ 1 - 1
IDE/Build/Linux/Makefile

@@ -1,5 +1,5 @@
 CC=g++
 CC=g++
-CFLAGS=-I../../Contents/Include -I../../../Release/Linux/Framework/Core/Dependencies/include -I../../../Release/Linux/Framework/Core/Dependencies/include/AL -I../../../Release/Linux/Framework/Core/include -I../../../Release/Linux/Framework/Modules/include -I../../../Release/Linux/Framework/Modules/Dependencies/include -I../../../Release/Linux/Framework/Modules/Dependencies/include/bullet
+CFLAGS=-I../../Contents/Include -I../../../Release/Linux/Framework/Core/Dependencies/include -I../../../Release/Linux/Framework/Core/Dependencies/include/AL -I../../../Release/Linux/Framework/Core/include -I../../../Release/Linux/Framework/Modules/include -I../../../Release/Linux/Framework/Modules/Dependencies/include -I../../../Release/Linux/Framework/Modules/Dependencies/include/bullet -DUSE_POLYCODEUI_FILE_DIALOGS
 LDFLAGS=-lrt -ldl -lpthread ../../../Release/Linux/Framework/Core/lib/libPolycore.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libfreetype.a ../../../Release/Linux/Framework/Core/Dependencies/lib/liblibvorbisfile.a ../../../Release/Linux/Framework/Core/Dependencies/lib/liblibvorbis.a ../../../Release/Linux/Framework/Core/Dependencies/lib/liblibogg.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libopenal.so ../../../Release/Linux/Framework/Core/Dependencies/lib/libphysfs.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libpng15.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libz.a -lGL -lGLU -lSDL ../../../Release/Linux/Framework/Modules/lib/libPolycode2DPhysics.a ../../../Release/Linux/Framework/Modules/Dependencies/lib/libBox2D.a ../../../Release/Linux/Framework/Modules/lib/libPolycode3DPhysics.a ../../../Release/Linux/Framework/Modules/Dependencies/lib/libBulletDynamics.a ../../../Release/Linux/Framework/Modules/Dependencies/lib/libBulletCollision.a ../../../Release/Linux/Framework/Modules/Dependencies/lib/libLinearMath.a ../../../Release/Linux/Framework/Modules/lib/libPolycodeUI.a
 LDFLAGS=-lrt -ldl -lpthread ../../../Release/Linux/Framework/Core/lib/libPolycore.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libfreetype.a ../../../Release/Linux/Framework/Core/Dependencies/lib/liblibvorbisfile.a ../../../Release/Linux/Framework/Core/Dependencies/lib/liblibvorbis.a ../../../Release/Linux/Framework/Core/Dependencies/lib/liblibogg.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libopenal.so ../../../Release/Linux/Framework/Core/Dependencies/lib/libphysfs.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libpng15.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libz.a -lGL -lGLU -lSDL ../../../Release/Linux/Framework/Modules/lib/libPolycode2DPhysics.a ../../../Release/Linux/Framework/Modules/Dependencies/lib/libBox2D.a ../../../Release/Linux/Framework/Modules/lib/libPolycode3DPhysics.a ../../../Release/Linux/Framework/Modules/Dependencies/lib/libBulletDynamics.a ../../../Release/Linux/Framework/Modules/Dependencies/lib/libBulletCollision.a ../../../Release/Linux/Framework/Modules/Dependencies/lib/libLinearMath.a ../../../Release/Linux/Framework/Modules/lib/libPolycodeUI.a
 SRCS=../../Contents/Source/ExampleBrowserWindow.cpp ../../Contents/Source/PolycodeEditorManager.cpp  ../../Contents/Source/PolycodeProject.cpp        ../../Contents/Source/PolycodeScreenEditor.cpp ../../Contents/Source/ExportProjectWindow.cpp  ../../Contents/Source/PolycodeFontEditor.cpp     ../../Contents/Source/PolycodeProjectBrowser.cpp ../../Contents/Source/PolycodeSpriteEditor.cpp ../../Contents/Source/NewFileWindow.cpp        ../../Contents/Source/PolycodeFrame.cpp          ../../Contents/Source/PolycodeProjectEditor.cpp  ../../Contents/Source/PolycodeTextEditor.cpp ../../Contents/Source/NewProjectWindow.cpp     ../../Contents/Source/PolycodeIDEApp.cpp         ../../Contents/Source/PolycodeProjectManager.cpp ../../Contents/Source/PolycodeToolLauncher.cpp ../../Contents/Source/PolycodeConsole.cpp      ../../Contents/Source/PolycodeImageEditor.cpp    ../../Contents/Source/PolycodeProps.cpp          ../../Contents/Source/TextureBrowser.cpp ../../Contents/Source/PolycodeEditor.cpp       ../../Contents/Source/PolycodeMaterialEditor.cpp ../../Contents/Source/PolycodeRemoteDebugger.cpp ../../Contents/Source/ToolWindows.cpp
 SRCS=../../Contents/Source/ExampleBrowserWindow.cpp ../../Contents/Source/PolycodeEditorManager.cpp  ../../Contents/Source/PolycodeProject.cpp        ../../Contents/Source/PolycodeScreenEditor.cpp ../../Contents/Source/ExportProjectWindow.cpp  ../../Contents/Source/PolycodeFontEditor.cpp     ../../Contents/Source/PolycodeProjectBrowser.cpp ../../Contents/Source/PolycodeSpriteEditor.cpp ../../Contents/Source/NewFileWindow.cpp        ../../Contents/Source/PolycodeFrame.cpp          ../../Contents/Source/PolycodeProjectEditor.cpp  ../../Contents/Source/PolycodeTextEditor.cpp ../../Contents/Source/NewProjectWindow.cpp     ../../Contents/Source/PolycodeIDEApp.cpp         ../../Contents/Source/PolycodeProjectManager.cpp ../../Contents/Source/PolycodeToolLauncher.cpp ../../Contents/Source/PolycodeConsole.cpp      ../../Contents/Source/PolycodeImageEditor.cpp    ../../Contents/Source/PolycodeProps.cpp          ../../Contents/Source/TextureBrowser.cpp ../../Contents/Source/PolycodeEditor.cpp       ../../Contents/Source/PolycodeMaterialEditor.cpp ../../Contents/Source/PolycodeRemoteDebugger.cpp ../../Contents/Source/ToolWindows.cpp
 
 

+ 9 - 1
IDE/Contents/Include/PolycodeFrame.h

@@ -160,6 +160,8 @@ public:
 	void showModal(UIWindow *modalChild);
 	void showModal(UIWindow *modalChild);
 	void hideModal();
 	void hideModal();
 	
 	
+	void showFileBrowser(String baseDir, bool foldersOnly, std::vector<String> extensions, bool allowMultiple);
+
 	void handleEvent(Event *event);
 	void handleEvent(Event *event);
 	
 	
 	void addEditor(PolycodeEditor *editor);
 	void addEditor(PolycodeEditor *editor);
@@ -195,11 +197,17 @@ public:
 		
 		
 	CurveEditor *curveEditor;
 	CurveEditor *curveEditor;
 	
 	
+	UIElement *modalRoot;
+	UIElement *fileBrowserRoot;
+	UIFileDialog *fileDialog;
+
 private:
 private:
 	
 	
 	int frameSizeX;
 	int frameSizeX;
 	int frameSizeY;
 	int frameSizeY;
 	
 	
+	ScreenShape *fileDialogBlocker;
+
 	ScreenShape *topBarBg;
 	ScreenShape *topBarBg;
 	ScreenImage *logo;	
 	ScreenImage *logo;	
 	ScreenImage *resizer;	
 	ScreenImage *resizer;	
@@ -225,4 +233,4 @@ private:
 	UIButton *newProjectButton;
 	UIButton *newProjectButton;
 	UIButton *examplesButton;
 	UIButton *examplesButton;
 	
 	
-};
+};

+ 3 - 0
IDE/Contents/Resources/UIThemes/default/theme.xml

@@ -157,4 +157,7 @@
 	<uiHSliderBgB>5</uiHSliderBgB>
 	<uiHSliderBgB>5</uiHSliderBgB>
 	<uiHSliderBgL>6</uiHSliderBgL>
 	<uiHSliderBgL>6</uiHSliderBgL>
 
 
+	<uiFileBrowserFileIcon>file.png</uiFileBrowserFileIcon>
+	<uiFileBrowserFolderIcon>folder.png</uiFileBrowserFolderIcon>
+	<uiFileBrowserPlaceIcon>boxIcon.png</uiFileBrowserPlaceIcon>
 </PolyConfig>
 </PolyConfig>

+ 16 - 0
IDE/Contents/Source/NewProjectWindow.cpp

@@ -21,6 +21,9 @@
 */
 */
 
 
 #include "NewProjectWindow.h"
 #include "NewProjectWindow.h"
+#include "PolycodeFrame.h"
+
+extern PolycodeFrame *globalFrame;
 
 
 NewProjectWindow::NewProjectWindow() : UIWindow(L"Create New Project", 480, 280){
 NewProjectWindow::NewProjectWindow() : UIWindow(L"Create New Project", 480, 280){
 	
 	
@@ -122,6 +125,13 @@ void NewProjectWindow::ResetForm() {
 
 
 void NewProjectWindow::handleEvent(Event *event) {
 void NewProjectWindow::handleEvent(Event *event) {
 	if(event->getEventType() == "UIEvent") {
 	if(event->getEventType() == "UIEvent") {
+		if(event->getEventCode() == UIEvent::OK_EVENT && event->getDispatcher() == globalFrame->fileDialog) {
+			String pathName = globalFrame->fileDialog->getSelection();
+			if(pathName != "")
+				projectLocationInput->setText(pathName);
+
+		}
+
 		if(event->getEventCode() == UIEvent::CLICK_EVENT) {
 		if(event->getEventCode() == UIEvent::CLICK_EVENT) {
 			if(event->getDispatcher() == okButton) {
 			if(event->getDispatcher() == okButton) {
 				dispatchEvent(new UIEvent(), UIEvent::OK_EVENT);						
 				dispatchEvent(new UIEvent(), UIEvent::OK_EVENT);						
@@ -132,9 +142,15 @@ void NewProjectWindow::handleEvent(Event *event) {
 			}			
 			}			
 			
 			
 			if(event->getDispatcher() == locationSelectButton) {
 			if(event->getDispatcher() == locationSelectButton) {
+#ifdef USE_POLYCODEUI_FILE_DIALOGS
+				std::vector<String> exts;
+				globalFrame->showFileBrowser(CoreServices::getInstance()->getCore()->getUserHomeDirectory(),  true, exts, false);
+				globalFrame->fileDialog->addEventListener(this, UIEvent::OK_EVENT);
+#else
 				String pathName = CoreServices::getInstance()->getCore()->openFolderPicker();
 				String pathName = CoreServices::getInstance()->getCore()->openFolderPicker();
 				if(pathName != "")
 				if(pathName != "")
 					projectLocationInput->setText(pathName);
 					projectLocationInput->setText(pathName);
+#endif
 			}			
 			}			
 			
 			
 		}
 		}

+ 41 - 2
IDE/Contents/Source/PolycodeFrame.cpp

@@ -610,6 +610,38 @@ PolycodeFrame::PolycodeFrame() : ScreenEntity() {
 	globalColorPicker = new UIColorPicker();
 	globalColorPicker = new UIColorPicker();
 	globalColorPicker->setPosition(300,300);
 	globalColorPicker->setPosition(300,300);
 	addChild(globalColorPicker);
 	addChild(globalColorPicker);
+
+	modalRoot = new UIElement();
+	addChild(modalRoot);
+	
+	fileDialogBlocker = new ScreenShape(ScreenShape::SHAPE_RECT, 100, 100);
+	fileDialogBlocker->setPositionMode(ScreenEntity::POSITION_TOPLEFT);
+	addChild(fileDialogBlocker);
+	fileDialogBlocker->setColor(0.0, 0.0, 0.0, 0.5);
+	fileDialogBlocker->processInputEvents = true;
+	fileDialogBlocker->blockMouseInput = true;
+	fileDialogBlocker->visible = false;
+	fileDialogBlocker->enabled = false;
+
+	fileBrowserRoot = new UIElement();
+	addChild(fileBrowserRoot);
+
+	fileDialog = NULL;
+}
+
+void PolycodeFrame::showFileBrowser(String baseDir, bool foldersOnly, std::vector<String> extensions, bool allowMultiple) {
+	
+	if(fileDialog)
+		delete fileDialog;
+
+	fileDialog = new UIFileDialog(baseDir, foldersOnly, extensions, allowMultiple);
+	fileDialog->addEventListener(this, UIEvent::CANCEL_EVENT);
+	fileDialog->addEventListener(this, UIEvent::OK_EVENT);
+	fileBrowserRoot->addChild(fileDialog);
+	fileDialog->setPosition(100,100);
+	
+	fileDialogBlocker->visible = true;
+	fileDialogBlocker->enabled = true;
 }
 }
 
 
 void PolycodeFrame::showCurveEditor() {
 void PolycodeFrame::showCurveEditor() {
@@ -621,7 +653,7 @@ void PolycodeFrame::showModal(UIWindow *modalChild) {
 	modalBlocker->enabled = true;
 	modalBlocker->enabled = true;
 	
 	
 	this->modalChild = modalChild;
 	this->modalChild = modalChild;
-	addChild(modalChild);
+	modalRoot->addChild(modalChild);
 	modalChild->showWindow();
 	modalChild->showWindow();
 	modalChild->addEventListener(this, UIEvent::CLOSE_EVENT);
 	modalChild->addEventListener(this, UIEvent::CLOSE_EVENT);
 	Resize(frameSizeX, frameSizeY);
 	Resize(frameSizeX, frameSizeY);
@@ -652,7 +684,7 @@ void PolycodeFrame::showEditor(PolycodeEditor *editor) {
 
 
 void PolycodeFrame::hideModal() {
 void PolycodeFrame::hideModal() {
 	if(modalChild) {
 	if(modalChild) {
-		removeChild(modalChild);
+		modalRoot->removeChild(modalChild);
 		modalChild->removeEventListener(this, UIEvent::CLOSE_EVENT);	
 		modalChild->removeEventListener(this, UIEvent::CLOSE_EVENT);	
 		modalChild->hideWindow(); 
 		modalChild->hideWindow(); 
 		modalChild = NULL;
 		modalChild = NULL;
@@ -671,6 +703,12 @@ void PolycodeFrame::showAssetBrowser(std::vector<String> extensions) {
 
 
 void PolycodeFrame::handleEvent(Event *event) {
 void PolycodeFrame::handleEvent(Event *event) {
 	
 	
+	if(event->getDispatcher() == fileDialog && event->getEventType() == "UIEvent") {
+		fileBrowserRoot->removeChild(fileDialog);
+		fileDialogBlocker->visible = false;
+		fileDialogBlocker->enabled = false;
+	}
+
 	if(event->getDispatcher() == CoreServices::getInstance()->getCore()->getInput()) {
 	if(event->getDispatcher() == CoreServices::getInstance()->getCore()->getInput()) {
 		switch(event->getEventCode()) {
 		switch(event->getEventCode()) {
 			case InputEvent::EVENT_MOUSEUP:
 			case InputEvent::EVENT_MOUSEUP:
@@ -745,6 +783,7 @@ void PolycodeFrame::Resize(int x, int y) {
 	mainSizer->Resize(x,y-45);	
 	mainSizer->Resize(x,y-45);	
 	
 	
 	modalBlocker->setShapeSize(x, y);
 	modalBlocker->setShapeSize(x, y);
+	fileDialogBlocker->setShapeSize(x, y);
 		
 		
 	
 	
 	if(this->modalChild) {
 	if(this->modalChild) {

+ 2 - 0
Modules/Contents/UI/CMakeLists.txt

@@ -21,6 +21,7 @@ SET(polycodeUI_SRCS
     Source/PolyUITreeEvent.cpp
     Source/PolyUITreeEvent.cpp
     Source/PolyUIVScrollBar.cpp
     Source/PolyUIVScrollBar.cpp
     Source/PolyUIWindow.cpp
     Source/PolyUIWindow.cpp
+    Source/PolyUIFileDialog.cpp
 )
 )
 
 
 SET(polycodeUI_HDRS
 SET(polycodeUI_HDRS
@@ -45,6 +46,7 @@ SET(polycodeUI_HDRS
     Include/PolyUITreeEvent.h
     Include/PolyUITreeEvent.h
     Include/PolyUIVScrollBar.h
     Include/PolyUIVScrollBar.h
     Include/PolyUIWindow.h
     Include/PolyUIWindow.h
+    Include/PolyUIFileDialog.h
 )
 )
 
 
 INCLUDE_DIRECTORIES(
 INCLUDE_DIRECTORIES(

+ 1 - 1
Modules/Contents/UI/Include/PolyUIButton.h

@@ -48,4 +48,4 @@ namespace Polycode {
 			ScreenLabel *buttonLabel;
 			ScreenLabel *buttonLabel;
 			bool pressedDown;
 			bool pressedDown;
 	};
 	};
-}
+}

+ 102 - 0
Modules/Contents/UI/Include/PolyUIFileDialog.h

@@ -0,0 +1,102 @@
+/*
+ Copyright (C) 2012 by Ivan Safrin
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+
+#pragma once
+
+#include "PolyGlobals.h"
+#include "PolyUIWindow.h"
+#include "PolyUIButton.h"
+#include "PolyUIScrollContainer.h"
+#include "PolyUITextInput.h"
+#include "OSBasics.h"
+#include "PolyInputEvent.h"
+
+namespace Polycode {
+	
+	class CreateFolderWindow : public UIWindow {
+		public:
+			CreateFolderWindow();
+			~CreateFolderWindow();
+
+			UIButton *okButton;
+			UIButton *cancelButton;
+			UITextInput *nameInput;
+
+	};
+
+	class UIFileDialogEntry : public UIElement {
+		public:
+			UIFileDialogEntry(OSFileEntry entry, bool canSelect, int width=340, bool isPlace=false);
+			~UIFileDialogEntry();
+			void Select();
+			void Deselect();
+
+			bool canSelect;
+			ScreenShape *bg;
+			ScreenLabel *label;
+			OSFileEntry fileEntry;
+			ScreenImage *icon;
+	};
+
+	class UIFileDialog : public UIWindow {
+		public:
+			UIFileDialog(String baseDir, bool foldersOnly, std::vector<String> extensions, bool allowMultiple);
+			virtual ~UIFileDialog();
+
+			void onClose();
+			void handleEvent(Event *event);
+			void clearEntries();
+			void showFolder(String folderPath);
+	
+			void addToSidebar(String path, String name);
+
+			void Update();
+
+			String getSelection();
+		protected:
+
+			String selection;
+
+			String currentFolderPath;
+
+			UIFileDialogEntry *currentEntry;
+
+			bool foldersOnly;
+			bool allowMultiple;
+
+			bool doChangeFolder;
+			String newPath;
+
+			UIButton *okButton;
+			UIButton *cancelButton;
+			UIButton *newFolderButton;
+
+			CreateFolderWindow *createFolderWindow;
+
+			UIScrollContainer *scrollContainer;
+
+			std::vector<UIFileDialogEntry*> entries;
+			std::vector<UIFileDialogEntry*> sideBarEntries;
+			UIElement *entryHolder;		
+	};
+}
+

+ 2 - 1
Modules/Contents/UI/Include/PolycodeUI.h

@@ -39,4 +39,5 @@
 #include "PolyUITreeEvent.h"
 #include "PolyUITreeEvent.h"
 #include "PolyUIVScrollBar.h"
 #include "PolyUIVScrollBar.h"
 #include "PolyUIWindow.h"
 #include "PolyUIWindow.h"
-#include "PolyUIMenu.h"
+#include "PolyUIMenu.h"
+#include "PolyUIFileDialog.h"

+ 311 - 0
Modules/Contents/UI/Source/PolyUIFileDialog.cpp

@@ -0,0 +1,311 @@
+
+#include "PolyUIFileDialog.h"
+#include "PolyConfig.h"
+
+using namespace Polycode;
+
+UIFileDialogEntry::UIFileDialogEntry(OSFileEntry entry, bool canSelect, int width, bool isPlace) : UIElement() {
+	this->canSelect = canSelect;
+	ownsChildren = true;
+
+	Config *conf = CoreServices::getInstance()->getConfig();	
+	String fileIconName = conf->getStringValue("Polycode", "uiFileBrowserFileIcon");
+	String folderIconName = conf->getStringValue("Polycode", "uiFileBrowserFolderIcon");
+	String placeIconName = conf->getStringValue("Polycode", "uiFileBrowserPlaceIcon");
+
+	bg = new ScreenShape(ScreenShape::SHAPE_RECT, width, 18);
+	bg->setPositionMode(ScreenEntity::POSITION_TOPLEFT);
+	addChild(bg);
+	bg->setColor(0.0, 0.0, 0.0, 0.1);
+	bg->processInputEvents = true;
+
+	this->fileEntry = entry;
+
+	if(isPlace) {
+		icon = new ScreenImage(placeIconName);
+	} else {
+		if(entry.type == OSFileEntry::TYPE_FILE) {
+			icon = new ScreenImage(fileIconName);
+		} else {
+			icon = new ScreenImage(folderIconName);
+		}
+	}
+
+	addChild(icon);
+	icon->setPosition(3,1);
+
+	label = new ScreenLabel(entry.name, 12, "sans");
+	addChild(label);
+	label->setPosition(25, 2);
+
+	if(!canSelect) {
+		label->color.a = 0.3;
+	}
+
+}
+
+void UIFileDialogEntry::Select() {
+	bg->setColor(0.0, 0.0, 0.0, 0.5);
+}
+
+void UIFileDialogEntry::Deselect() {
+	bg->setColor(0.0, 0.0, 0.0, 0.1);
+}
+
+UIFileDialogEntry::~UIFileDialogEntry() {
+
+}
+
+UIFileDialog::UIFileDialog(String baseDir, bool foldersOnly, std::vector<String> extensions, bool allowMultiple) : UIWindow("", 500, 400) {
+	this->foldersOnly = foldersOnly;
+	this->allowMultiple = allowMultiple;
+
+	ownsChildren = true;
+	
+	closeOnEscape = true;
+
+	if(foldersOnly) {
+		setWindowCaption("Select a folder");
+	} else {
+		if(allowMultiple) {
+			setWindowCaption("Select files");
+		} else {
+			setWindowCaption("Select a file");
+		}
+	}
+
+	cancelButton = new UIButton("Cancel", 100);
+	addChild(cancelButton);
+	cancelButton->setPosition(500-210, 400 - 20);
+
+	okButton = new UIButton("OK",  100);
+	addChild(okButton);
+	okButton->setPosition(500-100, 400 - 20);
+
+	newFolderButton = new UIButton("New Folder", 100);
+	addChild(newFolderButton);
+	newFolderButton->setPosition(25, 400-20);
+
+	newFolderButton->addEventListener(this, UIEvent::CLICK_EVENT);
+	okButton->addEventListener(this, UIEvent::CLICK_EVENT);
+	cancelButton->addEventListener(this, UIEvent::CLICK_EVENT);
+
+	entryHolder = new UIElement();
+	entryHolder->ownsChildren = true;
+
+	scrollContainer = new UIScrollContainer(entryHolder, false, true, 500-140, 320);
+	addChild(scrollContainer);
+
+	scrollContainer->setPosition(160, 40);
+	showFolder(baseDir);
+
+	createFolderWindow = new CreateFolderWindow();
+	createFolderWindow->visible = false;
+	createFolderWindow->enabled = false;
+
+	createFolderWindow->setPosition(100, 150);
+
+	createFolderWindow->okButton->addEventListener(this, UIEvent::CLICK_EVENT);
+	createFolderWindow->cancelButton->addEventListener(this, UIEvent::CLICK_EVENT);
+
+	addChild(createFolderWindow);
+
+	doChangeFolder = false;
+	addToSidebar("/", "Filesystem");
+	addToSidebar(CoreServices::getInstance()->getCore()->getUserHomeDirectory(), "Home");
+}
+
+void UIFileDialog::addToSidebar(String path, String name) {
+	OSFileEntry backEntry;
+	backEntry.type = OSFileEntry::TYPE_FOLDER;
+	backEntry.name = name;
+	backEntry.fullPath = path;
+
+	UIFileDialogEntry *newEntry = new UIFileDialogEntry(backEntry, true, 140, true);
+	addChild(newEntry);
+	newEntry->setPosition(10, 40 + (sideBarEntries.size() * 20));
+	sideBarEntries.push_back(newEntry);
+	newEntry->bg->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
+}
+
+void UIFileDialog::clearEntries() {
+	for(int i=0; i < entries.size(); i++) {
+		entryHolder->removeChild(entries[i]);
+		delete entries[i];	
+	}
+	entries.clear();
+}
+
+void UIFileDialog::onClose() {
+	dispatchEvent(new UIEvent(), UIEvent::CANCEL_EVENT);
+}
+
+String UIFileDialog::getSelection() {
+	return selection;
+}
+
+void UIFileDialog::showFolder(String folderPath) {
+	doChangeFolder = false;
+
+	currentFolderPath = folderPath;
+
+	if(foldersOnly) {
+		selection = folderPath;
+	}
+
+
+	for(int i=0; i < sideBarEntries.size(); i++) {
+		sideBarEntries[i]->Deselect();
+	}
+
+	currentEntry = NULL;
+	clearEntries();
+
+	std::vector<OSFileEntry> _entries = OSBasics::parseFolder(folderPath, false);
+	
+	int offset = 0;
+	if(folderPath != "/") {
+	offset = 1;
+	OSFileEntry backEntry;
+	backEntry.type = OSFileEntry::TYPE_FOLDER;
+	backEntry.name = "..";
+	backEntry.basePath = folderPath;
+	backEntry.fullPath = folderPath+"/..";
+
+	UIFileDialogEntry *newEntry = new UIFileDialogEntry(backEntry, true);
+	entryHolder->addChild(newEntry);
+	entries.push_back(newEntry);
+	newEntry->bg->addEventListener(this, InputEvent::EVENT_DOUBLECLICK);
+	newEntry->bg->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
+	}
+
+	int i;
+	for(i=0; i < _entries.size(); i++) {
+		bool canSelect = false;
+		if(foldersOnly) {
+			if(_entries[i].type == OSFileEntry::TYPE_FOLDER) {
+				canSelect = true;
+			}
+		} else {
+
+		}
+		UIFileDialogEntry *newEntry = new UIFileDialogEntry(_entries[i], canSelect);
+		entryHolder->addChild(newEntry);
+		newEntry->setPosition(0, (i+offset) * 20);
+		entries.push_back(newEntry);	
+		newEntry->bg->addEventListener(this, InputEvent::EVENT_DOUBLECLICK);
+		newEntry->bg->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
+	}
+	scrollContainer->setContentSize(500-160, (i+offset) * 20);
+}
+
+void UIFileDialog::Update() {
+	if(doChangeFolder) {
+		showFolder(newPath);
+		doChangeFolder = false;
+	}
+}
+
+void UIFileDialog::handleEvent(Event *event) {
+
+	for(int i=0; i < sideBarEntries.size(); i++) {
+		if(event->getDispatcher() == sideBarEntries[i]->bg) {
+			showFolder(sideBarEntries[i]->fileEntry.fullPath);
+			sideBarEntries[i]->Select();
+		}
+	}
+
+	for(int i=0; i < entries.size(); i++) {
+		if(event->getDispatcher() == entries[i]->bg) {
+			
+			switch(event->getEventCode()) {
+				case InputEvent::EVENT_DOUBLECLICK:
+					if(entries[i]->fileEntry.type == OSFileEntry::TYPE_FOLDER && entries[i]->canSelect) {
+						doChangeFolder = true;
+						if(entries[i]->fileEntry.name == "..") {
+							std::vector<String> bits = currentFolderPath.split("/");
+							newPath = "";
+							if(bits.size() > 2) {
+								for(int i=1; i < bits.size()-1; i++) {
+									newPath += "/"+bits[i];
+								}
+							} else {
+								newPath = "/";
+							}
+						} else{
+							newPath = entries[i]->fileEntry.fullPath;
+						}
+					}
+				break;
+				case InputEvent::EVENT_MOUSEDOWN:
+					if(entries[i]->canSelect) {
+						if(currentEntry)
+							currentEntry->Deselect();
+						entries[i]->Select();
+						currentEntry = entries[i];
+						if(foldersOnly) {
+							selection = entries[i]->fileEntry.fullPath;
+						}
+					}
+				break;
+			}
+		}
+	}
+
+	if(event->getDispatcher() == okButton) {
+		dispatchEvent(new UIEvent(), UIEvent::OK_EVENT);
+	}
+
+	if(event->getDispatcher() == cancelButton) {
+		dispatchEvent(new UIEvent(), UIEvent::CANCEL_EVENT);
+	}
+
+	if(event->getDispatcher() == createFolderWindow->okButton) {
+		CoreServices::getInstance()->getCore()->createFolder(currentFolderPath+"/"+createFolderWindow->nameInput->getText());
+		createFolderWindow->visible = false;
+		createFolderWindow->enabled = false;
+		showFolder(currentFolderPath);	
+	}
+
+	if(event->getDispatcher() == createFolderWindow->cancelButton) {
+		createFolderWindow->visible = false;
+		createFolderWindow->enabled = false;
+	}
+
+
+	if(event->getDispatcher() == newFolderButton) {
+		createFolderWindow->nameInput->setText("");
+		createFolderWindow->visible = true;
+		createFolderWindow->enabled = true;
+		
+	}
+
+	UIWindow::handleEvent(event);
+}
+
+UIFileDialog::~UIFileDialog() {
+
+}
+
+CreateFolderWindow::CreateFolderWindow() : UIWindow("New folder name", 290, 80) {
+	ownsChildren = true;
+	
+	closeBtn->visible = false;
+	closeBtn->enabled = false;
+
+	nameInput = new UITextInput(false, 270, 16);
+	addChild(nameInput);
+	nameInput->setPosition(20, 34);
+
+	cancelButton = new UIButton("Cancel", 100);
+	addChild(cancelButton);
+	cancelButton->setPosition(300-210, 80 - 12);
+
+	okButton = new UIButton("OK",  100);
+	addChild(okButton);
+	okButton->setPosition(300-100, 80 - 12);
+}
+
+CreateFolderWindow::~CreateFolderWindow() {
+	
+}