merge the formfield patch from ooo-build
[ooovba.git] / svtools / source / dialogs / filedlg2.cxx
blob8793165652ca6b00adedc95b1fd5f444156f75c5
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: filedlg2.cxx,v $
10 * $Revision: 1.15 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
33 #include <vcl/svapp.hxx>
34 #ifndef _SV_BUTTON_HXX //autogen
35 #include <vcl/button.hxx>
36 #endif
37 #include <vcl/fixed.hxx>
38 #include <vcl/edit.hxx>
39 #include <vcl/lstbox.hxx>
40 #include <svtools/svtdata.hxx>
42 #include <filedlg2.hxx>
43 #include <filedlg.hxx>
44 #include <filedlg2.hrc>
45 #include <vcl/msgbox.hxx>
46 #include <vos/security.hxx>
47 #include <com/sun/star/i18n/XCollator.hpp>
49 #include <svtools/stdctrl.hxx>
51 #ifdef _MSC_VER
52 #pragma optimize ("", off)
53 #endif
55 #include <svtools/helpid.hrc>
57 using namespace com::sun::star;
58 using namespace com::sun::star::uno;
61 DECLARE_LIST( UniStringList, UniString* )
63 #define STD_BTN_WIDTH 80
64 #define STD_BTN_HEIGHT 26
66 #ifndef UNX
67 #define ALLFILES "*.*"
68 #else
69 #define ALLFILES "*"
70 #endif
71 // #define STD_BTN_WIDTH 90
72 // #define STD_BTN_HEIGHT 35
74 #define INITCONTROL( p, ControlClass, nBits, aPos, aSize, aTitel, nHelpId ) \
75 p = new ControlClass( GetPathDialog(), WinBits( nBits ) ); \
76 p->SetHelpId( nHelpId ); \
77 p->SetPosSizePixel( aPos, aSize ); \
78 p->SetText( aTitel ); \
79 p->Show();
82 inline BOOL IsPrintable( sal_Unicode c )
84 return c >= 32 && c != 127 ? TRUE : FALSE;
87 long
88 KbdListBox::PreNotify( NotifyEvent& rNEvt )
90 if ( rNEvt.GetType() == EVENT_KEYINPUT )
92 KeyEvent aKeyEvt = *rNEvt.GetKeyEvent();
93 sal_Unicode cCharCode = aKeyEvt.GetCharCode();
95 if ( IsPrintable ( cCharCode ) )
97 USHORT nCurrentPos = GetSelectEntryPos();
98 USHORT nEntries = GetEntryCount();
100 for ( USHORT i = 1; i < nEntries; i++ )
102 UniString aEntry = GetEntry ( (i + nCurrentPos) % nEntries );
103 aEntry.EraseLeadingChars( ' ' );
104 aEntry.ToUpperAscii();
105 UniString aCompare( cCharCode );
106 aCompare.ToUpperAscii();
108 if ( aEntry.CompareTo( aCompare, 1 ) == COMPARE_EQUAL )
110 SelectEntryPos ( (i + nCurrentPos) % nEntries );
111 break;
115 else
116 if ( aKeyEvt.GetKeyCode().GetCode() == KEY_RETURN )
118 DoubleClick();
122 return ListBox::PreNotify ( rNEvt );
125 ImpPathDialog::ImpPathDialog( PathDialog* pDlg, RESOURCE_TYPE nType, BOOL bCreateDir )
127 pSvPathDialog = pDlg;
128 nDirCount = 0;
130 // initialize Controls if not used as a base class
131 if ( nType == WINDOW_PATHDIALOG )
133 InitControls();
134 if( pNewDirBtn )
135 pNewDirBtn->Enable( bCreateDir );
138 pDlg->SetHelpId( HID_FILEDLG_PATHDLG );
140 lang::Locale aLocale = Application::GetSettings().GetLocale();
141 xCollator = ::vcl::unohelper::CreateCollator();
142 if( xCollator.is() )
143 xCollator->loadDefaultCollator( aLocale, 1 );
144 DBG_ASSERT( xCollator.is(), "not collator service for path dialog" );
147 ImpPathDialog::~ImpPathDialog()
149 delete pEdit;
150 delete pDirTitel;
151 delete pDirList;
152 delete pDirPath;
153 delete pDriveList;
154 delete pDriveTitle;
155 delete pLoadBtn;
156 delete pOkBtn;
157 delete pCancelBtn;
158 delete pNewDirBtn;
159 # if defined(UNX) || defined(OS2)
160 delete pHomeBtn;
161 # endif
164 void ImpPathDialog::InitControls()
166 PathDialog* pDlg = GetPathDialog();
167 pDlg->SetText( UniString( SvtResId( STR_FILEDLG_SELECT ) ) );
169 Size a3Siz = pDlg->LogicToPixel( Size( 3, 3 ), MAP_APPFONT );
170 Size a6Siz = pDlg->LogicToPixel( Size( 6, 6 ), MAP_APPFONT );
171 Size aBtnSiz = pDlg->LogicToPixel( Size( 50, 14 ), MAP_APPFONT );
172 Size aFTSiz = pDlg->LogicToPixel( Size( 142, 10 ), MAP_APPFONT );
173 Size aEDSiz = pDlg->LogicToPixel( Size( 142, 12 ), MAP_APPFONT );
174 Point aPnt( a6Siz.Width(), a6Siz.Height() );
175 long nLbH1 = pDlg->LogicToPixel( Size( 0, 93 ), MAP_APPFONT ).Height();
176 long nH = 0;
177 UniString aEmptyStr;
179 INITCONTROL( pDirTitel, FixedText, 0,
180 aPnt, aFTSiz, UniString( SvtResId( STR_FILEDLG_DIR ) ), HID_FILEDLG_DIR );
181 aPnt.Y() += aFTSiz.Height() + a3Siz.Height();
183 INITCONTROL( pEdit, Edit, WB_BORDER, aPnt, aEDSiz, aPath.GetFull(), HID_FILEDLG_EDIT );
185 aPnt.Y() += aEDSiz.Height() + a3Siz.Height();
186 #ifndef UNX
187 long nLbH2 = pDlg->LogicToPixel( Size( 0, 60 ), MAP_APPFONT ).Height();
188 INITCONTROL( pDirList, KbdListBox, WB_AUTOHSCROLL | WB_BORDER,
189 aPnt, Size( aEDSiz.Width(), nLbH1 ), aEmptyStr, HID_FILEDLG_DIRS );
190 aPnt.Y() += nLbH1 + a6Siz.Height();
191 INITCONTROL( pDriveTitle, FixedText, 0,
192 aPnt, aFTSiz, UniString( SvtResId( STR_FILEDLG_DRIVES ) ), HID_FILEDLG_DRIVE );
193 aPnt.Y() += aFTSiz.Height() + a3Siz.Height();
194 INITCONTROL( pDriveList, ListBox, WB_DROPDOWN,
195 aPnt, Size( aEDSiz.Width(), nLbH2 ), aEmptyStr, HID_FILEDLG_DRIVES );
196 nH = aPnt.Y() + aEDSiz.Height() + a6Siz.Height();
197 #else
198 long nNewH = nLbH1 + 3 * a3Siz.Height() +
199 aFTSiz.Height() + aEDSiz.Height();
200 INITCONTROL( pDirList, KbdListBox, WB_AUTOHSCROLL | WB_BORDER,
201 aPnt, Size( aEDSiz.Width(), nNewH ), aEmptyStr, HID_FILEDLG_DIRS );
202 nH = aPnt.Y() + nNewH + a6Siz.Height();
203 pDriveTitle = NULL;
204 pDriveList = NULL;
205 #endif
207 long nExtraWidth = pDlg->GetTextWidth( String( RTL_CONSTASCII_USTRINGPARAM( "(W)" ) ) )+10;
208 String aOkStr = Button::GetStandardText( BUTTON_OK );
209 long nTextWidth = pDlg->GetTextWidth( aOkStr )+nExtraWidth;
210 if( nTextWidth > aBtnSiz.Width() )
211 aBtnSiz.Width() = nTextWidth;
213 String aCancelStr = Button::GetStandardText( BUTTON_CANCEL );
214 nTextWidth = pDlg->GetTextWidth( aCancelStr )+nExtraWidth;
215 if( nTextWidth > aBtnSiz.Width() )
216 aBtnSiz.Width() = nTextWidth;
218 String aNewDirStr( SvtResId( STR_FILEDLG_NEWDIR ) );
219 nTextWidth = pDlg->GetTextWidth( aNewDirStr )+nExtraWidth;
220 if( nTextWidth > aBtnSiz.Width() )
221 aBtnSiz.Width() = nTextWidth;
222 #if defined(UNX) || defined(OS2)
223 String aHomeDirStr( SvtResId( STR_FILEDLG_HOME ) );
224 nTextWidth = pDlg->GetTextWidth( aHomeDirStr )+nExtraWidth;
225 if( nTextWidth > aBtnSiz.Width() )
226 aBtnSiz.Width() = nTextWidth;
227 #endif
229 aPnt.X() = 2 * a6Siz.Width() + aEDSiz.Width();
230 aPnt.Y() = a6Siz.Height();
231 INITCONTROL( pOkBtn, PushButton, WB_DEFBUTTON,
232 aPnt, aBtnSiz, aOkStr, 0 );
233 aPnt.Y() += aBtnSiz.Height() + a3Siz.Height();
234 INITCONTROL( pCancelBtn, CancelButton, 0,
235 aPnt, aBtnSiz, aCancelStr, 0 );
236 aPnt.Y() += aBtnSiz.Height() + a3Siz.Height();
237 INITCONTROL( pNewDirBtn, PushButton, WB_DEFBUTTON,
238 aPnt, aBtnSiz, aNewDirStr, HID_FILEDLG_NEWDIR );
239 #if defined(UNX) || defined(OS2)
240 aPnt.Y() += aBtnSiz.Height() + a3Siz.Height();
241 INITCONTROL( pHomeBtn, PushButton, WB_DEFBUTTON,
242 aPnt, aBtnSiz, aHomeDirStr, HID_FILEDLG_HOME );
243 #else
244 pHomeBtn = NULL;
245 #endif
247 pDirPath = 0;
248 pLoadBtn = 0;
249 // Dialogbreite == OKBtn-Position + OKBtn-Breite + Rand
250 long nW = aPnt.X() + aBtnSiz.Width() + a6Siz.Width();
252 pDlg->SetOutputSizePixel( Size( nW, nH ) ); // Groesse ggf. auch Resource wird geplaettet?
254 if (pDirList)
255 pDirList->SetDoubleClickHdl(LINK( this, ImpPathDialog, DblClickHdl) );
257 if (pDirList)
258 pDirList->SetSelectHdl( LINK( this, ImpPathDialog, SelectHdl ) );
260 if (pDriveList)
261 pDriveList->SetSelectHdl( LINK( this, ImpPathDialog, SelectHdl ) );
263 if (pOkBtn)
264 pOkBtn->SetClickHdl( LINK( this, ImpPathDialog, ClickHdl) );
266 if (pCancelBtn)
267 pCancelBtn->SetClickHdl( LINK( this, ImpPathDialog, ClickHdl) );
269 if (pHomeBtn)
270 pHomeBtn->SetClickHdl( LINK( this, ImpPathDialog, ClickHdl) );
272 if (pNewDirBtn)
273 pNewDirBtn->SetClickHdl( LINK( this, ImpPathDialog, ClickHdl) );
275 nOwnChilds = pDlg->GetChildCount();
280 IMPL_LINK( ImpPathDialog, SelectHdl, ListBox *, p )
282 if( p == pDriveList )
284 UniString aDrive( pDriveList->GetSelectEntry(), 0, 2);
285 aDrive += '\\';
286 SetPath( aDrive );
288 else
289 if( p == pDirList )
291 // isolate the pure name of the entry
292 // removing trainling stuff and leading spaces
293 UniString aEntry( pDirList->GetSelectEntry() );
295 aEntry.EraseLeadingChars( ' ' );
296 USHORT nPos = aEntry.Search( '/' );
297 aEntry.Erase( nPos );
299 // build the absolute path to the selected item
300 DirEntry aNewPath;
301 aNewPath.ToAbs();
303 USHORT nCurPos = pDirList->GetSelectEntryPos();
305 // Wird nach oben gewechselt
306 if( nCurPos < nDirCount )
307 aNewPath = aNewPath[nDirCount-nCurPos-1];
308 else
309 aNewPath += aEntry;
311 pEdit->SetText( aNewPath.GetFull() );
314 return 0;
318 IMPL_LINK( ImpPathDialog, ClickHdl, Button*, pBtn )
320 if ( pBtn == pOkBtn || pBtn == pLoadBtn )
322 DirEntry aFile( pEdit->GetText() );
324 // Existiert File / File ueberschreiben
325 if( IsFileOk( aFile ) )
327 // Ja, dann kompletten Pfad mit Filenamen merken und Dialog beenden
328 aPath = aFile;
329 aPath.ToAbs();
330 GetPathDialog()->EndDialog( TRUE );
332 else
334 DirEntry aCheck( aPath );
335 aCheck += aFile;
336 if( aCheck.Exists() )
338 aCheck.ToAbs();
339 SetPath( aCheck.GetFull() );
340 pEdit->SetSelection( Selection( 0x7FFFFFFF, 0x7FFFFFFF ) );
344 else
345 if ( pBtn == pCancelBtn )
347 GetPathDialog()->EndDialog( FALSE );
349 else
350 if ( pBtn == pHomeBtn )
352 ::rtl::OUString aHomeDir;
353 NAMESPACE_VOS( OSecurity ) aSecurity;
354 if ( aSecurity.getHomeDir( aHomeDir ) )
356 DirEntry aFile ( aHomeDir );
357 if ( IsFileOk( aFile ) )
359 aFile.ToAbs();
360 SetPath( aFile.GetFull() );
364 else
365 if ( pBtn == pNewDirBtn )
367 DirEntry aFile( pEdit->GetText() );
368 if( ! aFile.Exists() && ! FileStat( aFile ).IsKind( FSYS_KIND_WILD ) )
369 aFile.MakeDir();
371 if( IsFileOk ( aFile ) )
373 aFile.ToAbs();
374 SetPath( aFile.GetFull() );
378 return 0;
382 IMPL_LINK( ImpPathDialog, DblClickHdl, ListBox*, pBox )
384 // isolate the pure name of the entry
385 // removing trainling stuff and leading spaces
386 UniString aEntry( pBox->GetSelectEntry() );
388 aEntry.EraseLeadingChars( ' ' );
389 USHORT nPos = aEntry.Search( '/' );
390 aEntry.Erase( nPos );
392 // build the absolute path to the selected item
393 DirEntry aNewPath;
394 aNewPath.ToAbs();
395 if( pBox == pDirList )
397 USHORT nCurPos = pDirList->GetSelectEntryPos();
399 // Wenn es schon das aktuelle ist, dann mache nichts
400 if( nCurPos == nDirCount-1 )
401 return 0;
403 // Wird nach oben gewechselt
404 if( nCurPos < nDirCount )
405 aNewPath = aNewPath[nDirCount-nCurPos-1];
406 else
407 aNewPath += aEntry;
409 else
410 aNewPath += aEntry;
412 pSvPathDialog->EnterWait();
414 if( FileStat( aNewPath ).GetKind() & FSYS_KIND_DIR )
416 // Neuen Pfad setzen und Listboxen updaten
417 aPath = aNewPath;
418 if( !aPath.SetCWD( TRUE ) )
420 ErrorBox aBox( GetPathDialog(),
421 WB_OK_CANCEL | WB_DEF_OK,
422 UniString( SvtResId( STR_FILEDLG_CANTCHDIR ) ) );
423 if( aBox.Execute() == RET_CANCEL )
424 GetPathDialog()->EndDialog( FALSE );
426 UpdateEntries( TRUE );
429 pSvPathDialog->LeaveWait();
430 return 0;
433 void ImpPathDialog::UpdateEntries( const BOOL )
435 UniString aTabString;
436 DirEntry aTmpPath;
437 aTmpPath.ToAbs();
439 nDirCount = aTmpPath.Level();
441 pDirList->SetUpdateMode( FALSE );
442 pDirList->Clear();
444 for( USHORT i = nDirCount; i > 0; i-- )
446 UniString aName( aTabString );
447 aName += aTmpPath[i-1].GetName();
448 pDirList->InsertEntry( aName );
449 aTabString.AppendAscii( " ", 2 );
452 // scan the directory
453 DirEntry aCurrent;
454 aCurrent.ToAbs();
456 Dir aDir( aCurrent, FSYS_KIND_DIR|FSYS_KIND_FILE );
458 USHORT nEntries = aDir.Count();
459 if( nEntries )
461 UniStringList aSortDirList;
462 for ( USHORT n = 0; n < nEntries; n++ )
464 DirEntry& rEntry = aDir[n];
465 UniString aName( rEntry.GetName() );
466 if( aName.Len() && ( aName.GetChar(0) != '.' ) && rEntry.Exists() )
468 if( FileStat( rEntry ).GetKind() & FSYS_KIND_DIR )
470 ULONG l = 0;
471 if( xCollator.is() )
473 for( l = 0; l < aSortDirList.Count(); l++ )
474 if( xCollator->compareString( *aSortDirList.GetObject(l), aName ) > 0 )
475 break;
477 aSortDirList.Insert( new UniString( aName ), l );
482 for( ULONG l = 0; l < aSortDirList.Count(); l++ )
484 UniString aEntryStr( aTabString );
485 aEntryStr += *aSortDirList.GetObject(l);
486 pDirList->InsertEntry( aEntryStr );
487 delete aSortDirList.GetObject(l);
491 UpdateDirs( aTmpPath );
494 void ImpPathDialog::UpdateDirs( const DirEntry& rTmpPath )
496 pDirList->SelectEntryPos( nDirCount-1 );
497 pDirList->SetTopEntry( nDirCount > 1
498 ? nDirCount - 2
499 : nDirCount - 1 );
500 pDirList->SetUpdateMode( TRUE );
501 pDirList->Invalidate();
502 pDirList->Update();
504 UniString aDirName = rTmpPath.GetFull();
505 if( pDirPath )
506 pDirPath->SetText( aDirName );
507 else
508 pEdit->SetText( aDirName );
511 BOOL ImpPathDialog::IsFileOk( const DirEntry& rDirEntry )
513 if( FileStat( rDirEntry ).GetKind() & (FSYS_KIND_WILD | FSYS_KIND_DEV) )
514 return FALSE;
515 else
517 // Datei vorhanden ?
518 if( ! rDirEntry.Exists() )
520 UniString aQueryTxt( SvtResId( STR_FILEDLG_ASKNEWDIR ) );
521 aQueryTxt.SearchAndReplaceAscii( "%s", rDirEntry.GetFull() );
522 QueryBox aQuery( GetPathDialog(),
523 WB_YES_NO | WB_DEF_YES,
524 aQueryTxt );
525 if( aQuery.Execute() == RET_YES )
526 rDirEntry.MakeDir();
527 else
528 return FALSE;
530 if( !FileStat( rDirEntry ).IsKind( FSYS_KIND_DIR ) )
532 UniString aBoxText( SvtResId( STR_FILEDLG_CANTOPENDIR ) );
533 aBoxText.AppendAscii( "\n[" );
534 aBoxText += rDirEntry.GetFull();
535 aBoxText.AppendAscii( "]" );
536 InfoBox aBox( GetPathDialog(), aBoxText );
537 aBox.Execute();
538 return FALSE;
541 return GetPathDialog()->OK() != 0;
545 void ImpPathDialog::PreExecute()
547 // Neues Verzeichnis setzen und Listboxen updaten
548 aPath.SetCWD( TRUE );
549 UpdateEntries( TRUE );
551 // Zusaetzliche Buttons anordnen
552 Point aPos;
553 Size aSize;
554 long nDY;
555 if( pLoadBtn )
557 aPos = pLoadBtn->GetPosPixel();
558 aSize = pLoadBtn->GetSizePixel();
559 nDY = pLoadBtn->GetSizePixel().Height() * 2;
561 else
563 aPos = pCancelBtn->GetPosPixel();
564 aSize = pCancelBtn->GetSizePixel();
565 nDY = pCancelBtn->GetPosPixel().Y() - pOkBtn->GetPosPixel().Y();
568 // Standard-Controls anpassen
569 long nMaxWidth = 0;
571 // Maximale Breite ermitteln
572 USHORT nChilds = GetPathDialog()->GetChildCount();
573 USHORT n;
574 for ( n = nOwnChilds; n < nChilds; n++ )
576 Window* pChild = GetPathDialog()->GetChild( n );
577 pChild = pChild->GetWindow( WINDOW_CLIENT );
578 if( pChild->GetType() != WINDOW_WINDOW )
580 long nWidth = pChild->GetTextWidth( pChild->GetText() ) + 12;
581 if( nMaxWidth < nWidth )
582 nMaxWidth = nWidth;
583 nWidth = pChild->GetSizePixel().Width();
584 if( nMaxWidth < nWidth )
585 nMaxWidth = nWidth;
589 if( nMaxWidth > aSize.Width() )
591 Size aDlgSize = GetPathDialog()->GetOutputSizePixel();
592 GetPathDialog()->SetOutputSizePixel( Size( aDlgSize.Width()+nMaxWidth-aSize.Width(), aDlgSize.Height() ) );
593 aSize.Width() = nMaxWidth;
595 if( pOkBtn )
596 pOkBtn->SetSizePixel( aSize );
597 if( pCancelBtn )
598 pCancelBtn->SetSizePixel( aSize );
599 if( pLoadBtn )
600 pLoadBtn->SetSizePixel( aSize );
602 else
603 nMaxWidth = aSize.Width();
605 for ( n = nOwnChilds; n < nChilds; n++ )
607 Window* pChild = GetPathDialog()->GetChild( n );
608 pChild = pChild->GetWindow( WINDOW_CLIENT );
609 if( pChild->GetType() != WINDOW_WINDOW )
611 aPos.Y() += nDY;
612 pChild->SetPosSizePixel( aPos, aSize );
614 else
616 Size aDlgSize = GetPathDialog()->GetOutputSizePixel();
617 long nExtra = Min( aDlgSize.Height(), (long)160);
618 GetPathDialog()->SetOutputSizePixel( Size( aDlgSize.Width()+nExtra, aDlgSize.Height() ) );
619 Size aSz( nExtra, nExtra );
620 aSz.Width() -= 8;
621 aSz.Height() -= 8;
622 Point aCtrlPos( aDlgSize.Width() + 2, (aDlgSize.Height()-aSz.Height())/2 );
623 pChild->SetPosSizePixel( aCtrlPos, aSz );
627 // Laufwerke-LB fuellen
628 if( pDriveList )
630 DirEntry aTmpDirEntry;
631 Dir aDir( aTmpDirEntry, FSYS_KIND_BLOCK );
633 USHORT nCount = aDir.Count(), i;
634 for( i = 0; i < nCount; ++i )
636 DirEntry& rEntry = aDir[i];
637 UniString aStr = rEntry.GetFull( FSYS_STYLE_HOST, FALSE );
639 UniString aVolume = rEntry.GetVolume() ;
640 aStr.ToUpperAscii();
641 if ( aVolume.Len() )
643 aStr += ' ';
644 aStr += aVolume;
646 pDriveList->InsertEntry( aStr );
649 UniString aPathStr = aPath.GetFull();
651 for ( i = 0; i < pDriveList->GetEntryCount(); ++i )
653 UniString aEntry = pDriveList->GetEntry(i);
654 xub_StrLen nLen = aEntry.Len();
655 nLen = nLen > 2 ? 2 : nLen;
656 if ( aEntry.CompareIgnoreCaseToAscii( aPathStr, nLen ) == COMPARE_EQUAL )
658 pDriveList->SelectEntryPos(i);
659 break;
665 void ImpPathDialog::PostExecute()
669 void ImpPathDialog::SetPath( UniString const & rPath )
671 aPath = DirEntry( rPath );
673 pSvPathDialog->EnterWait();
675 DirEntry aFile( rPath );
676 // Falls der Pfad eine Wildcard oder einen Filenamen enthaelt
677 // -> abschneiden und merken
678 if( FileStat( aFile ).GetKind() & (FSYS_KIND_FILE | FSYS_KIND_WILD) || !aFile.Exists() )
679 aFile.CutName();
681 // Neue Maske und neues Verzeichnis setzen, und Listboxen updaten
682 pEdit->SetText( rPath );
683 aFile.SetCWD( TRUE );
684 UpdateEntries( TRUE );
686 pSvPathDialog->LeaveWait();
689 void ImpPathDialog::SetPath( Edit const & rEdit )
691 UniString aPresetText = rEdit.GetText();
692 if( aPresetText.Len() )
693 SetPath( aPresetText );
697 UniString ImpPathDialog::GetPath() const
699 DirEntry aFile( pEdit->GetText() );
700 aFile.ToAbs();
701 return aFile.GetFull();
705 ImpFileDialog::ImpFileDialog( PathDialog* pDlg, WinBits nWinBits, RESOURCE_TYPE nType ) :
706 ImpPathDialog( pDlg, nType, FALSE )
708 bOpen = (nWinBits & WB_SAVEAS) == 0;
710 SvtResId aSvtResId = bOpen ? STR_FILEDLG_OPEN : STR_FILEDLG_SAVE;
712 // Titel setzen
713 GetFileDialog()->SetText( UniString( aSvtResId ) );
714 nDirCount = 0;
716 // initialize Controls if not used as a base class
717 if ( nType == WINDOW_FILEDIALOG )
718 InitControls();
720 pDlg->SetHelpId( HID_FILEDLG_OPENDLG );
724 ImpFileDialog::~ImpFileDialog()
726 ImpFilterItem* pItem = aFilterList.First();
727 while( pItem )
729 delete pItem;
730 pItem = aFilterList.Next();
733 delete pFileTitel;
734 if (pFileList && ( pFileList != pDirList ) )
735 delete pFileList;
737 delete pTypeTitel;
738 delete pTypeList;
741 void ImpFileDialog::InitControls()
743 UniString aEmptyStr;
745 const int nW = 160;
746 const int nH = 48; // Um den Dialog in eine akzeptable Form zu bringen
748 INITCONTROL( pFileTitel, FixedText, 0,
749 Point(10, 12), Size(nW, 18), UniString( SvtResId( STR_FILEDLG_FILE ) ), HID_FILEDLG_FILE );
750 INITCONTROL( pEdit, Edit, WB_BORDER,
751 Point(10, 31), Size(nW, 20), aEmptyStr, HID_FILEDLG_EDIT ); // aMask()
752 INITCONTROL( pFileList, ListBox, WB_SORT | WB_AUTOHSCROLL | WB_BORDER,
753 Point(10, 58), Size(nW, 180-nH), aEmptyStr, HID_FILEDLG_FILES );
755 INITCONTROL( pDirTitel, FixedText, 0,
756 Point(nW+20, 12), Size(nW, 18), UniString( SvtResId( STR_FILEDLG_DIR ) ), HID_FILEDLG_DIR );
757 INITCONTROL( pDirPath, FixedInfo, WB_PATHELLIPSIS,
758 Point(nW+20, 33), Size(nW, 20), aPath.GetFull(), HID_FILEDLG_PATH );
759 INITCONTROL( pDirList, KbdListBox, WB_AUTOHSCROLL | WB_BORDER,
760 Point(nW+20, 58), Size(nW, 180-nH ), aEmptyStr, HID_FILEDLG_DIRS );
762 INITCONTROL( pTypeTitel, FixedText, 0,
763 Point(10, 246-nH), Size(nW, 18), UniString( SvtResId( STR_FILEDLG_TYPE ) ), HID_FILEDLG_TYPE );
765 #ifndef UNX
766 INITCONTROL( pTypeList, ListBox, WB_DROPDOWN,
767 Point(10, 265-nH ), Size(nW, 100 ), aEmptyStr, HID_FILEDLG_TYPES );
769 INITCONTROL( pDriveTitle, FixedText, 0,
770 Point(nW+20, 246-nH), Size(nW, 18), UniString( SvtResId( STR_FILEDLG_DRIVES ) ), HID_FILEDLG_DRIVE );
771 INITCONTROL( pDriveList, ListBox, WB_DROPDOWN,
772 Point(nW+20, 265-nH ), Size(nW, 100 ), aEmptyStr, HID_FILEDLG_DRIVES );
773 pNewDirBtn = NULL;
774 pHomeBtn = NULL;
775 #else
776 INITCONTROL( pTypeList, ListBox, WB_DROPDOWN,
777 Point(10, 265-nH ), Size(2*nW+20, 100 ), aEmptyStr, HID_FILEDLG_TYPES );
779 pDriveTitle = NULL;
780 pDriveList = NULL;
781 pNewDirBtn = NULL;
782 pHomeBtn = NULL;
783 #endif
785 const long nButtonStartX = 2*nW+20+15;
786 INITCONTROL( pOkBtn, PushButton, WB_DEFBUTTON,
787 Point(nButtonStartX, 10), Size(STD_BTN_WIDTH, STD_BTN_HEIGHT),
788 Button::GetStandardText( BUTTON_OK ), 0 );
789 INITCONTROL( pCancelBtn, CancelButton, 0,
790 Point(nButtonStartX, 45 ), Size(STD_BTN_WIDTH, STD_BTN_HEIGHT),
791 Button::GetStandardText( BUTTON_CANCEL ), 0 );
793 pLoadBtn = 0;
795 GetFileDialog()->SetOutputSizePixel( Size(nButtonStartX+STD_BTN_WIDTH+10, 298-nH) );
797 nOwnChilds = GetPathDialog()->GetChildCount();
799 // Handler setzen
800 if (pDriveList)
801 pDriveList->SetSelectHdl( LINK( this, ImpFileDialog, SelectHdl ) );
803 if (pDirList)
804 pDirList->SetDoubleClickHdl(LINK( this, ImpFileDialog, DblClickHdl) );
806 if (pOkBtn)
807 pOkBtn->SetClickHdl( LINK( this, ImpFileDialog, ClickHdl) );
809 if (pCancelBtn)
810 pCancelBtn->SetClickHdl( LINK( this, ImpFileDialog, ClickHdl) );
812 if( pFileList )
814 pFileList->SetSelectHdl( LINK( this, ImpFileDialog, SelectHdl ) );
815 pFileList->SetDoubleClickHdl( LINK( this, ImpFileDialog, DblClickHdl ) );
818 if( pTypeList )
819 pTypeList->SetSelectHdl( LINK( this, ImpFileDialog, DblClickHdl ) );
822 IMPL_LINK( ImpFileDialog, SelectHdl, ListBox *, p )
824 if( p == pDriveList )
826 UniString aDrive ( pDriveList->GetSelectEntry(), 0, 2);
827 aDrive += '\\';
828 SetPath( aDrive );
830 else if (p == pFileList)
832 // Ausgewaehltes File in das Edit stellen
833 pEdit->SetText( pFileList->GetSelectEntry() );
834 GetFileDialog()->FileSelect();
836 return 0;
840 IMPL_LINK( ImpFileDialog, DblClickHdl, ListBox *, pBox )
842 // isolate the pure name of the entry
843 // removing trailing stuff and leading spaces
844 UniString aEntry( pBox->GetSelectEntry() );
846 aEntry.EraseLeadingChars( ' ' );
847 USHORT nPos = aEntry.Search( '/' );
848 aEntry.Erase( nPos );
850 // build the absolute path to the selected item
851 DirEntry aNewPath;
852 aNewPath.ToAbs();
854 if( ( pDirList != pFileList ) && ( pBox == pDirList ) )
856 // SVLOOK
857 USHORT nCurPos = pDirList->GetSelectEntryPos();
859 // Wenn es schon das aktuelle ist, dann mache nichts
860 if( nCurPos == nDirCount-1 )
861 return 0;
863 // Wird nach oben gewechselt
864 if( nCurPos < nDirCount )
865 aNewPath = aNewPath[nDirCount-nCurPos-1];
866 else
867 aNewPath += aEntry;
869 else
871 // non-SVLOOK
872 if( aEntry == UniString( SvtResId( STR_FILEDLG_GOUP ) ) )
873 aEntry.AssignAscii( ".." );
874 aNewPath += aEntry;
877 if( pBox == pFileList )
879 DirEntry aFile( aEntry );
881 // Abfrage, ob File ueberschrieben werden soll...
882 if( !FileStat(aFile).IsKind(FSYS_KIND_DIR) && IsFileOk( aFile ) )
884 // dann kompletten Pfad mit Filenamen merken und Dialog beenden
885 aPath = aNewPath;
886 GetFileDialog()->EndDialog( TRUE );
890 GetFileDialog()->EnterWait();
892 UniString aFull = aNewPath.GetFull();
894 if( ( ( pBox == pDirList ) && ( pDirList != pFileList ) ) ||
895 ( ( pDirList == pFileList ) && FileStat( aNewPath ).GetKind() & FSYS_KIND_DIR ) )
897 // Neuen Pfad setzen und Listboxen updaten
898 aPath = aNewPath;
899 if( !aPath.SetCWD( TRUE ) )
901 if( ErrorBox( GetFileDialog(), WB_OK_CANCEL|WB_DEF_OK,
902 UniString( SvtResId( STR_FILEDLG_CANTCHDIR ) ) ).Execute() == RET_CANCEL )
904 GetFileDialog()->EndDialog( FALSE );
907 UpdateEntries( TRUE );
908 GetFileDialog()->FileSelect();
911 if( pBox == pTypeList )
913 // Neue Maske setzen, und Listboxen updaten
914 USHORT nCurPos = pTypeList->GetSelectEntryPos();
915 if( nCurPos+1 > (USHORT)aFilterList.Count() )
916 aMask = UniString::CreateFromAscii( ALLFILES );
917 else
919 UniString aFilterListMask = aFilterList.GetObject( nCurPos )->aMask;
920 // if( aFilterListMask.Search( ';' ) == STRING_NOTFOUND ) // kein ; in der Maske
921 // aMask = WildCard( aFilterListMask, '\0' );
922 // else // ; muss beruecksichtigt werden
923 aMask = WildCard( aFilterListMask, ';' );
926 pEdit->SetText( aMask() );
927 UpdateEntries( FALSE );
928 GetFileDialog()->FilterSelect();
931 GetFileDialog()->LeaveWait();
933 return 0;
936 IMPL_LINK( ImpFileDialog, ClickHdl, Button*, pBtn )
938 if( ( pBtn == pOkBtn ) || ( pBtn == pLoadBtn ) )
940 DirEntry aFile( pEdit->GetText() );
942 // Existiert File / File ueberschreiben
943 if( IsFileOk( aFile ) )
945 // Ja, dann kompletten Pfad mit Filenamen merken und Dialog beenden
946 aPath = aFile;
947 aPath.ToAbs();
948 GetFileDialog()->EndDialog( TRUE );
950 else
952 GetFileDialog()->EnterWait();
954 // Falls der Pfad eine Wildcard oder einen Filenamen enthaelt
955 // -> abschneiden und merken
956 if( FileStat( aFile ).GetKind() & (FSYS_KIND_FILE | FSYS_KIND_WILD) || !aFile.Exists() )
958 aMask = aFile.CutName();
961 // Neue Maske und neues Verzeichnis setzen, und Listboxen updaten
962 pEdit->SetText( aMask() );
963 aFile.SetCWD( TRUE );
964 UpdateEntries( TRUE );
966 GetFileDialog()->LeaveWait();
969 else if( pBtn == pCancelBtn )
970 GetFileDialog()->EndDialog( FALSE );
972 return 0;
975 void ImpFileDialog::UpdateEntries( const BOOL bWithDirs )
977 GetFileDialog()->EnterWait();
979 UniString aTabString;
980 DirEntry aTmpPath;
981 aTmpPath.ToAbs();
982 nDirCount = aTmpPath.Level();
984 if( pFileList )
986 pFileList->SetUpdateMode( FALSE );
987 pFileList->Clear();
990 if( bWithDirs && (pDirList != pFileList) )
992 pDirList->SetUpdateMode( FALSE );
993 pDirList->Clear();
995 for( USHORT i = nDirCount; i > 0; i-- )
997 UniString aEntryStr( aTabString );
998 aEntryStr += aTmpPath[i-1].GetName();
999 pDirList->InsertEntry( aEntryStr );
1000 aTabString.AppendAscii( " ", 2 );
1004 // for the combined box insert a '..'
1005 // (this happens only if WB_3DLOOK is not set)
1007 if( pDirList == pFileList && nDirCount != 1 )
1008 pFileList->InsertEntry( UniString( SvtResId( STR_FILEDLG_GOUP ) ) );
1010 // scan the directory
1011 DirEntry aCurrent;
1012 aCurrent.ToAbs();
1013 Dir aDir( aCurrent, FSYS_KIND_DIR|FSYS_KIND_FILE );
1014 USHORT nEntries = aDir.Count();
1016 // TempMask, weil Vergleich case-sensitiv
1017 BOOL bMatchCase = FALSE; //aCurrent.IsCaseSensitive();
1018 UniString aWildCard( aMask.GetWildCard() );
1019 if ( !bMatchCase )
1020 aWildCard.ToLowerAscii();
1021 WildCard aTmpMask( aWildCard, ';' );
1022 if ( nEntries )
1024 UniStringList aSortDirList;
1025 for ( USHORT n = 0; n < nEntries; n++ )
1027 DirEntry& rEntry = aDir[n];
1028 UniString aName( rEntry.GetName() );
1030 if( aName.Len() &&
1031 ( ( ( aName.GetChar(0) != '.' ) ||
1032 ( ( aName.GetChar(0) == '.' ) && ( aMask.GetWildCard() ).GetChar(0) == '.' ) )
1033 && rEntry.Exists() ) )
1035 FileStat aFileStat( rEntry );
1036 UniString aTmpName( aName );
1037 if ( !bMatchCase )
1038 aTmpName.ToLowerAscii();
1039 if( ( aFileStat.GetKind() & FSYS_KIND_FILE ) && aTmpMask.Matches( aTmpName ) )
1041 if( pFileList )
1042 pFileList->InsertEntry( aName );
1044 else if( bWithDirs && ( aFileStat.GetKind() & FSYS_KIND_DIR ) )
1046 if( pDirList == pFileList )
1048 UniString aEntryStr( aName );
1049 aEntryStr += '/';
1050 pDirList->InsertEntry( aEntryStr );
1052 else
1054 ULONG l = 0;
1055 if( xCollator.is() )
1057 for( l = 0; l < aSortDirList.Count(); l++ )
1058 if( xCollator->compareString( *aSortDirList.GetObject(l), aName ) > 0 )
1059 break;
1061 aSortDirList.Insert( new UniString( aName ), l );
1066 for( ULONG l = 0; l < aSortDirList.Count(); l++ )
1068 UniString aEntryStr( aTabString );
1069 aEntryStr += *aSortDirList.GetObject(l);
1070 pDirList->InsertEntry( aEntryStr );
1071 delete aSortDirList.GetObject(l);
1075 if( bWithDirs )
1076 UpdateDirs( aTmpPath );
1078 if( pFileList )
1080 if ( pDirList == pFileList && nDirCount > 1 )
1081 pFileList->SelectEntryPos( 1 );
1082 else
1083 pFileList->SetNoSelection();
1084 pFileList->SetUpdateMode( TRUE );
1085 pFileList->Invalidate();
1086 pFileList->Update();
1089 if( pDriveList )
1091 if( pDirList->GetEntryCount() > 0 )
1093 UniString aStr( pDirList->GetEntry( 0 ) );
1094 aStr.Erase( 2 );
1095 aStr.ToLowerAscii();
1096 pDriveList->SelectEntry( aStr );
1100 GetFileDialog()->LeaveWait();
1103 BOOL ImpFileDialog::IsFileOk( const DirEntry& rDirEntry )
1105 if( FileStat( rDirEntry ).GetKind() & (FSYS_KIND_WILD | FSYS_KIND_DEV) )
1106 return FALSE;
1107 if( FileStat( rDirEntry ).GetKind() & FSYS_KIND_DIR )
1109 if( pFileList )
1110 return FALSE;
1112 else if( bOpen )
1114 // Datei vorhanden ?
1115 if( !FileStat( rDirEntry ).IsKind( FSYS_KIND_FILE ) )
1117 UniString aErrorString( SvtResId( STR_FILEDLG_CANTOPENFILE ) );
1118 aErrorString.AppendAscii( "\n[" );
1119 aErrorString += rDirEntry.GetFull();
1120 aErrorString += ']';
1121 InfoBox aBox( GetFileDialog(),
1122 aErrorString );
1123 aBox.Execute();
1124 return FALSE;
1127 else
1129 // Datei vorhanden ?
1130 if( FileStat( ExtendFileName( rDirEntry ) ).IsKind( FSYS_KIND_FILE ) )
1132 UniString aQueryString( SvtResId( STR_FILEDLG_OVERWRITE ) );
1133 aQueryString.AppendAscii( "\n[" );
1134 aQueryString += rDirEntry.GetFull();
1135 aQueryString += ']';
1136 QueryBox aBox( GetFileDialog(),
1137 WinBits( WB_YES_NO | WB_DEF_NO ),
1138 aQueryString );
1139 if( aBox.Execute() != RET_YES )
1140 return FALSE;
1143 return GetFileDialog()->OK() != 0;
1146 void ImpFileDialog::SetPath( UniString const & rPath )
1148 aPath = DirEntry( rPath );
1149 GetFileDialog()->EnterWait();
1151 DirEntry aFile( rPath );
1153 // Falls der Pfad eine Wildcard oder einen Filenamen enthaelt
1154 // -> abschneiden und merken
1155 if( FileStat( aFile ).GetKind() & (FSYS_KIND_FILE | FSYS_KIND_WILD) || !aFile.Exists() )
1157 aMask = aFile.CutName();
1159 // Neue Maske und neues Verzeichnis setzen, und Listboxen updaten
1160 if( pDirList )
1162 UniString aWildCard( aMask.GetWildCard() );
1163 pEdit->SetText( aWildCard );
1165 else
1166 pEdit->SetText( rPath );
1169 aFile.SetCWD( TRUE );
1171 UpdateEntries( TRUE );
1173 GetFileDialog()->LeaveWait();
1176 void ImpFileDialog::SetPath( Edit const& rEdit )
1178 UniString aPresetText = rEdit.GetText();
1179 if( aPresetText.Len() )
1180 SetPath( aPresetText );
1184 void ImpFileDialog::AddFilter( const UniString& rFilter, const UniString& rMask )
1186 aFilterList.Insert( new ImpFilterItem( rFilter, rMask ), LIST_APPEND );
1187 if( pTypeList )
1188 pTypeList->InsertEntry( rFilter, LISTBOX_APPEND );
1190 if( !GetCurFilter().Len() )
1191 SetCurFilter( rFilter );
1194 void ImpFileDialog::RemoveFilter( const UniString& rFilter )
1196 ImpFilterItem* pItem = aFilterList.First();
1197 while( pItem && pItem->aName != rFilter )
1198 pItem = aFilterList.Next();
1200 if( pItem )
1202 delete aFilterList.Remove();
1203 if( pTypeList )
1204 pTypeList->RemoveEntry( rFilter );
1208 void ImpFileDialog::RemoveAllFilter()
1210 ImpFilterItem* pItem = aFilterList.First();
1211 while( pItem )
1213 delete pItem;
1214 pItem = aFilterList.Next();
1216 aFilterList.Clear();
1218 if( pTypeList )
1219 pTypeList->Clear();
1222 void ImpFileDialog::SetCurFilter( const UniString& rFilter )
1224 if( !pTypeList )
1225 return;
1227 ImpFilterItem* pItem = aFilterList.First();
1228 while( pItem && pItem->aName != rFilter )
1229 pItem = aFilterList.Next();
1231 if( pItem )
1232 pTypeList->SelectEntryPos( (USHORT)aFilterList.GetCurPos() );
1233 else
1234 pTypeList->SetNoSelection();
1237 UniString ImpFileDialog::GetCurFilter() const
1239 UniString aFilter;
1240 if ( pTypeList )
1241 aFilter = pTypeList->GetSelectEntry();
1242 return aFilter;
1245 void ImpFileDialog::PreExecute()
1247 // ListBoxen erst unmittelbar vor Execute fuellen
1248 // (damit vor Execute der Pfad umgesetzt werden kann, ohne das immer die
1249 // Listboxen sofort upgedatet werden)
1251 GetFileDialog()->EnterWait();
1253 // Wenn kein Filter vorhanden, dann auch keine FilterBox
1254 if( pTypeList && !pTypeList->GetEntryCount() )
1256 // pTypeList->InsertEntry( "* (all files)" );
1257 pTypeTitel->Disable();
1258 pTypeList->Disable();
1261 if( pTypeList )
1263 USHORT nCurType = pTypeList->GetSelectEntryPos();
1264 if( nCurType < aFilterList.Count() )
1266 UniString aFilterListMask = aFilterList.GetObject( nCurType )->aMask;
1267 if( aFilterListMask.Search( ';' ) == STRING_NOTFOUND ) // kein ; in der Maske
1268 aMask = WildCard( aFilterListMask, '\0' );
1269 else // ; in der Maske, muss in der Wildcard beruecksichtigt werden
1270 aMask = WildCard( aFilterListMask, ';' );
1272 else
1273 aMask = UniString::CreateFromAscii( ALLFILES );
1275 else
1276 aMask = UniString::CreateFromAscii( ALLFILES );
1278 // Neue Maske setzen
1279 if( pEdit->GetText().Len() == 0 )
1280 pEdit->SetText( aMask() );
1282 ImpPathDialog::PreExecute();
1284 GetFileDialog()->LeaveWait();
1287 UniString ImpFileDialog::GetPath() const
1289 DirEntry aFile( pEdit->GetText() );
1290 return ExtendFileName( aFile );
1293 UniString ImpFileDialog::ExtendFileName( DirEntry aEntry ) const
1295 aEntry.ToAbs();
1296 // das ganze Theater hier ohnehin nur machen, wenn Dateiname
1297 // ohne Extension angegeben wurde
1298 if( !aEntry.GetExtension().Len() )
1300 UniString aPostfix; // hier kommt die ausgesuchte Extension herein
1302 // ist ein Filter mit Extension gesetzt?
1303 USHORT nChosenFilterPos = pTypeList->GetSelectEntryPos();
1304 if( nChosenFilterPos != LISTBOX_ENTRY_NOTFOUND )
1306 UniString aExtensionMask = GetFileDialog()->GetFilterType( nChosenFilterPos );
1307 // aExtension ist z.B. *.sdw, alles bis einschliesslich Punkt abschneiden
1308 UniString aExtension = aExtensionMask.Copy( aExtensionMask.Search( '.' )+1 );
1310 // hat der Filter ueberhaupt eine Extension
1311 if( aExtension.Len() )
1313 // keine Wildcards enthalten?
1314 if( ( aExtension.Search( '*' ) == STRING_NOTFOUND ) &&
1315 ( aExtension.Search( '?' ) == STRING_NOTFOUND ) )
1317 // OK, Filter hat Extension ohne Wildcards -> verwenden
1318 aPostfix = aExtension;
1320 else
1322 // Filter hat Extension mit Wildcards (z.B. *.*) -> nicht verwenden
1323 aPostfix.Erase();
1326 else
1328 // Filter hatte keine Extension (schwer vorstellbar) -> nichts anhaengen
1329 aPostfix.Erase();
1332 else
1334 // kein Filter gefunden (merkw�rdig) -> Default-Extension anhaengen
1335 aPostfix = GetFileDialog()->GetDefaultExt();
1338 // jetzt kann es mit dem Anhaengen losgehen
1339 const sal_Unicode* pExt = aPostfix.GetBuffer();
1340 while( *pExt == '*' || *pExt == '?' )
1341 pExt++;
1343 if( *pExt )
1345 UniString aName = aEntry.GetName();
1346 if( *pExt != '.' )
1347 aName += '.';
1348 aName += pExt;
1349 aEntry.SetName( aName );
1352 return aEntry.GetFull();
1356 void ImpSvFileDlg::CreateDialog( PathDialog* pSvDlg, WinBits nStyle, RESOURCE_TYPE nType, BOOL bCreate )
1358 delete pDlg;
1359 if ( nType == WINDOW_PATHDIALOG )
1360 pDlg = new ImpPathDialog( pSvDlg, nType, bCreate );
1361 else
1362 pDlg = new ImpFileDialog( pSvDlg, nStyle, nType );