You need boost/filesystem library for this! It's not included in depedencys of Ogre packet.
YourApplication
//Create new dialog: m_pFileDialog = new FileSelectionDialog; m_pFileDialog->setDialogTitle("Save file"); m_pFileDialog->setButtonCaption("Save"); m_pFileDialog->addFileExtension(".h"); m_pFileDialog->addFileExtension(".cpp"); //Add youd own callback function: boost::function<void(Dialog*, const std::string&)> my_callback = boost::bind(&My_Class::myFileSelectedCallBack, this, _1, _2); m_pFileDialog->eventEndDialog(my_callback); //Your callback must be something like that: //void myFileSelectedCallBack(FileSelectionDialog* dialog, const std::string& path){...Do what you want...}; //How to pop it up: m_pFileDialog->update(); m_pFileDialog->setVisible(true); //After all don't foget delete it: delete m_pFileDialog;
FileDialog.layout
<?xml version="1.0" encoding="UTF-8"?> <MyGUI type="Layout" version="3.2.0"> <Widget type="Window" skin="WindowCSX" position="40 44 505 351" layer="Main" name="DialogWindow"> <Widget type="ListBox" skin="ListBox" position="5 35 485 246" align="Stretch" name="List"/> <Widget type="ComboBox" skin="ComboBox" position="5 3 485 30" align="HStretch Top" name="Recent"/> <Widget type="Button" skin="Button" position="400 285 90 26" align="Right Bottom" name="Confirm"/> <Widget type="EditBox" skin="EditBox" position="5 285 285 26" align="HStretch Bottom" name="Edit"/> <Widget type="ComboBox" skin="ComboBox" position="300 285 95 26" align="Right Bottom" name="Extension"/> </Widget> </MyGUI>
FileSelectionDialog.h
#ifndef DIALOG_H #define DIALOG_H #include <boost\filesystem.hpp> #include <boost\function.hpp> #include <MyGUI.h> class FileSelectionDialog { public: FileSelectionDialog(const std::string& name); const std::string& getName(); void update(); void setVisible(bool set); void setDialogTitle(const std::string& title); void setButtonCaption(const std::string& caption); void addFileExtension(const std::string& ext); void setDefaultExtension(int index); void setUserString(const std::string& value); void buildGUI(); const std::string& getUserString(); void eventEndDialog(boost::function<void(FileSelectionDialog*, const std::string&)> method); private: void windowCloseCallback(MyGUI::Window* _sender, const std::string& _name); void itemAcceptedCallback(MyGUI::ListBox* _sender, size_t _index); void itemSelectedCallback(MyGUI::ListBox* _sender, size_t _index); void recentPathSelectedCallback(MyGUI::ComboBox* _sender, size_t _index); void endDialogCallback(MyGUI::Widget* _sender); void windowResizeCallback(MyGUI::Widget* _sender, const std::string& _key, const std::string& _value); void extensionChangeCallback(MyGUI::ComboBox* _sender, size_t _index); void updatePathList(boost::filesystem::path my_path); //static int nDialogs; //int mDialogIndex; //void (GUIManager::*mUserMethod)(const std::string&, const std::string&); std::string mName; std::string mUserString; // user callback boost::function<void(FileSelectionDialog*, const std::string&)> mUserMethod; // widgets MyGUI::Window* mWindow; MyGUI::List* mPathList; MyGUI::Edit* mFileEdit; MyGUI::Button* mButton; MyGUI::ComboBox* mRecentCombo; MyGUI::ComboBox* mExtensionCombo; boost::filesystem::path mCurrentPath; // current viewed directory std::vector<boost::filesystem::path> mPath_set; // list of paths in the viewed directory boost::filesystem::path* mSelectedFile; std::vector<boost::filesystem::path> mRecentPaths; }; #endif // DIALOG_H
FileSelectionDialog.cpp
#include "FileSelectionDialog.h" using namespace boost::filesystem; //int Dialog::nDialogs = 0; FileSelectionDialog::FileSelectionDialog(const std::string& name) : mName(name), mWindow(0), mPathList(0), mFileEdit(0), mButton(0), mRecentCombo(0), mExtensionCombo(0), mSelectedFile(0), mUserMethod(0) { buildGUI(); } //========================================================================== // Useful after after deleted all widgets from scene //========================================================================== void FileSelectionDialog::buildGUI(){ // load dialog layout MyGUI::VectorWidgetPtr widgets = MyGUI::LayoutManager::getInstance().loadLayout("FileDialog.layout"); mWindow = (MyGUI::Window*)*widgets.begin(); mWindow->eventWindowButtonPressed += MyGUI::newDelegate(this, &FileSelectionDialog::windowCloseCallback); mWindow->setVisible(false); mPathList = (MyGUI::List*)mWindow->findWidget("List"); mPathList->eventListSelectAccept += MyGUI::newDelegate(this, &FileSelectionDialog::itemAcceptedCallback); mPathList->eventListChangePosition += MyGUI::newDelegate(this, &FileSelectionDialog::itemSelectedCallback); mFileEdit = (MyGUI::Edit*)mWindow->findWidget("Edit"); mButton = (MyGUI::Button*)mWindow->findWidget("Confirm"); mButton->eventMouseButtonClick += MyGUI::newDelegate(this, &FileSelectionDialog::endDialogCallback); mRecentCombo = (MyGUI::ComboBox*)mWindow->findWidget("Recent"); mRecentCombo->eventComboChangePosition += MyGUI::newDelegate(this, &FileSelectionDialog::recentPathSelectedCallback); mExtensionCombo = (MyGUI::ComboBox*)mWindow->findWidget("Extension"); mExtensionCombo->eventComboChangePosition += MyGUI::newDelegate(this, &FileSelectionDialog::extensionChangeCallback); mExtensionCombo->addItem("All files \".\""); mExtensionCombo->setIndexSelected(0); } //========================================================================== // User closed Dialog window //========================================================================== void FileSelectionDialog::windowCloseCallback(MyGUI::Window* _sender, const std::string& _name) { mWindow->setVisible(false); } //========================================================================== // User selected a path (double-clicked) //========================================================================== void FileSelectionDialog::itemAcceptedCallback(MyGUI::ListBox* _sender, size_t _index) { if (_index == 0) // user clicked on the "[...]", so back up a directory { updatePathList(mCurrentPath.parent_path().string()); } // it's a folder, open it else if (is_directory(mPath_set[_index-1])) { updatePathList(mPath_set[_index-1]); } // it's a file, notify user and quit else { endDialogCallback(0); } } //========================================================================== // User selected a path (single click) //========================================================================== void FileSelectionDialog::itemSelectedCallback(MyGUI::ListBox* _sender, size_t _index) { //TODO fix bug?: if in filelist, file / folder selected and then click to list box to empty line, calls this with _index = int.max(?) if (_index > mPath_set.size()) return; // make sure it's a file if (_index != 0 && !is_directory(mPath_set[_index-1])) { // mark as selected mSelectedFile = &mPath_set[_index-1]; mFileEdit->setCaption(mPathList->getItemNameAt(_index)); } } //========================================================================== // User re-opened a recently visited folder //========================================================================== void FileSelectionDialog::recentPathSelectedCallback(MyGUI::ComboBox* _sender, size_t _index) { updatePathList(mRecentPaths[_index].parent_path()); } //========================================================================== // Dialog's closed //========================================================================== void FileSelectionDialog::endDialogCallback(MyGUI::Widget* _sender) { // last minute fix --forgot to account for the user entering the filename himself // Note that since the Dialog has no idea if the user should be creating a new file, it doesn't check if the // file exists or not. That's your job. std::string filename = mFileEdit->getCaption(); // make sure it has an extension if (mExtensionCombo->getIndexSelected() != 0) { std::string extension = mExtensionCombo->getCaption(); if (filename.length() > extension.length()) { if(filename.compare(filename.length() - extension.length(), extension.length(), extension)) filename.append(extension); } else filename.append(extension); } mSelectedFile = new path(mPath_set[0].parent_path().append(filename.begin(), filename.end())); //-- if (mSelectedFile) { // notify user of selected file (empty string if none) if (mUserMethod) { mUserMethod(this, mSelectedFile->string()); } // update recently visited paths bool newEntry = true; for (size_t i = 0; i < mRecentPaths.size(); i++) { if (*mSelectedFile == mRecentPaths[i]) { newEntry = false; break; } } if (newEntry) { mRecentPaths.push_back(*mSelectedFile); mRecentCombo->addItem(mSelectedFile->parent_path().string()); } // close dialog mWindow->setVisible(false); } // follow up of the fix delete mSelectedFile; mSelectedFile = 0; } //========================================================================== // called when a new extension is set //========================================================================== void FileSelectionDialog::extensionChangeCallback(MyGUI::ComboBox* _sender, size_t _index) { update(); } //========================================================================== // Set callback for when a file is selected //========================================================================== void FileSelectionDialog::eventEndDialog(boost::function<void(FileSelectionDialog*, const std::string&)> method) { mUserMethod = method; } //========================================================================== // get dialog name //========================================================================== const std::string& FileSelectionDialog::getName() { return mName; } //========================================================================== // Must be called once dialog is initialized with the functions below //========================================================================== void FileSelectionDialog::update() { updatePathList(current_path()); } //========================================================================== // show/hide dialog //========================================================================== void FileSelectionDialog::setVisible(bool set) { mWindow->setVisible(set); } //========================================================================== // set dialog window title //========================================================================== void FileSelectionDialog::setDialogTitle(const std::string& title) { mWindow->setCaption(title); } //========================================================================== // set button caption (ie: save, load, save as..) //========================================================================== void FileSelectionDialog::setButtonCaption(const std::string& caption) { mButton->setCaption(caption); } //========================================================================== // Attaches a string to this dialog that can be retrieved later. // Handy for using the same Dialog for different things //========================================================================== void FileSelectionDialog::setUserString(const std::string& value) { mUserString = value; } //========================================================================== // Return user string //========================================================================== const std::string& FileSelectionDialog::getUserString() { return mUserString; } //========================================================================== // Add an extension to the extension combobox //========================================================================== void FileSelectionDialog::addFileExtension(const std::string& ext) { mExtensionCombo->addItem(ext); mExtensionCombo->setIndexSelected(0); // MyGUI appears to reset // the selected item to ITEM_NONE // whenever a new item is added } //========================================================================== // If this isn't called, the default is show all files. //========================================================================== void FileSelectionDialog::setDefaultExtension(int index) { mExtensionCombo->setIndexSelected(index + 1); } //========================================================================== // Sort paths alphabetically (folders first, files last) //========================================================================== bool sortFunction(boost::filesystem::path p1, boost::filesystem::path p2) { bool d1 = is_directory(p1); bool d2 = is_directory(p2); if (d1 && d2) return (p1.filename() < p2.filename()); else if (d1) return true; else if (d2) return false; else return (p1.filename() < p2.filename()); } //========================================================================== // Update the paths in the dialog // my_path; parent directory // Note: this function is slow. Mainly because i'm lazy. //========================================================================== void FileSelectionDialog::updatePathList(path my_path) { mCurrentPath = my_path; mPathList->removeAllItems(); mPath_set.clear(); mPathList->addItem("[...]"); std::vector<path> temp_paths; try { copy(directory_iterator(mCurrentPath), directory_iterator(), back_inserter(temp_paths)); } catch(const filesystem_error& ex) { // the user probably backed up too far. Jackass. mCurrentPath = current_path().parent_path(); copy(directory_iterator(mCurrentPath), directory_iterator(), back_inserter(temp_paths)); } // some shitty OSs don't sort paths.. sort(temp_paths.begin(), temp_paths.end(), sortFunction); // extension std::string ext = mExtensionCombo->getItem(mExtensionCombo->getIndexSelected()); for (size_t i = 0; i < temp_paths.size(); i++) { // folder if (is_directory(temp_paths[i])) { mPath_set.push_back(temp_paths[i]); mPathList->addItem(MyGUI::UString("[") + MyGUI::UString(temp_paths[i].filename().c_str()) + ']'); } // file else { // filter to extension (if any) if (mExtensionCombo->getIndexSelected() != 0) { if (temp_paths[i].extension() == ext) { MyGUI::UString path = temp_paths[i].filename().c_str(); mPathList->addItem(path); mPath_set.push_back(temp_paths[i]); } } else { MyGUI::UString path = temp_paths[i].filename().c_str(); mPathList->addItem(path); mPath_set.push_back(temp_paths[i]); } } } }