Update ooo320-m1
[ooovba.git] / fpicker / source / win32 / filepicker / filepickerstate.cxx
blobdc0858a63a418f6f096d73411920b2946f2969da
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: filepickerstate.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_fpicker.hxx"
34 //------------------------------------------------------------------------
35 // includes
36 //------------------------------------------------------------------------
37 #include "filepickerstate.hxx"
38 #include <osl/diagnose.h>
39 #include "controlaccess.hxx"
40 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
41 #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
42 #include <com/sun/star/ui/dialogs/ListBoxControlActions.hpp>
43 #include <com/sun/star/ui/dialogs/ControlActions.hpp>
44 #include "controlcommandrequest.hxx"
45 #include "controlcommandresult.hxx"
46 #include <com/sun/star/uno/Reference.hxx>
47 #include <com/sun/star/uno/XInterface.hpp>
48 #include <osl/file.hxx>
49 #include "FileOpenDlg.hxx"
51 #include <memory>
52 #include "..\misc\WinImplHelper.hxx"
53 //---------------------------------------------
55 //---------------------------------------------
57 using rtl::OUString;
58 using com::sun::star::uno::Any;
59 using com::sun::star::uno::Sequence;
60 using com::sun::star::uno::Reference;
61 using com::sun::star::uno::XInterface;
63 using namespace ::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds;
64 using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds;
65 using namespace ::com::sun::star::ui::dialogs::ListboxControlActions;
67 //---------------------------------------------
69 //---------------------------------------------
71 const sal_Int32 MAX_LABEL = 256;
72 const sal_Int16 LISTBOX_LABEL_OFFSET = 100;
74 //---------------------------------------------
75 // declaration
76 //---------------------------------------------
78 CFilePickerState::~CFilePickerState( )
82 //---------------------------------------------
84 //---------------------------------------------
86 CNonExecuteFilePickerState::CNonExecuteFilePickerState( ) :
87 m_FirstControlCommand( NULL )
91 //---------------------------------------------
93 //---------------------------------------------
95 CNonExecuteFilePickerState::~CNonExecuteFilePickerState( )
97 reset( );
100 //---------------------------------------------
102 //---------------------------------------------
104 void SAL_CALL CNonExecuteFilePickerState::setValue( sal_Int16 aControlId, sal_Int16 aControlAction, const Any& aValue )
106 CValueControlCommand* value_command = new CValueControlCommand(
107 aControlId, aControlAction, aValue );
109 addControlCommand( value_command );
112 //---------------------------------------------
114 //---------------------------------------------
116 Any SAL_CALL CNonExecuteFilePickerState::getValue( sal_Int16 aControlId, sal_Int16 aControlAction )
118 CValueControlCommandRequest value_request( aControlId, aControlAction );
119 Any aAny;
121 if (m_FirstControlCommand)
123 // pass the request along the command-chain
124 std::auto_ptr< CControlCommandResult > result( m_FirstControlCommand->handleRequest( &value_request ) );
126 OSL_ENSURE( result.get(), "invalid getValue request" );
128 if ( result.get() )
130 // #101753 must remove assertion else running into deadlock
131 // because getValue may be called asynchronously from main thread
132 // with locked SOLAR_MUTEX but we also need SOLAR_MUTEX in
133 // WinFileOpenDialog::onInitDone ... but we cannot dismiss the
134 // assertion dialog because at this point the FileOpen Dialog
135 // has aleady the focus but is not yet visible :-(
136 // The real cure is to remove the VCL/SOLAR_MUTEX dependency
137 // cause by the use of our resource manager and not being able to
138 // generate native windows resources
139 //OSL_ENSURE( result->hasResult( ), "invalid getValue request" );
141 if ( result->hasResult( ) )
143 CValueCommandResult* value_result = dynamic_cast< CValueCommandResult* >( result.get( ) );
144 OSL_ENSURE( value_result, "should have be a CValueCommandResult" );
146 aAny = value_result->getValue( );
147 OSL_ENSURE( aAny.hasValue( ), "empty any" );
152 return aAny;
155 //---------------------------------------------
157 //---------------------------------------------
159 void SAL_CALL CNonExecuteFilePickerState::enableControl( sal_Int16 aControlId, sal_Bool bEnable )
161 CEnableControlCommand* enable_command = new CEnableControlCommand(
162 aControlId, bEnable );
164 addControlCommand( enable_command );
167 //---------------------------------------------
169 //---------------------------------------------
171 void SAL_CALL CNonExecuteFilePickerState::setLabel( sal_Int16 aControlId, const ::rtl::OUString& aLabel )
173 CLabelControlCommand* label_command = new CLabelControlCommand(
174 aControlId, aLabel );
176 addControlCommand( label_command );
179 //---------------------------------------------
181 //---------------------------------------------
183 OUString SAL_CALL CNonExecuteFilePickerState::getLabel( sal_Int16 aControlId )
185 CControlCommandRequest label_request( aControlId );
187 // pass the request along the command-chain
188 std::auto_ptr< CControlCommandResult > result( m_FirstControlCommand->handleRequest( &label_request ) );
190 OSL_ENSURE( result->hasResult( ), "invalid getValue request" );
192 OUString aLabel;
194 if ( result->hasResult( ) )
196 CLabelCommandResult* label_result = dynamic_cast< CLabelCommandResult* >( result.get( ) );
197 OSL_ENSURE( label_result, "should have be a CLabelCommandResult" );
199 aLabel = label_result->getLabel( );
202 return aLabel;
205 /* #i26224#
206 When typing file names with drive letter but without '\'
207 in the "File name" box of the FileOpen dialog the FileOpen
208 dialog makes strange paths out of them e.g. "d:.\test.sxw".
209 Such file names will not be accepted by sal so we fix these
210 somehow broken paths here. */
211 OUString MatchFixBrokenPath(const OUString& path)
213 OSL_ASSERT(path.getLength() >= 4);
215 if (path[1] == ':' && path[2] == '.' && path[3] == '\\')
217 // skip the '.'
218 return OUString(path, 2) + path.copy(3, path.getLength() - 3);
220 return path;
223 //-----------------------------------------------------------------------------------------
225 //-----------------------------------------------------------------------------------------
226 static ::rtl::OUString trimTrailingSpaces(const ::rtl::OUString& rString)
228 rtl::OUString aResult(rString);
230 sal_Int32 nIndex = rString.lastIndexOf(' ');
231 if (nIndex == rString.getLength()-1)
233 while (nIndex >= 0 && rString[nIndex] == ' ')
234 nIndex--;
235 if (nIndex >= 0)
236 aResult = rString.copy(0,nIndex+1);
237 else
238 aResult = ::rtl::OUString();
240 return aResult;
243 Sequence< OUString > SAL_CALL CNonExecuteFilePickerState::getFiles( CFileOpenDialog* aFileOpenDialog )
245 OSL_PRECOND( aFileOpenDialog, "invalid parameter" );
247 Sequence< OUString > aFilePathList;
248 OUString aFilePathURL;
249 OUString aFilePath;
250 ::osl::FileBase::RC rc;
252 aFilePath = aFileOpenDialog->getFullFileName( );
254 if ( aFilePath.getLength( ) )
256 // tokenize the returned string and copy the
257 // sub-strings separately into a sequence
258 const sal_Unicode* pTemp = aFilePath.getStr();
259 const sal_Unicode* pStrEnd = pTemp + aFilePath.getLength();
260 sal_uInt32 lSubStr;
262 while (pTemp < pStrEnd)
264 // detect the length of the next sub string
265 lSubStr = rtl_ustr_getLength(pTemp);
267 aFilePathList.realloc(aFilePathList.getLength() + 1);
269 aFilePathList[aFilePathList.getLength() - 1] =
270 MatchFixBrokenPath(OUString(pTemp, lSubStr));
272 pTemp += (lSubStr + 1);
275 // change all entries to file URLs
276 sal_Int32 lenFileList = aFilePathList.getLength( );
277 OSL_ASSERT( lenFileList >= 1 );
279 for ( sal_Int32 i = 0; i < lenFileList; i++ )
281 aFilePath = trimTrailingSpaces(aFilePathList[i]);
282 rc = ::osl::FileBase::getFileURLFromSystemPath(
283 aFilePath, aFilePathURL );
285 // we do return all or nothing, that means
286 // in case of failures we destroy the sequence
287 // and return an empty sequence
288 if ( rc != ::osl::FileBase::E_None )
290 aFilePathList.realloc( 0 );
291 break;
294 aFilePathList[i] = aFilePathURL;
298 return aFilePathList;
301 //---------------------------------------------
303 //---------------------------------------------
305 OUString SAL_CALL CNonExecuteFilePickerState::getDisplayDirectory( CFileOpenDialog* aFileOpenDialog )
307 OSL_PRECOND( aFileOpenDialog, "invalid parameter" );
309 OUString pathURL;
310 OUString displayDir;
312 displayDir = aFileOpenDialog->getLastDisplayDirectory( );
314 if ( displayDir.getLength( ) )
315 ::osl::FileBase::getFileURLFromSystemPath( displayDir, pathURL );
317 return pathURL;
320 //---------------------------------------------
322 //---------------------------------------------
324 void SAL_CALL CNonExecuteFilePickerState::reset( )
326 CControlCommand* nextCommand;
327 CControlCommand* currentCommand = m_FirstControlCommand;
329 while( currentCommand )
331 nextCommand = currentCommand->getNextCommand( );
332 delete currentCommand;
333 currentCommand = nextCommand;
336 m_FirstControlCommand = NULL;
339 //---------------------------------------------
341 //---------------------------------------------
343 CControlCommand* SAL_CALL CNonExecuteFilePickerState::getControlCommand( ) const
345 return m_FirstControlCommand;
348 //---------------------------------------------
349 // we append new control commands to the end
350 // of the list so that we are sure the commands
351 // will be executed as the client issued it
352 //---------------------------------------------
354 void SAL_CALL CNonExecuteFilePickerState::addControlCommand( CControlCommand* aControlCommand )
356 OSL_ASSERT( aControlCommand );
358 if ( NULL == m_FirstControlCommand )
360 m_FirstControlCommand = aControlCommand;
362 else
364 CControlCommand* pNextControlCommand = m_FirstControlCommand;
366 while ( pNextControlCommand->getNextCommand( ) != NULL )
367 pNextControlCommand = pNextControlCommand->getNextCommand( );
369 pNextControlCommand->setNextCommand( aControlCommand );
373 //#######################################################################
375 //---------------------------------------------
377 //---------------------------------------------
379 CExecuteFilePickerState::CExecuteFilePickerState( HWND hwndDlg ) :
380 m_hwndDlg( hwndDlg )
384 //---------------------------------------------
386 //---------------------------------------------
388 void SAL_CALL CExecuteFilePickerState::setValue( sal_Int16 aControlId, sal_Int16 aControlAction, const Any& aValue )
390 // we do not support SET_HELP_URL/GET_HELP_URL
391 if ( com::sun::star::ui::dialogs::ControlActions::SET_HELP_URL == aControlAction )
392 return;
394 HWND hwndCtrl = GetHwndDlgItem( aControlId );
396 // the filter listbox can be manipulated via this
397 // method the caller should use XFilterManager
398 if ( !hwndCtrl || (aControlId == LISTBOX_FILTER) )
400 OSL_ENSURE( sal_False, "invalid control id" );
401 return;
404 CTRL_CLASS aCtrlClass = GetCtrlClass( hwndCtrl );
405 if ( UNKNOWN == aCtrlClass )
407 OSL_ENSURE( sal_False, "unsupported control class" );
408 return;
411 CTRL_SETVALUE_FUNCTION_T lpfnSetValue =
412 GetCtrlSetValueFunction( aCtrlClass, aControlAction );
414 if ( !lpfnSetValue )
416 OSL_ENSURE( sal_False, "unsupported control action" );
417 return;
420 // the function that we call should throw an IllegalArgumentException if
421 // the given value is invalid or empty, that's why we provide a Reference
422 // to an XInterface and a argument position
423 lpfnSetValue( hwndCtrl, aValue, Reference< XInterface >( ), 3 );
426 //---------------------------------------------
428 //---------------------------------------------
430 Any SAL_CALL CExecuteFilePickerState::getValue( sal_Int16 aControlId, sal_Int16 aControlAction )
432 // we do not support SET_HELP_URL/GET_HELP_URL
433 if ( com::sun::star::ui::dialogs::ControlActions::GET_HELP_URL == aControlAction )
434 return Any( );
436 HWND hwndCtrl = GetHwndDlgItem( aControlId );
438 // the filter listbox can be manipulated via this
439 // method the caller should use XFilterManager
440 if ( !hwndCtrl || (aControlId == LISTBOX_FILTER) )
442 OSL_ENSURE( sal_False, "invalid control id" );
443 return Any( );
446 CTRL_CLASS aCtrlClass = GetCtrlClass( hwndCtrl );
447 if ( UNKNOWN == aCtrlClass )
449 OSL_ENSURE( sal_False, "unsupported control class" );
450 return Any( );
453 CTRL_GETVALUE_FUNCTION_T lpfnGetValue =
454 GetCtrlGetValueFunction( aCtrlClass, aControlAction );
456 if ( !lpfnGetValue )
458 OSL_ENSURE( sal_False, "unsupported control action" );
459 return Any( );
462 return lpfnGetValue( hwndCtrl );
465 //---------------------------------------------
467 //---------------------------------------------
469 void SAL_CALL CExecuteFilePickerState::enableControl( sal_Int16 aControlId, sal_Bool bEnable )
471 HWND hwndCtrl = GetHwndDlgItem( aControlId );
473 OSL_ENSURE( IsWindow( hwndCtrl ), "invalid element id");
475 EnableWindow( hwndCtrl, bEnable );
478 //---------------------------------------------
480 //---------------------------------------------
482 void SAL_CALL CExecuteFilePickerState::setLabel( sal_Int16 aControlId, const OUString& aLabel )
484 HWND hwndCtrl = GetHwndDlgItem( aControlId );
486 OSL_ENSURE( IsWindow( hwndCtrl ), "invalid element id");
488 if ( IsListboxControl( hwndCtrl ) )
489 hwndCtrl = GetListboxLabelItem( aControlId );
491 OUString aWinLabel = SOfficeToWindowsLabel( aLabel );
493 // somewhat risky because we don't know if OUString
494 // has a terminating '\0'
495 SetWindowText( hwndCtrl, reinterpret_cast<LPCTSTR>(aWinLabel.getStr( )) );
498 //---------------------------------------------
500 //---------------------------------------------
502 OUString SAL_CALL CExecuteFilePickerState::getLabel( sal_Int16 aControlId )
504 HWND hwndCtrl = GetHwndDlgItem( aControlId );
506 OSL_ENSURE( IsWindow( hwndCtrl ), "invalid element id");
508 if ( IsListboxControl( hwndCtrl ) )
509 hwndCtrl = GetListboxLabelItem( aControlId );
511 sal_Unicode aLabel[MAX_LABEL];
512 int nRet = GetWindowText( hwndCtrl, reinterpret_cast<LPTSTR>(aLabel), MAX_LABEL );
514 OUString ctrlLabel;
515 if ( nRet )
517 ctrlLabel = OUString( aLabel, rtl_ustr_getLength( aLabel ) );
518 ctrlLabel = WindowsToSOfficeLabel( aLabel );
521 return ctrlLabel;
524 //---------------------------------------------
526 //---------------------------------------------
528 Sequence< OUString > SAL_CALL CExecuteFilePickerState::getFiles( CFileOpenDialog* aFileOpenDialog )
530 OSL_POSTCOND( aFileOpenDialog, "invalid parameter" );
532 Sequence< OUString > aFilePathList;
533 OUString aFilePathURL;
534 OUString aFilePath;
535 ::osl::FileBase::RC rc;
537 // in execution mode getFullFileName doesn't
538 // return anything, so we must use another way
540 // returns the currently selected file(s)
541 // including path information
542 aFilePath = aFileOpenDialog->getCurrentFilePath( );
544 // if multiple files are selected or the user
545 // typed anything that doesn't seem to be a valid
546 // file name getFileURLFromSystemPath fails
547 // and we return an empty file list
548 rc = ::osl::FileBase::getFileURLFromSystemPath(
549 aFilePath, aFilePathURL );
551 if ( ::osl::FileBase::E_None == rc )
553 aFilePathList.realloc( 1 );
554 aFilePathList[0] = aFilePathURL;
557 return aFilePathList;
560 //---------------------------------------------
562 //---------------------------------------------
564 OUString SAL_CALL CExecuteFilePickerState::getDisplayDirectory( CFileOpenDialog* aFileOpenDialog )
566 OSL_POSTCOND( aFileOpenDialog, "invalid parameter" );
568 OUString pathURL;
569 OUString displayDir;
571 displayDir = aFileOpenDialog->getCurrentFolderPath( );
573 if ( displayDir.getLength( ) )
574 ::osl::FileBase::getFileURLFromSystemPath( displayDir, pathURL );
576 return pathURL;
579 //---------------------------------------------
581 //---------------------------------------------
583 void SAL_CALL CExecuteFilePickerState::initFilePickerControls( CControlCommand* firstControlCommand )
585 CControlCommand* aControlCommand = firstControlCommand;
587 while ( aControlCommand )
589 aControlCommand->exec( this );
590 aControlCommand = aControlCommand->getNextCommand( );
594 //---------------------------------------------
596 //---------------------------------------------
598 void SAL_CALL CExecuteFilePickerState::cacheControlState( HWND hwndControl, CFilePickerState* aNonExecFilePickerState )
600 OSL_ENSURE( hwndControl && aNonExecFilePickerState, "invalid parameters" );
602 CTRL_CLASS aCtrlClass = GetCtrlClass( hwndControl );
604 sal_Int16 aControlAction;
605 CTRL_GETVALUE_FUNCTION_T lpfnGetValue;
607 if ( CHECKBOX == aCtrlClass )
609 aControlAction = 0;
611 lpfnGetValue = GetCtrlGetValueFunction( aCtrlClass, aControlAction );
613 OSL_ASSERT( lpfnGetValue );
615 aNonExecFilePickerState->setValue(
616 sal::static_int_cast< sal_Int16 >( GetDlgCtrlID( hwndControl ) ),
617 aControlAction,
618 lpfnGetValue( hwndControl ) );
620 aNonExecFilePickerState->setLabel(
621 sal::static_int_cast< sal_Int16 >( GetDlgCtrlID( hwndControl ) ),
622 getLabel(
623 sal::static_int_cast< sal_Int16 >(
624 GetDlgCtrlID( hwndControl ) ) ) );
626 else if ( LISTBOX == aCtrlClass )
628 // for listboxes we save only the
629 // last selected item and the last
630 // selected item index
632 aControlAction = GET_SELECTED_ITEM;
634 lpfnGetValue = GetCtrlGetValueFunction( aCtrlClass, aControlAction );
636 aNonExecFilePickerState->setValue(
637 sal::static_int_cast< sal_Int16 >( GetDlgCtrlID( hwndControl ) ),
638 aControlAction,
639 lpfnGetValue( hwndControl ) );
641 aControlAction = ::com::sun::star::ui::dialogs::ControlActions::GET_SELECTED_ITEM_INDEX;
643 lpfnGetValue = GetCtrlGetValueFunction( aCtrlClass, aControlAction );
645 aNonExecFilePickerState->setValue(
646 sal::static_int_cast< sal_Int16 >( GetDlgCtrlID( hwndControl ) ),
647 aControlAction,
648 lpfnGetValue( hwndControl ) );
652 //---------------------------------------------
654 //---------------------------------------------
656 void SAL_CALL CExecuteFilePickerState::setHwnd( HWND hwndDlg )
658 m_hwndDlg = hwndDlg;
661 //---------------------------------------------
663 //---------------------------------------------
665 inline sal_Bool SAL_CALL CExecuteFilePickerState::IsListboxControl( HWND hwndControl ) const
667 OSL_PRECOND( IsWindow( hwndControl ), "invalid parameter" );
669 CTRL_CLASS aCtrlClass = GetCtrlClass( hwndControl );
670 return ( LISTBOX == aCtrlClass );
673 //---------------------------------------------
674 // because listboxes (comboboxes) and their labels
675 // are seperated we have to translate the listbox
676 // id to their corresponding label id
677 // the convention is that the label id of a listbox
678 // is the id of the listbox + 100
679 //---------------------------------------------
681 inline sal_Int16 SAL_CALL CExecuteFilePickerState::ListboxIdToListboxLabelId( sal_Int16 aListboxId ) const
683 return ( aListboxId + LISTBOX_LABEL_OFFSET );
686 //---------------------------------------------
688 //---------------------------------------------
690 inline HWND SAL_CALL CExecuteFilePickerState::GetListboxLabelItem( sal_Int16 aControlId ) const
692 sal_Int16 aLabelId = ListboxIdToListboxLabelId( aControlId );
693 HWND hwndCtrl = GetHwndDlgItem( aLabelId );
695 OSL_ASSERT( IsWindow( hwndCtrl ) );
697 return hwndCtrl;
700 //---------------------------------------------
702 //---------------------------------------------
704 HWND SAL_CALL CExecuteFilePickerState::GetHwndDlgItem( sal_Int16 aControlId, sal_Bool bIncludeStdCtrls ) const
706 OSL_ENSURE( IsWindow( m_hwndDlg ), "no valid parent window set before" );
708 HWND hwndCtrl = GetDlgItem( m_hwndDlg, aControlId );
710 // maybe it's a control of the dialog itself for instance
711 // the ok and cancel button
712 if ( !hwndCtrl && bIncludeStdCtrls )
714 hwndCtrl = GetDlgItem(
715 GetParent( m_hwndDlg ),
716 CommonFilePickerCtrlIdToWinFileOpenCtrlId( aControlId ) );
719 return hwndCtrl;