From 51a58d8b4bb58b66ec84dc94c56fe328d77c904a Mon Sep 17 00:00:00 2001 From: Julian Smart Date: Sun, 23 Jul 2000 19:10:27 +0000 Subject: [PATCH] Added wxGenericDirCtrl, wxGenericDirDialog and associated icons. Altered dialog sample to show generic dir dialog. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@7811 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- distrib/msw/tmake/filelist.txt | 2 + include/wx/dirctrl.h | 7 + include/wx/generic/dirctrlg.h | 245 +++++++ include/wx/msw/cdrom.ico | Bin 0 -> 318 bytes include/wx/msw/computer.ico | Bin 0 -> 318 bytes include/wx/msw/drive.ico | Bin 0 -> 318 bytes include/wx/msw/file1.ico | Bin 0 -> 1078 bytes include/wx/msw/floppy.ico | Bin 0 -> 318 bytes include/wx/msw/folder1.ico | Bin 0 -> 1078 bytes include/wx/msw/folder2.ico | Bin 0 -> 318 bytes include/wx/msw/removble.ico | Bin 0 -> 318 bytes include/wx/msw/wx.rc | 22 +- samples/dialogs/dialogs.cpp | 20 + samples/dialogs/dialogs.h | 2 + src/generic/dirctrlg.cpp | 1204 ++++++++++++++++++++++++++++++++ src/msw/makefile.vc | 1 + src/wxvc.dsp | 4 + 17 files changed, 1501 insertions(+), 6 deletions(-) create mode 100644 include/wx/dirctrl.h create mode 100644 include/wx/generic/dirctrlg.h create mode 100644 include/wx/msw/cdrom.ico create mode 100644 include/wx/msw/computer.ico create mode 100644 include/wx/msw/drive.ico create mode 100644 include/wx/msw/file1.ico create mode 100644 include/wx/msw/floppy.ico create mode 100644 include/wx/msw/folder1.ico create mode 100644 include/wx/msw/folder2.ico create mode 100644 include/wx/msw/removble.ico create mode 100644 src/generic/dirctrlg.cpp diff --git a/distrib/msw/tmake/filelist.txt b/distrib/msw/tmake/filelist.txt index bc6e317f83..c8443f57f8 100644 --- a/distrib/msw/tmake/filelist.txt +++ b/distrib/msw/tmake/filelist.txt @@ -65,6 +65,7 @@ caret.cpp G U choicdgg.cpp G colrdlgg.cpp G G dcpsg.cpp G U +dirctrlg.cpp G dirdlgg.cpp G 16,P dragimgg.cpp G P fontdlgg.cpp G G,R,P @@ -1084,6 +1085,7 @@ caret.h N choicdgg.h N colrdlgg.h N dcpsg.h N +dirctrlg.h N dirdlgg.h N 16 dragimgg.h N 16 fontdlgg.h N diff --git a/include/wx/dirctrl.h b/include/wx/dirctrl.h new file mode 100644 index 0000000000..6fe73a80b8 --- /dev/null +++ b/include/wx/dirctrl.h @@ -0,0 +1,7 @@ +#ifndef _WX_DIRCTRL_H_BASE_ +#define _WX_DIRCTRL_H_BASE_ + +#include "wx/generic/dirctrlg.h" + +#endif + // _WX_DIRCTRL_H_BASE_ diff --git a/include/wx/generic/dirctrlg.h b/include/wx/generic/dirctrlg.h new file mode 100644 index 0000000000..05d354d1d0 --- /dev/null +++ b/include/wx/generic/dirctrlg.h @@ -0,0 +1,245 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: dirctrlg.h +// Purpose: wxGenericDirCtrl class +// Builds on wxDirCtrl class written by Robert Roebling for the +// wxFile application, modified by Harm van der Heijden. +// Further modified for Windows. +// Author: Julian Smart et al +// Modified by: +// Created: 21/3/2000 +// RCS-ID: $Id$ +// Copyright: (c) Julian Smart +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_DIRCTRL_H_ +#define _WX_DIRCTRL_H_ + +#ifdef __GNUG__ +#pragma interface "dirctrlg.h" +#endif + +#include "wx/treectrl.h" + +//----------------------------------------------------------------------------- +// classes +//----------------------------------------------------------------------------- + +class wxDirItemData; +class wxDirCtrl; + +//----------------------------------------------------------------------------- +// Extra styles for wxGenericDirCtrl +//----------------------------------------------------------------------------- + +// Only allow directory viewing/selection, no files +#define wxDIRCTRL_DIR_ONLY 0x0010 +// When setting the default path, select the first file in the directory +#define wxDIRCTRL_SELECT_FIRST 0x0020 +// Show the filter list +#define wxDIRCTRL_SHOW_FILTERS 0x0040 +// Use 3D borders on internal controls +#define wxDIRCTRL_3D_INTERNAL 0x0080 + +//----------------------------------------------------------------------------- +// wxDirItemData +//----------------------------------------------------------------------------- + +class WXDLLEXPORT wxDirItemDataEx : public wxTreeItemData +{ +public: + wxDirItemDataEx(const wxString& path, const wxString& name, bool isDir); + ~wxDirItemDataEx(); + bool HasSubDirs(); + void SetNewDirName( wxString path ); + wxString m_path, m_name; + bool m_isHidden; + bool m_hasSubDirs; + bool m_isExpanded; + bool m_isDir; +}; + +//----------------------------------------------------------------------------- +// wxDirCtrl +//----------------------------------------------------------------------------- + +class WXDLLEXPORT wxDirFilterListCtrl; + +class WXDLLEXPORT wxGenericDirCtrl: public wxControl +{ +public: + wxGenericDirCtrl(); + wxGenericDirCtrl(wxWindow *parent, const wxWindowID id = -1, + const wxString &dir = wxDirDialogDefaultFolderStr, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxDIRCTRL_3D_INTERNAL, + const wxString& filter = wxEmptyString, + int defaultFilter = 0, + const wxString& name = wxTreeCtrlNameStr ) + { + Init(); + Create(parent, id, dir, pos, size, style, filter, defaultFilter, name); + } + + bool Create(wxWindow *parent, const wxWindowID id = -1, + const wxString &dir = wxDirDialogDefaultFolderStr, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxDIRCTRL_3D_INTERNAL, + const wxString& filter = wxEmptyString, + int defaultFilter = 0, + const wxString& name = wxTreeCtrlNameStr ); + + void Init(); + + ~wxGenericDirCtrl(); + + void OnExpandItem(wxTreeEvent &event ); + void OnCollapseItem(wxTreeEvent &event ); + void OnBeginEditItem(wxTreeEvent &event ); + void OnEndEditItem(wxTreeEvent &event ); + void OnSize(wxSizeEvent &event ); + + // Try to expand as much of the given path as possible. + bool ExpandPath(const wxString& path); + + // Accessors + + inline wxString GetDefaultPath() const { return m_defaultPath; } + void SetDefaultPath(const wxString& path) { m_defaultPath = path; } + + //inline long GetStyleEx() const { return m_styleEx; } + //void SetStyleEx(long styleEx) { m_styleEx = styleEx; } + + // Get dir or filename + wxString GetPath() const ; + // Get selected filename path only (else empty string). + // I.e. don't count a directory as a selection + wxString GetFilePath() const ; + void SetPath(const wxString& path) ; + + wxString GetFilter() const { return m_filter; } + void SetFilter(const wxString& filter); + + int GetFilterIndex() const { return m_currentFilter; } + void SetFilterIndex(int n) ; + + wxTreeItemId GetRootId() { return m_rootId; } + + wxTreeCtrl* GetTreeCtrl() const { return m_treeCtrl; } + wxDirFilterListCtrl* GetFilterListCtrl() const { return m_filterListCtrl; } + +//// Helpers + void SetupSections(); + // Parse the filter into an array of filters and an array of descriptions + int ParseFilter(const wxString& filterStr, wxArrayString& filters, wxArrayString& descriptions); + // Find the child that matches the first part of 'path'. + // E.g. if a child path is "/usr" and 'path' is "/usr/include" + // then the child for /usr is returned. + // If the path string has been used (we're at the leaf), done is set to TRUE + wxTreeItemId FindChild(wxTreeItemId parentId, const wxString& path, bool& done); + + // Resize the components of the control + void DoResize(); +protected: + void ExpandDir(wxTreeItemId parentId); + void AddSection(const wxString& path, const wxString& name, int imageId = 0); + //void FindChildFiles(wxTreeItemId id, int dirFlags, wxArrayString& filenames); + + // Extract description and actual filter from overall filter string + bool ExtractWildcard(const wxString& filterStr, int n, wxString& filter, wxString& description); + +private: + bool m_showHidden; + wxTreeItemId m_rootId; + wxImageList* m_imageList; + wxString m_defaultPath; // Starting path + long m_styleEx; // Extended style + wxString m_filter; // Wildcards in same format as per wxFileDialog + int m_currentFilter; // The current filter index + wxString m_currentFilterStr; // Current filter string + wxTreeCtrl* m_treeCtrl; + wxDirFilterListCtrl* m_filterListCtrl; + +private: + DECLARE_EVENT_TABLE() + DECLARE_DYNAMIC_CLASS(wxGenericDirCtrl) +}; + +//----------------------------------------------------------------------------- +// wxDirFilterListCtrl +//----------------------------------------------------------------------------- + +class WXDLLEXPORT wxDirFilterListCtrl: public wxChoice +{ +public: + wxDirFilterListCtrl() { Init(); } + wxDirFilterListCtrl(wxGenericDirCtrl* parent, const wxWindowID id = -1, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0) + { + Init(); + Create(parent, id, pos, size, style); + } + + bool Create(wxGenericDirCtrl* parent, const wxWindowID id = -1, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0); + + void Init(); + + ~wxDirFilterListCtrl() {}; + +//// Operations + void FillFilterList(const wxString& filter, int defaultFilter); + +//// Events + void OnSelFilter(wxCommandEvent& event); + +protected: + wxGenericDirCtrl* m_dirCtrl; + + DECLARE_EVENT_TABLE() + DECLARE_CLASS(wxDirFilterListCtrl) +}; + +#define wxID_TREECTRL 7000 +#define wxID_FILTERLISTCTRL 7001 + +//----------------------------------------------------------------------------- +// wxGenericDirDialog +// +//----------------------------------------------------------------------------- + +class wxGenericDirDialog: public wxDialog +{ +DECLARE_EVENT_TABLE() +public: + wxGenericDirDialog(): wxDialog() {} + wxGenericDirDialog(wxWindow* parent, const wxString& title, + const wxString& defaultPath = wxEmptyString, long style = wxDEFAULT_DIALOG_STYLE, const wxPoint& pos = wxDefaultPosition, const wxSize& sz = wxSize(450, 550), const wxString& name = "dialog"); + + void OnCloseWindow(wxCloseEvent& event); + void OnOK(wxCommandEvent& event); + + inline void SetMessage(const wxString& message) { m_message = message; } + void SetPath(const wxString& path) ; + inline void SetStyle(long style) { m_dialogStyle = style; } + + inline wxString GetMessage(void) const { return m_message; } + wxString GetPath(void) const ; + inline long GetStyle(void) const { return m_dialogStyle; } + +protected: + wxString m_message; + long m_dialogStyle; + wxString m_path; + wxGenericDirCtrl* m_dirCtrl; + +}; + +#endif + // _WX_DIRCTRLG_H_ diff --git a/include/wx/msw/cdrom.ico b/include/wx/msw/cdrom.ico new file mode 100644 index 0000000000000000000000000000000000000000..af5c619601af9b626d1a9d3507f5129ffc6f6d12 GIT binary patch literal 318 zcmZutF$w}P5S&Bd(wWLu%lnDnxh{bSw_O%IxIg%kls>~J*l8ie*@(^I?#@hhk}M%W z$MoKlw-`EL4`3iXaU{&QD2@M-04#`nh0G;NDOB62tx&722&P#^tI!sLTbzwn-|3tO0g$M&t|g% U|3Qd5?H?ZO4KJR3^G-bgA5NY}IRF3v literal 0 HcmV?d00001 diff --git a/include/wx/msw/computer.ico b/include/wx/msw/computer.ico new file mode 100644 index 0000000000000000000000000000000000000000..64b7c7697d3e9697c7be3ded35c0c906cfe71d44 GIT binary patch literal 318 zcmb7g?=9t4)|Q?Ox3t?Wsgz?;c@B?2w|4jw+HD-jOqf9OkOFI-XBlom zx|kB?T#2AFELGO920BWLBQ~&?~ literal 0 HcmV?d00001 diff --git a/include/wx/msw/drive.ico b/include/wx/msw/drive.ico new file mode 100644 index 0000000000000000000000000000000000000000..4e25200a358f873dbdfa61627027d61a134c8ef6 GIT binary patch literal 318 zcmah^F%rWt2$QcJI(q7yF+WU3ZRyrOPD6$)0sl%lIaGY0c;x1T)EX*x)`VKE5Fr0_^SFsjC;I! W{@la6X#Iz#_5UkS#ZYhT{nsD+iAkma literal 0 HcmV?d00001 diff --git a/include/wx/msw/file1.ico b/include/wx/msw/file1.ico new file mode 100644 index 0000000000000000000000000000000000000000..cc828ab4f2c896df378febb8e501332db93e4c54 GIT binary patch literal 1078 zcmeH`O%B2!6oiLr;?8mdS()BKkM@qnaa{HW_zlFwMHfw6xX>x{{^%n>1}SM$DOtv2 zlCJoiN4_NKe2^Au1>RxO5exWt8zC_iF&vgqwN|_*S|4i75#)2p=8vDg0W|PcSm#!L zfiIm0@iqdDGlQnP!xDa`^V!E|&DpTupO3!QR@&UZI-tMjuDxNrH}-nkN%m4N@aA_a FJpqxL*3JL` literal 0 HcmV?d00001 diff --git a/include/wx/msw/floppy.ico b/include/wx/msw/floppy.ico new file mode 100644 index 0000000000000000000000000000000000000000..c7f056d11e53e09253f785c34a71ca88aed05190 GIT binary patch literal 318 zcmZvXJr2S!4253>5*;%!Gxm7hyk?81cH}xa3MZ(zLHL|X2u0X=@A*fz9BIN+O7K<7 zB;6$~Ab|&ndRXoJkFvy5&ZoeHshjL5W literal 0 HcmV?d00001 diff --git a/include/wx/msw/folder1.ico b/include/wx/msw/folder1.ico new file mode 100644 index 0000000000000000000000000000000000000000..c43de1c07cd64c30413a2c53f521d0e203198a58 GIT binary patch literal 1078 zcmeH{F%AMD5Jf+$1(o3lRA!Iiy)2xP!~?vfUP&SZtvm{`_HB2qB-9 zf(GTBYc(nu}C6AaoD0pBjeB)ZJH5J^>QMSWswUDMPn`8aB-=0Ml-AgfD*@PpCja_E+ T_r_T%*c$R5s2Azc-l_Bfjgso2 literal 0 HcmV?d00001 diff --git a/include/wx/msw/folder2.ico b/include/wx/msw/folder2.ico new file mode 100644 index 0000000000000000000000000000000000000000..98b6d3f9203d9dfca90df76cc972478ea45e33b7 GIT binary patch literal 318 zcmZ`zI}XAy41JXtGG=0C>@Bz!QigiW)~m1uiGduYM_{88gLy9vQU|d8p1-mU4AdAS z`G9c%jsQj?5+_1+Np1X#44}bmb7Y37wbHBM&ET$xpsFPLCm}aMc$HG_hB-+BW~QZt z@K$=wflJ);rH|iwpFX9@eO3P8CU9_Vw{o`K&Fv51$=cFU=>^+C`4`KX^OODuKB+QQ A&j0`b literal 0 HcmV?d00001 diff --git a/include/wx/msw/removble.ico b/include/wx/msw/removble.ico new file mode 100644 index 0000000000000000000000000000000000000000..db8bb820b8889e4cfa85f16ce0a50ecb9abf0c8b GIT binary patch literal 318 zcmaivI}*Y$3`93WigdW5rpygZhe|pRH`0;lLMNVV3W_jUNvpp{mL{Z>0?%3}=^|;x z3UkIXHF2|6?-5)2mvqKIOAppend(DIALOGS_FILES_OPEN, "Open &files\tCtrl-Q"); file_menu->Append(DIALOGS_FILE_SAVE, "Sa&ve file\tCtrl-S"); file_menu->Append(DIALOGS_DIR_CHOOSE, "&Choose a directory\tCtrl-D"); + file_menu->Append(DIALOGS_GENERIC_DIR_CHOOSE, "&Choose a directory (generic implementation)"); #if wxUSE_PROGRESSDLG file_menu->Append(DIALOGS_PROGRESS, "Pro&gress dialog\tCtrl-G"); #endif // wxUSE_PROGRESSDLG @@ -418,6 +423,21 @@ void MyFrame::DirChoose(wxCommandEvent& WXUNUSED(event) ) } } +void MyFrame::GenericDirChoose(wxCommandEvent& WXUNUSED(event) ) +{ + // pass some initial dir to wxDirDialog + wxString dirHome; + wxGetHomeDir(&dirHome); + + wxGenericDirDialog dialog(this, "Testing generic directory picker", dirHome); + + if (dialog.ShowModal() == wxID_OK) + { + wxMessageDialog dialog2(this, dialog.GetPath(), "Selected path"); + dialog2.ShowModal(); + } +} + void MyFrame::ModalDlg(wxCommandEvent& WXUNUSED(event)) { MyModalDialog dlg(this); diff --git a/samples/dialogs/dialogs.h b/samples/dialogs/dialogs.h index d8e4665ab9..d1bb0fe773 100644 --- a/samples/dialogs/dialogs.h +++ b/samples/dialogs/dialogs.h @@ -68,6 +68,7 @@ public: void FilesOpen(wxCommandEvent& event); void FileSave(wxCommandEvent& event); void DirChoose(wxCommandEvent& event); + void GenericDirChoose(wxCommandEvent& event); void ShowTip(wxCommandEvent& event); void ModalDlg(wxCommandEvent& event); void ModelessDlg(wxCommandEvent& event); @@ -114,6 +115,7 @@ enum DIALOGS_FILES_OPEN, DIALOGS_FILE_SAVE, DIALOGS_DIR_CHOOSE, + DIALOGS_GENERIC_DIR_CHOOSE, DIALOGS_TIP, DIALOGS_NUM_ENTRY, DIALOGS_LOG_DIALOG, diff --git a/src/generic/dirctrlg.cpp b/src/generic/dirctrlg.cpp new file mode 100644 index 0000000000..33a6be8d05 --- /dev/null +++ b/src/generic/dirctrlg.cpp @@ -0,0 +1,1204 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: dirctrlg.cpp +// Purpose: wxGenericDirCtrl +// Author: Harm van der Heijden, Robert Roebling, Julian Smart +// Modified by: +// Created: 12/12/98 +// RCS-ID: $Id$ +// Copyright: (c) Harm van der Heijden, Robert Roebling and Julian Smart +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ +#pragma implementation "dirctrl.h" +#endif + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#include "wx/defs.h" + +#include "wx/utils.h" +#include "wx/dialog.h" +#include "wx/button.h" +#include "wx/layout.h" +#include "wx/msgdlg.h" +#include "wx/textdlg.h" +#include "wx/filefn.h" +#include "wx/cmndata.h" +#include "wx/gdicmn.h" +#include "wx/intl.h" +#include "wx/imaglist.h" +#include "wx/icon.h" +#include "wx/log.h" +#include "wx/sizer.h" +#include "wx/tokenzr.h" +#include "wx/dir.h" + +#if wxUSE_STATLINE + #include "wx/statline.h" +#endif + +#include "wx/generic/dirctrlg.h" + +#ifdef __WXMSW__ +#include +#include +#include +#endif + +// If compiled under Windows, this macro can cause problems +#ifdef GetFirstChild +#undef GetFirstChild +#endif + +#if !defined(__WXMSW__) || wxUSE_XPM_IN_MSW +/* Closed folder */ +static char * icon1_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +" s None c None", +". c #000000", +"+ c #c0c0c0", +"@ c #808080", +"# c #ffff00", +"$ c #ffffff", +/* pixels */ +" ", +" @@@@@ ", +" @#+#+#@ ", +" @#+#+#+#@@@@@@ ", +" @$$$$$$$$$$$$@.", +" @$#+#+#+#+#+#@.", +" @$+#+#+#+#+#+@.", +" @$#+#+#+#+#+#@.", +" @$+#+#+#+#+#+@.", +" @$#+#+#+#+#+#@.", +" @$+#+#+#+#+#+@.", +" @$#+#+#+#+#+#@.", +" @@@@@@@@@@@@@@.", +" ..............", +" ", +" "}; + +/* Open folder */ +static char * icon2_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +" s None c None", +". c #000000", +"+ c #c0c0c0", +"@ c #808080", +"# c #ffff00", +"$ c #ffffff", +/* pixels */ +" ", +" @@@@@ ", +" @$$$$$@ ", +" @$#+#+#$@@@@@@ ", +" @$+#+#+$$$$$$@.", +" @$#+#+#+#+#+#@.", +"@@@@@@@@@@@@@#@.", +"@$$$$$$$$$$@@+@.", +"@$#+#+#+#+##.@@.", +" @$#+#+#+#+#+.@.", +" @$+#+#+#+#+#.@.", +" @$+#+#+#+##@..", +" @@@@@@@@@@@@@.", +" .............", +" ", +" "}; + +/* File */ +static char * icon3_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 3 1", +/* colors */ +" s None c None", +". c #000000", +"+ c #ffffff", +/* pixels */ +" ", +" ........ ", +" .++++++.. ", +" .+.+.++.+. ", +" .++++++.... ", +" .+.+.+++++. ", +" .+++++++++. ", +" .+.+.+.+.+. ", +" .+++++++++. ", +" .+.+.+.+.+. ", +" .+++++++++. ", +" .+.+.+.+.+. ", +" .+++++++++. ", +" ........... ", +" ", +" "}; + +/* Computer */ +static char * icon4_xpm[] = { +"16 16 7 1", +" s None c None", +". c #808080", +"X c #c0c0c0", +"o c Black", +"O c Gray100", +"+ c #008080", +"@ c Blue", +" ........... ", +" .XXXXXXXXXX.o", +" .OOOOOOOOO..o", +" .OoooooooX..o", +" .Oo+...@+X..o", +" .Oo+XXX.+X..o", +" .Oo+....+X..o", +" .Oo++++++X..o", +" .OXXXXXXXX.oo", +" ..........o.o", +" ...........Xo", +" .XXXXXXXXXX.o", +" .o.o.o.o.o...o", +" .oXoXoXoXoXo.o ", +".XOXXXXXXXXX.o ", +"............o "}; + +/* Drive */ +static char * icon5_xpm[] = { +"16 16 7 1", +" s None c None", +". c #808080", +"X c #c0c0c0", +"o c Black", +"O c Gray100", +"+ c Green", +"@ c #008000", +" ", +" ", +" ", +" ", +" ............. ", +" .XXXXXXXXXXXX.o", +".OOOOOOOOOOOO..o", +".XXXXXXXXX+@X..o", +".XXXXXXXXXXXX..o", +".X..........X..o", +".XOOOOOOOOOOX..o", +"..............o ", +" ooooooooooooo ", +" ", +" ", +" "}; + +/* CD-ROM */ +static char *icon6_xpm[] = { +"16 16 10 1", +" s None c None", +". c #808080", +"X c #c0c0c0", +"o c Yellow", +"O c Blue", +"+ c Black", +"@ c Gray100", +"# c #008080", +"$ c Green", +"% c #008000", +" ... ", +" ..XoX.. ", +" .O.XoXXX+ ", +" ...O.oXXXX+ ", +" .O..X.XXXX+ ", +" ....X.+..XXX+", +" .XXX.+@+.XXX+", +" .X@XX.+.X@@X+", +" .....X...#XX@+ ", +".@@@...XXo.O@X+ ", +".@XXX..XXoXOO+ ", +".@++++..XoX+++ ", +".@$%@@XX+++X.+ ", +".............+ ", +" ++++++++++++ ", +" "}; + +/* Floppy */ +static char * icon7_xpm[] = { +"16 16 7 1", +" s None c None", +". c #808080", +"X c Gray100", +"o c #c0c0c0", +"O c Black", +"+ c Cyan", +"@ c Red", +" ......X", +" .ooooooO", +" .+++++OO", +" .++++++O", +" .++++++O", +" .ooooooO", +" .......o....oO", +" .oooooo.o.O.XoO", +".XXXXXXXXOOOOOO ", +".ooooooooo@o..O ", +".ooo....oooo..O ", +".o..OOOO...o..O ", +".oooXXXXoooo..O ", +".............O ", +" OOOOOOOOOOOO ", +" "}; + +/* Removeable */ +static char * icon8_xpm[] = { +"16 16 7 1", +" s None c None", +". c #808080", +"X c #c0c0c0", +"o c Black", +"O c Gray100", +"+ c Red", +"@ c #800000", +" ", +" ", +" ", +" ............. ", +" .XXXXXXXXXXXX.o", +".OOOOOOOOOOOO..o", +".OXXXXXXXXXXX..o", +".O+@.oooooo.X..o", +".OXXOooooooOX..o", +".OXXXOOOOOOXX..o", +".OXXXXXXXXXXX..o", +".O............o ", +" ooooooooooooo ", +" ", +" ", +" "}; +#endif // !wxMSW + +static const int ID_DIRCTRL = 1000; +static const int ID_TEXTCTRL = 1001; +static const int ID_OK = 1002; +static const int ID_CANCEL = 1003; +static const int ID_NEW = 1004; +//static const int ID_CHECK = 1005; + +//----------------------------------------------------------------------------- +// wxDirItemDataEx +//----------------------------------------------------------------------------- + +wxDirItemDataEx::wxDirItemDataEx(const wxString& path, const wxString& name, + bool isDir) +{ + m_path = path; + m_name = name; + /* Insert logic to detect hidden files here + * In UnixLand we just check whether the first char is a dot + * For FileNameFromPath read LastDirNameInThisPath ;-) */ + // m_isHidden = (bool)(wxFileNameFromPath(*m_path)[0] == '.'); + m_isHidden = FALSE; + m_hasSubDirs = HasSubDirs(); + m_isExpanded = FALSE; + m_isDir = isDir; +} + +wxDirItemDataEx::~wxDirItemDataEx() +{ +} + +void wxDirItemDataEx::SetNewDirName( wxString path ) +{ + m_path = path; + m_name = wxFileNameFromPath( path ); +} + +bool wxDirItemDataEx::HasSubDirs() +{ + wxString search = m_path + wxT("/*"); + wxLogNull log; + wxString path = wxFindFirstFile( search, wxDIR ); + return (bool)(!path.IsNull()); +} + +//----------------------------------------------------------------------------- +// wxGenericDirCtrl +//----------------------------------------------------------------------------- + +IMPLEMENT_DYNAMIC_CLASS(wxGenericDirCtrl, wxControl) + +BEGIN_EVENT_TABLE(wxGenericDirCtrl, wxControl) + EVT_TREE_ITEM_EXPANDING (-1, wxGenericDirCtrl::OnExpandItem) + EVT_TREE_ITEM_COLLAPSED (-1, wxGenericDirCtrl::OnCollapseItem) + EVT_TREE_BEGIN_LABEL_EDIT (-1, wxGenericDirCtrl::OnBeginEditItem) + EVT_TREE_END_LABEL_EDIT (-1, wxGenericDirCtrl::OnEndEditItem) + EVT_SIZE (wxGenericDirCtrl::OnSize) +END_EVENT_TABLE() + +wxGenericDirCtrl::wxGenericDirCtrl(void) +{ + Init(); +} + +bool wxGenericDirCtrl::Create(wxWindow *parent, + const wxWindowID id, + const wxString& dir, + const wxPoint& pos, + const wxSize& size, + long style, + const wxString& filter, + int defaultFilter, + const wxString& name ) +{ + if (!wxControl::Create(parent, id, pos, size, style, wxDefaultValidator, name)) + return FALSE; + + SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE)); + + Init(); + + long treeStyle = wxTR_HAS_BUTTONS; + if ((style & wxDIRCTRL_3D_INTERNAL) == 0) + treeStyle |= wxNO_BORDER; + + long filterStyle = 0; + if ((style & wxDIRCTRL_3D_INTERNAL) == 0) + filterStyle |= wxNO_BORDER; + + m_treeCtrl = new wxTreeCtrl(this, wxID_TREECTRL, pos, size, treeStyle); + + if (!filter.IsEmpty() && (style & wxDIRCTRL_SHOW_FILTERS)) + m_filterListCtrl = new wxDirFilterListCtrl(this, wxID_FILTERLISTCTRL, wxDefaultPosition, wxDefaultSize, filterStyle); + + m_defaultPath = dir; + m_filter = filter; + + SetFilterIndex(defaultFilter); + + if (m_filterListCtrl) + m_filterListCtrl->FillFilterList(filter, defaultFilter); + + m_imageList = new wxImageList(16, 16, TRUE); +#if !defined(__WXMSW__) || wxUSE_XPM_IN_MSW + m_imageList->Add(wxIcon(icon1_xpm)); + m_imageList->Add(wxIcon(icon2_xpm)); + m_imageList->Add(wxIcon(icon3_xpm)); + m_imageList->Add(wxIcon(icon4_xpm)); + m_imageList->Add(wxIcon(icon5_xpm)); + m_imageList->Add(wxIcon(icon6_xpm)); + m_imageList->Add(wxIcon(icon7_xpm)); + m_imageList->Add(wxIcon(icon8_xpm)); +#elif defined(__WXMSW__) + m_imageList->Add(wxIcon(wxT("wxICON_SMALL_CLOSED_FOLDER"), wxBITMAP_TYPE_RESOURCE)); + m_imageList->Add(wxIcon(wxT("wxICON_SMALL_OPEN_FOLDER"), wxBITMAP_TYPE_RESOURCE)); + m_imageList->Add(wxIcon(wxT("wxICON_SMALL_FILE"), wxBITMAP_TYPE_RESOURCE)); + m_imageList->Add(wxIcon(wxT("wxICON_SMALL_COMPUTER"), wxBITMAP_TYPE_RESOURCE)); + m_imageList->Add(wxIcon(wxT("wxICON_SMALL_DRIVE"), wxBITMAP_TYPE_RESOURCE)); + m_imageList->Add(wxIcon(wxT("wxICON_SMALL_CDROM"), wxBITMAP_TYPE_RESOURCE)); + m_imageList->Add(wxIcon(wxT("wxICON_SMALL_FLOPPY"), wxBITMAP_TYPE_RESOURCE)); + m_imageList->Add(wxIcon(wxT("wxICON_SMALL_REMOVEABLE"), wxBITMAP_TYPE_RESOURCE)); +#else +#error "Sorry, we don't have icons available for this platforms." +#endif + m_treeCtrl->SetImageList(m_imageList); + + m_showHidden = FALSE; + wxDirItemDataEx* rootData = new wxDirItemDataEx(wxT(""), wxT(""), TRUE); + + wxString rootName; + +#ifdef __WXMSW__ + rootName = _("Computer"); +#else + rootName = _("Sections"); +#endif + + m_rootId = m_treeCtrl->AddRoot( rootName, 3, -1, rootData); + m_treeCtrl->SetItemHasChildren(m_rootId); + m_treeCtrl->Expand(m_rootId); // automatically expand first level + + // Expand and select the default path + if (!m_defaultPath.IsEmpty()) + ExpandPath(m_defaultPath); + + DoResize(); + + return TRUE; +} + +wxGenericDirCtrl::~wxGenericDirCtrl() +{ + m_treeCtrl->SetImageList(NULL); + delete m_imageList; +} + +void wxGenericDirCtrl::Init() +{ + m_showHidden = FALSE; + m_imageList = NULL; + m_rootId = 0; + m_currentFilter = 0; + m_currentFilterStr = wxEmptyString; // Default: any file + m_treeCtrl = NULL; + m_filterListCtrl = NULL; +} + +void wxGenericDirCtrl::AddSection(const wxString& path, const wxString& name, int imageId) +{ + wxDirItemDataEx *dir_item = new wxDirItemDataEx(path,name,TRUE); + +#ifdef __WXMSW__ + // Windows: sections are displayed as drives + wxTreeItemId id = m_treeCtrl->AppendItem( m_rootId, name, imageId, -1, dir_item); +#else + // Unix: sections are displayed as folders + wxTreeItemId id = m_treeCtrl->AppendItem( m_rootId, name, 0, -1, dir_item); + SetItemImage( id, 1, wxTreeItemIcon_Expanded ); +#endif + // TODO: other operating systems. + + m_treeCtrl->SetItemHasChildren(id); +} + +void wxGenericDirCtrl::SetupSections() +{ +#ifdef __WXMSW__ + +#ifdef __WIN32__ + wxChar driveBuffer[256]; + size_t n = (size_t) GetLogicalDriveStrings(255, driveBuffer); + size_t i = 0; + while (i < n) + { + wxString path, name; + path.Printf(wxT("%c:\\"), driveBuffer[i]); + name.Printf(wxT("(%c:)"), driveBuffer[i]); + + int imageId = 4; + int driveType = ::GetDriveType(path); + switch (driveType) + { + case DRIVE_REMOVABLE: + if (path == wxT("a:\\") || path == wxT("b:\\")) + imageId = 6; // Floppy + else + imageId = 7; + break; + case DRIVE_FIXED: + imageId = 4; + break; + case DRIVE_REMOTE: + imageId = 4; + break; + case DRIVE_CDROM: + imageId = 5; + break; + default: + imageId = 4; + break; + } + + AddSection(path, name, imageId); + + while (driveBuffer[i] != wxT('\0')) + i ++; + i ++; + if (driveBuffer[i] == wxT('\0')) + break; + } +#else + int drive; + int currentDrive; + + /* Save current drive. */ + currentDrive = _getdrive(); + + /* If we can switch to the drive, it exists. */ + for( drive = 1; drive <= 26; drive++ ) + { + wxString path, name; + path.Printf(wxT("%c:\\"), (char) (drive + 'a' - 1)); + name.Printf(wxT("(%c:)"), (char) (drive + 'a' - 1)); + + if( !_chdrive( drive ) ) + { + + AddSection(path, name); + } + } + + /* Restore original drive.*/ + _chdrive( currentDrive ); +#endif + +#else + wxString home; + AddSection(wxT("/"), _("The Computer"), 0) + wxGetHomeDir(&home); + AddSection(home, _("My Home"), 0 ) + AddSection(wxT("/mnt"), _("Mounted Devices"), 0 ) + AddSection(wxT("/usr/local"), _("User Local"), 0 ) + AddSection(wxT("/usr"), _("User"), 0 ) + AddSection(wxT("/var"), _("Variables"), 0 ) + AddSection(wxT("/etc"), _("Etcetera"), 0 ) + AddSection(wxT("/tmp"), _("Temporary"), 0 ) +#endif +} + +void wxGenericDirCtrl::OnBeginEditItem(wxTreeEvent &event) +{ + // don't rename the main entry "Sections" + if (event.GetItem() == m_rootId) + { + event.Veto(); + return; + } + + // don't rename the individual sections + if (m_treeCtrl->GetParent( event.GetItem() ) == m_rootId) + { + event.Veto(); + return; + } +} + +void wxGenericDirCtrl::OnEndEditItem(wxTreeEvent &event) +{ + if ((event.GetLabel().IsEmpty()) || + (event.GetLabel() == _(".")) || + (event.GetLabel() == _("..")) || + (event.GetLabel().First( wxT("/") ) != wxNOT_FOUND)) + { + wxMessageDialog dialog(this, _("Illegal directory name."), _("Error"), wxOK | wxICON_ERROR ); + dialog.ShowModal(); + event.Veto(); + return; + } + + wxTreeItemId id = event.GetItem(); + wxDirItemDataEx *data = (wxDirItemDataEx*)m_treeCtrl->GetItemData( id ); + wxASSERT( data ); + + wxString new_name( wxPathOnly( data->m_path ) ); + new_name += wxT("/"); + new_name += event.GetLabel(); + + wxLogNull log; + + if (wxFileExists(new_name)) + { + wxMessageDialog dialog(this, _("File name exists already."), _("Error"), wxOK | wxICON_ERROR ); + dialog.ShowModal(); + event.Veto(); + } + + if (wxRenameFile(data->m_path,new_name)) + { + data->SetNewDirName( new_name ); + } + else + { + wxMessageDialog dialog(this, _("Operation not permitted."), _("Error"), wxOK | wxICON_ERROR ); + dialog.ShowModal(); + event.Veto(); + } +} + +void wxGenericDirCtrl::OnExpandItem(wxTreeEvent &event) +{ + wxTreeItemId parentId = event.GetItem(); + + ExpandDir(parentId); +} + +void wxGenericDirCtrl::OnCollapseItem(wxTreeEvent &event ) +{ + wxTreeItemId child, parent = event.GetItem(); + + wxDirItemDataEx *data = (wxDirItemDataEx *) m_treeCtrl->GetItemData(event.GetItem()); + if (!data->m_isExpanded) + return; + + data->m_isExpanded = FALSE; + long cookie; + /* Workaround because DeleteChildren has disapeared (why?) and + * CollapseAndReset doesn't work as advertised (deletes parent too) */ + child = m_treeCtrl->GetFirstChild(parent, cookie); + while (child.IsOk()) + { + m_treeCtrl->Delete(child); + /* Not GetNextChild below, because the cookie mechanism can't + * handle disappearing children! */ + child = m_treeCtrl->GetFirstChild(parent, cookie); + } +} + +void wxGenericDirCtrl::ExpandDir(wxTreeItemId parentId) +{ + wxDirItemDataEx *data = (wxDirItemDataEx *) m_treeCtrl->GetItemData(parentId); + + if (data->m_isExpanded) + return; + + data->m_isExpanded = TRUE; + + if (parentId == m_rootId) + { + SetupSections(); + return; + } + + wxASSERT(data); + + wxString search,path,filename; + + wxString dirName(data->m_path); + +#ifdef __WXMSW__ + // Check if this is a root directory and if so, + // whether the drive is avaiable. + if (dirName.Len() == 3 && dirName[1] == wxT(':')) + { + int currentDrive = _getdrive(); + int thisDrive = (int) (dirName[0] - 'a' + 1) ; + int err = _chdrive( thisDrive ) ; + _chdrive( currentDrive ); + + if (err == -1) + { + data->m_isExpanded = FALSE; + wxMessageBox(wxT("Sorry, this drive is not available.")); + return; + } + } +#endif + + // This may take a longish time. Go to busy cursor + wxBusyCursor busy; + +#ifdef __WXMSW__ + if (dirName.Last() == ':') + dirName += wxString(wxFILE_SEP_PATH); +#endif + + wxArrayString dirs; + wxArrayString filenames; + + wxDir d; + wxString eachFilename; + + d.Open(dirName); + + if (d.IsOpened()) + { + if (d.GetFirst(& eachFilename, wxEmptyString, wxDIR_DIRS)) + { + do + { + if ((eachFilename != wxT(".")) && (eachFilename != wxT(".."))) + { + dirs.Add(eachFilename); + } + } + while (d.GetNext(& eachFilename)) ; + } + } + dirs.Sort(); + + // Now do the filenames -- but only if we're allowed to + if ((GetWindowStyle() & wxDIRCTRL_DIR_ONLY) == 0) + { + d.Open(dirName); + + if (d.IsOpened()) + { + if (d.GetFirst(& eachFilename, m_currentFilterStr, wxDIR_FILES)) + { + do + { + if ((eachFilename != wxT(".")) && (eachFilename != wxT(".."))) + { + filenames.Add(eachFilename); + } + } + while (d.GetNext(& eachFilename)) ; + } + } + filenames.Sort(); + } + + // Add the sorted dirs + size_t i; + for (i = 0; i < dirs.Count(); i++) + { + wxString eachFilename(dirs[i]); + path = dirName; + if (path.Last() != wxFILE_SEP_PATH) + path += wxString(wxFILE_SEP_PATH); + path += eachFilename; + + wxDirItemDataEx *dir_item = new wxDirItemDataEx(path,eachFilename,TRUE); + wxTreeItemId id = m_treeCtrl->AppendItem( parentId, eachFilename, 0, -1, dir_item); + m_treeCtrl->SetItemImage( id, 1, wxTreeItemIcon_Expanded ); + + // Has this got any children? If so, make it expandable. + int options = wxDIR_DEFAULT; + if (GetWindowStyle() & wxDIRCTRL_DIR_ONLY) // If only showing dirs, then we specify dirs only here + { + options = wxDIR_DIRS; + } + + wxDir dir2(path); + wxString str; + // Have to test for wxDIR_DIRS separately in case m_currentFilterStr is non-empty and + // and filters out any directories + if (dir2.GetFirst(& str, m_currentFilterStr, options) || dir2.GetFirst(& str, wxEmptyString, wxDIR_DIRS)) + { + m_treeCtrl->SetItemHasChildren(id); + } + } + + // Add the sorted filenames + if ((GetWindowStyle() & wxDIRCTRL_DIR_ONLY) == 0) + { + for (i = 0; i < filenames.Count(); i++) + { + wxString eachFilename(filenames[i]); + path = dirName; + if (path.Last() != wxFILE_SEP_PATH) + path += wxString(wxFILE_SEP_PATH); + path += eachFilename; + //path = dirName + wxString(wxT("/")) + eachFilename; + wxDirItemDataEx *dir_item = new wxDirItemDataEx(path,eachFilename,FALSE); + wxTreeItemId id = m_treeCtrl->AppendItem( parentId, eachFilename, 2, -1, dir_item); + } + } +} + +// Find the child that matches the first part of 'path'. +// E.g. if a child path is "/usr" and 'path' is "/usr/include" +// then the child for /usr is returned. +wxTreeItemId wxGenericDirCtrl::FindChild(wxTreeItemId parentId, const wxString& path, bool& done) +{ + wxString path2(path); + + // Make sure all separators are as per the current platform + path2.Replace(wxT("\\"), wxString(wxFILE_SEP_PATH)); + path2.Replace(wxT("/"), wxString(wxFILE_SEP_PATH)); + + // Append a separator to foil bogus substring matching + path2 += wxString(wxFILE_SEP_PATH); + + // In MSW, case is not significant +#ifdef __WXMSW__ + path2.MakeLower(); +#endif + + long cookie; + wxTreeItemId childId = m_treeCtrl->GetFirstChild(parentId, cookie); + while (childId != 0) + { + wxDirItemDataEx* data = (wxDirItemDataEx*) m_treeCtrl->GetItemData(childId); + + if (data && data->m_path != "") + { + wxString childPath(data->m_path); + if (childPath.Last() != wxFILE_SEP_PATH) + childPath += wxString(wxFILE_SEP_PATH); + + // In MSW, case is not significant +#ifdef __WXMSW__ + childPath.MakeLower(); +#endif + + if (childPath.Len() <= path2.Len()) + { + wxString path3 = path2.Mid(0, childPath.Len()); + if (childPath == path3) + { + if (path3.Len() == path2.Len()) + done = TRUE; + else + done = FALSE; + return childId; + } + } + } + + childId = m_treeCtrl->GetNextChild(childId, cookie); + } + return 0; +} + +// Try to expand as much of the given path as possible, +// and select the given tree item. +bool wxGenericDirCtrl::ExpandPath(const wxString& path) +{ + bool done = FALSE; + wxTreeItemId id = FindChild(m_rootId, path, done); + wxTreeItemId lastId = id; // The last non-zero id + while ((id > 0) && !done) + { + ExpandDir(id); + + id = FindChild(id, path, done); + if (id != 0) + lastId = id; + } + if (lastId > 0) + { + wxDirItemDataEx *data = (wxDirItemDataEx *) m_treeCtrl->GetItemData(lastId); + if (data->m_isDir) + { + m_treeCtrl->Expand(lastId); + } + if ((GetWindowStyle() & wxDIRCTRL_SELECT_FIRST) && data->m_isDir) + { + // Find the first file in this directory + long cookie; + wxTreeItemId childId = m_treeCtrl->GetFirstChild(lastId, cookie); + bool selectedChild = FALSE; + while (childId != 0) + { + wxDirItemDataEx* data = (wxDirItemDataEx*) m_treeCtrl->GetItemData(childId); + + if (data && data->m_path != "" && !data->m_isDir) + { + m_treeCtrl->SelectItem(childId); + m_treeCtrl->EnsureVisible(childId); + selectedChild = TRUE; + break; + } + childId = m_treeCtrl->GetNextChild(lastId, cookie); + } + if (!selectedChild) + { + m_treeCtrl->SelectItem(lastId); + m_treeCtrl->EnsureVisible(lastId); + } + } + else + { + m_treeCtrl->SelectItem(lastId); + m_treeCtrl->EnsureVisible(lastId); + } + + return TRUE; + } + else + return FALSE; +} + +wxString wxGenericDirCtrl::GetPath() const +{ + wxTreeItemId id = m_treeCtrl->GetSelection(); + if (id) + { + wxDirItemDataEx* data = (wxDirItemDataEx*) m_treeCtrl->GetItemData(id); + return data->m_path; + } + else + return wxEmptyString; +} + +wxString wxGenericDirCtrl::GetFilePath() const +{ + wxTreeItemId id = m_treeCtrl->GetSelection(); + if (id) + { + wxDirItemDataEx* data = (wxDirItemDataEx*) m_treeCtrl->GetItemData(id); + if (data->m_isDir) + return wxEmptyString; + else + return data->m_path; + } + else + return wxEmptyString; +} + +void wxGenericDirCtrl::SetPath(const wxString& path) +{ + m_defaultPath = path; + if (m_rootId) + ExpandPath(path); +} + +// Not used +#if 0 +void wxGenericDirCtrl::FindChildFiles(wxTreeItemId id, int dirFlags, wxArrayString& filenames) +{ + wxDirItemDataEx *data = (wxDirItemDataEx *) m_treeCtrl->GetItemData(id); + + // This may take a longish time. Go to busy cursor + wxBusyCursor busy; + + wxASSERT(data); + + wxString search,path,filename; + + wxString dirName(data->m_path); + +#ifdef __WXMSW__ + if (dirName.Last() == ':') + dirName += wxString(wxFILE_SEP_PATH); +#endif + + wxDir d; + wxString eachFilename; + + d.Open(dirName); + + if (d.IsOpened()) + { + if (d.GetFirst(& eachFilename, m_currentFilterStr, dirFlags)) + { + do + { + if ((eachFilename != wxT(".")) && (eachFilename != wxT(".."))) + { + filenames.Add(eachFilename); + } + } + while (d.GetNext(& eachFilename)) ; + } + } +} +#endif + +void wxGenericDirCtrl::SetFilterIndex(int n) +{ + m_currentFilter = n; + + wxString f, d; + if (ExtractWildcard(m_filter, n, f, d)) + m_currentFilterStr = f; + else + m_currentFilterStr = wxT("*.*"); +} + +void wxGenericDirCtrl::SetFilter(const wxString& filter) +{ + m_filter = filter; + + wxString f, d; + if (ExtractWildcard(m_filter, m_currentFilter, f, d)) + m_currentFilterStr = f; + else + m_currentFilterStr = wxT("*.*"); +} + +// Extract description and actual filter from overall filter string +bool wxGenericDirCtrl::ExtractWildcard(const wxString& filterStr, int n, wxString& filter, wxString& description) +{ + wxArrayString filters, descriptions; + int count = ParseFilter(filterStr, filters, descriptions); + if (count > 0 && n < count) + { + filter = filters[n]; + description = descriptions[n]; + return TRUE; + } + else + return FALSE; +} + +// Parses the global filter, returning the number of filters. +// Returns 0 if none or if there's a problem. +// filterStr is in the form: +// +// "All files (*.*)|*.*|JPEG Files (*.jpeg)|*.jpg" + +int wxGenericDirCtrl::ParseFilter(const wxString& filterStr, wxArrayString& filters, wxArrayString& descriptions) +{ + wxString str(filterStr); + + wxString description, filter; + int pos; + bool finished = FALSE; + do + { + pos = str.Find(wxT('|')); + if (pos == -1) + return 0; // Problem + description = str.Left(pos); + str = str.Mid(pos+1); + pos = str.Find(wxT('|')); + if (pos == -1) + { + filter = str; + finished = TRUE; + } + else + { + filter = str.Left(pos); + str = str.Mid(pos+1); + } + descriptions.Add(description); + filters.Add(filter); + } + while (!finished) ; + + return filters.Count(); +} + +void wxGenericDirCtrl::DoResize() +{ + wxSize sz = GetClientSize(); + int verticalSpacing = 3; + if (m_treeCtrl) + { + wxSize filterSz ; + if (m_filterListCtrl) + { + filterSz = m_filterListCtrl->GetSize(); + sz.y -= (filterSz.y + verticalSpacing); + } + m_treeCtrl->SetSize(0, 0, sz.x, sz.y); + if (m_filterListCtrl) + { + m_filterListCtrl->SetSize(0, sz.y + verticalSpacing, sz.x, filterSz.y); + // Don't know why, but this needs refreshing after a resize (wxMSW) + m_filterListCtrl->Refresh(); + } + } +} + + +void wxGenericDirCtrl::OnSize(wxSizeEvent &event) +{ + DoResize(); +} + +//----------------------------------------------------------------------------- +// wxDirFilterListCtrl +//----------------------------------------------------------------------------- + +IMPLEMENT_CLASS(wxDirFilterListCtrl, wxChoice) + +BEGIN_EVENT_TABLE(wxDirFilterListCtrl, wxChoice) + EVT_CHOICE(-1, wxDirFilterListCtrl::OnSelFilter) +END_EVENT_TABLE() + +bool wxDirFilterListCtrl::Create(wxGenericDirCtrl* parent, const wxWindowID id, + const wxPoint& pos, + const wxSize& size, + long style) +{ + m_dirCtrl = parent; + return wxChoice::Create(parent, id, pos, size, 0, NULL, style); +} + +void wxDirFilterListCtrl::Init() +{ + m_dirCtrl = NULL; +} + +void wxDirFilterListCtrl::OnSelFilter(wxCommandEvent& event) +{ + int sel = GetSelection(); + + wxString currentPath = m_dirCtrl->GetPath(); + + m_dirCtrl->SetFilterIndex(sel); + + // If the filter has changed, the view is out of date, so + // collapse the tree. + m_dirCtrl->GetTreeCtrl()->Collapse(m_dirCtrl->GetRootId()); + m_dirCtrl->GetTreeCtrl()->Expand(m_dirCtrl->GetRootId()); + + // Try to restore the selection, or at least the directory + m_dirCtrl->ExpandPath(currentPath); +} + +void wxDirFilterListCtrl::FillFilterList(const wxString& filter, int defaultFilter) +{ + Clear(); + wxArrayString descriptions, filters; + size_t n = (size_t) m_dirCtrl->ParseFilter(filter, filters, descriptions); + + if (n > 0 && defaultFilter < (int) n) + { + size_t i = 0; + for (i = 0; i < n; i++) + Append(descriptions[i]); + SetSelection(defaultFilter); + } +} + +// wxGenericDirDialog implementation +// This should be moved into dirdlgg.cpp eventually + +BEGIN_EVENT_TABLE(wxGenericDirDialog, wxDialog) + EVT_BUTTON(wxID_OK, wxGenericDirDialog::OnOK) + EVT_CLOSE(wxGenericDirDialog::OnCloseWindow) +END_EVENT_TABLE() + +wxGenericDirDialog::wxGenericDirDialog(wxWindow* parent, const wxString& title, + const wxString& defaultPath, long style, const wxPoint& pos, const wxSize& sz, const wxString& name): + wxDialog(parent, ID_DIRCTRL, title, pos, sz, style, name) +{ + wxBusyCursor cursor; + + wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL ); + + // 1) dir ctrl + m_dirCtrl = new wxGenericDirCtrl(this, ID_DIRCTRL, + defaultPath, wxPoint(5, 5), + wxSize(300, 200), wxDIRCTRL_DIR_ONLY); + + topsizer->Add( m_dirCtrl, 1, wxTOP|wxLEFT|wxRIGHT | wxEXPAND, 10 ); + + // 2) TODO: text control for entering path? + +#if wxUSE_STATLINE + // 3) Static line + topsizer->Add( new wxStaticLine( this, -1 ), 0, wxEXPAND | wxLEFT|wxRIGHT|wxTOP, 10 ); +#endif + + // 4) Buttons + wxSizer* buttonsizer = new wxBoxSizer( wxHORIZONTAL ); + wxButton* okButton = new wxButton(this, wxID_OK, _("OK")); + buttonsizer->Add( okButton, 0, wxLEFT|wxRIGHT, 10 ); + wxButton* cancelButton = new wxButton(this, wxID_CANCEL, _("Cancel")); + buttonsizer->Add( cancelButton, 0, wxLEFT|wxRIGHT, 10 ); + +/* TODO: new directory button + wxButton* newButton = new wxButton( this, ID_NEW, _("New...") ); + buttonsizer->Add( newButton, 0, wxLEFT|wxRIGHT, 10 ); +*/ + topsizer->Add( buttonsizer, 0, wxALL | wxCENTER, 10 ); + + okButton->SetDefault(); + m_dirCtrl->SetFocus(); + + SetAutoLayout( TRUE ); + SetSizer( topsizer ); + + topsizer->SetSizeHints( this ); + topsizer->Fit( this ); + + Centre( wxBOTH ); +} + +void wxGenericDirDialog::OnCloseWindow(wxCloseEvent& event) +{ + EndModal(wxID_CANCEL); +} + +void wxGenericDirDialog::OnOK(wxCommandEvent& event) +{ + EndModal(wxID_OK); +} + +void wxGenericDirDialog::SetPath(const wxString& path) +{ + m_dirCtrl->SetPath(path); +} + +wxString wxGenericDirDialog::GetPath(void) const +{ + return m_dirCtrl->GetPath(); +} diff --git a/src/msw/makefile.vc b/src/msw/makefile.vc index 35a9264067..60b01a0e91 100644 --- a/src/msw/makefile.vc +++ b/src/msw/makefile.vc @@ -86,6 +86,7 @@ $(CPPFLAGS) /Fo$@ /c /Tp $< GENERICOBJS= ..\generic\$D\busyinfo.obj \ ..\generic\$D\calctrl.obj \ ..\generic\$D\choicdgg.obj \ + ..\generic\$D\dirctrlg.obj \ ..\generic\$D\dragimgg.obj \ ..\generic\$D\grid.obj \ ..\generic\$D\gridsel.obj \ diff --git a/src/wxvc.dsp b/src/wxvc.dsp index 3f70598deb..a69945aef9 100644 --- a/src/wxvc.dsp +++ b/src/wxvc.dsp @@ -512,6 +512,10 @@ SOURCE=.\generic\choicdgg.cpp # End Source File # Begin Source File +SOURCE=.\generic\dirctrlg.cpp +# End Source File +# Begin Source File + SOURCE=.\generic\dragimgg.cpp # End Source File # Begin Source File