(C++) FileSaveDialog patch [v0.1]

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.

(C++) FileSaveDialog patch [v0.1]

Postby Rambus » Thu Mar 27, 2008 10:19 pm

FileSaveDialog is a GUI object much like FileOpenDialog that allows a user to specify an output path for a file. A user can check if the file selected/entered exists and decide if the location is valid. It looks *almost* identical to FileOpenDialog.

The full version includes
-compiled irrlicht.dll (dx9,dx8,openGl)
-pre-compiled example usage (Examples/05.UserInterface)
-Full source code, ready to build visual studio 05 project file.
-New, updated version of ChatQueue 0.3.2 built into the irrlicht.dll and included in the full source code.

The latest version of the code is available at:
www.g0dsoft.com/irrlicht/FileSaveDialog/v01/full.zip

And for just the changes to the irrlicht source: (Much smaller)
www.g0dsoft.com/irrlicht/FileSaveDialog/v01/src.zip

Image

(ChatQueue) Updated for 0.3.2
-Fixed a uncommon bug with word wrapping.

ToDo:
-Allow a user to define what output file types are acceptable.
-Filter directory list by acceptable file types.

Note: The code was built off of an irrlicht widget and as such may still be covered under the irrlicht liscense. The FileSaveWidget is proposed as a patch, rather then a user widget.

See 05.UserInterface/main.cpp for example usage.

IGUIFileSaveQueue.h
Code: Select all
/*
FileSaveDialog is a unofficial modification/addition to the Irrlicht Source code.
Version: 0.1
Code by: Mark Laprairie
Contact: webmaster@g0dsoft.com
Url: www.g0dsoft.com
*/

#ifndef __I_GUI_FILE_SAVE_DIALOG_H_INCLUDED__
#define __I_GUI_FILE_SAVE_DIALOG_H_INCLUDED__

#include "IGUIElement.h"

namespace irr
{
namespace gui
{

   //! Standard file chooser dialog.
   class IGUIFileSaveDialog : public IGUIElement
   {
   public:

      //! constructor
      IGUIFileSaveDialog(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle)
         : IGUIElement(EGUIET_FILE_SAVE_DIALOG, environment, parent, id, rectangle) {}

      //! destructor
      virtual ~IGUIFileSaveDialog() {}

      //! Returns the filename of the selected file. Returns NULL, if no file was selected.
      virtual const wchar_t* getFileName() const = 0;
   };


} // end namespace gui
} // end namespace irr

#endif


CGUIFileSaveQueue.h
Code: Select all
/*
FileSaveDialog is a unofficial modification/addition to the Irrlicht Source code.
For conditions of distribution and use, see copyright notice in irrlicht.h
Version: 0.1
Code by: Mark Laprairie
Contact: webmaster@g0dsoft.com
Url: www.g0dsoft.com
*/

#ifndef __C_GUI_FILE_SAVE_DIALOG_H_INCLUDED__
#define __C_GUI_FILE_SAVE_DIALOG_H_INCLUDED__

#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_GUI_

#include "IGUIFileSaveDialog.h"
#include "IGUIButton.h"
#include "IGUIListBox.h"
#include "IGUIEditBox.h"
#include "IFileSystem.h"

namespace irr
{
namespace gui
{

   class CGUIFileSaveDialog : public IGUIFileSaveDialog
   {
   public:

      //! constructor
      CGUIFileSaveDialog(const wchar_t* title, IGUIEnvironment* environment, IGUIElement* parent, s32 id);

      //! destructor
      virtual ~CGUIFileSaveDialog();

      //! returns the filename of the selected file. Returns NULL, if no file was selected.
      virtual const wchar_t* getFileName() const;

      //! called if an event happened.
      virtual bool OnEvent(const SEvent& event);

      //! draws the element and its children
      virtual void draw();

   protected:

      //! fills the listbox with files.
      void fillListBox();

      //! sends the event that the file has been selected.
      void sendSelectedEvent();

      //! sends the event that the file choose process has been canceld
      void sendCancelEvent();

      core::position2d<s32> DragStart;
      core::stringw FileName;
      bool Dragging;
      IGUIButton* CloseButton;
      IGUIButton* OKButton;
      IGUIButton* CancelButton;
      IGUIListBox* FileBox;
      IGUIElement* FileNameText;
      IGUIElement* EventParent;
      io::IFileSystem* FileSystem;

      io::IFileList* FileList;
   };


} // end namespace gui
} // end namespace irr

#endif // _IRR_COMPILE_WITH_GUI_

#endif // __C_GUI_FILE_Save_DIALOG_H_INCLUDED__


CGUIFileSaveQueue.cpp
Code: Select all
/*
FileSaveDialog is a unofficial modification/addition to the Irrlicht Source code.
For conditions of distribution and use, see copyright notice in irrlicht.h
Version: 0.1
Code by: Mark Laprairie
Contact: webmaster@g0dsoft.com
Url: www.g0dsoft.com
*/

#include "CGUIFileSaveDialog.h"
#ifdef _IRR_COMPILE_WITH_GUI_

#include "IGUISkin.h"
#include "IGUIEnvironment.h"
#include "IVideoDriver.h"
#include "IGUIButton.h"
#include "IGUIFont.h"
#include "IGUIFontBitmap.h"
#include "IFileList.h"
#include "os.h"

namespace irr
{
namespace gui
{

const s32 FOD_WIDTH = 350;
const s32 FOD_HEIGHT = 250;


//! constructor
CGUIFileSaveDialog::CGUIFileSaveDialog(const wchar_t* title,
      IGUIEnvironment* environment, IGUIElement* parent, s32 id)
: IGUIFileSaveDialog(environment, parent, id,
      core::rect<s32>((parent->getAbsolutePosition().getWidth()-FOD_WIDTH)/2,
               (parent->getAbsolutePosition().getHeight()-FOD_HEIGHT)/2,
               (parent->getAbsolutePosition().getWidth()-FOD_WIDTH)/2+FOD_WIDTH,
               (parent->getAbsolutePosition().getHeight()-FOD_HEIGHT)/2+FOD_HEIGHT)),
   Dragging(false), FileNameText(0), FileList(0)
{
   #ifdef _DEBUG
   IGUIElement::setDebugName("CGUIFileSaveDialog");
   #endif

   Text = title;
   FileName = L"";

   IGUISkin* skin = Environment->getSkin();
   IGUISpriteBank* sprites = 0;
   video::SColor color(255,255,255,255);
   if (skin)
   {
      sprites = skin->getSpriteBank();
      color = skin->getColor(EGDC_WINDOW_SYMBOL);
   }

   s32 buttonw = environment->getSkin()->getSize(EGDS_WINDOW_BUTTON_WIDTH);
   s32 posx = RelativeRect.getWidth() - buttonw - 4;

   CloseButton = Environment->addButton(core::rect<s32>(posx, 3, posx + buttonw, 3 + buttonw), this, -1,
      L"", skin ? skin->getDefaultText(EGDT_WINDOW_CLOSE) : L"Close");
   CloseButton->setSubElement(true);
   CloseButton->setTabStop(false);
   if (sprites)
   {
      CloseButton->setSpriteBank(sprites);
      CloseButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_CLOSE), color);
      CloseButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_CLOSE), color);
   }
   CloseButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
   CloseButton->grab();

   OKButton = Environment->addButton(
      core::rect<s32>(RelativeRect.getWidth()-80, 30, RelativeRect.getWidth()-10, 50),
      this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_OK) : L"OK");
   OKButton->setSubElement(true);
   OKButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
   OKButton->grab();

   CancelButton = Environment->addButton(
      core::rect<s32>(RelativeRect.getWidth()-80, 55, RelativeRect.getWidth()-10, 75),
      this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_CANCEL) : L"Cancel");
   CancelButton->setSubElement(true);
   CancelButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
   CancelButton->grab();

   FileBox = Environment->addListBox(core::rect<s32>(10, 55, RelativeRect.getWidth()-90, 230), this, -1,true);
   FileBox->setSubElement(true);
   FileBox->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
   FileBox->grab();

   FileNameText = Environment->addEditBox(L"",core::rect<s32>(10, 30, RelativeRect.getWidth()-90, 50), true, this,-1);
   FileNameText->setSubElement(true);
   FileNameText->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
   FileNameText->grab();

   FileSystem = Environment->getFileSystem();

   if (FileSystem)
      FileSystem->grab();

   setTabGroup(true);

   fillListBox();
}


//! destructor
CGUIFileSaveDialog::~CGUIFileSaveDialog()
{
   if (CloseButton)
      CloseButton->drop();

   if (OKButton)
      OKButton->drop();

   if (CancelButton)
      CancelButton->drop();

   if (FileBox)
      FileBox->drop();

   if (FileNameText)
      FileNameText->drop();

   if (FileSystem)
      FileSystem->drop();

   if (FileList)
      FileList->drop();
}


//! returns the filename of the selected file. Returns NULL, if no file was selected.
const wchar_t* CGUIFileSaveDialog::getFileName() const
{
   return FileName.c_str();
}


//! called if an event happened.
bool CGUIFileSaveDialog::OnEvent(const SEvent& event)
{
   switch(event.EventType)
   {
   case EET_GUI_EVENT:
      switch(event.GUIEvent.EventType)
      {
         case EGET_ELEMENT_FOCUS_LOST:
            Dragging = false;
            break;
         case EGET_EDITBOX_ENTER:
            if(event.GUIEvent.Caller != FileNameText)
               break;
         case EGET_BUTTON_CLICKED:
            if (event.GUIEvent.Caller == CloseButton ||
               event.GUIEvent.Caller == CancelButton)
            {
               sendCancelEvent();
               remove();
               return true;
            }
            else
            {
               if (event.GUIEvent.Caller == OKButton || event.GUIEvent.Caller == FileNameText)
               {
                  if((core::stringw)FileNameText->getText() != L"")
                  {
                     core::stringw s;
                     s = FileSystem->getWorkingDirectory();
                     if(s.findLast('\\',-1) != s.findFirst('\\'))
                        s.append('\\');
                     s.append(FileNameText->getText());
                     FileName = s.c_str();
                     os::Printer::log(s.c_str());
                     sendSelectedEvent();
                     remove();
                     return true;
                  }
               }
            }
            break;

         case EGET_LISTBOX_CHANGED:
            {
               s32 selected = FileBox->getSelected();
               if (FileList && FileSystem && !(FileList->isDirectory(selected)) )
               {
                     core::stringw s;
                     s = FileList->getFileName(selected);
                     FileNameText->setText(s.c_str());
                     return true;
               }
            }
            break;
         case EGET_LISTBOX_SELECTED_AGAIN:
            {
               const s32 selected = FileBox->getSelected();
               if (FileList && FileSystem)
               {
                  if (FileList->isDirectory(selected))
                  {
                     FileSystem->changeWorkingDirectoryTo(FileList->getFileName(selected));
                     fillListBox();
                  }
                  else
                  {
                     core::stringw s;
                     s = FileList->getFileName(selected);
                     FileNameText->setText(s.c_str());
                     return true;
                  }
               }
            }
            break;
         default: //For GCC compatibility
            break;
      }
      break;
   case EET_MOUSE_INPUT_EVENT:
      switch(event.MouseInput.Event)
      {
      case EMIE_MOUSE_WHEEL:
         return FileBox->OnEvent(event);
      case EMIE_LMOUSE_PRESSED_DOWN:
         DragStart.X = event.MouseInput.X;
         DragStart.Y = event.MouseInput.Y;
         Dragging = true;
         Environment->setFocus(this);
         return true;
      case EMIE_LMOUSE_LEFT_UP:
         Dragging = false;
         return true;
      case EMIE_MOUSE_MOVED:
         if (Dragging)
         {
            // gui window should not be dragged outside its parent
            if (Parent)
               if (event.MouseInput.X < Parent->getAbsolutePosition().UpperLeftCorner.X +1 ||
                  event.MouseInput.Y < Parent->getAbsolutePosition().UpperLeftCorner.Y +1 ||
                  event.MouseInput.X > Parent->getAbsolutePosition().LowerRightCorner.X -1 ||
                  event.MouseInput.Y > Parent->getAbsolutePosition().LowerRightCorner.Y -1)

                  return true;

            move(core::position2d<s32>(event.MouseInput.X - DragStart.X, event.MouseInput.Y - DragStart.Y));
            DragStart.X = event.MouseInput.X;
            DragStart.Y = event.MouseInput.Y;
            return true;
         }
         break;
      default:
         break;
      }
   default:
      break;
   }

   return Parent ? Parent->OnEvent(event) : false;
}


//! draws the element and its children
void CGUIFileSaveDialog::draw()
{
   if (!IsVisible)
      return;

   IGUISkin* skin = Environment->getSkin();

   core::rect<s32> rect = AbsoluteRect;

   rect = skin->draw3DWindowBackground(this, true, skin->getColor(EGDC_ACTIVE_BORDER),
      rect, &AbsoluteClippingRect);

   if (Text.size())
   {
      rect.UpperLeftCorner.X += 2;
      rect.LowerRightCorner.X -= skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) + 5;

      IGUIFont* font = skin->getFont(EGDF_WINDOW);
      if (font)
         font->draw(Text.c_str(), rect,
               skin->getColor(EGDC_ACTIVE_CAPTION),
               false, true, &AbsoluteClippingRect);
   }

   IGUIElement::draw();
}


//! fills the listbox with files.
void CGUIFileSaveDialog::fillListBox()
{
   IGUISkin *skin = Environment->getSkin();

   if (!FileSystem || !FileBox || !skin)
      return;

   if (FileList)
      FileList->drop();

   FileBox->clear();

   FileList = FileSystem->createFileList();
   core::stringw s;

   for (u32 i=0; i<FileList->getFileCount(); ++i)
   {
      s = FileList->getFileName(i);
      FileBox->addItem(s.c_str(), skin->getIcon(FileList->isDirectory(i) ? EGDI_DIRECTORY : EGDI_FILE));
   }
}


//! sends the event that the file has been selected.
void CGUIFileSaveDialog::sendSelectedEvent()
{
   SEvent event;
   event.EventType = EET_GUI_EVENT;
   event.GUIEvent.Caller = this;
   event.GUIEvent.Element = 0;
   event.GUIEvent.EventType = EGET_FILE_SELECTED;
   Parent->OnEvent(event);
}


//! sends the event that the file choose process has been canceld
void CGUIFileSaveDialog::sendCancelEvent()
{
   SEvent event;
   event.EventType = EET_GUI_EVENT;
   event.GUIEvent.Caller = this;
   event.GUIEvent.Element = 0;
   event.GUIEvent.EventType = EGET_FILE_CHOOSE_DIALOG_CANCELLED;
   Parent->OnEvent(event);
}

} // end namespace gui
} // end namespace irr

#endif // _IRR_COMPILE_WITH_GUI_
Rambus
 
Posts: 96
Joined: Thu Nov 24, 2005 4:56 pm
Location: Canada

Postby christianclavet » Tue Jul 22, 2008 4:30 pm

Hi, That's very nice.

I've done a version with filetypes icons but the code is looking very bad. (Right now it seem to compile only on DEVC++, and failed for some on Linux and other (Perhaps because of the iconbank)

I think it will take some time before we're able to mimic our OS's dialogs. (Path, drive selection, "favorites", filetypes, etc)

Do you plan to do other versions in the future?
User avatar
christianclavet
 
Posts: 1638
Joined: Mon Apr 30, 2007 3:24 am
Location: Montreal, CANADA

Postby Seven » Tue Jul 22, 2008 8:32 pm

two things I have always wanted and will hack into these.

1) dont change directories when selecting a file, or at least change back to the original when the file is selected

2) Filter directory list by acceptable file types if this means something like *.dat and only .dat files show up.
Seven
 
Posts: 871
Joined: Mon Nov 14, 2005 2:03 pm

Postby vitek » Tue Jul 22, 2008 11:42 pm

Seven wrote:two things I have always wanted and will hack into these.

1) dont change directories when selecting a file, or at least change back to the original when the file is selected

Easily done by having the dialog cache the working directory and restore it.

Seven wrote:2) Filter directory list by acceptable file types if this means something like *.dat and only .dat files show up.

Code for doing that with the original file dialog is here...
Last edited by vitek on Thu Jul 31, 2008 5:04 pm, edited 1 time in total.
User avatar
vitek
Bug Slayer
 
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Postby pera » Thu Jul 31, 2008 10:44 am

Simple file type selector:

Code: Select all
s = FileList->getFileName(i);
if (FileList->isDirectory(i) || (s.find(".irr")> -1))
   FileBox->addItem(s.c_str(), skin->getIcon(FileList->isDirectory(i) ? EGDI_DIRECTORY : EGDI_FILE));
pera
 
Posts: 460
Joined: Wed May 14, 2008 1:05 pm
Location: Novi Sad, Serbia

Postby JP » Thu Jul 31, 2008 10:51 am

I've done a simple upgrade of irrlicht's filedialog which doesn't affect the working directory (using the method vitek mentions basically) and also allows a file filter to be specified.

I also made it standard for open/save type uses which i think is probably a better idea, rather than having one type for opening and one type for saving, seems to be the commonly used approach.

Another thing i 'solved' was to allow drive switching which the standard irrlicht filedialog doesn't allow, you can only navigate the drive that the working directory is on. But i didn't solve this nicely, i just put an edit box to put the requested drive letter in and then a button to make the change... not very elegant but it gets the job done :lol:

anyway, this looks good and thanks for sharing it. If anyone's interested in mine then it's available via IrrAI and is in the IrrAI Editor source folder.
Image Image Image
User avatar
JP
 
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK

Postby pera » Thu Jul 31, 2008 4:57 pm

You don't have link to irrAI in your signature?
pera
 
Posts: 460
Joined: Wed May 14, 2008 1:05 pm
Location: Novi Sad, Serbia

Postby JP » Fri Aug 01, 2008 10:16 am

Clearly not :lol:
Image Image Image
User avatar
JP
 
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK

Postby CarlS » Sun Aug 03, 2008 5:45 pm

Thanks for making this available :)

--Carl
User avatar
CarlS
 
Posts: 86
Joined: Wed May 09, 2007 1:21 am

Postby Seven » Sun Aug 31, 2008 12:43 am

JP wrote: and also allows a file filter to be specified.


JP,
Could you make it so that you can specify multiple file types. For example, when allowing the user to select an animation file, something like this might be nice. "*.X,*.md2,*.MD3" or for sound ""*.mp3,*.ogg"

Seven
Seven
 
Posts: 871
Joined: Mon Nov 14, 2005 2:03 pm


Return to Code Snippets

Who is online

Users browsing this forum: No registered users and 1 guest