diff options
Diffstat (limited to 'fpicker/source')
186 files changed, 45744 insertions, 0 deletions
diff --git a/fpicker/source/aqua/AquaFilePickerDelegate.hxx b/fpicker/source/aqua/AquaFilePickerDelegate.hxx new file mode 100644 index 000000000000..4ae6eecb04c9 --- /dev/null +++ b/fpicker/source/aqua/AquaFilePickerDelegate.hxx @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _AQUAFILEPICKERDELEGATE_HXX_ +#define _AQUAFILEPICKERDELEGATE_HXX_ + +#include <premac.h> +#include <Cocoa/Cocoa.h> +#include <postmac.h> + +class SalAquaFilePicker; +class FilterHelper; + +@interface AquaFilePickerDelegate : NSObject +{ + SalAquaFilePicker* filePicker; + FilterHelper* filterHelper; +} + +- (id)initWithFilePicker:(SalAquaFilePicker*)fPicker; + +- (void)setFilterHelper:(FilterHelper*)filterHelper; + +- (MacOSBOOL)panel:(id)sender shouldShowFilename:(NSString *)filename; +- (void)panelSelectionDidChange:(id)sender; +- (void)panel:(id)sender directoryDidChange:(NSString *)path; + +- (void)filterSelectedAtIndex:(id)sender; +- (void)autoextensionChanged:(id)sender; + +@end + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/aqua/AquaFilePickerDelegate.mm b/fpicker/source/aqua/AquaFilePickerDelegate.mm new file mode 100644 index 000000000000..4266453a7102 --- /dev/null +++ b/fpicker/source/aqua/AquaFilePickerDelegate.mm @@ -0,0 +1,123 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#include <com/sun/star/uno/Any.hxx> + +#ifndef _SALAQUAFILEPICKER_HXX_ +#include "SalAquaFilePicker.hxx" +#endif + +#ifndef _FILTERHELPER_HXX_ +#include "FilterHelper.hxx" +#endif + +#include "AquaFilePickerDelegate.hxx" + +@implementation AquaFilePickerDelegate + +- (id)initWithFilePicker:(SalAquaFilePicker*)fPicker +{ + if ((self = [super init])) { + filePicker = fPicker; + filterHelper = NULL; + return self; + } + return nil; +} + +- (void)setFilterHelper:(FilterHelper*)helper +{ + filterHelper = helper; +} + +#pragma mark NSSavePanel delegate methods + +- (MacOSBOOL)panel:(id)sender shouldShowFilename:(NSString *)filename +{ + if( filterHelper == NULL ) + return true; + if( filename == nil ) + return false; + return filterHelper->filenameMatchesFilter(filename); +} + +- (void)panelSelectionDidChange:(id)sender +{ + if (filePicker != NULL) { + ::com::sun::star::ui::dialogs::FilePickerEvent evt; + filePicker->fileSelectionChanged(evt); + } +} + +- (void)panel:(id)sender directoryDidChange:(NSString *)path +{ + if (filePicker != NULL) { + ::com::sun::star::ui::dialogs::FilePickerEvent evt; + filePicker->directoryChanged(evt); + } +} + + +#pragma mark UIActions +- (void)filterSelectedAtIndex:(id)sender +{ + if (sender == nil) { + return; + } + + if ([sender class] != [NSPopUpButton class]) { + return; + } + + if (filterHelper == NULL) { + return; + } + + NSPopUpButton *popup = (NSPopUpButton*)sender; + unsigned int selectedIndex = [popup indexOfSelectedItem]; + + filterHelper->SetFilterAtIndex(selectedIndex); + + filePicker->filterControlChanged(); +} + +- (void)autoextensionChanged:(id)sender +{ + if (sender == nil) { + return; + } + + if ([sender class] != [NSButton class]) { + return; + } + uno::Any aValue; + aValue <<= ([((NSButton*)sender) state] == NSOnState); + + filePicker->setValue(::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, 0, aValue); +} + +@end diff --git a/fpicker/source/aqua/CFStringUtilities.cxx b/fpicker/source/aqua/CFStringUtilities.cxx new file mode 100644 index 000000000000..7d9293d7a1f1 --- /dev/null +++ b/fpicker/source/aqua/CFStringUtilities.cxx @@ -0,0 +1,124 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <osl/diagnose.h> +#include "CFStringUtilities.hxx" + +rtl::OUString CFStringToOUString(const CFStringRef sOrig) { + //DBG_PRINT_ENTRY("CFStringUtilities", __func__, "sOrig", sOrig); + + if (NULL == sOrig) { + return rtl::OUString(); + } + + CFRetain(sOrig); + CFIndex nFileNameLength = CFStringGetLength(sOrig); + //OSL_TRACE("FH: string length: %d", (int)(nFileNameLength)); + UniChar unichars[nFileNameLength+1]; + //'close' the string buffer correctly + unichars[nFileNameLength] = '\0'; + + CFStringGetCharacters (sOrig, CFRangeMake(0,nFileNameLength), unichars); + + //we no longer need the original string + CFRelease(sOrig); + + //DBG_PRINT_EXIT("CFStringUtilities", __func__, unichars); + + return rtl::OUString(unichars); +} + +CFStringRef CFStringCreateWithOUString(const rtl::OUString& aString) { + //DBG_PRINT_ENTRY("CFStringUtilities", __func__); + + CFStringRef ref = CFStringCreateWithCharacters(kCFAllocatorDefault, aString.getStr(), aString.getLength()); + + //DBG_PRINT_EXIT("CFStringUtilities", __func__, ref); + + return ref; +} + +rtl::OUString FSRefToOUString(FSRef fsRef, InfoType info) +{ + //DBG_PRINT_ENTRY("CFStringUtilities", __func__); + + CFURLRef aUrlRef = CFURLCreateFromFSRef(NULL, &fsRef); + + rtl::OUString sResult = CFURLRefToOUString(aUrlRef, info); + + //we no longer need the CFURLRef + CFRelease(aUrlRef); + + //DBG_PRINT_EXIT("CFStringUtilities", __func__, OUStringToOString(sResult, RTL_TEXTENCODING_UTF8).getStr()); + + return sResult; +} + +rtl::OUString CFURLRefToOUString(CFURLRef aUrlRef, InfoType info) +{ + //DBG_PRINT_ENTRY("CFStringUtilities", __func__); + + CFStringRef sURLString = NULL; + + switch(info) { + case FULLPATH: + OSL_TRACE("Extracting the full path of an item"); + sURLString = CFURLGetString(aUrlRef); + CFRetain(sURLString); + break; + case FILENAME: + OSL_TRACE("Extracting the file name of an item"); + CFStringRef fullString = CFURLGetString(aUrlRef); + CFURLRef dirRef = CFURLCreateCopyDeletingLastPathComponent(NULL,aUrlRef); + CFIndex dirLength = CFStringGetLength(CFURLGetString(dirRef)); + CFRelease(dirRef); + CFIndex fullLength = CFStringGetLength(fullString); + CFRange substringRange = CFRangeMake(dirLength, fullLength - dirLength); + sURLString = CFStringCreateWithSubstring(NULL, fullString, substringRange); + break; + case PATHWITHOUTLASTCOMPONENT: + OSL_TRACE("Extracting the last but one component of an item's path"); + CFURLRef directoryRef = CFURLCreateCopyDeletingLastPathComponent(NULL,aUrlRef); + sURLString = CFURLGetString(directoryRef); + CFRetain(sURLString); + CFRelease(directoryRef); + break; + default: + break; + } + + rtl::OUString sResult = CFStringToOUString(sURLString); + + CFRelease(sURLString); + + //DBG_PRINT_EXIT("CFStringUtilities", __func__, OUStringToOString(sResult, RTL_TEXTENCODING_UTF8).getStr()); + + return sResult; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/aqua/CFStringUtilities.hxx b/fpicker/source/aqua/CFStringUtilities.hxx new file mode 100644 index 000000000000..578782b5567c --- /dev/null +++ b/fpicker/source/aqua/CFStringUtilities.hxx @@ -0,0 +1,164 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _CFSTRINGUTILITIES_HXX_ +#define _CFSTRINGUTILITIES_HXX_ + +#include <premac.h> +#include <Carbon/Carbon.h> +#include <Cocoa/Cocoa.h> +#include <postmac.h> +#include <rtl/ustring.hxx> +#include <sal/types.h> +#include <osl/diagnose.h> + +enum InfoType { + FULLPATH, + FILENAME, + PATHWITHOUTLASTCOMPONENT +}; + +rtl::OUString CFStringToOUString(const CFStringRef sOrig); +rtl::OUString FSRefToOUString(FSRef fsRef, InfoType info = FULLPATH); +rtl::OUString CFURLRefToOUString(CFURLRef aUrlRef, InfoType info); +CFStringRef CFStringCreateWithOUString(const rtl::OUString& aString); + +//debug utils +#define PARAMFILLER "\n " + +inline void DBG_PRINT_ENTRY() { + OSL_TRACE(">>> %s", __func__); +} + +inline void DBG_PRINT_ENTRY(const char * classname, const char * methodname) { + OSL_TRACE(">>> %s::%s", classname, methodname); +} + +inline void DBG_PRINT_ENTRY(const char * classname, const char * methodname, const char* param1, const char* value1) { + OSL_TRACE(">>> %s::%s%s%s = %s", classname, methodname, PARAMFILLER, param1, value1); +} + +inline void DBG_PRINT_ENTRY(const char * classname, const char * methodname, const char* param1, const rtl::OUString& value1) { + OSL_TRACE(">>> %s::%s%s%s = %s", classname, methodname, PARAMFILLER, param1, OUStringToOString(value1, RTL_TEXTENCODING_UTF8).getStr()); +} + +inline void DBG_PRINT_ENTRY(const char * classname, const char * methodname, const char* param1, const CFStringRef value1) { + OSL_TRACE(">>> %s::%s%s%s =", classname, methodname, PARAMFILLER, param1); +#if OSL_DEBUG_LEVEL > 1 + CFShow(value1); +#endif +} + +inline void DBG_PRINT_ENTRY(const char * classname, const char * methodname, const char* param1, const NSString* value1) { + OSL_TRACE(">>> %s::%s%s%s =", classname, methodname, PARAMFILLER, param1); +#if OSL_DEBUG_LEVEL > 1 + NSLog(value1); +#endif +} + +inline void DBG_PRINT_ENTRY(const char * classname, const char * methodname, const char* param1, const int value1) { + OSL_TRACE(">>> %s::%s%s%s = %d", classname, methodname, PARAMFILLER, param1, value1); +} + +inline void DBG_PRINT_ENTRY(const char * classname, const char * methodname, const char* param1, const char* value1, const char* param2, const int value2) { + OSL_TRACE(">>> %s::%s%s%s = %s%s%s = %d", classname, methodname, PARAMFILLER, param1, value1, PARAMFILLER, param2, value2); +} + +inline void DBG_PRINT_ENTRY(const char * classname, const char * methodname, const char* param1, const char* value1, const char* param2, const char* value2) { + OSL_TRACE(">>> %s::%s%s%s = %s%s%s = %s", classname, methodname, PARAMFILLER, param1, value1, PARAMFILLER, param2, value2); +} + +inline void DBG_PRINT_ENTRY(const char * classname, const char * methodname, const char* param1, const int value1, const char* param2, const int value2) { + OSL_TRACE(">>> %s::%s%s%s = %d%s%s = %d", classname, methodname, PARAMFILLER, param1, value1, PARAMFILLER, param2, value2); +} + +inline void DBG_PRINT_ENTRY(const char * classname, const char * methodname, const char* param1, const int value1, const char* param2, const char* value2) { + OSL_TRACE(">>> %s::%s%s%s = %d%s%s = %s", classname, methodname, PARAMFILLER, param1, value1, PARAMFILLER, param2, value2); +} + +inline void DBG_PRINT_ENTRY(const char * classname, const char * methodname, const char* param1, const int value1, const char* param2, const CFStringRef value2) { + OSL_TRACE(">>> %s::%s%s%s = %d%s%s =", classname, methodname, PARAMFILLER, param1, value1, PARAMFILLER, param2, value2); +#if OSL_DEBUG_LEVEL > 1 + CFShow(value2); +#endif +} + +inline void DBG_PRINT_ENTRY(const char * classname, const char * methodname, const char* param1, const int value1, const char* param2, const NSString* value2) { + OSL_TRACE(">>> %s::%s%s%s = %d%s%s =", classname, methodname, PARAMFILLER, param1, value1, PARAMFILLER, param2, value2); +#if OSL_DEBUG_LEVEL > 1 + NSLog(value2); +#endif +} + +inline void DBG_PRINT_ENTRY(const char * classname, const char * methodname, const char* param1, const rtl::OUString& value1, const char* param2, const rtl::OUString& value2) { + OSL_TRACE(">>> %s::%s%s%s = %s%s%s = %s", classname, methodname, PARAMFILLER, param1, OUStringToOString(value1, RTL_TEXTENCODING_UTF8).getStr(), PARAMFILLER, param2, OUStringToOString(value2, RTL_TEXTENCODING_UTF8).getStr()); +} + +inline void DBG_PRINT_ENTRY(const char * classname, const char * methodname, const char* param1, const rtl::OUString& value1, const char* param2, const int value2) { + OSL_TRACE(">>> %s::%s%s%s = %s%s%s = %d", classname, methodname, PARAMFILLER, param1, OUStringToOString(value1, RTL_TEXTENCODING_UTF8).getStr(), PARAMFILLER, param2, value2); +} + +//exit method debugs + +inline void DBG_PRINT_EXIT() { + OSL_TRACE("<<< %s", __func__); +} + +inline void DBG_PRINT_EXIT(const char * classname, const char * methodname) { + OSL_TRACE("<<< %s::%s", classname, methodname); +} + +inline void DBG_PRINT_EXIT(const char * classname, const char * methodname, const char* retVal) { + OSL_TRACE("<<< %s::%s%sreturnValue = %s", classname, methodname, PARAMFILLER, retVal); +} + +inline void DBG_PRINT_EXIT(const char * classname, const char * methodname, int retVal) { + OSL_TRACE("<<< %s::%s%sreturnValue = %d", classname, methodname, PARAMFILLER, retVal); +} + +inline void DBG_PRINT_EXIT(const char * classname, const char * methodname, const CFStringRef retVal) { + OSL_TRACE("<<< %s::%s%sreturnValue = ", classname, methodname, PARAMFILLER); +#if OSL_DEBUG_LEVEL > 1 + CFShow(retVal); +#endif +} + +inline void DBG_PRINT_EXIT(const char * classname, const char * methodname, const NSString* retVal) { + OSL_TRACE("<<< %s::%s%sreturnValue = ", classname, methodname, PARAMFILLER); +#if OSL_DEBUG_LEVEL > 1 + NSLog(retVal); +#endif +} + +inline void DBG_PRINT_EXIT(const char * classname, const char * methodname, const rtl::OUString& retVal) { + OSL_TRACE("<<< %s::%s%sreturnValue = %s", classname, methodname, PARAMFILLER, OUStringToOString(retVal, RTL_TEXTENCODING_UTF8).getStr()); +} + +#endif //_CFSTRINGUTILITIES_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/aqua/ControlHelper.cxx b/fpicker/source/aqua/ControlHelper.cxx new file mode 100644 index 000000000000..15b01c88db95 --- /dev/null +++ b/fpicker/source/aqua/ControlHelper.cxx @@ -0,0 +1,1022 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/ControlActions.hpp> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include <osl/mutex.hxx> +#include <vcl/svapp.hxx> +#include "CFStringUtilities.hxx" +#include "resourceprovider.hxx" +#include "NSString_OOoAdditions.hxx" + +#include "ControlHelper.hxx" + +#pragma mark DEFINES +#define CLASS_NAME "ControlHelper" +#define POPUP_WIDTH_MIN 200 +#define POPUP_WIDTH_MAX 350 + +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::ui::dialogs::TemplateDescription; +using namespace ::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds; +using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds; +using namespace ::rtl; + +#pragma mark Constructor / Destructor +//------------------------------------------------------------------------------------ +// Constructor / Destructor +//------------------------------------------------------------------------------------ +ControlHelper::ControlHelper() +: m_pUserPane(NULL) +, m_pFilterControl(nil) +, m_bUserPaneNeeded( false ) +, m_bIsUserPaneLaidOut(false) +, m_bIsFilterControlNeeded(false) +, m_pFilterHelper(NULL) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + int i; + + for( i = 0; i < TOGGLE_LAST; i++ ) { + m_bToggleVisibility[i] = false; + } + + for( i = 0; i < LIST_LAST; i++ ) { + m_bListVisibility[i] = false; + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +ControlHelper::~ControlHelper() +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + NSAutoreleasePool *pool = [NSAutoreleasePool new]; + + if (NULL != m_pUserPane) { + [m_pUserPane release]; + } + + for(std::list<NSControl *>::iterator control = m_aActiveControls.begin(); control != m_aActiveControls.end(); control++) { + NSControl* pControl = (*control); + NSString* sLabelName = m_aMapListLabels[pControl]; + if (sLabelName != nil) { + [sLabelName release]; + } + if ([pControl class] == [NSPopUpButton class]) { + NSTextField* pField = m_aMapListLabelFields[(NSPopUpButton*)pControl]; + if (pField != nil) { + [pField release]; + } + } + [pControl release]; + } + + if (m_pFilterControl != NULL) { + [m_pFilterControl setTarget:nil]; + } + + [pool release]; + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +#pragma mark XInitialization delegate +//------------------------------------------------ +// XInitialization delegate +//------------------------------------------------ +void ControlHelper::initialize( sal_Int16 nTemplateId ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "templateId", nTemplateId); + + switch( nTemplateId ) + { + case FILESAVE_AUTOEXTENSION_PASSWORD: + m_bToggleVisibility[AUTOEXTENSION] = true; + m_bToggleVisibility[PASSWORD] = true; + break; + case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS: + m_bToggleVisibility[AUTOEXTENSION] = true; + m_bToggleVisibility[PASSWORD] = true; + m_bToggleVisibility[FILTEROPTIONS] = true; + break; + case FILESAVE_AUTOEXTENSION_SELECTION: + m_bToggleVisibility[AUTOEXTENSION] = true; + m_bToggleVisibility[SELECTION] = true; + break; + case FILESAVE_AUTOEXTENSION_TEMPLATE: + m_bToggleVisibility[AUTOEXTENSION] = true; + m_bListVisibility[TEMPLATE] = true; + break; + case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE: + m_bToggleVisibility[LINK] = true; + m_bToggleVisibility[PREVIEW] = true; + m_bListVisibility[IMAGE_TEMPLATE] = true; + break; + case FILEOPEN_READONLY_VERSION: + m_bToggleVisibility[READONLY] = true; + m_bListVisibility[VERSION] = true; + break; + case FILEOPEN_LINK_PREVIEW: + m_bToggleVisibility[LINK] = true; + m_bToggleVisibility[PREVIEW] = true; + break; + case FILESAVE_AUTOEXTENSION: + m_bToggleVisibility[AUTOEXTENSION] = true; + break; + } + + createControls(); + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +#pragma mark XFilePickerControlAccess delegates +//------------------------------------------------------------------------------------ +// XFilePickerControlAccess functions +//------------------------------------------------------------------------------------ + +void ControlHelper::enableControl( const sal_Int16 nControlId, const sal_Bool bEnable ) const +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "controlId", nControlId, "enable", bEnable); + + SolarMutexGuard aGuard; + + if (nControlId == ExtendedFilePickerElementIds::CHECKBOX_PREVIEW) { + OSL_TRACE(" preview checkbox cannot be changed"); + DBG_PRINT_EXIT(CLASS_NAME, __func__); + return; + } + + NSControl* pControl = getControl(nControlId); + + if( pControl != nil ) { + if( bEnable ) { + OSL_TRACE( "enable" ); + } else { + OSL_TRACE( "disable" ); + } + [pControl setEnabled:bEnable]; + } else { + OSL_TRACE("enable unknown control %d", nControlId ); + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +OUString ControlHelper::getLabel( sal_Int16 nControlId ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "controlId", nControlId); + + SolarMutexGuard aGuard; + + NSControl* pControl = getControl( nControlId ); + + if( pControl == nil ) { + OSL_TRACE("Get label for unknown control %d", nControlId); + return OUString(); + } + + rtl::OUString retVal; + if ([pControl class] == [NSPopUpButton class]) { + NSString *temp = m_aMapListLabels[pControl]; + if (temp != nil) + retVal = [temp OUString]; + } + else { + NSString* sLabel = [[pControl cell] title]; + retVal = [sLabel OUString]; + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__, retVal); + + return retVal; +} + +void ControlHelper::setLabel( sal_Int16 nControlId, const NSString* aLabel ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "controlId", nControlId, "label", aLabel); + + SolarMutexGuard aGuard; + + NSAutoreleasePool *pool = [NSAutoreleasePool new]; + + NSControl* pControl = getControl(nControlId); + + if (nil != pControl) { + if ([pControl class] == [NSPopUpButton class]) { + NSString *sOldName = m_aMapListLabels[pControl]; + if (sOldName != NULL && sOldName != aLabel) { + [sOldName release]; + } + + m_aMapListLabels[pControl] = [aLabel retain]; + } else if ([pControl class] == [NSButton class]) { + [[pControl cell] setTitle:aLabel]; + } + } else { + OSL_TRACE("Control not found to set label for"); + } + + layoutControls(); + + [pool release]; + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +void ControlHelper::setValue( sal_Int16 nControlId, sal_Int16 nControlAction, const uno::Any& rValue ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "controlId", nControlId, "controlAction", nControlAction); + + SolarMutexGuard aGuard; + + if (nControlId == ExtendedFilePickerElementIds::CHECKBOX_PREVIEW) { + OSL_TRACE(" value for preview is unchangeable"); + } + else { + NSControl* pControl = getControl( nControlId ); + + if( pControl == nil ) { + OSL_TRACE("enable unknown control %d", nControlId); + } else { + if( [pControl class] == [NSPopUpButton class] ) { + HandleSetListValue(pControl, nControlAction, rValue); + } else if( [pControl class] == [NSButton class] ) { + sal_Bool bChecked = false; + rValue >>= bChecked; + OSL_TRACE(" value is a bool: %d", bChecked); + [(NSButton*)pControl setState:(bChecked ? NSOnState : NSOffState)]; + } else + { + OSL_TRACE("Can't set value on button / list %d %d", + nControlId, nControlAction); + } + } + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +uno::Any ControlHelper::getValue( sal_Int16 nControlId, sal_Int16 nControlAction ) const +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "controlId", nControlId, "controlAction", nControlAction); + + SolarMutexGuard aGuard; + uno::Any aRetval; + + NSControl* pControl = getControl( nControlId ); + + if( pControl == nil ) { + OSL_TRACE("get value for unknown control %d", nControlId); + aRetval <<= sal_True; + } else { + if( [pControl class] == [NSPopUpButton class] ) { + aRetval = HandleGetListValue(pControl, nControlAction); + } else if( [pControl class] == [NSButton class] ) { + //NSLog(@"control: %@", [[pControl cell] title]); + sal_Bool bValue = [(NSButton*)pControl state] == NSOnState ? sal_True : sal_False; + aRetval <<= bValue; + OSL_TRACE("value is a bool (checkbox): %d", bValue); + } + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__); + + return aRetval; +} + +void ControlHelper::createUserPane() +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + if (m_bUserPaneNeeded == false) { + OSL_TRACE("no user pane needed"); + DBG_PRINT_EXIT(CLASS_NAME, __func__); + return; + } + + if (nil != m_pUserPane) { + OSL_TRACE("user pane already exists"); + DBG_PRINT_EXIT(CLASS_NAME, __func__); + return; + } + + if (m_bIsFilterControlNeeded == true && m_pFilterControl == nil) { + createFilterControl(); + } + + NSRect minRect = NSMakeRect(0,0,300,33); + m_pUserPane = [[NSView alloc] initWithFrame:minRect]; + + int currentHeight = kAquaSpaceBoxFrameViewDiffTop + kAquaSpaceBoxFrameViewDiffBottom; + int currentWidth = 300; + + BOOL bPopupControlPresent = NO; + BOOL bButtonControlPresent = NO; + + int nCheckboxMaxWidth = 0; + int nPopupMaxWidth = 0; + int nPopupLabelMaxWidth = 0; + + for (::std::list<NSControl*>::iterator child = m_aActiveControls.begin(); child != m_aActiveControls.end(); child++) { + OSL_TRACE("currentHeight: %d", currentHeight); + + NSControl* pControl = *child; + + //let the control calculate its size + [pControl sizeToFit]; + + NSRect frame = [pControl frame]; + OSL_TRACE("frame for control %s is {%f, %f, %f, %f}", [[pControl description] UTF8String], frame.origin.x, frame.origin.y, frame.size.width, frame.size.height); + + int nControlHeight = frame.size.height; + int nControlWidth = frame.size.width; + + // Note: controls are grouped by kind, first all popup menus, then checkboxes + if ([pControl class] == [NSPopUpButton class]) { + if (bPopupControlPresent == YES) { + //this is not the first popup + currentHeight += kAquaSpaceBetweenPopupMenus; + } + else if (child != m_aActiveControls.begin()){ + currentHeight += kAquaSpaceBetweenControls; + } + + bPopupControlPresent = YES; + + // we have to add the label text width + NSString *label = m_aMapListLabels[pControl]; + + NSTextField *textField = createLabelWithString(label); + [textField sizeToFit]; + m_aMapListLabelFields[(NSPopUpButton*)pControl] = textField; + [m_pUserPane addSubview:textField]; + + NSRect tfRect = [textField frame]; + OSL_TRACE("frame for textfield %s is {%f, %f, %f, %f}", [[textField description] UTF8String], tfRect.origin.x, tfRect.origin.y, tfRect.size.width, tfRect.size.height); + + int tfWidth = tfRect.size.width; + + if (nPopupLabelMaxWidth < tfWidth) { + nPopupLabelMaxWidth = tfWidth; + } + + frame.origin.x += (kAquaSpaceBetweenControls - kAquaSpaceLabelFrameBoundsDiffH - kAquaSpacePopupMenuFrameBoundsDiffLeft) + tfWidth; + + if (nControlWidth < POPUP_WIDTH_MIN) { + nControlWidth = POPUP_WIDTH_MIN; + frame.size.width = nControlWidth; + [pControl setFrame:frame]; + } + + if (nControlWidth > POPUP_WIDTH_MAX) { + nControlWidth = POPUP_WIDTH_MAX; + frame.size.width = nControlWidth; + [pControl setFrame:frame]; + } + + //set the max size + if (nPopupMaxWidth < nControlWidth) { + nPopupMaxWidth = nControlWidth; + } + + nControlWidth += tfWidth + kAquaSpaceBetweenControls - kAquaSpaceLabelFrameBoundsDiffH - kAquaSpacePopupMenuFrameBoundsDiffLeft; + if (nControlHeight < kAquaPopupButtonDefaultHeight) { + //maybe the popup has no menu item yet, so set a default height + nControlHeight = kAquaPopupButtonDefaultHeight; + } + + nControlHeight -= kAquaSpacePopupMenuFrameBoundsDiffV; + } + else if ([pControl class] == [NSButton class]) { + if (child != m_aActiveControls.begin()){ + currentHeight += kAquaSpaceBetweenControls; + } + + if (nCheckboxMaxWidth < nControlWidth) { + nCheckboxMaxWidth = nControlWidth; + } + + bButtonControlPresent = YES; + nControlWidth -= 2 * kAquaSpaceSwitchButtonFrameBoundsDiff; + nControlHeight -= 2 * kAquaSpaceSwitchButtonFrameBoundsDiff; + } + + // if ((nControlWidth + 2 * kAquaSpaceInsideGroupH) > currentWidth) { + // currentWidth = nControlWidth + 2 * kAquaSpaceInsideGroupH; + // } + + currentHeight += nControlHeight; + + [m_pUserPane addSubview:pControl]; + } + + OSL_TRACE("height after adding all controls: %d", currentHeight); + + if (bPopupControlPresent && bButtonControlPresent) + { + //after a popup button (array) and before a different kind of control we need some extra space instead of the standard + currentHeight -= kAquaSpaceBetweenControls; + currentHeight += kAquaSpaceAfterPopupButtonsV; + OSL_TRACE("popup extra space added, currentHeight: %d", currentHeight); + } + + int nLongestPopupWidth = nPopupMaxWidth + nPopupLabelMaxWidth + kAquaSpaceBetweenControls - kAquaSpacePopupMenuFrameBoundsDiffLeft - kAquaSpaceLabelFrameBoundsDiffH; + + currentWidth = nLongestPopupWidth > nCheckboxMaxWidth ? nLongestPopupWidth : nCheckboxMaxWidth; + OSL_TRACE("longest control width: %d", currentWidth); + + currentWidth += 2* kAquaSpaceInsideGroupH; + + if (currentWidth < minRect.size.width) + currentWidth = minRect.size.width; + + if (currentHeight < minRect.size.height) + currentHeight = minRect.size.height; + + NSRect upRect = NSMakeRect(0, 0, currentWidth, currentHeight ); + OSL_TRACE("setting user pane rect to {%f, %f, %f, %f}",upRect.origin.x, upRect.origin.y, upRect.size.width, upRect.size.height); + + [m_pUserPane setFrame:upRect]; + + layoutControls(); + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +#pragma mark Private / Misc +//------------------------------------------------------------------------------------ +// Private / Misc +//------------------------------------------------------------------------------------ +void ControlHelper::createControls() +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + CResourceProvider aResProvider; + for (int i = 0; i < LIST_LAST; i++) { + if (true == m_bListVisibility[i]) { + m_bUserPaneNeeded = true; + + int elementName = getControlElementName([NSPopUpButton class], i); + NSString* sLabel = aResProvider.getResString(elementName); + + m_pListControls[i] = [NSPopUpButton new]; + +#define MAP_LIST_( elem ) \ + case elem: \ + setLabel(ExtendedFilePickerElementIds::LISTBOX_##elem, sLabel); \ + break + + switch(i) { + MAP_LIST_(VERSION); + MAP_LIST_(TEMPLATE); + MAP_LIST_(IMAGE_TEMPLATE); + } + + m_aActiveControls.push_back(m_pListControls[i]); + } else { + m_pListControls[i] = nil; + } + } + + for (int i = 0/*#i102102*/; i < TOGGLE_LAST; i++) { + if (true == m_bToggleVisibility[i]) { + m_bUserPaneNeeded = true; + + int elementName = getControlElementName([NSButton class], i); + NSString* sLabel = aResProvider.getResString(elementName); + + NSButton *button = [NSButton new]; + [button setTitle:sLabel]; + + [button setButtonType:NSSwitchButton]; + + [button setState:NSOffState]; + + if (i == AUTOEXTENSION) { + [button setTarget:m_pDelegate]; + [button setAction:@selector(autoextensionChanged:)]; + } + + m_pToggles[i] = button; + + m_aActiveControls.push_back(m_pToggles[i]); + } else { + m_pToggles[i] = nil; + } + } + + //preview is always on with Mac OS X + NSControl *pPreviewBox = m_pToggles[PREVIEW]; + if (pPreviewBox != nil) { + [pPreviewBox setEnabled:NO]; + [(NSButton*)pPreviewBox setState:NSOnState]; + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +#define TOGGLE_ELEMENT( elem ) \ +case elem: \ + nReturn = CHECKBOX_##elem; \ + DBG_PRINT_EXIT(CLASS_NAME, __func__, nReturn); \ + return nReturn +#define LIST_ELEMENT( elem ) \ +case elem: \ + nReturn = LISTBOX_##elem##_LABEL; \ + DBG_PRINT_EXIT(CLASS_NAME, __func__, nReturn); \ + return nReturn + +int ControlHelper::getControlElementName(const Class aClazz, const int nControlId) const +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "aClazz", [[aClazz description] UTF8String], "controlId", nControlId); + + int nReturn = -1; + if (aClazz == [NSButton class]) + { + switch (nControlId) { + TOGGLE_ELEMENT( AUTOEXTENSION ); + TOGGLE_ELEMENT( PASSWORD ); + TOGGLE_ELEMENT( FILTEROPTIONS ); + TOGGLE_ELEMENT( READONLY ); + TOGGLE_ELEMENT( LINK ); + TOGGLE_ELEMENT( PREVIEW ); + TOGGLE_ELEMENT( SELECTION ); + } + } + else if (aClazz == [NSPopUpButton class]) + { + switch (nControlId) { + LIST_ELEMENT( VERSION ); + LIST_ELEMENT( TEMPLATE ); + LIST_ELEMENT( IMAGE_TEMPLATE ); + } + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__, nReturn); + + return nReturn; +} + +void ControlHelper::HandleSetListValue(const NSControl* pControl, const sal_Int16 nControlAction, const uno::Any& rValue) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "controlAction", nControlAction); + + if ([pControl class] != [NSPopUpButton class]) { + OSL_TRACE("not a popup menu"); + DBG_PRINT_EXIT(CLASS_NAME, __func__); + return; + } + + NSPopUpButton *pButton = (NSPopUpButton*)pControl; + NSMenu *rMenu = [pButton menu]; + if (nil == rMenu) { + OSL_TRACE("button has no menu"); + DBG_PRINT_EXIT(CLASS_NAME, __func__); + return; + } + + switch (nControlAction) + { + case ControlActions::ADD_ITEM: + { + OSL_TRACE("ADD_ITEMS"); + OUString sItem; + rValue >>= sItem; + + NSString* sCFItem = [NSString stringWithOUString:sItem]; + OSL_TRACE("Adding menu item: %s", OUStringToOString(sItem, RTL_TEXTENCODING_UTF8).getStr()); + [pButton addItemWithTitle:sCFItem]; + } + break; + case ControlActions::ADD_ITEMS: + { + OSL_TRACE("ADD_ITEMS"); + uno::Sequence< OUString > aStringList; + rValue >>= aStringList; + sal_Int32 nItemCount = aStringList.getLength(); + for (sal_Int32 i = 0; i < nItemCount; ++i) + { + NSString* sCFItem = [NSString stringWithOUString:aStringList[i]]; + OSL_TRACE("Adding menu item: %s", OUStringToOString(aStringList[i], RTL_TEXTENCODING_UTF8).getStr()); + [pButton addItemWithTitle:sCFItem]; + } + } + break; + case ControlActions::DELETE_ITEM: + { + OSL_TRACE("DELETE_ITEM"); + sal_Int32 nPos = -1; + rValue >>= nPos; + OSL_TRACE("Deleting item at position %d", (nPos)); + [rMenu removeItemAtIndex:nPos]; + } + break; + case ControlActions::DELETE_ITEMS: + { + OSL_TRACE("DELETE_ITEMS"); + int nItems = [rMenu numberOfItems]; + if (nItems == 0) { + OSL_TRACE("no menu items to delete"); + DBG_PRINT_EXIT(CLASS_NAME, __func__); + return; + } + for(sal_Int32 i = 0; i < nItems; i++) { + [rMenu removeItemAtIndex:i]; + } + } + break; + case ControlActions::SET_SELECT_ITEM: + { + sal_Int32 nPos = -1; + rValue >>= nPos; + OSL_TRACE("Selecting item at position %d", nPos); + [pButton selectItemAtIndex:nPos]; + } + break; + default: + OSL_TRACE("undocumented/unimplemented ControlAction for a list"); + break; + } + + layoutControls(); + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + + +uno::Any ControlHelper::HandleGetListValue(const NSControl* pControl, const sal_Int16 nControlAction) const +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "controlAction", nControlAction); + + uno::Any aAny; + + if ([pControl class] != [NSPopUpButton class]) { + OSL_TRACE("not a popup button"); + DBG_PRINT_EXIT(CLASS_NAME, __func__); + return aAny; + } + + NSPopUpButton *pButton = (NSPopUpButton*)pControl; + NSMenu *rMenu = [pButton menu]; + if (nil == rMenu) { + OSL_TRACE("button has no menu"); + DBG_PRINT_EXIT(CLASS_NAME, __func__); + return aAny; + } + + switch (nControlAction) + { + case ControlActions::GET_ITEMS: + { + OSL_TRACE("GET_ITEMS"); + uno::Sequence< OUString > aItemList; + + int nItems = [rMenu numberOfItems]; + if (nItems > 0) { + aItemList.realloc(nItems); + } + for (int i = 0; i < nItems; i++) { + NSString* sCFItem = [pButton itemTitleAtIndex:i]; + if (nil != sCFItem) { + aItemList[i] = [sCFItem OUString]; + OSL_TRACE("Return value[%d]: %s", (i - 1), OUStringToOString(aItemList[i - 1], RTL_TEXTENCODING_UTF8).getStr()); + } + } + + aAny <<= aItemList; + } + break; + case ControlActions::GET_SELECTED_ITEM: + { + OSL_TRACE("GET_SELECTED_ITEM"); + NSString* sCFItem = [pButton titleOfSelectedItem]; + if (nil != sCFItem) { + OUString sString = [sCFItem OUString]; + OSL_TRACE("Return value: %s", OUStringToOString(sString, RTL_TEXTENCODING_UTF8).getStr()); + aAny <<= sString; + } + } + break; + case ControlActions::GET_SELECTED_ITEM_INDEX: + { + OSL_TRACE("GET_SELECTED_ITEM_INDEX"); + sal_Int32 nActive = [pButton indexOfSelectedItem]; + OSL_TRACE("Return value: %d", nActive); + aAny <<= nActive; + } + break; + default: + OSL_TRACE("undocumented/unimplemented ControlAction for a list"); + break; + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__); + + return aAny; +} + + +// cf. offapi/com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.idl +NSControl* ControlHelper::getControl( const sal_Int16 nControlId ) const +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "controlId", nControlId); + + NSControl* pWidget = nil; + +#define MAP_TOGGLE( elem ) \ +case ExtendedFilePickerElementIds::CHECKBOX_##elem: \ + pWidget = m_pToggles[elem]; \ + break + +#define MAP_BUTTON( elem ) \ +case ExtendedFilePickerElementIds::PUSHBUTTON_##elem: \ + pWidget = m_pButtons[elem]; \ + break + +#define MAP_LIST( elem ) \ +case ExtendedFilePickerElementIds::LISTBOX_##elem: \ + pWidget = m_pListControls[elem]; \ + break + +#define MAP_LIST_LABEL( elem ) \ +case ExtendedFilePickerElementIds::LISTBOX_##elem##_LABEL: \ + pWidget = m_pListControls[elem]; \ + break + + switch( nControlId ) + { + MAP_TOGGLE( AUTOEXTENSION ); + MAP_TOGGLE( PASSWORD ); + MAP_TOGGLE( FILTEROPTIONS ); + MAP_TOGGLE( READONLY ); + MAP_TOGGLE( LINK ); + MAP_TOGGLE( PREVIEW ); + MAP_TOGGLE( SELECTION ); + //MAP_BUTTON( PLAY ); + MAP_LIST( VERSION ); + MAP_LIST( TEMPLATE ); + MAP_LIST( IMAGE_TEMPLATE ); + MAP_LIST_LABEL( VERSION ); + MAP_LIST_LABEL( TEMPLATE ); + MAP_LIST_LABEL( IMAGE_TEMPLATE ); + default: + OSL_TRACE("Handle unknown control %d", nControlId); + break; + } +#undef MAP + + DBG_PRINT_EXIT(CLASS_NAME, __func__); + + return pWidget; +} + +void ControlHelper::layoutControls() +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + SolarMutexGuard aGuard; + + if (nil == m_pUserPane) { + OSL_TRACE("no user pane to layout"); + DBG_PRINT_EXIT(CLASS_NAME, __func__); + return; + } + + if (m_bIsUserPaneLaidOut == true) { + OSL_TRACE("user pane already laid out"); + DBG_PRINT_EXIT(CLASS_NAME, __func__); + return; + } + + NSRect userPaneRect = [m_pUserPane frame]; + OSL_TRACE("userPane frame: {%f, %f, %f, %f}",userPaneRect.origin.x, userPaneRect.origin.y, userPaneRect.size.width, userPaneRect.size.height); + + int nUsableWidth = userPaneRect.size.width; + + //NOTE: NSView's coordinate system starts in the lower left hand corner but we start adding controls from the top, + // so we subtract from the vertical position as we make our way down the pane. + int currenttop = userPaneRect.size.height; + int nCheckboxMaxWidth = 0; + int nPopupMaxWidth = 0; + int nPopupLabelMaxWidth = 0; + + //first loop to determine max sizes + for (::std::list<NSControl*>::iterator child = m_aActiveControls.begin(); child != m_aActiveControls.end(); child++) { + NSControl* pControl = *child; + + NSRect controlRect = [pControl frame]; + int nControlWidth = controlRect.size.width; + + Class aSubType = [pControl class]; + if (aSubType == [NSPopUpButton class]) { + if (nPopupMaxWidth < nControlWidth) { + nPopupMaxWidth = nControlWidth; + } + NSTextField *label = m_aMapListLabelFields[(NSPopUpButton*)pControl]; + NSRect labelFrame = [label frame]; + int nLabelWidth = labelFrame.size.width; + if (nPopupLabelMaxWidth < nLabelWidth) { + nPopupLabelMaxWidth = nLabelWidth; + } + } else { + if (nCheckboxMaxWidth < nControlWidth) { + nCheckboxMaxWidth = nControlWidth; + } + } + } + + int nLongestPopupWidth = nPopupMaxWidth + nPopupLabelMaxWidth + kAquaSpaceBetweenControls - kAquaSpacePopupMenuFrameBoundsDiffLeft - kAquaSpaceLabelFrameBoundsDiffH; + OSL_TRACE("longest popup width: %d", nLongestPopupWidth); + + NSControl* previousControl = nil; + + int nDistBetweenControls = 0; + + for (::std::list<NSControl*>::iterator child = m_aActiveControls.begin(); child != m_aActiveControls.end(); child++) { + NSControl* pControl = *child; + + //get the control's bounds + NSRect controlRect = [pControl frame]; + int nControlHeight = controlRect.size.height; + int nControlWidth = controlRect.size.width; + + //subtract the height from the current vertical position, because the control's bounds origin rect will be its lower left hand corner + currenttop -= nControlHeight; + + Class aSubType = [pControl class]; + + //add space between the previous control and this control according to Apple's HIG + nDistBetweenControls = getVerticalDistance(previousControl, pControl); + OSL_TRACE("vertical distance: %d", nDistBetweenControls); + currenttop -= nDistBetweenControls; + + previousControl = pControl; + + if (aSubType == [NSPopUpButton class]) { + //move vertically up some pixels to space the controls between their real (visual) bounds + currenttop += kAquaSpacePopupMenuFrameBoundsDiffTop;//from top + + //get the corresponding popup label + NSTextField *label = m_aMapListLabelFields[(NSPopUpButton*)pControl]; + NSRect labelFrame = [label frame]; + int totalWidth = nPopupMaxWidth + labelFrame.size.width + kAquaSpaceBetweenControls - kAquaSpacePopupMenuFrameBoundsDiffLeft - kAquaSpaceLabelFrameBoundsDiffH; + OSL_TRACE("totalWidth: %d", totalWidth); + //let's center popups + int left = (nUsableWidth + nLongestPopupWidth) / 2 - totalWidth; + OSL_TRACE("left: %d", left); + labelFrame.origin.x = left; + labelFrame.origin.y = currenttop + kAquaSpaceLabelPopupDiffV; + OSL_TRACE("setting label at: {%f, %f, %f, %f}",labelFrame.origin.x, labelFrame.origin.y, labelFrame.size.width, labelFrame.size.height); + [label setFrame:labelFrame]; + + controlRect.origin.x = left + labelFrame.size.width + kAquaSpaceBetweenControls - kAquaSpaceLabelFrameBoundsDiffH - kAquaSpacePopupMenuFrameBoundsDiffLeft; + controlRect.origin.y = currenttop; + controlRect.size.width = nPopupMaxWidth; + OSL_TRACE("setting popup at: {%f, %f, %f, %f}",controlRect.origin.x, controlRect.origin.y, controlRect.size.width, controlRect.size.height); + [pControl setFrame:controlRect]; + + //add some space to place the vertical position right below the popup's visual bounds + currenttop += kAquaSpacePopupMenuFrameBoundsDiffBottom; + } else { + currenttop += kAquaSpaceSwitchButtonFrameBoundsDiff;//from top + + nControlWidth = nCheckboxMaxWidth; + int left = (nUsableWidth - nCheckboxMaxWidth) / 2; + controlRect.origin.x = left; + controlRect.origin.y = currenttop; + controlRect.size.width = nPopupMaxWidth; + [pControl setFrame:controlRect]; + OSL_TRACE("setting checkbox at: {%f, %f, %f, %f}",controlRect.origin.x, controlRect.origin.y, controlRect.size.width, controlRect.size.height); + + currenttop += kAquaSpaceSwitchButtonFrameBoundsDiff; + } + } + + m_bIsUserPaneLaidOut = true; + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +void ControlHelper::createFilterControl() { + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + CResourceProvider aResProvider; + NSString* sLabel = aResProvider.getResString(CommonFilePickerElementIds::LISTBOX_FILTER_LABEL); + + m_pFilterControl = [NSPopUpButton new]; + + [m_pFilterControl setAction:@selector(filterSelectedAtIndex:)]; + [m_pFilterControl setTarget:m_pDelegate]; + + NSMenu *menu = [m_pFilterControl menu]; + + for (NSStringList::iterator iter = m_pFilterHelper->getFilterNames()->begin(); iter != m_pFilterHelper->getFilterNames()->end(); iter++) { + NSString *filterName = *iter; + OSL_TRACE("adding filter name: %s", [filterName UTF8String]); + if ([filterName isEqualToString:@"-"]) { + [menu addItem:[NSMenuItem separatorItem]]; + } + else { + [m_pFilterControl addItemWithTitle:filterName]; + } + } + + // always add the filter as first item + m_aActiveControls.push_front(m_pFilterControl); + m_aMapListLabels[m_pFilterControl] = [sLabel retain]; + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +NSTextField* ControlHelper::createLabelWithString(const NSString* labelString) { + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "label", labelString); + + NSTextField *textField = [NSTextField new]; + [textField setEditable:NO]; + [textField setSelectable:NO]; + [textField setDrawsBackground:NO]; + [textField setBordered:NO]; + [[textField cell] setTitle:labelString]; + + DBG_PRINT_EXIT(CLASS_NAME, __func__); + return textField; +} + +int ControlHelper::getVerticalDistance(const NSControl* first, const NSControl* second) +{ + if (first == nil) { + return kAquaSpaceBoxFrameViewDiffTop; + } + else if (second == nil) { + return kAquaSpaceBoxFrameViewDiffBottom; + } + else { + Class firstClass = [first class]; + Class secondClass = [second class]; + + if (firstClass == [NSPopUpButton class]) { + if (secondClass == [NSPopUpButton class]) { + return kAquaSpaceBetweenPopupMenus; + } + else { + return kAquaSpaceAfterPopupButtonsV; + } + } + + return kAquaSpaceBetweenControls; + } +} + +void ControlHelper::updateFilterUI() +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + if (m_bIsFilterControlNeeded == false || m_pFilterHelper == NULL) { + OSL_TRACE("no filter control needed or no filter helper present"); + DBG_PRINT_EXIT(CLASS_NAME, __func__); + return; + } + + int index = m_pFilterHelper->getCurrentFilterIndex(); + + if (m_pFilterControl == nil) { + createFilterControl(); + } + + [m_pFilterControl selectItemAtIndex:index]; + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/aqua/ControlHelper.hxx b/fpicker/source/aqua/ControlHelper.hxx new file mode 100644 index 000000000000..fa5ebc0bc0a6 --- /dev/null +++ b/fpicker/source/aqua/ControlHelper.hxx @@ -0,0 +1,198 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _CONTROLHELPER_HXX_ +#define _CONTROLHELPER_HXX_ + +#include <rtl/ustring.hxx> +#include <com/sun/star/uno/Any.hxx> + +#include <list> +#include <map> + +#include <premac.h> +#include <Cocoa/Cocoa.h> +#include <postmac.h> +#include "SalAquaConstants.h" +#include "FilterHelper.hxx" +#include "AquaFilePickerDelegate.hxx" + +using namespace com::sun::star; +using namespace rtl; + +class ControlHelper { + +public: + + //------------------------------------------------------------------------------------ + // Constructor / Destructor + //------------------------------------------------------------------------------------ + ControlHelper(); + virtual ~ControlHelper(); + + //------------------------------------------------ + // XInitialization delegate + //------------------------------------------------ + void initialize( sal_Int16 templateId ); + + //------------------------------------------------------------------------------------ + // XFilePickerControlAccess function delegates + //------------------------------------------------------------------------------------ + void setValue( sal_Int16 nControlId, sal_Int16 nControlAction, const uno::Any& rValue ); + uno::Any getValue( sal_Int16 nControlId, sal_Int16 nControlAction ) const; + void enableControl( sal_Int16 nControlId, sal_Bool bEnable ) const; + OUString getLabel( sal_Int16 nControlId ); + void setLabel( sal_Int16 nControlId, const NSString* aLabel ); + + //------------------------------------------------------------------------------------ + // other stuff + //------------------------------------------------------------------------------------ + void updateFilterUI(); + + //------------------------------------------------------------------------------------ + // Type definitions + //------------------------------------------------------------------------------------ + enum ToggleType { + AUTOEXTENSION, //but autoextension is handled differently on MacOSX + PASSWORD, + FILTEROPTIONS, + READONLY, + LINK, + PREVIEW, + SELECTION, + TOGGLE_LAST + }; + + enum ListType { + VERSION, + TEMPLATE, + IMAGE_TEMPLATE, + LIST_LAST + }; + + //------------------------------------------------------------------------------------ + // inline functions + //------------------------------------------------------------------------------------ + inline NSView* getUserPane() { + if (m_bIsUserPaneLaidOut == false) { + createUserPane(); + } + return m_pUserPane; + } + + inline bool getVisibility(ToggleType tToggle) { + return m_bToggleVisibility[tToggle]; + } + + inline void setFilterControlNeeded(bool bNeeded) { + m_bIsFilterControlNeeded = bNeeded; + if (bNeeded == true) { + m_bUserPaneNeeded = true; + } + } + + inline void setFilterHelper(FilterHelper* pFilterHelper) { + m_pFilterHelper = pFilterHelper; + } + + inline void setFilePickerDelegate(AquaFilePickerDelegate* pDelegate) { + m_pDelegate = pDelegate; + } + + inline bool isAutoExtensionEnabled() { + return ([((NSButton*) m_pToggles[AUTOEXTENSION]) state] == NSOnState); + } + +private: + //------------------------------------------------------------------------------------ + // private member variables + //------------------------------------------------------------------------------------ + + /** the native view object */ + NSView* m_pUserPane; + + /** the checkbox controls */ + NSControl* m_pToggles[ TOGGLE_LAST ]; + + /** the visibility flags for the checkboxes */ + bool m_bToggleVisibility[TOGGLE_LAST]; + + /** the special filter control */ + NSPopUpButton *m_pFilterControl; + + /** the popup menu controls (except for the filter control) */ + NSControl* m_pListControls[ LIST_LAST ]; + + /** a map to store a control's label text */ + ::std::map<NSControl *, NSString *> m_aMapListLabels; + + /** a map to store a popup menu's label text field */ + ::std::map<NSPopUpButton *, NSTextField *> m_aMapListLabelFields; + + /** the visibility flags for the popup menus */ + bool m_bListVisibility[ LIST_LAST ]; + + /** indicates if a user pane is needed */ + bool m_bUserPaneNeeded; + + /** indicates if the user pane was laid out already */ + bool m_bIsUserPaneLaidOut; + + /** indicates if a filter control is needed */ + bool m_bIsFilterControlNeeded; + + /** a list with all actively used controls */ + ::std::list<NSControl*> m_aActiveControls; + + /** the filter helper */ + FilterHelper *m_pFilterHelper; + + /** the save or open panel's delegate */ + AquaFilePickerDelegate *m_pDelegate; + + //------------------------------------------------------------------------------------ + // private methods + //------------------------------------------------------------------------------------ + void HandleSetListValue(const NSControl* pControl, const sal_Int16 nControlAction, const uno::Any& rValue); + uno::Any HandleGetListValue(const NSControl* pControl, const sal_Int16 nControlAction) const; + + void createControls(); + void createFilterControl(); + void createUserPane(); + NSTextField* createLabelWithString(const NSString* label); + + int getControlElementName(const Class clazz, const int nControlId) const; + NSControl* getControl( const sal_Int16 nControlId ) const; + static int getVerticalDistance(const NSControl* first, const NSControl* second); + + void layoutControls(); +}; + +#endif //_CONTROLHELPER_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/aqua/FPServiceInfo.hxx b/fpicker/source/aqua/FPServiceInfo.hxx new file mode 100644 index 000000000000..c3cb6b841b44 --- /dev/null +++ b/fpicker/source/aqua/FPServiceInfo.hxx @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FPSERVICEINFO_HXX_ +#define _FPSERVICEINFO_HXX_ + +//------------------------------------------------------------------------ +// defines +//------------------------------------------------------------------------ + +// the service names +#define FILE_PICKER_SERVICE_NAME "com.sun.star.ui.dialogs.AquaFilePicker" +#define FOLDER_PICKER_SERVICE_NAME "com.sun.star.ui.dialogs.AquaFolderPicker" + +// the implementation names +#define FILE_PICKER_IMPL_NAME "com.sun.star.ui.dialogs.SalAquaFilePicker" +#define FOLDER_PICKER_IMPL_NAME "com.sun.star.ui.dialogs.SalAquaFolderPicker" + +// the registry key names +// a key under which this service will be registered, +// Format: -> "/ImplName/UNO/SERVICES/ServiceName" +// <Implementation-Name></UNO/SERVICES/><Service-Name> +#define FILE_PICKER_REGKEY_NAME "/com.sun.star.ui.dialogs.SalAquaFilePicker/UNO/SERVICES/com.sun.star.ui.dialogs.AquaFilePicker" +#define FOLDER_PICKER_REGKEY_NAME "/com.sun.star.ui.dialogs.SalAquaFolderPicker/UNO/SERVICES/com.sun.star.ui.dialogs.AquaFolderPicker" + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/aqua/FPentry.cxx b/fpicker/source/aqua/FPentry.cxx new file mode 100644 index 000000000000..3a264fc61789 --- /dev/null +++ b/fpicker/source/aqua/FPentry.cxx @@ -0,0 +1,158 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <cppuhelper/factory.hxx> +#include <com/sun/star/container/XSet.hpp> + +#include "SalAquaFilePicker.hxx" +#include "SalAquaFolderPicker.hxx" + +#include "FPServiceInfo.hxx" + + +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::registry; +using namespace ::cppu; +using ::com::sun::star::ui::dialogs::XFilePicker; +using ::com::sun::star::ui::dialogs::XFolderPicker; + + +static Reference< XInterface > SAL_CALL createFileInstance( + const Reference< XMultiServiceFactory >& rServiceManager ) +{ + return Reference< XInterface >( + *new SalAquaFilePicker( rServiceManager ) ); +} + +static Reference< XInterface > SAL_CALL createFolderInstance( + const Reference< XMultiServiceFactory >& rServiceManager ) +{ + return Reference< XInterface >( + *new SalAquaFolderPicker( rServiceManager ) ); +} + +//------------------------------------------------ +// the three uno functions that will be exported +//------------------------------------------------ + +extern "C" +{ + +//------------------------------------------------ +// component_getImplementationEnvironment +//------------------------------------------------ + +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +//------------------------------------------------ +// +//------------------------------------------------ + +sal_Bool SAL_CALL component_writeInfo( void* /*pServiceManager*/, void* pRegistryKey ) +{ + sal_Bool bRetVal = sal_True; + + if ( pRegistryKey ) + { + try + { + Reference< XRegistryKey > pXNewKey( static_cast< XRegistryKey* >( pRegistryKey ) ); + pXNewKey->createKey( OUString(RTL_CONSTASCII_USTRINGPARAM( FILE_PICKER_REGKEY_NAME ) )); + pXNewKey->createKey( OUString(RTL_CONSTASCII_USTRINGPARAM( FOLDER_PICKER_REGKEY_NAME ) )); + } + catch( InvalidRegistryException& ) + { + OSL_ENSURE( sal_False, "InvalidRegistryException caught" ); + bRetVal = sal_False; + } + } + + return bRetVal; +} + +//------------------------------------------------ +// +//------------------------------------------------ + +void* SAL_CALL component_getFactory( + const sal_Char* pImplName, uno_Interface* pSrvManager, uno_Interface* /*pRegistryKey*/ ) +{ + void* pRet = 0; + + if( pSrvManager ) + { + // FIXME: PJ: when we do not need native file and folder picker... + if (0) return 0; + + Reference< XSingleServiceFactory > xFactory; + + if (0 == rtl_str_compare(pImplName, FILE_PICKER_IMPL_NAME)) + { + Sequence< OUString > aSNS( 1 ); + aSNS.getArray( )[0] = + OUString(RTL_CONSTASCII_USTRINGPARAM(FILE_PICKER_SERVICE_NAME)); + + xFactory = createSingleFactory( + reinterpret_cast< XMultiServiceFactory* > ( pSrvManager ), + OUString::createFromAscii( pImplName ), + createFileInstance, + aSNS ); + } + else if (0 == rtl_str_compare(pImplName, FOLDER_PICKER_IMPL_NAME)) + { + Sequence< OUString > aSNS( 1 ); + aSNS.getArray( )[0] = + OUString(RTL_CONSTASCII_USTRINGPARAM(FOLDER_PICKER_SERVICE_NAME)); + + xFactory = createSingleFactory( + reinterpret_cast< XMultiServiceFactory* > ( pSrvManager ), + OUString::createFromAscii( pImplName ), + createFolderInstance, + aSNS ); + } + + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + } + + return pRet; +} + +} // extern "C" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/aqua/FilterHelper.cxx b/fpicker/source/aqua/FilterHelper.cxx new file mode 100644 index 000000000000..c0a590977ca3 --- /dev/null +++ b/fpicker/source/aqua/FilterHelper.cxx @@ -0,0 +1,545 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <functional> +#include <algorithm> +#include <osl/mutex.hxx> +#include <vcl/svapp.hxx> + +#include "CFStringUtilities.hxx" +#include "NSString_OOoAdditions.hxx" +#include "NSURL_OOoAdditions.hxx" + +#include "FilterHelper.hxx" + +#pragma mark DEFINES +#define CLASS_NAME "FilterEntry" + +#pragma mark FilterEntry +//--------------------------------------------------------------------- +FilterEntry::FilterEntry( const rtl::OUString& _rTitle, const UnoFilterList& _rSubFilters ) +:m_sTitle( _rTitle ) +,m_aSubFilters( _rSubFilters ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "title", _rTitle); + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +//--------------------------------------------------------------------- +sal_Bool FilterEntry::hasSubFilters() const +{ +// OSL_TRACE(">>> FilterEntry::%s", __func__); + sal_Bool bReturn = ( 0 < m_aSubFilters.getLength() ); +// OSL_TRACE("<<< FilterEntry::%s retVal: %d", __func__, bReturn); + return bReturn; +} + +//--------------------------------------------------------------------- +sal_Int32 FilterEntry::getSubFilters( UnoFilterList& _rSubFilterList ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + _rSubFilterList = m_aSubFilters; + sal_Int32 nReturn = m_aSubFilters.getLength(); + + DBG_PRINT_EXIT(CLASS_NAME, __func__, nReturn); + + return nReturn; +} + +#pragma mark statics +static bool +isFilterString( const rtl::OUString& rFilterString, const char *pMatch ) +{ + sal_Int32 nIndex = 0; + rtl::OUString aToken; + bool bIsFilter = true; + + rtl::OUString aMatch(rtl::OUString::createFromAscii(pMatch)); + + do + { + aToken = rFilterString.getToken( 0, ';', nIndex ); + if( !aToken.match( aMatch ) ) + { + bIsFilter = false; + break; + } + } + while( nIndex >= 0 ); + + return bIsFilter; +} + +//===================================================================== + +static rtl::OUString +shrinkFilterName( const rtl::OUString aFilterName, bool bAllowNoStar = false ) +{ + // DBG_PRINT_ENTRY(CLASS_NAME, "shrinkFilterName", "filterName", aFilterName); + + int i; + int nBracketLen = -1; + int nBracketEnd = -1; + rtl::OUString rFilterName = aFilterName; + const sal_Unicode *pStr = rFilterName; + rtl::OUString aRealName = rFilterName; + + for( i = aRealName.getLength() - 1; i > 0; i-- ) + { + if( pStr[i] == ')' ) + nBracketEnd = i; + else if( pStr[i] == '(' ) + { + nBracketLen = nBracketEnd - i; + if( nBracketEnd <= 0 ) + continue; + if( isFilterString( rFilterName.copy( i + 1, nBracketLen - 1 ), "*." ) ) + aRealName = aRealName.replaceAt( i, nBracketLen + 1, rtl::OUString() ); + else if (bAllowNoStar) + { + if( isFilterString( rFilterName.copy( i + 1, nBracketLen - 1 ), ".") ) + aRealName = aRealName.replaceAt( i, nBracketLen + 1, rtl::OUString() ); + } + } + } + + return aRealName; +} + +//------------------------------------------------------------------------------------ +namespace { + //................................................................................ + struct FilterTitleMatch : public ::std::unary_function< FilterEntry, bool > + { +protected: + const rtl::OUString rTitle; + +public: + FilterTitleMatch( const rtl::OUString _rTitle ) : rTitle( _rTitle ) { } + + //............................................................................ + bool operator () ( const FilterEntry& _rEntry ) + { + sal_Bool bMatch; + if( !_rEntry.hasSubFilters() ) { + //first try the complete filter name + rtl::OUString title = _rEntry.getTitle(); + bMatch = ( title.equals(rTitle) ); + if (!bMatch) { + //we didn't find a match using the full name, let's give it another + //try using the shrunk version + rtl::OUString aShrunkName = shrinkFilterName( _rEntry.getTitle() ).trim(); + bMatch = ( aShrunkName.equals(rTitle) ); + } + } + else + // a filter group -> search the sub filters + bMatch = + _rEntry.endSubFilters() != ::std::find_if( + _rEntry.beginSubFilters(), + _rEntry.endSubFilters(), + *this + ); + + return bMatch ? true : false; + } + + bool operator () ( const UnoFilterEntry& _rEntry ) + { + rtl::OUString aShrunkName = shrinkFilterName( _rEntry.First ); + bool retVal = aShrunkName.equals(rTitle); + return retVal; + } + }; +} + +#undef CLASS_NAME +#define CLASS_NAME "FilterHelper" + +FilterHelper::FilterHelper() +: m_pFilterList(NULL) +, m_pFilterNames(NULL) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +FilterHelper::~FilterHelper() +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + NSAutoreleasePool *pool = [NSAutoreleasePool new]; + + if (NULL != m_pFilterList) { + delete m_pFilterList; + } + + if (NULL != m_pFilterNames) { + //we called retain when we added the strings to the list, so we should release them now + for (NSStringList::iterator iter = m_pFilterNames->begin(); iter != m_pFilterNames->end(); iter++) { + [*iter release]; + } + delete m_pFilterNames; + } + + [pool release]; + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +//------------------------------------------------------------------------------------ +sal_Bool FilterHelper::FilterNameExists( const rtl::OUString rTitle ) +{ + sal_Bool bRet = sal_False; + + if( m_pFilterList ) + bRet = + m_pFilterList->end() != ::std::find_if( + m_pFilterList->begin(), + m_pFilterList->end(), + FilterTitleMatch( rTitle ) + ); + + return bRet; +} + +//------------------------------------------------------------------------------------ +sal_Bool FilterHelper::FilterNameExists( const UnoFilterList& _rGroupedFilters ) +{ + sal_Bool bRet = sal_False; + + if( m_pFilterList ) + { + const UnoFilterEntry* pStart = _rGroupedFilters.getConstArray(); + const UnoFilterEntry* pEnd = pStart + _rGroupedFilters.getLength(); + for( ; pStart != pEnd; ++pStart ) + if( m_pFilterList->end() != ::std::find_if( + m_pFilterList->begin(), + m_pFilterList->end(), + FilterTitleMatch( pStart->First ) ) ) + break; + + bRet = (pStart != pEnd); + } + + return bRet; +} + +//------------------------------------------------------------------------------------ +void FilterHelper::ensureFilterList( const ::rtl::OUString& _rInitialCurrentFilter ) +{ + //OSL_TRACE(">>> FilterHelper::%s", __func__); + if( NULL == m_pFilterList ) + { + m_pFilterList = new FilterList; + + // set the first filter to the current filter + m_aCurrentFilter = _rInitialCurrentFilter; + OSL_TRACE("ensureFilterList filter:%s", OUStringToOString(m_aCurrentFilter, RTL_TEXTENCODING_UTF8).getStr()); + } + //OSL_TRACE("<<< FilterHelper::%s", __func__); +} + +void FilterHelper::SetCurFilter( const rtl::OUString& rFilter ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "filter", rFilter); + + SolarMutexGuard aGuard; + + if(m_aCurrentFilter.equals(rFilter) == false) + { + m_aCurrentFilter = rFilter; + } + + //only for output purposes +#if OSL_DEBUG_LEVEL > 1 + FilterList::iterator aFilter = ::std::find_if(m_pFilterList->begin(), m_pFilterList->end(), FilterTitleMatch(m_aCurrentFilter)); + if (aFilter != m_pFilterList->end()) { + OUStringList suffixes = aFilter->getFilterSuffixList(); + if (!suffixes.empty()) { + OSL_TRACE("Current active suffixes: "); + OUStringList::iterator suffIter = suffixes.begin(); + while(suffIter != suffixes.end()) { + OSL_TRACE("%s", OUStringToOString((*suffIter), RTL_TEXTENCODING_UTF8).getStr()); + suffIter++; + } + } + } else { + OSL_TRACE("No filter entry was found for that name!"); + } +#endif + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +void FilterHelper::SetFilters() +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + // set the default filter + if( m_aCurrentFilter.getLength() > 0 ) + { + OSL_TRACE( "Setting current filter to %s", OUStringToOString(m_aCurrentFilter, RTL_TEXTENCODING_UTF8).getStr()); + + SetCurFilter( m_aCurrentFilter ); + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +void FilterHelper::appendFilter(const ::rtl::OUString& aTitle, const ::rtl::OUString& aFilterString) +throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ) { + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "title", aTitle, "filter", aFilterString); + + SolarMutexGuard aGuard; + + if( FilterNameExists( aTitle ) ) { + throw com::sun::star::lang::IllegalArgumentException(); + } + + // ensure that we have a filter list + ensureFilterList( aTitle ); + + // append the filter + OUStringList suffixList; + fillSuffixList(suffixList, aFilterString); + m_pFilterList->push_back(FilterEntry( aTitle, suffixList ) ); + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +void FilterHelper::setCurrentFilter( const ::rtl::OUString& aTitle ) +throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ) { + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "aTitle", OUStringToOString(aTitle, RTL_TEXTENCODING_UTF8).getStr()); + + SetCurFilter(aTitle); + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +::rtl::OUString SAL_CALL FilterHelper::getCurrentFilter( ) +throw( ::com::sun::star::uno::RuntimeException ) { + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + ::rtl::OUString sReturn = (m_aCurrentFilter); + + DBG_PRINT_EXIT(CLASS_NAME, __func__, OUStringToOString(sReturn, RTL_TEXTENCODING_UTF8).getStr()); + + return sReturn; +} + +void SAL_CALL FilterHelper::appendFilterGroup( const ::rtl::OUString& sGroupTitle, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::StringPair >& aFilters ) +throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) { + + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "title", OUStringToOString(sGroupTitle, RTL_TEXTENCODING_UTF8).getStr()); + + SolarMutexGuard aGuard; + + //add a separator if this is not the first group to be added + sal_Bool bPrependSeparator = m_pFilterList != NULL; + + // ensure that we have a filter list + ::rtl::OUString sInitialCurrentFilter; + if( aFilters.getLength() > 0) + sInitialCurrentFilter = aFilters[0].First; + ensureFilterList( sInitialCurrentFilter ); + + // append the filter + if (bPrependSeparator) { + rtl::OUString dash(RTL_CONSTASCII_USTRINGPARAM("-")); + OUStringList emptyList; + m_pFilterList->push_back(FilterEntry(dash, emptyList)); + } + + const com::sun::star::beans::StringPair* pSubFilters = aFilters.getConstArray(); + const com::sun::star::beans::StringPair* pSubFiltersEnd = pSubFilters + aFilters.getLength(); + for( ; pSubFilters != pSubFiltersEnd; ++pSubFilters ) { + appendFilter(pSubFilters->First, pSubFilters->Second); + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +sal_Bool FilterHelper::filenameMatchesFilter(NSString* sFilename) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + if (m_aCurrentFilter == NULL) { + OSL_TRACE("filter name is null"); + return sal_True; + } + + NSFileManager *manager = [NSFileManager defaultManager]; + NSDictionary* pAttribs = [manager fileAttributesAtPath: sFilename traverseLink: NO]; + if( pAttribs ) + { + NSObject* pType = [pAttribs objectForKey: NSFileType]; + if( pType && [pType isKindOfClass: [NSString class]] ) + { + NSString* pT = (NSString*)pType; + if( [pT isEqualToString: NSFileTypeDirectory] || + [pT isEqualToString: NSFileTypeSymbolicLink] ) + return sal_True; + } + } + + FilterList::iterator filter = ::std::find_if(m_pFilterList->begin(), m_pFilterList->end(), FilterTitleMatch(m_aCurrentFilter)); + if (filter == m_pFilterList->end()) { + OSL_TRACE("filter not found in list"); + return sal_True; + } + + OUStringList suffixList = filter->getFilterSuffixList(); + + { + rtl::OUString aName = [sFilename OUString]; + rtl::OUString allMatcher(RTL_CONSTASCII_USTRINGPARAM(".*")); + for(OUStringList::iterator iter = suffixList.begin(); iter != suffixList.end(); iter++) { + if (aName.matchIgnoreAsciiCase(*iter, aName.getLength() - (*iter).getLength()) || ((*iter).equals(allMatcher))) { + return sal_True; + } + } + } + + // might be an alias + NSString* pResolved = resolveAlias( sFilename ); + if( pResolved ) + { + sal_Bool bResult = filenameMatchesFilter( pResolved ); + [pResolved autorelease]; + if( bResult ) + return sal_True; + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__); + + return sal_False; +} + +FilterList* FilterHelper::getFilterList() { + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + DBG_PRINT_EXIT(CLASS_NAME, __func__); + + return m_pFilterList; +} + +NSStringList* FilterHelper::getFilterNames() { + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + if (NULL == m_pFilterList) + return NULL; + if (NULL == m_pFilterNames) { + //build filter names list + m_pFilterNames = new NSStringList; + for (FilterList::iterator iter = m_pFilterList->begin(); iter != m_pFilterList->end(); iter++) { + m_pFilterNames->push_back([[NSString stringWithOUString:iter->getTitle()] retain]); + } + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__); + + return m_pFilterNames; +} + +void FilterHelper::SetFilterAtIndex(unsigned index) { + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "index", index); + + if (m_pFilterList->size() <= index) { + index = 0; + } + FilterEntry entry = m_pFilterList->at(index); + SetCurFilter(entry.getTitle()); + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +void FilterHelper::fillSuffixList(OUStringList& aSuffixList, const ::rtl::OUString& suffixString) { + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "aSuffixList", suffixString); + + sal_Int32 nIndex = 0; + do { + rtl::OUString aToken = suffixString.getToken( 0, ';', nIndex ); + aSuffixList.push_back(aToken.copy(1)); + } while ( nIndex >= 0 ); + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +int FilterHelper::getCurrentFilterIndex() { + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + int result = 0;//default to first filter + if (m_aCurrentFilter.getLength() > 0) { + int i = 0; + for (FilterList::iterator iter = m_pFilterList->begin(); iter != m_pFilterList->end(); iter++, i++) { + rtl::OUString aTitle = iter->getTitle(); + if (m_aCurrentFilter.equals(aTitle)) { + result = i; + break; + } else { + aTitle = shrinkFilterName(aTitle).trim(); + if (m_aCurrentFilter.equals(aTitle)) { + result = i; + break; + } + } + } + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__, result); + + return result; +} + +OUStringList FilterHelper::getCurrentFilterSuffixList() { + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + OUStringList retVal; + if (m_aCurrentFilter.getLength() > 0) { + for (FilterList::iterator iter = m_pFilterList->begin(); iter != m_pFilterList->end(); iter++) { + rtl::OUString aTitle = iter->getTitle(); + if (m_aCurrentFilter.equals(aTitle)) { + retVal = iter->getFilterSuffixList(); + break; + } else { + aTitle = shrinkFilterName(aTitle).trim(); + if (m_aCurrentFilter.equals(aTitle)) { + retVal = iter->getFilterSuffixList(); + break; + } + } + } + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__); + + return retVal; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/aqua/FilterHelper.hxx b/fpicker/source/aqua/FilterHelper.hxx new file mode 100644 index 000000000000..8e8bcc4b6cf7 --- /dev/null +++ b/fpicker/source/aqua/FilterHelper.hxx @@ -0,0 +1,139 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FILTERHELPER_HXX_ +#define _FILTERHELPER_HXX_ + +#include <com/sun/star/beans/StringPair.hpp> +#include <com/sun/star/uno/Sequence.hxx> + +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +#include <com/sun/star/uno/RuntimeException.hpp> + +#include <list> +#include <vector> + +#include <premac.h> +#include <Cocoa/Cocoa.h> +#include <postmac.h> + +typedef ::com::sun::star::beans::StringPair UnoFilterEntry; +typedef ::com::sun::star::uno::Sequence< UnoFilterEntry > UnoFilterList; // can be transported more effectively +typedef ::std::list<NSString *> NSStringList; +typedef ::std::list<rtl::OUString> OUStringList; + +struct FilterEntry +{ +protected: + rtl::OUString m_sTitle; + OUStringList m_sFilterSuffixList; + UnoFilterList m_aSubFilters; + +public: + FilterEntry( const rtl::OUString& _rTitle, const OUStringList _rFilter ) + : m_sTitle( _rTitle ) + , m_sFilterSuffixList( _rFilter ) + { + } + + FilterEntry( const rtl::OUString& _rTitle, const UnoFilterList& _rSubFilters ); + + rtl::OUString getTitle() const { return m_sTitle; } + OUStringList getFilterSuffixList() const { return m_sFilterSuffixList; } + + /// determines if the filter has sub filter (i.e., the filter is a filter group in real) + sal_Bool hasSubFilters( ) const; + + /** retrieves the filters belonging to the entry + @return + the number of sub filters + */ + sal_Int32 getSubFilters( UnoFilterList& _rSubFilterList ); + + // helpers for iterating the sub filters + const UnoFilterEntry* beginSubFilters() const { return m_aSubFilters.getConstArray(); } + const UnoFilterEntry* endSubFilters() const { return m_aSubFilters.getConstArray() + m_aSubFilters.getLength(); } +}; + +typedef ::std::vector < FilterEntry > FilterList; + +class FilterHelper { + +public: + FilterHelper(); + virtual ~FilterHelper(); + + //XFilterManager delegates + void SAL_CALL appendFilter( const ::rtl::OUString& aTitle, const ::rtl::OUString& aFilter ) + throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + + void SAL_CALL setCurrentFilter( const ::rtl::OUString& aTitle ) + throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + + ::rtl::OUString SAL_CALL getCurrentFilter( ) + throw( ::com::sun::star::uno::RuntimeException ); + + //XFilterGroupManager delegates + void SAL_CALL appendFilterGroup( const ::rtl::OUString& sGroupTitle, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::StringPair >& aFilters ) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + + //accessor + FilterList* getFilterList(); + NSStringList* getFilterNames(); + + //misc + void SetCurFilter( const rtl::OUString& rFilter ); + void SetFilterAtIndex(unsigned index); + OUStringList getCurrentFilterSuffixList(); + int getCurrentFilterIndex(); + void SetFilters(); + sal_Bool filenameMatchesFilter(NSString * sFilename); + +private: + FilterList *m_pFilterList; + rtl::OUString m_aCurrentFilter; + NSStringList *m_pFilterNames; + + int implAddFilter( const rtl::OUString rFilter, const OUStringList rSuffixList); + int implAddFilterGroup( const rtl::OUString rFilter, + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::StringPair>& _rFilters ); + + sal_Bool FilterNameExists( const rtl::OUString rTitle ); + sal_Bool FilterNameExists( const UnoFilterList& _rGroupedFilters ); + + void ensureFilterList( const ::rtl::OUString& _rInitialCurrentFilter ); + + void fillSuffixList(OUStringList& aSuffixList, const ::rtl::OUString& suffixString); + +}; + +#endif //_FILTERHELPER_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/aqua/NSString_OOoAdditions.hxx b/fpicker/source/aqua/NSString_OOoAdditions.hxx new file mode 100644 index 000000000000..65551d15f17e --- /dev/null +++ b/fpicker/source/aqua/NSString_OOoAdditions.hxx @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _NSSTRING_OOOADDITIONS_HXX_ +#define _NSSTRING_OOOADDITIONS_HXX_ + +#include <premac.h> +#import <Cocoa/Cocoa.h> +#include <postmac.h> +#include <rtl/ustring.hxx> + +//for Cocoa types +@interface NSString (OOoAdditions) ++ (id) stringWithOUString:(const rtl::OUString&)ouString; +- (id) initWithOUString:(const rtl::OUString&)ouString; +- (rtl::OUString) OUString; +@end + +#endif // _NSSTRING_OOOADDITIONS_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/aqua/NSString_OOoAdditions.mm b/fpicker/source/aqua/NSString_OOoAdditions.mm new file mode 100644 index 000000000000..6707cff4c847 --- /dev/null +++ b/fpicker/source/aqua/NSString_OOoAdditions.mm @@ -0,0 +1,77 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _CFSTRINGUTILITIES_HXX_ +#include "CFStringUtilities.hxx" +#endif + +#include "NSString_OOoAdditions.hxx" + +#define CLASS_NAME "NSString" + +@implementation NSString (OOoAdditions) + ++ (id) stringWithOUString:(const rtl::OUString&)ouString +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "ouString", ouString); + + NSString *string = [[NSString alloc] initWithOUString:ouString]; + + DBG_PRINT_EXIT(CLASS_NAME, __func__, string); + return [string autorelease]; +} + +- (id) initWithOUString:(const rtl::OUString&)ouString +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "ouString", ouString); + if ((self = [super init])) { + self = [self initWithCharacters:ouString.getStr() length:ouString.getLength()]; + + DBG_PRINT_EXIT(CLASS_NAME, __func__, self); + + return self; + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__, self); + return nil; +} + +- (rtl::OUString) OUString +{ + unsigned int nFileNameLength = [self length]; + + UniChar unichars[nFileNameLength+1]; + + //'close' the string buffer correctly + unichars[nFileNameLength] = '\0'; + + [self getCharacters:unichars]; + + return rtl::OUString(unichars); +} + +@end diff --git a/fpicker/source/aqua/NSURL_OOoAdditions.hxx b/fpicker/source/aqua/NSURL_OOoAdditions.hxx new file mode 100644 index 000000000000..b5ef549ea51b --- /dev/null +++ b/fpicker/source/aqua/NSURL_OOoAdditions.hxx @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _NSURL_OOOADDITIONS_HXX_ +#define _NSURL_OOOADDITIONS_HXX_ + +#include <premac.h> +#include <CoreFoundation/CoreFoundation.h> +#include <postmac.h> +#include "CFStringUtilities.hxx" +#include <rtl/ustring.hxx> + +@interface NSURL (OOoAdditions) +- (rtl::OUString) OUStringForInfo:(InfoType)info; +@end + +/* + returns the resolved string if there was an alias + if there was no alias, nil is returned +*/ + +NSString* resolveAlias( NSString* i_pSystemPath ); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/aqua/NSURL_OOoAdditions.mm b/fpicker/source/aqua/NSURL_OOoAdditions.mm new file mode 100644 index 000000000000..ecc38b7e232b --- /dev/null +++ b/fpicker/source/aqua/NSURL_OOoAdditions.mm @@ -0,0 +1,112 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _NSSTRING_OOOADDITIONS_HXX_ +#include "NSString_OOoAdditions.hxx" +#endif + +#include "NSURL_OOoAdditions.hxx" + +@implementation NSURL (OOoAdditions) +- (rtl::OUString) OUStringForInfo:(InfoType)info +{ + NSAutoreleasePool *pool = [NSAutoreleasePool new]; + + NSString *sURLString = nil; + + switch(info) { + case FULLPATH: + OSL_TRACE("Extracting the full path of an item"); + sURLString = [self absoluteString]; + [sURLString retain]; + break; + case FILENAME: + OSL_TRACE("Extracting the file name of an item"); + NSString *path = [self path]; + if (path == nil) { + sURLString = @""; + } + else { + sURLString = [path lastPathComponent]; + } + [sURLString retain]; + break; + case PATHWITHOUTLASTCOMPONENT: + OSL_TRACE("Extracting the last but one component of an item's path"); + path = [self absoluteString]; + if (path == nil) { + sURLString = @""; + } + else { + NSString* lastComponent = [path lastPathComponent]; + unsigned int lastLength = [lastComponent length]; + sURLString = [path substringToIndex:([path length] - lastLength)]; + } + [sURLString retain]; + break; + default: + break; + } + + rtl::OUString sResult = [sURLString OUString]; + [sURLString release]; + + [pool release]; + + return sResult; +} +@end + +NSString* resolveAlias( NSString* i_pSystemPath ) +{ + NSString* pResolvedPath = nil; + CFURLRef rUrl = CFURLCreateWithFileSystemPath( kCFAllocatorDefault, + (CFStringRef)i_pSystemPath, + kCFURLPOSIXPathStyle, false); + if( rUrl != NULL ) + { + FSRef rFS; + if( CFURLGetFSRef( rUrl, &rFS ) ) + { + MacOSBoolean bIsFolder = false; + MacOSBoolean bAlias = false; + OSErr err = FSResolveAliasFile( &rFS, true, &bIsFolder, &bAlias); + if( (err == noErr) && bAlias ) + { + CFURLRef rResolvedUrl = CFURLCreateFromFSRef( kCFAllocatorDefault, &rFS ); + if( rResolvedUrl != NULL ) + { + pResolvedPath = (NSString*)CFURLCopyFileSystemPath( rResolvedUrl, kCFURLPOSIXPathStyle ); + CFRelease( rResolvedUrl ); + } + } + } + CFRelease( rUrl ); + } + + return pResolvedPath; +} diff --git a/fpicker/source/aqua/SalAquaConstants.h b/fpicker/source/aqua/SalAquaConstants.h new file mode 100644 index 000000000000..7a1ecd353abe --- /dev/null +++ b/fpicker/source/aqua/SalAquaConstants.h @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SALAQUACONSTANTS_H_ +#define _SALAQUACONSTANTS_H_ + +#define kAppFourCharCode 'LibO' +#define kControlPropertyTracking 'Trck' +#define kControlPropertyLastPartCode 'LsPc' +#define kControlPropertySubType 'SuTy' +#define kPopupControlPropertyTitleWidth 'PoTW' + +#define kAquaSpaceBetweenControls (8) +#define kAquaSpaceBetweenPopupMenus (10) + +#define kAquaSpaceInsideGroupH (16) +#define kAquaSpaceInsideGroupV (11) + +#define kAquaSpaceBoxFrameViewDiffTop (7) +#define kAquaSpaceBoxFrameViewDiffLeft (7) +#define kAquaSpaceBoxFrameViewDiffBottom (9) +#define kAquaSpaceBoxFrameViewDiffRight (7) + +#define kAquaSpaceButtonFrameBoundsDiff (6) +#define kAquaSpaceSwitchButtonFrameBoundsDiff (2) + +#define kAquaSpacePopupMenuFrameBoundsDiffTop (2) +#define kAquaSpacePopupMenuFrameBoundsDiffBottom (4) +#define kAquaSpacePopupMenuFrameBoundsDiffV (kAquaSpacePopupMenuFrameBoundsDiffTop + kAquaSpacePopupMenuFrameBoundsDiffBottom) +#define kAquaSpacePopupMenuFrameBoundsDiffLeft (3) + +#define kAquaSpaceLabelFrameBoundsDiffH (3) +#define kAquaSpaceLabelPopupDiffV (6) +#define kAquaSpaceAfterPopupButtonsV (20) + +#define kAquaPopupButtonDefaultHeight (26) + +#endif //_SALAQUACONSTANTS_H_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/aqua/SalAquaFilePicker.cxx b/fpicker/source/aqua/SalAquaFilePicker.cxx new file mode 100644 index 000000000000..12846f54caf3 --- /dev/null +++ b/fpicker/source/aqua/SalAquaFilePicker.cxx @@ -0,0 +1,809 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> +#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#include <cppuhelper/interfacecontainer.h> +#include <osl/diagnose.h> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include <com/sun/star/ui/dialogs/ControlActions.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <FPServiceInfo.hxx> +#include <osl/mutex.hxx> +#include <vcl/svapp.hxx> + +#include <tools/urlobj.hxx> +#include "resourceprovider.hxx" + +#include <tools/rc.hxx> +#include <osl/file.hxx> +#include "CFStringUtilities.hxx" +#include "NSString_OOoAdditions.hxx" +#include "NSURL_OOoAdditions.hxx" + +#include <iostream> + +#include "SalAquaFilePicker.hxx" + + +#pragma mark DEFINES + +#define LABEL_TOGGLE( elem ) \ +case elem : \ +aLabel = aResProvider.getResString( CHECKBOX_##elem ); \ + setLabel( CHECKBOX_##elem, aLabel ); \ + break + +#define CLASS_NAME "SalAquaFilePicker" + +//------------------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------------------ + +using namespace ::com::sun::star; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::ui::dialogs::TemplateDescription; +using namespace ::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds; +using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; + +//------------------------------------------------------------------------ +// helper functions +//------------------------------------------------------------------------ + +namespace +{ + // controling event notifications + const bool STARTUP_SUSPENDED = true; + const bool STARTUP_ALIVE = false; + + uno::Sequence<rtl::OUString> SAL_CALL FilePicker_getSupportedServiceNames() + { + uno::Sequence<rtl::OUString> aRet(3); + aRet[0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.FilePicker" )); + aRet[1] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.SystemFilePicker" )); + aRet[2] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.AquaFilePicker" )); + return aRet; + } +} + +#pragma mark Constructor +//----------------------------------------------------------------------------------------- +// constructor +//----------------------------------------------------------------------------------------- + +SalAquaFilePicker::SalAquaFilePicker( const uno::Reference<lang::XMultiServiceFactory>& xServiceMgr ) : +cppu::WeakComponentImplHelper8<XFilterManager, XFilterGroupManager, XFilePickerControlAccess, XFilePickerNotifier, + lang::XInitialization, util::XCancellable, lang::XEventListener, lang::XServiceInfo>( m_rbHelperMtx ) +, m_xServiceMgr( xServiceMgr ) +, m_pFilterHelper( NULL ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + m_pDelegate = [[AquaFilePickerDelegate alloc] initWithFilePicker:this]; + m_pControlHelper->setFilePickerDelegate(m_pDelegate); + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +SalAquaFilePicker::~SalAquaFilePicker() +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + if (NULL != m_pFilterHelper) + delete m_pFilterHelper; + + [m_pDelegate release]; + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + + +#pragma mark XFilePickerNotifier +//------------------------------------------------------------------------------------ +// XFilePickerNotifier +//------------------------------------------------------------------------------------ + +void SAL_CALL SalAquaFilePicker::addFilePickerListener( const uno::Reference<XFilePickerListener>& xListener ) + throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + SolarMutexGuard aGuard; + m_xListener = xListener; + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +void SAL_CALL SalAquaFilePicker::removeFilePickerListener( const uno::Reference<XFilePickerListener>& ) + throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + SolarMutexGuard aGuard; + m_xListener.clear(); + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +#pragma mark XAsynchronousExecutableDialog +//----------------------------------------------------------------------------------------- +// XExecutableDialog functions +//----------------------------------------------------------------------------------------- +void SAL_CALL SalAquaFilePicker::setTitle( const rtl::OUString& aTitle ) throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "title", aTitle); + + SolarMutexGuard aGuard; + implsetTitle(aTitle); + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +sal_Int16 SAL_CALL SalAquaFilePicker::execute() throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + SolarMutexGuard aGuard; + + sal_Int16 retVal = 0; + + implInitialize(); + + // if m_pDialog is nil after initialization, something must have gone wrong before + // or there was no initialization (see issue http://www.openoffice.org/issues/show_bug.cgi?id=100214) + if (m_pDialog == nil) { + m_nDialogType = NAVIGATIONSERVICES_OPEN; + } + + if (m_pFilterHelper) { + m_pFilterHelper->SetFilters(); + } + + if (m_nDialogType == NAVIGATIONSERVICES_SAVE) { + if (m_sSaveFileName.getLength() == 0) { + //if no filename is set, NavigationServices will set the name to "untitled". We don't want this! + //So let's try to get the window title to get the real untitled name + NSWindow *frontWindow = [NSApp keyWindow]; + if (NULL != frontWindow) { + NSString *windowTitle = [frontWindow title]; + if (windowTitle != nil) { + rtl::OUString ouName = [windowTitle OUString]; + //a window title will typically be something like "Untitled1 - OpenOffice.org Writer" + //but we only want the "Untitled1" part of it + sal_Int32 indexOfDash = ouName.indexOf(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" - "))); + if (indexOfDash > -1) { + m_sSaveFileName = ouName.copy(0,indexOfDash); + if (m_sSaveFileName.getLength() > 0) { + setDefaultName(m_sSaveFileName); + } + } else { + OSL_TRACE("no dash present in window title"); + } + } else { + OSL_TRACE("couldn't get window title"); + } + } else { + OSL_TRACE("no front window found"); + } + } + } + + //Set the delegate to be notified of certain events + [m_pDialog setDelegate:m_pDelegate]; + + int nStatus = runandwaitforresult(); + + [m_pDialog setDelegate:nil]; + + switch( nStatus ) + { + case NSOKButton: + OSL_TRACE("The dialog returned OK"); + retVal = ExecutableDialogResults::OK; + break; + + case NSCancelButton: + OSL_TRACE("The dialog was cancelled by the user!"); + retVal = ExecutableDialogResults::CANCEL; + break; + + default: + throw uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("The dialog returned with an unknown result!")), static_cast< XFilePicker* >( this )); + break; + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__, retVal); + + return retVal; +} + + +#pragma mark XFilePicker +//----------------------------------------------------------------------------------------- +// XFilePicker functions +//----------------------------------------------------------------------------------------- + +void SAL_CALL SalAquaFilePicker::setMultiSelectionMode( sal_Bool bMode ) throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "multiSelectable?", bMode); + + SolarMutexGuard aGuard; + + if (m_nDialogType == NAVIGATIONSERVICES_OPEN) { + [(NSOpenPanel*)m_pDialog setAllowsMultipleSelection:YES]; + OSL_TRACE("dialog allows multi-selection? %d", [(NSOpenPanel*)m_pDialog allowsMultipleSelection]); + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +void SAL_CALL SalAquaFilePicker::setDefaultName( const rtl::OUString& aName ) +throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "name", aName); + + SolarMutexGuard aGuard; + + m_sSaveFileName = aName; + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +void SAL_CALL SalAquaFilePicker::setDisplayDirectory( const rtl::OUString& rDirectory ) +throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "directory", rDirectory); + + SolarMutexGuard aGuard; + + implsetDisplayDirectory(rDirectory); + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +rtl::OUString SAL_CALL SalAquaFilePicker::getDisplayDirectory() throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + rtl::OUString retVal = implgetDisplayDirectory(); + + DBG_PRINT_EXIT(CLASS_NAME, __func__, retVal); + return retVal; +} + +uno::Sequence<rtl::OUString> SAL_CALL SalAquaFilePicker::getFiles() throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + SolarMutexGuard aGuard; + + // OSL_TRACE("starting work"); + /* + * If more than one file is selected in an OpenDialog, then the first result + * is the directory and the remaining results contain just the files' names + * without the basedir path. + */ + NSArray *files = nil; + if (m_nDialogType == NAVIGATIONSERVICES_OPEN) { + files = [(NSOpenPanel*)m_pDialog URLs]; + } + else if (m_nDialogType == NAVIGATIONSERVICES_SAVE) { + files = [NSArray arrayWithObjects:[m_pDialog URL], nil]; + } + + long nFiles = [files count]; + OSL_TRACE("# of items: %d", nFiles); + + uno::Sequence< rtl::OUString > aSelectedFiles(nFiles > 1 ? nFiles + 1 : nFiles); + + for(int nIndex = 0; nIndex < nFiles; nIndex += 1) + { + NSURL *url = [files objectAtIndex:nIndex]; + OSL_TRACE("handling %s", [[url description] UTF8String]); + InfoType info = FULLPATH; + if (nFiles > 1) { + //just get the file's name (only in OpenDialog) + info = FILENAME; + } + OUString sFileOrDirURL = [url OUStringForInfo:info]; + + //get the directory information, only on the first file processed + if (nIndex == 0) { + OUString sDirectoryURL = [url OUStringForInfo:PATHWITHOUTLASTCOMPONENT]; + + if (nFiles > 1) { + aSelectedFiles[0] = OUString(sDirectoryURL); + } + } + + short nSequenceIndex = nFiles > 1 ? nIndex + 1 : nIndex; + aSelectedFiles[nSequenceIndex] = sFileOrDirURL; + + OSL_TRACE("Returned file in getFiles: \"%s\".", OUStringToOString(sFileOrDirURL, RTL_TEXTENCODING_UTF8).getStr()); + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__); + return aSelectedFiles; +} + +#pragma mark XFilterManager +//----------------------------------------------------------------------------------------- +// XFilterManager functions +//----------------------------------------------------------------------------------------- + +void SAL_CALL SalAquaFilePicker::appendFilter( const rtl::OUString& aTitle, const rtl::OUString& aFilter ) +throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + SolarMutexGuard aGuard; + + ensureFilterHelper(); + m_pFilterHelper->appendFilter( aTitle, aFilter ); + m_pControlHelper->setFilterControlNeeded(YES); + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +void SAL_CALL SalAquaFilePicker::setCurrentFilter( const rtl::OUString& aTitle ) +throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + OSL_TRACE( "Setting current filter to %s", + OUStringToOString( aTitle, RTL_TEXTENCODING_UTF8 ).getStr() ); + + SolarMutexGuard aGuard; + + ensureFilterHelper(); + m_pFilterHelper->setCurrentFilter(aTitle); + updateFilterUI(); + + updateSaveFileNameExtension(); + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +rtl::OUString SAL_CALL SalAquaFilePicker::getCurrentFilter() throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + SolarMutexGuard aGuard; + + ensureFilterHelper(); + + DBG_PRINT_EXIT(CLASS_NAME, __func__); + return m_pFilterHelper->getCurrentFilter(); +} + +#pragma mark XFilterGroupManager +//----------------------------------------------------------------------------------------- +// XFilterGroupManager functions +//----------------------------------------------------------------------------------------- + +void SAL_CALL SalAquaFilePicker::appendFilterGroup( const rtl::OUString& sGroupTitle, const uno::Sequence<beans::StringPair>& aFilters ) +throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + SolarMutexGuard aGuard; + + ensureFilterHelper(); + m_pFilterHelper->appendFilterGroup(sGroupTitle, aFilters); + m_pControlHelper->setFilterControlNeeded(YES); + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +#pragma mark XFilePickerControlAccess +//------------------------------------------------------------------------------------ +// XFilePickerControlAccess functions +//------------------------------------------------------------------------------------ + +void SAL_CALL SalAquaFilePicker::setValue( sal_Int16 nControlId, sal_Int16 nControlAction, const uno::Any& rValue ) +throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + SolarMutexGuard aGuard; + + m_pControlHelper->setValue(nControlId, nControlAction, rValue); + + if (nControlId == ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION && m_nDialogType == NAVIGATIONSERVICES_SAVE) { + updateSaveFileNameExtension(); + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +uno::Any SAL_CALL SalAquaFilePicker::getValue( sal_Int16 nControlId, sal_Int16 nControlAction ) +throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + uno::Any aValue = m_pControlHelper->getValue(nControlId, nControlAction); + + DBG_PRINT_EXIT(CLASS_NAME, __func__); + return aValue; +} + +void SAL_CALL SalAquaFilePicker::enableControl( sal_Int16 nControlId, sal_Bool bEnable ) +throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + m_pControlHelper->enableControl(nControlId, bEnable); + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +void SAL_CALL SalAquaFilePicker::setLabel( sal_Int16 nControlId, const ::rtl::OUString& aLabel ) +throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + SolarMutexGuard aGuard; + + NSString* sLabel = [NSString stringWithOUString:aLabel]; + m_pControlHelper->setLabel( nControlId, sLabel ) ; + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +rtl::OUString SAL_CALL SalAquaFilePicker::getLabel( sal_Int16 nControlId ) +throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + DBG_PRINT_EXIT(CLASS_NAME, __func__); + + return m_pControlHelper->getLabel(nControlId); +} + +#pragma mark XInitialization +//------------------------------------------------------------------------------------ +// XInitialization +//------------------------------------------------------------------------------------ + +void SAL_CALL SalAquaFilePicker::initialize( const uno::Sequence<uno::Any>& aArguments ) +throw( uno::Exception, uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "arguments size", aArguments.getLength()); + + SolarMutexGuard aGuard; + + // parameter checking + uno::Any aAny; + if( 0 == aArguments.getLength() ) + throw lang::IllegalArgumentException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "no arguments" )), + static_cast<XFilePicker*>( this ), 1 ); + + aAny = aArguments[0]; + + if( ( aAny.getValueType() != ::getCppuType( ( sal_Int16* )0 ) ) && + (aAny.getValueType() != ::getCppuType( ( sal_Int8* )0 ) ) ) + throw lang::IllegalArgumentException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "invalid argument type" )), + static_cast<XFilePicker*>( this ), 1 ); + + sal_Int16 templateId = -1; + aAny >>= templateId; + + switch( templateId ) + { + case FILEOPEN_SIMPLE: + m_nDialogType = NAVIGATIONSERVICES_OPEN; + OSL_TRACE( "Template: FILEOPEN_SIMPLE" ); + break; + case FILESAVE_SIMPLE: + m_nDialogType = NAVIGATIONSERVICES_SAVE; + OSL_TRACE( "Template: FILESAVE_SIMPLE" ); + break; + case FILESAVE_AUTOEXTENSION_PASSWORD: + m_nDialogType = NAVIGATIONSERVICES_SAVE; + OSL_TRACE( "Template: FILESAVE_AUTOEXTENSION_PASSWORD" ); + break; + case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS: + m_nDialogType = NAVIGATIONSERVICES_SAVE; + OSL_TRACE( "Template: FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS" ); + break; + case FILESAVE_AUTOEXTENSION_SELECTION: + m_nDialogType = NAVIGATIONSERVICES_SAVE; + OSL_TRACE( "Template: FILESAVE_AUTOEXTENSION_SELECTION" ); + break; + case FILESAVE_AUTOEXTENSION_TEMPLATE: + m_nDialogType = NAVIGATIONSERVICES_SAVE; + OSL_TRACE( "Template: FILESAVE_AUTOEXTENSION_TEMPLATE" ); + break; + case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE: + m_nDialogType = NAVIGATIONSERVICES_OPEN; + OSL_TRACE( "Template: FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE" ); + break; + case FILEOPEN_PLAY: + m_nDialogType = NAVIGATIONSERVICES_OPEN; + OSL_TRACE( "Template: FILEOPEN_PLAY" ); + break; + case FILEOPEN_READONLY_VERSION: + m_nDialogType = NAVIGATIONSERVICES_OPEN; + OSL_TRACE( "Template: FILEOPEN_READONLY_VERSION" ); + break; + case FILEOPEN_LINK_PREVIEW: + m_nDialogType = NAVIGATIONSERVICES_OPEN; + OSL_TRACE( "Template: FILEOPEN_LINK_PREVIEW" ); + break; + case FILESAVE_AUTOEXTENSION: + m_nDialogType = NAVIGATIONSERVICES_SAVE; + OSL_TRACE( "Template: FILESAVE_AUTOEXTENSION" ); + break; + default: + throw lang::IllegalArgumentException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Unknown template" )), + static_cast< XFilePicker* >( this ), + 1 ); + } + + m_pControlHelper->initialize(templateId); + + implInitialize(); + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +#pragma mark XCancellable +//------------------------------------------------------------------------------------ +// XCancellable +//------------------------------------------------------------------------------------ + +void SAL_CALL SalAquaFilePicker::cancel() throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + SolarMutexGuard aGuard; + + if (m_pDialog != nil) { + [m_pDialog cancel:nil]; + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +#pragma mark XEventListener +//------------------------------------------------ +// XEventListener +//------------------------------------------------ + +void SAL_CALL SalAquaFilePicker::disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + SolarMutexGuard aGuard; + + uno::Reference<XFilePickerListener> xFilePickerListener( aEvent.Source, ::com::sun::star::uno::UNO_QUERY ); + + if( xFilePickerListener.is() ) + removeFilePickerListener( xFilePickerListener ); + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +#pragma mark XServiceInfo +// ------------------------------------------------- +// XServiceInfo +// ------------------------------------------------- + +rtl::OUString SAL_CALL SalAquaFilePicker::getImplementationName() +throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + rtl::OUString retVal(RTL_CONSTASCII_USTRINGPARAM( FILE_PICKER_IMPL_NAME )); + + DBG_PRINT_EXIT(CLASS_NAME, __func__, retVal); + + return retVal; +} + +sal_Bool SAL_CALL SalAquaFilePicker::supportsService( const rtl::OUString& sServiceName ) +throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "service name", sServiceName); + + sal_Bool retVal = sal_False; + + uno::Sequence <rtl::OUString> supportedServicesNames = FilePicker_getSupportedServiceNames(); + + for( sal_Int32 n = supportedServicesNames.getLength(); n--; ) { + if( supportedServicesNames[n].compareTo( sServiceName ) == 0) { + retVal = sal_True; + break; + } + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__); + + return retVal; +} + +uno::Sequence<rtl::OUString> SAL_CALL SalAquaFilePicker::getSupportedServiceNames() +throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + DBG_PRINT_EXIT(CLASS_NAME, __func__); + + return FilePicker_getSupportedServiceNames(); +} + +#pragma mark Misc/Private +//----------------------------------------------------------------------------------------- +// FilePicker Event functions +//----------------------------------------------------------------------------------------- + +void SAL_CALL SalAquaFilePicker::fileSelectionChanged( FilePickerEvent aEvent ) +{ + OSL_TRACE( "file selection changed"); + if (m_xListener.is()) + m_xListener->fileSelectionChanged( aEvent ); +} + +void SAL_CALL SalAquaFilePicker::directoryChanged( FilePickerEvent aEvent ) +{ + OSL_TRACE("directory changed"); + if (m_xListener.is()) + m_xListener->directoryChanged( aEvent ); +} + +void SAL_CALL SalAquaFilePicker::controlStateChanged( FilePickerEvent aEvent ) +{ + OSL_TRACE("control state changed"); + if (m_xListener.is()) + m_xListener->controlStateChanged( aEvent ); +} + +void SAL_CALL SalAquaFilePicker::dialogSizeChanged() +{ + OSL_TRACE("dialog size changed"); + if (m_xListener.is()) + m_xListener->dialogSizeChanged(); +} + +//------------------------------------------------------------------------------------ + +#define MAP_TOGGLE( elem ) \ +case ExtendedFilePickerElementIds::CHECKBOX_##elem: \ + pWidget = m_pToggles[elem]; \ + break + +#define MAP_BUTTON( elem ) \ +case ExtendedFilePickerElementIds::PUSHBUTTON_##elem: \ + pWidget = m_pButtons[elem]; \ + break +#undef MAP_LIST +#define MAP_LIST( elem ) \ +case ExtendedFilePickerElementIds::LISTBOX_##elem: \ + pWidget = m_pListControls[elem]; if (isAList != NULL) *isAList = sal_True; \ + break + +#define MAP_LIST_LABEL( elem ) \ +case ExtendedFilePickerElementIds::LISTBOX_##elem##_LABEL: \ + pWidget = m_pListControls[elem]; \ + break + +//-------------------------------------------------- +// Misc +//------------------------------------------------- +void SalAquaFilePicker::ensureFilterHelper() { + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + SolarMutexGuard aGuard; + + if (NULL == m_pFilterHelper) { + m_pFilterHelper = new FilterHelper; + m_pControlHelper->setFilterHelper(m_pFilterHelper); + [m_pDelegate setFilterHelper:m_pFilterHelper]; + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +void SalAquaFilePicker::implInitialize() +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + //call super + SalAquaPicker::implInitialize(); + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +void SalAquaFilePicker::updateFilterUI() { + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + m_pControlHelper->updateFilterUI(); + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +void SalAquaFilePicker::updateSaveFileNameExtension() { + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + if (m_nDialogType != NAVIGATIONSERVICES_SAVE) { + return; + } + + // we need to set this here again because initial setting does + //[m_pDialog setExtensionHidden:YES]; + + SolarMutexGuard aGuard; + + if (m_pControlHelper->isAutoExtensionEnabled() == false) { + OSL_TRACE("allowing other file types"); + [m_pDialog setAllowedFileTypes:nil]; + [m_pDialog setAllowsOtherFileTypes:YES]; + } else { + ensureFilterHelper(); + + OUStringList aStringList = m_pFilterHelper->getCurrentFilterSuffixList(); + if( aStringList.empty()) // #i9328# + return; + + rtl::OUString suffix = (*(aStringList.begin())).copy(1); + NSString *requiredFileType = [NSString stringWithOUString:suffix]; + + [m_pDialog setRequiredFileType:requiredFileType]; + + OSL_TRACE("disallowing other file types"); + [m_pDialog setAllowsOtherFileTypes:NO]; + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +void SalAquaFilePicker::filterControlChanged() { + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + if (m_pDialog == nil) { + return; + } + + SolarMutexGuard aGuard; + + updateSaveFileNameExtension(); + + [m_pDialog validateVisibleColumns]; + + FilePickerEvent evt; + evt.ElementId = LISTBOX_FILTER; + controlStateChanged( evt ); + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/aqua/SalAquaFilePicker.hxx b/fpicker/source/aqua/SalAquaFilePicker.hxx new file mode 100644 index 000000000000..a9a7564da2b4 --- /dev/null +++ b/fpicker/source/aqua/SalAquaFilePicker.hxx @@ -0,0 +1,251 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SALAQUAFILEPICKER_HXX_ +#define _SALAQUAFILEPICKER_HXX_ + +//_______________________________________________________________________________________________________________________ +// includes of other projects +//_______________________________________________________________________________________________________________________ + +#include <cppuhelper/compbase8.hxx> +#include <com/sun/star/util/XCancellable.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerNotifier.hpp> +#include <com/sun/star/ui/dialogs/XFilterManager.hpp> +#include <com/sun/star/ui/dialogs/XFilterGroupManager.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp> +#include <com/sun/star/beans/StringPair.hpp> + +#include "SalAquaPicker.hxx" + +#include <memory> +#include <list> + +#include <rtl/ustring.hxx> +#include "FilterHelper.hxx" +#include "AquaFilePickerDelegate.hxx" + +//---------------------------------------------------------- +// Implementation class for the XFilePicker Interface +//---------------------------------------------------------- + +//---------------------------------------------------------- +// forward declarations +//---------------------------------------------------------- + +using namespace rtl; + +//---------------------------------------------------------- +// class declaration +//---------------------------------------------------------- + +class SalAquaFilePicker : + public SalAquaPicker, + public cppu::WeakComponentImplHelper8< + ::com::sun::star::ui::dialogs::XFilterManager, + ::com::sun::star::ui::dialogs::XFilterGroupManager, + ::com::sun::star::ui::dialogs::XFilePickerControlAccess, + ::com::sun::star::ui::dialogs::XFilePickerNotifier, + ::com::sun::star::lang::XInitialization, + ::com::sun::star::util::XCancellable, + ::com::sun::star::lang::XEventListener, + ::com::sun::star::lang::XServiceInfo > +{ +public: + + // constructor + SalAquaFilePicker( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceMgr ); + + //------------------------------------------------------------------------------------ + // XFilePickerNotifier + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL addFilePickerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener >& xListener ) + throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL removeFilePickerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener >& xListener ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XExecutableDialog functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setTitle( const ::rtl::OUString& aTitle ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual sal_Int16 SAL_CALL execute( ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFilePicker functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setMultiSelectionMode( sal_Bool bMode ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setDefaultName( const ::rtl::OUString& aName ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setDisplayDirectory( const ::rtl::OUString& aDirectory ) + throw( com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::uno::RuntimeException ); + + virtual ::rtl::OUString SAL_CALL getDisplayDirectory( ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getFiles( ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFilterManager functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL appendFilter( const ::rtl::OUString& aTitle, const ::rtl::OUString& aFilter ) + throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setCurrentFilter( const ::rtl::OUString& aTitle ) + throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + + virtual ::rtl::OUString SAL_CALL getCurrentFilter( ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFilterGroupManager functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL appendFilterGroup( const ::rtl::OUString& sGroupTitle, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::StringPair >& aFilters ) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + //------------------------------------------------------------------------------------ + // XFilePickerControlAccess functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setValue( sal_Int16 nControlId, sal_Int16 nControlAction, const ::com::sun::star::uno::Any& aValue ) + throw (::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Any SAL_CALL getValue( sal_Int16 aControlId, sal_Int16 aControlAction ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL enableControl( sal_Int16 nControlId, sal_Bool bEnable ) + throw(::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setLabel( sal_Int16 nControlId, const ::rtl::OUString& aLabel ) + throw (::com::sun::star::uno::RuntimeException); + + virtual ::rtl::OUString SAL_CALL getLabel( sal_Int16 nControlId ) + throw (::com::sun::star::uno::RuntimeException); + + //------------------------------------------------ + // XInitialization + //------------------------------------------------ + + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) + throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + //------------------------------------------------ + // XCancellable + //------------------------------------------------ + + virtual void SAL_CALL cancel( ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------ + // XEventListener + //------------------------------------------------ + + using cppu::WeakComponentImplHelperBase::disposing; + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& aEvent ) + throw(::com::sun::star::uno::RuntimeException); + + //------------------------------------------------ + // XServiceInfo + //------------------------------------------------ + + virtual ::rtl::OUString SAL_CALL getImplementationName( ) + throw(::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) + throw(::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) + throw(::com::sun::star::uno::RuntimeException); + + //------------------------------------------------------------------------------------ + // FilePicker Event functions + //------------------------------------------------------------------------------------ + + void SAL_CALL fileSelectionChanged( ::com::sun::star::ui::dialogs::FilePickerEvent aEvent ); + void SAL_CALL directoryChanged( ::com::sun::star::ui::dialogs::FilePickerEvent aEvent ); + // rtl::OUString SAL_CALL helpRequested( ::com::sun::star::ui::dialogs::FilePickerEvent aEvent ) const; + void SAL_CALL controlStateChanged( ::com::sun::star::ui::dialogs::FilePickerEvent aEvent ); + void SAL_CALL dialogSizeChanged( ); + + inline AquaFilePickerDelegate * getDelegate() { + return m_pDelegate; + } + + inline rtl::OUString getSaveFileName() { + return m_sSaveFileName; + } + +private: + // prevent copy and assignment + SalAquaFilePicker( const SalAquaFilePicker& ); + SalAquaFilePicker& operator=( const SalAquaFilePicker& ); + + virtual void ensureFilterHelper(); + + // to instantiate own services + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xServiceMgr; + + ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener > + m_xListener; + + FilterHelper *m_pFilterHelper; + + rtl::OUString m_sSaveFileName; + + AquaFilePickerDelegate *m_pDelegate; + + void updateFilterUI(); + void updateSaveFileNameExtension(); + +public: + + virtual ~SalAquaFilePicker(); + + void filterControlChanged(); + + void implInitialize(); + +}; + +#endif // _SALAQUAFILEPICKER_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/aqua/SalAquaFolderPicker.cxx b/fpicker/source/aqua/SalAquaFolderPicker.cxx new file mode 100644 index 000000000000..7f269ec2b3c4 --- /dev/null +++ b/fpicker/source/aqua/SalAquaFolderPicker.cxx @@ -0,0 +1,290 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#include <cppuhelper/interfacecontainer.h> +#include <osl/diagnose.h> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <FPServiceInfo.hxx> +#include <osl/mutex.hxx> +#include <vcl/svapp.hxx> +#include "SalAquaFolderPicker.hxx" + +#include <tools/urlobj.hxx> +#include <iostream> + +#include "resourceprovider.hxx" + +#include <tools/rc.hxx> + +#include <osl/file.hxx> +#include "CFStringUtilities.hxx" +#include "NSString_OOoAdditions.hxx" +#include "NSURL_OOoAdditions.hxx" + +#pragma mark DEFINES +#define CLASS_NAME "SalAquaFolderPicker" + +//------------------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------------------ + +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; + +//------------------------------------------------------------------------ +// helper functions +//------------------------------------------------------------------------ + +namespace +{ + // controling event notifications + uno::Sequence<rtl::OUString> SAL_CALL FolderPicker_getSupportedServiceNames() + { + uno::Sequence<rtl::OUString> aRet(2); + aRet[0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.SystemFolderPicker" )); + aRet[1] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.AquaFolderPicker" )); + return aRet; + } +} + +//----------------------------------------------------------------------------------------- +// constructor +//----------------------------------------------------------------------------------------- +SalAquaFolderPicker::SalAquaFolderPicker( const uno::Reference<lang::XMultiServiceFactory>& xServiceMgr ) : + m_xServiceMgr( xServiceMgr ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + m_nDialogType = NAVIGATIONSERVICES_DIRECTORY; + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +//----------------------------------------------------------------------------------------- +// XExecutableDialog functions +//----------------------------------------------------------------------------------------- + +void SAL_CALL SalAquaFolderPicker::setTitle( const rtl::OUString& aTitle ) throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "title", aTitle); + + SolarMutexGuard aGuard; + + implsetTitle(aTitle); + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +sal_Int16 SAL_CALL SalAquaFolderPicker::execute() throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + SolarMutexGuard aGuard; + + sal_Int16 retVal = 0; + + int nResult = runandwaitforresult(); + + switch( nResult ) + { + case NSOKButton: + OSL_TRACE("Dialog returned with OK"); + retVal = ExecutableDialogResults::OK; + break; + + case NSCancelButton: + OSL_TRACE("Dialog was cancelled!"); + retVal = ExecutableDialogResults::CANCEL; + break; + + default: + throw uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("The dialog returned with an unknown result!")), static_cast< XFolderPicker* >( this )); + break; + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__); + return retVal; +} + +//------------------------------------------------------------------------------------ +// XFolderPicker functions +//------------------------------------------------------------------------------------ + +void SAL_CALL SalAquaFolderPicker::setDisplayDirectory( const rtl::OUString& aDirectory ) + throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "directory", aDirectory); + + SolarMutexGuard aGuard; + + implsetDisplayDirectory(aDirectory); + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +rtl::OUString SAL_CALL SalAquaFolderPicker::getDisplayDirectory() throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + SolarMutexGuard aGuard; + + OUString aDirectory = implgetDisplayDirectory(); + + DBG_PRINT_EXIT(CLASS_NAME, __func__, aDirectory); + + return aDirectory; +} + +rtl::OUString SAL_CALL SalAquaFolderPicker::getDirectory() throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + SolarMutexGuard aGuard; + + NSArray *files = nil; + if (m_nDialogType == NAVIGATIONSERVICES_DIRECTORY) { + files = [(NSOpenPanel*)m_pDialog URLs]; + } + + long nFiles = [files count]; + OSL_TRACE("# of items: %d", nFiles); + + if (nFiles < 1) { + throw uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("no directory selected")), static_cast< XFolderPicker* >( this )); + } + + rtl::OUString aDirectory; + + NSURL *url = [files objectAtIndex:0]; + OSL_TRACE("handling %s", [[url description] UTF8String]); + + aDirectory = [url OUStringForInfo:FULLPATH]; + + implsetDisplayDirectory(aDirectory); + + OSL_TRACE("dir url: %s", OUStringToOString(aDirectory, RTL_TEXTENCODING_UTF8).getStr()); + + DBG_PRINT_EXIT(CLASS_NAME, __func__); + return aDirectory; +} + +void SAL_CALL SalAquaFolderPicker::setDescription( const rtl::OUString& rDescription ) + throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "description", rDescription); + + [m_pDialog setMessage:[NSString stringWithOUString:rDescription]]; + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +// ------------------------------------------------- +// XServiceInfo +// ------------------------------------------------- + +rtl::OUString SAL_CALL SalAquaFolderPicker::getImplementationName() + throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + rtl::OUString retVal(RTL_CONSTASCII_USTRINGPARAM( FOLDER_PICKER_IMPL_NAME )); + + DBG_PRINT_EXIT(CLASS_NAME, __func__, retVal); + + return retVal; +} + +sal_Bool SAL_CALL SalAquaFolderPicker::supportsService( const rtl::OUString& sServiceName ) + throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "serviceName", sServiceName); + + sal_Bool retVal = sal_False; + uno::Sequence <rtl::OUString> supportedServicesNames = FolderPicker_getSupportedServiceNames(); + + for( sal_Int32 n = supportedServicesNames.getLength(); n--; ) { + if( supportedServicesNames[n].compareTo( sServiceName ) == 0) { + retVal = sal_True; + break; + } + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__, retVal); + return retVal; +} + +uno::Sequence<rtl::OUString> SAL_CALL SalAquaFolderPicker::getSupportedServiceNames() + throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + DBG_PRINT_EXIT(CLASS_NAME, __func__); + + return FolderPicker_getSupportedServiceNames(); +} + +//------------------------------------------------------------------------------------ +// XCancellable +//------------------------------------------------------------------------------------ + +void SAL_CALL SalAquaFolderPicker::cancel() throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + SolarMutexGuard aGuard; + + [m_pDialog cancel:nil]; + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +// ------------------------------------------------- +// XEventListener +// ------------------------------------------------- + +void SAL_CALL SalAquaFolderPicker::disposing( const lang::EventObject& ) + throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/aqua/SalAquaFolderPicker.hxx b/fpicker/source/aqua/SalAquaFolderPicker.hxx new file mode 100644 index 000000000000..8cd643e24029 --- /dev/null +++ b/fpicker/source/aqua/SalAquaFolderPicker.hxx @@ -0,0 +1,133 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SALAQUAFOLDERPICKER_HXX_ +#define _SALAQUAFOLDERPICKER_HXX_ + +//_______________________________________________________________________________________________________________________ +// includes of other projects +//_______________________________________________________________________________________________________________________ + +#include <cppuhelper/implbase4.hxx> +#include <com/sun/star/util/XCancellable.hpp> +#include <com/sun/star/lang/XEventListener.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> + +#include <com/sun/star/ui/dialogs/XFolderPicker.hpp> + +#include "SalAquaPicker.hxx" + +#include <memory> + +#include <rtl/ustring.hxx> + +#include <list> + +//---------------------------------------------------------- +// class declaration +//---------------------------------------------------------- + +class SalAquaFolderPicker : + public SalAquaPicker, + public cppu::WeakImplHelper4< + ::com::sun::star::ui::dialogs::XFolderPicker, + ::com::sun::star::lang::XServiceInfo, + ::com::sun::star::lang::XEventListener, + ::com::sun::star::util::XCancellable > +{ +public: + + // constructor + SalAquaFolderPicker( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceMgr ); + + //------------------------------------------------------------------------------------ + // XExecutableDialog functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setTitle( const ::rtl::OUString& aTitle ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual sal_Int16 SAL_CALL execute( ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFolderPicker functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setDisplayDirectory( const rtl::OUString& rDirectory ) + throw( com::sun::star::lang::IllegalArgumentException, com::sun::star::uno::RuntimeException ); + + virtual rtl::OUString SAL_CALL getDisplayDirectory( ) + throw( com::sun::star::uno::RuntimeException ); + + virtual rtl::OUString SAL_CALL getDirectory( ) + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setDescription( const rtl::OUString& rDescription ) + throw( com::sun::star::uno::RuntimeException ); + + //------------------------------------------------ + // XServiceInfo + //------------------------------------------------ + + virtual ::rtl::OUString SAL_CALL getImplementationName( ) + throw(::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) + throw(::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) + throw(::com::sun::star::uno::RuntimeException); + + //------------------------------------------------ + // XCancellable + //------------------------------------------------ + + virtual void SAL_CALL cancel( ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------ + // XEventListener + //------------------------------------------------ + + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& aEvent ) + throw(::com::sun::star::uno::RuntimeException); + +private: + // prevent copy and assignment + SalAquaFolderPicker( const SalAquaFolderPicker& ); + SalAquaFolderPicker& operator=( const SalAquaFolderPicker& ); + + // to instantiate own services + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xServiceMgr; + +}; + +#endif // _SALAQUAFOLDERPICKER_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/aqua/SalAquaPicker.cxx b/fpicker/source/aqua/SalAquaPicker.cxx new file mode 100644 index 000000000000..43962a30d3d5 --- /dev/null +++ b/fpicker/source/aqua/SalAquaPicker.cxx @@ -0,0 +1,265 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <cppuhelper/interfacecontainer.h> +#include <osl/diagnose.h> +#include <com/sun/star/uno/Any.hxx> +#include <FPServiceInfo.hxx> +#include <osl/mutex.hxx> +#include <vcl/svapp.hxx> +#include "SalAquaPicker.hxx" +#include <tools/urlobj.hxx> +#include <osl/file.hxx> +#include "CFStringUtilities.hxx" +#include "NSString_OOoAdditions.hxx" + +#include "NSURL_OOoAdditions.hxx" + +#include "SalAquaFilePicker.hxx" + +#include <stdio.h> + +#pragma mark DEFINES +#define CLASS_NAME "SalAquaPicker" +#define kSetHideExtensionStateKey @"NSNavLastUserSetHideExtensionButtonState" + +//------------------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------------------ + +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; + +// constructor +SalAquaPicker::SalAquaPicker() +: m_pDialog(NULL) +, m_pControlHelper(new ControlHelper()) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +SalAquaPicker::~SalAquaPicker() +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + SolarMutexGuard aGuard; + + NSAutoreleasePool *pool = [NSAutoreleasePool new]; + + if (NULL != m_pControlHelper) + delete m_pControlHelper; + + if (NULL != m_pDialog) + [m_pDialog release]; + + [pool release]; + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +void SAL_CALL SalAquaPicker::implInitialize() +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + SolarMutexGuard aGuard; + + if (m_pDialog != nil) { + return; + } + + switch (m_nDialogType) + { + case NAVIGATIONSERVICES_OPEN: + OSL_TRACE("NAVIGATIONSERVICES_OPEN"); + m_pDialog = [NSOpenPanel openPanel]; + [(NSOpenPanel*)m_pDialog setCanChooseDirectories:NO]; + [(NSOpenPanel*)m_pDialog setCanChooseFiles:YES]; + break; + + case NAVIGATIONSERVICES_SAVE: + OSL_TRACE("NAVIGATIONSERVICES_SAVE"); + m_pDialog = [NSSavePanel savePanel]; + [(NSSavePanel*)m_pDialog setCanSelectHiddenExtension:NO]; //changed for issue #102102 + /* I would have loved to use + * [(NSSavePanel*)m_pDialog setExtensionHidden:YES]; + * here but unfortunately this + * a) only works when the dialog is already displayed because it seems to act on the corresponding checkbox (that we don't show but that doesn't matter) + * b) Mac OS X saves this setting on an application-based level which means that the last state is always being restored again when the app runs for the next time + * + * So the only reliable way seems to be using the NSUserDefaults object because that is where that value is stored and + * to just overwrite it if it has the wrong value. + */ + NSUserDefaults *pDefaults = [NSUserDefaults standardUserDefaults]; + NSNumber *pExtn = [pDefaults objectForKey:kSetHideExtensionStateKey]; + if(pExtn == nil || [pExtn boolValue] == NO) { + OSL_TRACE("Hiding extension"); + [pDefaults setBool:YES forKey:kSetHideExtensionStateKey]; + } + break; + + case NAVIGATIONSERVICES_DIRECTORY: + OSL_TRACE("NAVIGATIONSERVICES_DIRECTORY"); + m_pDialog = [NSOpenPanel openPanel]; + [(NSOpenPanel*)m_pDialog setCanChooseDirectories:YES]; + [(NSOpenPanel*)m_pDialog setCanChooseFiles:NO]; + break; + + default: + OSL_TRACE("m_nDialogType is UNKNOWN: %d", m_nDialogType); + break; + } + + if (m_pDialog == nil) { + OSL_TRACE("An error occurred while creating the dialog!"); + } + else { + [(NSOpenPanel*)m_pDialog setCanCreateDirectories:YES]; + //Retain the dialog instance or it will go away immediately + [m_pDialog retain]; + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +int SalAquaPicker::run() +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + SolarMutexGuard aGuard; + + NSAutoreleasePool *pool = [NSAutoreleasePool new]; + + if (m_pDialog == NULL) { + //this is the case e.g. for the folder picker at this stage + implInitialize(); + } + + NSView *userPane = m_pControlHelper->getUserPane(); + if (userPane != NULL) { + [m_pDialog setAccessoryView:userPane]; + } + + int retVal = 0; + + NSString *startDirectory; + if (m_sDisplayDirectory.getLength() > 0) { + NSString *temp = [NSString stringWithOUString:m_sDisplayDirectory]; + NSURL *url = [NSURL URLWithString:temp]; + startDirectory = [url path]; + + OSL_TRACE("start dir: %s", [startDirectory UTF8String]); + // NSLog(@"%@", startDirectory); + } + else { + startDirectory = NSHomeDirectory(); + } + + switch(m_nDialogType) { + case NAVIGATIONSERVICES_DIRECTORY: + case NAVIGATIONSERVICES_OPEN: + retVal = [(NSOpenPanel*)m_pDialog runModalForDirectory:startDirectory file:nil types:nil]; + break; + case NAVIGATIONSERVICES_SAVE: + retVal = [m_pDialog runModalForDirectory:startDirectory file:[NSString stringWithOUString:((SalAquaFilePicker*)this)->getSaveFileName()]/*[m_pDialog saveFilename]*/]; + break; + // [m_pDialog beginSheetForDirectory:startDirectory file:[m_pDialog saveFilename] modalForWindow:[NSApp keyWindow] modalDelegate:((SalAquaFilePicker*)this)->getDelegate() didEndSelector:@selector(savePanelDidEnd:returnCode:contextInfo:) contextInfo:nil]; + default: + break; + } + + if (retVal == NSFileHandlingPanelOKButton) { + NSString* pDir = [m_pDialog directory]; + if (pDir) { + implsetDisplayDirectory([[NSURL fileURLWithPath:pDir] OUStringForInfo:FULLPATH]); + } + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__, retVal); + + [pool release]; + + return retVal; +} + +int SalAquaPicker::runandwaitforresult() +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + + SolarMutexGuard aGuard; + + int status = this->run(); + + DBG_PRINT_EXIT(CLASS_NAME, __func__, status); + return status; +} + +void SAL_CALL SalAquaPicker::implsetDisplayDirectory( const rtl::OUString& aDirectory ) + throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "directory", aDirectory); + + SolarMutexGuard aGuard; + + if (aDirectory != m_sDisplayDirectory) { + m_sDisplayDirectory = aDirectory; + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +rtl::OUString SAL_CALL SalAquaPicker::implgetDisplayDirectory() throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__); + DBG_PRINT_EXIT(CLASS_NAME, __func__, m_sDisplayDirectory); + + return m_sDisplayDirectory; +} + +void SAL_CALL SalAquaPicker::implsetTitle( const rtl::OUString& aTitle ) throw( uno::RuntimeException ) +{ + DBG_PRINT_ENTRY(CLASS_NAME, __func__, "title", aTitle); + + SolarMutexGuard aGuard; + + if (m_pDialog != nil) { + [m_pDialog setTitle:[NSString stringWithOUString:aTitle]]; + } + + DBG_PRINT_EXIT(CLASS_NAME, __func__); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/aqua/SalAquaPicker.hxx b/fpicker/source/aqua/SalAquaPicker.hxx new file mode 100644 index 000000000000..001dac2d7d92 --- /dev/null +++ b/fpicker/source/aqua/SalAquaPicker.hxx @@ -0,0 +1,103 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SALAQUAFPICKER_HXX_ +#define _SALAQUAFPICKER_HXX_ + +//_____________________________________________________________________________ +// includes of other projects +//_____________________________________________________________________________ + +#include <osl/mutex.hxx> + +#include <rtl/ustring.hxx> + +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +#include <com/sun/star/uno/RuntimeException.hpp> +#include "ControlHelper.hxx" + +#include <premac.h> +#import <Cocoa/Cocoa.h> +#include <postmac.h> + +//---------------------------------------------------------- +// class declaration +//---------------------------------------------------------- + +class SalAquaPicker +{ +public: + // constructor + SalAquaPicker(); + virtual ~SalAquaPicker(); + + int run(); + int runandwaitforresult(); + + inline rtl::OUString getDisplayDirectory() { return m_sDisplayDirectory; } + + inline ControlHelper* getControlHelper() const { + return m_pControlHelper; + } + +protected: + + rtl::OUString m_sDisplayDirectory; + + NSSavePanel *m_pDialog; + + ControlHelper *m_pControlHelper; + + osl::Mutex m_rbHelperMtx; + + // The type of dialog + enum NavigationServices_DialogType { + NAVIGATIONSERVICES_OPEN, + NAVIGATIONSERVICES_SAVE, + NAVIGATIONSERVICES_DIRECTORY + }; + + NavigationServices_DialogType m_nDialogType; + + void implsetTitle( const ::rtl::OUString& aTitle ) + throw( ::com::sun::star::uno::RuntimeException ); + + void implsetDisplayDirectory( const rtl::OUString& rDirectory ) + throw( com::sun::star::lang::IllegalArgumentException, com::sun::star::uno::RuntimeException ); + + rtl::OUString implgetDisplayDirectory( ) + throw( com::sun::star::uno::RuntimeException ); + + void implInitialize( ); + +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/aqua/fps-aqua-ucd.txt b/fpicker/source/aqua/fps-aqua-ucd.txt new file mode 100644 index 000000000000..d71e8f4a574f --- /dev/null +++ b/fpicker/source/aqua/fps-aqua-ucd.txt @@ -0,0 +1,13 @@ +[ComponentDescriptor] +ImplementationName=com.sun.star.ui.dialogs.SalAquaFilePicker +ComponentName=fps_aqua.uno.dylib +LoaderName=com.sun.star.loader.SharedLibrary +[SupportedServices] +com.sun.star.ui.dialogs.AquaFilePicker + +[ComponentDescriptor] +ImplementationName=com.sun.star.ui.dialogs.SalAquaFolderPicker +ComponentName=fps_aqua.uno.dylib +LoaderName=com.sun.star.loader.SharedLibrary +[SupportedServices] +com.sun.star.ui.dialogs.AquaFolderPicker diff --git a/fpicker/source/aqua/fps_aqua.xml b/fpicker/source/aqua/fps_aqua.xml new file mode 100644 index 000000000000..955ad4e32886 --- /dev/null +++ b/fpicker/source/aqua/fps_aqua.xml @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + <module-name>fps</module-name> + <component-description> + <author>Florian Heckl, Pavel JanÃk</author> + <name>com.sun.star.comp.ui.dialogs.FilePicker</name> + <description> + The native Mac OS X (Aqua) implementation of the FilePicker service. + </description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="beta"/> + <supported-service>com.sun.star.ui.dialogs.FilePicker</supported-service> + <service-dependency>...</service-dependency> + <type>com.sun.star.ui.dialogs.XExecutableDialog</type> + <type>com.sun.star.ui.dialogs.XFilePicker</type> + <type>com.sun.star.ui.dialogs.XFilterManager</type> + <type>com.sun.star.ui.dialogs.XFilterGroupManager</type> + <type>com.sun.star.ui.dialogs.XFilePickerListener</type> + <type>com.sun.star.ui.dialogs.ExecutableDialogException</type> + <type>com.sun.star.ui.dialogs.XFilePickerNotifier</type> + <type>com.sun.star.ui.dialogs.XFilePickerControlAccess</type> + <type>com.sun.star.ui.dialogs.ExtendedFilePickerElementIds</type> + <type>com.sun.star.ui.dialogs.ExecutableDialogResults</type> + <type>com.sun.star.ui.dialogs.FilePickerEvent</type> + <type>com.sun.star.ui.dialogs.CommonFilePickerElementIds</type> + <type>com.sun.star.ui.dialogs.ListboxControlActions</type> + <type>com.sun.star.ui.dialogs.TemplateDescription</type> + <type>com.sun.star.ui.dialogs.FilePreviewImageFormats</type> + <type>com.sun.star.util.XCancellable</type> + <type>com.sun.star.lang.XComponent</type> + <type>com.sun.star.lang.XMultiServiceFactory</type> + <type>com.sun.star.lang.XSingleServiceFactory</type> + <type>com.sun.star.lang.XServiceInfo</type> + <type>com.sun.star.lang.XTypeProvider</type> + <type>com.sun.star.lang.IllegalArgumentException</type> + <type>com.sun.star.uno.TypeClass</type> + <type>com.sun.star.uno.XWeak</type> + <type>com.sun.star.uno.XAggregation</type> + <type>com.sun.star.registry.XRegistryKey</type> + <type>com.sun.star.container.XSet</type> + </component-description> + <component-description> + <author>Florian Heckl, Pavel JanÃk</author> + <name>com.sun.star.comp.ui.dialogs.FolderPicker</name> + <description> + The native Mac OS X (Aqua) implementation of the FolderPicker service. + </description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="beta"/> + <supported-service>com.sun.star.ui.dialogs.FolderPicker</supported-service> + <service-dependency>...</service-dependency> + <type>com.sun.star.ui.dialogs.XExecutableDialog</type> + <type>com.sun.star.ui.dialogs.XFolderPicker</type> + <type>com.sun.star.ui.dialogs.ExecutableDialogException</type> + <type>com.sun.star.ui.dialogs.ExecutableDialogResults</type> + <type>com.sun.star.util.XCancellable</type> + <type>com.sun.star.lang.XComponent</type> + <type>com.sun.star.lang.XMultiServiceFactory</type> + <type>com.sun.star.lang.XSingleServiceFactory</type> + <type>com.sun.star.lang.XServiceInfo</type> + <type>com.sun.star.lang.XTypeProvider</type> + <type>com.sun.star.lang.IllegalArgumentException</type> + <type>com.sun.star.uno.TypeClass</type> + <type>com.sun.star.uno.XWeak</type> + <type>com.sun.star.uno.XAggregation</type> + <type>com.sun.star.registry.XRegistryKey</type> + <type>com.sun.star.container.XSet</type> + </component-description> + <project-build-dependency>cppuhelper</project-build-dependency> + <project-build-dependency>cppu</project-build-dependency> + <project-build-dependency>sal</project-build-dependency> + <runtime-module-dependency>cppuhelper</runtime-module-dependency> + <runtime-module-dependency>cppu2</runtime-module-dependency> + <runtime-module-dependency>sal2</runtime-module-dependency> +</module-description> diff --git a/fpicker/source/aqua/makefile.mk b/fpicker/source/aqua/makefile.mk new file mode 100644 index 000000000000..10990e22d5e1 --- /dev/null +++ b/fpicker/source/aqua/makefile.mk @@ -0,0 +1,85 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=fpicker +TARGET=fps_aqua.uno +TARGETTYPE=GUI +LIBTARGET=NO +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +DLLPRE= + +# ------------------------------------------------------------------ + +.IF "$(GUIBASE)" != "aqua" + +dummy: + @echo "Nothing to build. GUIBASE == $(GUIBASE)" + +.ELSE # we build for aqua +CFLAGSCXX+=$(OBJCXXFLAGS) + +# --- Files -------------------------------------------------------- + +SLOFILES =\ + $(SLO)$/resourceprovider.obj \ + $(SLO)$/FPentry.obj \ + $(SLO)$/SalAquaPicker.obj \ + $(SLO)$/SalAquaFilePicker.obj \ + $(SLO)$/SalAquaFolderPicker.obj \ + $(SLO)$/CFStringUtilities.obj \ + $(SLO)$/FilterHelper.obj \ + $(SLO)$/ControlHelper.obj \ + $(SLO)$/NSString_OOoAdditions.obj \ + $(SLO)$/NSURL_OOoAdditions.obj \ + $(SLO)$/AquaFilePickerDelegate.obj + +SHL1NOCHECK=TRUE +SHL1TARGET= $(TARGET) +SHL1OBJS= $(SLOFILES) +SHL1STDLIBS=\ + $(VCLLIB) \ + $(TOOLSLIB) \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) + +SHL1VERSIONMAP=$(SOLARENV)/src/component.map +SHL1DEF= $(MISC)$/$(SHL1TARGET).def +DEF1NAME=$(SHL1TARGET) + +.ENDIF # "$(GUIBASE)" != "aqua" + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/fpicker/source/aqua/resourceprovider.cxx b/fpicker/source/aqua/resourceprovider.cxx new file mode 100644 index 000000000000..2d5c4595f886 --- /dev/null +++ b/fpicker/source/aqua/resourceprovider.cxx @@ -0,0 +1,239 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <osl/diagnose.h> +#include <rtl/ustrbuf.hxx> +#include <osl/mutex.hxx> +#include <vcl/svapp.hxx> +#include <tools/resmgr.hxx> +#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> + +#include <svtools/svtools.hrc> + +#include <svtools/filedlg2.hrc> +#include "NSString_OOoAdditions.hxx" + +#include "resourceprovider.hxx" + +//------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------ + +using rtl::OUString; +using namespace ::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds; +using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds; + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +static const char* RES_NAME = "fps_office"; +static const char* OTHER_RES_NAME = "svt"; + +//------------------------------------------------------------ +// we have to translate control ids to resource ids +//------------------------------------------------------------ + +struct _Entry +{ + sal_Int32 ctrlId; + sal_Int16 resId; +}; + +_Entry CtrlIdToResIdTable[] = { + { CHECKBOX_AUTOEXTENSION, STR_SVT_FILEPICKER_AUTO_EXTENSION }, + { CHECKBOX_PASSWORD, STR_SVT_FILEPICKER_PASSWORD }, + { CHECKBOX_FILTEROPTIONS, STR_SVT_FILEPICKER_FILTER_OPTIONS }, + { CHECKBOX_READONLY, STR_SVT_FILEPICKER_READONLY }, + { CHECKBOX_LINK, STR_SVT_FILEPICKER_INSERT_AS_LINK }, + { CHECKBOX_PREVIEW, STR_SVT_FILEPICKER_SHOW_PREVIEW }, + { PUSHBUTTON_PLAY, STR_SVT_FILEPICKER_PLAY }, + { LISTBOX_VERSION_LABEL, STR_SVT_FILEPICKER_VERSION }, + { LISTBOX_TEMPLATE_LABEL, STR_SVT_FILEPICKER_TEMPLATES }, + { LISTBOX_IMAGE_TEMPLATE_LABEL, STR_SVT_FILEPICKER_IMAGE_TEMPLATE }, + { CHECKBOX_SELECTION, STR_SVT_FILEPICKER_SELECTION }, + { FOLDERPICKER_TITLE, STR_SVT_FOLDERPICKER_DEFAULT_TITLE }, + { FOLDER_PICKER_DEF_DESCRIPTION, STR_SVT_FOLDERPICKER_DEFAULT_DESCRIPTION }, + { FILE_PICKER_OVERWRITE, STR_SVT_ALREADYEXISTOVERWRITE }, + { LISTBOX_FILTER_LABEL, STR_SVT_FILEPICKER_FILTER_TITLE} +}; + +_Entry OtherCtrlIdToResIdTable[] = { + { FILE_PICKER_TITLE_OPEN, STR_FILEDLG_OPEN }, + { FILE_PICKER_TITLE_SAVE, STR_FILEDLG_SAVE }, + { FILE_PICKER_FILE_TYPE, STR_FILEDLG_TYPE } +}; + + +const sal_Int32 SIZE_TABLE = sizeof( CtrlIdToResIdTable ) / sizeof( _Entry ); +const sal_Int32 OTHER_SIZE_TABLE = sizeof( OtherCtrlIdToResIdTable ) / sizeof( _Entry ); + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +sal_Int16 CtrlIdToResId( sal_Int32 aControlId ) +{ + sal_Int16 aResId = -1; + + for ( sal_Int32 i = 0; i < SIZE_TABLE; i++ ) + { + if ( CtrlIdToResIdTable[i].ctrlId == aControlId ) + { + aResId = CtrlIdToResIdTable[i].resId; + break; + } + } + + return aResId; +} + +sal_Int16 OtherCtrlIdToResId( sal_Int32 aControlId ) +{ + sal_Int16 aResId = -1; + + for ( sal_Int32 i = 0; i < OTHER_SIZE_TABLE; i++ ) + { + if ( OtherCtrlIdToResIdTable[i].ctrlId == aControlId ) + { + aResId = OtherCtrlIdToResIdTable[i].resId; + break; + } + } + + return aResId; +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +class CResourceProvider_Impl +{ +public: + + //------------------------------------- + // + //------------------------------------- + + CResourceProvider_Impl( ) + { + m_ResMgr = ResMgr::CreateResMgr( RES_NAME ); + m_OtherResMgr = ResMgr::CreateResMgr( OTHER_RES_NAME ); + } + + //------------------------------------- + // + //------------------------------------- + + ~CResourceProvider_Impl( ) + { + delete m_ResMgr; + delete m_OtherResMgr; + } + + //------------------------------------- + // + //------------------------------------- + + NSString* getResString( sal_Int16 aId ) + { + String aResString; + OUString aResOUString; + + const SolarMutexGuard aGuard; + + try + { + OSL_ASSERT( m_ResMgr && m_OtherResMgr ); + + // translate the control id to a resource id + sal_Int16 aResId = CtrlIdToResId( aId ); + if ( aResId > -1 ) + aResString = String( ResId( aResId, *m_ResMgr ) ); + else + { + aResId = OtherCtrlIdToResId( aId ); + if ( aResId > -1 ) { + aResString = String( ResId( aResId, *m_OtherResMgr ) ); + } + } + if ( aResId > -1 ) + aResOUString = OUString( aResString ); + } + catch(...) + { + } + + return [NSString stringWithOUString:aResOUString]; + } + +public: + ResMgr* m_ResMgr; + ResMgr* m_OtherResMgr; +}; + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +CResourceProvider::CResourceProvider( ) : + m_pImpl( new CResourceProvider_Impl() ) +{ +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +CResourceProvider::~CResourceProvider( ) +{ + delete m_pImpl; +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +NSString* CResourceProvider::getResString( sal_Int32 aId ) +{ + NSString* sImmutable = m_pImpl->getResString( aId ); + NSMutableString *sMutableString = [NSMutableString stringWithString:sImmutable]; + [sMutableString replaceOccurrencesOfString:@"~" withString:@"" options:0 range:NSMakeRange(0, [sMutableString length])]; + + NSString *result = [NSString stringWithString:sMutableString]; + + return result; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/aqua/resourceprovider.hxx b/fpicker/source/aqua/resourceprovider.hxx new file mode 100644 index 000000000000..6300def58f07 --- /dev/null +++ b/fpicker/source/aqua/resourceprovider.hxx @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _RESOURCEPROVIDER_HXX_ +#define _RESOURCEPROVIDER_HXX_ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <sal/types.h> + +#include <premac.h> +#include <Cocoa/Cocoa.h> +#include <postmac.h> + +#define FOLDERPICKER_TITLE 500 +#define FOLDER_PICKER_DEF_DESCRIPTION 501 +#define FILE_PICKER_TITLE_OPEN 502 +#define FILE_PICKER_TITLE_SAVE 503 +#define FILE_PICKER_FILE_TYPE 504 +#define FILE_PICKER_OVERWRITE 505 + +//------------------------------------------------------------------------ +// declarations +//------------------------------------------------------------------------ + +class CResourceProvider_Impl; + +class CResourceProvider +{ +public: + CResourceProvider( ); + ~CResourceProvider( ); + + NSString* getResString( sal_Int32 aId ); + +private: + CResourceProvider_Impl* m_pImpl; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/generic/fpicker.cxx b/fpicker/source/generic/fpicker.cxx new file mode 100644 index 000000000000..0f207a3fe57b --- /dev/null +++ b/fpicker/source/generic/fpicker.cxx @@ -0,0 +1,252 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" +#include "sal/types.h" +#include "rtl/ustring.hxx" + +#include "cppuhelper/implementationentry.hxx" +#include "com/sun/star/lang/XMultiComponentFactory.hpp" + +#ifdef WNT +#include <tools/prewin.h> +#include <tools/postwin.h> +#include <odma_lib.hxx> +#endif + +#include "svtools/miscopt.hxx" +#include "svl/pickerhistoryaccess.hxx" + +#include "vcl/svapp.hxx" + +namespace css = com::sun::star; + +using css::uno::Reference; +using css::uno::Sequence; +using rtl::OUString; + +/* + * FilePicker implementation. + */ +static OUString FilePicker_getSystemPickerServiceName() +{ +#ifdef UNX + OUString aDesktopEnvironment (Application::GetDesktopEnvironment()); + if (aDesktopEnvironment.equalsIgnoreAsciiCaseAscii ("gnome")) + return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.GtkFilePicker")); + else if (aDesktopEnvironment.equalsIgnoreAsciiCaseAscii ("kde")) + return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.KDEFilePicker")); + else if (aDesktopEnvironment.equalsIgnoreAsciiCaseAscii ("kde4")) + return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.KDE4FilePicker")); + else if (aDesktopEnvironment.equalsIgnoreAsciiCaseAscii ("macosx")) + return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.AquaFilePicker")); +#endif +#ifdef WNT + if (SvtMiscOptions().TryODMADialog() && ::odma::DMSsAvailable()) { + return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.ODMAFilePicker")); + } + return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.Win32FilePicker")); +#endif + return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.SystemFilePicker")); +} + +static Reference< css::uno::XInterface > FilePicker_createInstance ( + Reference< css::uno::XComponentContext > const & rxContext) +{ + Reference< css::uno::XInterface > xResult; + if (rxContext.is()) + { + Reference< css::lang::XMultiComponentFactory > xFactory (rxContext->getServiceManager()); + if (xFactory.is()) + { + if (SvtMiscOptions().UseSystemFileDialog()) + { + try + { + xResult = xFactory->createInstanceWithContext ( + FilePicker_getSystemPickerServiceName(), + rxContext); + } + catch (css::uno::Exception const &) + { + // Handled below (see @ fallback). + } + } + if (!xResult.is()) + { + // Always fall back to OfficeFilePicker. + xResult = xFactory->createInstanceWithContext ( + OUString (RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.OfficeFilePicker")), + rxContext); + } + if (xResult.is()) + { + // Add to FilePicker history. + svt::addFilePicker (xResult); + } + } + } + return xResult; +} + +static OUString FilePicker_getImplementationName() +{ + return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.comp.fpicker.FilePicker")); +} + +static Sequence< OUString > FilePicker_getSupportedServiceNames() +{ + Sequence< OUString > aServiceNames(1); + aServiceNames.getArray()[0] = + OUString (RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.FilePicker")); + return aServiceNames; +} + +/* + * FolderPicker implementation. + */ +static OUString FolderPicker_getSystemPickerServiceName() +{ + OUString aDesktopEnvironment (Application::GetDesktopEnvironment()); +#ifdef UNX + if (aDesktopEnvironment.equalsIgnoreAsciiCaseAscii ("gnome")) + return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.GtkFolderPicker")); + else if (aDesktopEnvironment.equalsIgnoreAsciiCaseAscii ("kde")) + return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.KDEFolderPicker")); + else if (aDesktopEnvironment.equalsIgnoreAsciiCaseAscii ("macosx")) + return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.AquaFolderPicker")); +#endif +#ifdef WNT + if (SvtMiscOptions().TryODMADialog() && ::odma::DMSsAvailable()) { + return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.ODMAFolderPicker")); + } +#endif + return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.SystemFolderPicker")); +} + +static Reference< css::uno::XInterface > FolderPicker_createInstance ( + Reference< css::uno::XComponentContext > const & rxContext) +{ + Reference< css::uno::XInterface > xResult; + if (rxContext.is()) + { + Reference< css::lang::XMultiComponentFactory > xFactory (rxContext->getServiceManager()); + if (xFactory.is()) + { + if (SvtMiscOptions().UseSystemFileDialog()) + { + try + { + xResult = xFactory->createInstanceWithContext ( + FolderPicker_getSystemPickerServiceName(), + rxContext); + } + catch (css::uno::Exception const &) + { + // Handled below (see @ fallback). + } + } + if (!xResult.is()) + { + // Always fall back to OfficeFolderPicker. + xResult = xFactory->createInstanceWithContext ( + OUString (RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.OfficeFolderPicker")), + rxContext); + } + if (xResult.is()) + { + // Add to FolderPicker history. + svt::addFolderPicker (xResult); + } + } + } + return xResult; +} + +static OUString FolderPicker_getImplementationName() +{ + return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.comp.fpicker.FolderPicker")); +} + +static Sequence< OUString > FolderPicker_getSupportedServiceNames() +{ + Sequence< OUString > aServiceNames(1); + aServiceNames.getArray()[0] = + OUString (RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.FolderPicker")); + return aServiceNames; +} + +/* + * Implementation entries. + */ +static cppu::ImplementationEntry g_entries[] = +{ + { + FilePicker_createInstance, + FilePicker_getImplementationName, + FilePicker_getSupportedServiceNames, + cppu::createSingleComponentFactory, 0, 0 + }, + { + FolderPicker_createInstance, + FolderPicker_getImplementationName, + FolderPicker_getSupportedServiceNames, + cppu::createSingleComponentFactory, 0, 0 + }, + { 0, 0, 0, 0, 0, 0 } +}; + +/* + * Public (exported) interface. + */ +extern "C" +{ +SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment ( + const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL component_writeInfo ( + void * pServiceManager, void * pRegistryKey) +{ + return cppu::component_writeInfoHelper ( + pServiceManager, pRegistryKey, g_entries); +} + +SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory ( + const sal_Char * pImplementationName, void * pServiceManager, void * pRegistryKey) +{ + return cppu::component_getFactoryHelper ( + pImplementationName, pServiceManager, pRegistryKey, g_entries); +} + +} // extern "C" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/generic/makefile.mk b/fpicker/source/generic/makefile.mk new file mode 100644 index 000000000000..f426bd7ad7d1 --- /dev/null +++ b/fpicker/source/generic/makefile.mk @@ -0,0 +1,63 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=fpicker +TARGET=fpicker.uno +LIBTARGET=NO +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +DLLPRE= + +# --- Files -------------------------------------------------------- + +SLOFILES= \ + $(SLO)$/fpicker.obj + +SHL1TARGET= $(TARGET) +SHL1IMPLIB= i$(TARGET) +SHL1OBJS= $(SLOFILES) +SHL1STDLIBS=\ + $(ODMA_LIB_LIB) \ + $(VCLLIB) \ + $(SVLLIB) \ + $(SVTOOLLIB) \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) + +SHL1VERSIONMAP=$(SOLARENV)/src/component.map +SHL1DEF= $(MISC)$/$(SHL1TARGET).def +DEF1NAME= $(SHL1TARGET) + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/fpicker/source/odma/ODMAFilePicker.cxx b/fpicker/source/odma/ODMAFilePicker.cxx new file mode 100644 index 000000000000..685da9f377eb --- /dev/null +++ b/fpicker/source/odma/ODMAFilePicker.cxx @@ -0,0 +1,550 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +#include "ODMAFilePicker.hxx" + +#include <tools/debug.hxx> + +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/StringPair.hpp> +#include <com/sun/star/ui/dialogs/FilePreviewImageFormats.hpp> +#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include <com/sun/star/ucb/XCommandEnvironment.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Sequence.hxx> + +#include <comphelper/sequence.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <ucbhelper/content.hxx> +#include <unotools/ucbhelper.hxx> + +#ifndef ODMA_LIB_HXX +#include <tools/prewin.h> +#include <tools/postwin.h> +#include <odma_lib.hxx> +#endif + +// using ---------------------------------------------------------------- + +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::utl; + +//------------------------------------------------------------------------------------ +// class ODMAFilePicker +//------------------------------------------------------------------------------------ +ODMAFilePicker::ODMAFilePicker( const Reference < XMultiServiceFactory >& xFactory ) : + cppu::WeakComponentImplHelper9< + XFilterManager, + XFilterGroupManager, + XFilePickerControlAccess, + XFilePickerNotifier, + XFilePreview, + XInitialization, + XCancellable, + XEventListener, + XServiceInfo>( m_rbHelperMtx ), + m_bMultiSelectionMode( sal_False ), + m_aDefaultName( ), + m_aFiles( ), + m_nDialogKind( OPEN ) +{ + m_bUseDMS = ::odma::DMSsAvailable(); + m_xSystemFilePicker = xFactory->createInstance( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.Win32FilePicker" ) )); +} + +// XExecutableDialog functions + +void SAL_CALL ODMAFilePicker::setTitle( const ::rtl::OUString& aTitle ) + throw (RuntimeException) +{ + Reference< XExecutableDialog > xExecutableDialog( m_xSystemFilePicker, UNO_QUERY ); + xExecutableDialog->setTitle( aTitle); +} + +inline bool is_current_process_window(HWND hwnd) +{ + DWORD pid; + GetWindowThreadProcessId(hwnd, &pid); + return (pid == GetCurrentProcessId()); +} + +HWND choose_parent_window() +{ + HWND hwnd_parent = GetForegroundWindow(); + if (!is_current_process_window(hwnd_parent)) + hwnd_parent = GetDesktopWindow(); + return hwnd_parent; +} + +sal_Int16 SAL_CALL ODMAFilePicker::execute( ) + throw (RuntimeException) +{ + ODMSTATUS status; + ODMHANDLE handle; + WORD count = 0; + DWORD flags; + + status = NODMRegisterApp( &handle, ODM_API_VERSION, "sodma", (DWORD) choose_parent_window( ), NULL ); + if (status == ODM_SUCCESS) + { + if (m_nDialogKind == OPEN) + { + const int MAXDOCS = 10; + char docids[ODM_DOCID_MAX*MAXDOCS+1]; + WORD docidslen = sizeof( docids ); + + flags = 0; + if (m_bMultiSelectionMode) + count = MAXDOCS; + else + count = 1; + status = NODMSelectDocEx( handle, docids, &docidslen, &count, &flags, NULL ); + if (status == ODM_SUCCESS) + { + // GroupWise doesn't set docidslen or count, so + // calculate number of document IDs manually + char *p = docids; + count = 0; + while (*p) { + count++; + p += strlen( p ) + 1; + } + } + else if (status == ODM_E_NOSUPPORT) + { + status = NODMSelectDoc( handle, docids, &flags ); + if (status == ODM_SUCCESS) + count = 1; + } + NODMUnRegisterApp( handle ); + if (status == ODM_SUCCESS) + { + rtl::OUString *strings = new rtl::OUString[count]; + int i; + char *p = docids; + + for (i = 0; i < count; i++) { + // Insane API... the first element is a full URI, the rest + // are just the "basenames" in the same "directory". + if (i == 0) + strings[0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.odma:/" )) + rtl::OUString::createFromAscii( p ); + else + strings[i] = rtl::OUString::createFromAscii( p ); + p += strlen( p ); + } + + m_aFiles = Sequence< rtl::OUString >( strings, count ); + delete[] strings; + return ExecutableDialogResults::OK; + } + } + else /* m_nDialogKind == SAVE */ + { + char newdocid[ODM_DOCID_MAX+1]; + + if (m_aDefaultName.getLength() == 0 || + !m_aDefaultName.matchIgnoreAsciiCaseAsciiL( "::ODMA\\", 7, 0 )) + { + char tempdocid[ODM_DOCID_MAX+1]; + + status = NODMNewDoc( handle, tempdocid, ODM_SILENT, NULL, NULL ); + if (status == ODM_SUCCESS) + status = NODMSaveAs( handle, tempdocid, newdocid, NULL, NULL, NULL ); + } + else + { + rtl::OString sDefaultName = rtl::OUStringToOString( m_aDefaultName, RTL_TEXTENCODING_ASCII_US ); + status = NODMSaveAs( handle, + const_cast<sal_Char*>( sDefaultName.getStr() ), + newdocid, NULL, NULL, NULL ); + } + + NODMUnRegisterApp( handle ); + if (status == ODM_SUCCESS) + { + rtl::OUString s( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.odma:/" )) + + rtl::OUString::createFromAscii( newdocid ) ); + // Create a Content for the odma URL so that + // odma::ContentProvider will learn about the DOCID we + // just created. + ucbhelper::Content content( s, Reference< XCommandEnvironment >() ); + m_aFiles = Sequence< rtl::OUString >( &s, 1 ); + return ExecutableDialogResults::OK; + } + } + } + if (status == ODM_E_APPSELECT) + { + m_bUseDMS = sal_False; + + Reference< XExecutableDialog > xExecutableDialog( m_xSystemFilePicker, UNO_QUERY ); + return xExecutableDialog->execute(); + } + + // Fallback + return ExecutableDialogResults::CANCEL; +} + +// XFilePicker functions + +void SAL_CALL ODMAFilePicker::setMultiSelectionMode( sal_Bool bMode ) + throw( RuntimeException ) +{ + m_bMultiSelectionMode = bMode; + + Reference< XFilePicker > xFilePicker( m_xSystemFilePicker, UNO_QUERY ); + xFilePicker->setMultiSelectionMode( bMode ); +} + +void SAL_CALL ODMAFilePicker::setDefaultName( const rtl::OUString& aName ) + throw( RuntimeException ) +{ + // When editing a document from DMS, and doing Save As, this is + // called twice, first with the complete DOCID, the second time + // with the "extension" removed. Of course, this is bogus, as + // DOCIDs should be treated as opaque strings, they don't have + // "extensions". + + // In the GroupWise case a DOCID is like + // ::ODMA\GRPWISE\FOO1.BAR.FOO-Bla_bla:12345.12 where the final + // dot separates the version number, not an "extension". + // + // So ignore the second call. + // + // The second call without "extension" is done if the + // XFilePickerControlAccess is set to have auto-extension turned + // on. (See sfx2/source/dialog/filedlghelper.cxx: + // FileDialogHelper_Impl::implInitializeFileName().) Thus we could + // alternatively make sure that a getValue call to get + // ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION returns + // false. But that might be hard as we don't know in advance + // whether the user will click the "use application dialog" + // button. If so, we indeed do use auto-extensions. + // + // Yes, this is ugly, relying on knowing details on how this + // function will be called. + + if ( m_aDefaultName.getLength() == 0 ) + m_aDefaultName = aName; + + Reference< XFilePicker > xFilePicker( m_xSystemFilePicker, UNO_QUERY ); + xFilePicker->setDefaultName( aName ); +} + +void SAL_CALL ODMAFilePicker::setDisplayDirectory( const rtl::OUString& aDirectory ) + throw( IllegalArgumentException, RuntimeException ) +{ + m_aDisplayDirectory = aDirectory; + + Reference< XFilePicker > xFilePicker( m_xSystemFilePicker, UNO_QUERY ); + xFilePicker->setDisplayDirectory( aDirectory ); +} + +rtl::OUString SAL_CALL ODMAFilePicker::getDisplayDirectory( ) + throw( RuntimeException ) +{ + if (m_bUseDMS) + return m_aDisplayDirectory; + + Reference< XFilePicker > xFilePicker( m_xSystemFilePicker, UNO_QUERY ); + return xFilePicker->getDisplayDirectory(); +} + +Sequence< rtl::OUString > SAL_CALL ODMAFilePicker::getFiles( ) + throw( RuntimeException ) +{ + if (m_bUseDMS) + return m_aFiles; + + Reference< XFilePicker > xFilePicker( m_xSystemFilePicker, UNO_QUERY ); + return xFilePicker->getFiles(); +} + +// XFilePickerControlAccess functions + +void SAL_CALL ODMAFilePicker::setValue( sal_Int16 nElementID, + sal_Int16 nControlAction, + const Any& rValue ) + throw( RuntimeException ) +{ + Reference< XFilePickerControlAccess > xFilePickerControlAccess( m_xSystemFilePicker, UNO_QUERY ); + xFilePickerControlAccess->setValue( nElementID, nControlAction, rValue ); +} + +Any SAL_CALL ODMAFilePicker::getValue( sal_Int16 nElementID, sal_Int16 nControlAction ) + throw( RuntimeException ) +{ + Reference< XFilePickerControlAccess > xFilePickerControlAccess( m_xSystemFilePicker, UNO_QUERY ); + return xFilePickerControlAccess->getValue( nElementID, nControlAction ); +} + +void SAL_CALL ODMAFilePicker::setLabel( sal_Int16 nLabelID, const rtl::OUString& rValue ) + throw ( RuntimeException ) +{ + Reference< XFilePickerControlAccess > xFilePickerControlAccess( m_xSystemFilePicker, UNO_QUERY ); + xFilePickerControlAccess->setLabel( nLabelID, rValue ); +} + +rtl::OUString SAL_CALL ODMAFilePicker::getLabel( sal_Int16 nLabelID ) + throw ( RuntimeException ) +{ + Reference< XFilePickerControlAccess > xFilePickerControlAccess( m_xSystemFilePicker, UNO_QUERY ); + return xFilePickerControlAccess->getLabel( nLabelID ); +} + +void SAL_CALL ODMAFilePicker::enableControl( sal_Int16 nElementID, sal_Bool bEnable ) + throw( RuntimeException ) +{ + Reference< XFilePickerControlAccess > xFilePickerControlAccess( m_xSystemFilePicker, UNO_QUERY ); + xFilePickerControlAccess->enableControl( nElementID, bEnable ); +} + +// XFilePickerNotifier functions + +void SAL_CALL ODMAFilePicker::addFilePickerListener( const Reference< XFilePickerListener >& xListener ) + throw ( RuntimeException ) +{ + Reference< XFilePickerNotifier > xFilePickerNotifier( m_xSystemFilePicker, UNO_QUERY ); + xFilePickerNotifier->addFilePickerListener( xListener ); +} + +void SAL_CALL ODMAFilePicker::removeFilePickerListener( const Reference< XFilePickerListener >& xListener ) + throw ( RuntimeException ) +{ + Reference< XFilePickerNotifier > xFilePickerNotifier( m_xSystemFilePicker, UNO_QUERY ); + xFilePickerNotifier->removeFilePickerListener( xListener ); +} + +// XFilePreview functions + +Sequence< sal_Int16 > SAL_CALL ODMAFilePicker::getSupportedImageFormats( ) + throw ( RuntimeException ) +{ + Reference< XFilePreview > xFilePreview( m_xSystemFilePicker, UNO_QUERY ); + return xFilePreview->getSupportedImageFormats(); +} + +sal_Int32 SAL_CALL ODMAFilePicker::getTargetColorDepth( ) + throw ( RuntimeException ) +{ + Reference< XFilePreview > xFilePreview( m_xSystemFilePicker, UNO_QUERY ); + return xFilePreview->getTargetColorDepth(); +} + +sal_Int32 SAL_CALL ODMAFilePicker::getAvailableWidth( ) + throw ( RuntimeException ) +{ + Reference< XFilePreview > xFilePreview( m_xSystemFilePicker, UNO_QUERY ); + return xFilePreview->getAvailableWidth(); +} + +sal_Int32 SAL_CALL ODMAFilePicker::getAvailableHeight( ) + throw ( RuntimeException ) +{ + Reference< XFilePreview > xFilePreview( m_xSystemFilePicker, UNO_QUERY ); + return xFilePreview->getAvailableHeight(); +} + +void SAL_CALL ODMAFilePicker::setImage( sal_Int16 aImageFormat, const Any& rImage ) + throw ( IllegalArgumentException, RuntimeException ) +{ + Reference< XFilePreview > xFilePreview( m_xSystemFilePicker, UNO_QUERY ); + xFilePreview->setImage( aImageFormat, rImage); +} + +sal_Bool SAL_CALL ODMAFilePicker::setShowState( sal_Bool bShowState ) + throw ( RuntimeException ) +{ + Reference< XFilePreview > xFilePreview( m_xSystemFilePicker, UNO_QUERY ); + return xFilePreview->setShowState( bShowState); +} + +sal_Bool SAL_CALL ODMAFilePicker::getShowState( ) + throw ( RuntimeException ) +{ + Reference< XFilePreview > xFilePreview( m_xSystemFilePicker, UNO_QUERY ); + return xFilePreview->getShowState(); +} + +// XFilterGroupManager functions + +void SAL_CALL ODMAFilePicker::appendFilterGroup( const ::rtl::OUString& sGroupTitle, + const Sequence< StringPair >& aFilters ) + throw ( IllegalArgumentException, RuntimeException ) +{ + Reference< XFilterGroupManager > xFilterGroupManager( m_xSystemFilePicker, UNO_QUERY ); + xFilterGroupManager->appendFilterGroup( sGroupTitle, aFilters ); +} + +// XFilterManager functions + +void SAL_CALL ODMAFilePicker::appendFilter( const rtl::OUString& aTitle, + const rtl::OUString& aFilter ) + throw( IllegalArgumentException, RuntimeException ) +{ + Reference< XFilterManager > xFilterManager( m_xSystemFilePicker, UNO_QUERY ); + xFilterManager->appendFilter( aTitle, aFilter ); +} + +void SAL_CALL ODMAFilePicker::setCurrentFilter( const rtl::OUString& aTitle ) + throw( IllegalArgumentException, RuntimeException ) +{ + Reference< XFilterManager > xFilterManager( m_xSystemFilePicker, UNO_QUERY ); + xFilterManager->setCurrentFilter( aTitle ); +} + +rtl::OUString SAL_CALL ODMAFilePicker::getCurrentFilter( ) + throw( RuntimeException ) +{ + Reference< XFilterManager > xFilterManager( m_xSystemFilePicker, UNO_QUERY ); + return xFilterManager->getCurrentFilter(); +} + +// XInitialization functions + +void SAL_CALL ODMAFilePicker::initialize( const Sequence< Any >& aArguments ) + throw ( Exception, RuntimeException ) +{ + if (aArguments.getLength( ) > 0) + { + Any aAny = aArguments[0]; + + if ( (aAny.getValueType() == ::getCppuType((sal_Int16*)0)) || + (aAny.getValueType() == ::getCppuType((sal_Int8*)0)) ) + { + sal_Int16 nTemplateId = -1; + aAny >>= nTemplateId; + + switch (nTemplateId) { + case TemplateDescription::FILEOPEN_SIMPLE: + case TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE: + case TemplateDescription::FILEOPEN_PLAY: + case TemplateDescription::FILEOPEN_READONLY_VERSION: + case TemplateDescription::FILEOPEN_LINK_PREVIEW: + m_nDialogKind = OPEN; + break; + default: + m_nDialogKind = SAVE; + } + } + } + + Reference< XInitialization > xInitialization( m_xSystemFilePicker, UNO_QUERY ); + xInitialization->initialize( aArguments ); +} + +// XCancellable functions + +void SAL_CALL ODMAFilePicker::cancel( ) + throw( ::com::sun::star::uno::RuntimeException ) +{ + Reference< XCancellable > xCancellable( m_xSystemFilePicker, UNO_QUERY ); + xCancellable->cancel(); +} + +// XEventListener functions + +void SAL_CALL ODMAFilePicker::disposing( const ::com::sun::star::lang::EventObject& aEvent ) + throw( RuntimeException ) +{ + Reference< XEventListener > xEventListener( m_xSystemFilePicker, UNO_QUERY ); + xEventListener->disposing( aEvent ); +} + +// XServiceInfo functions + +rtl::OUString SAL_CALL ODMAFilePicker::getImplementationName( ) + throw( RuntimeException ) +{ + return impl_getStaticImplementationName(); +} + +sal_Bool SAL_CALL ODMAFilePicker::supportsService( const rtl::OUString& sServiceName ) + throw( RuntimeException ) +{ + Sequence< rtl::OUString > seqServiceNames = getSupportedServiceNames(); + const rtl::OUString* pArray = seqServiceNames.getConstArray(); + for ( sal_Int32 i = 0; i < seqServiceNames.getLength(); i++ ) + { + if ( sServiceName == pArray[i] ) + { + return sal_True ; + } + } + return sal_False ; +} + +Sequence< rtl::OUString > SAL_CALL ODMAFilePicker::getSupportedServiceNames( ) + throw( RuntimeException ) +{ + return impl_getStaticSupportedServiceNames(); +} + +Sequence< rtl::OUString > ODMAFilePicker::impl_getStaticSupportedServiceNames( ) +{ + Sequence< rtl::OUString > seqServiceNames( 2 ); + rtl::OUString* pArray = seqServiceNames.getArray(); + pArray[0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.ODMAFilePicker" )); + + // Super-ugly, but check the function sal_Bool + // lcl_isSystemFilePicker( const Reference< XFilePicker >& ) in + // sfx2/source/dialog/filedlghelper.cxx + + // Lovely undocumented coupling right across abstraction layers, + // isn't it? If we don't claim to implement this "service" (which + // is not defined in any IDL file, btw), we get hangs. + + pArray[1] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.SystemFilePicker" )); + return seqServiceNames ; +} + +rtl::OUString ODMAFilePicker::impl_getStaticImplementationName( ) +{ + return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.svtools.ODMAFilePicker" )); +} + +Reference< XInterface > SAL_CALL ODMAFilePicker::impl_createInstance( + const Reference< XComponentContext >& rxContext) + throw( Exception ) +{ + Reference< XMultiServiceFactory > xServiceManager (rxContext->getServiceManager(), UNO_QUERY_THROW); + return Reference< XInterface >( *new ODMAFilePicker( xServiceManager ) ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/odma/ODMAFilePicker.hxx b/fpicker/source/odma/ODMAFilePicker.hxx new file mode 100644 index 000000000000..bb389d8cb8cb --- /dev/null +++ b/fpicker/source/odma/ODMAFilePicker.hxx @@ -0,0 +1,216 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_ODMA_FILEPICKER_HXX +#define INCLUDED_ODMA_FILEPICKER_HXX + +#include <cppuhelper/compbase9.hxx> + +#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerNotifier.hpp> +#include <com/sun/star/ui/dialogs/XFilePreview.hpp> +#include <com/sun/star/ui/dialogs/XFilterManager.hpp> +#include <com/sun/star/ui/dialogs/XFilterGroupManager.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerListener.hpp> +#include <com/sun/star/util/XCancellable.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/lang/XInitialization.hpp> + +// class ODMAFilePicker --------------------------------------------------- + +class ODMAFilePicker : + public cppu::WeakComponentImplHelper9< + ::com::sun::star::ui::dialogs::XFilterManager, + ::com::sun::star::ui::dialogs::XFilterGroupManager, + ::com::sun::star::ui::dialogs::XFilePickerControlAccess, + ::com::sun::star::ui::dialogs::XFilePickerNotifier, + ::com::sun::star::ui::dialogs::XFilePreview, + ::com::sun::star::lang::XInitialization, + ::com::sun::star::util::XCancellable, + ::com::sun::star::lang::XEventListener, + ::com::sun::star::lang::XServiceInfo > +{ +private: + sal_Bool m_bUseDMS; + sal_Bool m_bMultiSelectionMode; + rtl::OUString m_aDefaultName; + rtl::OUString m_aDisplayDirectory; + ::com::sun::star::uno::Sequence< rtl::OUString > m_aFiles; + enum { OPEN, SAVE } m_nDialogKind; + + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > m_xSystemFilePicker; + +protected: + ::osl::Mutex m_rbHelperMtx; + +public: + + ODMAFilePicker( const ::com::sun::star::uno::Reference < ::com::sun::star::lang::XMultiServiceFactory >& xFactory ); + + // XFilterManager functions + + virtual void SAL_CALL appendFilter( const ::rtl::OUString& aTitle, + const ::rtl::OUString& aFilter ) + throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setCurrentFilter( const ::rtl::OUString& aTitle ) + throw( ::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::uno::RuntimeException ); + + virtual ::rtl::OUString SAL_CALL getCurrentFilter( ) + throw( ::com::sun::star::uno::RuntimeException ); + + // XFilterGroupManager functions + + virtual void SAL_CALL appendFilterGroup( const ::rtl::OUString& sGroupTitle, + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::StringPair >& aFilters ) + throw (::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::uno::RuntimeException ); + + // XFilePickerControlAccess functions + + virtual void SAL_CALL setValue( sal_Int16 nControlID, + sal_Int16 nControlAction, + const ::com::sun::star::uno::Any& aValue ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual ::com::sun::star::uno::Any SAL_CALL getValue( sal_Int16 nControlID, + sal_Int16 nControlAction ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setLabel( sal_Int16 nControlID, + const ::rtl::OUString& aValue ) + throw ( ::com::sun::star::uno::RuntimeException ); + + virtual ::rtl::OUString SAL_CALL getLabel( sal_Int16 nControlID ) + throw ( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL enableControl( sal_Int16 nControlID, + sal_Bool bEnable ) + throw( ::com::sun::star::uno::RuntimeException ); + + // XFilePicker functions + + virtual void SAL_CALL setMultiSelectionMode( sal_Bool bMode ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setDefaultName( const ::rtl::OUString& aName ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setDisplayDirectory( const ::rtl::OUString& aDirectory ) + throw( ::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::uno::RuntimeException ); + + virtual ::rtl::OUString SAL_CALL getDisplayDirectory( ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getFiles( ) + throw( ::com::sun::star::uno::RuntimeException ); + + // XExecutableDialog functions + + virtual void SAL_CALL setTitle( const ::rtl::OUString& aTitle ) + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Int16 SAL_CALL execute( ) + throw (::com::sun::star::uno::RuntimeException); + + // XFilePickerNotifier functions + + virtual void SAL_CALL addFilePickerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener >& xListener ) + throw ( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL removeFilePickerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener >& xListener ) + throw ( ::com::sun::star::uno::RuntimeException ); + + // XFilePreview functions + + virtual ::com::sun::star::uno::Sequence< sal_Int16 > SAL_CALL getSupportedImageFormats( ) + throw ( ::com::sun::star::uno::RuntimeException ); + + virtual sal_Int32 SAL_CALL getTargetColorDepth( ) + throw ( ::com::sun::star::uno::RuntimeException ); + + virtual sal_Int32 SAL_CALL getAvailableWidth( ) + throw ( ::com::sun::star::uno::RuntimeException ); + + virtual sal_Int32 SAL_CALL getAvailableHeight( ) + throw ( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setImage( sal_Int16 aImageFormat, + const ::com::sun::star::uno::Any& aImage ) + throw ( ::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::uno::RuntimeException ); + + virtual sal_Bool SAL_CALL setShowState( sal_Bool bShowState ) + throw ( ::com::sun::star::uno::RuntimeException ); + + virtual sal_Bool SAL_CALL getShowState( ) + throw ( ::com::sun::star::uno::RuntimeException ); + + // XInitialization functions + + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) + throw ( ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException ); + + // XCancellable functions + + virtual void SAL_CALL cancel( ) + throw( ::com::sun::star::uno::RuntimeException ); + + // XEventListener functions + + using cppu::WeakComponentImplHelperBase::disposing; + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& aEvent ) + throw( ::com::sun::star::uno::RuntimeException ); + + // XServiceInfo functions + + virtual ::rtl::OUString SAL_CALL getImplementationName( ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& sServiceName ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) + throw( ::com::sun::star::uno::RuntimeException ); + + /* Helper for XServiceInfo */ + static ::com::sun::star::uno::Sequence< ::rtl::OUString > impl_getStaticSupportedServiceNames( ); + static ::rtl::OUString impl_getStaticImplementationName( ); + + /* Helper for registry */ + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL impl_createInstance ( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext ) + throw( ::com::sun::star::uno::Exception ); +}; + +#endif // INCLUDED_ODMA_FILEPICKER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/odma/ODMAFolderPicker.cxx b/fpicker/source/odma/ODMAFolderPicker.cxx new file mode 100644 index 000000000000..5c9536ac3290 --- /dev/null +++ b/fpicker/source/odma/ODMAFolderPicker.cxx @@ -0,0 +1,185 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +#include "ODMAFolderPicker.hxx" + +#define _SVSTDARR_STRINGSDTOR +#include "svl/svstdarr.hxx" + +#include <com/sun/star/container/XContentEnumerationAccess.hpp> +#include <com/sun/star/container/XSet.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <cppuhelper/factory.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <unotools/pathoptions.hxx> + +#ifndef ODMA_LIB_HXX +#include <tools/prewin.h> +#include <odma_lib.hxx> +#include <tools/postwin.h> +#endif + +// using ---------------------------------------------------------------- + +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; + +//------------------------------------------------------------------------------------ +// class ODMAFolderPicker +//------------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------------ +ODMAFolderPicker::ODMAFolderPicker( const Reference < XMultiServiceFactory >& xFactory ) : + cppu::WeakComponentImplHelper2< + XFolderPicker, + XServiceInfo>( m_rbHelperMtx ), + m_bUseDMS( sal_False ) +{ + m_xInterface = xFactory->createInstance( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.SystemFolderPicker" ) )); +} + +// XExecutableDialog functions + +void SAL_CALL ODMAFolderPicker::setTitle( const ::rtl::OUString& _rTitle ) throw (RuntimeException) +{ + if (m_bUseDMS) + return; + + Reference< XExecutableDialog > xExecutableDialog( m_xInterface, UNO_QUERY ); + xExecutableDialog->setTitle( _rTitle); +} + +sal_Int16 SAL_CALL ODMAFolderPicker::execute( ) + throw (RuntimeException) +{ + if (m_bUseDMS) + throw new RuntimeException( ); + + Reference< XExecutableDialog > xExecutableDialog( m_xInterface, UNO_QUERY ); + return xExecutableDialog->execute(); +} + +// XFolderPicker functions + +void SAL_CALL ODMAFolderPicker::setDisplayDirectory( const ::rtl::OUString& aDirectory ) + throw( IllegalArgumentException, RuntimeException ) +{ + if (m_bUseDMS) + return; + + Reference< XFolderPicker > xFolderPicker( m_xInterface, UNO_QUERY ); + xFolderPicker->setDisplayDirectory( aDirectory ); +} + +::rtl::OUString SAL_CALL ODMAFolderPicker::getDisplayDirectory( ) + throw( RuntimeException ) +{ + if (m_bUseDMS) + return rtl::OUString(); + + Reference< XFolderPicker > xFolderPicker( m_xInterface, UNO_QUERY ); + return xFolderPicker->getDisplayDirectory(); +} + +::rtl::OUString SAL_CALL ODMAFolderPicker::getDirectory( ) + throw( RuntimeException ) +{ + if (m_bUseDMS) + return rtl::OUString(); + + Reference< XFolderPicker > xFolderPicker( m_xInterface, UNO_QUERY ); + return xFolderPicker->getDirectory(); +} + +void SAL_CALL ODMAFolderPicker::setDescription( const ::rtl::OUString& aDescription ) + throw( RuntimeException ) +{ + if (m_bUseDMS) + return; + + Reference< XFolderPicker > xFolderPicker( m_xInterface, UNO_QUERY ); + xFolderPicker->setDescription( aDescription ); +} + +// XServiceInfo + +::rtl::OUString SAL_CALL ODMAFolderPicker::getImplementationName( ) + throw( RuntimeException ) +{ + return impl_getStaticImplementationName(); +} + +sal_Bool SAL_CALL ODMAFolderPicker::supportsService( const ::rtl::OUString& sServiceName ) + throw( RuntimeException ) +{ + Sequence< ::rtl::OUString > seqServiceNames = getSupportedServiceNames(); + const ::rtl::OUString* pArray = seqServiceNames.getConstArray(); + for ( sal_Int32 i = 0; i < seqServiceNames.getLength(); i++ ) + { + if ( sServiceName == pArray[i] ) + { + return sal_True ; + } + } + return sal_False ; +} + +Sequence< ::rtl::OUString > SAL_CALL ODMAFolderPicker::getSupportedServiceNames() + throw( RuntimeException ) +{ + return impl_getStaticSupportedServiceNames(); +} + +Sequence< ::rtl::OUString > ODMAFolderPicker::impl_getStaticSupportedServiceNames( ) +{ + Sequence< ::rtl::OUString > seqServiceNames( 1 ); + ::rtl::OUString* pArray = seqServiceNames.getArray(); + pArray[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.ODMAFolderPicker" )); + return seqServiceNames ; +} + +::rtl::OUString ODMAFolderPicker::impl_getStaticImplementationName( ) +{ + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.svtools.ODMAFolderPicker" )); +} + +Reference< XInterface > SAL_CALL ODMAFolderPicker::impl_createInstance( const Reference< XComponentContext >& rxContext ) + throw( Exception ) +{ + Reference< XMultiServiceFactory > xServiceManager (rxContext->getServiceManager(), UNO_QUERY_THROW); + return Reference< XInterface >( *new ODMAFolderPicker( xServiceManager ) ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/odma/ODMAFolderPicker.hxx b/fpicker/source/odma/ODMAFolderPicker.hxx new file mode 100644 index 000000000000..880d5a534500 --- /dev/null +++ b/fpicker/source/odma/ODMAFolderPicker.hxx @@ -0,0 +1,103 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_ODMA_FOLDERPICKER_HXX +#define INCLUDED_ODMA_FOLDERPICKER_HXX + +#include <cppuhelper/compbase2.hxx> + +#include <com/sun/star/ui/dialogs/XFolderPicker.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + +// class ODMAFolderPicker --------------------------------------------------- + +class ODMAFolderPicker : + public cppu::WeakComponentImplHelper2< + ::com::sun::star::ui::dialogs::XFolderPicker, + ::com::sun::star::lang::XServiceInfo > +{ +private: + sal_Bool m_bUseDMS; + +protected: + ::osl::Mutex m_rbHelperMtx; + + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > m_xInterface; + +public: + ODMAFolderPicker( const ::com::sun::star::uno::Reference < ::com::sun::star::lang::XMultiServiceFactory >& xFactory ); + + // XFolderPicker functions + + virtual void SAL_CALL setDisplayDirectory( const ::rtl::OUString& aDirectory ) + throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + + virtual ::rtl::OUString SAL_CALL getDisplayDirectory( ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual ::rtl::OUString SAL_CALL getDirectory( ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setDescription( const ::rtl::OUString& aDescription ) + throw ( ::com::sun::star::uno::RuntimeException ); + + // XExecutableDialog functions + + virtual void SAL_CALL setTitle( const ::rtl::OUString& _rTitle ) + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Int16 SAL_CALL execute( ) + throw (::com::sun::star::uno::RuntimeException); + + // XServiceInfo functions + + virtual ::rtl::OUString SAL_CALL getImplementationName( ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& sServiceName ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) + throw( ::com::sun::star::uno::RuntimeException ); + + /* Helper for XServiceInfo */ + static com::sun::star::uno::Sequence< ::rtl::OUString > impl_getStaticSupportedServiceNames( ); + static ::rtl::OUString impl_getStaticImplementationName( ); + + /* Helper for registry */ + static ::com::sun::star::uno::Reference< com::sun::star::uno::XInterface > SAL_CALL impl_createInstance ( const ::com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >& rxContext ) + throw( com::sun::star::uno::Exception ); +}; + +#endif // INCLUDED_ODMA_FOLDERPICKER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/odma/exports.map b/fpicker/source/odma/exports.map new file mode 100644 index 000000000000..f4ed78b9e970 --- /dev/null +++ b/fpicker/source/odma/exports.map @@ -0,0 +1,8 @@ +UDK_3_0_0 { + global: + component_getImplementationEnvironment; + component_writeInfo; + component_getFactory; + local: + *; +}; diff --git a/fpicker/source/odma/fps_odma.cxx b/fpicker/source/odma/fps_odma.cxx new file mode 100644 index 000000000000..6d7642ca0674 --- /dev/null +++ b/fpicker/source/odma/fps_odma.cxx @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +#include "sal/types.h" + +#include "cppuhelper/implementationentry.hxx" + +#include "ODMAFilePicker.hxx" +#include "ODMAFolderPicker.hxx" + +static cppu::ImplementationEntry g_entries[] = +{ + { + ODMAFilePicker::impl_createInstance, + ODMAFilePicker::impl_getStaticImplementationName, + ODMAFilePicker::impl_getStaticSupportedServiceNames, + cppu::createSingleComponentFactory, 0, 0 + }, + { + ODMAFolderPicker::impl_createInstance, + ODMAFolderPicker::impl_getStaticImplementationName, + ODMAFolderPicker::impl_getStaticSupportedServiceNames, + cppu::createSingleComponentFactory, 0, 0 + }, + { 0, 0, 0, 0, 0, 0 } +}; + +extern "C" +{ +SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment ( + const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL component_writeInfo ( + void * pServiceManager, void * pRegistryKey) +{ + return cppu::component_writeInfoHelper ( + pServiceManager, pRegistryKey, g_entries); +} + +SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory ( + const sal_Char * pImplementationName, void * pServiceManager, void * pRegistryKey) +{ + return cppu::component_getFactoryHelper ( + pImplementationName, pServiceManager, pRegistryKey, g_entries); +} + +} // extern "C" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/odma/makefile.mk b/fpicker/source/odma/makefile.mk new file mode 100644 index 000000000000..3cc62d6f94c4 --- /dev/null +++ b/fpicker/source/odma/makefile.mk @@ -0,0 +1,72 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# Copyright 2010 Novell, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=fpicker +TARGET=fps_odma +LIBTARGET=NO +ENABLE_EXCEPTIONS=TRUE +GEN_HID=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +DLLPRE= + +# --- Files -------------------------------------------------------- + +SLOFILES=\ + $(SLO)$/ODMAFilePicker.obj \ + $(SLO)$/ODMAFolderPicker.obj \ + $(SLO)$/fps_odma.obj + +SHL1TARGET= $(TARGET).uno +SHL1IMPLIB= i$(TARGET) +SHL1OBJS= $(SLOFILES) +SHL1STDLIBS=\ + $(ODMA_LIB_LIB) \ + $(SVTOOLLIB) \ + $(TKLIB) \ + $(VCLLIB) \ + $(SVLLIB) \ + $(UNOTOOLSLIB) \ + $(TOOLSLIB) \ + $(UCBHELPERLIB) \ + $(COMPHELPERLIB) \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) + +SHL1VERSIONMAP=exports.map +SHL1DEF= $(MISC)$/$(SHL1TARGET).def +DEF1NAME= $(SHL1TARGET) + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/fpicker/source/office/OfficeControlAccess.cxx b/fpicker/source/office/OfficeControlAccess.cxx new file mode 100644 index 000000000000..f8bec371a898 --- /dev/null +++ b/fpicker/source/office/OfficeControlAccess.cxx @@ -0,0 +1,792 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +#include <sal/macros.h> +#include "OfficeControlAccess.hxx" +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/ControlActions.hpp> +#include <vcl/lstbox.hxx> +#include <com/sun/star/uno/Sequence.hxx> + +#include <algorithm> +#include <functional> + +//......................................................................... +namespace svt +{ +//......................................................................... + + // helper ------------------------------------------------------------- + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::ui::dialogs; + + using namespace ExtendedFilePickerElementIds; + using namespace CommonFilePickerElementIds; + using namespace InternalFilePickerElementIds; + + // -------------------------------------------------------------------- + namespace + { + // ---------------------------------------------------------------- + #define PROPERTY_FLAG_TEXT 0x00000001 + #define PROPERTY_FLAG_ENDBALED 0x00000002 + #define PROPERTY_FLAG_VISIBLE 0x00000004 + #define PROPERTY_FLAG_HELPURL 0x00000008 + #define PROPERTY_FLAG_LISTITEMS 0x00000010 + #define PROPERTY_FLAG_SELECTEDITEM 0x00000020 + #define PROPERTY_FLAG_SELECTEDITEMINDEX 0x00000040 + #define PROPERTY_FLAG_CHECKED 0x00000080 + + // ---------------------------------------------------------------- + // ................................................................ + struct ControlDescription + { + const sal_Char* pControlName; + sal_Int16 nControlId; + sal_Int32 nPropertyFlags; + }; + + // ................................................................ + typedef const ControlDescription* ControlDescIterator; + typedef ::std::pair< ControlDescIterator, ControlDescIterator > ControlDescRange; + + // ...................................................................... + #define PROPERTY_FLAGS_COMMON ( PROPERTY_FLAG_ENDBALED | PROPERTY_FLAG_VISIBLE | PROPERTY_FLAG_HELPURL ) + #define PROPERTY_FLAGS_LISTBOX ( PROPERTY_FLAG_LISTITEMS | PROPERTY_FLAG_SELECTEDITEM | PROPERTY_FLAG_SELECTEDITEMINDEX ) + #define PROPERTY_FLAGS_CHECKBOX ( PROPERTY_FLAG_CHECKED | PROPERTY_FLAG_TEXT ) + + // Note: this array MUST be sorted by name! + static const ControlDescription aDescriptions[] = { + { "AutoExtensionBox", CHECKBOX_AUTOEXTENSION, PROPERTY_FLAGS_COMMON | PROPERTY_FLAGS_CHECKBOX }, + { "CancelButton", PUSHBUTTON_CANCEL, PROPERTY_FLAGS_COMMON | PROPERTY_FLAG_TEXT }, + { "CurrentFolderText", FIXEDTEXT_CURRENTFOLDER, PROPERTY_FLAGS_COMMON | PROPERTY_FLAG_TEXT }, + { "DefaultLocationButton", TOOLBOXBUTOON_DEFAULT_LOCATION, PROPERTY_FLAGS_COMMON }, + { "FileURLEdit", EDIT_FILEURL, PROPERTY_FLAGS_COMMON | PROPERTY_FLAG_TEXT }, + { "FileURLEditLabel", EDIT_FILEURL_LABEL, PROPERTY_FLAGS_COMMON | PROPERTY_FLAG_TEXT }, + { "FileView", CONTROL_FILEVIEW, PROPERTY_FLAGS_COMMON }, + { "FilterList", LISTBOX_FILTER, PROPERTY_FLAGS_COMMON }, + { "FilterListLabel", LISTBOX_FILTER_LABEL, PROPERTY_FLAGS_COMMON | PROPERTY_FLAG_TEXT }, + { "FilterOptionsBox", CHECKBOX_FILTEROPTIONS, PROPERTY_FLAGS_COMMON | PROPERTY_FLAGS_CHECKBOX }, + { "HelpButton", PUSHBUTTON_HELP, PROPERTY_FLAGS_COMMON | PROPERTY_FLAG_TEXT }, + { "ImageTemplateList", LISTBOX_IMAGE_TEMPLATE, PROPERTY_FLAGS_COMMON | PROPERTY_FLAGS_LISTBOX }, + { "ImageTemplateListLabel", LISTBOX_IMAGE_TEMPLATE_LABEL, PROPERTY_FLAGS_COMMON | PROPERTY_FLAG_TEXT }, + { "LevelUpButton", TOOLBOXBUTOON_LEVEL_UP, PROPERTY_FLAGS_COMMON }, + { "LinkBox", CHECKBOX_LINK, PROPERTY_FLAGS_COMMON | PROPERTY_FLAGS_CHECKBOX }, + { "NewFolderButton", TOOLBOXBUTOON_NEW_FOLDER, PROPERTY_FLAGS_COMMON }, + { "OkButton", PUSHBUTTON_OK , PROPERTY_FLAGS_COMMON | PROPERTY_FLAG_TEXT }, + { "PasswordBox", CHECKBOX_PASSWORD, PROPERTY_FLAGS_COMMON | PROPERTY_FLAGS_CHECKBOX }, + { "PlayButton", PUSHBUTTON_PLAY, PROPERTY_FLAGS_COMMON | PROPERTY_FLAG_TEXT }, + { "PreviewBox", CHECKBOX_PREVIEW, PROPERTY_FLAGS_COMMON | PROPERTY_FLAGS_CHECKBOX }, + { "ReadOnlyBox", CHECKBOX_READONLY, PROPERTY_FLAGS_COMMON | PROPERTY_FLAGS_CHECKBOX }, + { "SelectionBox", CHECKBOX_SELECTION, PROPERTY_FLAGS_COMMON | PROPERTY_FLAGS_CHECKBOX }, + { "TemplateList", LISTBOX_TEMPLATE, PROPERTY_FLAGS_COMMON | PROPERTY_FLAGS_LISTBOX }, + { "TemplateListLabel", LISTBOX_TEMPLATE_LABEL, PROPERTY_FLAGS_COMMON | PROPERTY_FLAG_TEXT }, + { "VersionList", LISTBOX_VERSION, PROPERTY_FLAGS_COMMON | PROPERTY_FLAGS_LISTBOX }, + { "VersionListLabel", LISTBOX_VERSION_LABEL, PROPERTY_FLAGS_COMMON | PROPERTY_FLAG_TEXT } + }; + + // ................................................................ + static const sal_Int32 s_nControlCount = SAL_N_ELEMENTS( aDescriptions ); + + static ControlDescIterator s_pControls = aDescriptions; + static ControlDescIterator s_pControlsEnd = aDescriptions + s_nControlCount; + + // ................................................................ + struct ControlDescriptionLookup + { + bool operator()( const ::rtl::OUString& _rLookup, const ControlDescription& _rDesc ) + { + return _rLookup.compareToAscii( _rDesc.pControlName ) < 0; + } + bool operator()( const ControlDescription& _rDesc, const ::rtl::OUString& _rLookup ) + { + return _rLookup.compareToAscii( _rDesc.pControlName ) > 0; + } + }; + + // ................................................................ + struct ExtractControlName : public ::std::unary_function< ControlDescription, ::rtl::OUString > + { + ::rtl::OUString operator()( const ControlDescription& _rDesc ) + { + return ::rtl::OUString::createFromAscii( _rDesc.pControlName ); + } + }; + + // ---------------------------------------------------------------- + // ................................................................ + struct ControlProperty + { + const sal_Char* pPropertyName; + sal_Int16 nPropertyId; + }; + + typedef const ControlProperty* ControlPropertyIterator; + + // ................................................................ + static const ControlProperty aProperties[] = { + { "Text", PROPERTY_FLAG_TEXT }, + { "Enabled", PROPERTY_FLAG_ENDBALED }, + { "Visible", PROPERTY_FLAG_VISIBLE }, + { "HelpURL", PROPERTY_FLAG_HELPURL }, + { "ListItems", PROPERTY_FLAG_LISTITEMS }, + { "SelectedItem", PROPERTY_FLAG_SELECTEDITEM }, + { "SelectedItemIndex", PROPERTY_FLAG_SELECTEDITEMINDEX }, + { "Checked", PROPERTY_FLAG_CHECKED } + }; + + // ................................................................ + static const int s_nPropertyCount = SAL_N_ELEMENTS( aProperties ); + + static ControlPropertyIterator s_pProperties = aProperties; + static ControlPropertyIterator s_pPropertiesEnd = aProperties + s_nPropertyCount; + + // ................................................................ + struct ControlPropertyLookup + { + ::rtl::OUString m_sLookup; + ControlPropertyLookup( const ::rtl::OUString& _rLookup ) : m_sLookup( _rLookup ) { } + + sal_Bool operator()( const ControlProperty& _rProp ) + { + return m_sLookup.equalsAscii( _rProp.pPropertyName ); + } + }; + + //----------------------------------------------------------------- + void lcl_throwIllegalArgumentException( ) SAL_THROW( (IllegalArgumentException) ) + { + throw IllegalArgumentException(); + // TODO: error message in the exception + } + } + + //--------------------------------------------------------------------- + OControlAccess::OControlAccess( IFilePickerController* _pController, SvtFileView* _pFileView ) + :m_pFilePickerController( _pController ) + ,m_pFileView( _pFileView ) + { + DBG_ASSERT( m_pFilePickerController, "OControlAccess::OControlAccess: invalid control locator!" ); + } + + //--------------------------------------------------------------------- + void OControlAccess::setHelpURL( Window* _pControl, const ::rtl::OUString& _rURL, sal_Bool _bFileView ) + { + String sHelpURL( _rURL ); + if ( COMPARE_EQUAL == sHelpURL.CompareIgnoreCaseToAscii( "HID:", sizeof( "HID:" ) - 1 ) ) + { + String sID = sHelpURL.Copy( sizeof( "HID:" ) - 1 ); + sal_Int32 nHelpId = sID.ToInt32(); + + if ( _bFileView ) + // the file view "overloaded" the SetHelpId + static_cast< SvtFileView* >( _pControl )->SetHelpId( nHelpId ); + else + _pControl->SetHelpId( nHelpId ); + } + else + { + DBG_ERRORFILE( "OControlAccess::setHelpURL: unsupported help URL type!" ); + } + } + + //--------------------------------------------------------------------- + ::rtl::OUString OControlAccess::getHelpURL( Window* _pControl, sal_Bool _bFileView ) + { + sal_Int32 nHelpId = _pControl->GetHelpId(); + if ( _bFileView ) + // the file view "overloaded" the SetHelpId + nHelpId = static_cast< SvtFileView* >( _pControl )->GetHelpId( ); + + ::rtl::OUString sHelpURL( RTL_CONSTASCII_USTRINGPARAM( "HID:" ) ); + sHelpURL += ::rtl::OUString::valueOf( (sal_Int32)nHelpId ); + + return sHelpURL; + } + + // -------------------------------------------------------------------------- + Any OControlAccess::getControlProperty( const ::rtl::OUString& _rControlName, const ::rtl::OUString& _rControlProperty ) + { + // look up the control + sal_Int16 nControlId = -1; + sal_Int32 nPropertyMask = 0; + Control* pControl = implGetControl( _rControlName, &nControlId, &nPropertyMask ); + // will throw an IllegalArgumentException if the name is not valid + + // look up the property + ControlPropertyIterator aPropDesc = ::std::find_if( s_pProperties, s_pPropertiesEnd, ControlPropertyLookup( _rControlProperty ) ); + if ( aPropDesc == s_pPropertiesEnd ) + // it's a completely unknown property + lcl_throwIllegalArgumentException(); + + if ( 0 == ( nPropertyMask & aPropDesc->nPropertyId ) ) + // it's a property which is known, but not allowed for this control + lcl_throwIllegalArgumentException(); + + return implGetControlProperty( pControl, aPropDesc->nPropertyId ); + } + + //--------------------------------------------------------------------- + Control* OControlAccess::implGetControl( const ::rtl::OUString& _rControlName, sal_Int16* _pId, sal_Int32* _pPropertyMask ) const SAL_THROW( (IllegalArgumentException) ) + { + Control* pControl = NULL; + + // translate the name into an id + ControlDescRange aFoundRange = ::std::equal_range( s_pControls, s_pControlsEnd, _rControlName, ControlDescriptionLookup() ); + if ( aFoundRange.first != aFoundRange.second ) + { + // get the VCL control determined by this id + pControl = m_pFilePickerController->getControl( aFoundRange.first->nControlId ); + } + + // if not found 'til here, the name is invalid, or we do not have the control in the current mode + if ( !pControl ) + lcl_throwIllegalArgumentException(); + + // out parameters and outta here + if ( _pId ) + *_pId = aFoundRange.first->nControlId; + if ( _pPropertyMask ) + *_pPropertyMask = aFoundRange.first->nPropertyFlags; + + return pControl; + } + + //--------------------------------------------------------------------- + void OControlAccess::setControlProperty( const ::rtl::OUString& _rControlName, const ::rtl::OUString& _rControlProperty, const ::com::sun::star::uno::Any& _rValue ) + { + // look up the control + sal_Int16 nControlId = -1; + Control* pControl = implGetControl( _rControlName, &nControlId ); + // will throw an IllegalArgumentException if the name is not valid + + // look up the property + ControlPropertyIterator aPropDesc = ::std::find_if( s_pProperties, s_pPropertiesEnd, ControlPropertyLookup( _rControlProperty ) ); + if ( aPropDesc == s_pPropertiesEnd ) + lcl_throwIllegalArgumentException(); + + // set the property + implSetControlProperty( nControlId, pControl, aPropDesc->nPropertyId, _rValue, sal_False ); + } + + // -------------------------------------------------------------------------- + Sequence< ::rtl::OUString > OControlAccess::getSupportedControls( ) + { + Sequence< ::rtl::OUString > aControls( s_nControlCount ); + ::rtl::OUString* pControls = aControls.getArray(); + + // collect the names of all _actually_existent_ controls + for ( ControlDescIterator aControl = s_pControls; aControl != s_pControlsEnd; ++aControl ) + { + if ( m_pFilePickerController->getControl( aControl->nControlId ) ) + *pControls++ = ::rtl::OUString::createFromAscii( aControl->pControlName ); + } + + aControls.realloc( pControls - aControls.getArray() ); + return aControls; + } + + // -------------------------------------------------------------------------- + Sequence< ::rtl::OUString > OControlAccess::getSupportedControlProperties( const ::rtl::OUString& _rControlName ) + { + sal_Int16 nControlId = -1; + sal_Int32 nPropertyMask = 0; + implGetControl( _rControlName, &nControlId, &nPropertyMask ); + // will throw an IllegalArgumentException if the name is not valid + + // fill in the property names + Sequence< ::rtl::OUString > aProps( s_nPropertyCount ); + ::rtl::OUString* pProperty = aProps.getArray(); + + for ( ControlPropertyIterator aProp = s_pProperties; aProp != s_pPropertiesEnd; ++aProp ) + if ( 0 != ( nPropertyMask & aProp->nPropertyId ) ) + *pProperty++ = ::rtl::OUString::createFromAscii( aProp->pPropertyName ); + + aProps.realloc( pProperty - aProps.getArray() ); + return aProps; + } + + // -------------------------------------------------------------------------- + sal_Bool OControlAccess::isControlSupported( const ::rtl::OUString& _rControlName ) + { + return ::std::binary_search( s_pControls, s_pControlsEnd, _rControlName, ControlDescriptionLookup() ); + } + + // -------------------------------------------------------------------------- + sal_Bool OControlAccess::isControlPropertySupported( const ::rtl::OUString& _rControlName, const ::rtl::OUString& _rControlProperty ) + { + // look up the control + sal_Int16 nControlId = -1; + sal_Int32 nPropertyMask = 0; + implGetControl( _rControlName, &nControlId, &nPropertyMask ); + // will throw an IllegalArgumentException if the name is not valid + + // look up the property + ControlPropertyIterator aPropDesc = ::std::find_if( s_pProperties, s_pPropertiesEnd, ControlPropertyLookup( _rControlProperty ) ); + if ( aPropDesc == s_pPropertiesEnd ) + // it's a property which is completely unknown + return sal_False; + + return 0 != ( aPropDesc->nPropertyId & nPropertyMask ); + } + + //----------------------------------------------------------------------------- + void OControlAccess::setValue( sal_Int16 _nControlId, sal_Int16 _nControlAction, const Any& _rValue ) + { + Control* pControl = m_pFilePickerController->getControl( _nControlId ); + DBG_ASSERT( pControl, "OControlAccess::SetValue: don't have this control in the current mode!" ); + if ( pControl ) + { + sal_Int16 nPropertyId = -1; + if ( ControlActions::SET_HELP_URL == _nControlAction ) + { + nPropertyId = PROPERTY_FLAG_HELPURL; + } + else + { + switch ( _nControlId ) + { + case CHECKBOX_AUTOEXTENSION: + case CHECKBOX_PASSWORD: + case CHECKBOX_FILTEROPTIONS: + case CHECKBOX_READONLY: + case CHECKBOX_LINK: + case CHECKBOX_PREVIEW: + case CHECKBOX_SELECTION: + nPropertyId = PROPERTY_FLAG_CHECKED; + break; + + case LISTBOX_FILTER: + DBG_ERRORFILE( "Use the XFilterManager to access the filter listbox" ); + break; + + case LISTBOX_VERSION: + case LISTBOX_TEMPLATE: + case LISTBOX_IMAGE_TEMPLATE: + if ( ControlActions::SET_SELECT_ITEM == _nControlAction ) + { + nPropertyId = PROPERTY_FLAG_SELECTEDITEMINDEX; + } + else + { + DBG_ASSERT( WINDOW_LISTBOX == pControl->GetType(), "OControlAccess::SetValue: implGetControl returned nonsense!" ); + implDoListboxAction( static_cast< ListBox* >( pControl ), _nControlAction, _rValue ); + } + break; + } + } + + if ( -1 != nPropertyId ) + implSetControlProperty( _nControlId, pControl, nPropertyId, _rValue ); + } + } + + //----------------------------------------------------------------------------- + Any OControlAccess::getValue( sal_Int16 _nControlId, sal_Int16 _nControlAction ) const + { + Any aRet; + + Control* pControl = m_pFilePickerController->getControl( _nControlId, sal_False ); + DBG_ASSERT( pControl, "OControlAccess::GetValue: don't have this control in the current mode!" ); + if ( pControl ) + { + sal_Int16 nPropertyId = -1; + if ( ControlActions::SET_HELP_URL == _nControlAction ) + { + nPropertyId = PROPERTY_FLAG_HELPURL; + } + else + { + switch ( _nControlId ) + { + case CHECKBOX_AUTOEXTENSION: + case CHECKBOX_PASSWORD: + case CHECKBOX_FILTEROPTIONS: + case CHECKBOX_READONLY: + case CHECKBOX_LINK: + case CHECKBOX_PREVIEW: + case CHECKBOX_SELECTION: + nPropertyId = PROPERTY_FLAG_CHECKED; + break; + + case LISTBOX_FILTER: + if ( ControlActions::GET_SELECTED_ITEM == _nControlAction ) + { + aRet <<= ::rtl::OUString( m_pFilePickerController->getCurFilter() );; + } + else + { + DBG_ERRORFILE( "Use the XFilterManager to access the filter listbox" ); + } + break; + + case LISTBOX_VERSION: + case LISTBOX_TEMPLATE: + case LISTBOX_IMAGE_TEMPLATE: + switch ( _nControlAction ) + { + case ControlActions::GET_SELECTED_ITEM: + nPropertyId = PROPERTY_FLAG_SELECTEDITEM; + break; + case ControlActions::GET_SELECTED_ITEM_INDEX: + nPropertyId = PROPERTY_FLAG_SELECTEDITEMINDEX; + break; + case ControlActions::GET_ITEMS: + nPropertyId = PROPERTY_FLAG_LISTITEMS; + break; + default: + DBG_ERRORFILE( "OControlAccess::GetValue: invalid control action for the listbox!" ); + break; + } + break; + } + } + + if ( -1 != nPropertyId ) + aRet = implGetControlProperty( pControl, nPropertyId ); + } + + return aRet; + } + + //----------------------------------------------------------------------------- + void OControlAccess::setLabel( sal_Int16 nId, const ::rtl::OUString &rLabel ) + { + Control* pControl = m_pFilePickerController->getControl( nId, sal_True ); + DBG_ASSERT( pControl, "OControlAccess::GetValue: don't have this control in the current mode!" ); + if ( pControl ) + pControl->SetText( rLabel ); + } + + //----------------------------------------------------------------------------- + ::rtl::OUString OControlAccess::getLabel( sal_Int16 nId ) const + { + ::rtl::OUString sLabel; + + Control* pControl = m_pFilePickerController->getControl( nId, sal_True ); + DBG_ASSERT( pControl, "OControlAccess::GetValue: don't have this control in the current mode!" ); + if ( pControl ) + sLabel = pControl->GetText(); + + return sLabel; + } + + //----------------------------------------------------------------------------- + void OControlAccess::enableControl( sal_Int16 _nId, sal_Bool _bEnable ) + { + m_pFilePickerController->enableControl( _nId, _bEnable ); + } + + // ----------------------------------------------------------------------- + void OControlAccess::implDoListboxAction( ListBox* _pListbox, sal_Int16 _nControlAction, const Any& _rValue ) + { + switch ( _nControlAction ) + { + case ControlActions::ADD_ITEM: + { + ::rtl::OUString aEntry; + _rValue >>= aEntry; + if ( aEntry.getLength() ) + _pListbox->InsertEntry( aEntry ); + } + break; + + case ControlActions::ADD_ITEMS: + { + Sequence < ::rtl::OUString > aTemplateList; + _rValue >>= aTemplateList; + + if ( aTemplateList.getLength() ) + { + for ( long i=0; i < aTemplateList.getLength(); i++ ) + _pListbox->InsertEntry( aTemplateList[i] ); + } + } + break; + + case ControlActions::DELETE_ITEM: + { + sal_Int32 nPos = 0; + if ( _rValue >>= nPos ) + _pListbox->RemoveEntry( (USHORT) nPos ); + } + break; + + case ControlActions::DELETE_ITEMS: + _pListbox->Clear(); + break; + + default: + DBG_ERRORFILE( "Wrong ControlAction for implDoListboxAction()" ); + } + } + + //----------------------------------------------------------------------------- + void OControlAccess::implSetControlProperty( sal_Int16 _nControlId, Control* _pControl, sal_Int16 _nProperty, const Any& _rValue, sal_Bool _bIgnoreIllegalArgument ) + { + if ( !_pControl ) + _pControl = m_pFilePickerController->getControl( _nControlId ); + DBG_ASSERT( _pControl, "OControlAccess::implSetControlProperty: invalid argument, this will crash!" ); + if ( !_pControl ) + return; + + DBG_ASSERT( _pControl == m_pFilePickerController->getControl( _nControlId ), + "OControlAccess::implSetControlProperty: inconsistent parameters!" ); + + switch ( _nProperty ) + { + case PROPERTY_FLAG_TEXT: + { + ::rtl::OUString sText; + if ( _rValue >>= sText ) + { + _pControl->SetText( sText ); + } + else if ( !_bIgnoreIllegalArgument ) + { + lcl_throwIllegalArgumentException(); + } + } + break; + + case PROPERTY_FLAG_ENDBALED: + { + sal_Bool bEnabled = sal_False; + if ( _rValue >>= bEnabled ) + { + m_pFilePickerController->enableControl( _nControlId, bEnabled ); + } + else if ( !_bIgnoreIllegalArgument ) + { + lcl_throwIllegalArgumentException(); + } + } + break; + + case PROPERTY_FLAG_VISIBLE: + { + sal_Bool bVisible = sal_False; + if ( _rValue >>= bVisible ) + { + _pControl->Show( bVisible ); + } + else if ( !_bIgnoreIllegalArgument ) + { + lcl_throwIllegalArgumentException(); + } + } + break; + + case PROPERTY_FLAG_HELPURL: + { + ::rtl::OUString sHelpURL; + if ( _rValue >>= sHelpURL ) + { + setHelpURL( _pControl, sHelpURL, m_pFileView == _pControl ); + } + else if ( !_bIgnoreIllegalArgument ) + { + lcl_throwIllegalArgumentException(); + } + } + break; + + case PROPERTY_FLAG_LISTITEMS: + { + DBG_ASSERT( WINDOW_LISTBOX == _pControl->GetType(), + "OControlAccess::implSetControlProperty: invalid control/property combination!" ); + + Sequence< ::rtl::OUString > aItems; + if ( _rValue >>= aItems ) + { + // remove all previous items + static_cast< ListBox* >( _pControl )->Clear(); + + // add the new ones + const ::rtl::OUString* pItems = aItems.getConstArray(); + const ::rtl::OUString* pItemsEnd = aItems.getConstArray() + aItems.getLength(); + for ( const ::rtl::OUString* pItem = pItems; + pItem != pItemsEnd; + ++pItem + ) + { + static_cast< ListBox* >( _pControl )->InsertEntry( *pItem ); + } + + } + else if ( !_bIgnoreIllegalArgument ) + { + lcl_throwIllegalArgumentException(); + } + } + break; + + case PROPERTY_FLAG_SELECTEDITEM: + { + DBG_ASSERT( WINDOW_LISTBOX == _pControl->GetType(), + "OControlAccess::implSetControlProperty: invalid control/property combination!" ); + + ::rtl::OUString sSelected; + if ( _rValue >>= sSelected ) + { + static_cast< ListBox* >( _pControl )->SelectEntry( sSelected ); + } + else if ( !_bIgnoreIllegalArgument ) + { + lcl_throwIllegalArgumentException(); + } + } + break; + + case PROPERTY_FLAG_SELECTEDITEMINDEX: + { + DBG_ASSERT( WINDOW_LISTBOX == _pControl->GetType(), + "OControlAccess::implSetControlProperty: invalid control/property combination!" ); + + sal_Int32 nPos = 0; + if ( _rValue >>= nPos ) + { + static_cast< ListBox* >( _pControl )->SelectEntryPos( (USHORT) nPos ); + } + else if ( !_bIgnoreIllegalArgument ) + { + lcl_throwIllegalArgumentException(); + } + } + break; + + case PROPERTY_FLAG_CHECKED: + { + DBG_ASSERT( WINDOW_CHECKBOX == _pControl->GetType(), + "OControlAccess::implSetControlProperty: invalid control/property combination!" ); + + sal_Bool bChecked = sal_False; + if ( _rValue >>= bChecked ) + { + static_cast< CheckBox* >( _pControl )->Check( bChecked ); + } + else if ( !_bIgnoreIllegalArgument ) + { + lcl_throwIllegalArgumentException(); + } + } + break; + + default: + DBG_ERROR( "OControlAccess::implSetControlProperty: invalid property id!" ); + } + } + + //----------------------------------------------------------------------------- + Any OControlAccess::implGetControlProperty( Control* _pControl, sal_Int16 _nProperty ) const + { + DBG_ASSERT( _pControl, "OControlAccess::implGetControlProperty: invalid argument, this will crash!" ); + + Any aReturn; + switch ( _nProperty ) + { + case PROPERTY_FLAG_TEXT: + aReturn <<= ::rtl::OUString( _pControl->GetText() ); + break; + + case PROPERTY_FLAG_ENDBALED: + aReturn <<= (sal_Bool)_pControl->IsEnabled(); + break; + + case PROPERTY_FLAG_VISIBLE: + aReturn <<= (sal_Bool)_pControl->IsVisible(); + break; + + case PROPERTY_FLAG_HELPURL: + aReturn <<= getHelpURL( _pControl, m_pFileView == _pControl ); + break; + + case PROPERTY_FLAG_LISTITEMS: + { + DBG_ASSERT( WINDOW_LISTBOX == _pControl->GetType(), + "OControlAccess::implGetControlProperty: invalid control/property combination!" ); + + Sequence< ::rtl::OUString > aItems( static_cast< ListBox* >( _pControl )->GetEntryCount() ); + ::rtl::OUString* pItems = aItems.getArray(); + for ( USHORT i=0; i<static_cast< ListBox* >( _pControl )->GetEntryCount(); ++i ) + *pItems++ = static_cast< ListBox* >( _pControl )->GetEntry( i ); + + aReturn <<= aItems; + } + break; + + case PROPERTY_FLAG_SELECTEDITEM: + { + DBG_ASSERT( WINDOW_LISTBOX == _pControl->GetType(), + "OControlAccess::implGetControlProperty: invalid control/property combination!" ); + + USHORT nSelected = static_cast< ListBox* >( _pControl )->GetSelectEntryPos(); + ::rtl::OUString sSelected; + if ( LISTBOX_ENTRY_NOTFOUND != nSelected ) + sSelected = static_cast< ListBox* >( _pControl )->GetSelectEntry(); + aReturn <<= sSelected; + } + break; + + case PROPERTY_FLAG_SELECTEDITEMINDEX: + { + DBG_ASSERT( WINDOW_LISTBOX == _pControl->GetType(), + "OControlAccess::implGetControlProperty: invalid control/property combination!" ); + + USHORT nSelected = static_cast< ListBox* >( _pControl )->GetSelectEntryPos(); + if ( LISTBOX_ENTRY_NOTFOUND != nSelected ) + aReturn <<= (sal_Int32)static_cast< ListBox* >( _pControl )->GetSelectEntryPos(); + else + aReturn <<= (sal_Int32)-1; + } + break; + + case PROPERTY_FLAG_CHECKED: + DBG_ASSERT( WINDOW_CHECKBOX == _pControl->GetType(), + "OControlAccess::implGetControlProperty: invalid control/property combination!" ); + + aReturn <<= (sal_Bool)static_cast< CheckBox* >( _pControl )->IsChecked( ); + break; + + default: + DBG_ERROR( "OControlAccess::implGetControlProperty: invalid property id!" ); + } + return aReturn; + } + +//......................................................................... +} // namespace svt +//......................................................................... + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/office/OfficeControlAccess.hxx b/fpicker/source/office/OfficeControlAccess.hxx new file mode 100644 index 000000000000..44bd416f60c1 --- /dev/null +++ b/fpicker/source/office/OfficeControlAccess.hxx @@ -0,0 +1,127 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SVTOOLS_CONTROLACCESS_HXX +#define SVTOOLS_CONTROLACCESS_HXX + +#include <svtools/fileview.hxx> +#include <vcl/lstbox.hxx> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include "pickercallbacks.hxx" + +//......................................................................... +namespace svt +{ +//......................................................................... + + // -------------------------------------------------------------------- + namespace InternalFilePickerElementIds + { + static const sal_Int16 PUSHBUTTON_HELP = (sal_Int16)0x1000; + static const sal_Int16 TOOLBOXBUTOON_DEFAULT_LOCATION = (sal_Int16)0x1001; + static const sal_Int16 TOOLBOXBUTOON_LEVEL_UP = (sal_Int16)0x1002; + static const sal_Int16 TOOLBOXBUTOON_NEW_FOLDER = (sal_Int16)0x1003; + static const sal_Int16 FIXEDTEXT_CURRENTFOLDER = (sal_Int16)0x1004; + } + + // -------------------------------------------------------------------- + /** implements the XControlAccess, XControlInformation and XFilePickerControlAccess for the file picker + */ + class OControlAccess + { + IFilePickerController* m_pFilePickerController; + SvtFileView* m_pFileView; + + public: + OControlAccess( IFilePickerController* _pController, SvtFileView* _pFileView ); + + // XControlAccess implementation + void setControlProperty( const ::rtl::OUString& _rControlName, const ::rtl::OUString& _rControlProperty, const ::com::sun::star::uno::Any& _rValue ); + ::com::sun::star::uno::Any getControlProperty( const ::rtl::OUString& _rControlName, const ::rtl::OUString& _rControlProperty ); + + // XControlInformation implementation + ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedControls( ); + ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedControlProperties( const ::rtl::OUString& _rControlName ); + sal_Bool isControlSupported( const ::rtl::OUString& _rControlName ); + sal_Bool isControlPropertySupported( const ::rtl::OUString& _rControlName, const ::rtl::OUString& _rControlProperty ); + + // XFilePickerControlAccess + void setValue( sal_Int16 _nId, sal_Int16 _nCtrlAction, const ::com::sun::star::uno::Any& _rValue ); + ::com::sun::star::uno::Any getValue( sal_Int16 _nId, sal_Int16 _nCtrlAction ) const; + void setLabel( sal_Int16 _nId, const ::rtl::OUString& _rValue ); + ::rtl::OUString getLabel( sal_Int16 _nId ) const; + void enableControl( sal_Int16 _nId, sal_Bool _bEnable ); + + static void setHelpURL( Window* _pControl, const ::rtl::OUString& _rURL, sal_Bool _bFileView ); + static ::rtl::OUString getHelpURL( Window* _pControl, sal_Bool _bFileView ); + + private: + /** implements the various methods for setting properties on controls + + @param _nControlId + the id of the control + @param _pControl + the affected control. Must be the same as referred by <arg>_nControlId</arg>, or NULL. + @param _nProperty + the property to set + See PROPERTY_FLAG_* + @param _rValue + the value to set + @param _bIgnoreIllegalArgument + if <FALSE/>, an exception will be thrown if the given value is of improper type + */ + void implSetControlProperty( + sal_Int16 _nControlId, + Control* _pControl, sal_Int16 _nProperty, const ::com::sun::star::uno::Any& _rValue, + sal_Bool _bIgnoreIllegalArgument = sal_True ); + + Control* implGetControl( const ::rtl::OUString& _rControlName, sal_Int16* _pId = NULL, sal_Int32* _pPropertyMask = NULL ) const SAL_THROW( (::com::sun::star::lang::IllegalArgumentException) ); + + /** implements the various methods for retrieving properties from controls + + @param _pControl + the affected control + @PRECOND not <NULL/> + @param _nProperty + the property to retrieve + See PROPERTY_FLAG_* + @return + */ + ::com::sun::star::uno::Any implGetControlProperty( Control* _pControl, sal_Int16 _nProperty ) const; + + void implDoListboxAction( ListBox* _pListbox, sal_Int16 _nCtrlAction, const ::com::sun::star::uno::Any& _rValue ); + + }; + +//......................................................................... +} // namespace svt +//......................................................................... + +#endif // SVTOOLS_CONTROLACCESS_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/office/OfficeFilePicker.cxx b/fpicker/source/office/OfficeFilePicker.cxx new file mode 100644 index 000000000000..20b542825c8b --- /dev/null +++ b/fpicker/source/office/OfficeFilePicker.cxx @@ -0,0 +1,1187 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +#include "OfficeFilePicker.hxx" +#include "iodlg.hxx" + +#ifndef _LIST_ +#include <list> +#endif +#ifndef _FUNCTIONAL_ +#include <functional> +#endif +#ifndef _ALGORITHM_ +#include <algorithm> +#endif +#include <tools/urlobj.hxx> +#include <tools/debug.hxx> +#define _SVSTDARR_STRINGSDTOR +#include "svl/svstdarr.hxx" +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/ui/dialogs/FilePickerEvent.hpp> +#include <com/sun/star/ui/dialogs/FilePreviewImageFormats.hpp> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/beans/StringPair.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/beans/NamedValue.hpp> +#include <unotools/ucbhelper.hxx> +#include <unotools/pathoptions.hxx> +#include <comphelper/sequence.hxx> +#include <cppuhelper/typeprovider.hxx> +#include "osl/mutex.hxx" +#include "vcl/svapp.hxx" + +// define ---------------------------------------------------------------- + +#define MAKE_ANY ::com::sun::star::uno::makeAny + +// using ---------------------------------------------------------------- + +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::awt; +using namespace ::utl; + +//===================================================================== + +//===================================================================== + +struct FilterEntry +{ +protected: + ::rtl::OUString m_sTitle; + ::rtl::OUString m_sFilter; + + UnoFilterList m_aSubFilters; + +public: + FilterEntry( const ::rtl::OUString& _rTitle, const ::rtl::OUString& _rFilter ) + :m_sTitle( _rTitle ) + ,m_sFilter( _rFilter ) + { + } + + FilterEntry( const ::rtl::OUString& _rTitle, const UnoFilterList& _rSubFilters ); + + ::rtl::OUString getTitle() const { return m_sTitle; } + ::rtl::OUString getFilter() const { return m_sFilter; } + + /// determines if the filter has sub filter (i.e., the filter is a filter group in real) + sal_Bool hasSubFilters( ) const; + + /** retrieves the filters belonging to the entry + @return + the number of sub filters + */ + sal_Int32 getSubFilters( UnoFilterList& _rSubFilterList ); + + // helpers for iterating the sub filters + const UnoFilterEntry* beginSubFilters() const { return m_aSubFilters.getConstArray(); } + const UnoFilterEntry* endSubFilters() const { return m_aSubFilters.getConstArray() + m_aSubFilters.getLength(); } +}; + +//===================================================================== + +//--------------------------------------------------------------------- +FilterEntry::FilterEntry( const ::rtl::OUString& _rTitle, const UnoFilterList& _rSubFilters ) + :m_sTitle( _rTitle ) + ,m_aSubFilters( _rSubFilters ) +{ +} + +//--------------------------------------------------------------------- +sal_Bool FilterEntry::hasSubFilters( ) const +{ + return ( 0 < m_aSubFilters.getLength() ); +} + +//--------------------------------------------------------------------- +sal_Int32 FilterEntry::getSubFilters( UnoFilterList& _rSubFilterList ) +{ + _rSubFilterList = m_aSubFilters; + return m_aSubFilters.getLength(); +} + +// struct ElementEntry_Impl ---------------------------------------------- + +struct ElementEntry_Impl +{ + sal_Int16 m_nElementID; + sal_Int16 m_nControlAction; + Any m_aValue; + rtl::OUString m_aLabel; + sal_Bool m_bEnabled : 1; + + sal_Bool m_bHasValue : 1; + sal_Bool m_bHasLabel : 1; + sal_Bool m_bHasEnabled : 1; + + ElementEntry_Impl( sal_Int16 nId ); + + void setValue( const Any& rVal ) { m_aValue = rVal; m_bHasValue = sal_True; } + void setAction( sal_Int16 nAction ) { m_nControlAction = nAction; } + void setLabel( const rtl::OUString& rVal ) { m_aLabel = rVal; m_bHasLabel = sal_True; } + void setEnabled( sal_Bool bEnabled ) { m_bEnabled = bEnabled; m_bHasEnabled = sal_True; } +}; + +ElementEntry_Impl::ElementEntry_Impl( sal_Int16 nId ) + : m_nElementID( nId ) + , m_nControlAction( 0 ) + , m_bEnabled( sal_False ) + , m_bHasValue( sal_False ) + , m_bHasLabel( sal_False ) + , m_bHasEnabled( sal_False ) +{} + +//------------------------------------------------------------------------------------ +void SvtFilePicker::prepareExecute() +{ + // set the default directory + // --**-- doesn't match the spec yet + if ( m_aDisplayDirectory.getLength() > 0 || m_aDefaultName.getLength() > 0 ) + { + if ( m_aDisplayDirectory.getLength() > 0 ) + { + + INetURLObject aPath( m_aDisplayDirectory ); + if ( m_aDefaultName.getLength() > 0 ) + { + aPath.insertName( m_aDefaultName ); + getDialog()->SetHasFilename( true ); + } + String sPath = aPath.GetMainURL( INetURLObject::NO_DECODE ); + getDialog()->SetPath( aPath.GetMainURL( INetURLObject::NO_DECODE ) ); + } + else if ( m_aDefaultName.getLength() > 0 ) + { + getDialog()->SetPath( m_aDefaultName ); + getDialog()->SetHasFilename( true ); + } + } + else + { + // Default-Standard-Dir setzen + INetURLObject aStdDirObj( SvtPathOptions().GetWorkPath() ); + getDialog()->SetPath( aStdDirObj.GetMainURL( INetURLObject::NO_DECODE ) ); + } + + // set the control values and set the control labels, too + if ( m_pElemList && !m_pElemList->empty() ) + { + ::svt::OControlAccess aAccess( getDialog(), getDialog()->GetView() ); + + ElementList::iterator aListIter; + for ( aListIter = m_pElemList->begin(); + aListIter != m_pElemList->end(); ++aListIter ) + { + ElementEntry_Impl& rEntry = *aListIter; + if ( rEntry.m_bHasValue ) + aAccess.setValue( rEntry.m_nElementID, rEntry.m_nControlAction, rEntry.m_aValue ); + if ( rEntry.m_bHasLabel ) + aAccess.setLabel( rEntry.m_nElementID, rEntry.m_aLabel ); + if ( rEntry.m_bHasEnabled ) + aAccess.enableControl( rEntry.m_nElementID, rEntry.m_bEnabled ); + } + + getDialog()->updateListboxLabelSizes(); + } + + if ( m_pFilterList && !m_pFilterList->empty() ) + { + for ( FilterList::iterator aListIter = m_pFilterList->begin(); + aListIter != m_pFilterList->end(); + ++aListIter + ) + { + if ( aListIter->hasSubFilters() ) + { // it's a filter group + UnoFilterList aSubFilters; + aListIter->getSubFilters( aSubFilters ); + + getDialog()->AddFilterGroup( aListIter->getTitle(), aSubFilters ); + } + else + // it's a single filter + getDialog()->AddFilter( aListIter->getTitle(), aListIter->getFilter() ); + } + } + + // set the default filter + if ( m_aCurrentFilter.getLength() > 0 ) + getDialog()->SetCurFilter( m_aCurrentFilter ); + +} + +//----------------------------------------------------------------------------- +IMPL_LINK( SvtFilePicker, DialogClosedHdl, Dialog*, pDlg ) +{ + if ( m_xDlgClosedListener.is() ) + { + sal_Int16 nRet = static_cast< sal_Int16 >( pDlg->GetResult() ); + ::com::sun::star::ui::dialogs::DialogClosedEvent aEvent( *this, nRet ); + m_xDlgClosedListener->dialogClosed( aEvent ); + m_xDlgClosedListener.clear(); + } + return 0; +} + +//------------------------------------------------------------------------------------ +// SvtFilePicker +//------------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------------ +WinBits SvtFilePicker::getWinBits( WinBits& rExtraBits ) +{ + // set the winbits for creating the filedialog + WinBits nBits = 0L; + rExtraBits = 0L; + + // set the standard bits acording to the service name + if ( m_nServiceType == TemplateDescription::FILEOPEN_SIMPLE ) + { + nBits = WB_OPEN; + } + else if ( m_nServiceType == TemplateDescription::FILESAVE_SIMPLE ) + { + nBits = WB_SAVEAS; + } + else if ( m_nServiceType == TemplateDescription::FILESAVE_AUTOEXTENSION ) + { + nBits = WB_SAVEAS; + rExtraBits = SFX_EXTRA_AUTOEXTENSION; + } + else if ( m_nServiceType == TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD ) + { + nBits = WB_SAVEAS | SFXWB_PASSWORD; + rExtraBits = SFX_EXTRA_AUTOEXTENSION; + } + else if ( m_nServiceType == TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS ) + { + nBits = WB_SAVEAS | SFXWB_PASSWORD; + rExtraBits = SFX_EXTRA_AUTOEXTENSION | SFX_EXTRA_FILTEROPTIONS; + } + else if ( m_nServiceType == TemplateDescription::FILESAVE_AUTOEXTENSION_TEMPLATE ) + { + nBits = WB_SAVEAS; + rExtraBits = SFX_EXTRA_AUTOEXTENSION | SFX_EXTRA_TEMPLATES; + } + else if ( m_nServiceType == TemplateDescription::FILESAVE_AUTOEXTENSION_SELECTION ) + { + nBits = WB_SAVEAS; + rExtraBits = SFX_EXTRA_AUTOEXTENSION | SFX_EXTRA_SELECTION; + } + + else if ( m_nServiceType == TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE ) + { + nBits = WB_OPEN; + rExtraBits = SFX_EXTRA_INSERTASLINK | SFX_EXTRA_SHOWPREVIEW | SFX_EXTRA_IMAGE_TEMPLATE; + } + else if ( m_nServiceType == TemplateDescription::FILEOPEN_PLAY ) + { + nBits = WB_OPEN; + rExtraBits = SFX_EXTRA_PLAYBUTTON; + } + else if ( m_nServiceType == TemplateDescription::FILEOPEN_READONLY_VERSION ) + { + nBits = WB_OPEN | SFXWB_READONLY; + rExtraBits = SFX_EXTRA_SHOWVERSIONS; + } + else if ( m_nServiceType == TemplateDescription::FILEOPEN_LINK_PREVIEW ) + { + nBits = WB_OPEN; + rExtraBits = SFX_EXTRA_INSERTASLINK | SFX_EXTRA_SHOWPREVIEW; + } + if ( m_bMultiSelection && ( ( nBits & WB_OPEN ) == WB_OPEN ) ) + nBits |= SFXWB_MULTISELECTION; + + return nBits; +} + +//------------------------------------------------------------------------------------ +void SvtFilePicker::notify( sal_Int16 _nEventId, sal_Int16 _nControlId ) +{ + if ( !m_xListener.is() ) + return; + + FilePickerEvent aEvent( *this, _nControlId ); + + switch ( _nEventId ) + { + case FILE_SELECTION_CHANGED: + m_xListener->fileSelectionChanged( aEvent ); + break; + case DIRECTORY_CHANGED: + m_xListener->directoryChanged( aEvent ); + break; + case HELP_REQUESTED: + m_xListener->helpRequested( aEvent ); + break; + case CTRL_STATE_CHANGED: + m_xListener->controlStateChanged( aEvent ); + break; + case DIALOG_SIZE_CHANGED: + m_xListener->dialogSizeChanged(); + break; + default: + DBG_ERRORFILE( "SvtFilePicker::notify(): Unknown event id!" ); + break; + } +} + +//------------------------------------------------------------------------------------ +namespace { + //................................................................................ + struct FilterTitleMatch : public ::std::unary_function< FilterEntry, bool > + { + protected: + const ::rtl::OUString& rTitle; + + public: + FilterTitleMatch( const ::rtl::OUString& _rTitle ) : rTitle( _rTitle ) { } + + //............................................................................ + bool operator () ( const FilterEntry& _rEntry ) + { + sal_Bool bMatch; + if ( !_rEntry.hasSubFilters() ) + // a real filter + bMatch = ( _rEntry.getTitle() == rTitle ); + else + // a filter group -> search the sub filters + bMatch = + _rEntry.endSubFilters() != ::std::find_if( + _rEntry.beginSubFilters(), + _rEntry.endSubFilters(), + *this + ); + + return bMatch ? true : false; + } + bool operator () ( const UnoFilterEntry& _rEntry ) + { + return _rEntry.First == rTitle ? true : false; + } + }; +} + +//------------------------------------------------------------------------------------ +sal_Bool SvtFilePicker::FilterNameExists( const ::rtl::OUString& rTitle ) +{ + sal_Bool bRet = sal_False; + + if ( m_pFilterList ) + bRet = + m_pFilterList->end() != ::std::find_if( + m_pFilterList->begin(), + m_pFilterList->end(), + FilterTitleMatch( rTitle ) + ); + + return bRet; +} + +//------------------------------------------------------------------------------------ +sal_Bool SvtFilePicker::FilterNameExists( const UnoFilterList& _rGroupedFilters ) +{ + sal_Bool bRet = sal_False; + + if ( m_pFilterList ) + { + const UnoFilterEntry* pStart = _rGroupedFilters.getConstArray(); + const UnoFilterEntry* pEnd = pStart + _rGroupedFilters.getLength(); + for ( ; pStart != pEnd; ++pStart ) + if ( m_pFilterList->end() != ::std::find_if( m_pFilterList->begin(), m_pFilterList->end(), FilterTitleMatch( pStart->First ) ) ) + break; + + bRet = pStart != pEnd; + } + + return bRet; +} + +//------------------------------------------------------------------------------------ +void SvtFilePicker::ensureFilterList( const ::rtl::OUString& _rInitialCurrentFilter ) +{ + if ( !m_pFilterList ) + { + m_pFilterList = new FilterList; + + // set the first filter to the current filter + if ( ! m_aCurrentFilter.getLength() ) + m_aCurrentFilter = _rInitialCurrentFilter; + } +} + +//------------------------------------------------------------------------------------ +// class SvtFilePicker +//------------------------------------------------------------------------------------ +SvtFilePicker::SvtFilePicker( const Reference < XMultiServiceFactory >& xFactory ) + :OCommonPicker( xFactory ) + ,m_pFilterList ( NULL ) + ,m_pElemList ( NULL ) + ,m_bMultiSelection ( sal_False ) + ,m_nServiceType ( TemplateDescription::FILEOPEN_SIMPLE ) +{ +} + +SvtFilePicker::~SvtFilePicker() +{ + if ( m_pFilterList && !m_pFilterList->empty() ) + m_pFilterList->erase( m_pFilterList->begin(), m_pFilterList->end() ); + delete m_pFilterList; + + if ( m_pElemList && !m_pElemList->empty() ) + m_pElemList->erase( m_pElemList->begin(), m_pElemList->end() ); + delete m_pElemList; +} + +//------------------------------------------------------------------------------------ +sal_Int16 SvtFilePicker::implExecutePicker( ) +{ + getDialog()->SetFileCallback( this ); + + prepareExecute(); + + getDialog()->EnableAutocompletion( TRUE ); + // now we are ready to execute the dialog + sal_Int16 nRet = getDialog()->Execute(); + + // the execution of the dialog yields, so it is possible the at this point the window or the dialog is closed + if ( getDialog() ) + getDialog()->SetFileCallback( NULL ); + + return nRet; +} + +//------------------------------------------------------------------------------------ +SvtFileDialog* SvtFilePicker::implCreateDialog( Window* _pParent ) +{ + WinBits nExtraBits; + WinBits nBits = getWinBits( nExtraBits ); + + SvtFileDialog* dialog = new SvtFileDialog( _pParent, nBits, nExtraBits ); + + // Set StandardDir if present + if ( m_aStandardDir.getLength() > 0) + { + String sStandardDir = String( m_aStandardDir ); + dialog->SetStandardDir( sStandardDir ); + dialog->SetBlackList( m_aBlackList ); + } + + return dialog; +} + +//------------------------------------------------------------------------------------ +// disambiguate XInterface +//------------------------------------------------------------------------------------ +IMPLEMENT_FORWARD_XINTERFACE2( SvtFilePicker, OCommonPicker, SvtFilePicker_Base ) + +//------------------------------------------------------------------------------------ +// disambiguate XTypeProvider +//------------------------------------------------------------------------------------ +IMPLEMENT_FORWARD_XTYPEPROVIDER2( SvtFilePicker, OCommonPicker, SvtFilePicker_Base ) + +//------------------------------------------------------------------------------------ +// XExecutableDialog functions +//------------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------------ +void SAL_CALL SvtFilePicker::setTitle( const ::rtl::OUString& _rTitle ) throw (RuntimeException) +{ + OCommonPicker::setTitle( _rTitle ); +} + +//------------------------------------------------------------------------------------ +sal_Int16 SAL_CALL SvtFilePicker::execute( ) throw (RuntimeException) +{ + return OCommonPicker::execute(); +} + +//------------------------------------------------------------------------------------ +// XAsynchronousExecutableDialog functions +//------------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------------ +void SAL_CALL SvtFilePicker::setDialogTitle( const ::rtl::OUString& _rTitle ) throw (RuntimeException) +{ + setTitle( _rTitle ); +} + +//------------------------------------------------------------------------------------ +void SAL_CALL SvtFilePicker::startExecuteModal( const Reference< ::com::sun::star::ui::dialogs::XDialogClosedListener >& xListener ) throw (RuntimeException) +{ + m_xDlgClosedListener = xListener; + prepareDialog(); + prepareExecute(); + getDialog()->EnableAutocompletion( TRUE ); + getDialog()->StartExecuteModal( LINK( this, SvtFilePicker, DialogClosedHdl ) ); +} + +//------------------------------------------------------------------------------------ +// XFilePicker functions +//------------------------------------------------------------------------------------ + +void SAL_CALL SvtFilePicker::setMultiSelectionMode( sal_Bool bMode ) throw( RuntimeException ) +{ + checkAlive(); + + SolarMutexGuard aGuard; + m_bMultiSelection = bMode; +} + +void SAL_CALL SvtFilePicker::setDefaultName( const rtl::OUString& aName ) throw( RuntimeException ) +{ + checkAlive(); + + SolarMutexGuard aGuard; + m_aDefaultName = aName; +} + +void SAL_CALL SvtFilePicker::setDisplayDirectory( const rtl::OUString& aDirectory ) + throw( IllegalArgumentException, RuntimeException ) +{ + checkAlive(); + + SolarMutexGuard aGuard; + m_aDisplayDirectory = aDirectory; +} + +rtl::OUString SAL_CALL SvtFilePicker::getDisplayDirectory() throw( RuntimeException ) +{ + checkAlive(); + + SolarMutexGuard aGuard; + if ( getDialog() ) + { + rtl::OUString aPath = getDialog()->GetPath(); + + // #97148# ---- + if( m_aOldHideDirectory == aPath ) + return m_aOldDisplayDirectory; + m_aOldHideDirectory = aPath; + + // #102204# ----- + if( !getDialog()->ContentIsFolder( aPath ) ) + { + INetURLObject aFolder( aPath ); + aFolder.CutLastName(); + aPath = aFolder.GetMainURL( INetURLObject::NO_DECODE ); + } + m_aOldDisplayDirectory = aPath; + return aPath; + } + else + return m_aDisplayDirectory; +} + +Sequence< rtl::OUString > SAL_CALL SvtFilePicker::getFiles() throw( RuntimeException ) +{ + checkAlive(); + + SolarMutexGuard aGuard; + if ( ! getDialog() ) + { + Sequence< rtl::OUString > aEmpty; + return aEmpty; + } + + // if there is more than one path we have to return the path to the + // files first and then the list of the selected entries + + SvStringsDtor* pPathList = getDialog()->GetPathList(); + USHORT i, nCount = pPathList->Count(); + USHORT nTotal = nCount > 1 ? nCount+1: nCount; + + Sequence< rtl::OUString > aPath( nTotal ); + + if ( nCount == 1 ) + aPath[0] = rtl::OUString( *pPathList->GetObject( 0 ) ); + else if ( nCount > 1 ) + { + INetURLObject aObj( *pPathList->GetObject( 0 ) ); + aObj.removeSegment(); + aPath[0] = aObj.GetMainURL( INetURLObject::NO_DECODE ); + + for ( i = 0; i < nCount; /* i++ is done below */ ) + { + aObj.SetURL( *pPathList->GetObject(i++) ); + aPath[i] = aObj.getName(); + } + } + + delete pPathList; + return aPath; +} + +//------------------------------------------------------------------------------------ +// XFilePickerControlAccess functions +//------------------------------------------------------------------------------------ + +void SAL_CALL SvtFilePicker::setValue( sal_Int16 nElementID, + sal_Int16 nControlAction, + const Any& rValue ) + throw( RuntimeException ) +{ + checkAlive(); + + SolarMutexGuard aGuard; + if ( getDialog() ) + { + ::svt::OControlAccess aAccess( getDialog(), getDialog()->GetView() ); + aAccess.setValue( nElementID, nControlAction, rValue ); + } + else + { + if ( !m_pElemList ) + m_pElemList = new ElementList; + + sal_Bool bFound = sal_False; + ElementList::iterator aListIter; + + for ( aListIter = m_pElemList->begin(); + aListIter != m_pElemList->end(); ++aListIter ) + { + ElementEntry_Impl& rEntry = *aListIter; + if ( ( rEntry.m_nElementID == nElementID ) && + ( !rEntry.m_bHasValue || ( rEntry.m_nControlAction == nControlAction ) ) ) + { + rEntry.setAction( nControlAction ); + rEntry.setValue( rValue ); + bFound = sal_True; + } + } + + if ( !bFound ) + { + ElementEntry_Impl aNew( nElementID ); + aNew.setAction( nControlAction ); + aNew.setValue( rValue ); + m_pElemList->insert( m_pElemList->end(), aNew ); + } + } +} + +//------------------------------------------------------------------------------------ + +Any SAL_CALL SvtFilePicker::getValue( sal_Int16 nElementID, sal_Int16 nControlAction ) + throw( RuntimeException ) +{ + checkAlive(); + + SolarMutexGuard aGuard; + Any aAny; + + // execute() called? + if ( getDialog() ) + { + ::svt::OControlAccess aAccess( getDialog(), getDialog()->GetView() ); + aAny = aAccess.getValue( nElementID, nControlAction ); + } + else if ( m_pElemList && !m_pElemList->empty() ) + { + ElementList::iterator aListIter; + for ( aListIter = m_pElemList->begin(); + aListIter != m_pElemList->end(); ++aListIter ) + { + ElementEntry_Impl& rEntry = *aListIter; + if ( ( rEntry.m_nElementID == nElementID ) && + ( rEntry.m_bHasValue ) && + ( rEntry.m_nControlAction == nControlAction ) ) + { + aAny = rEntry.m_aValue; + break; + } + } + } + + return aAny; +} + + +//------------------------------------------------------------------------------------ +void SAL_CALL SvtFilePicker::setLabel( sal_Int16 nLabelID, const rtl::OUString& rValue ) + throw ( RuntimeException ) +{ + checkAlive(); + + SolarMutexGuard aGuard; + if ( getDialog() ) + { + ::svt::OControlAccess aAccess( getDialog(), getDialog()->GetView() ); + aAccess.setLabel( nLabelID, rValue ); + } + else + { + if ( !m_pElemList ) + m_pElemList = new ElementList; + + sal_Bool bFound = sal_False; + ElementList::iterator aListIter; + + for ( aListIter = m_pElemList->begin(); + aListIter != m_pElemList->end(); ++aListIter ) + { + ElementEntry_Impl& rEntry = *aListIter; + if ( rEntry.m_nElementID == nLabelID ) + { + rEntry.setLabel( rValue ); + bFound = sal_True; + } + } + + if ( !bFound ) + { + ElementEntry_Impl aNew( nLabelID ); + aNew.setLabel( rValue ); + m_pElemList->insert( m_pElemList->end(), aNew ); + } + } +} + +//------------------------------------------------------------------------------------ +rtl::OUString SAL_CALL SvtFilePicker::getLabel( sal_Int16 nLabelID ) + throw ( RuntimeException ) +{ + checkAlive(); + + SolarMutexGuard aGuard; + rtl::OUString aLabel; + + if ( getDialog() ) + { + ::svt::OControlAccess aAccess( getDialog(), getDialog()->GetView() ); + aLabel = aAccess.getLabel( nLabelID ); + } + else if ( m_pElemList && !m_pElemList->empty() ) + { + ElementList::iterator aListIter; + for ( aListIter = m_pElemList->begin(); + aListIter != m_pElemList->end(); ++aListIter ) + { + ElementEntry_Impl& rEntry = *aListIter; + if ( rEntry.m_nElementID == nLabelID ) + { + if ( rEntry.m_bHasLabel ) + aLabel = rEntry.m_aLabel; + break; + } + } + } + + return aLabel; +} + +//------------------------------------------------------------------------------------ +void SAL_CALL SvtFilePicker::enableControl( sal_Int16 nElementID, sal_Bool bEnable ) + throw( RuntimeException ) +{ + checkAlive(); + + SolarMutexGuard aGuard; + if ( getDialog() ) + { + ::svt::OControlAccess aAccess( getDialog(), getDialog()->GetView() ); + aAccess.enableControl( nElementID, bEnable ); + } + else + { + if ( !m_pElemList ) + m_pElemList = new ElementList; + + sal_Bool bFound = sal_False; + ElementList::iterator aListIter; + + for ( aListIter = m_pElemList->begin(); + aListIter != m_pElemList->end(); ++aListIter ) + { + ElementEntry_Impl& rEntry = *aListIter; + if ( rEntry.m_nElementID == nElementID ) + { + rEntry.setEnabled( bEnable ); + bFound = sal_True; + } + } + + if ( !bFound ) + { + ElementEntry_Impl aNew( nElementID ); + aNew.setEnabled( bEnable ); + m_pElemList->insert( m_pElemList->end(), aNew ); + } + } +} + +//------------------------------------------------------------------------------------ +// XFilePickerNotifier functions +//------------------------------------------------------------------------------------ + +void SAL_CALL SvtFilePicker::addFilePickerListener( const Reference< XFilePickerListener >& xListener ) throw ( RuntimeException ) +{ + checkAlive(); + + SolarMutexGuard aGuard; + m_xListener = xListener; +} + +//------------------------------------------------------------------------------------ +void SAL_CALL SvtFilePicker::removeFilePickerListener( const Reference< XFilePickerListener >& ) throw ( RuntimeException ) +{ + checkAlive(); + + SolarMutexGuard aGuard; + m_xListener.clear(); +} + +//------------------------------------------------------------------------------------ +// XFilePreview functions +//------------------------------------------------------------------------------------ + +Sequence< sal_Int16 > SAL_CALL SvtFilePicker::getSupportedImageFormats() + throw ( RuntimeException ) +{ + checkAlive(); + + SolarMutexGuard aGuard; + Sequence< sal_Int16 > aFormats( 1 ); + + aFormats[0] = FilePreviewImageFormats::BITMAP; + + return aFormats; +} + +//------------------------------------------------------------------------------------ +sal_Int32 SAL_CALL SvtFilePicker::getTargetColorDepth() throw ( RuntimeException ) +{ + checkAlive(); + + SolarMutexGuard aGuard; + sal_Int32 nDepth = 0; + + if ( getDialog() ) + nDepth = getDialog()->getTargetColorDepth(); + + return nDepth; +} + +//------------------------------------------------------------------------------------ +sal_Int32 SAL_CALL SvtFilePicker::getAvailableWidth() throw ( RuntimeException ) +{ + checkAlive(); + + SolarMutexGuard aGuard; + sal_Int32 nWidth = 0; + + if ( getDialog() ) + nWidth = getDialog()->getAvailableWidth(); + + return nWidth; +} + +//------------------------------------------------------------------------------------ +sal_Int32 SAL_CALL SvtFilePicker::getAvailableHeight() throw ( RuntimeException ) +{ + checkAlive(); + + SolarMutexGuard aGuard; + sal_Int32 nHeigth = 0; + + if ( getDialog() ) + nHeigth = getDialog()->getAvailableHeight(); + + return nHeigth; +} + +//------------------------------------------------------------------------------------ +void SAL_CALL SvtFilePicker::setImage( sal_Int16 aImageFormat, const Any& rImage ) + throw ( IllegalArgumentException, RuntimeException ) +{ + checkAlive(); + + SolarMutexGuard aGuard; + if ( getDialog() ) + getDialog()->setImage( aImageFormat, rImage ); +} + +//------------------------------------------------------------------------------------ +sal_Bool SAL_CALL SvtFilePicker::setShowState( sal_Bool bShowState ) + throw ( RuntimeException ) +{ + checkAlive(); + + SolarMutexGuard aGuard; + sal_Bool bRet = sal_False; + + if ( getDialog() ) + bRet = getDialog()->setShowState( bShowState ); + + return bRet; +} + +//------------------------------------------------------------------------------------ +sal_Bool SAL_CALL SvtFilePicker::getShowState() throw ( RuntimeException ) +{ + checkAlive(); + + SolarMutexGuard aGuard; + sal_Bool bRet = sal_False; + + if ( getDialog() ) + bRet = getDialog()->getShowState(); + + return bRet; +} + +//------------------------------------------------------------------------------------ +// XFilterGroupManager functions +//------------------------------------------------------------------------------------ + +void SAL_CALL SvtFilePicker::appendFilterGroup( const ::rtl::OUString& sGroupTitle, + const Sequence< StringPair >& aFilters ) + throw ( IllegalArgumentException, RuntimeException ) +{ + checkAlive(); + + SolarMutexGuard aGuard; + + // check the names + if ( FilterNameExists( aFilters ) ) + throw IllegalArgumentException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("filter name exists")), + static_cast< OWeakObject * >(this), 1); + + // ensure that we have a filter list + ::rtl::OUString sInitialCurrentFilter; + if ( aFilters.getLength() ) + sInitialCurrentFilter = aFilters[0].First; + ensureFilterList( sInitialCurrentFilter ); + + // append the filter + m_pFilterList->insert( m_pFilterList->end(), FilterEntry( sGroupTitle, aFilters ) ); +} + +//------------------------------------------------------------------------------------ +// XFilterManager functions +//------------------------------------------------------------------------------------ + +void SAL_CALL SvtFilePicker::appendFilter( const rtl::OUString& aTitle, + const rtl::OUString& aFilter ) + throw( IllegalArgumentException, RuntimeException ) +{ + checkAlive(); + + SolarMutexGuard aGuard; + // check the name + if ( FilterNameExists( aTitle ) ) + // TODO: a more precise exception message + throw IllegalArgumentException(); + + // ensure that we have a filter list + ensureFilterList( aTitle ); + + // append the filter + m_pFilterList->insert( m_pFilterList->end(), FilterEntry( aTitle, aFilter ) ); +} + +//------------------------------------------------------------------------------------ +void SAL_CALL SvtFilePicker::setCurrentFilter( const rtl::OUString& aTitle ) + throw( IllegalArgumentException, RuntimeException ) +{ + checkAlive(); + + SolarMutexGuard aGuard; + if ( ! FilterNameExists( aTitle ) ) + throw IllegalArgumentException(); + + m_aCurrentFilter = aTitle; + + if ( getDialog() ) + getDialog()->SetCurFilter( aTitle ); +} + +//------------------------------------------------------------------------------------ +rtl::OUString SAL_CALL SvtFilePicker::getCurrentFilter() + throw( RuntimeException ) +{ + checkAlive(); + + SolarMutexGuard aGuard; + rtl::OUString aFilter = getDialog() ? rtl::OUString( getDialog()->GetCurFilter() ) : + rtl::OUString( m_aCurrentFilter ); + return aFilter; +} + + +//------------------------------------------------------------------------------------ +// XInitialization functions +//------------------------------------------------------------------------------------ + +void SAL_CALL SvtFilePicker::initialize( const Sequence< Any >& _rArguments ) + throw ( Exception, RuntimeException ) +{ + checkAlive(); + + Sequence< Any > aArguments( _rArguments.getLength()); + + m_nServiceType = TemplateDescription::FILEOPEN_SIMPLE; + + if ( _rArguments.getLength() >= 1 ) + { + // compatibility: one argument, type sal_Int16 , specifies the service type + int index = 0; + + if (_rArguments[0] >>= m_nServiceType) + { + // skip the first entry if it was the ServiceType, because it's not needed in OCommonPicker::initialize and it's not a NamedValue + NamedValue emptyNamedValue; + aArguments[0] <<= emptyNamedValue; + index = 1; + + } + for ( int i = index; i < _rArguments.getLength(); i++) + { + NamedValue namedValue; + aArguments[i] <<= _rArguments[i]; + + if (aArguments[i] >>= namedValue ) + { + + if ( namedValue.Name.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StandardDir" ) ) ) ) + { + ::rtl::OUString sStandardDir; + + namedValue.Value >>= sStandardDir; + + // Set the directory for the "back to the default dir" button + if ( sStandardDir.getLength() > 0 ) + { + m_aStandardDir = sStandardDir; + } + } + else if ( namedValue.Name.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BlackList" ) ) ) ) + { + namedValue.Value >>= m_aBlackList; + } + } + } + } + + // let the base class analyze the sequence (will call into implHandleInitializationArgument) + OCommonPicker::initialize( aArguments ); +} + +//------------------------------------------------------------------------- +sal_Bool SvtFilePicker::implHandleInitializationArgument( const ::rtl::OUString& _rName, const Any& _rValue ) SAL_THROW( ( Exception, RuntimeException ) ) +{ + if ( _rName.equalsAscii( "TemplateDescription" ) ) + { + m_nServiceType = TemplateDescription::FILEOPEN_SIMPLE; + OSL_VERIFY( _rValue >>= m_nServiceType ); + return sal_True; + } + if ( _rName.equalsAscii( "StandardDir" ) ) + { + OSL_VERIFY( _rValue >>= m_aStandardDir ); + return sal_True; + } + + if ( _rName.equalsAscii( "BlackList" ) ) + { + OSL_VERIFY( _rValue >>= m_aBlackList ); + return sal_True; + } + + + + return OCommonPicker::implHandleInitializationArgument( _rName, _rValue ); +} + +//------------------------------------------------------------------------------------ +// XServiceInfo +//------------------------------------------------------------------------------------ + +/* XServiceInfo */ +rtl::OUString SAL_CALL SvtFilePicker::getImplementationName() throw( RuntimeException ) +{ + return impl_getStaticImplementationName(); +} + +/* XServiceInfo */ +sal_Bool SAL_CALL SvtFilePicker::supportsService( const rtl::OUString& sServiceName ) throw( RuntimeException ) +{ + Sequence< rtl::OUString > seqServiceNames = getSupportedServiceNames(); + const rtl::OUString* pArray = seqServiceNames.getConstArray(); + for ( sal_Int32 i = 0; i < seqServiceNames.getLength(); i++ ) + { + if ( sServiceName == pArray[i] ) + { + return sal_True ; + } + } + return sal_False ; +} + +/* XServiceInfo */ +Sequence< rtl::OUString > SAL_CALL SvtFilePicker::getSupportedServiceNames() throw( RuntimeException ) +{ + return impl_getStaticSupportedServiceNames(); +} + +/* Helper for XServiceInfo */ +Sequence< rtl::OUString > SvtFilePicker::impl_getStaticSupportedServiceNames() +{ + Sequence< rtl::OUString > seqServiceNames( 1 ); + rtl::OUString* pArray = seqServiceNames.getArray(); + pArray[0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.OfficeFilePicker" )); + return seqServiceNames ; +} + +/* Helper for XServiceInfo */ +rtl::OUString SvtFilePicker::impl_getStaticImplementationName() +{ + return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.svtools.OfficeFilePicker" )); +} + +/* Helper for registry */ +Reference< XInterface > SAL_CALL SvtFilePicker::impl_createInstance( + const Reference< XComponentContext >& rxContext) throw( Exception ) +{ + Reference< XMultiServiceFactory > xServiceManager (rxContext->getServiceManager(), UNO_QUERY_THROW); + return Reference< XInterface >( *new SvtFilePicker( xServiceManager ) ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/office/OfficeFilePicker.hxx b/fpicker/source/office/OfficeFilePicker.hxx new file mode 100644 index 000000000000..360e497090b0 --- /dev/null +++ b/fpicker/source/office/OfficeFilePicker.hxx @@ -0,0 +1,230 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef INCLUDED_SVT_FILEPICKER_HXX +#define INCLUDED_SVT_FILEPICKER_HXX + +#include <cppuhelper/implbase7.hxx> +#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerNotifier.hpp> +#include <com/sun/star/ui/dialogs/XFilePreview.hpp> +#include <com/sun/star/ui/dialogs/XFilterManager.hpp> +#include <com/sun/star/ui/dialogs/XFilterGroupManager.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerListener.hpp> +#include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XEventListener.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + + +#include <vcl/wintypes.hxx> +#include "commonpicker.hxx" +#include "pickercallbacks.hxx" + +#include <list> + +class Dialog; + +struct FilterEntry; +struct ElementEntry_Impl; + +typedef ::std::list< FilterEntry > FilterList; // can be maintained more effectively +typedef ::std::list < ElementEntry_Impl > ElementList; + +typedef ::com::sun::star::beans::StringPair UnoFilterEntry; +typedef ::com::sun::star::uno::Sequence< UnoFilterEntry > UnoFilterList; // can be transported more effectively +typedef ::com::sun::star::uno::Sequence< ::rtl::OUString > OUStringList; // can be transported more effectively + +// class SvtFilePicker --------------------------------------------------- + +typedef ::cppu::ImplHelper7 < ::com::sun::star::ui::dialogs::XFilePickerControlAccess + , ::com::sun::star::ui::dialogs::XFilePickerNotifier + , ::com::sun::star::ui::dialogs::XFilePreview + , ::com::sun::star::ui::dialogs::XFilterManager + , ::com::sun::star::ui::dialogs::XFilterGroupManager + , ::com::sun::star::lang::XServiceInfo + , ::com::sun::star::ui::dialogs::XAsynchronousExecutableDialog + > SvtFilePicker_Base; + +class SvtFilePicker :public SvtFilePicker_Base + ,public ::svt::OCommonPicker + ,public ::svt::IFilePickerListener +{ +private: + FilterList* m_pFilterList; + ElementList* m_pElemList; + + sal_Bool m_bMultiSelection; + sal_Int16 m_nServiceType; + ::rtl::OUString m_aDefaultName; + ::rtl::OUString m_aCurrentFilter; + + // #97148# -------------- + ::rtl::OUString m_aOldDisplayDirectory; + ::rtl::OUString m_aOldHideDirectory; + + ::rtl::OUString m_aStandardDir; + OUStringList m_aBlackList; + + ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener > + m_xListener; + ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XDialogClosedListener > + m_xDlgClosedListener; + +public: + SvtFilePicker( const ::com::sun::star::uno::Reference < ::com::sun::star::lang::XMultiServiceFactory >& xFactory ); + virtual ~SvtFilePicker(); + + //------------------------------------------------------------------------------------ + // disambiguate XInterface + //------------------------------------------------------------------------------------ + DECLARE_XINTERFACE( ) + + //------------------------------------------------------------------------------------ + // disambiguate XTypeProvider + //------------------------------------------------------------------------------------ + DECLARE_XTYPEPROVIDER( ) + + //------------------------------------------------------------------------------------ + // XExecutableDialog functions + //------------------------------------------------------------------------------------ + virtual void SAL_CALL setTitle( const ::rtl::OUString& _rTitle ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL execute( ) throw (::com::sun::star::uno::RuntimeException); + + //------------------------------------------------------------------------------------ + // XAsynchronousExecutableDialog functions + //------------------------------------------------------------------------------------ + virtual void SAL_CALL setDialogTitle( const ::rtl::OUString& _rTitle ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL startExecuteModal( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XDialogClosedListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + + //------------------------------------------------------------------------------------ + // XFilePicker functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setMultiSelectionMode( sal_Bool bMode ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setDefaultName( const ::rtl::OUString& aName ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setDisplayDirectory( const ::rtl::OUString& aDirectory ) throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + virtual ::rtl::OUString SAL_CALL getDisplayDirectory() throw( ::com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getFiles() throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFilePickerControlAccess functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setValue( sal_Int16 ElementID, sal_Int16 ControlAction, const com::sun::star::uno::Any& value ) throw( ::com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Any SAL_CALL getValue( sal_Int16 ElementID, sal_Int16 ControlAction ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setLabel( sal_Int16 ElementID, const ::rtl::OUString& aValue ) throw ( ::com::sun::star::uno::RuntimeException ); + virtual ::rtl::OUString SAL_CALL getLabel( sal_Int16 ElementID ) throw ( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL enableControl( sal_Int16 ElementID, sal_Bool bEnable ) throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFilePickerNotifier functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL addFilePickerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener >& xListener ) throw ( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL removeFilePickerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener >& xListener ) throw ( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFilePreview functions + //------------------------------------------------------------------------------------ + + virtual com::sun::star::uno::Sequence< sal_Int16 > SAL_CALL getSupportedImageFormats() throw ( ::com::sun::star::uno::RuntimeException ); + virtual sal_Int32 SAL_CALL getTargetColorDepth() throw ( ::com::sun::star::uno::RuntimeException ); + virtual sal_Int32 SAL_CALL getAvailableWidth() throw ( ::com::sun::star::uno::RuntimeException ); + virtual sal_Int32 SAL_CALL getAvailableHeight() throw ( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setImage( sal_Int16 aImageFormat, const com::sun::star::uno::Any& aImage ) throw ( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL setShowState( sal_Bool bShowState ) throw ( ::com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL getShowState() throw ( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFilterManager functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL appendFilter( const ::rtl::OUString& aTitle, const ::rtl::OUString& aFilter ) throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setCurrentFilter( const ::rtl::OUString& aTitle ) throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + virtual ::rtl::OUString SAL_CALL getCurrentFilter() throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFilterGroupManager functions + //------------------------------------------------------------------------------------ + virtual void SAL_CALL appendFilterGroup( const ::rtl::OUString& sGroupTitle, const com::sun::star::uno::Sequence< com::sun::star::beans::StringPair >& aFilters ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + //------------------------------------------------------------------------------------ + // XInitialization functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL initialize( const com::sun::star::uno::Sequence< com::sun::star::uno::Any >& aArguments ) throw ( com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XServiceInfo functions + //------------------------------------------------------------------------------------ + + /* XServiceInfo */ + virtual ::rtl::OUString SAL_CALL getImplementationName() throw( ::com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& sServiceName ) throw( ::com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames() throw( ::com::sun::star::uno::RuntimeException ); + + /* Helper for XServiceInfo */ + static com::sun::star::uno::Sequence< ::rtl::OUString > + impl_getStaticSupportedServiceNames(); + static ::rtl::OUString impl_getStaticImplementationName(); + + /* Helper for registry */ + static ::com::sun::star::uno::Reference< com::sun::star::uno::XInterface > SAL_CALL impl_createInstance ( + const ::com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >& rxContext ) + throw( com::sun::star::uno::Exception ); + +protected: + //------------------------------------------------------------------------------------ + // OCommonPicker overridables + //------------------------------------------------------------------------------------ + virtual SvtFileDialog* implCreateDialog( Window* _pParent ); + virtual sal_Int16 implExecutePicker( ); + virtual sal_Bool implHandleInitializationArgument( + const ::rtl::OUString& _rName, + const ::com::sun::star::uno::Any& _rValue + ) + SAL_THROW( ( ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException ) ); + +private: + WinBits getWinBits( WinBits& rExtraBits ); + virtual void notify( sal_Int16 _nEventId, sal_Int16 _nControlId ); + + sal_Bool FilterNameExists( const ::rtl::OUString& rTitle ); + sal_Bool FilterNameExists( const UnoFilterList& _rGroupedFilters ); + + void ensureFilterList( const ::rtl::OUString& _rInitialCurrentFilter ); + + void prepareExecute( ); + + DECL_LINK( DialogClosedHdl, Dialog* ); +}; + +#endif // INCLUDED_SVT_FILEPICKER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/office/OfficeFilePicker.src b/fpicker/source/office/OfficeFilePicker.src new file mode 100644 index 000000000000..8fbbc35a40e5 --- /dev/null +++ b/fpicker/source/office/OfficeFilePicker.src @@ -0,0 +1,99 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "svtools/svtools.hrc" + +String STR_SVT_FILEPICKER_AUTO_EXTENSION +{ + Text [ en-US ] = "~Automatic file name extension" ; +}; + +String STR_SVT_FILEPICKER_PASSWORD +{ + Text [ en-US ] = "Save with pass~word" ; +}; + +String STR_SVT_FILEPICKER_FILTER_OPTIONS +{ + Text [ en-US ] = "~Edit filter settings"; +}; + +String STR_SVT_FILEPICKER_READONLY +{ + Text [ en-US ] = "~Read-only" ; +}; + +String STR_SVT_FILEPICKER_INSERT_AS_LINK +{ + Text [ en-US ] = "~Link" ; +}; + +String STR_SVT_FILEPICKER_SHOW_PREVIEW +{ + Text [ en-US ] = "Pr~eview" ; +}; + +String STR_SVT_FILEPICKER_PLAY +{ + Text [ en-US ] = "~Play" ; +}; + +String STR_SVT_FILEPICKER_VERSION +{ + Text [ en-US ] = "~Version:"; +}; + +String STR_SVT_FILEPICKER_TEMPLATES +{ + Text [ en-US ] = "S~tyles:" ; +}; + +String STR_SVT_FILEPICKER_IMAGE_TEMPLATE +{ + Text [ en-US ] = "Style:"; +}; + +String STR_SVT_FILEPICKER_SELECTION +{ + Text [ en-US ] = "~Selection" ; +}; + +String STR_SVT_FILEPICKER_FILTER_TITLE +{ + Text [ en-US ] = "File ~type:" ; +}; + +String STR_SVT_FOLDERPICKER_DEFAULT_TITLE +{ + Text [ en-US ] = "Select Path" ; +}; + +String STR_SVT_FOLDERPICKER_DEFAULT_DESCRIPTION +{ + Text [ en-US ] = "Please select a folder."; +}; + diff --git a/fpicker/source/office/OfficeFolderPicker.cxx b/fpicker/source/office/OfficeFolderPicker.cxx new file mode 100644 index 000000000000..945616b5ec4a --- /dev/null +++ b/fpicker/source/office/OfficeFolderPicker.cxx @@ -0,0 +1,267 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +#include "OfficeFolderPicker.hxx" + +#include "iodlg.hxx" + +#include <list> +#include <tools/urlobj.hxx> + +#define _SVSTDARR_STRINGSDTOR +#include "svl/svstdarr.hxx" +#include <com/sun/star/container/XContentEnumerationAccess.hpp> +#include <com/sun/star/container/XSet.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <cppuhelper/factory.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <unotools/pathoptions.hxx> + +// using ---------------------------------------------------------------- + +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; + +//------------------------------------------------------------------------------------ +// class SvtFolderPicker +//------------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------------ +SvtFolderPicker::SvtFolderPicker( const Reference < XMultiServiceFactory >& _rxFactory ) + :OCommonPicker( _rxFactory ) +{ +} + +//------------------------------------------------------------------------------------ +SvtFolderPicker::~SvtFolderPicker() +{ +} + +//------------------------------------------------------------------------------------ +// disambiguate XInterface +//------------------------------------------------------------------------------------ +IMPLEMENT_FORWARD_XINTERFACE2( SvtFolderPicker, OCommonPicker, SvtFolderPicker_Base ) + +//------------------------------------------------------------------------------------ +// disambiguate XTypeProvider +//------------------------------------------------------------------------------------ +IMPLEMENT_FORWARD_XTYPEPROVIDER2( SvtFolderPicker, OCommonPicker, SvtFolderPicker_Base ) + +//------------------------------------------------------------------------------------ +// XExecutableDialog functions +//------------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------------ +void SAL_CALL SvtFolderPicker::setTitle( const ::rtl::OUString& _rTitle ) throw (RuntimeException) +{ + OCommonPicker::setTitle( _rTitle ); +} + +//------------------------------------------------------------------------------------ +sal_Int16 SAL_CALL SvtFolderPicker::execute( ) throw (RuntimeException) +{ + return OCommonPicker::execute(); +} + +//------------------------------------------------------------------------------------ +// XAsynchronousExecutableDialog functions +//------------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------------ +void SAL_CALL SvtFolderPicker::setDialogTitle( const ::rtl::OUString& _rTitle) throw (RuntimeException) +{ + setTitle( _rTitle ); +} + +//------------------------------------------------------------------------------------ +void SAL_CALL SvtFolderPicker::startExecuteModal( const Reference< ::com::sun::star::ui::dialogs::XDialogClosedListener >& xListener ) throw (RuntimeException) +{ + m_xListener = xListener; + prepareDialog(); + prepareExecute(); + getDialog()->EnableAutocompletion( TRUE ); + getDialog()->StartExecuteModal( LINK( this, SvtFolderPicker, DialogClosedHdl ) ); +} + +//------------------------------------------------------------------------------------ +SvtFileDialog* SvtFolderPicker::implCreateDialog( Window* _pParent ) +{ + return new SvtFileDialog( _pParent, SFXWB_PATHDIALOG ); +} + +//------------------------------------------------------------------------------------ +sal_Int16 SvtFolderPicker::implExecutePicker( ) +{ + prepareExecute(); + + // now we are ready to execute the dialog + getDialog()->EnableAutocompletion( FALSE ); + sal_Int16 nRet = getDialog()->Execute(); + + return nRet; +} + +//------------------------------------------------------------------------------------ +void SvtFolderPicker::prepareExecute() +{ + // set the default directory + if ( m_aDisplayDirectory.getLength() > 0 ) + getDialog()->SetPath( m_aDisplayDirectory ); + else + { + // Default-Standard-Dir setzen + INetURLObject aStdDirObj( SvtPathOptions().GetWorkPath() ); + getDialog()->SetPath( aStdDirObj.GetMainURL( INetURLObject::NO_DECODE) ); + } +} + +//----------------------------------------------------------------------------- +IMPL_LINK( SvtFolderPicker, DialogClosedHdl, Dialog*, pDlg ) +{ + if ( m_xListener.is() ) + { + sal_Int16 nRet = static_cast< sal_Int16 >( pDlg->GetResult() ); + ::com::sun::star::ui::dialogs::DialogClosedEvent aEvent( *this, nRet ); + m_xListener->dialogClosed( aEvent ); + m_xListener.clear(); + } + return 0; + } + +//------------------------------------------------------------------------------------ +// XFolderPicker functions +//------------------------------------------------------------------------------------ + +void SAL_CALL SvtFolderPicker::setDisplayDirectory( const ::rtl::OUString& aDirectory ) + throw( IllegalArgumentException, RuntimeException ) +{ + m_aDisplayDirectory = aDirectory; +} + +//------------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL SvtFolderPicker::getDisplayDirectory() throw( RuntimeException ) +{ + ::rtl::OUString aResult; + + if ( ! getDialog() ) + return m_aDisplayDirectory; + + SvStringsDtor* pPathList = getDialog()->GetPathList(); + + if ( pPathList->Count() ) + aResult = ::rtl::OUString( *pPathList->GetObject( 0 ) ); + + delete pPathList; + + return aResult; +} + +//------------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL SvtFolderPicker::getDirectory() throw( RuntimeException ) +{ + ::rtl::OUString aResult; + + if ( ! getDialog() ) + return m_aDisplayDirectory; + + SvStringsDtor* pPathList = getDialog()->GetPathList(); + + if ( pPathList->Count() ) + aResult = ::rtl::OUString( *pPathList->GetObject( 0 ) ); + + delete pPathList; + + return aResult; +} + +//------------------------------------------------------------------------------------ +void SAL_CALL SvtFolderPicker::setDescription( const ::rtl::OUString& aDescription ) + throw( RuntimeException ) +{ + m_aDescription = aDescription; +} + +//------------------------------------------------------------------------------------ +// XServiceInfo +//------------------------------------------------------------------------------------ + +/* XServiceInfo */ +::rtl::OUString SAL_CALL SvtFolderPicker::getImplementationName() throw( RuntimeException ) +{ + return impl_getStaticImplementationName(); +} + +/* XServiceInfo */ +sal_Bool SAL_CALL SvtFolderPicker::supportsService( const ::rtl::OUString& sServiceName ) throw( RuntimeException ) +{ + Sequence< ::rtl::OUString > seqServiceNames = getSupportedServiceNames(); + const ::rtl::OUString* pArray = seqServiceNames.getConstArray(); + for ( sal_Int32 i = 0; i < seqServiceNames.getLength(); i++ ) + { + if ( sServiceName == pArray[i] ) + { + return sal_True ; + } + } + return sal_False ; +} + +/* XServiceInfo */ +Sequence< ::rtl::OUString > SAL_CALL SvtFolderPicker::getSupportedServiceNames() throw( RuntimeException ) +{ + return impl_getStaticSupportedServiceNames(); +} + +/* Helper for XServiceInfo */ +Sequence< ::rtl::OUString > SvtFolderPicker::impl_getStaticSupportedServiceNames() +{ + Sequence< ::rtl::OUString > seqServiceNames(1); + seqServiceNames[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.OfficeFolderPicker" )); + return seqServiceNames ; +} + +/* Helper for XServiceInfo */ +::rtl::OUString SvtFolderPicker::impl_getStaticImplementationName() +{ + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.svtools.OfficeFolderPicker" )); +} + +/* Helper for registry */ +Reference< XInterface > SAL_CALL SvtFolderPicker::impl_createInstance( const Reference< XComponentContext >& rxContext ) + throw( Exception ) +{ + Reference< XMultiServiceFactory > xServiceManager (rxContext->getServiceManager(), UNO_QUERY_THROW); + return Reference< XInterface >( *new SvtFolderPicker( xServiceManager ) ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/office/OfficeFolderPicker.hxx b/fpicker/source/office/OfficeFolderPicker.hxx new file mode 100644 index 000000000000..273f971edb5a --- /dev/null +++ b/fpicker/source/office/OfficeFolderPicker.hxx @@ -0,0 +1,125 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef INCLUDED_SVT_FOLDERPICKER_HXX +#define INCLUDED_SVT_FOLDERPICKER_HXX + +#include <cppuhelper/implbase3.hxx> +#include <com/sun/star/ui/dialogs/XFolderPicker.hpp> +#include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include "commonpicker.hxx" + +class Dialog; + +// class SvtFolderPicker --------------------------------------------------- + +typedef ::cppu::ImplHelper3 < ::com::sun::star::ui::dialogs::XFolderPicker + , ::com::sun::star::ui::dialogs::XAsynchronousExecutableDialog + , ::com::sun::star::lang::XServiceInfo + > SvtFolderPicker_Base; + +class SvtFolderPicker :public SvtFolderPicker_Base + ,public ::svt::OCommonPicker +{ +private: + ::rtl::OUString m_aDescription; + + ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XDialogClosedListener > + m_xListener; + + void prepareExecute( ); + DECL_LINK( DialogClosedHdl, Dialog* ); + +public: + SvtFolderPicker( const ::com::sun::star::uno::Reference < ::com::sun::star::lang::XMultiServiceFactory >& xFactory ); + virtual ~SvtFolderPicker(); + + //------------------------------------------------------------------------------------ + // disambiguate XInterface + //------------------------------------------------------------------------------------ + DECLARE_XINTERFACE( ) + + //------------------------------------------------------------------------------------ + // disambiguate XTypeProvider + //------------------------------------------------------------------------------------ + DECLARE_XTYPEPROVIDER( ) + + //------------------------------------------------------------------------------------ + // XFolderPicker functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setDisplayDirectory( const ::rtl::OUString& aDirectory ) throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + virtual ::rtl::OUString SAL_CALL getDisplayDirectory() throw( ::com::sun::star::uno::RuntimeException ); + virtual ::rtl::OUString SAL_CALL getDirectory() throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setDescription( const ::rtl::OUString& aDescription ) throw ( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XExecutableDialog functions + //------------------------------------------------------------------------------------ + virtual void SAL_CALL setTitle( const ::rtl::OUString& _rTitle ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL execute( ) throw (::com::sun::star::uno::RuntimeException); + + //------------------------------------------------------------------------------------ + // XAsynchronousExecutableDialog functions + //------------------------------------------------------------------------------------ + virtual void SAL_CALL setDialogTitle( const ::rtl::OUString& _rTitle ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL startExecuteModal( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XDialogClosedListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + + //------------------------------------------------------------------------------------ + // XServiceInfo functions + //------------------------------------------------------------------------------------ + + /* XServiceInfo */ + virtual ::rtl::OUString SAL_CALL getImplementationName() throw( ::com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& sServiceName ) throw( ::com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames() throw( ::com::sun::star::uno::RuntimeException ); + + /* Helper for XServiceInfo */ + static com::sun::star::uno::Sequence< ::rtl::OUString > impl_getStaticSupportedServiceNames(); + static ::rtl::OUString impl_getStaticImplementationName(); + + /* Helper for registry */ + static ::com::sun::star::uno::Reference< com::sun::star::uno::XInterface > SAL_CALL impl_createInstance ( + const ::com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >& rxContext ) + throw( com::sun::star::uno::Exception ); + +protected: + //------------------------------------------------------------------------------------ + // OCommonPicker overridables + //------------------------------------------------------------------------------------ + virtual SvtFileDialog* implCreateDialog( Window* _pParent ); + virtual sal_Int16 implExecutePicker( ); +}; + +#endif // INCLUDED_SVT_FOLDERPICKER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/office/asyncfilepicker.cxx b/fpicker/source/office/asyncfilepicker.cxx new file mode 100644 index 000000000000..330eaebe26b2 --- /dev/null +++ b/fpicker/source/office/asyncfilepicker.cxx @@ -0,0 +1,222 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +#include "asyncfilepicker.hxx" +#include "iodlg.hxx" +#include "svtools/fileview.hxx" +#include <tools/debug.hxx> + +#include <memory> + +//........................................................................ +namespace svt +{ +//........................................................................ + + //==================================================================== + //= AsyncPickerAction + //==================================================================== + DBG_NAME( AsyncPickerAction ) + //-------------------------------------------------------------------- + AsyncPickerAction::AsyncPickerAction( SvtFileDialog* _pDialog, SvtFileView* _pView, const Action _eAction ) + :m_refCount ( 0 ) + ,m_eAction ( _eAction ) + ,m_pView ( _pView ) + ,m_pDialog ( _pDialog ) + ,m_bRunning ( false ) + { + DBG_CTOR( AsyncPickerAction, NULL ); + DBG_ASSERT( m_pDialog, "AsyncPickerAction::AsyncPickerAction: invalid dialog!" ); + DBG_ASSERT( m_pView, "AsyncPickerAction::AsyncPickerAction: invalid view!" ); + } + + //-------------------------------------------------------------------- + AsyncPickerAction::~AsyncPickerAction() + { + DBG_DTOR( AsyncPickerAction, NULL ); + } + + //-------------------------------------------------------------------- + oslInterlockedCount SAL_CALL AsyncPickerAction::acquire() + { + return osl_incrementInterlockedCount( &m_refCount ); + } + + //-------------------------------------------------------------------- + oslInterlockedCount SAL_CALL AsyncPickerAction::release() + { + if ( 0 == osl_decrementInterlockedCount( &m_refCount ) ) + { + delete this; + return 0; + } + return m_refCount; + } + + //-------------------------------------------------------------------- + void AsyncPickerAction::cancel() + { + DBG_TESTSOLARMUTEX(); + // if this asserts, we'd need to have an own mutex per instance + + OSL_ENSURE( m_bRunning, "AsyncPickerAction::cancel: not running" ); + if ( m_pView ) + m_pView->CancelRunningAsyncAction(); + } + + //-------------------------------------------------------------------- + void AsyncPickerAction::execute( + const String& _rURL, + const String& _rFilter, + sal_Int32 _nMinTimeout, + sal_Int32 _nMaxTimeout, + const OUStringList& rBlackList ) + { + DBG_TESTSOLARMUTEX(); + // if this asserts, we'd need to have an own mutex per instance + + sal_Int32 nMinTimeout = _nMinTimeout; + sal_Int32 nMaxTimeout = _nMaxTimeout; + // normalizations + if ( nMinTimeout < 0 ) + // if negative, this is considered as "do it synchronously" + nMinTimeout = 0; + else if ( nMinTimeout < 1000 ) + nMinTimeout = 1000; + if ( nMaxTimeout <= nMinTimeout ) + nMaxTimeout = nMinTimeout + 30000; + + ::std::auto_ptr< FileViewAsyncAction > pActionDescriptor; + if ( nMinTimeout ) + { + pActionDescriptor.reset( new FileViewAsyncAction ); + pActionDescriptor->nMinTimeout = nMinTimeout; + pActionDescriptor->nMaxTimeout = nMaxTimeout; + pActionDescriptor->aFinishHandler = LINK( this, AsyncPickerAction, OnActionDone ); + } + + FileViewResult eResult = eFailure; + m_sURL = _rURL; + switch ( m_eAction ) + { + case ePrevLevel: + eResult = m_pView->PreviousLevel( pActionDescriptor.get() ); + break; + + case eOpenURL: + eResult = m_pView->Initialize( _rURL, _rFilter, pActionDescriptor.get(), rBlackList ); + break; + + case eExecuteFilter: + // preserve the filename (FS: why?) + m_sFileName = m_pDialog->getCurrentFileText(); + // execute the new filter + eResult = m_pView->ExecuteFilter( _rFilter, pActionDescriptor.get() ); + break; + + default: + DBG_ERROR( "AsyncPickerAction::execute: unknown action!" ); + break; + } + + acquire(); + if ( ( eResult == eSuccess ) || ( eResult == eFailure ) ) + { + // the handler is only called if the action could not be finished within + // the given minimum time period. In case of success, we need to call it + // explicitly + OnActionDone( reinterpret_cast< void* >( eResult ) ); + } + else if ( eResult == eStillRunning ) + { + m_bRunning = true; + m_pDialog->onAsyncOperationStarted(); + } + } + + //-------------------------------------------------------------------- + IMPL_LINK( AsyncPickerAction, OnActionDone, void*, pEmptyArg ) + { + DBG_TESTSOLARMUTEX(); + // if this asserts, we'd need to have an own mutex per instance + + FileViewResult eResult = static_cast< FileViewResult >( reinterpret_cast< sal_IntPtr >( pEmptyArg ) ); + OSL_ENSURE( eStillRunning != eResult, "AsyncPickerAction::OnActionDone: invalid result!" ); + + // release once (since we acquired in |execute|), but keep alive until the + // end of the method + ::rtl::Reference< AsyncPickerAction > xKeepAlive( this ); + release(); + + m_pDialog->onAsyncOperationFinished(); + m_bRunning = true; + + if ( eFailure == eResult ) + // TODO: do we need some kind of cleanup here? + return 0L; + + if ( eTimeout == eResult ) + { + m_pDialog->displayIOException( m_sURL, ::com::sun::star::ucb::IOErrorCode_CANT_READ ); + return 0L; + } + + OSL_ENSURE( eSuccess == eResult, "AsyncPickerAction::OnActionDone: what else valid results are there?" ); + + switch ( m_eAction ) + { + case ePrevLevel: + case eOpenURL: + m_pDialog->UpdateControls( m_pView->GetViewURL() ); + break; + + case eExecuteFilter: + // restore the filename + m_pView->SetNoSelection(); + m_pDialog->setCurrentFileText( m_sFileName, true ); + + // notify listeners + m_pDialog->FilterSelect(); + break; + + default: + DBG_ERROR( "AsyncPickerAction::OnActionDone: unknown action!" ); + break; + } + + return 1L; + } + +//........................................................................ +} // namespace svt +//........................................................................ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/office/asyncfilepicker.hxx b/fpicker/source/office/asyncfilepicker.hxx new file mode 100644 index 000000000000..4ec9be11ec31 --- /dev/null +++ b/fpicker/source/office/asyncfilepicker.hxx @@ -0,0 +1,120 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SVTOOLS_SOURCE_FILEPICKER_ASYNCFILEPICKER_HXX +#define SVTOOLS_SOURCE_FILEPICKER_ASYNCFILEPICKER_HXX + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +#include <tools/link.hxx> +#include <tools/string.hxx> +#include <rtl/ref.hxx> +#include <rtl/ustring.hxx> +#include <com/sun/star/uno/Sequence.h> + +class SvtFileView; +class SvtFileDialog; + +typedef ::com::sun::star::uno::Sequence< ::rtl::OUString > OUStringList; + +//........................................................................ +namespace svt +{ +//........................................................................ + + + //==================================================================== + //= AsyncPickerAction + //==================================================================== + class AsyncPickerAction : public ::rtl::IReference + { + public: + enum Action + { + ePrevLevel, + eOpenURL, + eExecuteFilter + }; + + private: + mutable oslInterlockedCount m_refCount; + Action m_eAction; + SvtFileView* m_pView; + SvtFileDialog* m_pDialog; + String m_sURL; + String m_sFileName; + bool m_bRunning; + + public: + AsyncPickerAction( SvtFileDialog* _pDialog, SvtFileView* _pView, const Action _eAction ); + + /** executes the action + + @param _nMinTimeout + the minimum timeout to wait, in milliseconds. If negative, the action will we done + synchronously. If between 0 and 999, it will be corrected to 1000, means the + smallest valid value is 1000 (which equals one second). + @param _nMaxTimeout + The maximum time to wait for a result, in milliseconds. If there's no result of + the action within the given time frame, the action will be cancelled. + If smaller than or equal to <arg>_nMinTimeout</arg>, it will be corrected to + <arg>_nMinTimeout</arg> + 30000. + */ + void execute( + const String& _rURL, + const String& _rFilter, + sal_Int32 _nMinTimeout, + sal_Int32 _nMaxTimeout, + const OUStringList& rBlackList = OUStringList() ); + + /// cancels the running action + void cancel(); + + // IReference overridables + virtual oslInterlockedCount SAL_CALL acquire(); + virtual oslInterlockedCount SAL_CALL release(); + + protected: + virtual ~AsyncPickerAction(); + + private: + DECL_LINK( OnActionDone, void* ); + + AsyncPickerAction(); // never implemented + AsyncPickerAction( const AsyncPickerAction& ); // never implemented + AsyncPickerAction& operator=( const AsyncPickerAction& ); // never implemented + }; + +//........................................................................ +} // namespace svt +//........................................................................ + +#endif // SVTOOLS_SOURCE_FILEPICKER_ASYNCFILEPICKER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/office/commonpicker.cxx b/fpicker/source/office/commonpicker.cxx new file mode 100644 index 000000000000..59181a3db9e6 --- /dev/null +++ b/fpicker/source/office/commonpicker.cxx @@ -0,0 +1,508 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +#include "commonpicker.hxx" +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <vcl/svapp.hxx> +#include <osl/mutex.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <comphelper/weakeventlistener.hxx> +#include <comphelper/types.hxx> +#include <vcl/msgbox.hxx> +#include "iodlg.hxx" + +//......................................................................... +namespace svt +{ +//......................................................................... + +#define PROPERTY_ID_HELPURL 1 +#define PROPERTY_ID_WINDOW 2 + + // using -------------------------------------------------------------- + + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::ui::dialogs; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::comphelper; + + //--------------------------------------------------------------------- + OCommonPicker::OCommonPicker( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory ) + :OCommonPicker_Base( m_aMutex ) + ,OPropertyContainer( GetBroadcastHelper() ) + ,m_xORB( _rxFactory ) + ,m_pDlg( NULL ) + ,m_nCancelEvent( 0 ) + ,m_bExecuting( sal_False ) + { + // the two properties we have + registerProperty( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "HelpURL" )), PROPERTY_ID_HELPURL, + PropertyAttribute::TRANSIENT, + &m_sHelpURL, ::getCppuType( &m_sHelpURL ) + ); + + registerProperty( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Window" )), PROPERTY_ID_WINDOW, + PropertyAttribute::TRANSIENT | PropertyAttribute::READONLY, + &m_xWindow, ::getCppuType( &m_xWindow ) + ); + } + + //--------------------------------------------------------------------- + OCommonPicker::~OCommonPicker() + { + if ( !GetBroadcastHelper().bDisposed ) + { + acquire(); + dispose(); + } + } + + //--------------------------------------------------------------------- + // disambiguate XInterface + //--------------------------------------------------------------------- + IMPLEMENT_FORWARD_XINTERFACE2( OCommonPicker, OCommonPicker_Base, OPropertyContainer ) + + //--------------------------------------------------------------------- + // disambiguate XTypeProvider + //--------------------------------------------------------------------- + IMPLEMENT_FORWARD_XTYPEPROVIDER2( OCommonPicker, OCommonPicker_Base, OPropertyContainer ) + + //--------------------------------------------------------------------- + // XComponent related methods + //--------------------------------------------------------------------- + void OCommonPicker::checkAlive() const SAL_THROW( (DisposedException) ) + { + if ( GetBroadcastHelper().bInDispose || GetBroadcastHelper().bDisposed ) + throw DisposedException(); + } + + void OCommonPicker::prepareDialog() + { + if ( !getDialog() ) + createPicker(); + + // set the title + if ( m_aTitle.getLength() > 0 ) + getDialog()->SetText( m_aTitle ); + } + + //--------------------------------------------------------------------- + void SAL_CALL OCommonPicker::disposing() + { + SolarMutexGuard aGuard; + + stopWindowListening(); + + if ( m_nCancelEvent ) + Application::RemoveUserEvent( m_nCancelEvent ); + + { + ::osl::MutexGuard aOwnGuard( m_aMutex ); + if ( m_bExecuting && m_pDlg ) + m_pDlg->EndDialog( RET_CANCEL ); + } + + delete m_pDlg; + m_pDlg = NULL; + m_xWindow = NULL; + m_xDialogParent = NULL; + } + + //--------------------------------------------------------------------- + void OCommonPicker::stopWindowListening() + { + disposeComponent( m_xWindowListenerAdapter ); + disposeComponent( m_xParentListenerAdapter ); + } + + //--------------------------------------------------------------------- + // XEventListener + //--------------------------------------------------------------------- + void SAL_CALL OCommonPicker::disposing( const EventObject& _rSource ) throw (RuntimeException) + { + SolarMutexGuard aGuard; + sal_Bool bDialogDying = _rSource.Source == m_xWindow; + sal_Bool bParentDying = _rSource.Source == m_xDialogParent; + + if ( bDialogDying || bParentDying ) + { + stopWindowListening(); + + if ( !bDialogDying ) // it's the parent which is dying -> delete the dialog + delete m_pDlg; + + m_pDlg = NULL; + m_xWindow = NULL; + m_xDialogParent = NULL; + } + else + { + DBG_ERROR( "OCommonPicker::disposing: where did this come from?" ); + } + } + + //--------------------------------------------------------------------- + // property set related methods + //--------------------------------------------------------------------- + ::cppu::IPropertyArrayHelper* OCommonPicker::createArrayHelper( ) const + { + Sequence< Property > aProps; + describeProperties( aProps ); + return new cppu::OPropertyArrayHelper( aProps ); + } + + //--------------------------------------------------------------------- + ::cppu::IPropertyArrayHelper& SAL_CALL OCommonPicker::getInfoHelper() + { + return *const_cast< OCommonPicker* >( this )->getArrayHelper(); + } + + //--------------------------------------------------------------------- + Reference< XPropertySetInfo > SAL_CALL OCommonPicker::getPropertySetInfo( ) throw(RuntimeException) + { + return ::cppu::OPropertySetHelper::createPropertySetInfo( getInfoHelper() ); + } + + //--------------------------------------------------------------------- + void SAL_CALL OCommonPicker::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw (Exception) + { + OPropertyContainer::setFastPropertyValue_NoBroadcast( _nHandle, _rValue ); + + // if the HelpURL changed, forward this to the dialog + if ( PROPERTY_ID_HELPURL == _nHandle ) + if ( m_pDlg ) + OControlAccess::setHelpURL( m_pDlg, m_sHelpURL, sal_False ); + } + + + //--------------------------------------------------------------------- + sal_Bool OCommonPicker::createPicker() + { + SolarMutexGuard aGuard; + + if ( !m_pDlg ) + { + m_pDlg = implCreateDialog( VCLUnoHelper::GetWindow( m_xDialogParent ) ); + DBG_ASSERT( m_pDlg, "OCommonPicker::createPicker: invalid dialog returned!" ); + + if ( m_pDlg ) + { + // synchronize the help id of the dialog with out help URL property + if ( m_sHelpURL.getLength() ) + { // somebody already set the help URL while we had no dialog yet + OControlAccess::setHelpURL( m_pDlg, m_sHelpURL, sal_False ); + } + else + { + m_sHelpURL = OControlAccess::getHelpURL( m_pDlg, sal_False ); + } + + m_xWindow = VCLUnoHelper::GetInterface( m_pDlg ); + + // add as event listener to the window + Reference< XComponent > xWindowComp( m_xWindow, UNO_QUERY ); + OSL_ENSURE( xWindowComp.is(), "OCommonPicker::createFileDialog: invalid window component!" ); + if ( xWindowComp.is() ) + { + m_xWindowListenerAdapter = new OWeakEventListenerAdapter( this, xWindowComp ); + // the adapter will add itself as listener, and forward notifications + } + + // _and_ add as event listener to the parent - in case the parent is destroyed + // before we are disposed, our disposal would access dead VCL windows then .... + m_xDialogParent = VCLUnoHelper::GetInterface( m_pDlg->GetParent() ); + xWindowComp = xWindowComp.query( m_xDialogParent ); + OSL_ENSURE( xWindowComp.is() || !m_pDlg->GetParent(), "OCommonPicker::createFileDialog: invalid window component (the parent this time)!" ); + if ( xWindowComp.is() ) + { + m_xParentListenerAdapter = new OWeakEventListenerAdapter( this, xWindowComp ); + // the adapter will add itself as listener, and forward notifications + } + } + } + + return NULL != m_pDlg; + } + + //--------------------------------------------------------------------- + // XControlAccess functions + //--------------------------------------------------------------------- + void SAL_CALL OCommonPicker::setControlProperty( const ::rtl::OUString& aControlName, const ::rtl::OUString& aControlProperty, const Any& aValue ) throw (IllegalArgumentException, RuntimeException) + { + checkAlive(); + + SolarMutexGuard aGuard; + if ( createPicker() ) + { + ::svt::OControlAccess aAccess( m_pDlg, m_pDlg->GetView() ); + aAccess.setControlProperty( aControlName, aControlProperty, aValue ); + } + } + + //--------------------------------------------------------------------- + Any SAL_CALL OCommonPicker::getControlProperty( const ::rtl::OUString& aControlName, const ::rtl::OUString& aControlProperty ) throw (IllegalArgumentException, RuntimeException) + { + checkAlive(); + + SolarMutexGuard aGuard; + if ( createPicker() ) + { + ::svt::OControlAccess aAccess( m_pDlg, m_pDlg->GetView() ); + return aAccess.getControlProperty( aControlName, aControlProperty ); + } + + return Any(); + } + + //--------------------------------------------------------------------- + // XControlInformation functions + //--------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL OCommonPicker::getSupportedControls( ) throw (RuntimeException) + { + checkAlive(); + + SolarMutexGuard aGuard; + if ( createPicker() ) + { + ::svt::OControlAccess aAccess( m_pDlg, m_pDlg->GetView() ); + return aAccess.getSupportedControls( ); + } + + return Sequence< ::rtl::OUString >(); + } + + //--------------------------------------------------------------------- + sal_Bool SAL_CALL OCommonPicker::isControlSupported( const ::rtl::OUString& aControlName ) throw (RuntimeException) + { + checkAlive(); + + SolarMutexGuard aGuard; + if ( createPicker() ) + { + ::svt::OControlAccess aAccess( m_pDlg, m_pDlg->GetView() ); + return aAccess.isControlSupported( aControlName ); + } + + return sal_False; + } + + //--------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL OCommonPicker::getSupportedControlProperties( const ::rtl::OUString& aControlName ) throw (IllegalArgumentException, RuntimeException) + { + checkAlive(); + + SolarMutexGuard aGuard; + if ( createPicker() ) + { + ::svt::OControlAccess aAccess( m_pDlg, m_pDlg->GetView() ); + return aAccess.getSupportedControlProperties( aControlName ); + } + + return Sequence< ::rtl::OUString >(); + } + + //--------------------------------------------------------------------- + sal_Bool SAL_CALL OCommonPicker::isControlPropertySupported( const ::rtl::OUString& aControlName, const ::rtl::OUString& aControlProperty ) throw (IllegalArgumentException, RuntimeException) + { + checkAlive(); + + SolarMutexGuard aGuard; + if ( createPicker() ) + { + ::svt::OControlAccess aAccess( m_pDlg, m_pDlg->GetView() ); + return aAccess.isControlPropertySupported( aControlName, aControlProperty ); + } + + return sal_False; + } + + //--------------------------------------------------------------------- + // XExecutableDialog functions + //--------------------------------------------------------------------- + void SAL_CALL OCommonPicker::setTitle( const rtl::OUString& _rTitle ) throw( RuntimeException ) + { + SolarMutexGuard aGuard; + m_aTitle = _rTitle; + } + + //--------------------------------------------------------------------- + sal_Int16 OCommonPicker::execute() throw (RuntimeException) + { + SolarMutexGuard aGuard; + + prepareDialog(); + + { + ::osl::MutexGuard aOwnGuard( m_aMutex ); + m_bExecuting = sal_True; + } + sal_Int16 nResult = implExecutePicker(); + { + ::osl::MutexGuard aOwnGuard( m_aMutex ); + m_bExecuting = sal_False; + } + + return nResult; + } + + //--------------------------------------------------------------------- + // XCancellable functions + //--------------------------------------------------------------------- + void SAL_CALL OCommonPicker::cancel( ) throw (RuntimeException) + { + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_nCancelEvent ) + // nothing to do - the event for cancelling the dialog is already on the way + return; + } + + // The thread which executes our dialog has locked the solar mutex for + // sure. Cancelling the dialog should be done with a locked solar mutex, too. + // Thus we post ourself a message for cancelling the dialog. This way, the message + // is either handled in the thread which opened the dialog (which may even be + // this thread here), or, if no dialog is open, in the thread doing scheduling + // currently. Both is okay for us .... + // + // Note that we could do check if we are really executing the dialog currently. + // but the information would be potentially obsolete at the moment our event + // arrives, so we need to check it there, anyway ... + m_nCancelEvent = Application::PostUserEvent( LINK( this, OCommonPicker, OnCancelPicker ) ); + } + + //--------------------------------------------------------------------- + IMPL_LINK( OCommonPicker, OnCancelPicker, void*, EMPTYARG ) + { + // By definition, the solar mutex is locked when we arrive here. Note that this + // is important, as for instance the consistency of m_pDlg depends on this mutex. + ::osl::MutexGuard aGuard( m_aMutex ); + m_nCancelEvent = 0; + + if ( !m_bExecuting ) + // nothing to do. This may be because the dialog was cancelled after our cancel method + // posted this async event, or because somebody called cancel without the dialog + // being executed at this time. + return 0; + + OSL_ENSURE( getDialog(), "OCommonPicker::OnCancelPicker: executing, but no dialog!" ); + if ( getDialog() ) + getDialog()->EndDialog( RET_CANCEL ); + + return 0L; + } + + //------------------------------------------------------------------------------------ + // XInitialization functions + //------------------------------------------------------------------------------------ + void SAL_CALL OCommonPicker::initialize( const Sequence< Any >& _rArguments ) + throw ( Exception, RuntimeException ) + { + checkAlive(); + + ::rtl::OUString sSettingName; + Any aSettingValue; + + PropertyValue aPropArg; + NamedValue aPairArg; + + + const Any* pArguments = _rArguments.getConstArray(); + const Any* pArgumentsEnd = _rArguments.getConstArray() + _rArguments.getLength(); + for ( const Any* pArgument = pArguments; + pArgument != pArgumentsEnd; + ++pArgument + ) + { + if ( *pArgument >>= aPropArg ) + { + if ( aPropArg.Name.getLength() <= 0) + continue; + + sSettingName = aPropArg.Name; + aSettingValue = aPropArg.Value; + } + else if ( *pArgument >>= aPairArg ) + { + if ( aPairArg.Name.getLength() <= 0) + continue; + + sSettingName = aPairArg.Name; + aSettingValue = aPairArg.Value; + + + } + else + { + DBG_ERROR( + ( ::rtl::OString( "OCommonPicker::initialize: unknown argument type at position " ) + += ::rtl::OString::valueOf( (sal_Int32)( pArguments - _rArguments.getConstArray() ) ) + ).getStr() + ); + continue; + } + +#ifdef DBG_UTIL + sal_Bool bKnownSetting = +#endif + implHandleInitializationArgument( sSettingName, aSettingValue ); + DBG_ASSERT( bKnownSetting, + ( ::rtl::OString( "OCommonPicker::initialize: unknown argument \"" ) + += ::rtl::OString( sSettingName.getStr(), sSettingName.getLength(), osl_getThreadTextEncoding() ) + += ::rtl::OString( "\"!" ) + ).getStr() + ); + } + } + + //--------------------------------------------------------------------- + sal_Bool OCommonPicker::implHandleInitializationArgument( const ::rtl::OUString& _rName, const Any& _rValue ) SAL_THROW( ( Exception, RuntimeException ) ) + { + sal_Bool bKnown = sal_True; + if ( _rName.equalsAscii( "ParentWindow" ) ) + { + m_xDialogParent.clear(); + OSL_VERIFY( _rValue >>= m_xDialogParent ); + OSL_ENSURE( VCLUnoHelper::GetWindow( m_xDialogParent ), "OCommonPicker::implHandleInitializationArgument: invalid parent window given!" ); + } + else + bKnown = sal_False; + return bKnown; + } + +//......................................................................... +} // namespace svt +//......................................................................... + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/office/commonpicker.hxx b/fpicker/source/office/commonpicker.hxx new file mode 100644 index 000000000000..6422019affa5 --- /dev/null +++ b/fpicker/source/office/commonpicker.hxx @@ -0,0 +1,211 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SVTOOLS_COMMONPICKER_HXX +#define SVTOOLS_COMMONPICKER_HXX + +#include <cppuhelper/compbase5.hxx> +#include <com/sun/star/ui/dialogs/XControlInformation.hpp> +#include <com/sun/star/ui/dialogs/XControlAccess.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/util/XCancellable.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <comphelper/broadcasthelper.hxx> +#include <comphelper/propertycontainer.hxx> +#include <comphelper/proparrhlp.hxx> +#include <comphelper/uno3.hxx> +#include <tools/link.hxx> + +class SvtFileDialog; +class Window; + +namespace comphelper +{ + class OWeakEventListenerAdapter; +} + +//......................................................................... +namespace svt +{ +//......................................................................... + + typedef ::cppu::WeakComponentImplHelper5 < ::com::sun::star::ui::dialogs::XControlAccess + , ::com::sun::star::ui::dialogs::XControlInformation + , ::com::sun::star::lang::XEventListener + , ::com::sun::star::util::XCancellable + , ::com::sun::star::lang::XInitialization + > OCommonPicker_Base; + /** implements common functionality for the 2 UNO picker components + */ + class OCommonPicker + :public ::comphelper::OBaseMutex + ,public OCommonPicker_Base + ,public ::comphelper::OPropertyContainer + ,public ::comphelper::OPropertyArrayUsageHelper< OCommonPicker > + { + private: + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xORB; + + // <properties> + ::rtl::OUString m_sHelpURL; + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > m_xWindow; + // </properties> + + SvtFileDialog* m_pDlg; + sal_uInt32 m_nCancelEvent; + sal_Bool m_bExecuting; + + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > m_xDialogParent; + + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > m_xWindowListenerAdapter; + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > m_xParentListenerAdapter; + + protected: + ::rtl::OUString m_aTitle; + ::rtl::OUString m_aDisplayDirectory; + + protected: + inline SvtFileDialog* getDialog() { return m_pDlg; } + + inline const ::cppu::OBroadcastHelper& GetBroadcastHelper() const { return OCommonPicker_Base::rBHelper; } + inline ::cppu::OBroadcastHelper& GetBroadcastHelper() { return OCommonPicker_Base::rBHelper; } + + public: + OCommonPicker( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory ); + + protected: + virtual ~OCommonPicker(); + + // overridables + + // will be called with locked SolarMutex + virtual SvtFileDialog* implCreateDialog( Window* _pParent ) = 0; + virtual sal_Int16 implExecutePicker( ) = 0; + // do NOT override XExecutableDialog::execute! We need to do some stuff there ourself ... + + protected: + //------------------------------------------------------------------------------------ + // disambiguate XInterface + //------------------------------------------------------------------------------------ + DECLARE_XINTERFACE( ) + + //------------------------------------------------------------------------------------ + // disambiguate XTypeProvider + //------------------------------------------------------------------------------------ + DECLARE_XTYPEPROVIDER( ) + + //------------------------------------------------------------------------------------ + // ComponentHelper/XComponent + //------------------------------------------------------------------------------------ + virtual void SAL_CALL disposing(); + + //------------------------------------------------------------------------------------ + // XEventListner + //------------------------------------------------------------------------------------ + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); + + //------------------------------------------------------------------------------------ + // property set related methods + //------------------------------------------------------------------------------------ + + // XPropertySet pure methods + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException); + // OPropertySetHelper pure methods + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + // OPropertyArrayUsageHelper pure methods + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + + // OPropertySetHelper overridden methods + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( + sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) throw (::com::sun::star::uno::Exception); + + //------------------------------------------------------------------------------------ + // XExecutableDialog functions + //------------------------------------------------------------------------------------ + virtual void SAL_CALL setTitle( const ::rtl::OUString& _rTitle ) throw( ::com::sun::star::uno::RuntimeException ); + virtual sal_Int16 SAL_CALL execute() throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XControlAccess functions + //------------------------------------------------------------------------------------ + virtual void SAL_CALL setControlProperty( const ::rtl::OUString& aControlName, const ::rtl::OUString& aControlProperty, const ::com::sun::star::uno::Any& aValue ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getControlProperty( const ::rtl::OUString& aControlName, const ::rtl::OUString& aControlProperty ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + //------------------------------------------------------------------------------------ + // XControlInformation functions + //------------------------------------------------------------------------------------ + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedControls( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isControlSupported( const ::rtl::OUString& aControlName ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedControlProperties( const ::rtl::OUString& aControlName ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isControlPropertySupported( const ::rtl::OUString& aControlName, const ::rtl::OUString& aControlProperty ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + //------------------------------------------------------------------------------------ + // XCancellable functions + //------------------------------------------------------------------------------------ + virtual void SAL_CALL cancel( ) throw (::com::sun::star::uno::RuntimeException); + + //------------------------------------------------------------------------------------ + // XInitialization functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw ( ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // misc + //------------------------------------------------------------------------------------ + void checkAlive() const SAL_THROW( (::com::sun::star::lang::DisposedException) ); + + void prepareDialog(); + + protected: + sal_Bool createPicker(); + + /** handle a single argument from the XInitialization::initialize method + + @return <TRUE/> if the argument could be handled + */ + virtual sal_Bool implHandleInitializationArgument( + const ::rtl::OUString& _rName, + const ::com::sun::star::uno::Any& _rValue + ) + SAL_THROW( ( ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException ) ); + + private: + void stopWindowListening(); + + DECL_LINK( OnCancelPicker, void* ); + }; +//......................................................................... +} // namespace svt +//......................................................................... + +#endif // SVTOOLS_COMMONPICKER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/office/fpinteraction.cxx b/fpicker/source/office/fpinteraction.cxx new file mode 100644 index 000000000000..4f5d906737af --- /dev/null +++ b/fpicker/source/office/fpinteraction.cxx @@ -0,0 +1,171 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" +#include "fpinteraction.hxx" +#include <tools/debug.hxx> +#include <com/sun/star/ucb/InteractiveIOException.hpp> +#include <com/sun/star/task/XInteractionAbort.hpp> +#include <com/sun/star/task/XInteractionApprove.hpp> +#include <com/sun/star/task/XInteractionDisapprove.hpp> +#include <com/sun/star/task/XInteractionRetry.hpp> + +//........................................................................ +namespace svt +{ +//........................................................................ + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::task; + using namespace ::com::sun::star::ucb; + + //==================================================================== + //= OFilePickerInteractionHandler + //==================================================================== + DBG_NAME( OFilePickerInteractionHandler ) + //-------------------------------------------------------------------- + OFilePickerInteractionHandler::OFilePickerInteractionHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& _rxMaster ) + :m_xMaster( _rxMaster ) + ,m_bUsed( sal_False ) + ,m_eInterceptions( OFilePickerInteractionHandler::E_NOINTERCEPTION ) + { + DBG_CTOR( OFilePickerInteractionHandler, NULL ); + DBG_ASSERT( m_xMaster.is(), "OFilePickerInteractionHandler::OFilePickerInteractionHandler: invalid master handler!" ); + } + + //-------------------------------------------------------------------- + OFilePickerInteractionHandler::~OFilePickerInteractionHandler( ) + { + DBG_DTOR( OFilePickerInteractionHandler, NULL ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OFilePickerInteractionHandler::handle( const Reference< XInteractionRequest >& _rxRequest ) throw (RuntimeException) + { + if (!_rxRequest.is()) + return; + + m_bUsed = sal_True; + + // extract some generic continuations ... might we need it later + // if something goes wrong. + Reference< XInteractionAbort > xAbort; + Reference< XInteractionApprove > xApprove; + Reference< XInteractionDisapprove > xDisapprove; + Reference< XInteractionRetry > xRetry; + + const Sequence< Reference< XInteractionContinuation > > lConts = _rxRequest->getContinuations(); + const Reference< XInteractionContinuation >* pConts = lConts.getConstArray(); + for (sal_Int32 i=0; i<lConts.getLength(); ++i) + { + if (!xAbort.is()) + xAbort = Reference< XInteractionAbort >(pConts[i], UNO_QUERY); + if (!xApprove.is()) + xApprove = Reference< XInteractionApprove >(pConts[i], UNO_QUERY); + if (!xDisapprove.is()) + xDisapprove = Reference< XInteractionDisapprove >(pConts[i], UNO_QUERY); + if (!xRetry.is()) + xRetry = Reference< XInteractionRetry >(pConts[i], UNO_QUERY); + } + + // safe the original request for later analyzing! + m_aException = _rxRequest->getRequest(); + + // intercept some interesting interactions + + // The "does not exist" interaction will be supressed here completly. + if (m_eInterceptions & OFilePickerInteractionHandler::E_DOESNOTEXIST) + { + InteractiveIOException aIoException; + if ( + (m_aException >>= aIoException ) && + (IOErrorCode_NOT_EXISTING == aIoException.Code) + ) + { + if (xAbort.is()) + xAbort->select(); + return; + } + } + + // no master => abort this operation ... + if (!m_xMaster.is()) + { + if (xAbort.is()) + xAbort->select(); + return; + } + + // forward it to our master - so he can handle all + // not interesting interactions :-) + m_xMaster->handle(_rxRequest); + } + + //-------------------------------------------------------------------- + void OFilePickerInteractionHandler::enableInterceptions( EInterceptedInteractions eInterceptions ) + { + m_eInterceptions = eInterceptions; + } + + //-------------------------------------------------------------------- + sal_Bool OFilePickerInteractionHandler::wasUsed() const + { + return m_bUsed; + } + + //-------------------------------------------------------------------- + void OFilePickerInteractionHandler::resetUseState() + { + m_bUsed = sal_False; + } + + //-------------------------------------------------------------------- + void OFilePickerInteractionHandler::forgetRequest() + { + m_aException = Any(); + } + + //-------------------------------------------------------------------- + sal_Bool OFilePickerInteractionHandler::wasAccessDenied() const + { + InteractiveIOException aIoException; + if ( + (m_aException >>= aIoException ) && + (IOErrorCode_ACCESS_DENIED == aIoException.Code) + ) + { + return sal_True; + } + return sal_False; + } + +//........................................................................ +} // namespace svt +//........................................................................ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/office/fpinteraction.hxx b/fpicker/source/office/fpinteraction.hxx new file mode 100644 index 000000000000..88a2590384cf --- /dev/null +++ b/fpicker/source/office/fpinteraction.hxx @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SVTOOLS_FILEPICKER_INTERACTION_HXX +#define SVTOOLS_FILEPICKER_INTERACTION_HXX + +#include <cppuhelper/implbase1.hxx> +#include <com/sun/star/task/XInteractionHandler.hpp> + +//........................................................................ +namespace svt +{ +//........................................................................ + + //==================================================================== + //= OFilePickerInteractionHandler + //==================================================================== + typedef ::cppu::WeakImplHelper1 < ::com::sun::star::task::XInteractionHandler + > OFilePickerInteractionHandler_Base; + + /** a InteractionHandler implementation which extends another handler with some customizability + */ + class OFilePickerInteractionHandler : public OFilePickerInteractionHandler_Base + { + public: + /** flags, which indicates special handled interactions + These values will be used combained as flags - so they must + in range [2^n]! + */ + enum EInterceptedInteractions + { + E_NOINTERCEPTION = 0, + E_DOESNOTEXIST = 1 + // next values [2,4,8,16 ...]! + }; + + protected: + ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler > m_xMaster ; // our master handler + ::com::sun::star::uno::Any m_aException ; // the last handled request + sal_Bool m_bUsed ; // indicates using of this interaction handler instance + EInterceptedInteractions m_eInterceptions ; // enable/disable interception of some special interactions + + public: + OFilePickerInteractionHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& _rxMaster ); + + // some generic functions + void enableInterceptions( EInterceptedInteractions eInterceptions ); + sal_Bool wasUsed () const; + void resetUseState (); + void forgetRequest (); + + // functions to analyze last cached request + sal_Bool wasAccessDenied() const; + + protected: + // XInteractionHandler + virtual void SAL_CALL handle( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionRequest >& _rxRequest ) throw (::com::sun::star::uno::RuntimeException); + + private: + ~OFilePickerInteractionHandler(); + }; + +//........................................................................ +} // namespace svt +//........................................................................ + +#endif // SVTOOLS_FILEPICKER_INTERACTION_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/office/fps_office.cxx b/fpicker/source/office/fps_office.cxx new file mode 100644 index 000000000000..77160e4a8253 --- /dev/null +++ b/fpicker/source/office/fps_office.cxx @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" +#include "sal/types.h" + +#include "cppuhelper/implementationentry.hxx" + +#include "OfficeFilePicker.hxx" +#include "OfficeFolderPicker.hxx" + +static cppu::ImplementationEntry g_entries[] = +{ + { + SvtFilePicker::impl_createInstance, + SvtFilePicker::impl_getStaticImplementationName, + SvtFilePicker::impl_getStaticSupportedServiceNames, + cppu::createSingleComponentFactory, 0, 0 + }, + { + SvtFolderPicker::impl_createInstance, + SvtFolderPicker::impl_getStaticImplementationName, + SvtFolderPicker::impl_getStaticSupportedServiceNames, + cppu::createSingleComponentFactory, 0, 0 + }, + { 0, 0, 0, 0, 0, 0 } +}; + +extern "C" +{ +SAL_DLLPUBLIC_EXPORT void SAL_CALL +component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL component_writeInfo( + void * pServiceManager, void * pRegistryKey) +{ + return cppu::component_writeInfoHelper ( + pServiceManager, pRegistryKey, g_entries); +} + +SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory( + const sal_Char * pImplementationName, void * pServiceManager, void * pRegistryKey) +{ + return cppu::component_getFactoryHelper ( + pImplementationName, pServiceManager, pRegistryKey, g_entries); +} + +} // extern "C" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/office/fpsmartcontent.cxx b/fpicker/source/office/fpsmartcontent.cxx new file mode 100644 index 000000000000..31c7030afb03 --- /dev/null +++ b/fpicker/source/office/fpsmartcontent.cxx @@ -0,0 +1,310 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" +#include "fpsmartcontent.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/ucb/ContentInfo.hpp> +#include <com/sun/star/ucb/ContentInfoAttribute.hpp> +#include <com/sun/star/ucb/XContent.hpp> +/** === end UNO includes === **/ + +#include <comphelper/processfactory.hxx> +#include <ucbhelper/commandenvironment.hxx> +#include <tools/solar.h> +#include <tools/debug.hxx> +#include <tools/string.hxx> + +//........................................................................ +namespace svt +{ +//........................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::task; + using namespace ::com::sun::star::ucb; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::container; + + //==================================================================== + //= SmartContent + //==================================================================== + //-------------------------------------------------------------------- + SmartContent::SmartContent() + :m_pContent( NULL ) + ,m_eState( NOT_BOUND ) + ,m_pOwnInteraction( NULL ) + { + } + + //-------------------------------------------------------------------- + SmartContent::SmartContent( const ::rtl::OUString& _rInitialURL ) + :m_pContent( NULL ) + ,m_eState( NOT_BOUND ) + { + bindTo( _rInitialURL ); + } + + //-------------------------------------------------------------------- + SmartContent::~SmartContent() + { + //Do not delete the content. Because the content will be used by the cache. + //DELETEZ( m_pContent ); + } + + //-------------------------------------------------------------------- + void SmartContent::enableOwnInteractionHandler(::svt::OFilePickerInteractionHandler::EInterceptedInteractions eInterceptions) + { + Reference< XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); + Reference< XInteractionHandler > xGlobalInteractionHandler = Reference< XInteractionHandler >( + xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.task.InteractionHandler") ) ), UNO_QUERY ); + + m_pOwnInteraction = new ::svt::OFilePickerInteractionHandler(xGlobalInteractionHandler); + m_pOwnInteraction->enableInterceptions(eInterceptions); + m_xOwnInteraction = m_pOwnInteraction; + + m_xCmdEnv = new ::ucbhelper::CommandEnvironment( m_xOwnInteraction, Reference< XProgressHandler >() ); + } + + //-------------------------------------------------------------------- + void SmartContent::enableDefaultInteractionHandler() + { + // Don't free the memory here! It will be done by the next + // call automaticly - releasing of the uno reference ... + m_pOwnInteraction = NULL; + m_xOwnInteraction = Reference< XInteractionHandler >(); + + Reference< XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); + Reference< XInteractionHandler > xGlobalInteractionHandler = Reference< XInteractionHandler >( + xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.task.InteractionHandler") ) ), UNO_QUERY ); + m_xCmdEnv = new ucbhelper::CommandEnvironment( xGlobalInteractionHandler, Reference< XProgressHandler >() ); + } + + //-------------------------------------------------------------------- + ::svt::OFilePickerInteractionHandler* SmartContent::getOwnInteractionHandler() const + { + if (!m_xOwnInteraction.is()) + return NULL; + return m_pOwnInteraction; + } + + //-------------------------------------------------------------------- + SmartContent::InteractionHandlerType SmartContent::queryCurrentInteractionHandler() const + { + if (m_xOwnInteraction.is()) + return IHT_OWN; + + if (!m_xCmdEnv.is()) + return IHT_NONE; + + return IHT_DEFAULT; + } + + //-------------------------------------------------------------------- + void SmartContent::disableInteractionHandler() + { + // Don't free the memory here! It will be done by the next + // call automaticly - releasing of the uno reference ... + m_pOwnInteraction = NULL; + m_xOwnInteraction.clear(); + + m_xCmdEnv.clear(); + } + + //-------------------------------------------------------------------- + void SmartContent::bindTo( const ::rtl::OUString& _rURL ) + { + if ( getURL() == _rURL ) + // nothing to do, regardless of the state + return; + + DELETEZ( m_pContent ); + m_eState = INVALID; // default to INVALID + m_sURL = _rURL; + + if ( m_sURL.getLength() ) + { + try + { + m_pContent = new ::ucbhelper::Content( _rURL, m_xCmdEnv ); + m_eState = UNKNOWN; + // from now on, the state is unknown -> we cannot know for sure if the content + // is really valid (some UCP's only tell this when asking for properties, not upon + // creation) + } + catch( ContentCreationException& ) + { + } + catch( Exception& ) + { + DBG_ERROR( "SmartContent::bindTo: unexpected exception caught!" ); + } + } + else + { + m_eState = NOT_BOUND; + } + + + // don't forget to reset the may internal used interaction handler ... + // But do it only for our own specialized interaction helper! + ::svt::OFilePickerInteractionHandler* pHandler = getOwnInteractionHandler(); + if (pHandler) + { + pHandler->resetUseState(); + pHandler->forgetRequest(); + } + } + + //-------------------------------------------------------------------- + sal_Bool SmartContent::implIs( const ::rtl::OUString& _rURL, Type _eType ) + { + // bind to this content + bindTo( _rURL ); + + // did we survive this? + if ( isInvalid() || !isBound() ) + return sal_False; + + DBG_ASSERT( m_pContent, "SmartContent::implIs: inconsistence!" ); + // if, after an bindTo, we don't have a content, then we should be INVALID, or at least + // NOT_BOUND (the latter happens, for example, if somebody tries to ask for an empty URL) + + sal_Bool bIs = sal_False; + try + { + if ( Folder == _eType ) + bIs = m_pContent->isFolder(); + else + bIs = m_pContent->isDocument(); + + // from here on, we definately know that the content is valid + m_eState = VALID; + } + catch( Exception& ) + { + // now we're definately invalid + m_eState = INVALID; + } + return bIs; + } + + //-------------------------------------------------------------------- + void SmartContent::getTitle( ::rtl::OUString& /* [out] */ _rTitle ) + { + if ( !isBound() || isInvalid() ) + return; + + try + { + ::rtl::OUString sTitle; + m_pContent->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Title" )) ) >>= sTitle; + _rTitle = sTitle; + + // from here on, we definately know that the content is valid + m_eState = VALID; + } + catch( ::com::sun::star::uno::Exception& ) + { + // now we're definately invalid + m_eState = INVALID; + } + } + + //-------------------------------------------------------------------- + sal_Bool SmartContent::hasParentFolder( ) + { + if ( !isBound() || isInvalid() ) + return sal_False; + + sal_Bool bRet = sal_False; + try + { + Reference< XChild > xChild( m_pContent->get(), UNO_QUERY ); + if ( xChild.is() ) + { + Reference< XContent > xParent( xChild->getParent(), UNO_QUERY ); + if ( xParent.is() ) + { + String aParentURL = String( xParent->getIdentifier()->getContentIdentifier() ); + bRet = ( aParentURL.Len() > 0 && aParentURL != (String)(m_pContent->getURL()) ); + + // now we're definately valid + m_eState = VALID; + } + } + } + catch( const Exception& ) + { + // now we're definately invalid + m_eState = INVALID; + } + return bRet; + } + + //-------------------------------------------------------------------- + sal_Bool SmartContent::canCreateFolder( ) + { + if ( !isBound() || isInvalid() ) + return sal_False; + + sal_Bool bRet = sal_False; + try + { + Sequence< ContentInfo > aInfo = m_pContent->queryCreatableContentsInfo(); + const ContentInfo* pInfo = aInfo.getConstArray(); + sal_Int32 nCount = aInfo.getLength(); + for ( sal_Int32 i = 0; i < nCount; ++i, ++pInfo ) + { + // Simply look for the first KIND_FOLDER... + if ( pInfo->Attributes & ContentInfoAttribute::KIND_FOLDER ) + { + bRet = sal_True; + break; + } + } + + // now we're definately valid + m_eState = VALID; + } + catch( Exception& ) + { + // now we're definately invalid + m_eState = INVALID; + } + return bRet; + } + +//........................................................................ +} // namespace svt +//........................................................................ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/office/fpsmartcontent.hxx b/fpicker/source/office/fpsmartcontent.hxx new file mode 100644 index 000000000000..e16c288678b1 --- /dev/null +++ b/fpicker/source/office/fpsmartcontent.hxx @@ -0,0 +1,215 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SVTOOLS_SOURCE_FILEPICKER_FPSMARTCONTENT_HXX +#define SVTOOLS_SOURCE_FILEPICKER_FPSMARTCONTENT_HXX + +#include "fpinteraction.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/ucb/XCommandEnvironment.hpp> +#include <com/sun/star/task/XInteractionHandler.hpp> +/** === end UNO includes === **/ +#include <ucbhelper/content.hxx> + +//........................................................................ +namespace svt +{ +//........................................................................ + + //==================================================================== + //= SmartContent + //==================================================================== + /** a "smart content" which basically wraps an UCB content, but caches some informations + so that repeatedly recreating it may be faster + */ + class SmartContent + { + public: + enum State + { + NOT_BOUND, // never bound + UNKNOWN, // bound, but validity is unknown + VALID, // bound to an URL, and valid + INVALID // bound to an URL, and invalid + }; + + private: + ::rtl::OUString m_sURL; + ::ucbhelper::Content* m_pContent; + State m_eState; + ::com::sun::star::uno::Reference < ::com::sun::star::ucb::XCommandEnvironment > m_xCmdEnv; + ::com::sun::star::uno::Reference < ::com::sun::star::task::XInteractionHandler > m_xOwnInteraction; + ::svt::OFilePickerInteractionHandler* m_pOwnInteraction; + + private: + enum Type { Folder, Document }; + /// checks if the currently bound content is a folder or document + sal_Bool implIs( const ::rtl::OUString& _rURL, Type _eType ); + + SmartContent( const SmartContent& _rSource ); // never implemented + SmartContent& operator=( const SmartContent& _rSource ); // never implemented + + public: + SmartContent(); + SmartContent( const ::rtl::OUString& _rInitialURL ); + ~SmartContent(); + + public: + + /** create and set a specialized interaction handler at the internal used command environment. + + @param eInterceptions + will be directly forwarded to OFilePickerInteractionHandler::enableInterceptions() + */ + void enableOwnInteractionHandler(::svt::OFilePickerInteractionHandler::EInterceptedInteractions eInterceptions); + + /** disable the specialized interaction handler and use the global UI interaction handler only. + */ + void enableDefaultInteractionHandler(); + + /** return the internal used interaction handler object ... + Because this pointer will be valid only, if the uno object is hold + alive by it's uno reference (and this reference is set on the + command environment) we must return NULL, in case this environment does + not exist! + */ + ::svt::OFilePickerInteractionHandler* getOwnInteractionHandler() const; + + /** describes different types of interaction handlers + */ + enum InteractionHandlerType + { + IHT_NONE, + IHT_OWN, + IHT_DEFAULT + }; + + /** return the type of the internal used interaction handler object ... + + @seealso InteractionHandlerType + */ + InteractionHandlerType queryCurrentInteractionHandler() const; + + /** disable internal used interaction handler object ... + */ + void disableInteractionHandler(); + + /** returns the current state of the content + + @seealso State + */ + inline State getState( ) const { return m_eState; } + + /** checks if the content is valid + <p>Note that "not (is valid)" is not the same as "is invalid"</p> + */ + inline sal_Bool isValid( ) const { return VALID == getState(); } + + /** checks if the content is valid + <p>Note that "not (is invalid)" is not the same as "is valid"</p> + */ + inline sal_Bool isInvalid( ) const { return INVALID == getState(); } + + /** checks if the content is bound + */ + inline sal_Bool isBound( ) const { return NOT_BOUND != getState(); } + + /** returns the URL of the content + */ + inline ::rtl::OUString getURL() const { return m_pContent ? m_pContent->getURL() : m_sURL; } + + /** (re)creates the content for the given URL + + <p>Note that getState will return either UNKNOWN or INVALID after the call returns, + but never VALID. The reason is that there are content providers which allow to construct + content objects, even if the respective contents are not accessible. They tell about this + only upon working with the content object (e.g. when asking for the IsFolder).</p> + + @postcond + <member>getState</member> does not return NOT_BOUND after the call returns + */ + void bindTo( const ::rtl::OUString& _rURL ); + + /** retrieves the title of the content + @precond + the content is bound and not invalid + */ + void getTitle( ::rtl::OUString& /* [out] */ _rTitle ); + + /** checks if the content has a parent folder + @precond + the content is bound and not invalid + */ + sal_Bool hasParentFolder( ); + + /** checks if sub folders below the content can be created + @precond + the content is bound and not invalid + */ + sal_Bool canCreateFolder( ); + + /** binds to the given URL, checks whether or not it refers to a folder + + @postcond + the content is not in the state UNKNOWN + */ + inline sal_Bool isFolder( const ::rtl::OUString& _rURL ) + { + return implIs( _rURL, Folder ); + } + + /** binds to the given URL, checks whether or not it refers to a document + + @postcond + the content is not in the state UNKNOWN + */ + inline sal_Bool isDocument( const ::rtl::OUString& _rURL ) + { + return implIs( _rURL, Document ); + } + + /** checks if the content is existent (it is if and only if it is a document or a folder) + */ + inline sal_Bool is( const ::rtl::OUString& _rURL ) + { + return implIs( _rURL, Folder ) || implIs( _rURL, Document ); + } + + inline sal_Bool isFolder( ) { return isFolder( getURL() ); } + inline sal_Bool isDocument( ) { return isDocument( getURL() ); } + inline sal_Bool is( ) { return is( getURL() ); } + }; + +//........................................................................ +} // namespace svt +//........................................................................ + +#endif // SVTOOLS_SOURCE_FILEPICKER_FPSMARTCONTENT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/office/iodlg.cxx b/fpicker/source/office/iodlg.cxx new file mode 100644 index 000000000000..f7d48f81b72a --- /dev/null +++ b/fpicker/source/office/iodlg.cxx @@ -0,0 +1,3468 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +// includes -------------------------------------------------------------- +#include <sal/macros.h> +#include "iodlg.hxx" +#include <tools/stream.hxx> +#include <tools/urlobj.hxx> +#include <vcl/fixed.hxx> +#include <vcl/lstbox.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/svapp.hxx> +#include <vcl/timer.hxx> +#include <unotools/ucbhelper.hxx> +#include <ucbhelper/contentbroker.hxx> +#include "svtools/ehdl.hxx" +#include "svl/urihelper.hxx" +#include "unotools/pathoptions.hxx" +#include "unotools/viewoptions.hxx" +#include "svtools/fileview.hxx" +#include "unotools/inetoptions.hxx" +#include "svtools/sfxecode.hxx" +#include "svl/svarray.hxx" +#include "svtools/svtabbx.hxx" + +#define _SVSTDARR_USHORTS +#define _SVSTDARR_STRINGSDTOR +#include "svl/svstdarr.hxx" +#include <toolkit/helper/vclunohelper.hxx> +#include <unotools/localfilehelper.hxx> + +#include "svtools/svtools.hrc" +#include "svtools/helpid.hrc" +#include "iodlg.hrc" +#include "rtl/instance.hxx" +#include "asyncfilepicker.hxx" +#include "iodlgimp.hxx" +#include "svtools/inettbc.hxx" +#include "unotools/syslocale.hxx" +#include "svtools/QueryFolderName.hxx" +#include <rtl/ustring.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/ucb/XContentProviderManager.hpp> +#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/ControlActions.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/util/URL.hpp> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> + +#include <comphelper/processfactory.hxx> +#include <osl/file.h> +#include <vcl/waitobj.hxx> + +// #97148# ------------------------------------ +#include <com/sun/star/task/XInteractionHandler.hpp> +#include "com/sun/star/ucb/InteractiveAugmentedIOException.hpp" +#include "fpinteraction.hxx" +#include <osl/process.h> +#include <comphelper/interaction.hxx> + +#include <algorithm> +#include <functional> + +//#define AUTOSELECT_USERFILTER + // define this for the experimental feature of user-filter auto selection + // means if the user enters e.g. *.doc<enter>, and there is a filter which is responsible for *.doc files (only), + // then this filter is selected automatically + +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::task; +using namespace ::com::sun::star::sdbc; +using namespace ::utl; +using namespace ::svt; + +using namespace ExtendedFilePickerElementIds; +using namespace CommonFilePickerElementIds; +using namespace InternalFilePickerElementIds; + +#define IODLG_CONFIGNAME String(RTL_CONSTASCII_USTRINGPARAM("FileDialog")) +#define IMPGRF_CONFIGNAME String(RTL_CONSTASCII_USTRINGPARAM("ImportGraphicDialog")) + +#define GET_DECODED_NAME(aObj) \ + aObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ) + +// Zeit die beim Traveln in der Filterbox gewartet wird, +// bis in der Browsebox gefiltert wird ( in ms ). +#define TRAVELFILTER_TIMEOUT 750 + +#define WIDTH_ADDITION 15 + +// functions ------------------------------------------------------------- + +namespace +{ + + //----------------------------------------------------------------------------- + String getMostCurrentFilter( SvtExpFileDlg_Impl* pImpl ) + { + DBG_ASSERT( pImpl, "invalid impl pointer" ); + const SvtFileDialogFilter_Impl* pFilter = pImpl->_pUserFilter; + + if ( !pFilter ) + pFilter = pImpl->GetCurFilter(); + + // Filtern. + if ( !pFilter ) + return String(); + + return pFilter->GetType(); + } + + //----------------------------------------------------------------------------- + sal_Bool restoreCurrentFilter( SvtExpFileDlg_Impl* _pImpl ) + { + DBG_ASSERT( _pImpl->GetCurFilter(), "restoreCurrentFilter: no current filter!" ); + DBG_ASSERT( _pImpl->GetCurFilterDisplayName().Len(), "restoreCurrentFilter: no current filter (no display name)!" ); + + _pImpl->SelectFilterListEntry( _pImpl->GetCurFilterDisplayName() ); + +#ifdef DBG_UTIL + String sSelectedDisplayName; + DBG_ASSERT( ( _pImpl->GetSelectedFilterEntry( sSelectedDisplayName ) == _pImpl->GetCurFilter() ) + && ( sSelectedDisplayName == _pImpl->GetCurFilterDisplayName() ), + "restoreCurrentFilter: inconsistence!" ); +#endif + return _pImpl->m_bNeedDelayedFilterExecute; + } + + //----------------------------------------------------------------------------- + String GetFsysExtension_Impl( const String& rFile, const String& rLastFilterExt ) + { + xub_StrLen nDotPos = rFile.SearchBackward( '.' ); + if ( nDotPos != STRING_NOTFOUND ) + { + if ( rLastFilterExt.Len() ) + { + if ( rFile.Copy( nDotPos + 1 ).EqualsIgnoreCaseAscii( rLastFilterExt ) ) + return String( rLastFilterExt ); + } + else + return String( rFile.Copy( nDotPos ) ); + } + return String(); + } + + //----------------------------------------------------------------------------- + void SetFsysExtension_Impl( String& rFile, const String& rExtension ) + { + const sal_Unicode* p0 = rFile.GetBuffer(); + const sal_Unicode* p1 = p0 + rFile.Len() - 1; + while ( p1 >= p0 && *p1 != sal_Unicode( '.' ) ) + p1--; + if ( p1 >= p0 ) + // remove old extension + rFile.Erase( + sal::static_int_cast< xub_StrLen >( + p1 - p0 + 1 - ( rExtension.Len() > 0 ? 0 : 1 ) ) ); + else if ( rExtension.Len() ) + // no old extension + rFile += sal_Unicode( '.' ); + rFile += rExtension; + } + + //----------------------------------------------------------------------------- + // move the control with the given offset + void lcl_MoveControl( Control* _pControl, sal_Int32 _nDeltaX, sal_Int32 _nDeltaY, sal_Int32* _pMaxY = NULL ) + { + if ( _pControl ) + { + Point aNewPos = _pControl->GetPosPixel(); + + // adjust the vertical position + aNewPos.Y() += _nDeltaY; + if ( _pMaxY && ( aNewPos.Y() > *_pMaxY ) ) + *_pMaxY = aNewPos.Y(); + + // adjust the horizontal position + aNewPos.X() += _nDeltaX; + + _pControl->SetPosPixel( aNewPos ); + } + } + + //------------------------------------------------------------------------- + void lcl_autoUpdateFileExtension( SvtFileDialog* _pDialog, const String& _rLastFilterExt ) + { + // if auto extension is enabled .... + if ( _pDialog->isAutoExtensionEnabled() ) + { + // automatically switch to the extension of the (maybe just newly selected) extension + String aNewFile = _pDialog->getCurrentFileText( ); + String aExt = GetFsysExtension_Impl( aNewFile, _rLastFilterExt ); + + // but only if there already is an extension + if ( aExt.Len() ) + { + // check if it is a real file extension, and not only the "post-dot" part in + // a directory name + // 28.03.2002 - 98337 - fs@openoffice.org + sal_Bool bRealExtensions = sal_True; + if ( STRING_NOTFOUND != aExt.Search( '/' ) ) + bRealExtensions = sal_False; + else if ( STRING_NOTFOUND != aExt.Search( '\\' ) ) + bRealExtensions = sal_False; + else + { + // no easy way to tell, because the part containing the dot already is the last + // segment of the complete file name + // So we have to check if the file name denotes a folder or a file. + // For performance reasons, we do this for file urls only + INetURLObject aURL( aNewFile ); + if ( INET_PROT_NOT_VALID == aURL.GetProtocol() ) + { + String sURL; + if ( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( aNewFile, sURL ) ) + aURL = INetURLObject( sURL ); + } + if ( INET_PROT_FILE == aURL.GetProtocol() ) + { + // #97148# & #102204# ----- + try + { + bRealExtensions = !_pDialog->ContentIsFolder( aURL.GetMainURL( INetURLObject::NO_DECODE ) ); + } + catch( ::com::sun::star::uno::Exception& ) + { + DBG_WARNING( "Exception in lcl_autoUpdateFileExtension" ); + } + } + } + + if ( bRealExtensions ) + { + SetFsysExtension_Impl( aNewFile, _pDialog->GetDefaultExt() ); + _pDialog->setCurrentFileText( aNewFile ); + } + } + } + } + + //------------------------------------------------------------------------- + sal_Bool lcl_getHomeDirectory( const String& _rForURL, String& /* [out] */ _rHomeDir ) + { + _rHomeDir.Erase(); + + // now ask the content broker for a provider for this scheme + //================================================================= + try + { + // get the content provider manager + ::ucbhelper::ContentBroker* pBroker = ::ucbhelper::ContentBroker::get(); + Reference< XContentProviderManager > xProviderManager; + if ( pBroker ) + xProviderManager = pBroker->getContentProviderManagerInterface(); + + //================================================================= + // get the provider for the current scheme + Reference< XContentProvider > xProvider; + if ( xProviderManager.is() ) + xProvider = xProviderManager->queryContentProvider( _rForURL ); + + DBG_ASSERT( xProvider.is(), "lcl_getHomeDirectory: could not find a (valid) content provider for the current URL!" ); + Reference< XPropertySet > xProviderProps( xProvider, UNO_QUERY ); + if ( xProviderProps.is() ) + { + Reference< XPropertySetInfo > xPropInfo = xProviderProps->getPropertySetInfo(); + const ::rtl::OUString sHomeDirPropertyName( RTL_CONSTASCII_USTRINGPARAM( "HomeDirectory" ) ); + if ( !xPropInfo.is() || xPropInfo->hasPropertyByName( sHomeDirPropertyName ) ) + { + ::rtl::OUString sHomeDirectory; + xProviderProps->getPropertyValue( sHomeDirPropertyName ) >>= sHomeDirectory; + _rHomeDir = sHomeDirectory; + } + } + } + catch( const Exception& ) + { + DBG_ERROR( "lcl_getHomeDirectory: caught an exception!" ); + } + return 0 < _rHomeDir.Len(); + } + + //--------------------------------------------------------------------- + static String lcl_ensureFinalSlash( const String& _rDir ) + { + INetURLObject aWorkPathObj( _rDir, INET_PROT_FILE ); + aWorkPathObj.setFinalSlash(); + return aWorkPathObj.GetMainURL( INetURLObject::NO_DECODE ); + } + + //--------------------------------------------------------------------- + void convertStringListToUrls( const String& _rColonSeparatedList, ::std::vector< String >& _rTokens, bool _bFinalSlash ) + { + const sal_Unicode s_cSeparator = +#if defined(WNT) || defined(OS2) + ';' +#else + ':' +#endif + ; + xub_StrLen nTokens = _rColonSeparatedList.GetTokenCount( s_cSeparator ); + _rTokens.resize( 0 ); _rTokens.reserve( nTokens ); + for ( xub_StrLen i=0; i<nTokens; ++i ) + { + // the current token in the list + String sCurrentToken = _rColonSeparatedList.GetToken( i, s_cSeparator ); + if ( !sCurrentToken.Len() ) + continue; + + INetURLObject aCurrentURL; + + String sURL; + if ( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( sCurrentToken, sURL ) ) + aCurrentURL = INetURLObject( sURL ); + else + { + // smart URL parsing, assuming FILE protocol + aCurrentURL = INetURLObject( sCurrentToken, INET_PROT_FILE ); + } + + if ( _bFinalSlash ) + aCurrentURL.setFinalSlash( ); + else + aCurrentURL.removeFinalSlash( ); + _rTokens.push_back( aCurrentURL.GetMainURL( INetURLObject::NO_DECODE ) ); + } + } + + //--------------------------------------------------------------------- + struct RemoveFinalSlash : public ::std::unary_function< String, void > + { + void operator()( String& _rURL ) + { + INetURLObject aURL( _rURL ); +#if defined(WNT) || defined(OS2) + if ( aURL.getSegmentCount() > 1 ) +#endif + aURL.removeFinalSlash( ); + _rURL = aURL.GetMainURL( INetURLObject::NO_DECODE ); + } + }; + + // ----------------------------------------------------------------------- + /** retrieves the value of an environment variable + @return <TRUE/> if and only if the retrieved string value is not empty + */ + bool getEnvironmentValue( const sal_Char* _pAsciiEnvName, ::rtl::OUString& _rValue ) + { + _rValue = ::rtl::OUString(); + ::rtl::OUString sEnvName = ::rtl::OUString::createFromAscii( _pAsciiEnvName ); + osl_getEnvironment( sEnvName.pData, &_rValue.pData ); + return _rValue.getLength() != 0; + } +} + +//*************************************************************************** +// ControlChain_Impl +//*************************************************************************** + +struct ControlChain_Impl +{ + Window* _pControl; + ControlChain_Impl* _pNext; + BOOL _bHasOwnerShip; + + ControlChain_Impl( Window* pControl, ControlChain_Impl* pNext ); + ~ControlChain_Impl(); +}; + +//*************************************************************************** + +ControlChain_Impl::ControlChain_Impl +( + Window* pControl, + ControlChain_Impl* pNext +) + : _pControl( pControl ), + _pNext( pNext ), + _bHasOwnerShip( TRUE ) +{ +} + +//*************************************************************************** + +ControlChain_Impl::~ControlChain_Impl() +{ + if ( _bHasOwnerShip ) + { + delete _pControl; + } + delete _pNext; +} + +//***************************************************************************** +// ResMgrHolder +//***************************************************************************** +namespace +{ + struct ResMgrHolder + { + ResMgr * operator ()() + { + return ResMgr::CreateResMgr (CREATEVERSIONRESMGR_NAME(fps_office)); + } + + static ResMgr * getOrCreate() + { + return rtl_Instance< + ResMgr, ResMgrHolder, + osl::MutexGuard, osl::GetGlobalMutex >::create ( + ResMgrHolder(), osl::GetGlobalMutex()); + } + }; + + struct SvtResId : public ResId + { + SvtResId (USHORT nId) : ResId (nId, *ResMgrHolder::getOrCreate()) {} + }; +} + +//***************************************************************************** +// SvtFileDialog +//***************************************************************************** +SvtFileDialog::SvtFileDialog +( + Window* _pParent, + WinBits nBits, + WinBits nExtraBits +) : + ModalDialog( _pParent, SvtResId( DLG_SVT_EXPLORERFILE ) ) + + ,_pUserControls( NULL ) + ,_pCbReadOnly( NULL ) + ,_pCbLinkBox( NULL) + ,_pCbPreviewBox( NULL ) + ,_pCbSelection( NULL ) + ,_pPbPlay( NULL ) + ,_pPrevWin( NULL ) + ,_pPrevBmp( NULL ) + ,_pFileView( NULL ) + ,_pFileNotifier( NULL ) + ,_pImp( new SvtExpFileDlg_Impl( nBits ) ) + ,_nExtraBits( nExtraBits ) + ,_bIsInExecute( FALSE ) + ,m_bInExecuteAsync( false ) + ,m_bHasFilename( false ) +{ + Init_Impl( nBits ); +} + +//***************************************************************************** + +SvtFileDialog::SvtFileDialog ( Window* _pParent, WinBits nBits ) + :ModalDialog( _pParent, SvtResId( DLG_SVT_EXPLORERFILE ) ) + ,_pUserControls( NULL ) + ,_pCbReadOnly( NULL ) + ,_pCbLinkBox( NULL) + ,_pCbPreviewBox( NULL ) + ,_pCbSelection( NULL ) + ,_pPbPlay( NULL ) + ,_pPrevWin( NULL ) + ,_pPrevBmp( NULL ) + ,_pFileView( NULL ) + ,_pFileNotifier( NULL ) + ,_pImp( new SvtExpFileDlg_Impl( nBits ) ) + ,_nExtraBits( 0L ) + ,_bIsInExecute( FALSE ) + ,m_bHasFilename( false ) +{ + Init_Impl( nBits ); +} + +//***************************************************************************** + +SvtFileDialog::~SvtFileDialog() +{ + if ( _pImp->_aIniKey.Len() ) + { + // save window state + SvtViewOptions aDlgOpt( E_DIALOG, _pImp->_aIniKey ); + aDlgOpt.SetWindowState( String( GetWindowState(), osl_getThreadTextEncoding() ) ); + String sUserData = _pFileView->GetConfigString(); + aDlgOpt.SetUserItem( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "UserData" )), + makeAny( ::rtl::OUString( sUserData ) ) ); + } + + _pFileView->SetSelectHdl( Link() ); + + delete _pImp; + delete _pFileView; + + delete _pCbReadOnly; + delete _pCbLinkBox; + delete _pCbPreviewBox; + delete _pCbSelection; + delete _pPbPlay; + delete _pPrevWin; + delete _pPrevBmp; + + delete _pUserControls; +} + +//***************************************************************************** + +void SvtFileDialog::Init_Impl +( + WinBits nStyle +) +{ + m_aImages = ImageList( SvtResId( RID_FILEPICKER_IMAGES ) ); + + _pImp->_nStyle = nStyle; + _pImp->_a6Size = LogicToPixel( Size( 6, 6 ), MAP_APPFONT ); + _pImp->_eMode = ( nStyle & WB_SAVEAS ) ? FILEDLG_MODE_SAVE : FILEDLG_MODE_OPEN; + _pImp->_eDlgType = FILEDLG_TYPE_FILEDLG; + + if ( ( nStyle & SFXWB_PATHDIALOG ) == SFXWB_PATHDIALOG ) + _pImp->_eDlgType = FILEDLG_TYPE_PATHDLG; + + // Set the directory for the "back to the default dir" button + INetURLObject aStdDirObj( SvtPathOptions().GetWorkPath() ); + SetStandardDir( aStdDirObj.GetMainURL( INetURLObject::NO_DECODE ) ); + + // Reichweite bestimmen. + if ( !( nStyle & SFXWB_NOREMOTE ) ) + { + _pImp->_nState |= FILEDLG_STATE_REMOTE; + } + + // Kontrollelement erzeugen, wobei die Reihenfolge die Tab-Steuerung + // bestimmt. + _pImp->_pFtFileName = new FixedText( this, SvtResId( FT_EXPLORERFILE_FILENAME ) ); + + SvtURLBox* pURLBox = new SvtURLBox( this ); + pURLBox->SetUrlFilter( &m_aURLFilter ); + _pImp->_pEdFileName = pURLBox; + + Edit aDummy( this, SvtResId( ED_EXPLORERFILE_FILENAME ) ); + _pImp->_pEdFileName->SetPosSizePixel( aDummy.GetPosPixel(), aDummy.GetSizePixel() ); + _pImp->_pEdFileName->Show(); + pURLBox->SetSelectHdl( LINK( this, SvtFileDialog, EntrySelectHdl_Impl ) ); + pURLBox->SetOpenHdl( STATIC_LINK( this, SvtFileDialog, OpenHdl_Impl ) ); + + // in folder picker mode, only auto-complete directories (no files) + bool bIsFolderPicker = ( _pImp->_eDlgType == FILEDLG_TYPE_PATHDLG ); + pURLBox->SetOnlyDirectories( bIsFolderPicker ); + + // in save mode, don't use the autocompletion as selection in the edit part + bool bSaveMode = ( FILEDLG_MODE_SAVE == _pImp->_eMode ); + pURLBox->SetNoURLSelection( bSaveMode ); + + _pImp->_pEdFileName->SetHelpId( HID_FILEDLG_AUTOCOMPLETEBOX ); + + _pImp->_pFtFileType = new FixedText( this, SvtResId( FT_EXPLORERFILE_FILETYPE ) ); + _pImp->CreateFilterListControl( this, SvtResId( LB_EXPLORERFILE_FILETYPE ) ); + + // move the filter listbox to the space occupied by the version listbox + // if that box isn't needed + if ( !( _nExtraBits & SFX_EXTRA_SHOWVERSIONS ) && + !( _nExtraBits & SFX_EXTRA_TEMPLATES ) && + !( _nExtraBits & SFX_EXTRA_IMAGE_TEMPLATE ) ) + { + { + FixedText aSharedListBoxLabel( this, SvtResId( FT_EXPLORERFILE_SHARED_LISTBOX ) ); + _pImp->_pFtFileType->SetPosPixel( aSharedListBoxLabel.GetPosPixel() ); + } + + { + ListBox aSharedListBox( this, SvtResId( LB_EXPLORERFILE_SHARED_LISTBOX ) ); + _pImp->GetFilterListControl()->SetPosPixel( aSharedListBox.GetPosPixel() ); + } + } + + _pImp->_pFtCurrentPath = new FixedText( this, SvtResId( FT_EXPLORERFILE_CURRENTPATH ) ); + WinBits nTmpStyle = _pImp->_pFtCurrentPath->GetStyle(); + nTmpStyle |= WB_PATHELLIPSIS; + _pImp->_pFtCurrentPath->SetStyle( nTmpStyle ); + + _pImp->_pBtnFileOpen = new PushButton( this, SvtResId( BTN_EXPLORERFILE_OPEN ) ); + _pImp->_pBtnCancel = new CancelButton( this, SvtResId( BTN_EXPLORERFILE_CANCEL ) ); + _pImp->_pBtnHelp = new HelpButton( this, SvtResId( BTN_EXPLORERFILE_HELP ) ); + + _pImp->_pBtnUp = new SvtUpButton_Impl( this, SvtResId( BTN_EXPLORERFILE_UP ) ); + _pImp->_pBtnNewFolder = new ImageButton( this, SvtResId( BTN_EXPLORERFILE_NEWFOLDER ) ); + _pImp->_pBtnNewFolder->SetStyle( _pImp->_pBtnNewFolder->GetStyle() | WB_NOPOINTERFOCUS ); + _pImp->_pBtnStandard = new SvtTravelButton_Impl( this, SvtResId( BTN_EXPLORERFILE_STANDARD ) ); + + _pImp->_pBtnUp->SetAccessibleName( _pImp->_pBtnUp->GetQuickHelpText() ); + _pImp->_pBtnNewFolder->SetAccessibleName( _pImp->_pBtnNewFolder->GetQuickHelpText() ); + _pImp->_pBtnStandard->SetAccessibleName( _pImp->_pBtnStandard->GetQuickHelpText() ); + + if ( ( nStyle & SFXWB_MULTISELECTION ) == SFXWB_MULTISELECTION ) + _pImp->_bMultiSelection = TRUE; + + _pFileView = new SvtFileView( this, SvtResId( CTL_EXPLORERFILE_FILELIST ), + FILEDLG_TYPE_PATHDLG == _pImp->_eDlgType, + _pImp->_bMultiSelection ); + _pFileView->SetUrlFilter( &m_aURLFilter ); + _pFileView->EnableAutoResize(); + + _pFileView->SetHelpId( HID_FILEDLG_STANDARD ); + _pFileView->SetStyle( _pFileView->GetStyle() | WB_TABSTOP ); + + // Positionen und Groessen der Knoepfe bestimmen. + Image aNewFolderImg( GetButtonImage( IMG_FILEDLG_CREATEFOLDER ) ); + _pImp->_pBtnNewFolder->SetModeImage( aNewFolderImg ); + + Size aSize( aNewFolderImg.GetSizePixel() ); + aSize.Width() += FILEDIALOG_DEF_IMAGEBORDER; + aSize.Height() += FILEDIALOG_DEF_IMAGEBORDER; + _pImp->_pBtnNewFolder->SetSizePixel( aSize ); + _pImp->_pBtnUp->SetSizePixel( aSize ); + _pImp->_pBtnStandard->SetSizePixel( aSize ); + + Size aDlgSize = GetOutputSizePixel(); + long n6AppFontInPixel = + LogicToPixel( Size( 6, 0 ), MAP_APPFONT ).Width(); + long n3AppFontInPixel = + LogicToPixel( Size( 3, 0 ), MAP_APPFONT ).Width(); + + // calculate the length of all buttons + const USHORT nBtnCount = 3; // "previous level", "new folder" and "standard dir" + long nDelta = n6AppFontInPixel; // right border + nDelta += ( nBtnCount * aSize.Width() ); // button count * button width + nDelta += ( n3AppFontInPixel + n3AppFontInPixel / 2 ); // spacing 1*big 1*small + + Point aPos( + aDlgSize.Width() - nDelta, + _pImp->_pBtnUp->GetPosPixel().Y() + ); + Size aCurPathSize( + aPos.X() - n6AppFontInPixel, + _pImp->_pFtCurrentPath->GetOutputSizePixel().Height() + ); + _pImp->_pFtCurrentPath->SetOutputSizePixel( aCurPathSize ); + _pImp->_pBtnUp->SetPosPixel( aPos ); + aPos.X() += aSize.Width(); + aPos.X() += n3AppFontInPixel; + _pImp->_pBtnNewFolder->SetPosPixel( aPos ); + aPos.X() += aSize.Width(); + aPos.X() += n3AppFontInPixel / 2; + _pImp->_pBtnStandard->SetPosPixel( aPos ); + nDelta = aSize.Height(); + nDelta -= aCurPathSize.Height(); + nDelta /= 2; + Point aCurPathPos = _pImp->_pFtCurrentPath->GetPosPixel(); + aCurPathPos.Y() += nDelta; + _pImp->_pFtCurrentPath->SetPosPixel( aCurPathPos ); + + if ( nStyle & SFXWB_READONLY ) + { + _pCbReadOnly = new CheckBox( this, SvtResId( CB_EXPLORERFILE_READONLY ) ); + _pCbReadOnly->SetHelpId( HID_FILEOPEN_READONLY ); + _pCbReadOnly->SetText( SvtResId( STR_SVT_FILEPICKER_READONLY ) ); + AddControl( _pCbReadOnly ); + ReleaseOwnerShip( _pCbReadOnly ); + _pCbReadOnly->SetClickHdl( LINK( this, SvtFileDialog, ClickHdl_Impl ) ); + } + + if ( nStyle & SFXWB_PASSWORD ) + { + _pImp->_pCbPassword = new CheckBox( this, SvtResId( CB_EXPLORERFILE_PASSWORD ) ); + _pImp->_pCbPassword->SetText( SvtResId( STR_SVT_FILEPICKER_PASSWORD ) ); + AddControl( _pImp->_pCbPassword ); + ReleaseOwnerShip( _pImp->_pCbPassword ); + _pImp->_pCbPassword->SetClickHdl( LINK( this, SvtFileDialog, ClickHdl_Impl ) ); + } + + // set the ini file for extracting the size + _pImp->_aIniKey = IODLG_CONFIGNAME; + + AddControls_Impl( ); + + // Zahl der Pixel bestimmen, um die die anderen Elemente in der Position + // Angepasst werden muessen. + aPos.Y() += aSize.Height(); + aPos.Y() += LogicToPixel( Size( 0, 6 ), MAP_APPFONT ).Height(); + long nYOffset = aPos.Y(); + aPos = _pFileView->GetPosPixel(); + nYOffset -= aPos.Y(); + + // Positionen der uebrigen Elemente anpassen. + aPos.Y() += nYOffset; + _pFileView->SetPosPixel( aPos ); + + lcl_MoveControl( _pImp->_pFtFileName, 0, nYOffset ); + lcl_MoveControl( _pImp->_pEdFileName, 0, nYOffset ); + + lcl_MoveControl( _pImp->_pFtFileVersion, 0, nYOffset ); + lcl_MoveControl( _pImp->_pLbFileVersion, 0, nYOffset ); + + lcl_MoveControl( _pImp->_pFtTemplates, 0, nYOffset ); + lcl_MoveControl( _pImp->_pLbTemplates, 0, nYOffset ); + + lcl_MoveControl( _pImp->_pFtImageTemplates, 0, nYOffset ); + lcl_MoveControl( _pImp->_pLbImageTemplates, 0, nYOffset ); + + lcl_MoveControl( _pImp->_pFtFileType, 0, nYOffset ); + lcl_MoveControl( _pImp->GetFilterListControl(), 0, nYOffset ); + + lcl_MoveControl( _pImp->_pBtnFileOpen, 0, nYOffset ); + lcl_MoveControl( _pImp->_pBtnCancel, 0, nYOffset ); + + lcl_MoveControl( _pImp->_pBtnHelp, 0, nYOffset + 3 ); + // a little more spacing between Cancel- and HelpButton + + // Groesse des Dialoges anpassen. + aSize = GetSizePixel(); + aSize.Height() += nYOffset; + SetSizePixel( aSize ); + + // Beschriftungen dem Modus anpassen. + USHORT nResId = STR_EXPLORERFILE_OPEN; + USHORT nButtonResId = 0; + + if ( nStyle & WB_SAVEAS ) + { + nResId = STR_EXPLORERFILE_SAVE; + nButtonResId = STR_EXPLORERFILE_BUTTONSAVE; + } + + if ( ( nStyle & SFXWB_PATHDIALOG ) == SFXWB_PATHDIALOG ) + { + _pImp->_pFtFileName->SetText( SvtResId( STR_PATHNAME ) ); + nResId = STR_PATHSELECT; + nButtonResId = STR_BUTTONSELECT; + } + + SetText( SvtResId( nResId ) ); + + if ( nButtonResId ) + _pImp->_pBtnFileOpen->SetText( SvtResId( nButtonResId ) ); + + if ( FILEDLG_TYPE_FILEDLG != _pImp->_eDlgType ) + { + _pImp->_pFtFileType->Hide(); + _pImp->GetFilterListControl()->Hide(); + } + + // Einstellungen der Steuerelemente vornehmen. + _pImp->_pBtnNewFolder->SetClickHdl( STATIC_LINK( this, SvtFileDialog, NewFolderHdl_Impl ) ); + _pImp->_pBtnFileOpen->SetClickHdl( STATIC_LINK( this, SvtFileDialog, OpenHdl_Impl ) ); + _pImp->_pBtnCancel->SetClickHdl( LINK( this, SvtFileDialog, CancelHdl_Impl ) ); + _pImp->SetFilterListSelectHdl( STATIC_LINK( this, SvtFileDialog, FilterSelectHdl_Impl ) ); + _pImp->_pEdFileName->SetGetFocusHdl( STATIC_LINK( this, SvtFileDialog, FileNameGetFocusHdl_Impl ) ); + _pImp->_pEdFileName->SetModifyHdl( STATIC_LINK( this, SvtFileDialog, FileNameModifiedHdl_Impl ) ); + _pFileView->SetSelectHdl( LINK( this, SvtFileDialog, SelectHdl_Impl ) ); + _pFileView->SetDoubleClickHdl( LINK( this, SvtFileDialog, DblClickHdl_Impl ) ); + _pFileView->SetOpenDoneHdl( LINK( this, SvtFileDialog, OpenDoneHdl_Impl ) ); + + // Resourcen freigeben. + FreeResource(); + + // Timer fuer Filterbox Travel setzen + _pImp->_aFilterTimer.SetTimeout( TRAVELFILTER_TIMEOUT ); + _pImp->_aFilterTimer.SetTimeoutHdl( STATIC_LINK( this, SvtFileDialog, FilterSelectHdl_Impl ) ); + + if ( WB_SAVEAS & nStyle ) + { + // different help ids if in save-as mode + // 90744 - 09.08.2001 - frank.schoenheit@sun.com + SetHelpId( HID_FILESAVE_DIALOG ); + + _pImp->_pEdFileName->SetHelpId( HID_FILESAVE_FILEURL ); + _pImp->_pBtnFileOpen->SetHelpId( HID_FILESAVE_DOSAVE ); + _pImp->_pBtnNewFolder->SetHelpId( HID_FILESAVE_CREATEDIRECTORY ); + _pImp->_pBtnStandard->SetHelpId( HID_FILESAVE_DEFAULTDIRECTORY ); + _pImp->_pBtnUp->SetHelpId( HID_FILESAVE_LEVELUP ); + _pImp->GetFilterListControl()->SetHelpId( HID_FILESAVE_FILETYPE ); + _pFileView->SetHelpId( HID_FILESAVE_FILEVIEW ); + + // formerly, there was only _pLbFileVersion, which was used for 3 different + // use cases. For reasons of maintainability, I introduced extra members (_pLbTemplates, _pLbImageTemplates) + // for the extra use cases, and separated _pLbFileVersion + // I did not find out in which cases the help ID is really needed HID_FILESAVE_TEMPLATE - all + // tests I made lead to a dialog where _no_ of the three list boxes was present. + // 96930 - 15.08.2002 - fs@openoffice.org + if ( _pImp->_pLbFileVersion ) + _pImp->_pLbFileVersion->SetHelpId( HID_FILESAVE_TEMPLATE ); + if ( _pImp->_pLbTemplates ) + _pImp->_pLbTemplates->SetHelpId( HID_FILESAVE_TEMPLATE ); + if ( _pImp->_pLbImageTemplates ) + _pImp->_pLbImageTemplates->SetHelpId( HID_FILESAVE_TEMPLATE ); + + if ( _pImp->_pCbPassword ) _pImp->_pCbPassword->SetHelpId( HID_FILESAVE_SAVEWITHPASSWORD ); + if ( _pImp->_pCbAutoExtension ) _pImp->_pCbAutoExtension->SetHelpId( HID_FILESAVE_AUTOEXTENSION ); + if ( _pImp->_pCbOptions ) _pImp->_pCbOptions->SetHelpId( HID_FILESAVE_CUSTOMIZEFILTER ); + if ( _pCbSelection ) _pCbSelection->SetHelpId( HID_FILESAVE_SELECTION ); + } + + // correct the z-order of the controls + implArrangeControls(); + + // special URLs, such as favourites and "restricted" paths + implInitializeSpecialURLLists( ); + + /// read our settings from the configuration + m_aConfiguration = OConfigurationTreeRoot::createWithServiceFactory( + ::comphelper::getProcessServiceFactory(), + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI/FilePicker" ) ) + ); +} + +//***************************************************************************** + +IMPL_STATIC_LINK( SvtFileDialog, NewFolderHdl_Impl, PushButton*, EMPTYARG ) +{ + pThis->_pFileView->EndInplaceEditing( false ); + + INetURLObject aObj( pThis->_pFileView->GetViewURL() ); + String sFolderName = aObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET, RTL_TEXTENCODING_UTF8 ); + svtools::QueryFolderNameDialog aDlg( pThis, sFolderName, String( SvtResId( STR_SVT_NEW_FOLDER ) ) ); + sal_Bool bHandled = sal_False; + + while ( !bHandled ) + { + if ( aDlg.Execute() == RET_OK ) + bHandled = pThis->_pFileView->CreateNewFolder( aDlg.GetName() ); + else + bHandled = sal_True; + } + + return 0; +} + +//***************************************************************************** + +IMPL_STATIC_LINK_NOINSTANCE( SvtFileDialog, ViewHdl_Impl, ImageButton*, EMPTYARG ) +{ + return 0; +} + +//***************************************************************************** +//----------------------------------------------------------------------------- +sal_Bool SvtFileDialog::createNewUserFilter( const String& _rNewFilter, sal_Bool _bAllowUserDefExt ) +{ + // delete the old user filter and create a new one + DELETEZ( _pImp->_pUserFilter ); + _pImp->_pUserFilter = new SvtFileDialogFilter_Impl( _rNewFilter, _rNewFilter ); + + // remember the extension + sal_Bool bIsAllFiles = _rNewFilter.EqualsAscii( FILEDIALOG_FILTER_ALL ); + if ( bIsAllFiles ) + EraseDefaultExt(); + else + SetDefaultExt( _rNewFilter.Copy( 2 ) ); + // TODO: this is nonsense. In the whole file there are a lotta places where we assume that a user filter + // is always "*.<something>". But changing this would take some more time than I have now ... + // 05.12.2001 - 95486 - fs@openoffice.org + + // now, the default extension is set to the one of the user filter (or empty) + // if the former is not allowed (_bAllowUserDefExt = <FALSE/>), we have to use the ext of the current filter + // (if possible) + sal_Bool bUseCurFilterExt = sal_True; + String sUserFilter = _pImp->_pUserFilter->GetType(); + xub_StrLen nSepPos = sUserFilter.SearchBackward( '.' ); + if ( STRING_NOTFOUND != nSepPos ) + { + String sUserExt = sUserFilter.Copy( nSepPos + 1 ); + if ( ( STRING_NOTFOUND == sUserExt.Search( '*' ) ) + && ( STRING_NOTFOUND == sUserExt.Search( '?' ) ) + ) + bUseCurFilterExt = sal_False; + } + + if ( !_bAllowUserDefExt || bUseCurFilterExt ) + { + if ( _pImp->GetCurFilter( ) ) + SetDefaultExt( _pImp->GetCurFilter( )->GetExtension() ); + else + EraseDefaultExt(); + } + + // outta here + return bIsAllFiles; +} + +//----------------------------------------------------------------------------- +#define FLT_NONEMPTY 0x0001 +#define FLT_CHANGED 0x0002 +#define FLT_USERFILTER 0x0004 +#define FLT_ALLFILESFILTER 0x0008 + +//----------------------------------------------------------------------------- +sal_uInt16 SvtFileDialog::adjustFilter( const String& _rFilter ) +{ + sal_uInt16 nReturn = 0; + + const sal_Bool bNonEmpty = ( _rFilter.Len() != 0 ); + if ( bNonEmpty ) + { + nReturn |= FLT_NONEMPTY; + + sal_Bool bFilterChanged = sal_True; + + // search for a corresponding filter + SvtFileDialogFilter_Impl* pFilter = FindFilter_Impl( _rFilter, FALSE, bFilterChanged ); + +#ifdef AUTOSELECT_USERFILTER + // if we found a filter which without allowing multi-extensions -> select it + if ( pFilter ) + { + _pImp->SelectFilterListEntry( pFilter->GetName() ); + _pImp->SetCurFilter( pFilter ); + } +#endif // AUTOSELECT_USERFILTER + + // look for multi-ext filters if necessary + if ( !pFilter ) + pFilter = FindFilter_Impl( _rFilter, TRUE, bFilterChanged ); + + if ( bFilterChanged ) + nReturn |= FLT_CHANGED; + + if ( !pFilter ) + { + nReturn |= FLT_USERFILTER; + // no filter found : use it as user defined filter +#ifdef AUTOSELECT_USERFILTER + if ( createNewUserFilter( _rFilter, sal_True ) ) +#else + if ( createNewUserFilter( _rFilter, sal_False ) ) +#endif + { // it's the "all files" filter + nReturn |= FLT_ALLFILESFILTER; + +#ifdef AUTOSELECT_USERFILTER + // select the "all files" entry + String sAllFilesFilter( SvtResId( STR_FILTERNAME_ALL ) ); + if ( _pImp->HasFilterListEntry( sAllFilesFilter ) ) + { + _pImp->SelectFilterListEntry( sAllFilesFilter ); + _pImp->SetCurFilter( _pImp->GetSelectedFilterEntry( sAllFilesFilter ) ); + } + else + _pImp->SetNoFilterListSelection( ); // there is no "all files" entry +#endif // AUTOSELECT_USERFILTER + } +#ifdef AUTOSELECT_USERFILTER + else + _pImp->SetNoFilterListSelection( ); +#endif // AUTOSELECT_USERFILTER + } + } + + return nReturn; +} + +//----------------------------------------------------------------------------- +IMPL_LINK( SvtFileDialog, CancelHdl_Impl, void*, EMPTYARG ) +{ + if ( m_pCurrentAsyncAction.is() ) + { + m_pCurrentAsyncAction->cancel(); + onAsyncOperationFinished(); + } + else + { + EndDialog( FALSE ); + } + return 1L; +} + +//----------------------------------------------------------------------------- +IMPL_STATIC_LINK( SvtFileDialog, OpenHdl_Impl, void*, pVoid ) +{ + if ( pThis->_pImp->_bMultiSelection && pThis->_pFileView->GetSelectionCount() > 1 ) + { + // bei Multiselektion spezielles Open + pThis->OpenMultiSelection_Impl(); + return 0; + } + + String aFileName; + String aOldPath( pThis->_pFileView->GetViewURL() ); + if ( pThis->_pImp->_bDoubleClick || pThis->_pFileView->HasChildPathFocus() ) + // Selection done by doubleclicking in the view, get filename from the view + aFileName = pThis->_pFileView->GetCurrentURL(); + + if ( !aFileName.Len() ) + { + // if an entry is selected in the view .... + if ( pThis->_pFileView->GetSelectionCount() ) + { // -> use this one. This will allow us to step down this folder + // #i8928# - 2002-12-20 - fs@openoffice.org + aFileName = pThis->_pFileView->GetCurrentURL(); + } + } + + if ( !aFileName.Len() ) + { + if ( pThis->_pImp->_eMode == FILEDLG_MODE_OPEN && pThis->_pImp->_pEdFileName->IsTravelSelect() ) + // OpenHdl called from URLBox; travelling through the list of URLs should not cause an opening + return 0; // MBA->PB: seems to be called never ?! + + // get the URL from from the edit field ( if not empty ) + if ( pThis->_pImp->_pEdFileName->GetText().Len() ) + { + String aText = pThis->_pImp->_pEdFileName->GetText(); + + // did we reach the root? + if ( !INetURLObject( aOldPath ).getSegmentCount() ) + { + if ( ( aText.Len() == 2 && aText.EqualsAscii( ".." ) ) || + ( aText.Len() == 3 && ( aText.EqualsAscii( "..\\" ) || aText.EqualsAscii( "../" ) ) ) ) + // don't go higher than the root + return 0; + } + +#if defined( UNX ) || defined( FS_PRIV_DEBUG ) + if ( ( 1 == aText.Len() ) && ( '~' == aText.GetBuffer()[0] ) ) + { + // go to the home directory + if ( lcl_getHomeDirectory( pThis->_pFileView->GetViewURL(), aFileName ) ) + // in case we got a home dir, reset the text of the edit + pThis->_pImp->_pEdFileName->SetText( String() ); + } + if ( !aFileName.Len() ) +#endif + { + // get url from autocomplete edit + aFileName = pThis->_pImp->_pEdFileName->GetURL(); + } + } + else if ( pVoid == pThis->_pImp->_pBtnFileOpen ) + // OpenHdl was called for the "Open" Button; if edit field is empty, use selected element in the view + aFileName = pThis->_pFileView->GetCurrentURL(); + } + + // MBA->PB: ?! + if ( !aFileName.Len() && pVoid == pThis->_pImp->_pEdFileName && pThis->_pImp->_pUserFilter ) + { + DELETEZ( pThis->_pImp->_pUserFilter ); + return 0; + } + + USHORT nLen = aFileName.Len(); + if ( !nLen ) + { + // if the dialog was opened to select a folder, the last selected folder should be selected + if( pThis->_pImp->_eDlgType == FILEDLG_TYPE_PATHDLG ) + { + aFileName = pThis->_pImp->_pFtCurrentPath->GetText(); + nLen = aFileName.Len(); + } + else + // no file selected ! + return 0; + } + + // mark input as selected + pThis->_pImp->_pEdFileName->SetSelection( Selection( 0, nLen ) ); + + // if a path with wildcards is given, divide the string into path and wildcards + String aFilter; + if ( !pThis->IsolateFilterFromPath_Impl( aFileName, aFilter ) ) + return 0; + + // if a filter was retrieved, there were wildcards ! + sal_uInt16 nNewFilterFlags = pThis->adjustFilter( aFilter ); + if ( nNewFilterFlags & FLT_CHANGED ) + { + // cut off all text before wildcard in edit and select wildcard + pThis->_pImp->_pEdFileName->SetText( aFilter ); + pThis->_pImp->_pEdFileName->SetSelection( Selection( 0, aFilter.Len() ) ); + } + + { + INetURLObject aFileObject( aFileName ); + if ( ( aFileObject.GetProtocol() == INET_PROT_NOT_VALID ) && aFileName.Len() ) + { + String sCompleted = SvtURLBox::ParseSmart( aFileName, pThis->_pFileView->GetViewURL(), SvtPathOptions().GetWorkPath() ); + if ( sCompleted.Len() ) + aFileName = sCompleted; + } + } + + // Pr"ufen, ob es sich um einen Ordner handelt. + BOOL bIsFolder = FALSE; + + // first thing before doing anyhing with the content: Reset it. When the user presses "open" (or "save" or "export", + // for that matter), s/he wants the complete handling, including all possible error messages, even if s/he + // does the same thing for the same content twice, s/he wants both fails to be displayed. + // Without the reset, it could be that the content cached all relevant information, and will not display any + // error messages for the same content a second time .... + pThis->m_aContent.bindTo( ::rtl::OUString( ) ); + + // #97148# & #102204# --------- + if ( aFileName.Len() ) + { + // Make sure we have own Interaction Handler in place. We do not need + // to intercept interactions here, but to record the fact that there + // was an interaction. + SmartContent::InteractionHandlerType eInterActionHandlerType + = pThis->m_aContent.queryCurrentInteractionHandler(); + if ( ( eInterActionHandlerType == SmartContent::IHT_NONE ) || + ( eInterActionHandlerType == SmartContent::IHT_DEFAULT ) ) + pThis->m_aContent.enableOwnInteractionHandler( + OFilePickerInteractionHandler::E_NOINTERCEPTION ); + + bIsFolder = pThis->m_aContent.isFolder( aFileName ); + + // access denied to the given resource - and interaction was already + // used => break following operations + OFilePickerInteractionHandler* pHandler + = pThis->m_aContent.getOwnInteractionHandler(); + + OSL_ENSURE( pHandler, "Got no Interaction Handler!!!" ); + + if ( pHandler->wasAccessDenied() ) + return 0; + + if ( pThis->m_aContent.isInvalid() && + ( pThis->_pImp->_eMode == FILEDLG_MODE_OPEN ) ) + { + if ( !pHandler->wasUsed() ) + ErrorHandler::HandleError( ERRCODE_IO_NOTEXISTS ); + + return 0; + } + + // restore previous Interaction Handler + if ( eInterActionHandlerType == SmartContent::IHT_NONE ) + pThis->m_aContent.disableInteractionHandler(); + else if ( eInterActionHandlerType == SmartContent::IHT_DEFAULT ) + pThis->m_aContent.enableDefaultInteractionHandler(); + } + + if ( !bIsFolder // no existent folder + && pThis->_pImp->_pCbAutoExtension // auto extension is enabled in general + && pThis->_pImp->_pCbAutoExtension->IsChecked() // auto extension is really to be used + && pThis->GetDefaultExt().Len() // there is a default extension + && pThis->GetDefaultExt() != '*' // the default extension is not "all" + && !( FILEDLG_MODE_SAVE == pThis->_pImp->_eMode // we're saving a file + && pThis->_pFileView->GetSelectionCount() // there is a selected file in the file view -> it will later on + ) // (in SvtFileDialog::GetPathList) be taken as file to save to + // (#114818# - 2004-03-17 - fs@openoffice.org) + && FILEDLG_MODE_OPEN != pThis->_pImp->_eMode // pb: #i83408# don't append extension on open + ) + { + // check extension and append the default extension if necessary + appendDefaultExtension(aFileName, + pThis->GetDefaultExt(), + pThis->_pImp->GetCurFilter()->GetType()); + } + + BOOL bOpenFolder = ( FILEDLG_TYPE_PATHDLG == pThis->_pImp->_eDlgType ) && + !pThis->_pImp->_bDoubleClick && pVoid != pThis->_pImp->_pEdFileName; + if ( bIsFolder ) + { + if ( bOpenFolder ) + { + pThis->_aPath = aFileName; + } + else + { + if ( aFileName != pThis->_pFileView->GetViewURL() ) + { + if ( !pThis->m_aURLFilter.isUrlAllowed( aFileName ) ) + { + pThis->simulateAccessDenied( aFileName ); + return 0; + } + + pThis->OpenURL_Impl( aFileName ); + } + else + { + if ( nNewFilterFlags & FLT_CHANGED ) + pThis->ExecuteFilter(); + } + + return 0; + } + } + else if ( !( nNewFilterFlags & FLT_NONEMPTY ) ) + { + // Ggf. URL speichern. + pThis->_aPath = aFileName; + } + else + { + // Ggf. neu filtern. + if ( nNewFilterFlags & FLT_CHANGED ) + pThis->ExecuteFilter(); + return 0; + } + + INetURLObject aFileObj( aFileName ); + if ( aFileObj.HasError() ) + { + ErrorHandler::HandleError( ERRCODE_IO_GENERAL ); + return 0; + } + + // if restrictions for the allowed folders are in place, we need to do a check here + if ( !pThis->m_aURLFilter.isUrlAllowed( aFileObj.GetMainURL( INetURLObject::NO_DECODE ) ) ) + { + pThis->simulateAccessDenied( aFileName ); + return 0; + } + + switch ( pThis->_pImp->_eMode ) + { + case FILEDLG_MODE_SAVE: + { + if ( ::utl::UCBContentHelper::Exists( aFileObj.GetMainURL( INetURLObject::NO_DECODE ) ) ) + { + QueryBox aBox( pThis, WB_YES_NO, SvtResId( STR_SVT_ALREADYEXISTOVERWRITE ) ); + if ( aBox.Execute() != RET_YES ) + return 0; + } + else + { + String aCurPath; + if ( ::utl::LocalFileHelper::ConvertURLToSystemPath( aFileName, aCurPath ) ) + { + // if content does not exist: at least its path must exist + INetURLObject aPathObj = aFileObj; + aPathObj.removeSegment(); + // #97148# & #102204# ------------ + BOOL bFolder = pThis->m_aContent.isFolder( aPathObj.GetMainURL( INetURLObject::NO_DECODE ) ); + if ( !bFolder ) + { + ErrorHandler::HandleError( ERRCODE_IO_NOTEXISTSPATH ); + return 0; + } + } + } + } + break; + + case FILEDLG_MODE_OPEN: + { + // do an existence check herein, again + // 16.11.2001 - 93107 - frank.schoenheit@sun.com + + if ( INET_PROT_FILE == aFileObj.GetProtocol( ) ) + { + sal_Bool bExists = sal_False; + // #102204# -------------- + bExists = pThis->m_aContent.is( aFileObj.GetMainURL( INetURLObject::NO_DECODE ) ); + + + if ( !bExists ) + { + String sError( SvtResId( RID_FILEOPEN_NOTEXISTENTFILE ) ); + + String sInvalidFile( aFileObj.GetMainURL( INetURLObject::DECODE_TO_IURI ) ); + if ( INET_PROT_FILE == aFileObj.GetProtocol() ) + { // if it's a file URL, transform the URL into system notation + ::rtl::OUString sURL( sInvalidFile ); + ::rtl::OUString sSystem; + osl_getSystemPathFromFileURL( sURL.pData, &sSystem.pData ); + sInvalidFile = sSystem; + } + sError.SearchAndReplaceAscii( "$name$", sInvalidFile ); + + ErrorBox aError( pThis, WB_OK, sError ); + aError.Execute(); + return 0; + } + } + } + break; + + default: + DBG_ERROR("SvtFileDialog, OpenHdl_Impl: invalid mode!"); + } + + // Interessenten benachrichtigen. + long nRet; + + if ( pThis->_aOKHdl.IsSet() ) + nRet = pThis->_aOKHdl.Call( pThis ); + else + nRet = pThis->OK(); + + if ( nRet ) + { + pThis->EndDialog( TRUE ); + } + + return nRet; +} + +//***************************************************************************** + +void SvtFileDialog::EnableAutocompletion( BOOL _bEnable ) +{ + _pImp->_pEdFileName->EnableAutocompletion( _bEnable ); +} + +//***************************************************************************** + +IMPL_STATIC_LINK( SvtFileDialog, FilterSelectHdl_Impl, ListBox*, pBox ) +{ + DBG_ASSERT( pBox, "SvtFileDialog:keine Instanz" ); + + // wurde der Handler vom Travel-Timer gefeuert? + if ( pBox == (ListBox*)&pThis->_pImp->_aFilterTimer ) + { + // Anzeige erneut filtern. + pThis->ExecuteFilter(); + return 0; + } + + String sSelectedFilterDisplayName; + SvtFileDialogFilter_Impl* pSelectedFilter = pThis->_pImp->GetSelectedFilterEntry( sSelectedFilterDisplayName ); + if ( !pSelectedFilter ) + { // there is no current selection. This happens if for instance the user selects a group separator using + // the keyboard, and then presses enter: When the selection happens, we immediately deselect the entry, + // so in this situation there is no current selection. + if ( restoreCurrentFilter( pThis->_pImp ) ) + pThis->ExecuteFilter(); + } + else + { + if ( pSelectedFilter->isGroupSeparator() ) + { // group separators can't be selected + // return to the previously selected entry + if ( pThis->_pImp->IsFilterListTravelSelect() ) + { + pThis->_pImp->SetNoFilterListSelection( ); + + // stop the timer for executing the filter + if ( pThis->_pImp->_aFilterTimer.IsActive() ) + pThis->_pImp->m_bNeedDelayedFilterExecute = sal_True; + pThis->_pImp->_aFilterTimer.Stop(); + } + else + { + if ( restoreCurrentFilter( pThis->_pImp ) ) + pThis->ExecuteFilter(); + } + } + else if ( ( pSelectedFilter != pThis->_pImp->GetCurFilter() ) + || pThis->_pImp->_pUserFilter + ) + { + // Store the old filter for the auto extension handling + String sLastFilterExt = pThis->_pImp->GetCurFilter()->GetExtension(); + DELETEZ( pThis->_pImp->_pUserFilter ); + + // Ggf. Filter des Benutzers entfernen. + pThis->_pImp->SetCurFilter( pSelectedFilter, sSelectedFilterDisplayName ); + + // Ggf. Endung anzeigen. + pThis->SetDefaultExt( pSelectedFilter->GetExtension() ); + USHORT nSepPos = pThis->GetDefaultExt().Search( FILEDIALOG_DEF_EXTSEP ); + + if ( nSepPos != STRING_NOTFOUND ) + pThis->EraseDefaultExt( nSepPos ); + + // update the extension of the current file if necessary + lcl_autoUpdateFileExtension( pThis, sLastFilterExt ); + + // wenn der Benutzer schnell durch die Filterbox + // travelt, nicht sofort Filtern + if ( pThis->_pImp->IsFilterListTravelSelect() ) + { + // FilterSelectHdl_Impl soll in + // TRAVELFILTER_TIMEOUT ms neu gefeuert werden + pThis->_pImp->_aFilterTimer.Start(); + } + else + { + // evtl. vorher gestarteten Timer stoppen + pThis->_pImp->_aFilterTimer.Stop(); + + // Anzeige erneut filtern. + pThis->ExecuteFilter(); + } + } + } + + return 0; +} + +//***************************************************************************** + +IMPL_STATIC_LINK( SvtFileDialog, FileNameGetFocusHdl_Impl, void*, EMPTYARG ) +{ + pThis->_pFileView->SetNoSelection(); + pThis->_pFileView->Update(); + return 0; +} + +//***************************************************************************** + +IMPL_STATIC_LINK( SvtFileDialog, FileNameModifiedHdl_Impl, void*, EMPTYARG ) +{ + FileNameGetFocusHdl_Impl( pThis, NULL ); + return 0; +} + +//***************************************************************************** + +SvtFileDialogFilter_Impl* SvtFileDialog::FindFilter_Impl +( + const String& _rFilter, + sal_Bool _bMultiExt,/* TRUE - auch Filter mit mehreren Endungen + beruecksichtigen + FALSE - keine ... + */ + sal_Bool& _rFilterChanged +) + +/* [Beschreibung] + + Die Methode sucht in den eingef"ugten Filtern nach der + spezifizierten Endung. +*/ + +{ + SvtFileDialogFilter_Impl* pFoundFilter = NULL; + SvtFileDialogFilterList_Impl* pList = _pImp->_pFilter; + USHORT nFilter = pList->Count(); + + while ( nFilter-- ) + { + SvtFileDialogFilter_Impl* pFilter = pList->GetObject( nFilter ); + const String& rType = pFilter->GetType(); + String aSingleType = rType; + + if ( _bMultiExt ) + { + USHORT nIdx = 0; + while ( !pFoundFilter && nIdx != STRING_NOTFOUND ) + { + aSingleType = rType.GetToken( 0, FILEDIALOG_DEF_EXTSEP, nIdx ); +#ifdef UNX + if ( aSingleType.CompareTo( _rFilter ) == COMPARE_EQUAL ) +#else + if ( aSingleType.CompareIgnoreCaseToAscii( _rFilter ) == COMPARE_EQUAL ) +#endif + pFoundFilter = pFilter; + } + } +#ifdef UNX + else if ( rType.CompareTo( _rFilter ) == COMPARE_EQUAL ) +#else + else if ( rType.CompareIgnoreCaseToAscii( _rFilter ) == COMPARE_EQUAL ) +#endif + pFoundFilter = pFilter; + + if ( pFoundFilter ) + { + // Filter aktivieren. + _rFilterChanged = _pImp->_pUserFilter || ( _pImp->GetCurFilter() != pFilter ); + + createNewUserFilter( _rFilter, sal_False ); + + break; + } + } + return pFoundFilter; +} + +//***************************************************************************** + +void SvtFileDialog::ExecuteFilter() +{ + _pImp->m_bNeedDelayedFilterExecute = sal_False; + executeAsync( AsyncPickerAction::eExecuteFilter, String(), getMostCurrentFilter( _pImp ) ); +} + +//***************************************************************************** + +void SvtFileDialog::OpenMultiSelection_Impl() + +/* [Beschreibung] + + OpenHandler f"ur MultiSelektion +*/ + +{ + String aPath; + ULONG nCount = _pFileView->GetSelectionCount(); + SvLBoxEntry* pEntry = nCount ? _pFileView->FirstSelected() : NULL; + + if ( nCount && pEntry ) + _aPath = _pFileView->GetURL( pEntry ); + + // Interessenten benachrichtigen. + long nRet; + + if ( _aOKHdl.IsSet() ) + nRet = _aOKHdl.Call( this ); + else + nRet = OK(); + + if ( nRet ) + EndDialog( TRUE ); +} + +//***************************************************************************** + +void SvtFileDialog::UpdateControls( const String& rURL ) +{ + _pImp->_pEdFileName->SetBaseURL( rURL ); + + INetURLObject aObj( rURL ); + + //========================================================================= + { + String sText; + DBG_ASSERT( INET_PROT_NOT_VALID != aObj.GetProtocol(), "SvtFileDialog::UpdateControls: Invalid URL!" ); + + if ( aObj.getSegmentCount() ) + { + ::utl::LocalFileHelper::ConvertURLToSystemPath( rURL, sText ); + if ( sText.Len() ) + { + // no Fsys path for server file system ( only UCB has mountpoints! ) + if ( INET_PROT_FILE != aObj.GetProtocol() ) + sText = rURL.Copy( static_cast< USHORT >( + INetURLObject::GetScheme( aObj.GetProtocol() ).getLength() ) ); + } + + if ( !sText.Len() && aObj.getSegmentCount() ) + sText = rURL; + } + + // path mode ? + if ( FILEDLG_TYPE_PATHDLG == _pImp->_eDlgType ) + // -> set new path in the edit field + _pImp->_pEdFileName->SetText( sText ); + + // in the "current path" field, truncate the trailing slash + if ( aObj.hasFinalSlash() ) + { + aObj.removeFinalSlash(); + String sURL( aObj.GetMainURL( INetURLObject::NO_DECODE ) ); + if ( !::utl::LocalFileHelper::ConvertURLToSystemPath( sURL, sText ) ) + sText = sURL; + } + + if ( !sText.Len() && rURL.Len() ) + // happens, for instance, for URLs which the INetURLObject does not know to belong to a hierarchical scheme + sText = rURL; + _pImp->_pFtCurrentPath->SetText( sText ); + } + + //========================================================================= + _aPath = rURL; + if ( _pFileNotifier ) + _pFileNotifier->notify( DIRECTORY_CHANGED, 0 ); +} + +//***************************************************************************** + +IMPL_LINK( SvtFileDialog, SelectHdl_Impl, SvTabListBox*, pBox ) +{ + SvLBoxEntry* pEntry = pBox->FirstSelected(); + DBG_ASSERT( pEntry, "SelectHandler without selected entry" ); + SvtContentEntry* pUserData = (SvtContentEntry*)pEntry->GetUserData(); + + if ( pUserData ) + { + INetURLObject aObj( pUserData->maURL ); + if ( FILEDLG_TYPE_PATHDLG == _pImp->_eDlgType ) + { + if ( aObj.GetProtocol() == INET_PROT_FILE ) + { + if ( !pUserData->mbIsFolder ) + aObj.removeSegment(); + String aName = aObj.getFSysPath( (INetURLObject::FSysStyle)(INetURLObject::FSYS_DETECT & ~INetURLObject::FSYS_VOS) ); + _pImp->_pEdFileName->SetText( aName ); + _pImp->_pEdFileName->SetSelection( Selection( 0, aName.Len() ) ); + _aPath = pUserData->maURL; + } + else if ( !pUserData->mbIsFolder ) + { + _pImp->_pEdFileName->SetText( pUserData->maURL ); + _pImp->_pEdFileName->SetSelection( Selection( 0, pUserData->maURL.Len() ) ); + _aPath = pUserData->maURL; + } + else + _pImp->_pEdFileName->SetText( UniString() ); + } + else + { + if ( !pUserData->mbIsFolder ) + { + String aName = pBox->GetEntryText( pEntry, 0 ); + _pImp->_pEdFileName->SetText( aName ); + _pImp->_pEdFileName->SetSelection( Selection( 0, aName.Len() ) ); + _aPath = pUserData->maURL; + } + } + } + + if ( _pImp->_bMultiSelection && _pFileView->GetSelectionCount() > 1 ) + { + // bei Multiselektion den Datei-Edit leeren + _pImp->_pEdFileName->SetText( String() ); + } + + FileSelect(); + + return 0; +} + +//***************************************************************************** + +IMPL_LINK( SvtFileDialog, DblClickHdl_Impl, SvTabListBox*, EMPTYARG ) +{ + _pImp->_bDoubleClick = TRUE; + OpenHdl_Impl( this, NULL ); + _pImp->_bDoubleClick = FALSE; + + return 0; +} + +//***************************************************************************** + +IMPL_LINK( SvtFileDialog, EntrySelectHdl_Impl, ComboBox*, EMPTYARG ) +{ + FileSelect(); + + return 0; +} + +//***************************************************************************** + +IMPL_LINK( SvtFileDialog, OpenDoneHdl_Impl, SvtFileView*, pView ) +{ + String sCurrentFolder( pView->GetViewURL() ); + // check if we can create new folders + EnableControl( _pImp->_pBtnNewFolder, ContentCanMakeFolder( sCurrentFolder ) && m_aURLFilter.isUrlAllowed( sCurrentFolder, false ) ); + + // check if we can travel one level up + bool bCanTravelUp = ContentHasParentFolder( pView->GetViewURL() ); + if ( bCanTravelUp ) + { + // additional check: the parent folder should not be prohibited + INetURLObject aCurrentFolder( sCurrentFolder ); + DBG_ASSERT( INET_PROT_NOT_VALID != aCurrentFolder.GetProtocol(), + "SvtFileDialog::OpenDoneHdl_Impl: invalid current URL!" ); + + aCurrentFolder.removeSegment(); + bCanTravelUp &= m_aURLFilter.isUrlAllowed( aCurrentFolder.GetMainURL( INetURLObject::NO_DECODE ) ); + } + EnableControl( _pImp->_pBtnUp, bCanTravelUp ); + + return 0; +} + +//***************************************************************************** + +IMPL_LINK( SvtFileDialog, AutoExtensionHdl_Impl, CheckBox*, EMPTYARG ) +{ + if ( _pFileNotifier ) + _pFileNotifier->notify( CTRL_STATE_CHANGED, + CHECKBOX_AUTOEXTENSION ); + + // update the extension of the current file if necessary + lcl_autoUpdateFileExtension( this, _pImp->GetCurFilter()->GetExtension() ); + + return 0; +} + +//***************************************************************************** + +IMPL_LINK( SvtFileDialog, ClickHdl_Impl, CheckBox*, pCheckBox ) +{ + if ( ! _pFileNotifier ) + return 0; + + sal_Int16 nId = -1; + + if ( pCheckBox == _pImp->_pCbOptions ) + nId = CHECKBOX_FILTEROPTIONS; + else if ( pCheckBox == _pCbSelection ) + nId = CHECKBOX_SELECTION; + else if ( pCheckBox == _pCbReadOnly ) + nId = CHECKBOX_READONLY; + else if ( pCheckBox == _pImp->_pCbPassword ) + nId = CHECKBOX_PASSWORD; + else if ( pCheckBox == _pCbLinkBox ) + nId = CHECKBOX_LINK; + else if ( pCheckBox == _pCbPreviewBox ) + nId = CHECKBOX_PREVIEW; + + if ( nId != -1 ) + _pFileNotifier->notify( CTRL_STATE_CHANGED, nId ); + + return 0; +} + +//***************************************************************************** + +IMPL_LINK( SvtFileDialog, PlayButtonHdl_Impl, PushButton*, EMPTYARG ) +{ + if ( _pFileNotifier ) + _pFileNotifier->notify( CTRL_STATE_CHANGED, + PUSHBUTTON_PLAY ); + + return 0; +} + +//***************************************************************************** + +long SvtFileDialog::Notify( NotifyEvent& rNEvt ) + +/* [Beschreibung] + + Die Methode wird gerufen, <BACKSPACE> abzufangen. +*/ + +{ + USHORT nType = rNEvt.GetType(); + long nRet = 0; + + if ( EVENT_KEYINPUT == nType && rNEvt.GetKeyEvent() ) + { + const KeyCode& rKeyCode = rNEvt.GetKeyEvent()->GetKeyCode(); + USHORT nCode = rKeyCode.GetCode(); + + if ( !rKeyCode.GetModifier() && + KEY_BACKSPACE == nCode && !_pImp->_pEdFileName->HasChildPathFocus() ) + { + nRet = 0; //! (long)_pFileView->DoBeamerKeyInput( *rNEvt.GetKeyEvent() ); + + if ( !nRet && _pImp->_pBtnUp->IsEnabled() ) + { + PrevLevel_Impl(); + nRet = 1; + } + } +// else if ( rKeyCode.IsMod1() && ( KEY_C == nCode || KEY_V == nCode || KEY_X == nCode ) ) +// { +/* (mhu) + String aVerb = KEY_C == nCode ? UniString(RTL_CONSTASCII_USTRINGPARAM(SVT_MENUPART_VERB_COPY)) : + ( KEY_V == nCode ? UniString(RTL_CONSTASCII_USTRINGPARAM(SVT_MENUPART_VERB_PASTE)) : UniString(RTL_CONSTASCII_USTRINGPARAM(SVT_MENUPART_VERB_CUT)) ); +//(dv) if ( !CntPopupMenu::DoVerbCommand( aVerb, _pFileView->GetView() ) ) +//(dv) Sound::Beep(); +*/ +// } + } + return nRet ? nRet : ModalDialog::Notify( rNEvt ); +} + +//***************************************************************************** + +long SvtFileDialog::OK() +{ + return TRUE; +} + +//***************************************************************************** + +class SvtDefModalDialogParent_Impl +{ +private: + Window* _pOld; + +public: + SvtDefModalDialogParent_Impl( Window *pNew ) : + _pOld( Application::GetDefDialogParent() ) + { Application::SetDefDialogParent( pNew ); } + + ~SvtDefModalDialogParent_Impl() { Application::SetDefDialogParent( _pOld ); } +}; + +//***************************************************************************** + +//--------------------------------------------------------------------- +void SvtFileDialog::updateListboxLabelSizes() +{ + sal_Int16 nLineControlId[5] = { + LISTBOX_VERSION, LISTBOX_TEMPLATE, LISTBOX_IMAGE_TEMPLATE, LISTBOX_FILTER, EDIT_FILEURL + }; + + // determine the maximum width needed for the listbox labels + long nMaxWidth = 0; + for ( sal_Int32 i=0; i<5; ++i ) + { + FixedText* pLabel = static_cast< FixedText* >( getControl( nLineControlId[i], sal_True ) ); + if ( !pLabel ) + continue; + nMaxWidth = ::std::max( pLabel->GetTextWidth( pLabel->GetText() ), nMaxWidth ); + } + + // ensure that all labels are wide enough + for ( sal_Int32 i=0; i<5; ++i ) + { + FixedText* pLabel = static_cast< FixedText* >( getControl( nLineControlId[i], sal_True ) ); + ListBox* pListbox = static_cast< ListBox* >( getControl( nLineControlId[i], sal_False ) ); + if ( !pLabel || !pListbox ) + continue; + Size aCurrentSize( pLabel->GetSizePixel() ); + if ( aCurrentSize.Width() >= nMaxWidth ) + continue; + + long nChange = nMaxWidth - aCurrentSize.Width(); + pLabel->SetSizePixel( Size( nMaxWidth, aCurrentSize.Height() ) ); + + aCurrentSize = pListbox->GetSizePixel(); + pListbox->SetSizePixel( Size( aCurrentSize.Width() - nChange, aCurrentSize.Height() ) ); + lcl_MoveControl( pListbox, nChange, 0 ); + } +} + +namespace +{ + +bool implIsInvalid( const String & rURL ) +{ + SmartContent aContent( rURL ); + aContent.enableOwnInteractionHandler( ::svt::OFilePickerInteractionHandler::E_DOESNOTEXIST ); + aContent.isFolder(); // do this _before_ asking isInvalid! Otherwise result might be wrong. + return aContent.isInvalid(); +} + +} + +//--------------------------------------------------------------------- +String SvtFileDialog::implGetInitialURL( const String& _rPath, const String& _rFallback ) +{ + // an URL parser for the fallback + INetURLObject aURLParser; + + // set the path + bool bWasAbsolute = FALSE; + aURLParser = aURLParser.smartRel2Abs( _rPath, bWasAbsolute ); + + // is it a valid folder? + m_aContent.bindTo( aURLParser.GetMainURL( INetURLObject::NO_DECODE ) ); + sal_Bool bIsFolder = m_aContent.isFolder( ); // do this _before_ asking isInvalid! + sal_Bool bIsInvalid = m_aContent.isInvalid(); + + if ( bIsInvalid && m_bHasFilename && !aURLParser.hasFinalSlash() ) + { // check if the parent folder exists + // #108429# - 2003-03-26 - fs@openoffice.org + INetURLObject aParent( aURLParser ); + aParent.removeSegment( ); + aParent.setFinalSlash( ); + bIsInvalid = implIsInvalid( aParent.GetMainURL( INetURLObject::NO_DECODE ) ); + } + + if ( bIsInvalid ) + { + INetURLObject aFallback( _rFallback ); + bIsInvalid = implIsInvalid( aFallback.GetMainURL( INetURLObject::NO_DECODE ) ); + + if ( !bIsInvalid ) + aURLParser = aFallback; + } + + if ( bIsInvalid ) + { + INetURLObject aParent( aURLParser ); + while ( bIsInvalid && aParent.removeSegment() ) + { + aParent.setFinalSlash( ); + bIsInvalid = implIsInvalid( aParent.GetMainURL( INetURLObject::NO_DECODE ) ); + } + + if ( !bIsInvalid ) + aURLParser = aParent; + } + + if ( !bIsInvalid && bIsFolder ) + { + aURLParser.setFinalSlash(); + } + return aURLParser.GetMainURL( INetURLObject::NO_DECODE ); +} + +//--------------------------------------------------------------------- +short SvtFileDialog::Execute() +{ + if ( !PrepareExecute() ) + return 0; + + // Start des Dialogs. + _bIsInExecute = TRUE; + short nResult = ModalDialog::Execute(); + _bIsInExecute = FALSE; + + DBG_ASSERT( !m_pCurrentAsyncAction.is(), "SvtFilePicker::Execute: still running an async action!" ); + // the dialog should not be cancellable while an async action is running - firs, the action + // needs to be cancelled + + // letztes Verzeichnis merken + if ( RET_OK == nResult ) + { + INetURLObject aURL( _aPath ); + if ( aURL.GetProtocol() == INET_PROT_FILE ) + { + // nur bei File-URL's und nicht bei virtuelle Folder + // das ausgew"ahlte Verzeichnis merken + sal_Int32 nLevel = aURL.getSegmentCount(); + // #97148# & #102204# ------ + sal_Bool bDir = m_aContent.isFolder( aURL.GetMainURL( INetURLObject::NO_DECODE ) ); + // BOOL bClassPath = ( ( _pImp->_nStyle & SFXWB_CLASSPATH ) == SFXWB_CLASSPATH ); + if ( nLevel > 1 && ( FILEDLG_TYPE_FILEDLG == _pImp->_eDlgType || !bDir ) ) + aURL.removeSegment(); + } + } + + return nResult; +} + +//--------------------------------------------------------------------- +void SvtFileDialog::StartExecuteModal( const Link& rEndDialogHdl ) +{ + PrepareExecute(); + + // Start des Dialogs. +// _bIsInExecute = TRUE; + ModalDialog::StartExecuteModal( rEndDialogHdl ); +} + +//----------------------------------------------------------------------------- +void SvtFileDialog::onAsyncOperationStarted() +{ + EnableUI( FALSE ); + // the cancel button must be always enabled + _pImp->_pBtnCancel->Enable( TRUE ); + _pImp->_pBtnCancel->GrabFocus(); +} + +//----------------------------------------------------------------------------- +void SvtFileDialog::onAsyncOperationFinished() +{ + EnableUI( TRUE ); + m_pCurrentAsyncAction = NULL; + if ( !m_bInExecuteAsync ) + _pImp->_pEdFileName->GrabFocus(); + // (if m_bInExecuteAsync is true, then the operation was finished within the minium wait time, + // and to the user, the operation appears to be synchronous) +} + +//------------------------------------------------------------------------- +void SvtFileDialog::displayIOException( const String& _rURL, IOErrorCode _eCode ) +{ + try + { + // create make a human-readable string from the URL + String sDisplayPath( _rURL ); + ::utl::LocalFileHelper::ConvertURLToSystemPath( _rURL, sDisplayPath ); + + // build an own exception which tells "access denied" + InteractiveAugmentedIOException aException; + aException.Arguments.realloc( 2 ); + aException.Arguments[ 0 ] <<= ::rtl::OUString( sDisplayPath ); + aException.Arguments[ 1 ] <<= PropertyValue( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Uri" ) ), + -1, aException.Arguments[ 0 ], PropertyState_DIRECT_VALUE + ); + // (formerly, it was sufficient to put the URL first parameter. Nowadays, + // the services expects the URL in a PropertyValue named "Uri" ...) + aException.Code = _eCode; + aException.Classification = InteractionClassification_ERROR; + + // let and interaction handler handle this exception + ::comphelper::OInteractionRequest* pRequest = NULL; + Reference< ::com::sun::star::task::XInteractionRequest > xRequest = pRequest = + new ::comphelper::OInteractionRequest( makeAny( aException ) ); + pRequest->addContinuation( new ::comphelper::OInteractionAbort( ) ); + + Reference< XInteractionHandler > xHandler( + ::comphelper::getProcessServiceFactory()->createInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.task.InteractionHandler") ) + ), + UNO_QUERY + ); + if ( xHandler.is() ) + xHandler->handle( xRequest ); + } + catch( const Exception& ) + { + DBG_ERROR( "iodlg::displayIOException: caught an exception!" ); + } +} + +//----------------------------------------------------------------------------- +void SvtFileDialog::EnableUI( BOOL _bEnable ) +{ + Enable( _bEnable ); + + if ( _bEnable ) + { + for ( ::std::set< Control* >::iterator aLoop = m_aDisabledControls.begin(); + aLoop != m_aDisabledControls.end(); + ++aLoop + ) + { + (*aLoop)->Enable( FALSE ); + } + } +} + +//----------------------------------------------------------------------------- +void SvtFileDialog::EnableControl( Control* _pControl, BOOL _bEnable ) +{ + if ( !_pControl ) + { + DBG_ERRORFILE( "SvtFileDialog::EnableControl: invalid control!" ); + return; + } + + _pControl->Enable( _bEnable ); + + if ( _bEnable ) + { + ::std::set< Control* >::iterator aPos = m_aDisabledControls.find( _pControl ); + if ( m_aDisabledControls.end() != aPos ) + m_aDisabledControls.erase( aPos ); + } + else + m_aDisabledControls.insert( _pControl ); +} + +//---------------------------------------------------------------------------- + +short SvtFileDialog::PrepareExecute() +{ + rtl::OUString aEnvValue; + if ( getEnvironmentValue( "WorkDirMustContainRemovableMedia", aEnvValue ) && + aEnvValue.equalsAscii( "1" ) ) + { + try + { + INetURLObject aStdDir( GetStandardDir() ); + ::ucbhelper::Content aCnt( rtl::OUString( aStdDir.GetMainURL( + INetURLObject::NO_DECODE ) ), + Reference< XCommandEnvironment >() ); + Sequence< rtl::OUString > aProps(2); + aProps[0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "IsVolume" )); + aProps[1] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "IsRemoveable" )); + + Reference< XResultSet > xResultSet + = aCnt.createCursor( aProps, ::ucbhelper::INCLUDE_FOLDERS_ONLY ); + if ( xResultSet.is() ) + { + Reference< XRow > xRow( xResultSet, UNO_QUERY ); + + bool bEmpty = true; + if ( !xResultSet->next() ) + { + // folder is empty + bEmpty = true; + } + else + { +// @@@ KSO 05/18/2006: support for removable media currently hardcoded/incomplete in OSL +// +// do +// { +// // check, whether child is a removable volume +// if ( xRow->getBoolean( 1 ) && !xRow->wasNull() ) +// { +// if ( xRow->getBoolean( 2 ) && !xRow->wasNull() ) +// { + bEmpty = false; +// break; +// } +// } +// } +// while ( xResultSet->next() ); + } + + if ( bEmpty ) + { + ErrorBox aBox( this, WB_OK, SvtResId( STR_SVT_NOREMOVABLEDEVICE ) ); + aBox.Execute(); + return 0; + } + } + } + catch ( ContentCreationException const & ) + { + } + catch ( CommandAbortedException const & ) + { + } + } + + // #102204# --------------- + if ( ( _pImp->_nStyle & WB_SAVEAS ) && m_bHasFilename ) + // when doing a save-as, we do not want the handler to handle "this file does not exist" messages + // - finally we're going to save that file, aren't we? + // #105812# - 2002-12-02 - fs@openoffice.org + m_aContent.enableOwnInteractionHandler(::svt::OFilePickerInteractionHandler::E_DOESNOTEXIST); + else + m_aContent.enableDefaultInteractionHandler(); + + // #53016# evtl. nur ein Filename ohne Pfad? + String aFileNameOnly; + if( _aPath.Len() && (_pImp->_eMode == FILEDLG_MODE_SAVE) + && (_aPath.Search(':') == STRING_NOTFOUND) + && (_aPath.Search('\\') == STRING_NOTFOUND) + && (_aPath.Search('/') == STRING_NOTFOUND)) + { + aFileNameOnly = _aPath; + _aPath.Erase(); + } + + // kein Startpfad angegeben? + if ( !_aPath.Len() ) + { + // dann das Standard-Dir verwenden + _aPath = lcl_ensureFinalSlash( _pImp->GetStandardDir() ); + + // #53016# vorgegebener Dateiname an Pfad anh"angen + if ( aFileNameOnly.Len() ) + _aPath += aFileNameOnly; + } + + //..................................................................... + _aPath = implGetInitialURL( _aPath, GetStandardDir() ); + + if ( _pImp->_nStyle & WB_SAVEAS && !m_bHasFilename ) + // when doing a save-as, we do not want the handler to handle "this file does not exist" messages + // - finally we're going to save that file, aren't we? + m_aContent.enableOwnInteractionHandler(::svt::OFilePickerInteractionHandler::E_DOESNOTEXIST); + + //..................................................................... + // care for possible restrictions on the paths we're allowed to show + if ( !m_aURLFilter.isUrlAllowed( _aPath ) ) + _aPath = m_aURLFilter.getFilter()[0]; + + // Ggf. Filter anzeigen. + _pImp->InitFilterList(); + + // Initialen Filter einstellen. + USHORT nFilterCount = GetFilterCount(); + String aAll( SvtResId( STR_FILTERNAME_ALL ) ); + BOOL bHasAll = _pImp->HasFilterListEntry( aAll ); + if ( _pImp->GetCurFilter() || nFilterCount == 1 || ( nFilterCount == 2 && bHasAll ) ) + { + // Ggf. einzigen Filter als aktuellen Filter setzen oder den einzigen + // Filter, der nicht auf alle Dateien verweist. + if ( !_pImp->GetCurFilter() ) + { + USHORT nPos = 0; + if ( 2 == nFilterCount && bHasAll ) + { + nPos = nFilterCount; + while ( nPos-- ) + { + if ( GetFilterName( nPos ) != aAll ) + break; + } + } + SvtFileDialogFilter_Impl* pNewCurFilter = _pImp->_pFilter->GetObject( nPos ); + DBG_ASSERT( pNewCurFilter, "SvtFileDialog::Execute: invalid filter pos!" ); + _pImp->SetCurFilter( pNewCurFilter, pNewCurFilter->GetName() ); + } + + // Anzeige anpassen. + _pImp->SelectFilterListEntry( _pImp->GetCurFilter()->GetName() ); + SetDefaultExt( _pImp->GetCurFilter()->GetExtension() ); + USHORT nSepPos = GetDefaultExt().Search( FILEDIALOG_DEF_EXTSEP ); + if ( nSepPos != STRING_NOTFOUND ) + EraseDefaultExt( nSepPos ); + } + else + { + // Ggf. Filter fuer alle Dateien setzen bzw. erzeugen. + if ( !bHasAll ) + { + SvtFileDialogFilter_Impl* pAllFilter = implAddFilter( aAll, UniString(RTL_CONSTASCII_USTRINGPARAM(FILEDIALOG_FILTER_ALL)) ); + _pImp->InsertFilterListEntry( pAllFilter ); + _pImp->SetCurFilter( pAllFilter, aAll ); + } + _pImp->SelectFilterListEntry( aAll ); + } + + _pImp->_pDefaultFilter = _pImp->GetCurFilter(); + + // HACK #50065# + // ggf. Filter isolieren. + String aFilter; + + if ( !IsolateFilterFromPath_Impl( _aPath, aFilter ) ) + return 0; + + sal_uInt16 nNewFilterFlags = adjustFilter( aFilter ); + if ( nNewFilterFlags & ( FLT_NONEMPTY | FLT_USERFILTER ) ) + { + _pImp->_pEdFileName->SetText( aFilter ); + } + // HACK #50065# + + // Instanz fuer den gesetzten Pfad erzeugen und anzeigen. + INetURLObject aFolderURL( _aPath ); + String aFileName( aFolderURL.getName( INetURLObject::LAST_SEGMENT, false ) ); + xub_StrLen nFileNameLen = aFileName.Len(); + bool bFileToSelect = nFileNameLen != 0; + if ( bFileToSelect && aFileName.GetChar( nFileNameLen - 1 ) != INET_PATH_TOKEN ) + { + _pImp->_pEdFileName->SetText( GET_DECODED_NAME( aFolderURL ) ); + aFolderURL.removeSegment(); + } + + INetURLObject aObj = aFolderURL; + if ( aObj.GetProtocol() == INET_PROT_FILE ) + { + // Ordner als aktuelles Verzeichnis setzen. + aObj.setFinalSlash(); + } + + UpdateControls( aObj.GetMainURL( INetURLObject::NO_DECODE ) ); + + // Somebody might want to enable some controls acording to the current filter + FilterSelect(); + + // Zustand der Steuerelemente anpassen. +// EndListeningAll(); + + ViewHdl_Impl( this, NULL ); + OpenURL_Impl( aObj.GetMainURL( INetURLObject::NO_DECODE ) ); + + _pFileView->Show(); + SvtDefModalDialogParent_Impl aDefParent( this ); + + // ggf. Gr"osse aus Ini lesen und setzen + InitSize(); + + return 1; +} + +//----------------------------------------------------------------------------- +void SvtFileDialog::implInitializeSpecialURLLists( ) +{ + m_aURLFilter = ::svt::RestrictedPaths(); + + ::std::vector< String > aFavourites; + if ( m_aURLFilter.hasFilter() ) + { + // if we have restrictions, then the "favourites" are the restricted folders only + aFavourites = m_aURLFilter.getFilter(); + // for approved URLs, we needed the final slashes, for + // favourites, we do not want to have them + ::std::for_each( aFavourites.begin(), aFavourites.end(), RemoveFinalSlash() ); + } + else + { + ::rtl::OUString sFavouritesList; + if ( getEnvironmentValue( "PathFavourites", sFavouritesList ) ) + convertStringListToUrls( sFavouritesList, aFavourites, false ); + } + + DBG_ASSERT( _pImp->_pBtnStandard, "SvtFileDialog::implInitializeSpecialURLLists: how this?" ); + if ( _pImp->_pBtnStandard ) + _pImp->_pBtnStandard->SetFavouriteLocations( aFavourites ); +} + +//----------------------------------------------------------------------------- +void SvtFileDialog::executeAsync( ::svt::AsyncPickerAction::Action _eAction, + const String& _rURL, const String& _rFilter ) +{ + DBG_ASSERT( !m_pCurrentAsyncAction.is(), "SvtFileDialog::executeAsync: previous async action not yet finished!" ); + + m_pCurrentAsyncAction = new AsyncPickerAction( this, _pFileView, _eAction ); + + bool bReallyAsync = true; + m_aConfiguration.getNodeValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FillAsynchronously" ) ) ) >>= bReallyAsync; + + sal_Int32 nMinTimeout = 0; + m_aConfiguration.getNodeValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Timeout/Min" ) ) ) >>= nMinTimeout; + sal_Int32 nMaxTimeout = 0; + m_aConfiguration.getNodeValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Timeout/Max" ) ) ) >>= nMaxTimeout; + + m_bInExecuteAsync = true; + m_pCurrentAsyncAction->execute( _rURL, _rFilter, bReallyAsync ? nMinTimeout : -1, nMaxTimeout, GetBlackList() ); + m_bInExecuteAsync = false; +} + +//***************************************************************************** + +void SvtFileDialog::FileSelect() +{ + if ( _pFileNotifier ) + _pFileNotifier->notify( FILE_SELECTION_CHANGED, 0 ); +} + +//***************************************************************************** + +void SvtFileDialog::FilterSelect() +{ + if ( _pFileNotifier ) + _pFileNotifier->notify( CTRL_STATE_CHANGED, + LISTBOX_FILTER ); +} + +//***************************************************************************** + +void SvtFileDialog::SetStandardDir( const String& rStdDir ) + +/* [Beschreibung] + + Die Methode setzt den Pfad f"ur den Standardknopf. +*/ + +{ + INetURLObject aObj( rStdDir ); + DBG_ASSERT( aObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid protocol!" ); + aObj.setFinalSlash(); + _pImp->SetStandardDir( aObj.GetMainURL( INetURLObject::NO_DECODE ) ); +} + +void SvtFileDialog::SetBlackList( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList ) +{ + _pImp->SetBlackList( rBlackList ); +} + +//***************************************************************************** + +const ::com::sun::star::uno::Sequence< ::rtl::OUString >& SvtFileDialog::GetBlackList() const +{ + return _pImp->GetBlackList(); +} +//***************************************************************************** + +const String& SvtFileDialog::GetStandardDir() const + +/* [Beschreibung] + + Diese Methode gibt den eingestellten Standardpfad zur"uck. +*/ + +{ + return _pImp->GetStandardDir(); +} + +//***************************************************************************** + +void SvtFileDialog::PrevLevel_Impl() +{ + _pFileView->EndInplaceEditing( false ); + + String sDummy; + executeAsync( AsyncPickerAction::ePrevLevel, sDummy, sDummy ); +} + +//***************************************************************************** + +void SvtFileDialog::OpenURL_Impl( const String& _rURL ) +{ + _pFileView->EndInplaceEditing( false ); + + DBG_ASSERT( m_aURLFilter.isUrlAllowed( _rURL ), "SvtFileDialog::OpenURL_Impl: forbidden URL! Should have been handled by the caller!" ); + executeAsync( AsyncPickerAction::eOpenURL, _rURL, getMostCurrentFilter( _pImp ) ); +} + +//***************************************************************************** +SvtFileDialogFilter_Impl* SvtFileDialog::implAddFilter( const String& _rFilter, const String& _rType ) +{ + SvtFileDialogFilter_Impl* pNewFilter = new SvtFileDialogFilter_Impl( _rFilter, _rType ); + _pImp->_pFilter->C40_INSERT( SvtFileDialogFilter_Impl, pNewFilter, (USHORT)0 ); + + if ( !_pImp->GetCurFilter() ) + _pImp->SetCurFilter( pNewFilter, _rFilter ); + + return pNewFilter; +} + +//***************************************************************************** + +void SvtFileDialog::AddFilter( const String& _rFilter, const String& _rType ) +{ + DBG_ASSERT( !IsInExecute(), "SvtFileDialog::AddFilter: currently executing!" ); + implAddFilter ( _rFilter, _rType ); +} + +//***************************************************************************** +void SvtFileDialog::AddFilterGroup( const String& _rFilter, const Sequence< StringPair >& _rFilters ) +{ + DBG_ASSERT( !IsInExecute(), "SvtFileDialog::AddFilter: currently executing!" ); + + implAddFilter( _rFilter, String() ); + const StringPair* pSubFilters = _rFilters.getConstArray(); + const StringPair* pSubFiltersEnd = pSubFilters + _rFilters.getLength(); + for ( ; pSubFilters != pSubFiltersEnd; ++pSubFilters ) + implAddFilter( pSubFilters->First, pSubFilters->Second ); +} + +//***************************************************************************** + +//----------------------------------------------------------------------------- +void SvtFileDialog::SetCurFilter( const String& rFilter ) +{ + DBG_ASSERT( !IsInExecute(), "SvtFileDialog::SetCurFilter: currently executing!" ); + + // Entsprechenden Filter suchen. + USHORT nPos = _pImp->_pFilter->Count(); + + while ( nPos-- ) + { + SvtFileDialogFilter_Impl* pFilter = _pImp->_pFilter->GetObject( nPos ); + if ( pFilter->GetName() == rFilter ) + { + _pImp->SetCurFilter( pFilter, rFilter ); + break; + } + } +} + +//***************************************************************************** + +String SvtFileDialog::GetCurFilter() const +{ + String aFilter; + + const SvtFileDialogFilter_Impl* pCurrentFilter = _pImp->GetCurFilter(); + if ( pCurrentFilter ) + aFilter = pCurrentFilter->GetName(); + + return aFilter; +} + +String SvtFileDialog::getCurFilter( ) const +{ + return GetCurFilter(); +} + +//***************************************************************************** + +USHORT SvtFileDialog::GetFilterCount() const +{ + return _pImp->_pFilter->Count(); +} + +//***************************************************************************** + +const String& SvtFileDialog::GetFilterName( USHORT nPos ) const +{ + DBG_ASSERT( nPos < GetFilterCount(), "invalid index" ); + return _pImp->_pFilter->GetObject( nPos )->GetName(); +} + +//***************************************************************************** + +void SvtFileDialog::InitSize() +{ + if ( ! _pImp->_aIniKey.Len() ) + return; + + Size aDlgSize = GetResizeOutputSizePixel(); + SetMinOutputSizePixel( aDlgSize ); + + if ( !_pImp->_nFixDeltaHeight ) + { + // Fixgr"ossen errechnen und merken + Point aPnt = _pFileView->GetPosPixel(); + long nBoxH = _pFileView->GetSizePixel().Height(); + long nH = GetSizePixel().Height(); + _pImp->_nFixDeltaHeight = nH - nBoxH; + } + + // initialize from config + SvtViewOptions aDlgOpt( E_DIALOG, _pImp->_aIniKey ); + + if ( aDlgOpt.Exists() ) + { + SetWindowState( ByteString( String( aDlgOpt.GetWindowState() ), osl_getThreadTextEncoding() ) ); + + Any aUserData = aDlgOpt.GetUserItem( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "UserData" ) )); + ::rtl::OUString sCfgStr; + if ( aUserData >>= sCfgStr ) + _pFileView->SetConfigString( String( sCfgStr ) ); + } +} + +//***************************************************************************** + +SvStringsDtor* SvtFileDialog::GetPathList() const +{ + SvStringsDtor* pList = new SvStringsDtor; + ULONG nCount = _pFileView->GetSelectionCount(); + SvLBoxEntry* pEntry = nCount ? _pFileView->FirstSelected() : NULL; + + if ( ! pEntry ) + { + String* pURL; + + if ( _pImp->_pEdFileName->GetText().Len() && _bIsInExecute ) + pURL = new String( _pImp->_pEdFileName->GetURL() ); + else + pURL = new String( _aPath ); + + pList->Insert( pURL, pList->Count() ); + } + else + { + while ( pEntry ) + { + String* pURL = new String( _pFileView->GetURL( pEntry ) ); + pList->Insert( pURL, pList->Count() ); + pEntry = _pFileView->NextSelected( pEntry ); + } + } + + return pList; +} + +//***************************************************************************** + +void SvtFileDialog::implArrangeControls() +{ + // this is the list of controls in the order they should be tabbed + // from topleft to bottomright + // pb: #136070# new order so all LabeledBy relations are correct now + Control* pControls[] = + { + _pImp->_pFtCurrentPath, + _pImp->_pBtnUp, _pImp->_pBtnNewFolder, _pImp->_pBtnStandard, // image buttons + _pFileView, // the file view + _pImp->_pFtFileName, _pImp->_pEdFileName, + _pImp->_pFtFileVersion, _pImp->_pLbFileVersion, + _pImp->_pFtTemplates, _pImp->_pLbTemplates, + _pImp->_pFtImageTemplates, _pImp->_pLbImageTemplates, + _pImp->_pFtFileType, _pImp->GetFilterListControl(), // edit fields/list boxes + _pImp->_pCbPassword, _pImp->_pCbAutoExtension, _pImp->_pCbOptions, // checkboxes + _pCbReadOnly, _pCbLinkBox, _pCbPreviewBox, _pCbSelection, _pPbPlay, // check boxes (continued) + _pImp->_pBtnFileOpen, _pImp->_pBtnCancel, _pImp->_pBtnHelp // buttons + + // (including the FixedTexts is important - not for tabbing order (they're irrelevant there), + // but for working keyboard shortcuts) + // 96861 - 23.01.2002 - fs@openoffice.org + }; + + // loop through all these controls and adjust the z-order + Window* pPreviousWin = NULL; + Control** pCurrent = pControls; + for ( sal_Int32 i = 0; i < sal_Int32(SAL_N_ELEMENTS( pControls )); ++i, ++pCurrent ) + { + if ( !*pCurrent ) + // this control is not available in the current operation mode -> skip + continue; + + if ( pPreviousWin ) + (*pCurrent)->SetZOrder( pPreviousWin, WINDOW_ZORDER_BEHIND ); + else + (*pCurrent)->SetZOrder( NULL, WINDOW_ZORDER_FIRST ); + + pPreviousWin = *pCurrent; + } + + // FileName edit not the first control but it should have the focus initially + _pImp->_pEdFileName->GrabFocus(); +} + +//***************************************************************************** + +BOOL SvtFileDialog::IsolateFilterFromPath_Impl( String& rPath, String& rFilter ) +{ + String aEmpty; + String aReversePath( rPath ); + aReversePath.Reverse(); + USHORT nQuestionMarkPos = rPath.Search( '?' ); + + if ( nQuestionMarkPos != STRING_NOTFOUND ) + { + // Fragezeichen als Wildcard nur bei Files + INetProtocol eProt = INetURLObject::CompareProtocolScheme( rPath ); + + if ( INET_PROT_NOT_VALID != eProt && INET_PROT_FILE != eProt ) + nQuestionMarkPos = STRING_NOTFOUND; + } + USHORT nWildCardPos = Min( rPath.Search( FILEDIALOG_DEF_WILDCARD ), nQuestionMarkPos ); + rFilter = aEmpty; + + if ( nWildCardPos != STRING_NOTFOUND ) + { + USHORT nPathTokenPos = aReversePath.Search( INET_PATH_TOKEN ); + + if ( nPathTokenPos == STRING_NOTFOUND ) + { + String aDelim( +#if defined(WNT) || defined(OS2) + '\\' +#else + '/' +#endif + ); + + nPathTokenPos = aReversePath.Search( aDelim ); +#if defined(OS2) + if ( nPathTokenPos == STRING_NOTFOUND ) + { + nPathTokenPos = aReversePath.Search( '/' ); + } +#endif +#if !defined( UNX ) + if ( nPathTokenPos == STRING_NOTFOUND ) + { + nPathTokenPos = aReversePath.Search( ':' ); + } +#endif + } + + // Syntax pr"ufen. + if ( nPathTokenPos != STRING_NOTFOUND ) + { + if ( nPathTokenPos < (rPath.Len() - nWildCardPos - 1) ) + { + ErrorHandler::HandleError( ERRCODE_SFX_INVALIDSYNTAX ); + return FALSE; + } + + // Filter abschneiden. + rFilter = aReversePath; + rFilter.Erase( nPathTokenPos ); + rFilter.Reverse(); + + // Ordner bestimmen. + rPath = aReversePath; + rPath.Erase( 0, nPathTokenPos ); + rPath.Reverse(); + } + else + { + rFilter = rPath; + rPath = aEmpty; + } + } + + return TRUE; +} + +//***************************************************************************** + +//----------------------------------------------------------------------------- +void SvtFileDialog::implUpdateImages( ) +{ + m_aImages = ImageList( SvtResId( RID_FILEPICKER_IMAGES ) ); + + // set the appropriate images on the buttons + if ( _pImp->_pBtnUp ) + _pImp->_pBtnUp->SetModeImage( GetButtonImage( IMG_FILEDLG_BTN_UP ) ); + + if ( _pImp->_pBtnStandard ) + _pImp->_pBtnStandard->SetModeImage( GetButtonImage( IMG_FILEDLG_BTN_STD ) ); + + if ( _pImp->_pBtnNewFolder ) + _pImp->_pBtnNewFolder->SetModeImage( GetButtonImage( IMG_FILEDLG_CREATEFOLDER ) ); +} + +//----------------------------------------------------------------------------- +void SvtFileDialog::DataChanged( const DataChangedEvent& _rDCEvt ) +{ + if ( DATACHANGED_SETTINGS == _rDCEvt.GetType() ) + implUpdateImages( ); + + ModalDialog::DataChanged( _rDCEvt ); +} + +//----------------------------------------------------------------------------- +void SvtFileDialog::Resize() +{ + if ( IsRollUp() ) + return; + + Size aDlgSize = GetResizeOutputSizePixel(); + Size aOldSize = _pImp->_aDlgSize; + _pImp->_aDlgSize = aDlgSize; + long nWinDeltaW = 0; + + if ( _pPrevWin && + _pPrevWin->GetPosPixel().X() > _pFileView->GetPosPixel().X() ) + { + nWinDeltaW = _pPrevWin->GetOutputSizePixel().Width() + _pImp->_a6Size.Width(); + } + + Size aNewSize = _pFileView->GetSizePixel(); + Point aBoxPos( _pFileView->GetPosPixel() ); + long nDeltaY = aNewSize.Height(); + long nDeltaX = aNewSize.Width(); + aNewSize.Height() = aDlgSize.Height() - _pImp->_nFixDeltaHeight; + aNewSize.Width() = aDlgSize.Width() - aBoxPos.X() - _pImp->_a6Size.Width() - nWinDeltaW; + if ( aOldSize.Height() ) + nDeltaY = _pImp->_aDlgSize.Height() - aOldSize.Height(); + else + nDeltaY = aNewSize.Height() - nDeltaY; + nDeltaX = aNewSize.Width() - nDeltaX; + + if ( nWinDeltaW ) + nWinDeltaW = nDeltaX * 2 / 3; + aNewSize.Width() -= nWinDeltaW; + nDeltaX -= nWinDeltaW; + + _pFileView->SetSizePixel( aNewSize ); + + if ( !nDeltaY && !nDeltaX ) + // Dieses Resize wurde nur zum Ein - oder Ausblenden des Indicators aufgerufen + return; + + // ------------- + // move controls + + // controls to move vertically + { + Control* aMoveControlsVert[] = + { + _pImp->_pFtFileName, _pImp->_pEdFileName, _pImp->_pFtFileVersion, _pImp->_pLbFileVersion, + _pImp->_pFtTemplates, _pImp->_pLbTemplates, _pImp->_pFtImageTemplates, _pImp->_pLbImageTemplates, + _pImp->_pFtFileType, _pImp->GetFilterListControl(), _pCbReadOnly, _pCbLinkBox, _pCbPreviewBox, + _pPbPlay, _pImp->_pCbPassword, _pImp->_pCbAutoExtension, _pImp->_pCbOptions, _pCbSelection + }; + Control** ppMoveControls = aMoveControlsVert; + Control** ppMoveControlsEnd = ppMoveControls + SAL_N_ELEMENTS( aMoveControlsVert ); + for ( ; ppMoveControls != ppMoveControlsEnd; ++ppMoveControls ) + lcl_MoveControl( *ppMoveControls, 0, nDeltaY ); + } + + // controls to move vertically and horizontally + { + Control* aMoveControlsBoth[] = + { + _pImp->_pBtnFileOpen, _pImp->_pBtnCancel, _pImp->_pBtnHelp + }; + Control** ppMoveControls = aMoveControlsBoth; + Control** ppMoveControlsEnd = ppMoveControls + SAL_N_ELEMENTS( aMoveControlsBoth ); + for ( ; ppMoveControls != ppMoveControlsEnd; ++ppMoveControls ) + lcl_MoveControl( *ppMoveControls, nDeltaX, nDeltaY ); + } + + // controls to move horizontally + { + Control* aMoveControlsHor[] = + { + _pImp->_pBtnUp, _pImp->_pBtnNewFolder, _pImp->_pBtnStandard + }; + Control** ppMoveControls = aMoveControlsHor; + Control** ppMoveControlsEnd = ppMoveControls + SAL_N_ELEMENTS( aMoveControlsHor ); + for ( ; ppMoveControls != ppMoveControlsEnd; ++ppMoveControls ) + lcl_MoveControl( *ppMoveControls, nDeltaX, 0 ); + } + + // --------------- + // resize controls + { + Control* aSizeControls[] = + { + _pImp->_pEdFileName, _pImp->_pLbFileVersion, _pImp->_pLbTemplates, _pImp->_pLbImageTemplates, + _pImp->GetFilterListControl(), _pImp->_pFtCurrentPath, + }; + sal_Int32 nSizeControls = SAL_N_ELEMENTS( aSizeControls ); + Control** ppSizeControls = aSizeControls; + for ( sal_Int32 j=0; j<nSizeControls; ++j, ++ppSizeControls ) + { + if ( *ppSizeControls ) + { + aNewSize = (*ppSizeControls)->GetSizePixel(); + aNewSize.Width() += nDeltaX; + (*ppSizeControls)->SetSizePixel( aNewSize ); + } + } + } + + // zus"atzliche Controls ausrichten + if ( _pPrevWin && + _pPrevWin->GetPosPixel().X() > _pFileView->GetPosPixel().X() ) + { + // Controls vom Typ Window speziell ausrichten + // auch die Gr"osse anpassen + Point aNewPos = _pPrevWin->GetPosPixel(); + aNewPos.X() += nDeltaX; + _pPrevWin->SetPosPixel( aNewPos ); + _pPrevBmp->SetPosPixel( aNewPos ); + aNewSize = _pPrevWin->GetOutputSizePixel(); + aNewSize.Width() += nWinDeltaW; + aNewSize.Height() += nDeltaY; + if ( !aOldSize.Height() ) + aNewSize.Height() -= ( _pImp->_a6Size.Height() / 2 ); + _pPrevWin->SetOutputSizePixel( aNewSize ); + _pPrevBmp->SetOutputSizePixel( aNewSize ); + _pPrevBmp->Invalidate(); + } + + if ( _pFileNotifier ) + _pFileNotifier->notify( DIALOG_SIZE_CHANGED, 0 ); +} + +//***************************************************************************** + +//----------------------------------------------------------------------------- +Control* SvtFileDialog::getControl( sal_Int16 _nControlId, sal_Bool _bLabelControl ) const +{ + Control* pReturn = NULL; + + switch ( _nControlId ) + { + case CONTROL_FILEVIEW: + pReturn = _bLabelControl ? NULL : static_cast< Control* >( _pFileView ); + break; + + case EDIT_FILEURL: + pReturn = _bLabelControl + ? static_cast< Control* >( _pImp->_pFtFileName ) + : static_cast< Control* >( _pImp->_pEdFileName ); + break; + + case EDIT_FILEURL_LABEL: + pReturn = static_cast< Control* >( _pImp->_pFtFileName ); + break; + + case CHECKBOX_AUTOEXTENSION: + pReturn = _pImp->_pCbAutoExtension; + break; + + case CHECKBOX_PASSWORD: + pReturn = _pImp->_pCbPassword; + break; + + case CHECKBOX_FILTEROPTIONS: + pReturn = _pImp->_pCbOptions; + break; + + case CHECKBOX_READONLY: + pReturn = _pCbReadOnly; + break; + + case CHECKBOX_LINK: + pReturn = _pCbLinkBox; + break; + + case CHECKBOX_PREVIEW: + pReturn = _pCbPreviewBox; + break; + + case CHECKBOX_SELECTION: + pReturn = _pCbSelection; + break; + + case LISTBOX_FILTER: + pReturn = _bLabelControl ? _pImp->_pFtFileType : _pImp->GetFilterListControl(); + break; + + case LISTBOX_FILTER_LABEL: + pReturn = _pImp->_pFtFileType; + break; + + case FIXEDTEXT_CURRENTFOLDER: + pReturn = _pImp->_pFtCurrentPath; + break; + + case LISTBOX_VERSION: + pReturn = _bLabelControl + ? static_cast< Control* >( _pImp->_pFtFileVersion ) + : static_cast< Control* >( _pImp->_pLbFileVersion ); + break; + + case LISTBOX_TEMPLATE: + pReturn = _bLabelControl + ? static_cast< Control* >( _pImp->_pFtTemplates ) + : static_cast< Control* >( _pImp->_pLbTemplates ); + break; + + case LISTBOX_IMAGE_TEMPLATE: + pReturn = _bLabelControl + ? static_cast< Control* >( _pImp->_pFtImageTemplates ) + : static_cast< Control* >( _pImp->_pLbImageTemplates ); + break; + + case LISTBOX_VERSION_LABEL: + pReturn = _pImp->_pFtFileVersion; + break; + + case LISTBOX_TEMPLATE_LABEL: + pReturn = _pImp->_pFtTemplates; + break; + + case LISTBOX_IMAGE_TEMPLATE_LABEL: + pReturn = _pImp->_pFtImageTemplates; + break; + + case PUSHBUTTON_OK: + pReturn = _pImp->_pBtnFileOpen; + break; + + case PUSHBUTTON_CANCEL: + pReturn = _pImp->_pBtnCancel; + break; + + case PUSHBUTTON_PLAY: + pReturn = _pPbPlay; + break; + + case PUSHBUTTON_HELP: + pReturn = _pImp->_pBtnHelp; + break; + + case TOOLBOXBUTOON_DEFAULT_LOCATION: + pReturn = _pImp->_pBtnStandard; + break; + + case TOOLBOXBUTOON_LEVEL_UP: + pReturn = _pImp->_pBtnUp; + break; + + case TOOLBOXBUTOON_NEW_FOLDER: + pReturn = _pImp->_pBtnNewFolder; + break; + + case LISTBOX_FILTER_SELECTOR: + // only exists on SalGtkFilePicker + break; + + default: + DBG_ERRORFILE( "SvtFileDialog::getControl: invalid id!" ); + } + return pReturn; +} + +// ----------------------------------------------------------------------- +void SvtFileDialog::enableControl( sal_Int16 _nControlId, sal_Bool _bEnable ) +{ + Control* pControl = getControl( _nControlId, sal_False ); + if ( pControl ) + EnableControl( pControl, _bEnable ); + Control* pLabel = getControl( _nControlId, sal_True ); + if ( pLabel ) + EnableControl( pLabel, _bEnable ); +} + +// ----------------------------------------------------------------------- +void SvtFileDialog::AddControls_Impl( ) +{ + // create the "insert as link" checkbox, if needed + if ( _nExtraBits & SFX_EXTRA_INSERTASLINK ) + { + _pCbLinkBox = new CheckBox( this ); + _pCbLinkBox ->SetText( SvtResId( STR_SVT_FILEPICKER_INSERT_AS_LINK ) ); + _pCbLinkBox ->SetHelpId( HID_FILEDLG_LINK_CB ); + AddControl( _pCbLinkBox ); + ReleaseOwnerShip( _pCbLinkBox ); + _pCbLinkBox->SetClickHdl( LINK( this, SvtFileDialog, ClickHdl_Impl ) ); + } + + // create the "show preview" checkbox ( and the preview window, too ), if needed + if ( _nExtraBits & SFX_EXTRA_SHOWPREVIEW ) + { + _pImp->_aIniKey = IMPGRF_CONFIGNAME; + // because the "<All Formats> (*.bmp,*...)" entry is to wide, + // we need to disable the auto width feature of the filter box + _pImp->DisableFilterBoxAutoWidth(); + + // "Vorschau" + _pCbPreviewBox = new CheckBox( this ); + _pCbPreviewBox->SetText( SvtResId( STR_SVT_FILEPICKER_SHOW_PREVIEW ) ); + _pCbPreviewBox->SetHelpId( HID_FILEDLG_PREVIEW_CB ); + AddControl( _pCbPreviewBox ); + ReleaseOwnerShip( _pCbPreviewBox ); + _pCbPreviewBox->SetClickHdl( LINK( this, SvtFileDialog, ClickHdl_Impl ) ); + + // Preview-Fenster erst hier erzeugen + _pPrevWin = new Window( this, WinBits( WB_BORDER ) ); + AddControl( _pPrevWin ); + ReleaseOwnerShip( _pPrevWin ); + _pPrevWin->Hide(); + + _pPrevBmp = new FixedBitmap( this, WinBits( WB_BORDER ) ); + _pPrevBmp->SetBackground( Wallpaper( Color( COL_WHITE ) ) ); + _pPrevBmp->Show(); + } + + if ( _nExtraBits & SFX_EXTRA_AUTOEXTENSION ) + { + _pImp->_pCbAutoExtension = new CheckBox( this, SvtResId( CB_AUTO_EXTENSION ) ); + _pImp->_pCbAutoExtension->SetText( SvtResId( STR_SVT_FILEPICKER_AUTO_EXTENSION ) ); + _pImp->_pCbAutoExtension->Check( TRUE ); + AddControl( _pImp->_pCbAutoExtension ); + ReleaseOwnerShip( _pImp->_pCbAutoExtension ); + _pImp->_pCbAutoExtension->SetClickHdl( LINK( this, SvtFileDialog, AutoExtensionHdl_Impl ) ); + } + + if ( _nExtraBits & SFX_EXTRA_FILTEROPTIONS ) + { + _pImp->_pCbOptions = new CheckBox( this, SvtResId( CB_OPTIONS ) ); + _pImp->_pCbOptions->SetText( SvtResId( STR_SVT_FILEPICKER_FILTER_OPTIONS ) ); + AddControl( _pImp->_pCbOptions ); + ReleaseOwnerShip( _pImp->_pCbOptions ); + _pImp->_pCbOptions->SetClickHdl( LINK( this, SvtFileDialog, ClickHdl_Impl ) ); + } + + if ( _nExtraBits & SFX_EXTRA_SELECTION ) + { + _pCbSelection = new CheckBox( this, SvtResId( CB_OPTIONS ) ); + _pCbSelection->SetText( SvtResId( STR_SVT_FILEPICKER_SELECTION ) ); + AddControl( _pCbSelection ); + ReleaseOwnerShip( _pCbSelection ); + _pCbSelection->SetClickHdl( LINK( this, SvtFileDialog, ClickHdl_Impl ) ); + } + + if ( _nExtraBits & SFX_EXTRA_PLAYBUTTON ) + { + _pPbPlay = new PushButton( this ); + _pPbPlay->SetText( SvtResId( STR_SVT_FILEPICKER_PLAY ) ); + _pPbPlay->SetHelpId( HID_FILESAVE_DOPLAY ); + AddControl( _pPbPlay ); + ReleaseOwnerShip( _pPbPlay ); + _pPbPlay->SetClickHdl( LINK( this, SvtFileDialog, PlayButtonHdl_Impl ) ); + } + + if ( _nExtraBits & SFX_EXTRA_SHOWVERSIONS ) + { + _pImp->_pFtFileVersion = new FixedText( this, SvtResId( FT_EXPLORERFILE_SHARED_LISTBOX ) ); + _pImp->_pFtFileVersion->SetText( SvtResId( STR_SVT_FILEPICKER_VERSION ) ); + + _pImp->_pLbFileVersion = new ListBox( this, SvtResId( LB_EXPLORERFILE_SHARED_LISTBOX ) ); + _pImp->_pLbFileVersion->SetHelpId( HID_FILEOPEN_VERSION ); + } + else if ( _nExtraBits & SFX_EXTRA_TEMPLATES ) + { + _pImp->_pFtTemplates = new FixedText( this, SvtResId( FT_EXPLORERFILE_SHARED_LISTBOX ) ); + _pImp->_pFtTemplates->SetText( SvtResId( STR_SVT_FILEPICKER_TEMPLATES ) ); + + _pImp->_pLbTemplates = new ListBox( this, SvtResId( LB_EXPLORERFILE_SHARED_LISTBOX ) ); + _pImp->_pLbTemplates->SetHelpId( HID_FILEOPEN_VERSION ); + // This is strange. During the re-factoring during 96930, I discovered that this help id + // is set in the "Templates mode". This was hidden in the previous implementation. + // Shouldn't this be a more meaningfull help id. + // 96930 - 15.08.2002 - fs@openoffice.org + } + else if ( _nExtraBits & SFX_EXTRA_IMAGE_TEMPLATE ) + { + _pImp->_pFtImageTemplates = new FixedText( this, SvtResId( FT_EXPLORERFILE_SHARED_LISTBOX ) ); + _pImp->_pFtImageTemplates->SetText( SvtResId( STR_SVT_FILEPICKER_IMAGE_TEMPLATE ) ); + + _pImp->_pLbImageTemplates = new ListBox( this, SvtResId( LB_EXPLORERFILE_SHARED_LISTBOX ) ); + _pImp->_pLbImageTemplates->SetHelpId( HID_FILEOPEN_IMAGE_TEMPLATE ); + } +} + +// ----------------------------------------------------------------------- +sal_Int32 SvtFileDialog::getTargetColorDepth() +{ + if ( _pPrevBmp ) + return _pPrevBmp->GetBitCount(); + else + return 0; +} + +// ----------------------------------------------------------------------- +sal_Int32 SvtFileDialog::getAvailableWidth() +{ + if ( _pPrevBmp ) + return _pPrevBmp->GetOutputSizePixel().Width(); + else + return 0; +} + +// ----------------------------------------------------------------------- +sal_Int32 SvtFileDialog::getAvailableHeight() +{ + if ( _pPrevBmp ) + return _pPrevBmp->GetOutputSizePixel().Height(); + else + return 0; +} + +// ----------------------------------------------------------------------- +void SvtFileDialog::setImage( sal_Int16 /*aImageFormat*/, const Any& rImage ) +{ + if ( ! _pPrevBmp || ! _pPrevBmp->IsVisible() ) + return; + + Sequence < sal_Int8 > aBmpSequence; + + if ( rImage >>= aBmpSequence ) + { + Bitmap aBmp; + SvMemoryStream aData( aBmpSequence.getArray(), + aBmpSequence.getLength(), + STREAM_READ ); + aData >> aBmp; + + _pPrevBmp->SetBitmap( aBmp ); + } + else + { + Bitmap aEmpty; + _pPrevBmp->SetBitmap( aEmpty ); + } +} + +// ----------------------------------------------------------------------- +sal_Bool SvtFileDialog::setShowState( sal_Bool /*bShowState*/ ) +{ + // #97633 for the system filedialog it's + // usefull to make the preview switchable + // because the preview occupies + // half of the size of the file listbox + // which is not the case here, + // so we (TRA/FS) decided not to make + // the preview window switchable because + // else we would have to change the layout + // of the file dialog dynamically + // support for set/getShowState is opionally + // see com::sun::star::ui::dialogs::XFilePreview + /* + if ( _pPrevBmp ) + { + _pPrevBmp->Show( bShowState ); + return sal_True; + } + else + return sal_False; + */ + + return sal_False; +} + +// ----------------------------------------------------------------------- +String SvtFileDialog::getCurrentFileText( ) const +{ + String sReturn; + if ( _pImp && _pImp->_pEdFileName ) + sReturn = _pImp->_pEdFileName->GetText(); + return sReturn; +} + +// ----------------------------------------------------------------------- +void SvtFileDialog::setCurrentFileText( const String& _rText, bool _bSelectAll ) +{ + if ( _pImp && _pImp->_pEdFileName ) + { + _pImp->_pEdFileName->SetText( _rText ); + if ( _bSelectAll ) + _pImp->_pEdFileName->SetSelection( Selection( 0, _rText.Len() ) ); + } +} + +// ----------------------------------------------------------------------- +sal_Bool SvtFileDialog::isAutoExtensionEnabled() +{ + return _pImp->_pCbAutoExtension && _pImp->_pCbAutoExtension->IsChecked(); +} + +// ----------------------------------------------------------------------- +sal_Bool SvtFileDialog::getShowState() +{ + if ( _pPrevBmp ) + return _pPrevBmp->IsVisible(); + else + return sal_False; +} + +// ----------------------------------------------------------------------- +void SvtFileDialog::ReleaseOwnerShip( Window* pUserControl ) + +/* + [Beschreibung] + Die Methode sorgt dafuer das das spezifizierte Element nicht mehr im Besitz + der Instanz ist. +*/ + +{ + ControlChain_Impl* pElement = _pUserControls; + while ( pElement ) + { + if ( pElement->_pControl == pUserControl ) + { + pElement->_bHasOwnerShip = FALSE; + break; + } + pElement = pElement->_pNext; + } +} + +//*************************************************************************** + +BOOL SvtFileDialog::AddControl( Window* pControl, BOOL bNewLine ) +{ + // control already exists + ControlChain_Impl* pElement = _pUserControls; + while ( pElement ) + { + if ( pElement->_pControl == pControl ) + return FALSE; + pElement = pElement->_pNext; + } + + // Check if controls have already been added. + Size aNewControlSize( pControl->GetOutputSizePixel() ); + Size aDlgSize( GetOutputSizePixel() ); + WindowType nType = pControl->GetType(); + if ( !aNewControlSize.Height() ) + { + // Detect a size. + Size aSize( 0, 10 ); + if ( nType == WINDOW_PUSHBUTTON ) + { + Size aDefSiz = LogicToPixel( Size( 50, 14 ), MAP_APPFONT ); + long nTextWidth = pControl->GetTextWidth( pControl->GetText() ); + aSize.Width() = nTextWidth + WIDTH_ADDITION; + + // PushButton: Mindestbreite 50 logische Einheiten, + // H"ohe immer 14 logische Einheiten + if ( aDefSiz.Width() > aSize.Width() ) + aSize.Width() = aDefSiz.Width(); + aSize.Height() = aDefSiz.Height(); + aNewControlSize = aSize; + } + else + aNewControlSize = LogicToPixel( aSize, MAP_APPFONT ); + if ( nType != WINDOW_PUSHBUTTON ) + aNewControlSize.Width() = pControl->GetTextWidth( pControl->GetText() ) + WIDTH_ADDITION; + if ( nType == WINDOW_CHECKBOX ) + aNewControlSize.Width() += WIDTH_ADDITION; + if ( nType == WINDOW_WINDOW ) + { + aNewControlSize.Height() = GetOutputSizePixel().Height() - 18; + aNewControlSize.Width() = 200; + aDlgSize.Width() += 210; + SetOutputSizePixel( aDlgSize ); + } + pControl->SetOutputSizePixel( aNewControlSize ); + } + Point aNewControlPos; + Size* pNewDlgSize = NULL; + BOOL bNewRow = bNewLine; + + if ( nType == WINDOW_WINDOW ) + { + aNewControlPos.X() = aDlgSize.Width() - 210; + aNewControlPos.Y() = 8; + } + else if ( _pUserControls ) + { + Point aNewControlRange( _pUserControls->_pControl->GetPosPixel() ); + long nPrevControlHeight = _pUserControls->_pControl->GetSizePixel().Height(); + aNewControlRange += + Point( _pUserControls->_pControl->GetOutputSizePixel().Width(), 0 ); + aNewControlPos = aNewControlRange; + if ( nPrevControlHeight > aNewControlSize.Height() ) + { + long nY = nPrevControlHeight; + nY -= aNewControlSize.Height(); + nY /= 2; + aNewControlPos.Y() += nY; + } + aNewControlPos += LogicToPixel( Point( 3, 0 ), MAP_APPFONT ); + aNewControlRange += LogicToPixel( Point( 9, 0 ), MAP_APPFONT ); + aNewControlRange += Point( aNewControlSize.Width(), 0 ); + + // Check if a new row has to be created. + if ( aNewControlRange.X() > aDlgSize.Width() ) + bNewRow = TRUE; + } + else + { + // Create a new row if there was no usercontrol before. + bNewRow = TRUE; + } + + // Check if a new row has to be created. + Size aBorderSize = LogicToPixel( Size( 6, 6 ), MAP_APPFONT ); + long nLeftBorder = aBorderSize.Width(); + long nLowerBorder = aBorderSize.Height(); + if ( bNewRow ) + { + // Set control at the beginning of a new line. + long nSmallBorderHeight = nLowerBorder / 2; + aNewControlPos = Point( nLeftBorder, 0 ); + aNewControlPos += Point( 0, aDlgSize.Height() ); + aNewControlPos.Y() -= nSmallBorderHeight; + // Set new size. + pNewDlgSize = new Size( aDlgSize ); + pNewDlgSize->Height() -= nSmallBorderHeight; + pNewDlgSize->Height() += aNewControlSize.Height(); + pNewDlgSize->Height() += nLowerBorder; + } + else + { + // Check if the window has to be resized. + Size aNewControlRange( 0, aNewControlPos.Y() ); + aNewControlRange.Height() += aNewControlSize.Height(); + aNewControlRange.Height() += nLowerBorder; + if ( aNewControlRange.Height() > aDlgSize.Height() ) + pNewDlgSize = new Size( aDlgSize.Width(), aNewControlRange.Height() ); + } + + // Update view. + if ( pNewDlgSize ) + { + SetOutputSizePixel( *pNewDlgSize ); + delete pNewDlgSize; + } + pControl->SetPosPixel( aNewControlPos ); + pControl->Show(); + _pUserControls = new ControlChain_Impl( pControl, _pUserControls ); + + return TRUE; +} + +sal_Bool SvtFileDialog::ContentHasParentFolder( const rtl::OUString& rURL ) +{ + m_aContent.bindTo( rURL ); + + if ( m_aContent.isInvalid() ) + return sal_False; + + return m_aContent.hasParentFolder( ) && m_aContent.isValid(); +} + +sal_Bool SvtFileDialog::ContentCanMakeFolder( const rtl::OUString& rURL ) +{ + m_aContent.bindTo( rURL ); + + if ( m_aContent.isInvalid() ) + return sal_False; + + return m_aContent.canCreateFolder( ) && m_aContent.isValid(); +} + +sal_Bool SvtFileDialog::ContentGetTitle( const rtl::OUString& rURL, String& rTitle ) +{ + m_aContent.bindTo( rURL ); + + if ( m_aContent.isInvalid() ) + return sal_False; + + ::rtl::OUString sTitle; + m_aContent.getTitle( sTitle ); + rTitle = sTitle; + + return m_aContent.isValid(); +} + +void SvtFileDialog::appendDefaultExtension(String& _rFileName, + const String& _rFilterDefaultExtension, + const String& _rFilterExtensions) +{ + String aTemp(_rFileName); + aTemp.ToLowerAscii(); + String aType(_rFilterExtensions); + aType.ToLowerAscii(); + + if ( ! aType.EqualsAscii(FILEDIALOG_FILTER_ALL) ) + { + USHORT nWildCard = aType.GetTokenCount( FILEDIALOG_DEF_EXTSEP ); + USHORT nIndex, nPos = 0; + + for ( nIndex = 0; nIndex < nWildCard; nIndex++ ) + { + String aExt(aType.GetToken( 0, FILEDIALOG_DEF_EXTSEP, nPos )); + // take care of a leading * + USHORT nExtOffset = (aExt.GetBuffer()[0] == '*' ? 1 : 0); + sal_Unicode* pExt = aExt.GetBufferAccess() + nExtOffset; + xub_StrLen nExtLen = aExt.Len() - nExtOffset; + xub_StrLen nOffset = aTemp.Len() - nExtLen; + // minimize search by starting at last possible index + if ( aTemp.Search(pExt, nOffset) == nOffset ) + break; + } + + if ( nIndex >= nWildCard ) + { + _rFileName += '.'; + _rFileName += _rFilterDefaultExtension; + } + } +} + +// ----------------------------------------------------------------------- + +// QueryFolderNameDialog ------------------------------------------------------- + +namespace svtools { + +QueryFolderNameDialog::QueryFolderNameDialog +( + Window* _pParent, + const String& rTitle, + const String& rDefaultText, + String* pGroupName +) : + ModalDialog( _pParent, SvtResId( DLG_SVT_QUERYFOLDERNAME ) ), + + aNameText ( this, SvtResId( FT_SVT_QUERYFOLDERNAME_DLG_NAME ) ), + aNameEdit ( this, SvtResId( ED_SVT_QUERYFOLDERNAME_DLG_NAME ) ), + aNameLine ( this, SvtResId( FL_SVT_QUERYFOLDERNAME_DLG_NAME ) ), + aOKBtn ( this, SvtResId( BT_SVT_QUERYFOLDERNAME_DLG_OK ) ), + aCancelBtn ( this, SvtResId( BT_SVT_QUERYFOLDERNAME_DLG_CANCEL ) ) +{ + FreeResource(); + SetText( rTitle ); + aNameEdit.SetText( rDefaultText ); + aNameEdit.SetSelection( Selection( 0, rDefaultText.Len() ) ); + aOKBtn.SetClickHdl( LINK( this, QueryFolderNameDialog, OKHdl ) ); + aNameEdit.SetModifyHdl( LINK( this, QueryFolderNameDialog, NameHdl ) ); + + if ( pGroupName ) + aNameLine.SetText( *pGroupName ); +}; + +// ----------------------------------------------------------------------- +IMPL_LINK( QueryFolderNameDialog, OKHdl, Button *, EMPTYARG ) +{ + // trim the strings + aNameEdit.SetText( aNameEdit.GetText().EraseLeadingChars().EraseTrailingChars() ); + EndDialog( RET_OK ); + return 1; +} + +// ----------------------------------------------------------------------- +IMPL_LINK( QueryFolderNameDialog, NameHdl, Edit *, EMPTYARG ) +{ + // trim the strings + String aName = aNameEdit.GetText(); + aName.EraseLeadingChars().EraseTrailingChars(); + if ( aName.Len() ) + { + if ( !aOKBtn.IsEnabled() ) + aOKBtn.Enable( TRUE ); + } + else + { + if ( aOKBtn.IsEnabled() ) + aOKBtn.Enable( FALSE ); + } + + return 0; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/office/iodlg.hrc b/fpicker/source/office/iodlg.hrc new file mode 100644 index 000000000000..15f5121b0965 --- /dev/null +++ b/fpicker/source/office/iodlg.hrc @@ -0,0 +1,107 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SVTOOLS_IODLGIMPL_HRC +#define _SVTOOLS_IODLGIMPL_HRC + +#ifndef _SVTOOLS_HRC +#include "svtools/svtools.hrc" +#endif + +// ModalDialog DLG_SVT_EXPLORERFILE + +#define FT_EXPLORERFILE_CURRENTPATH 10 +#define BTN_EXPLORERFILE_NEWFOLDER 11 +#define BTN_EXPLORERFILE_LISTVIEW 12 +#define BTN_EXPLORERFILE_DETAILSVIEW 13 +#define BTN_EXPLORERFILE_UP 14 +#define BTN_EXPLORERFILE_STANDARD 15 +#define BTN_EXPLORERFILE_OPEN 16 +#define BTN_EXPLORERFILE_CANCEL 17 +#define BTN_EXPLORERFILE_HELP 18 + +#define IMG_FILEDLG_BTN_UP 10 +#define IMG_FILEDLG_BTN_STD 11 +#define IMG_FILEDLG_CREATEFOLDER 14 + +#define CTL_EXPLORERFILE_FILELIST 20 + +#define FT_EXPLORERFILE_FILENAME 30 +#define ED_EXPLORERFILE_FILENAME 31 +#define FT_EXPLORERFILE_SHARED_LISTBOX 32 +#define LB_EXPLORERFILE_SHARED_LISTBOX 33 +#define FT_EXPLORERFILE_FILETYPE 34 +#define LB_EXPLORERFILE_FILETYPE 35 + +#define CB_EXPLORERFILE_READONLY 40 +#define CB_EXPLORERFILE_PASSWORD 41 +#define CB_AUTO_EXTENSION 42 +#define CB_OPTIONS 43 + +// ----------------------------------------------- + +#define STR_EXPLORERFILE_OPEN 1 +#define STR_EXPLORERFILE_SAVE 2 +#define STR_EXPLORERFILE_BUTTONSAVE 3 +#define STR_PATHNAME 4 +#define STR_PATHSELECT 5 +#define STR_BUTTONSELECT 6 +#define STR_ACTUALVERSION 7 + +// DLG_SVT_QUERYFOLDERNAME ----------------------- + +#define FT_SVT_QUERYFOLDERNAME_DLG_NAME 10 +#define ED_SVT_QUERYFOLDERNAME_DLG_NAME 11 +#define FL_SVT_QUERYFOLDERNAME_DLG_NAME 12 +#define BT_SVT_QUERYFOLDERNAME_DLG_OK 13 +#define BT_SVT_QUERYFOLDERNAME_DLG_CANCEL 14 +#define BT_SVT_QUERYFOLDERNAME_DLG_HELP 15 + +// ----------------------------------------------- + +#define SID_SFX_START 5000 +#define SID_OPENURL (SID_SFX_START + 596) + +#define HID_FILEDLG_STANDARD (HID_SFX_START + 27) +#define HID_FILEDLG_MANAGER (HID_SFX_START + 28) +#define HID_FILEDLG_URL (HID_SFX_START + 29) +#define HID_FILEDLG_USE_PASSWD (HID_SFX_START + 31) +#define HID_FILEDLG_READ_ONLY (HID_SFX_START + 32) + +#define HID_FILEDLG_AUTOCOMPLETEBOX (HID_SFX_START + 218) +#define HID_FILEDLG_SAVE_BTN (HID_SFX_START + 219) +#define HID_FILEDLG_SAVE_FILENAME (HID_SFX_START + 220) +#define HID_FILEDLG_SAVE_FILETYPE (HID_SFX_START + 221) +#define HID_FILEDLG_INSERT_BTN (HID_SFX_START + 222) +#define HID_FILEDLG_PATH_BTN (HID_SFX_START + 223) +#define HID_FILEDLG_PATH_FILENAME (HID_SFX_START + 224) +#define HID_FILEDLG_FOLDER_BTN (HID_SFX_START + 225) +#define HID_FILEDLG_FOLDER_FILENAME (HID_SFX_START + 226) +#define HID_FILEDLG_SRCHFOLDER_BTN (HID_SFX_START + 227) + +#endif + diff --git a/fpicker/source/office/iodlg.hxx b/fpicker/source/office/iodlg.hxx new file mode 100644 index 000000000000..25b519601f6c --- /dev/null +++ b/fpicker/source/office/iodlg.hxx @@ -0,0 +1,474 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _IODLGIMPL_HXX +#define _IODLGIMPL_HXX + +#include <vcl/dialog.hxx> +#include <vcl/button.hxx> +#include <vcl/fixed.hxx> +#include <vcl/edit.hxx> +#include <vcl/combobox.hxx> +#include <vcl/lstbox.hxx> +#include <com/sun/star/beans/StringPair.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/ucb/IOErrorCode.hpp> +#include <com/sun/star/ui/dialogs/XDialogClosedListener.hpp> +#include <unotools/confignode.hxx> +#include "svl/inettype.hxx" +#include "svl/urlfilter.hxx" +#include <svl/restrictedpaths.hxx> +#include "asyncfilepicker.hxx" +#include "OfficeControlAccess.hxx" +#include "fpsmartcontent.hxx" + +#include <set> + +// @@@ using namespace com::sun::star::ucb; + +//***************************************************************************** + +class SvTabListBox; +class SvStringsDtor; +class SvtFileView; +struct ControlChain_Impl; +class SvtFileDialogFilter_Impl; + +//***************************************************************************** + +#define SFXWB_INSERT ( 0x04000000L | WB_OPEN ) +#define SFXWB_PASSWORD WB_PASSWORD +#define SFXWB_READONLY WB_READONLY +#define SFXWB_PATHDIALOG WB_PATH +#define SFXWB_CLASSPATH ( 0x08000000L | SFXWB_PATHDIALOG ) +#define SFXWB_SHOWALLFOLDER 0x10000000L // alle Ordner auch Mail/News/... +#define SFXWB_MULTISELECTION 0x20000000L // Multiselection an +#define SFXWB_NOREMOTE 0x40000000L +#define SFXWB_SHOWVERSIONS 0x80000000L // Versionsauswahl anzeigen + +#define SFX_EXTRA_AUTOEXTENSION 0x00000001L +#define SFX_EXTRA_FILTEROPTIONS 0x00000002L +#define SFX_EXTRA_SHOWVERSIONS 0x00000004L +#define SFX_EXTRA_INSERTASLINK 0x00000008L +#define SFX_EXTRA_SHOWPREVIEW 0x00000010L +#define SFX_EXTRA_TEMPLATES 0x00000020L +#define SFX_EXTRA_PLAYBUTTON 0x00000040L +#define SFX_EXTRA_SELECTION 0x00000080L +#define SFX_EXTRA_IMAGE_TEMPLATE 0x00000100L + +#define RET_MANAGER 100 + +#define FILEDIALOG_FILTER_ALL "*.*" + +//***************************************************************************** +// SvtFileDialog +//***************************************************************************** + +class SvtExpFileDlg_Impl; +class SvtFileDialog : public ModalDialog, public ::svt::IFilePickerController +{ +private: + // originally from VclFileDialog + ControlChain_Impl* _pUserControls; + + CheckBox* _pCbReadOnly; + CheckBox* _pCbLinkBox; + CheckBox* _pCbPreviewBox; + CheckBox* _pCbSelection; + PushButton* _pPbPlay; + Window* _pPrevWin; + FixedBitmap* _pPrevBmp; + SvtFileView* _pFileView; + ::svt::IFilePickerListener* _pFileNotifier; + SvtExpFileDlg_Impl* _pImp; + WinBits _nExtraBits; + BOOL _bIsInExecute : 1; + + ImageList m_aImages; + ::svt::SmartContent m_aContent; + + ::svt::RestrictedPaths m_aURLFilter; + ::std::set< Control* > m_aDisabledControls; + + ::utl::OConfigurationNode m_aConfiguration; + ::rtl::Reference< ::svt::AsyncPickerAction > + m_pCurrentAsyncAction; + ::com::sun::star::uno::Reference< + ::com::sun::star::ui::dialogs::XDialogClosedListener > + m_xListener; + bool m_bInExecuteAsync; + bool m_bHasFilename; + + DECL_STATIC_LINK( SvtFileDialog, FilterSelectHdl_Impl, ListBox* ); + DECL_STATIC_LINK( SvtFileDialog, NewFolderHdl_Impl, PushButton* ); + DECL_STATIC_LINK( SvtFileDialog, ViewHdl_Impl, ImageButton* ); + DECL_STATIC_LINK( SvtFileDialog, OpenHdl_Impl, void* ); + DECL_LINK ( CancelHdl_Impl, void* ); + DECL_STATIC_LINK( SvtFileDialog, FileNameGetFocusHdl_Impl, void* ); + DECL_STATIC_LINK( SvtFileDialog, FileNameModifiedHdl_Impl, void* ); + + void Init_Impl( WinBits nBits ); + /** find a filter with the given wildcard + @param _rFilter + the wildcard pattern to look for in the filter list + @param _bMultiExt + allow for filters with more than one extension pattern + @param _rFilterChanged + set to <TRUE/> if the filter changed + @return + the filter which has been found + */ + SvtFileDialogFilter_Impl* FindFilter_Impl( const String& _rFilter, + sal_Bool _bMultiExt, + sal_Bool& _rFilterChanged + ); + void ExecuteFilter(); + void OpenMultiSelection_Impl(); + void AddControls_Impl( ); + + DECL_LINK( SelectHdl_Impl, SvTabListBox* ); + DECL_LINK( DblClickHdl_Impl, SvTabListBox* ); + DECL_LINK( EntrySelectHdl_Impl, ComboBox* ); + DECL_LINK( OpenDoneHdl_Impl, SvtFileView* ); + DECL_LINK( AutoExtensionHdl_Impl, CheckBox* ); + DECL_LINK( ClickHdl_Impl, CheckBox* ); + DECL_LINK( PlayButtonHdl_Impl, PushButton* ); + + // entfernt einen Filter mit Wildcards aus dem Path und gibt in zurueck + BOOL IsolateFilterFromPath_Impl( String& rPath, String& rFilter ); + + void implArrangeControls(); + void implUpdateImages( ); + +protected: + virtual long Notify( NotifyEvent& rNEvt ); + void EnableInternet( BOOL bInternet ); + + // originally from VclFileDialog + Link _aOKHdl; + Link _aFileSelectHdl; + Link _aFilterSelectHdl; + + String _aPath; + String _aDefExt; + + void ReleaseOwnerShip( Window* pUserControl ); + + /** enables or disables the complete UI of the file picker, with only offering a + cancel button + + This method preserves the "enabled" state of its controls in the following sense: + If you disable a certain control, then disable the dialog UI, then enable the dialog + UI, the control will still be disabled. + This is under the assumption that you'll use EnableControl. Direct access to the control + (such as pControl->Enable()) will break this. + */ + void EnableUI( BOOL _bEnable ); + + /** enables or disables a control + + You are strongly encouraged to prefer this method over pControl->Enable( _bEnable ). See + <member>EnableUI</member> for details. + */ + void EnableControl( Control* _pControl, BOOL _bEnable ); + short PrepareExecute(); + +public: + SvtFileDialog( Window* _pParent, WinBits nBits, WinBits nExtraBits ); + SvtFileDialog( Window* _pParent, WinBits nBits ); + ~SvtFileDialog(); + + virtual long OK(); + virtual short Execute(); + virtual void StartExecuteModal( const Link& rEndDialogHdl ); + + void FileSelect(); + void FilterSelect(); + + void SetBlackList( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList ); + const ::com::sun::star::uno::Sequence< ::rtl::OUString >& GetBlackList() const; + void SetStandardDir( const String& rStdDir ); + const String& GetStandardDir() const; + SvStringsDtor* GetPathList() const; // bei MultiSelektion + + void AddFilter( const String& rFilter, + const String& rType ); + + void AddFilterGroup( + const String& _rFilter, + const com::sun::star::uno::Sequence< com::sun::star::beans::StringPair >& rFilters ); + + void SetCurFilter( const String& rFilter ); + String GetCurFilter() const; + USHORT GetFilterCount() const; + const String& GetFilterName( USHORT nPos ) const; + + virtual void Resize(); + virtual void DataChanged( const DataChangedEvent& _rDCEvt ); + + void PrevLevel_Impl(); + void OpenURL_Impl( const String& rURL ); + + inline SvtFileView* GetView() const; + + void DisableSaveLastDirectory(); + void InitSize(); + void UpdateControls( const String& rURL ); + void EnableAutocompletion( BOOL _bEnable = TRUE ); + + void SetFileCallback( ::svt::IFilePickerListener *pNotifier ) { _pFileNotifier = pNotifier; } + + sal_Int32 getTargetColorDepth(); + sal_Int32 getAvailableWidth(); + sal_Int32 getAvailableHeight(); + void setImage( sal_Int16 aImageFormat, const ::com::sun::star::uno::Any& rImage ); + sal_Bool setShowState( sal_Bool bShowState ); + sal_Bool getShowState(); + sal_Bool isAutoExtensionEnabled(); + + String getCurrentFileText( ) const; + void setCurrentFileText( const String& _rText, bool _bSelectAll = false ); + + void onAsyncOperationStarted(); + void onAsyncOperationFinished(); + + void displayIOException( const String& _rURL, ::com::sun::star::ucb::IOErrorCode _eCode ); + void simulateAccessDenied( const String& _rURL ) + { + displayIOException( _rURL, ::com::sun::star::ucb::IOErrorCode_ACCESS_DENIED ); + } + + // originally from VclFileDialog + virtual BOOL AddControl( Window* pControl, BOOL bNewLine = FALSE ); + + // inline + inline void SetPath( const String& rNewURL ); + inline void SetHasFilename( bool bHasFilename ); + inline const String& GetPath() const; + inline void SetDefaultExt( const String& rExt ); + inline void EraseDefaultExt( xub_StrLen _nIndex = 0 ); + inline const String& GetDefaultExt() const; + inline void SetOKHdl( const Link& rLink ); + inline const Link& GetOKHdl() const; + inline void SetFileSelectHdl( const Link& rLink ); + inline const Link& GetFileSelectHdl() const; + inline void SetFilterSelectHdl( const Link& rLink ); + inline const Link& GetFilterSelectHdl() const; + + inline Image GetButtonImage( sal_uInt16 _nButtonId ) const { return m_aImages.GetImage( _nButtonId ); } + + sal_Bool ContentIsFolder( const rtl::OUString& rURL ) { return m_aContent.isFolder( rURL ) && m_aContent.isValid(); } + sal_Bool ContentHasParentFolder( const rtl::OUString& rURL ); + sal_Bool ContentCanMakeFolder( const rtl::OUString& rURL ); + sal_Bool ContentGetTitle( const rtl::OUString& rURL, String& rTitle ); + + /** updates the sizes of the listboxes in the bottom area of the dialog, and of their labels, + according to the space occupied by the current label texts + + @since #i42824# + */ + void updateListboxLabelSizes(); + + /** checks URL access permissions + + <p>with the "restriction" feature we have in the file dialog, it's possible that + only certain URLs can be browsed. This method checks whether a given URL belongs + to this set of permitted URLs.</p> + + <p>If no "access restriction" is effective, this method always returns <TRUE/>.</p> + */ + inline bool isUrlAllowed( const String& _rURL ) const { return m_aURLFilter.isUrlAllowed( _rURL ); } + +private: + SvtFileDialogFilter_Impl* implAddFilter( const String& _rFilter, const String& _rType ); + + /** updates _pUserFilter with a new filter + <p>No checks for necessity are made.</p> + @param _bAllowUserDefExt + set to <TRUE/> if a filter like "*.txt" should reset the DefaultExtension to doc. + <p> + In a file-save-dialog this would have the following effect:<br/> + Say that auto-extension is checked, and the user enters *.txt, while a non-txt filter is selected.<br/> + If _bAllowUserDefExt is set to <TRUE/>, then a user input of "foo" would save a foo.txt, but in a format + which is determined by the filter selected (which is no txt file as said above).<br/> + If _bAllowUserDefExt is set to <FALSE/>, the default extension will be the one of the selected filter, means + in the above scenario a file "foo.<ext>" will be saved where ext is the extension of the selected filter. + </p> + @return <TRUE/> if the new filter is "*.*" + */ + sal_Bool createNewUserFilter( const String& _rNewFilter, sal_Bool _bAllowUserDefExt ); + + sal_uInt16 adjustFilter( const String& _rFilter ); + + // IFilePickerController, needed by OControlAccess + virtual Control* getControl( sal_Int16 _nControlId, sal_Bool _bLabelControl = sal_False ) const; + virtual void enableControl( sal_Int16 _nControlId, sal_Bool _bEnable ); + virtual String getCurFilter( ) const; + + String implGetInitialURL( const String& _rPath, const String& _rFallback ); + + /// initializes the special URL lists, such as our favourites and our restricted paths + void implInitializeSpecialURLLists( ); + + /// executes a certain FileView action asynchronously + void executeAsync( + ::svt::AsyncPickerAction::Action _eAction, + const String& _rURL, + const String& _rFilter + ); + + /** helper function to check and append the default filter extension if + necessary. + The function checks if the specified filename already contains one of + the valid extensions of the specified filter. If not the filter default + extension is appended to the filename. + + @param _rFileName the filename which is checked and extended if necessary. + @param _rFilterDefaultExtension the default extension of the used filter. + @param _rFilterExtensions a list of one or more valid filter extensions + of the used filter. + + */ + static void appendDefaultExtension( + String& _rFileName, + const String& _rFilterDefaultExtension, + const String& _rFilterExtensions); +}; + +//*************************************************************************** + +inline void SvtFileDialog::SetPath( const String& rNewURL ) +{ + _aPath = rNewURL; +} + +//*************************************************************************** + +inline void SvtFileDialog::SetHasFilename( bool bHasFilename ) +{ + m_bHasFilename = bHasFilename; +} + +//*************************************************************************** + +inline const String& SvtFileDialog::GetPath() const +{ + return _aPath; +} + +//*************************************************************************** + +inline void SvtFileDialog::SetDefaultExt( const String& rExt ) +{ + _aDefExt = rExt; +} + +inline void SvtFileDialog::EraseDefaultExt( xub_StrLen _nIndex ) +{ + _aDefExt.Erase( _nIndex ); +} + +inline const String& SvtFileDialog::GetDefaultExt() const +{ + return _aDefExt; +} + +//***************************************************************************** + +inline void SvtFileDialog::SetOKHdl +( + const Link& rLink +) +{ + _aOKHdl = rLink; +} + +//***************************************************************************** + +inline const Link& SvtFileDialog::GetOKHdl() const +{ + return _aOKHdl; +} + +//***************************************************************************** + +inline void SvtFileDialog::SetFileSelectHdl +( + const Link& rLink +) +{ + _aFileSelectHdl = rLink; +} + +//***************************************************************************** + +inline const Link& SvtFileDialog::GetFileSelectHdl() const +{ + return _aFileSelectHdl; +} + +//***************************************************************************** + +inline void SvtFileDialog::SetFilterSelectHdl +( + const Link& rLink +) +{ + _aFilterSelectHdl = rLink; +} + +//***************************************************************************** + +inline const Link& SvtFileDialog::GetFilterSelectHdl() const +{ + return _aFilterSelectHdl; +} + +//***************************************************************************** + +inline SvtFileView* SvtFileDialog::GetView() const +{ + return _pFileView; +} + +//***************************************************************************** +//***************************************************************************** +//***************************************************************************** + +class SvtFilePicker; + +#define FILE_SELECTION_CHANGED 1 +#define DIRECTORY_CHANGED 2 +#define HELP_REQUESTED 3 +#define CTRL_STATE_CHANGED 4 +#define DIALOG_SIZE_CHANGED 5 + + +#endif // #ifndef _IODLG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/office/iodlg.src b/fpicker/source/office/iodlg.src new file mode 100644 index 000000000000..249383dc8a47 --- /dev/null +++ b/fpicker/source/office/iodlg.src @@ -0,0 +1,316 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + // includes ****************************************************************** +#include "svtools/svtools.hrc" +#include "svtools/helpid.hrc" +#include "iodlg.hrc" + +#define FILEPICKER_IL_IDLIST \ + IdList = \ + { \ + IMG_FILEDLG_BTN_UP; \ + IMG_FILEDLG_BTN_STD; \ + IMG_FILEDLG_CREATEFOLDER; \ + }; \ + IdCount = \ + { \ + 3; \ + }; + +#define MASKCOLOR MaskColor = Color { Red = 0xFFFF; Green = 0x0000; Blue = 0xFFFF; }; + + // image lists *************************************************************** + +ImageList RID_FILEPICKER_IMAGES +{ + Prefix = "fp"; + MASKCOLOR + FILEPICKER_IL_IDLIST +}; + + // dialogs ******************************************************************* + +ModalDialog DLG_SVT_EXPLORERFILE +{ + OutputSize = TRUE ; + SVLook = TRUE ; + Moveable = TRUE ; + Closeable = TRUE ; + Sizeable = TRUE; + HelpId = HID_EXPLORERDLG_FILE ; + Size = MAP_APPFONT ( 280 , 174 ) ; + FixedText FT_EXPLORERFILE_CURRENTPATH + { + Pos = MAP_APPFONT ( 6 , 6 ) ; + Size = MAP_APPFONT ( 100 , 10 ) ; + NoLabel = TRUE ; + }; + ImageButton BTN_EXPLORERFILE_NEWFOLDER + { + TabStop = FALSE ; + Pos = MAP_APPFONT ( 59 , 6 ) ; + QuickHelpText [ en-US ] = "Create New Directory" ; + }; + ImageButton BTN_EXPLORERFILE_LISTVIEW + { + TabStop = FALSE ; + Pos = MAP_APPFONT ( 109 , 6 ) ; + ButtonImage = Image + { + ImageBitmap = Bitmap + { + File = "list.bmp" ; + }; + MASKCOLOR + }; + QuickHelpText [ en-US ] = "List"; + }; + ImageButton BTN_EXPLORERFILE_DETAILSVIEW + { + TabStop = FALSE ; + Pos = MAP_APPFONT ( 109 , 6 ) ; + ButtonImage = Image + { + ImageBitmap = Bitmap + { + File = "sc06356.bmp" ; + }; + MASKCOLOR + }; + QuickHelpText [ en-US ] = "Details"; + }; + MenuButton BTN_EXPLORERFILE_UP + { + TabStop = FALSE ; + Pos = MAP_APPFONT ( 109 , 6 ) ; + QuickHelpText [ en-US ] = "Up One Level" ; + }; + + MenuButton BTN_EXPLORERFILE_STANDARD + { + TabStop = FALSE ; + Pos = MAP_APPFONT ( 59 , 6 ) ; + QuickHelpText [ en-US ] = "Default Directory" ; + }; + Control CTL_EXPLORERFILE_FILELIST + { + TabStop = TRUE ; + Pos = MAP_APPFONT ( 6 , 26 ) ; + Size = MAP_APPFONT ( 268 , 85 ) ; + Border = TRUE ; + }; + FixedText FT_EXPLORERFILE_FILENAME + { + Pos = MAP_APPFONT ( 6 , 118 ) ; + Size = MAP_APPFONT ( 50 , 10 ) ; + Text [ en-US ] = "File ~name:" ; + }; + Edit ED_EXPLORERFILE_FILENAME + { + Pos = MAP_APPFONT ( 59 , 117 ) ; + Size = MAP_APPFONT ( 159 , 12 ) ; + Border = TRUE ; + }; + FixedText FT_EXPLORERFILE_SHARED_LISTBOX + { + Pos = MAP_APPFONT ( 6 , 133 ) ; + Size = MAP_APPFONT ( 50 , 10 ) ; + // Note: this control does not have a text. The text is filled at runtime from the STR_SVT_FILEPICKER_VERSION, + // STR_SVT_FILEPICKER_TEMPLATES, or STR_SVT_FILEPICKER_IMAGE_TEMPLATE resource + }; + ListBox LB_EXPLORERFILE_SHARED_LISTBOX + { + Pos = MAP_APPFONT ( 59 , 132 ) ; + Size = MAP_APPFONT ( 159 , 40 ) ; + DropDown = TRUE ; + AutoSize = TRUE ; + AutoHScroll = TRUE ; + }; + FixedText FT_EXPLORERFILE_FILETYPE + { + Pos = MAP_APPFONT ( 6 , 148 ) ; + Size = MAP_APPFONT ( 50 , 10 ) ; + Text [ en-US ] = "File ~type:" ; + }; + ListBox LB_EXPLORERFILE_FILETYPE + { + Pos = MAP_APPFONT ( 59 , 147 ) ; + Size = MAP_APPFONT ( 159 , 80 ) ; + DropDown = TRUE ; + AutoSize = TRUE ; + AutoHScroll = TRUE ; + Sort = FALSE ; + }; + CheckBox CB_EXPLORERFILE_READONLY + { + Size = MAP_APPFONT ( 80 , 10 ) ; + Text [ en-US ] = "~Read-only" ; + }; + CheckBox CB_EXPLORERFILE_PASSWORD + { + Size = MAP_APPFONT ( 100, 10 ) ; + Text [ en-US ] = "Save with password" ; + }; + CheckBox CB_AUTO_EXTENSION + { + Size = MAP_APPFONT ( 160 , 10 ) ; + Text [ en-US ] = "~Automatic file name extension" ; + }; + CheckBox CB_OPTIONS + { + Size = MAP_APPFONT ( 120 , 10 ) ; + Text [ en-US ] = "Edit ~filter settings"; + }; + PushButton BTN_EXPLORERFILE_OPEN + { + Pos = MAP_APPFONT ( 224 , 117 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + DefButton = TRUE ; + Text [ en-US ] = "~Open" ; + }; + CancelButton BTN_EXPLORERFILE_CANCEL + { + Pos = MAP_APPFONT ( 224 , 134 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + }; + HelpButton BTN_EXPLORERFILE_HELP + { + Pos = MAP_APPFONT ( 224 , 151 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + }; + String STR_EXPLORERFILE_OPEN + { + Text [ en-US ] = "Open" ; + }; + String STR_EXPLORERFILE_SAVE + { + Text [ en-US ] = "Save as" ; + }; + String STR_EXPLORERFILE_BUTTONSAVE + { + Text [ en-US ] = "~Save" ; + }; + String STR_PATHNAME + { + Text [ en-US ] = "~Path:" ; + }; + String STR_PATHSELECT + { + Text [ en-US ] = "Select path" ; + }; + String STR_BUTTONSELECT + { + Text [ en-US ] = "~Select"; + }; + String STR_ACTUALVERSION + { + Text [ en-US ] = "Current version"; + }; +}; + +// QueryFolderNameDialog ---------------------------------------------------------- +ModalDialog DLG_SVT_QUERYFOLDERNAME +{ + Border = TRUE ; + Moveable = TRUE ; + OutputSize = TRUE ; + SVLook = TRUE ; + Text = "Ordner" ; + Size = MAP_APPFONT ( 218 , 45 ) ; + FixedText FT_SVT_QUERYFOLDERNAME_DLG_NAME + { + Pos = MAP_APPFONT ( 12 , 14 ) ; + Size = MAP_APPFONT ( 138 , 10 ) ; + Text [ en-US ] = "Na~me" ; + }; + Edit ED_SVT_QUERYFOLDERNAME_DLG_NAME + { + Pos = MAP_APPFONT ( 12 , 27 ) ; + Size = MAP_APPFONT ( 138 , 12 ) ; + Border = TRUE ; + Left = TRUE ; + }; + FixedLine FL_SVT_QUERYFOLDERNAME_DLG_NAME + { + Group = TRUE ; + Pos = MAP_APPFONT ( 6 , 3 ) ; + Size = MAP_APPFONT ( 150 , 8 ) ; + Text [ en-US ] = "Create new folder" ; + }; + OKButton BT_SVT_QUERYFOLDERNAME_DLG_OK + { + Pos = MAP_APPFONT ( 162 , 6 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + DefButton = TRUE ; + }; + CancelButton BT_SVT_QUERYFOLDERNAME_DLG_CANCEL + { + Pos = MAP_APPFONT ( 162 , 23 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + }; +}; + +// strings ******************************************************************* + +String RID_FILEOPEN_INVALIDFOLDER +{ + Text [ en-US ] = "$name$ does not exist."; +}; + +String RID_FILEOPEN_NOTEXISTENTFILE +{ + Text [ en-US ] = "The file $name$ does not exist.\nMake sure you have entered the correct file name."; +}; + +String STR_FILTERNAME_ALL +{ + Text [ en-US ] = "All files (*.*)" ; +}; + +String STR_SVT_ALREADYEXISTOVERWRITE +{ + Text [ en-US ] = "The file already exists. Overwrite?" ; +}; + +String STR_SVT_NEW_FOLDER +{ + Text [ en-US ] = "Folder" ; +}; + +String STR_SVT_NOREMOVABLEDEVICE +{ + Text [ en-US ] = "No removable storage device detected.\nMake sure it is plugged in properly and try again." ; +}; + +String STR_SVT_ALLFORMATS +{ + Text [ en-US ] = "All Formats" ; +}; + +//******************************************************************** EOF + diff --git a/fpicker/source/office/iodlgimp.cxx b/fpicker/source/office/iodlgimp.cxx new file mode 100644 index 000000000000..dfaac9bc7b01 --- /dev/null +++ b/fpicker/source/office/iodlgimp.cxx @@ -0,0 +1,505 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +// includes ******************************************************************* + +#include "iodlgimp.hxx" +#include "svtools/headbar.hxx" +#include <tools/debug.hxx> +#include <tools/wldcrd.hxx> +#include <tools/urlobj.hxx> +#include <vcl/menu.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/lstbox.hxx> +#include <vcl/svapp.hxx> +// #97148# --------------- +#include "svl/ctypeitm.hxx" +#include "svl/eitem.hxx" +#include "unotools/viewoptions.hxx" +#include "svtools/fileview.hxx" +#include "svtools/inettbc.hxx" +#include "iodlg.hxx" +#include "iodlg.hrc" +#include "svtools/imagemgr.hxx" +#include <unotools/localfilehelper.hxx> +#include "unotools/useroptions.hxx" +#include "rtl/instance.hxx" +#include <svl/svl.hrc> + +#define _SVSTDARR_STRINGSSORTDTOR +#define _SVSTDARR_STRINGSDTOR +#define _SVSTDARR_USHORTS +#include "svl/svstdarr.hxx" + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::utl; + +// some stuff for easier changes for SvtViewOptions +static const sal_Char* pViewOptDataName = "dialog data"; +#define VIEWOPT_DATANAME ::rtl::OUString::createFromAscii( pViewOptDataName ) + +static inline void SetViewOptUserItem( SvtViewOptions& rOpt, const String& rData ) +{ + rOpt.SetUserItem( VIEWOPT_DATANAME, makeAny( ::rtl::OUString( rData ) ) ); +} + +static inline String GetViewOptUserItem( const SvtViewOptions& rOpt ) +{ + Any aAny( rOpt.GetUserItem( VIEWOPT_DATANAME ) ); + ::rtl::OUString aUserData; + aAny >>= aUserData; + + return String( aUserData ); +} + + +// defines f"ur den Style der BrowseBox + +#define STYLE_MULTI_SELECTION \ + CNTVIEWSTYLE_NODE_BUTTONS | \ + CNTVIEWSTYLE_NODE_BUTTONS_AT_ROOT | \ + CNTVIEWSTYLE_SHOW_MESSAGES | \ + CNTVIEWSTYLE_SHOW_FOLDERS | \ + CNTVIEWSTYLE_NO_SMARTHIGHLIGHT | \ + CNTVIEWSTYLE_HIDE_OPENMENU | \ + CNTVIEWSTYLE_DEFAULT_APPEARANCE | \ + CNTVIEWSTYLE_SORT_BY_FOLDER + +#define STYLE_SINGLE_SELECTION \ + STYLE_MULTI_SELECTION | CNTVIEWSTYLE_SINGLE_SELECTION + +#define BOOL_NOT_INITIALIZE ((sal_Bool)2) + +//***************************************************************************** +// ResMgrHolder / SvtSimpleResId +//***************************************************************************** +namespace +{ + struct ResMgrHolder + { + ResMgr * operator ()() + { + return ResMgr::CreateResMgr (CREATEVERSIONRESMGR_NAME(svs)); + } + static ResMgr * getOrCreate() + { + return rtl_Instance< + ResMgr, ResMgrHolder, + osl::MutexGuard, osl::GetGlobalMutex >::create ( + ResMgrHolder(), osl::GetGlobalMutex()); + } + }; + + struct SvtSimpleResId : public ResId + { + SvtSimpleResId (USHORT nId) : ResId (nId, *ResMgrHolder::getOrCreate()) {} + }; +} + +//***************************************************************************** +// SvtFileDialogFilter_Impl +//***************************************************************************** + +DBG_NAME( SvtFileDialogFilter_Impl ) +SvtFileDialogFilter_Impl::SvtFileDialogFilter_Impl( const String& rName, const String& rType ) + :m_aName( rName ) + ,m_aType( rType ) +{ + DBG_CTOR( SvtFileDialogFilter_Impl, NULL ); + + m_aType.ToLowerAscii(); +} + +//***************************************************************************** + +SvtFileDialogFilter_Impl::~SvtFileDialogFilter_Impl() +{ + DBG_DTOR( SvtFileDialogFilter_Impl, NULL ); +} + +//***************************************************************************** +// SvtFileDialogFilterList_Impl +//***************************************************************************** + +SV_IMPL_PTRARR( SvtFileDialogFilterList_Impl, SvtFileDialogFilter_Impl* ); + +//============================================================================= +//= SvtFileDialogURLSelector +//============================================================================= + +//----------------------------------------------------------------------------- +SvtFileDialogURLSelector::SvtFileDialogURLSelector( SvtFileDialog* _pParent, const ResId& _rResId, sal_uInt16 _nButtonId ) + :MenuButton ( _pParent, _rResId ) + ,m_pParent ( _pParent ) + ,m_pMenu ( new PopupMenu ) +{ + SetStyle( GetStyle() | WB_NOPOINTERFOCUS | WB_RECTSTYLE | WB_SMALLSTYLE ); + SetModeImage( m_pParent->GetButtonImage( _nButtonId ) ); + SetMenuMode( MENUBUTTON_MENUMODE_TIMED ); + SetDropDown( PUSHBUTTON_DROPDOWN_TOOLBOX ); +} + +//----------------------------------------------------------------------------- +SvtFileDialogURLSelector::~SvtFileDialogURLSelector() +{ + delete m_pMenu; +} + +//----------------------------------------------------------------------------- +void SvtFileDialogURLSelector::OpenURL( const String& rURL ) +{ + INetURLObject aObj( rURL ); + DBG_ASSERT( aObj.GetProtocol() != INET_PROT_NOT_VALID, "SvtFileDialogURLSelector::OpenURL: Invalid URL!" ); + m_pParent->OpenURL_Impl( aObj.GetMainURL( INetURLObject::NO_DECODE ) ); +} + +//----------------------------------------------------------------------------- +void SvtFileDialogURLSelector::Activate() +{ + m_pMenu->Clear(); + + FillURLMenu( m_pMenu ); + + SetPopupMenu( m_pMenu ); +} + +//============================================================================= +//= SvtUpButton_Impl +//============================================================================= + +//----------------------------------------------------------------------------- +SvtUpButton_Impl::SvtUpButton_Impl( SvtFileDialog* pParent, const ResId& rResId ) + :SvtFileDialogURLSelector( pParent, rResId, IMG_FILEDLG_BTN_UP ) + ,_pURLs ( NULL ) +{ +} + +//----------------------------------------------------------------------------- +SvtUpButton_Impl::~SvtUpButton_Impl() +{ + delete _pURLs; +} + +//----------------------------------------------------------------------------- +void SvtUpButton_Impl::FillURLMenu( PopupMenu* _pMenu ) +{ + SvtFileView* pBox = GetDialogParent()->GetView(); + + sal_uInt16 nItemId = 1; + + delete _pURLs; + _pURLs = new SvStringsDtor; + + // "Ubergeordnete Ebenen bestimmen. + INetURLObject aObject( pBox->GetViewURL() ); + sal_Int32 nCount = aObject.getSegmentCount(); + + ::svtools::VolumeInfo aVolInfo( sal_True /* volume */, sal_False /* remote */, + sal_False /* removable */, sal_False /* floppy */, + sal_False /* compact disk */ ); + Image aVolumeImage( SvFileInformationManager::GetFolderImage( aVolInfo ) ); + + while ( nCount >= 1 ) + { + aObject.removeSegment(); + String* pParentURL = new String( aObject.GetMainURL( INetURLObject::NO_DECODE ) ); + + if ( GetDialogParent()->isUrlAllowed( *pParentURL ) ) + { + String aTitle; + // 97148# -------------------------------- + if ( !GetDialogParent()->ContentGetTitle( *pParentURL, aTitle ) || aTitle.Len() == 0 ) + aTitle = aObject.getName(); + + Image aImage = ( nCount > 1 ) // if nCount == 1 means workplace, which detects the wrong image + ? SvFileInformationManager::GetImage( aObject ) : aVolumeImage; + + _pMenu->InsertItem( nItemId++, aTitle, aImage ); + _pURLs->Insert( pParentURL, _pURLs->Count() ); + + if ( nCount == 1 ) + { + // adjust the title of the top level entry (the workspace) + _pMenu->SetItemText( --nItemId, SvtSimpleResId( STR_SVT_MIMETYPE_CNT_FSYSBOX ) ); + } + } + + --nCount; + } +} + +//----------------------------------------------------------------------------- +void SvtUpButton_Impl::Select() +{ + sal_uInt16 nId = GetCurItemId(); + + if ( nId ) + { + --nId; + DBG_ASSERT( nId <= _pURLs->Count(), "SvtUpButton_Impl:falscher Index" ); + + String aURL = *(_pURLs->GetObject( nId )); + GetDialogParent()->OpenURL_Impl( aURL ); + } +} + +//----------------------------------------------------------------------------- +void SvtUpButton_Impl::Click() +{ + GetDialogParent()->PrevLevel_Impl(); +} + +//============================================================================= +//= SvtTravelButton_Impl +//============================================================================= + +//----------------------------------------------------------------------------- +SvtTravelButton_Impl::SvtTravelButton_Impl( SvtFileDialog* pParent, const ResId& rResId ) + :SvtFileDialogURLSelector ( pParent, rResId, IMG_FILEDLG_BTN_STD ) +{ + SetDropDown( 0 ); // by default, don't drop down, as we don't have favourites +} + +//----------------------------------------------------------------------------- +void SvtTravelButton_Impl::SetFavouriteLocations( const ::std::vector< String >& _rLocations ) +{ + m_aFavourites = _rLocations; + // enable the drop down if and only if we have favourites + SetDropDown( m_aFavourites.empty() ? 0 : PUSHBUTTON_DROPDOWN_TOOLBOX ); +} + +//----------------------------------------------------------------------------- +SvtTravelButton_Impl::~SvtTravelButton_Impl() +{ +} + +//----------------------------------------------------------------------------- +void SvtTravelButton_Impl::FillURLMenu( PopupMenu* _pMenu ) +{ + if ( m_aFavourites.empty() ) + // though we claimed that we do not want to have a drop down button + // in this case, VCL nevertheless behaves as if we had one .... :( + return; + + _pMenu->Clear(); + + USHORT nItemId = 1; + String sDisplayName; + + ::std::vector< String >::const_iterator aLoop; + for ( aLoop = m_aFavourites.begin(); aLoop != m_aFavourites.end(); ++aLoop, ++nItemId ) + { + if ( GetDialogParent()->isUrlAllowed( *aLoop ) ) + { + Image aImage = SvFileInformationManager::GetImage( INetURLObject(*aLoop) ); + if ( LocalFileHelper::ConvertURLToSystemPath(*aLoop, sDisplayName) ) + _pMenu->InsertItem( nItemId, sDisplayName, aImage ); + else + _pMenu->InsertItem( nItemId, *aLoop, aImage ); + } + } +} + +//----------------------------------------------------------------------------- +void SvtTravelButton_Impl::Select() +{ + sal_uInt16 nId = GetCurItemId(); + if ( nId ) + { + --nId; + DBG_ASSERT( nId < m_aFavourites.size(), "SvtTravelButton_Impl::Select: invalid index!" ); + if ( nId < m_aFavourites.size() ) + OpenURL( m_aFavourites[ nId ] ); + } +} + +//----------------------------------------------------------------------------- +void SvtTravelButton_Impl::Click() +{ + OpenURL( GetDialogParent()->GetStandardDir() ); +} + +//***************************************************************************** +// SvtExpFileDlg_Impl +//***************************************************************************** + +SvtExpFileDlg_Impl::SvtExpFileDlg_Impl( WinBits ) : + + _pLbFilter ( NULL ), + _pCurFilter ( NULL ), + _pFilter ( new SvtFileDialogFilterList_Impl() ), + _pUserFilter ( NULL ), + _pFtFileName ( NULL ), + _pEdFileName ( NULL ), + _pFtFileVersion ( NULL ), + _pLbFileVersion ( NULL ), + _pFtTemplates ( NULL ), + _pLbTemplates ( NULL ), + _pFtImageTemplates ( NULL ), + _pLbImageTemplates ( NULL ), + _pFtFileType ( NULL ), + _pBtnFileOpen ( NULL ), + _pBtnCancel ( NULL ), + _pBtnHelp ( NULL ), + _pBtnUp ( NULL ), + _pBtnNewFolder ( NULL ), + _pBtnStandard ( NULL ), + _pCbPassword ( NULL ), + _pFtCurrentPath ( NULL ), + _pCbAutoExtension ( NULL ), + _pCbOptions ( NULL ), + _nState ( FILEDLG_STATE_REMOTE ), + _nStyle ( 0 ), + _bDoubleClick ( sal_False ), + m_bNeedDelayedFilterExecute ( sal_False ), + _pDefaultFilter ( NULL ), + _bMultiSelection ( sal_False ), + _nFixDeltaHeight ( 0 ), + _bFolderHasOpened ( sal_False ) +{ +} + +//***************************************************************************** + +SvtExpFileDlg_Impl::~SvtExpFileDlg_Impl() +{ + delete _pFtCurrentPath; + delete _pCbPassword; + delete _pCbAutoExtension; + delete _pCbOptions; + delete _pBtnStandard; + delete _pBtnNewFolder; + delete _pBtnUp; + delete _pBtnHelp; + delete _pBtnCancel; + delete _pBtnFileOpen; + delete _pLbFilter; + delete _pFtFileType; + delete _pLbFileVersion; + delete _pFtFileVersion; + delete _pFtTemplates; + delete _pLbTemplates; + delete _pFtImageTemplates; + delete _pLbImageTemplates; + delete _pEdFileName; + delete _pFtFileName; + delete _pUserFilter; + delete _pFilter; +} + +//***************************************************************************** + +void SvtExpFileDlg_Impl::SetStandardDir( const String& _rDir ) +{ + _aStdDir = _rDir; + if ( 0 == _aStdDir.Len() ) + _aStdDir.AssignAscii( "file:///" ); +} + +//***************************************************************************** +#if OSL_DEBUG_LEVEL > 0 +//----------------------------------------------------------------------------- +namespace { + String lcl_DecoratedFilter( const String& _rOriginalFilter ) + { + String aDecoratedFilter = '<'; + aDecoratedFilter += _rOriginalFilter; + aDecoratedFilter += '>'; + return aDecoratedFilter; + } +} +#endif +//----------------------------------------------------------------------------- + +void SvtExpFileDlg_Impl::ClearFilterList( ) +{ + _pLbFilter->Clear(); +} + +//----------------------------------------------------------------------------- +void SvtExpFileDlg_Impl::SetCurFilter( SvtFileDialogFilter_Impl* pFilter, const String& rDisplayName ) +{ + DBG_ASSERT( pFilter, "SvtExpFileDlg_Impl::SetCurFilter: invalid filter!" ); + DBG_ASSERT( ( rDisplayName == pFilter->GetName() ) + || ( rDisplayName == lcl_DecoratedFilter( pFilter->GetName() ) ), + "SvtExpFileDlg_Impl::SetCurFilter: arguments are inconsistent!" ); + + _pCurFilter = pFilter; + m_sCurrentFilterDisplayName = rDisplayName; +} + +//----------------------------------------------------------------------------- +void SvtExpFileDlg_Impl::InsertFilterListEntry( const SvtFileDialogFilter_Impl* _pFilterDesc ) +{ + String sName = _pFilterDesc->GetName(); + if ( _pFilterDesc->isGroupSeparator() ) + sName = String::CreateFromAscii( "------------------------------------------" ); + else + sName = _pFilterDesc->GetName(); + + // insert an set user data + USHORT nPos = _pLbFilter->InsertEntry( sName ); + _pLbFilter->SetEntryData( nPos, const_cast< void* >( static_cast< const void* >( _pFilterDesc ) ) ); +} + +//----------------------------------------------------------------------------- + +void SvtExpFileDlg_Impl::InitFilterList( ) +{ + // clear the current list + ClearFilterList( ); + + // reinit it + USHORT nPos = _pFilter->Count(); + + // search for the first entry which is no group separator + while ( nPos-- && _pFilter->GetObject( nPos ) && _pFilter->GetObject( nPos )->isGroupSeparator() ) + ; + + // add all following entries + while ( (sal_Int16)nPos >= 0 ) + InsertFilterListEntry( _pFilter->GetObject( nPos-- ) ); +} + +//----------------------------------------------------------------------------- + +void SvtExpFileDlg_Impl::CreateFilterListControl( Window* _pParent, const ResId& _rId ) +{ + DBG_ASSERT( !_pLbFilter, "SvtExpFileDlg_Impl::CreateFilterListControl: already created the control!" ); + if ( !_pLbFilter ) + { + _pLbFilter = new ListBox( _pParent, _rId ); + _pLbFilter->SetDropDownLineCount( 10 ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/office/iodlgimp.hxx b/fpicker/source/office/iodlgimp.hxx new file mode 100644 index 000000000000..9b1be54d4c50 --- /dev/null +++ b/fpicker/source/office/iodlgimp.hxx @@ -0,0 +1,341 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _IODLGIMP_HXX +#define _IODLGIMP_HXX + +#include <tools/string.hxx> +#include <vcl/fixed.hxx> +#include <vcl/lstbox.hxx> +#include <vcl/menubtn.hxx> +#include <vcl/timer.hxx> +#include <vcl/group.hxx> + +#include "svl/svarray.hxx" + +#include <vector> + +//***************************************************************************** + +class Accelerator; +class CheckBox; +class SvtFileDialog; +class SvStringsDtor; +class SvUShorts; + +//***************************************************************************** + +#define FILEDIALOG_DEF_EXTSEP ';' +#define FILEDIALOG_DEF_WILDCARD '*' +#define FILEDIALOG_DEF_IMAGEBORDER 10 +#define FILEDIALOG_DEF_TIMEOUT 250 + +//***************************************************************************** +// SvtFileDialogFilter_Impl +//***************************************************************************** + +/* [Beschreibung] + + Instanzen dieser Klasse repr"asentieren einen Filter +*/ + +class SvtFileDialogFilter_Impl +{ +private: + String m_aName; // name of the entry + String m_aType; // filter wildcard - if empty, the entry marks a group + +public: + SvtFileDialogFilter_Impl( const String& rName, const String& rType ); + ~SvtFileDialogFilter_Impl(); + + const String& GetName() const { return m_aName; } + const String& GetType() const { return m_aType; } + const String GetExtension() const { return m_aType.Copy( 2 ); } + + sal_Bool isGroupSeparator() const { return 0 == m_aType.Len(); } +}; + +//***************************************************************************** +// SvtFileDialogFilterList_Impl +//***************************************************************************** + +SV_DECL_PTRARR_DEL( SvtFileDialogFilterList_Impl, SvtFileDialogFilter_Impl*, 3, 3 ) + +//***************************************************************************** +// SvtFileDlgMode +//***************************************************************************** + +enum SvtFileDlgMode +{ + FILEDLG_MODE_OPEN = 0, + FILEDLG_MODE_SAVE = 1 +}; + +//***************************************************************************** +// SvtFileDlgType +//***************************************************************************** + +enum SvtFileDlgType +{ + FILEDLG_TYPE_FILEDLG = 0, + FILEDLG_TYPE_PATHDLG +}; + +//***************************************************************************** +// SvtFileDialogURLSelector +//***************************************************************************** +class SvtFileDialogURLSelector : public MenuButton +{ +private: + SvtFileDialog* m_pParent; + PopupMenu* m_pMenu; + +protected: + inline SvtFileDialog* GetDialogParent() { return m_pParent; } + +protected: + void OpenURL( const String& rURL ); + + virtual void FillURLMenu( PopupMenu* _pMenu ) = 0; + +protected: + SvtFileDialogURLSelector( SvtFileDialog* _pParent, const ResId& _rResId, sal_uInt16 _nButtonId ); + ~SvtFileDialogURLSelector(); + + virtual void Activate(); +}; + +//***************************************************************************** +// SvtUpButton_Impl +//***************************************************************************** + +class SvtUpButton_Impl : public SvtFileDialogURLSelector +{ +private: + SvStringsDtor* _pURLs; + +public: + SvtUpButton_Impl( SvtFileDialog* pParent, const ResId& rResId ); + ~SvtUpButton_Impl(); + +protected: + virtual void FillURLMenu( PopupMenu* _pMenu ); + virtual void Select(); + virtual void Click(); +}; + +//***************************************************************************** +// SvtTravelButton_Impl +//***************************************************************************** + +class SvtTravelButton_Impl : public SvtFileDialogURLSelector +{ +private: + ::std::vector< String > m_aFavourites; + +public: + SvtTravelButton_Impl( SvtFileDialog* pParent, const ResId& rResId ); + ~SvtTravelButton_Impl(); + + void SetFavouriteLocations( const ::std::vector< String >& _rLocations ); + +protected: + virtual void FillURLMenu( PopupMenu* _pMenu ); + virtual void Select(); + virtual void Click(); +}; + +//***************************************************************************** +// SvtFileDlgState +//***************************************************************************** + +typedef sal_uInt8 SvtFileDlgState; + +#define FILEDLG_STATE_NONE ((SvtFileDlgState)0x00) +#define FILEDLG_STATE_REMOTE ((SvtFileDlgState)0x01) + +//***************************************************************************** +// SvtExpFileDlg_Impl +//***************************************************************************** +class SvtURLBox; +class SvtExpFileDlg_Impl +{ +private: + DECL_STATIC_LINK( SvtExpFileDlg_Impl, UnClickHdl, Button* ); + +private: + ListBox* _pLbFilter; + + const SvtFileDialogFilter_Impl* _pCurFilter; + String m_sCurrentFilterDisplayName; // may differ from _pCurFilter->GetName in case it is a cached entry + + ::com::sun::star::uno::Sequence< ::rtl::OUString > _aBlackList; + +public: + SvtFileDialogFilterList_Impl* _pFilter; + SvtFileDialogFilter_Impl* _pUserFilter; + + FixedText* _pFtFileName; + SvtURLBox* _pEdFileName; + + FixedText* _pFtFileVersion; + ListBox* _pLbFileVersion; + + FixedText* _pFtTemplates; + ListBox* _pLbTemplates; + + FixedText* _pFtImageTemplates; + ListBox* _pLbImageTemplates; + + FixedText* _pFtFileType; + PushButton* _pBtnFileOpen; + PushButton* _pBtnCancel; + HelpButton* _pBtnHelp; + SvtUpButton_Impl* _pBtnUp; + ImageButton* _pBtnNewFolder; + SvtTravelButton_Impl* _pBtnStandard; + CheckBox* _pCbPassword; + FixedText* _pFtCurrentPath; + CheckBox* _pCbAutoExtension; + CheckBox* _pCbOptions; + + SvtFileDlgMode _eMode; + SvtFileDlgType _eDlgType; + SvtFileDlgState _nState; + WinBits _nStyle; + + String _aStdDir; + + // beim traveln der Filterbox erst Zeitversetzt filtern + Timer _aFilterTimer; + + // Zeigt der OpenHdl_Imp(), ob das Open durch einen Doppelclick ausgel"ost wurde + sal_Bool _bDoubleClick; + sal_Bool m_bNeedDelayedFilterExecute; + + // Liste mit den 5 zuletzt genutzten Filtern + // Defaultfilter fuer <Alle> oder <Alle ...> + const SvtFileDialogFilter_Impl* _pDefaultFilter; + + // Multiselektion? + sal_Bool _bMultiSelection; + + // Fixgr"ossen f"ur Resize merken + long _nFixDeltaHeight; + Size _a6Size; + Size _aDlgSize; + String _aIniKey; + + sal_Bool _bFolderHasOpened; + + SvtExpFileDlg_Impl( WinBits nBits ); + ~SvtExpFileDlg_Impl(); + + + inline void SetBlackList( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList ) { _aBlackList = rBlackList; } + inline const ::com::sun::star::uno::Sequence< ::rtl::OUString >& GetBlackList() const { return _aBlackList; } + void SetStandardDir( const String& _rDir ); + inline const String& GetStandardDir() const { return _aStdDir; } + inline void DisableFilterBoxAutoWidth() { _pLbFilter->EnableDDAutoWidth( FALSE ); } + + // ------------------------------------------ + // access to the filter listbox only as Control* - we want to maintain the entries/userdata ourself + Control* GetFilterListControl() { return _pLbFilter; } + const Control* GetFilterListControl() const { return _pLbFilter; } + void CreateFilterListControl( Window* _pParent, const ResId& _rId ); + inline void SetFilterListSelectHdl( const Link& _rHandler ); + + // inits the listbox for the filters from the filter list (_pFilter) + void ClearFilterList( ); + void InitFilterList( ); + inline sal_Bool HasFilterListEntry( const String& _rFilterName ); + inline void SelectFilterListEntry( const String& _rFilterName ); + inline void SetNoFilterListSelection( ); + void InsertFilterListEntry( const SvtFileDialogFilter_Impl* _pFilterDesc ); + // _pFilterDesc must already have been added to _pFilter + inline SvtFileDialogFilter_Impl* GetSelectedFilterEntry( String& /* [out] */ _rDisplayName ) const; + inline sal_Bool IsFilterListTravelSelect() const; + + // ------------------------------------------ + // access to the current filter via methods only - need to care for consistency between _pCurFilter and m_sCurrentFilterDisplayName + inline const SvtFileDialogFilter_Impl* GetCurFilter( ) const; + inline const String& GetCurFilterDisplayName() const; + void SetCurFilter( SvtFileDialogFilter_Impl* _pFilter, const String& _rDisplayName ); + inline void SetCurFilter( SvtFileDialogFilter_Impl* _pFilter ); +}; + +inline void SvtExpFileDlg_Impl::SetFilterListSelectHdl( const Link& _rHandler ) +{ + _pLbFilter->SetSelectHdl( _rHandler ); +} + +inline sal_Bool SvtExpFileDlg_Impl::HasFilterListEntry( const String& _rFilterName ) +{ + return ( LISTBOX_ENTRY_NOTFOUND != _pLbFilter->GetEntryPos( _rFilterName ) ); +} + +inline void SvtExpFileDlg_Impl::SelectFilterListEntry( const String& _rFilterName ) +{ + _pLbFilter->SelectEntry( _rFilterName ); +} + +inline void SvtExpFileDlg_Impl::SetNoFilterListSelection( ) +{ + _pLbFilter->SetNoSelection( ); +} + +inline SvtFileDialogFilter_Impl* SvtExpFileDlg_Impl::GetSelectedFilterEntry( String& _rDisplayName ) const +{ + _rDisplayName = _pLbFilter->GetSelectEntry(); + return static_cast< SvtFileDialogFilter_Impl* >( _pLbFilter->GetEntryData ( _pLbFilter->GetSelectEntryPos() ) ); +} + +inline sal_Bool SvtExpFileDlg_Impl::IsFilterListTravelSelect() const +{ + return _pLbFilter->IsTravelSelect(); +} + +inline const SvtFileDialogFilter_Impl* SvtExpFileDlg_Impl::GetCurFilter( ) const +{ + return _pCurFilter; +} + +inline const String& SvtExpFileDlg_Impl::GetCurFilterDisplayName() const +{ + return m_sCurrentFilterDisplayName; +} + +inline void SvtExpFileDlg_Impl::SetCurFilter( SvtFileDialogFilter_Impl* pFilter ) +{ + SetCurFilter( pFilter, pFilter->GetName() ); +} + +#endif // #ifndef _IODLGIMP_HXX + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/office/makefile.mk b/fpicker/source/office/makefile.mk new file mode 100644 index 000000000000..adc3c30f9a3d --- /dev/null +++ b/fpicker/source/office/makefile.mk @@ -0,0 +1,88 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=fpicker +TARGET=fps_office +LIBTARGET=NO +ENABLE_EXCEPTIONS=TRUE +VISIBILITY_HIDDEN=TRUE +GEN_HID=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +DLLPRE= + +# --- Files -------------------------------------------------------- + +SLOFILES=\ + $(SLO)$/asyncfilepicker.obj \ + $(SLO)$/commonpicker.obj \ + $(SLO)$/OfficeControlAccess.obj \ + $(SLO)$/OfficeFilePicker.obj \ + $(SLO)$/OfficeFolderPicker.obj \ + $(SLO)$/fpinteraction.obj \ + $(SLO)$/fpsmartcontent.obj \ + $(SLO)$/fps_office.obj \ + $(SLO)$/iodlg.obj \ + $(SLO)$/iodlgimp.obj + +SHL1TARGET= $(TARGET).uno +SHL1IMPLIB= i$(TARGET) +SHL1OBJS= $(SLOFILES) +SHL1STDLIBS=\ + $(SVTOOLLIB) \ + $(TKLIB) \ + $(VCLLIB) \ + $(SVLLIB) \ + $(UNOTOOLSLIB) \ + $(TOOLSLIB) \ + $(UCBHELPERLIB) \ + $(COMPHELPERLIB) \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) + +SHL1VERSIONMAP=$(SOLARENV)/src/component.map +SHL1DEF= $(MISC)$/$(SHL1TARGET).def +DEF1NAME= $(SHL1TARGET) + +SRS1NAME= $(TARGET) +SRC1FILES= \ + OfficeFilePicker.src \ + iodlg.src + +RESLIB1NAME=$(TARGET) +RESLIB1IMAGES=$(PRJ)$/res +RESLIB1SRSFILES=\ + $(SRS)$/fps_office.srs + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/fpicker/source/office/pickercallbacks.hxx b/fpicker/source/office/pickercallbacks.hxx new file mode 100644 index 000000000000..2140fe5c716d --- /dev/null +++ b/fpicker/source/office/pickercallbacks.hxx @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SVTOOLS_PICKER_CALLBACKS_HXX +#define SVTOOLS_PICKER_CALLBACKS_HXX + +#include <tools/string.hxx> +#include <sal/types.h> + +class Control; + +//......................................................................... +namespace svt +{ +//......................................................................... + + // -------------------------------------------------------------------- + class IFilePickerController + { + public: + virtual Control* getControl( sal_Int16 _nControlId, sal_Bool _bLabelControl = sal_False ) const = 0; + virtual void enableControl( sal_Int16 _nControlId, sal_Bool _bEnable ) = 0; + virtual String getCurFilter( ) const = 0; + }; + + // -------------------------------------------------------------------- + class IFilePickerListener + { + public: + virtual void notify( sal_Int16 _nEventId, sal_Int16 _nControlId ) = 0; + }; + +//......................................................................... +} // namespace svt +//......................................................................... + +#endif // SVTOOLS_PICKER_CALLBACKS_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/gnome/FPServiceInfo.hxx b/fpicker/source/unx/gnome/FPServiceInfo.hxx new file mode 100644 index 000000000000..c0352af2b25d --- /dev/null +++ b/fpicker/source/unx/gnome/FPServiceInfo.hxx @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FPSERVICEINFO_HXX_ +#define _FPSERVICEINFO_HXX_ + +//------------------------------------------------------------------------ +// defines +//------------------------------------------------------------------------ + +// the service names +#define FILE_PICKER_SERVICE_NAME "com.sun.star.ui.dialogs.GtkFilePicker" +#define FOLDER_PICKER_SERVICE_NAME "com.sun.star.ui.dialogs.GtkFolderPicker" + +// the implementation names +#define FILE_PICKER_IMPL_NAME "com.sun.star.ui.dialogs.SalGtkFilePicker" +#define FOLDER_PICKER_IMPL_NAME "com.sun.star.ui.dialogs.SalGtkFolderPicker" + +// the registry key names +// a key under which this service will be registered, +// Format: -> "/ImplName/UNO/SERVICES/ServiceName" +// <Implementation-Name></UNO/SERVICES/><Service-Name> +#define FILE_PICKER_REGKEY_NAME "/com.sun.star.ui.dialogs.SalGtkFilePicker/UNO/SERVICES/com.sun.star.ui.dialogs.GtkFilePicker" +#define FOLDER_PICKER_REGKEY_NAME "/com.sun.star.ui.dialogs.SalGtkFolderPicker/UNO/SERVICES/com.sun.star.ui.dialogs.GtkFolderPicker" + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/gnome/FPentry.cxx b/fpicker/source/unx/gnome/FPentry.cxx new file mode 100644 index 000000000000..4e533a55ad01 --- /dev/null +++ b/fpicker/source/unx/gnome/FPentry.cxx @@ -0,0 +1,189 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +#ifdef AIX +#define _LINUX_SOURCE_COMPAT +#include <sys/timer.h> +#undef _LINUX_SOURCE_COMPAT +#endif + +//---------------------------------------------- +// includes of other projects +//---------------------------------------------- +#include <cppuhelper/factory.hxx> +#include <com/sun/star/container/XSet.hpp> +#include <osl/diagnose.h> +#include "SalGtkFilePicker.hxx" +#include "SalGtkFolderPicker.hxx" +#include <vcl/svapp.hxx> +#include "FPServiceInfo.hxx" + +#include <glib-object.h> + +extern const guint gtk_major_version; +extern const guint gtk_minor_version; + +//----------------------------------------------- +// namespace directives +//----------------------------------------------- + +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::registry; +using namespace ::cppu; +using ::com::sun::star::ui::dialogs::XFilePicker; +using ::com::sun::star::ui::dialogs::XFilePicker2; +using ::com::sun::star::ui::dialogs::XFolderPicker; + +//------------------------------------------------ +// +//------------------------------------------------ + +static Reference< XInterface > SAL_CALL createFileInstance( + const Reference< XMultiServiceFactory >& rServiceManager ) +{ + return Reference< XInterface >( + static_cast< XFilePicker2* >( + new SalGtkFilePicker( rServiceManager ) ) ); +} + +static Reference< XInterface > SAL_CALL createFolderInstance( + const Reference< XMultiServiceFactory >& rServiceManager ) +{ + return Reference< XInterface >( + static_cast< XFolderPicker* >( + new SalGtkFolderPicker( rServiceManager ) ) ); +} + +//------------------------------------------------ +// the three uno functions that will be exported +//------------------------------------------------ + +extern "C" +{ + +//------------------------------------------------ +// component_getImplementationEnvironment +//------------------------------------------------ + +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +//------------------------------------------------ +// +//------------------------------------------------ + +sal_Bool SAL_CALL component_writeInfo( void* /*pServiceManager*/, void* pRegistryKey ) +{ + sal_Bool bRetVal = sal_True; + + if ( pRegistryKey ) + { + try + { + Reference< XRegistryKey > pXNewKey( static_cast< XRegistryKey* >( pRegistryKey ) ); + pXNewKey->createKey( OUString(RTL_CONSTASCII_USTRINGPARAM( FILE_PICKER_REGKEY_NAME ) )); + pXNewKey->createKey( OUString(RTL_CONSTASCII_USTRINGPARAM( FOLDER_PICKER_REGKEY_NAME ) )); + } + catch( InvalidRegistryException& ) + { + OSL_ENSURE( sal_False, "InvalidRegistryException caught" ); + bRetVal = sal_False; + } + } + + return bRetVal; +} + +//------------------------------------------------ +// +//------------------------------------------------ + +void* SAL_CALL component_getFactory( + const sal_Char* pImplName, uno_Interface* pSrvManager, uno_Interface* /*pRegistryKey*/ ) +{ + void* pRet = 0; + + if( pSrvManager ) + { + if ( + /* crude gtkplug check */ !g_type_from_name( "GdkDisplay" ) || + /* old version */ !( gtk_major_version >= 2 && gtk_minor_version >= 4 ) + ) + { + return 0; + } + + Reference< XSingleServiceFactory > xFactory; + + if (0 == rtl_str_compare(pImplName, FILE_PICKER_IMPL_NAME)) + { + Sequence< OUString > aSNS( 1 ); + aSNS.getArray( )[0] = + OUString(RTL_CONSTASCII_USTRINGPARAM(FILE_PICKER_SERVICE_NAME)); + + xFactory = createSingleFactory( + reinterpret_cast< XMultiServiceFactory* > ( pSrvManager ), + OUString::createFromAscii( pImplName ), + createFileInstance, + aSNS ); + } + else if (0 == rtl_str_compare(pImplName, FOLDER_PICKER_IMPL_NAME)) + { + Sequence< OUString > aSNS( 1 ); + aSNS.getArray( )[0] = + OUString(RTL_CONSTASCII_USTRINGPARAM(FOLDER_PICKER_SERVICE_NAME)); + + xFactory = createSingleFactory( + reinterpret_cast< XMultiServiceFactory* > ( pSrvManager ), + OUString::createFromAscii( pImplName ), + createFolderInstance, + aSNS ); + } + + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + } + + return pRet; +} + +} // extern "C" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/gnome/SalGtkFilePicker.cxx b/fpicker/source/unx/gnome/SalGtkFilePicker.cxx new file mode 100644 index 000000000000..4b681ab4f6fa --- /dev/null +++ b/fpicker/source/unx/gnome/SalGtkFilePicker.cxx @@ -0,0 +1,2087 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +#ifdef AIX +#define _LINUX_SOURCE_COMPAT +#include <sys/timer.h> +#undef _LINUX_SOURCE_COMPAT +#endif + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#include <cppuhelper/interfacecontainer.h> +#include <osl/diagnose.h> +#include <osl/process.h> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include <com/sun/star/ui/dialogs/ControlActions.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <FPServiceInfo.hxx> +#include <osl/mutex.hxx> +#include <vcl/svapp.hxx> +#include <SalGtkFilePicker.hxx> + +#include <tools/urlobj.hxx> + +#include <iostream> +#include <algorithm> +#include <set> +#include "resourceprovider.hxx" +#include <tools/rc.hxx> + +//------------------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------------------ + +using namespace ::com::sun::star; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::ui::dialogs::TemplateDescription; +using namespace ::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds; +using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; + +//------------------------------------------------------------------------ +// helper functions +//------------------------------------------------------------------------ + +namespace +{ + // controling event notifications + const bool STARTUP_SUSPENDED = true; + const bool STARTUP_ALIVE = false; + + uno::Sequence<rtl::OUString> SAL_CALL FilePicker_getSupportedServiceNames() + { + uno::Sequence<rtl::OUString> aRet(3); + aRet[0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.FilePicker" )); + aRet[1] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.SystemFilePicker" )); + aRet[2] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.GtkFilePicker" )); + return aRet; + } +} + +//----------------------------------------------------------------------------------------- +// constructor +//----------------------------------------------------------------------------------------- + +static void expandexpanders(GtkContainer *pWidget) +{ + GdkThreadLock aLock; + + GList *pChildren = gtk_container_get_children(pWidget); + for( GList *p = pChildren; p; p = p->next ) + { + if GTK_IS_CONTAINER(GTK_WIDGET(p->data)) + expandexpanders(GTK_CONTAINER(GTK_WIDGET(p->data))); + if GTK_IS_EXPANDER(GTK_WIDGET(p->data)) + gtk_expander_set_expanded(GTK_EXPANDER(GTK_WIDGET(p->data)), TRUE); + } + g_list_free(pChildren); +} + +void SalGtkFilePicker::dialog_mapped_cb(GtkWidget *, SalGtkFilePicker *pobjFP) +{ + pobjFP->InitialMapping(); +} + +void SalGtkFilePicker::InitialMapping() +{ + GdkThreadLock aLock; + + if (!mbPreviewState ) + { + gtk_widget_hide( m_pPreview ); + gtk_file_chooser_set_preview_widget_active( GTK_FILE_CHOOSER( m_pDialog ), false); + } + gtk_widget_set_size_request (m_pPreview, -1, -1); +} + +SalGtkFilePicker::SalGtkFilePicker( const uno::Reference<lang::XMultiServiceFactory>& xServiceMgr ) : + SalGtkPicker(xServiceMgr), + cppu::WeakComponentImplHelper10< + XFilterManager, + XFilterGroupManager, + XFilePickerControlAccess, + XFilePickerNotifier, + XFilePreview, + XFilePicker2, + lang::XInitialization, + util::XCancellable, + lang::XEventListener, + lang::XServiceInfo>( m_rbHelperMtx ), + m_xServiceMgr( xServiceMgr ), + m_pFilterList( NULL ), + m_pVBox ( NULL ), + mnHID_FolderChange( 0 ), + mnHID_SelectionChange( 0 ), + bVersionWidthUnset( false ), + mbPreviewState( sal_False ), + mHID_Preview( 0 ), + m_pPreview( NULL ), + m_pPseudoFilter( NULL ), + m_PreviewImageWidth( 256 ), + m_PreviewImageHeight( 256 ) +{ + int i; + + for( i = 0; i < TOGGLE_LAST; i++ ) + { + m_pToggles[i] = NULL; + mbToggleVisibility[i] = false; + } + + for( i = 0; i < BUTTON_LAST; i++ ) + { + m_pButtons[i] = NULL; + mbButtonVisibility[i] = false; + } + + for( i = 0; i < LIST_LAST; i++ ) + { + m_pHBoxs[i] = NULL; + m_pAligns[i] = NULL; + m_pLists[i] = NULL; + m_pListLabels[i] = NULL; + mbListVisibility[i] = false; + } + + CResourceProvider aResProvider; + OUString aFilePickerTitle = aResProvider.getResString( FILE_PICKER_TITLE_OPEN ); + + GdkThreadLock aLock; + + m_pDialog = gtk_file_chooser_dialog_new( + OUStringToOString( aFilePickerTitle, RTL_TEXTENCODING_UTF8 ).getStr(), + NULL, + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + (char *)NULL ); + + gtk_dialog_set_default_response( GTK_DIALOG (m_pDialog), GTK_RESPONSE_ACCEPT ); + + gtk_file_chooser_set_local_only( GTK_FILE_CHOOSER( m_pDialog ), FALSE ); + gtk_file_chooser_set_select_multiple( GTK_FILE_CHOOSER( m_pDialog ), FALSE ); + + m_pVBox = gtk_vbox_new( FALSE, 0 ); + + // We don't want clickable items to have a huge hit-area + GtkWidget *pHBox = gtk_hbox_new( FALSE, 0 ); + GtkWidget *pThinVBox = gtk_vbox_new( FALSE, 0 ); + + gtk_box_pack_end (GTK_BOX( m_pVBox ), pHBox, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX( pHBox ), pThinVBox, FALSE, FALSE, 0); + gtk_widget_show( pHBox ); + gtk_widget_show( pThinVBox ); + + OUString aLabel; + + for( i = 0; i < TOGGLE_LAST; i++ ) + { + m_pToggles[i] = gtk_check_button_new(); + +#define LABEL_TOGGLE( elem ) \ + case elem : \ + aLabel = aResProvider.getResString( CHECKBOX_##elem ); \ + setLabel( CHECKBOX_##elem, aLabel ); \ + break + + switch( i ) { + + LABEL_TOGGLE( AUTOEXTENSION ); + LABEL_TOGGLE( PASSWORD ); + LABEL_TOGGLE( FILTEROPTIONS ); + LABEL_TOGGLE( READONLY ); + LABEL_TOGGLE( LINK ); + LABEL_TOGGLE( PREVIEW ); + LABEL_TOGGLE( SELECTION ); + default: + OSL_TRACE("Handle unknown control %d\n", i); + break; + } + + gtk_box_pack_end( GTK_BOX( pThinVBox ), m_pToggles[i], FALSE, FALSE, 0 ); + } + + for( i = 0; i < LIST_LAST; i++ ) + { + m_pHBoxs[i] = gtk_hbox_new( FALSE, 0 ); + + m_pAligns[i] = gtk_alignment_new(0, 0, 0, 1); + + m_pLists[i] = gtk_combo_box_new_text(); + + m_pListLabels[i] = gtk_label_new( "" ); + +#define LABEL_LIST( elem ) \ + case elem : \ + aLabel = aResProvider.getResString( LISTBOX_##elem##_LABEL ); \ + setLabel( LISTBOX_##elem##_LABEL, aLabel ); \ + break + + switch( i ) + { + LABEL_LIST( VERSION ); + LABEL_LIST( TEMPLATE ); + LABEL_LIST( IMAGE_TEMPLATE ); + default: + OSL_TRACE("Handle unknown control %d\n", i); + break; + } + + gtk_container_add( GTK_CONTAINER( m_pAligns[i]), m_pLists[i] ); + gtk_box_pack_end( GTK_BOX( m_pHBoxs[i] ), m_pAligns[i], FALSE, FALSE, 0 ); + + gtk_box_pack_end( GTK_BOX( m_pHBoxs[i] ), m_pListLabels[i], FALSE, FALSE, 0 ); + + gtk_box_pack_end( GTK_BOX( m_pVBox ), m_pHBoxs[i], FALSE, FALSE, 0 ); + } + + aLabel = aResProvider.getResString( FILE_PICKER_FILE_TYPE ); + m_pFilterExpander = gtk_expander_new_with_mnemonic( + OUStringToOString( aLabel, RTL_TEXTENCODING_UTF8 ).getStr()); + + gtk_box_pack_end( GTK_BOX( m_pVBox ), m_pFilterExpander, FALSE, TRUE, 0 ); + + GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), + GTK_SHADOW_IN); + gtk_container_add (GTK_CONTAINER (m_pFilterExpander), scrolled_window); + gtk_widget_show (scrolled_window); + + ByteString sExpand(getenv("SAL_EXPANDFPICKER")); + sal_Int32 nExpand = sExpand.ToInt32(); + switch (nExpand) + { + default: + case 0: + break; + case 1: + gtk_expander_set_expanded(GTK_EXPANDER(m_pFilterExpander), TRUE); + break; + case 2: + expandexpanders(GTK_CONTAINER(m_pDialog)); + gtk_expander_set_expanded(GTK_EXPANDER(m_pFilterExpander), TRUE); + break; + } + + m_pFilterStore = gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING); + m_pFilterView = gtk_tree_view_new_with_model (GTK_TREE_MODEL(m_pFilterStore)); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(m_pFilterView), false); + gtk_tree_view_set_rules_hint (GTK_TREE_VIEW(m_pFilterView), true); + + GtkTreeViewColumn *column; + GtkCellRenderer *cell; + + for (i = 0; i < 2; ++i) + { + column = gtk_tree_view_column_new (); + cell = gtk_cell_renderer_text_new (); + gtk_tree_view_column_set_expand (column, TRUE); + gtk_tree_view_column_pack_start (column, cell, FALSE); + gtk_tree_view_column_set_attributes (column, cell, "text", i, (char *)NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW(m_pFilterView), column); + } + + gtk_container_add (GTK_CONTAINER (scrolled_window), m_pFilterView); + gtk_widget_show (m_pFilterView); + + gtk_file_chooser_set_extra_widget( GTK_FILE_CHOOSER( m_pDialog ), m_pVBox ); + + m_pPreview = gtk_image_new(); + gtk_file_chooser_set_preview_widget( GTK_FILE_CHOOSER( m_pDialog ), m_pPreview ); + + g_signal_connect( G_OBJECT( m_pToggles[PREVIEW] ), "toggled", + G_CALLBACK( preview_toggled_cb ), this ); + g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW(m_pFilterView)), "changed", + G_CALLBACK ( type_changed_cb ), this); + g_signal_connect( G_OBJECT( m_pDialog ), "notify::filter", + G_CALLBACK( filter_changed_cb ), this); + g_signal_connect( G_OBJECT( m_pFilterExpander ), "activate", + G_CALLBACK( expander_changed_cb ), this); + g_signal_connect (G_OBJECT( m_pDialog ), "map", + G_CALLBACK (dialog_mapped_cb), this); + + gtk_widget_show( m_pVBox ); + + PangoLayout *layout = gtk_widget_create_pango_layout (m_pFilterView, NULL); + guint ypad; + PangoRectangle row_height; + pango_layout_set_markup (layout, "All Files", -1); + pango_layout_get_pixel_extents (layout, NULL, &row_height); + g_object_get (cell, "ypad", &ypad, (char *)NULL); + guint height = (row_height.height + 2*ypad) * 5; + gtk_widget_set_size_request (m_pFilterView, -1, height); + gtk_widget_set_size_request (m_pPreview, 1, height); + + gtk_file_chooser_set_preview_widget_active( GTK_FILE_CHOOSER( m_pDialog ), true); +} + +//------------------------------------------------------------------------------------ +// XFilePickerNotifier +//------------------------------------------------------------------------------------ + +void SAL_CALL SalGtkFilePicker::addFilePickerListener( const uno::Reference<XFilePickerListener>& xListener ) + throw( uno::RuntimeException ) +{ + m_xListener = xListener; +} + +void SAL_CALL SalGtkFilePicker::removeFilePickerListener( const uno::Reference<XFilePickerListener>& ) + throw( uno::RuntimeException ) +{ + m_xListener.clear(); +} + +// ------------------------------------------------- +// XEventListener +// ------------------------------------------------- + +void SAL_CALL SalGtkFilePicker::disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException ) +{ + uno::Reference<XFilePickerListener> xFilePickerListener( aEvent.Source, ::com::sun::star::uno::UNO_QUERY ); + + if( xFilePickerListener.is() ) + removeFilePickerListener( xFilePickerListener ); +} + +//----------------------------------------------------------------------------------------- +// FilePicker Event functions +//----------------------------------------------------------------------------------------- + +void SAL_CALL SalGtkFilePicker::fileSelectionChanged( FilePickerEvent aEvent ) +{ + OSL_TRACE( "file selection changed"); + if (m_xListener.is()) m_xListener->fileSelectionChanged( aEvent ); +} + +void SAL_CALL SalGtkFilePicker::directoryChanged( FilePickerEvent aEvent ) +{ + OSL_TRACE("directory changed"); + if (m_xListener.is()) m_xListener->directoryChanged( aEvent ); +} + +void SAL_CALL SalGtkFilePicker::controlStateChanged( FilePickerEvent aEvent ) +{ + OSL_TRACE("control state changed"); + if (m_xListener.is()) m_xListener->controlStateChanged( aEvent ); +} + +//----------------------------------------------------------------------------------------- +// If there are more then one listener the return value of the last one wins +//----------------------------------------------------------------------------------------- + +rtl::OUString SAL_CALL SalGtkFilePicker::helpRequested( FilePickerEvent aEvent ) const +{ + rtl::OUString aHelpText; + + ::cppu::OInterfaceContainerHelper* pICHelper = + rBHelper.getContainer( getCppuType( ( uno::Reference<XFilePickerListener> * )0 ) ); + + if( pICHelper ) + { + ::cppu::OInterfaceIteratorHelper iter( *pICHelper ); + + while( iter.hasMoreElements() ) + { + try + { + /* + if there are multiple listeners responding + to this notification the next response + overwrittes the one before if it is not empty + */ + + rtl::OUString aTempString; + + uno::Reference<XFilePickerListener> xFPListener( iter.next(), uno::UNO_QUERY ); + if( xFPListener.is() ) + { + aTempString = xFPListener->helpRequested( aEvent ); + if( aTempString.getLength() ) + aHelpText = aTempString; + } + + } + catch( uno::RuntimeException& ) + { + OSL_ENSURE( false, "RuntimeException during event dispatching" ); + } + } + } + + return aHelpText; +} + +//===================================================================== + +struct FilterEntry +{ +protected: + ::rtl::OUString m_sTitle; + ::rtl::OUString m_sFilter; + + UnoFilterList m_aSubFilters; + +public: + FilterEntry( const ::rtl::OUString& _rTitle, const ::rtl::OUString& _rFilter ) + :m_sTitle( _rTitle ) + ,m_sFilter( _rFilter ) + { + } + + FilterEntry( const ::rtl::OUString& _rTitle, const UnoFilterList& _rSubFilters ); + + ::rtl::OUString getTitle() const { return m_sTitle; } + ::rtl::OUString getFilter() const { return m_sFilter; } + + /// determines if the filter has sub filter (i.e., the filter is a filter group in real) + sal_Bool hasSubFilters( ) const; + + /** retrieves the filters belonging to the entry + @return + the number of sub filters + */ + sal_Int32 getSubFilters( UnoFilterList& _rSubFilterList ); + + // helpers for iterating the sub filters + const UnoFilterEntry* beginSubFilters() const { return m_aSubFilters.getConstArray(); } + const UnoFilterEntry* endSubFilters() const { return m_aSubFilters.getConstArray() + m_aSubFilters.getLength(); } +}; + +//===================================================================== + +//--------------------------------------------------------------------- +FilterEntry::FilterEntry( const ::rtl::OUString& _rTitle, const UnoFilterList& _rSubFilters ) + :m_sTitle( _rTitle ) + ,m_aSubFilters( _rSubFilters ) +{ +} + +//--------------------------------------------------------------------- +sal_Bool FilterEntry::hasSubFilters() const +{ + return( 0 < m_aSubFilters.getLength() ); +} + +//--------------------------------------------------------------------- +sal_Int32 FilterEntry::getSubFilters( UnoFilterList& _rSubFilterList ) +{ + _rSubFilterList = m_aSubFilters; + return m_aSubFilters.getLength(); +} + +static bool +isFilterString( const rtl::OUString &rFilterString, const char *pMatch ) +{ + sal_Int32 nIndex = 0; + rtl::OUString aToken; + bool bIsFilter = true; + + rtl::OUString aMatch(rtl::OUString::createFromAscii(pMatch)); + + do + { + aToken = rFilterString.getToken( 0, ';', nIndex ); + if( !aToken.match( aMatch ) ) + { + bIsFilter = false; + break; + } + } + while( nIndex >= 0 ); + + return bIsFilter; +} + +static rtl::OUString +shrinkFilterName( const rtl::OUString &rFilterName, bool bAllowNoStar = false ) +{ + int i; + int nBracketLen = -1; + int nBracketEnd = -1; + const sal_Unicode *pStr = rFilterName; + OUString aRealName = rFilterName; + + for( i = aRealName.getLength() - 1; i > 0; i-- ) + { + if( pStr[i] == ')' ) + nBracketEnd = i; + else if( pStr[i] == '(' ) + { + nBracketLen = nBracketEnd - i; + if( nBracketEnd <= 0 ) + continue; + if( isFilterString( rFilterName.copy( i + 1, nBracketLen - 1 ), "*." ) ) + aRealName = aRealName.replaceAt( i, nBracketLen + 1, rtl::OUString() ); + else if (bAllowNoStar) + { + if( isFilterString( rFilterName.copy( i + 1, nBracketLen - 1 ), ".") ) + aRealName = aRealName.replaceAt( i, nBracketLen + 1, rtl::OUString() ); + } + } + } + + return aRealName; +} + +static void +dialog_remove_buttons( GtkDialog *pDialog ) +{ + GdkThreadLock aLock; + + g_return_if_fail( GTK_IS_DIALOG( pDialog ) ); + + GList *pChildren = + gtk_container_get_children( GTK_CONTAINER( pDialog->action_area ) ); + + for( GList *p = pChildren; p; p = p->next ) + gtk_widget_destroy( GTK_WIDGET( p->data ) ); + + g_list_free( pChildren ); +} + +//------------------------------------------------------------------------------------ +namespace { + //................................................................................ + struct FilterTitleMatch : public ::std::unary_function< FilterEntry, bool > + { + protected: + const ::rtl::OUString& rTitle; + + public: + FilterTitleMatch( const ::rtl::OUString& _rTitle ) : rTitle( _rTitle ) { } + + //............................................................................ + bool operator () ( const FilterEntry& _rEntry ) + { + sal_Bool bMatch; + if( !_rEntry.hasSubFilters() ) + // a real filter + bMatch = ( _rEntry.getTitle() == rTitle ); + else + // a filter group -> search the sub filters + bMatch = + _rEntry.endSubFilters() != ::std::find_if( + _rEntry.beginSubFilters(), + _rEntry.endSubFilters(), + *this + ); + + return bMatch ? true : false; + } + bool operator () ( const UnoFilterEntry& _rEntry ) + { + OUString aShrunkName = shrinkFilterName( _rEntry.First ); + return aShrunkName == rTitle ? true : false; + } + }; +} + + +//------------------------------------------------------------------------------------ +sal_Bool SalGtkFilePicker::FilterNameExists( const ::rtl::OUString& rTitle ) +{ + sal_Bool bRet = sal_False; + + if( m_pFilterList ) + bRet = + m_pFilterList->end() != ::std::find_if( + m_pFilterList->begin(), + m_pFilterList->end(), + FilterTitleMatch( rTitle ) + ); + + return bRet; +} + +//------------------------------------------------------------------------------------ +sal_Bool SalGtkFilePicker::FilterNameExists( const UnoFilterList& _rGroupedFilters ) +{ + sal_Bool bRet = sal_False; + + if( m_pFilterList ) + { + const UnoFilterEntry* pStart = _rGroupedFilters.getConstArray(); + const UnoFilterEntry* pEnd = pStart + _rGroupedFilters.getLength(); + for( ; pStart != pEnd; ++pStart ) + if( m_pFilterList->end() != ::std::find_if( + m_pFilterList->begin(), + m_pFilterList->end(), + FilterTitleMatch( pStart->First ) ) ) + break; + + bRet = pStart != pEnd; + } + + return bRet; +} + +//------------------------------------------------------------------------------------ +void SalGtkFilePicker::ensureFilterList( const ::rtl::OUString& _rInitialCurrentFilter ) +{ + if( !m_pFilterList ) + { + m_pFilterList = new FilterList; + + // set the first filter to the current filter + if ( !m_aCurrentFilter.getLength() ) + m_aCurrentFilter = _rInitialCurrentFilter; + } +} + + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL SalGtkFilePicker::appendFilter( const rtl::OUString& aTitle, const rtl::OUString& aFilter ) + throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + if( FilterNameExists( aTitle ) ) + throw IllegalArgumentException(); + + // ensure that we have a filter list + ensureFilterList( aTitle ); + + // append the filter + m_pFilterList->insert( m_pFilterList->end(), FilterEntry( aTitle, aFilter ) ); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL SalGtkFilePicker::setCurrentFilter( const rtl::OUString& aTitle ) + throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + OSL_TRACE( "Setting current filter to %s\n", + OUStringToOString( aTitle, RTL_TEXTENCODING_UTF8 ).getStr() ); + + if( aTitle != m_aCurrentFilter ) + { + m_aCurrentFilter = aTitle; + SetCurFilter( m_aCurrentFilter ); + OSL_TRACE( "REALLY Setting current filter to %s\n", + OUStringToOString( aTitle, RTL_TEXTENCODING_UTF8 ).getStr() ); + + } + + // TODO m_pImpl->setCurrentFilter( aTitle ); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SalGtkFilePicker::updateCurrentFilterFromName(const gchar* filtername) +{ + OUString aFilterName(filtername, strlen(filtername), RTL_TEXTENCODING_UTF8); + FilterList::iterator aEnd = m_pFilterList->end(); + for (FilterList::iterator aIter = m_pFilterList->begin(); aIter != aEnd; ++aIter) + { + if (aFilterName == shrinkFilterName( aIter->getTitle())) + { + m_aCurrentFilter = aIter->getTitle(); + break; + } + } +} + +void SalGtkFilePicker::UpdateFilterfromUI() +{ + // Update the filtername from the users selection if they have had a chance to do so. + // If the user explicitly sets a type then use that, if not then take the implicit type + // from the filter of the files glob on which he is currently searching + if (!mnHID_FolderChange || !mnHID_SelectionChange) + return; + + GdkThreadLock aLock; + + GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(m_pFilterView)); + GtkTreeIter iter; + GtkTreeModel *model; + if (gtk_tree_selection_get_selected (selection, &model, &iter)) + { + gchar *title; + gtk_tree_model_get (model, &iter, 2, &title, -1); + updateCurrentFilterFromName(title); + g_free (title); + } + else if( GtkFileFilter *filter = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(m_pDialog))) + { + if (m_pPseudoFilter != filter) + updateCurrentFilterFromName(gtk_file_filter_get_name( filter )); + else + updateCurrentFilterFromName(OUStringToOString( m_aInitialFilter, RTL_TEXTENCODING_UTF8 ).getStr()); + } +} + +rtl::OUString SAL_CALL SalGtkFilePicker::getCurrentFilter() throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + OSL_TRACE( "GetCURRENTfilter\n" ); + + UpdateFilterfromUI(); + + OSL_TRACE( "Returning current filter of %s\n", + OUStringToOString( m_aCurrentFilter, RTL_TEXTENCODING_UTF8 ).getStr() ); + + return m_aCurrentFilter; +} + +//----------------------------------------------------------------------------------------- +// XFilterGroupManager functions +//----------------------------------------------------------------------------------------- + +void SAL_CALL SalGtkFilePicker::appendFilterGroup( const rtl::OUString& /*sGroupTitle*/, const uno::Sequence<beans::StringPair>& aFilters ) + throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + // TODO m_pImpl->appendFilterGroup( sGroupTitle, aFilters ); + // check the names + if( FilterNameExists( aFilters ) ) + // TODO: a more precise exception message + throw IllegalArgumentException(); + + // ensure that we have a filter list + ::rtl::OUString sInitialCurrentFilter; + if( aFilters.getLength() ) + sInitialCurrentFilter = aFilters[0].First; + + ensureFilterList( sInitialCurrentFilter ); + + // append the filter + const StringPair* pSubFilters = aFilters.getConstArray(); + const StringPair* pSubFiltersEnd = pSubFilters + aFilters.getLength(); + for( ; pSubFilters != pSubFiltersEnd; ++pSubFilters ) + m_pFilterList->insert( m_pFilterList->end(), FilterEntry( pSubFilters->First, pSubFilters->Second ) ); + +} + +//----------------------------------------------------------------------------------------- +// XFilePicker functions +//----------------------------------------------------------------------------------------- + +void SAL_CALL SalGtkFilePicker::setMultiSelectionMode( sal_Bool bMode ) throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + GdkThreadLock aLock; + + gtk_file_chooser_set_select_multiple( GTK_FILE_CHOOSER(m_pDialog), bMode ); +} + +void SAL_CALL SalGtkFilePicker::setDefaultName( const rtl::OUString& aName ) + throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + GdkThreadLock aLock; + + OString aStr = OUStringToOString( aName, RTL_TEXTENCODING_UTF8 ); + GtkFileChooserAction eAction = gtk_file_chooser_get_action( GTK_FILE_CHOOSER( m_pDialog ) ); + + // set_current_name launches a Gtk critical error if called for other than save + if( GTK_FILE_CHOOSER_ACTION_SAVE == eAction ) + gtk_file_chooser_set_current_name( GTK_FILE_CHOOSER( m_pDialog ), aStr.getStr() ); +} + +void SAL_CALL SalGtkFilePicker::setDisplayDirectory( const rtl::OUString& rDirectory ) + throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + implsetDisplayDirectory(rDirectory); +} + +rtl::OUString SAL_CALL SalGtkFilePicker::getDisplayDirectory() throw( uno::RuntimeException ) +{ + return implgetDisplayDirectory(); +} + +uno::Sequence<rtl::OUString> SAL_CALL SalGtkFilePicker::getFiles() throw( uno::RuntimeException ) +{ + uno::Sequence< rtl::OUString > aFiles = getSelectedFiles(); + /* + The previous multiselection API design was completely broken + and unimplementable for some hetrogenous pseudo-URIs eg. search:// + Thus crop unconditionally to a single selection. + */ + aFiles.realloc (1); + return aFiles; +} + +uno::Sequence<rtl::OUString> SAL_CALL SalGtkFilePicker::getSelectedFiles() throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + GdkThreadLock aLock; + + GSList* pPathList = gtk_file_chooser_get_uris( GTK_FILE_CHOOSER(m_pDialog) ); + + int nCount = g_slist_length( pPathList ); + int nIndex = 0; + OSL_TRACE( "GETFILES called %d files\n", nCount ); + + // get the current action setting + GtkFileChooserAction eAction = gtk_file_chooser_get_action( + GTK_FILE_CHOOSER( m_pDialog )); + + uno::Sequence< rtl::OUString > aSelectedFiles(nCount); + + // Convert to OOo + for( GSList *pElem = pPathList; pElem; pElem = pElem->next) + { + gchar *pURI = reinterpret_cast<gchar*>(pElem->data); + aSelectedFiles[ nIndex ] = uritounicode(pURI); + + if( GTK_FILE_CHOOSER_ACTION_SAVE == eAction ) + { + OUString sFilterName; + sal_Int32 nTokenIndex = 0; + bool bExtensionTypedIn = false; + + GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(m_pFilterView)); + GtkTreeIter iter; + GtkTreeModel *model; + if (gtk_tree_selection_get_selected (selection, &model, &iter)) + { + gchar *title; + gtk_tree_model_get (model, &iter, 2, &title, -1); + sFilterName = OUString( title, strlen( title), RTL_TEXTENCODING_UTF8 ); + g_free (title); + } + else + { + if( aSelectedFiles[nIndex].indexOf('.') > 0 ) + { + rtl::OUString sExtension; + nTokenIndex = 0; + do + sExtension = aSelectedFiles[nIndex].getToken( 0, '.', nTokenIndex ); + while( nTokenIndex >= 0 ); + + if( sExtension.getLength() >= 3 ) // 3 = typical/minimum extension length + { + static const OUString aStarDot(RTL_CONSTASCII_USTRINGPARAM( "*." )); + + ::rtl::OUString aNewFilter; + ::rtl::OUString aOldFilter = getCurrentFilter(); + sal_Bool bChangeFilter = sal_True; + for ( FilterList::iterator aListIter = m_pFilterList->begin(); + aListIter != m_pFilterList->end(); + ++aListIter + ) + { + if( aListIter->getFilter().equalsIgnoreAsciiCase( aStarDot+sExtension ) ) + { + if( !aNewFilter.getLength() ) + aNewFilter = aListIter->getTitle(); + + if( aOldFilter == aListIter->getTitle() ) + bChangeFilter = sal_False; + + bExtensionTypedIn = true; + } + } + if( bChangeFilter && bExtensionTypedIn ) + setCurrentFilter( aNewFilter ); + } + } + + GtkFileFilter *filter = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(m_pDialog)); + if (m_pPseudoFilter != filter) + { + const gchar* filtername = gtk_file_filter_get_name( filter ); + sFilterName = OUString( filtername, strlen( filtername ), RTL_TEXTENCODING_UTF8 ); + } + else + sFilterName = m_aInitialFilter; + } + + OSL_TRACE( "2: current filter is %s\n", + OUStringToOString( sFilterName, RTL_TEXTENCODING_UTF8 ).getStr() ); + + FilterList::iterator aListIter = ::std::find_if( + m_pFilterList->begin(), m_pFilterList->end(), FilterTitleMatch(sFilterName) ); + + OUString aFilter; + if (aListIter != m_pFilterList->end()) + aFilter = aListIter->getFilter(); + + OSL_TRACE( "turned into %s\n", + OUStringToOString( aFilter, RTL_TEXTENCODING_UTF8 ).getStr() ); + + nTokenIndex = 0; + rtl::OUString sToken; + // rtl::OUString strExt; + do + { + sToken = aFilter.getToken( 0, '.', nTokenIndex ); + + if ( sToken.lastIndexOf( ';' ) != -1 ) + { + sal_Int32 nZero = 0; + OUString aCurrentToken = sToken.getToken( 0, ';', nZero); + + sToken = aCurrentToken; + break; + } + } + while( nTokenIndex >= 0 ); + + if( !bExtensionTypedIn && ( !sToken.equalsAscii( "*" ) ) ) + { + //if the filename does not already have the auto extension, stick it on + OUString sExtension = OUString(RTL_CONSTASCII_USTRINGPARAM( "." )) + sToken; + OUString &rBase = aSelectedFiles[nIndex]; + sal_Int32 nExtensionIdx = rBase.getLength() - sExtension.getLength(); + OSL_TRACE( "idx are %d %d\n", rBase.lastIndexOf( sExtension ), nExtensionIdx ); + + if( rBase.lastIndexOf( sExtension ) != nExtensionIdx ) + rBase += sExtension; + } + + } + + nIndex++; + g_free( pURI ); + } + + g_slist_free( pPathList ); + + return aSelectedFiles; +} + +//----------------------------------------------------------------------------------------- +// XExecutableDialog functions +//----------------------------------------------------------------------------------------- + +void SAL_CALL SalGtkFilePicker::setTitle( const rtl::OUString& rTitle ) throw( uno::RuntimeException ) +{ + implsetTitle(rTitle); +} + +sal_Int16 SAL_CALL SalGtkFilePicker::execute() throw( uno::RuntimeException ) +{ + OSL_TRACE( "1: HERE WE ARE\n"); + OSL_ASSERT( m_pDialog != NULL ); + + GdkThreadLock aLock; + + sal_Int16 retVal = 0; + + SetFilters(); + + mnHID_FolderChange = + g_signal_connect( GTK_FILE_CHOOSER( m_pDialog ), "current-folder-changed", + G_CALLBACK( folder_changed_cb ), ( gpointer )this ); + + mnHID_SelectionChange = + g_signal_connect( GTK_FILE_CHOOSER( m_pDialog ), "selection-changed", + G_CALLBACK( selection_changed_cb ), ( gpointer )this ); + + int btn = GTK_RESPONSE_NO; + + uno::Reference< awt::XExtendedToolkit > xToolkit( + m_xServiceMgr->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.Toolkit")) ), uno::UNO_QUERY); + + RunDialog* pRunDialog = new RunDialog(m_pDialog, xToolkit); + uno::Reference < awt::XTopWindowListener > xLifeCycle(pRunDialog); + while( GTK_RESPONSE_NO == btn ) + { + btn = GTK_RESPONSE_YES; // we dont want to repeat unless user clicks NO for file save. + + gint nStatus = pRunDialog->run(); + switch( nStatus ) + { + case GTK_RESPONSE_ACCEPT: + if( GTK_FILE_CHOOSER_ACTION_SAVE == gtk_file_chooser_get_action( GTK_FILE_CHOOSER( m_pDialog ) ) ) + { + Sequence < OUString > aPathSeq = getFiles(); + if( aPathSeq.getLength() == 1 ) + { + OString sFileName = unicodetouri( aPathSeq[0] ); + if( g_file_test( g_filename_from_uri( sFileName.getStr(), NULL, NULL ), G_FILE_TEST_IS_REGULAR ) ) + { + CResourceProvider aResProvider; + GtkWidget *dlg; + + dlg = gtk_message_dialog_new( NULL, + GTK_DIALOG_MODAL, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_YES_NO, + OUStringToOString( + aResProvider.getResString( FILE_PICKER_OVERWRITE ), + RTL_TEXTENCODING_UTF8 ).getStr() ); + + gtk_window_set_title( GTK_WINDOW( dlg ), + OUStringToOString(aResProvider.getResString(FILE_PICKER_TITLE_SAVE ), + RTL_TEXTENCODING_UTF8 ).getStr() ); + + RunDialog* pAnotherDialog = new RunDialog(dlg, xToolkit); + uno::Reference < awt::XTopWindowListener > xAnotherLifeCycle(pAnotherDialog); + btn = pAnotherDialog->run(); + + gtk_widget_destroy( dlg ); + } + + if( btn == GTK_RESPONSE_YES ) + retVal = ExecutableDialogResults::OK; + } + } + else + retVal = ExecutableDialogResults::OK; + break; + + case GTK_RESPONSE_CANCEL: + retVal = ExecutableDialogResults::CANCEL; + break; + + case 1: //PLAY + { + FilePickerEvent evt; + evt.ElementId = PUSHBUTTON_PLAY; + OSL_TRACE( "filter_changed, isn't it great %x\n", this); + controlStateChanged( evt ); + btn = GTK_RESPONSE_NO; + } + break; + + default: + retVal = 0; + break; + } + } + + if (mnHID_FolderChange) + g_signal_handler_disconnect(GTK_FILE_CHOOSER( m_pDialog ), mnHID_FolderChange); + if (mnHID_SelectionChange) + g_signal_handler_disconnect(GTK_FILE_CHOOSER( m_pDialog ), mnHID_SelectionChange); + + return retVal; +} + +//------------------------------------------------------------------------------------ + +// cf. offapi/com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.idl +GtkWidget *SalGtkFilePicker::getWidget( sal_Int16 nControlId, GType *pType ) +{ + OSL_TRACE("control id is %d", nControlId); + GType tType = GTK_TYPE_TOGGLE_BUTTON; //prevent waring by initializing + GtkWidget *pWidget = 0; + +#define MAP_TOGGLE( elem ) \ + case ExtendedFilePickerElementIds::CHECKBOX_##elem: \ + pWidget = m_pToggles[elem]; tType = GTK_TYPE_TOGGLE_BUTTON; \ + break +#define MAP_BUTTON( elem ) \ + case ExtendedFilePickerElementIds::PUSHBUTTON_##elem: \ + pWidget = m_pButtons[elem]; tType = GTK_TYPE_BUTTON; \ + break +#define MAP_LIST( elem ) \ + case ExtendedFilePickerElementIds::LISTBOX_##elem: \ + pWidget = m_pLists[elem]; tType = GTK_TYPE_COMBO_BOX; \ + break +#define MAP_LIST_LABEL( elem ) \ + case ExtendedFilePickerElementIds::LISTBOX_##elem##_LABEL: \ + pWidget = m_pListLabels[elem]; tType = GTK_TYPE_LABEL; \ + break + + switch( nControlId ) + { + MAP_TOGGLE( AUTOEXTENSION ); + MAP_TOGGLE( PASSWORD ); + MAP_TOGGLE( FILTEROPTIONS ); + MAP_TOGGLE( READONLY ); + MAP_TOGGLE( LINK ); + MAP_TOGGLE( PREVIEW ); + MAP_TOGGLE( SELECTION ); + MAP_BUTTON( PLAY ); + MAP_LIST( VERSION ); + MAP_LIST( TEMPLATE ); + MAP_LIST( IMAGE_TEMPLATE ); + MAP_LIST_LABEL( VERSION ); + MAP_LIST_LABEL( TEMPLATE ); + MAP_LIST_LABEL( IMAGE_TEMPLATE ); + default: + OSL_TRACE("Handle unknown control %d\n", nControlId); + break; + } +#undef MAP + + if( pType ) + *pType = tType; + return pWidget; +} + + + +//------------------------------------------------------------------------------------ +// XFilePickerControlAccess functions +//------------------------------------------------------------------------------------ +namespace +{ + void HackWidthToFirst(GtkComboBox *pWidget) + { + GdkThreadLock aLock; + + GtkRequisition requisition; + gtk_widget_size_request(GTK_WIDGET(pWidget), &requisition); + gtk_widget_set_size_request(GTK_WIDGET(pWidget), requisition.width, -1); + } +} + +void SalGtkFilePicker::HandleSetListValue(GtkComboBox *pWidget, sal_Int16 nControlAction, const uno::Any& rValue) +{ + GdkThreadLock aLock; + + switch (nControlAction) + { + case ControlActions::ADD_ITEM: + { + OUString sItem; + rValue >>= sItem; + gtk_combo_box_append_text(pWidget, rtl::OUStringToOString(sItem, RTL_TEXTENCODING_UTF8).getStr()); + if (!bVersionWidthUnset) + { + HackWidthToFirst(pWidget); + bVersionWidthUnset = true; + } + } + break; + case ControlActions::ADD_ITEMS: + { + Sequence< OUString > aStringList; + rValue >>= aStringList; + sal_Int32 nItemCount = aStringList.getLength(); + for (sal_Int32 i = 0; i < nItemCount; ++i) + { + gtk_combo_box_append_text(pWidget, + rtl::OUStringToOString(aStringList[i], RTL_TEXTENCODING_UTF8).getStr()); + if (!bVersionWidthUnset) + { + HackWidthToFirst(pWidget); + bVersionWidthUnset = true; + } + } + } + break; + case ControlActions::DELETE_ITEM: + { + sal_Int32 nPos=0; + rValue >>= nPos; + gtk_combo_box_remove_text(pWidget, nPos); + } + break; + case ControlActions::DELETE_ITEMS: + { + gtk_combo_box_set_active(pWidget, -1); + gint nItems = 0; + do + { + nItems = + gtk_tree_model_iter_n_children( + gtk_combo_box_get_model(pWidget), NULL); + for (gint nI = 0; nI < nItems; ++nI) + gtk_combo_box_remove_text(pWidget, nI); + } + while (nItems); + } + break; + case ControlActions::SET_SELECT_ITEM: + { + sal_Int32 nPos=0; + rValue >>= nPos; + gtk_combo_box_set_active(pWidget, nPos); + } + break; + default: + OSL_TRACE("undocumented/unimplemented ControlAction for a list"); + break; + } + + //I think its best to make it insensitive unless there is the chance to + //actually select something from the list. + gint nItems = gtk_tree_model_iter_n_children( + gtk_combo_box_get_model(pWidget), NULL); + gtk_widget_set_sensitive(GTK_WIDGET(pWidget), nItems > 1 ? true : false); +} + +uno::Any SalGtkFilePicker::HandleGetListValue(GtkComboBox *pWidget, sal_Int16 nControlAction) const +{ + GdkThreadLock aLock; + + uno::Any aAny; + switch (nControlAction) + { + case ControlActions::GET_ITEMS: + { + Sequence< OUString > aItemList; + + GtkTreeModel *pTree = gtk_combo_box_get_model(pWidget); + GtkTreeIter iter; + if (gtk_tree_model_get_iter_first(pTree, &iter)) + { + sal_Int32 nSize = gtk_tree_model_iter_n_children( + pTree, NULL); + + aItemList.realloc(nSize); + for (sal_Int32 i=0; i < nSize; ++i) + { + gchar *item; + gtk_tree_model_get(gtk_combo_box_get_model(pWidget), + &iter, 0, &item, -1); + aItemList[i] = OUString(item, strlen(item), RTL_TEXTENCODING_UTF8); + g_free(item); + gtk_tree_model_iter_next(pTree, &iter); + } + } + aAny <<= aItemList; + } + break; + case ControlActions::GET_SELECTED_ITEM: + { + GtkTreeIter iter; + if (gtk_combo_box_get_active_iter(pWidget, &iter)) + { + gchar *item; + gtk_tree_model_get(gtk_combo_box_get_model(pWidget), + &iter, 0, &item, -1); + OUString sItem(item, strlen(item), RTL_TEXTENCODING_UTF8); + aAny <<= sItem; + g_free(item); + } + } + break; + case ControlActions::GET_SELECTED_ITEM_INDEX: + { + gint nActive = gtk_combo_box_get_active(pWidget); + aAny <<= static_cast< sal_Int32 >(nActive); + } + break; + default: + OSL_TRACE("undocumented/unimplemented ControlAction for a list"); + break; + } + return aAny; +} + +void SAL_CALL SalGtkFilePicker::setValue( sal_Int16 nControlId, sal_Int16 nControlAction, const uno::Any& rValue ) + throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + OSL_TRACE( "SETTING VALUE %d\n", nControlAction ); + GType tType; + GtkWidget *pWidget; + + GdkThreadLock aLock; + + if( !( pWidget = getWidget( nControlId, &tType ) ) ) + OSL_TRACE("enable unknown control %d\n", nControlId); + else if( tType == GTK_TYPE_TOGGLE_BUTTON ) + { + sal_Bool bChecked = false; + rValue >>= bChecked; + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( pWidget ), bChecked ); + } + else if( tType == GTK_TYPE_COMBO_BOX ) + HandleSetListValue(GTK_COMBO_BOX(pWidget), nControlAction, rValue); + else + { + OSL_TRACE("Can't set value on button / list %d %d\n", + nControlId, nControlAction); + } +} + +uno::Any SAL_CALL SalGtkFilePicker::getValue( sal_Int16 nControlId, sal_Int16 nControlAction ) + throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + uno::Any aRetval; + + GType tType; + GtkWidget *pWidget; + + GdkThreadLock aLock; + + if( !( pWidget = getWidget( nControlId, &tType ) ) ) + OSL_TRACE("enable unknown control %d\n", nControlId); + else if( tType == GTK_TYPE_TOGGLE_BUTTON ) + aRetval <<= (sal_Bool) gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( pWidget ) ); + else if( tType == GTK_TYPE_COMBO_BOX ) + aRetval = HandleGetListValue(GTK_COMBO_BOX(pWidget), nControlAction); + else + OSL_TRACE("Can't get value on button / list %d %d\n", + nControlId, nControlAction ); + + return aRetval; +} + +void SAL_CALL SalGtkFilePicker::enableControl( sal_Int16 nControlId, sal_Bool bEnable ) +throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + GtkWidget *pWidget; + + GdkThreadLock aLock; + + if ( nControlId == ExtendedFilePickerElementIds::LISTBOX_FILTER_SELECTOR ) + gtk_expander_set_expanded( GTK_EXPANDER( m_pFilterExpander ), bEnable ); + else if( ( pWidget = getWidget( nControlId ) ) ) + { + if( bEnable ) + { + OSL_TRACE( "enable\n" ); + gtk_widget_set_sensitive( pWidget, TRUE ); + } + else + { + OSL_TRACE( "disable\n" ); + gtk_widget_set_sensitive( pWidget, FALSE ); + } + } + else + OSL_TRACE("enable unknown control %d\n", nControlId ); +} + +void SAL_CALL SalGtkFilePicker::setLabel( sal_Int16 nControlId, const ::rtl::OUString& rLabel ) + throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + GType tType; + GtkWidget *pWidget; + + GdkThreadLock aLock; + + if( !( pWidget = getWidget( nControlId, &tType ) ) ) + { + OSL_TRACE("Set label on unknown control %d\n", nControlId); + return; + } + + OString aTxt = OUStringToOString( rLabel.replace('~', '_'), RTL_TEXTENCODING_UTF8 ); + if (nControlId == ExtendedFilePickerElementIds::PUSHBUTTON_PLAY) + { +#ifdef GTK_STOCK_MEDIA_PLAY + if (!msPlayLabel.getLength()) + msPlayLabel = rLabel; + if (msPlayLabel == rLabel) + gtk_button_set_label(GTK_BUTTON(pWidget), GTK_STOCK_MEDIA_PLAY); + else + gtk_button_set_label(GTK_BUTTON(pWidget), GTK_STOCK_MEDIA_STOP); +#else + gtk_button_set_label(GTK_BUTTON(pWidget), aTxt.getStr()); +#endif + } + else if( tType == GTK_TYPE_TOGGLE_BUTTON || tType == GTK_TYPE_BUTTON || tType == GTK_TYPE_LABEL ) + g_object_set( pWidget, "label", aTxt.getStr(), + "use_underline", TRUE, (char *)NULL ); + else + OSL_TRACE("Can't set label on list\n"); +} + +rtl::OUString SAL_CALL SalGtkFilePicker::getLabel( sal_Int16 nControlId ) + throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + GType tType; + OString aTxt; + GtkWidget *pWidget; + + GdkThreadLock aLock; + + if( !( pWidget = getWidget( nControlId, &tType ) ) ) + OSL_TRACE("Get label on unknown control %d\n", nControlId); + else if( tType == GTK_TYPE_TOGGLE_BUTTON || tType == GTK_TYPE_BUTTON || tType == GTK_TYPE_LABEL ) + aTxt = gtk_button_get_label( GTK_BUTTON( pWidget ) ); + else + OSL_TRACE("Can't get label on list\n"); + + return OStringToOUString( aTxt, RTL_TEXTENCODING_UTF8 ); +} + +//------------------------------------------------------------------------------------ +// XFilePreview functions +//------------------------------------------------------------------------------------ + +uno::Sequence<sal_Int16> SAL_CALL SalGtkFilePicker::getSupportedImageFormats() throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + // TODO return m_pImpl->getSupportedImageFormats(); + return 0; +} + +sal_Int32 SAL_CALL SalGtkFilePicker::getTargetColorDepth() throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + // TODO return m_pImpl->getTargetColorDepth(); + return 0; +} + +sal_Int32 SAL_CALL SalGtkFilePicker::getAvailableWidth() throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + return m_PreviewImageWidth; +} + +sal_Int32 SAL_CALL SalGtkFilePicker::getAvailableHeight() throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + return m_PreviewImageHeight; +} + +void SAL_CALL SalGtkFilePicker::setImage( sal_Int16 /*aImageFormat*/, const uno::Any& /*aImage*/ ) + throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + // TODO m_pImpl->setImage( aImageFormat, aImage ); +} + +void SalGtkFilePicker::implChangeType( GtkTreeSelection *selection ) +{ + CResourceProvider aResProvider; + OUString aLabel = aResProvider.getResString( FILE_PICKER_FILE_TYPE ); + + GdkThreadLock aLock; + + GtkTreeIter iter; + GtkTreeModel *model; + if (gtk_tree_selection_get_selected (selection, &model, &iter)) + { + gchar *title; + gtk_tree_model_get (model, &iter, 2, &title, -1); + aLabel += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( ": " )); + aLabel += rtl::OUString( title, strlen(title), RTL_TEXTENCODING_UTF8 ); + g_free (title); + } + gtk_expander_set_label (GTK_EXPANDER (m_pFilterExpander), + OUStringToOString( aLabel, RTL_TEXTENCODING_UTF8 ).getStr()); + FilePickerEvent evt; + evt.ElementId = LISTBOX_FILTER; + controlStateChanged( evt ); +} + +void SalGtkFilePicker::type_changed_cb( GtkTreeSelection *selection, SalGtkFilePicker *pobjFP ) +{ + pobjFP->implChangeType(selection); +} + +void SalGtkFilePicker::unselect_type() +{ + GdkThreadLock aLock; + + gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(m_pFilterView))); +} + +void SalGtkFilePicker::expander_changed_cb( GtkExpander *expander, SalGtkFilePicker *pobjFP ) +{ + if (gtk_expander_get_expanded(expander)) + pobjFP->unselect_type(); +} + +void SalGtkFilePicker::filter_changed_cb( GtkFileChooser *, GParamSpec *, + SalGtkFilePicker *pobjFP ) +{ + FilePickerEvent evt; + evt.ElementId = LISTBOX_FILTER; + OSL_TRACE( "filter_changed, isn't it great %x\n", pobjFP ); + pobjFP->controlStateChanged( evt ); +} + +void SalGtkFilePicker::folder_changed_cb( GtkFileChooser *, SalGtkFilePicker *pobjFP ) +{ + FilePickerEvent evt; + OSL_TRACE( "folder_changed, isn't it great %x\n", pobjFP ); + pobjFP->directoryChanged( evt ); +} + +void SalGtkFilePicker::selection_changed_cb( GtkFileChooser *, SalGtkFilePicker *pobjFP ) +{ + FilePickerEvent evt; + OSL_TRACE( "selection_changed, isn't it great %x\n", pobjFP ); + pobjFP->fileSelectionChanged( evt ); +} + +void SalGtkFilePicker::update_preview_cb( GtkFileChooser *file_chooser, SalGtkFilePicker* pobjFP ) +{ + GtkWidget *preview; + char *filename; + GdkPixbuf *pixbuf; + gboolean have_preview = FALSE; + + preview = pobjFP->m_pPreview; + filename = gtk_file_chooser_get_preview_filename( file_chooser ); + + if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( pobjFP->m_pToggles[PREVIEW] ) ) && g_file_test( filename, G_FILE_TEST_IS_REGULAR ) ) + { + pixbuf = gdk_pixbuf_new_from_file_at_size( + filename, + pobjFP->m_PreviewImageWidth, + pobjFP->m_PreviewImageHeight, NULL ); + + have_preview = ( pixbuf != NULL ); + + gtk_image_set_from_pixbuf( GTK_IMAGE( preview ), pixbuf ); + if( pixbuf ) + gdk_pixbuf_unref( pixbuf ); + + } + + gtk_file_chooser_set_preview_widget_active( file_chooser, have_preview ); + + if( filename ) + g_free( filename ); +} + +sal_Bool SAL_CALL SalGtkFilePicker::setShowState( sal_Bool bShowState ) throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + // TODO return m_pImpl->setShowState( bShowState ); + if( bShowState != mbPreviewState ) + { + GdkThreadLock aLock; + + if( bShowState ) + { + // Show + if( !mHID_Preview ) + { + mHID_Preview = g_signal_connect( + GTK_FILE_CHOOSER( m_pDialog ), "update-preview", + G_CALLBACK( update_preview_cb ), ( gpointer )this ); + } + gtk_widget_show( m_pPreview ); + } + else + { + // Hide + gtk_widget_hide( m_pPreview ); + } + + // also emit the signal + g_signal_emit_by_name( GTK_OBJECT( m_pDialog ), "update-preview" ); + + mbPreviewState = bShowState; + } + return true; +} + +sal_Bool SAL_CALL SalGtkFilePicker::getShowState() throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + return mbPreviewState; +} + +//------------------------------------------------------------------------------------ +// XInitialization +//------------------------------------------------------------------------------------ + +void SAL_CALL SalGtkFilePicker::initialize( const uno::Sequence<uno::Any>& aArguments ) + throw( uno::Exception, uno::RuntimeException ) +{ + // parameter checking + uno::Any aAny; + if( 0 == aArguments.getLength() ) + throw lang::IllegalArgumentException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "no arguments" )), + static_cast<XFilePicker2*>( this ), 1 ); + + aAny = aArguments[0]; + + if( ( aAny.getValueType() != ::getCppuType( ( sal_Int16* )0 ) ) && + (aAny.getValueType() != ::getCppuType( ( sal_Int8* )0 ) ) ) + throw lang::IllegalArgumentException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "invalid argument type" )), + static_cast<XFilePicker2*>( this ), 1 ); + + sal_Int16 templateId = -1; + aAny >>= templateId; + + GtkFileChooserAction eAction = GTK_FILE_CHOOSER_ACTION_OPEN; + const gchar *first_button_text = GTK_STOCK_OPEN; + + + // TODO: extract full semantic from + // svtools/source/filepicker/filepicker.cxx (getWinBits) + switch( templateId ) + { + case FILEOPEN_SIMPLE: + eAction = GTK_FILE_CHOOSER_ACTION_OPEN; + first_button_text = GTK_STOCK_OPEN; + OSL_TRACE( "3all true\n" ); + break; + case FILESAVE_SIMPLE: + eAction = GTK_FILE_CHOOSER_ACTION_SAVE; + first_button_text = GTK_STOCK_SAVE; + OSL_TRACE( "2all true\n" ); + break; + case FILESAVE_AUTOEXTENSION_PASSWORD: + eAction = GTK_FILE_CHOOSER_ACTION_SAVE; + first_button_text = GTK_STOCK_SAVE; + mbToggleVisibility[PASSWORD] = true; + OSL_TRACE( "1all true\n" ); + // TODO + break; + case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS: + eAction = GTK_FILE_CHOOSER_ACTION_SAVE; + first_button_text = GTK_STOCK_SAVE; + mbToggleVisibility[PASSWORD] = true; + mbToggleVisibility[FILTEROPTIONS] = true; + OSL_TRACE( "4all true\n" ); + // TODO + break; + case FILESAVE_AUTOEXTENSION_SELECTION: + eAction = GTK_FILE_CHOOSER_ACTION_SAVE; // SELECT_FOLDER ? + first_button_text = GTK_STOCK_SAVE; + mbToggleVisibility[SELECTION] = true; + OSL_TRACE( "5all true\n" ); + // TODO + break; + case FILESAVE_AUTOEXTENSION_TEMPLATE: + eAction = GTK_FILE_CHOOSER_ACTION_SAVE; + first_button_text = GTK_STOCK_SAVE; + mbListVisibility[TEMPLATE] = true; + OSL_TRACE( "6all true\n" ); + // TODO + break; + case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE: + eAction = GTK_FILE_CHOOSER_ACTION_OPEN; + first_button_text = GTK_STOCK_OPEN; + mbToggleVisibility[LINK] = true; + mbToggleVisibility[PREVIEW] = true; + mbListVisibility[IMAGE_TEMPLATE] = true; + // TODO + break; + case FILEOPEN_PLAY: + eAction = GTK_FILE_CHOOSER_ACTION_OPEN; + first_button_text = GTK_STOCK_OPEN; + mbButtonVisibility[PLAY] = true; + // TODO + break; + case FILEOPEN_READONLY_VERSION: + eAction = GTK_FILE_CHOOSER_ACTION_OPEN; + first_button_text = GTK_STOCK_OPEN; + mbToggleVisibility[READONLY] = true; + mbListVisibility[VERSION] = true; + break; + case FILEOPEN_LINK_PREVIEW: + eAction = GTK_FILE_CHOOSER_ACTION_OPEN; + first_button_text = GTK_STOCK_OPEN; + mbToggleVisibility[LINK] = true; + mbToggleVisibility[PREVIEW] = true; + // TODO + break; + case FILESAVE_AUTOEXTENSION: + eAction = GTK_FILE_CHOOSER_ACTION_SAVE; + first_button_text = GTK_STOCK_SAVE; + OSL_TRACE( "7all true\n" ); + // TODO + break; + default: + throw lang::IllegalArgumentException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Unknown template" )), + static_cast< XFilePicker2* >( this ), + 1 ); + } + + GdkThreadLock aLock; + + if( GTK_FILE_CHOOSER_ACTION_SAVE == eAction ) + { + CResourceProvider aResProvider; + OUString aFilePickerTitle(aResProvider.getResString( FILE_PICKER_TITLE_SAVE )); + gtk_window_set_title ( GTK_WINDOW( m_pDialog ), + OUStringToOString( aFilePickerTitle, RTL_TEXTENCODING_UTF8 ).getStr() ); + } + + gtk_file_chooser_set_action( GTK_FILE_CHOOSER( m_pDialog ), eAction); + dialog_remove_buttons( GTK_DIALOG( m_pDialog ) ); + gtk_dialog_add_button( GTK_DIALOG( m_pDialog ), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL ); + for( int nTVIndex = 0; nTVIndex < BUTTON_LAST; nTVIndex++ ) + { + if( mbButtonVisibility[nTVIndex] ) + { +#ifdef GTK_STOCK_MEDIA_PLAY + m_pButtons[ nTVIndex ] = gtk_dialog_add_button( GTK_DIALOG( m_pDialog ), GTK_STOCK_MEDIA_PLAY, 1 ); +#else + CResourceProvider aResProvider; + OString aPlay = OUStringToOString( aResProvider.getResString( PUSHBUTTON_PLAY ), RTL_TEXTENCODING_UTF8 ); + m_pButtons[ nTVIndex ] = gtk_dialog_add_button( GTK_DIALOG( m_pDialog ), aPlay.getStr(), 1 ); +#endif + } + } + gtk_dialog_add_button( GTK_DIALOG( m_pDialog ), first_button_text, GTK_RESPONSE_ACCEPT ); + + gtk_dialog_set_default_response( GTK_DIALOG (m_pDialog), GTK_RESPONSE_ACCEPT ); + + // Setup special flags + for( int nTVIndex = 0; nTVIndex < TOGGLE_LAST; nTVIndex++ ) + { + if( mbToggleVisibility[nTVIndex] ) + gtk_widget_show( m_pToggles[ nTVIndex ] ); + } + + for( int nTVIndex = 0; nTVIndex < LIST_LAST; nTVIndex++ ) + { + if( mbListVisibility[nTVIndex] ) + { + gtk_widget_set_sensitive( m_pLists[ nTVIndex ], false ); + gtk_widget_show( m_pLists[ nTVIndex ] ); + gtk_widget_show( m_pListLabels[ nTVIndex ] ); + gtk_widget_show( m_pAligns[ nTVIndex ] ); + gtk_widget_show( m_pHBoxs[ nTVIndex ] ); + } + } +} + +void SalGtkFilePicker::preview_toggled_cb( GtkObject *cb, SalGtkFilePicker* pobjFP ) +{ + if( pobjFP->mbToggleVisibility[PREVIEW] ) + pobjFP->setShowState( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( cb ) ) ); +} + +//------------------------------------------------------------------------------------ +// XCancellable +//------------------------------------------------------------------------------------ + +void SAL_CALL SalGtkFilePicker::cancel() throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + // TODO m_pImpl->cancel(); +} + +// ------------------------------------------------- +// XServiceInfo +// ------------------------------------------------- + +rtl::OUString SAL_CALL SalGtkFilePicker::getImplementationName() + throw( uno::RuntimeException ) +{ + return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( FILE_PICKER_IMPL_NAME )); +} + +// ------------------------------------------------- +// XServiceInfo +// ------------------------------------------------- + +sal_Bool SAL_CALL SalGtkFilePicker::supportsService( const rtl::OUString& ServiceName ) + throw( uno::RuntimeException ) +{ + uno::Sequence <rtl::OUString> SupportedServicesNames = FilePicker_getSupportedServiceNames(); + + for( sal_Int32 n = SupportedServicesNames.getLength(); n--; ) + if( SupportedServicesNames[n].compareTo( ServiceName ) == 0) + return sal_True; + + return sal_False; +} + +// ------------------------------------------------- +// XServiceInfo +// ------------------------------------------------- + +uno::Sequence<rtl::OUString> SAL_CALL SalGtkFilePicker::getSupportedServiceNames() + throw( uno::RuntimeException ) +{ + return FilePicker_getSupportedServiceNames(); +} + + +//-------------------------------------------------- +// Misc +//------------------------------------------------- +void SalGtkFilePicker::SetCurFilter( const OUString& rFilter ) +{ + GdkThreadLock aLock; + + // Get all the filters already added + GSList *filters = gtk_file_chooser_list_filters ( GTK_FILE_CHOOSER( m_pDialog ) ); + bool bFound = false; + + for( GSList *iter = filters; !bFound && iter; iter = iter->next ) + { + GtkFileFilter* pFilter = reinterpret_cast<GtkFileFilter *>( iter->data ); + G_CONST_RETURN gchar * filtername = gtk_file_filter_get_name( pFilter ); + OUString sFilterName( filtername, strlen( filtername ), RTL_TEXTENCODING_UTF8 ); + + OUString aShrunkName = shrinkFilterName( rFilter ); + if( aShrunkName.equals( sFilterName) ) + { + OSL_TRACE( "actually setting %s\n", filtername ); + gtk_file_chooser_set_filter( GTK_FILE_CHOOSER( m_pDialog ), pFilter ); + bFound = true; + } + } + + g_slist_free( filters ); +} + +extern "C" +{ +static gboolean +case_insensitive_filter (const GtkFileFilterInfo *filter_info, gpointer data) +{ + gboolean bRetval = FALSE; + const char *pFilter = (const char *) data; + + g_return_val_if_fail( data != NULL, FALSE ); + g_return_val_if_fail( filter_info != NULL, FALSE ); + + if( !filter_info->uri ) + return FALSE; + + const char *pExtn = strrchr( filter_info->uri, '.' ); + if( !pExtn ) + return FALSE; + pExtn++; + + if( !g_ascii_strcasecmp( pFilter, pExtn ) ) + bRetval = TRUE; + +#ifdef DEBUG + fprintf( stderr, "'%s' match extn '%s' vs '%s' yeilds %d\n", + filter_info->uri, pExtn, pFilter, bRetval ); +#endif + + return bRetval; +} +} + +GtkFileFilter* SalGtkFilePicker::implAddFilter( const OUString& rFilter, const OUString& rType ) +{ + GdkThreadLock aLock; + + GtkFileFilter *filter = gtk_file_filter_new(); + + OUString aShrunkName = shrinkFilterName( rFilter ); + OString aFilterName = rtl::OUStringToOString( aShrunkName, RTL_TEXTENCODING_UTF8 ); + gtk_file_filter_set_name( filter, aFilterName ); + + static const OUString aStarDot(RTL_CONSTASCII_USTRINGPARAM( "*." )); + OUString aTokens; + + bool bAllGlob = !rType.compareToAscii( "*.*" ) || !rType.compareToAscii( "*" ); + if (bAllGlob) + gtk_file_filter_add_pattern( filter, "*" ); + else + { + sal_Int32 nIndex = 0; + rtl::OUString aToken; + do + { + aToken = rType.getToken( 0, ';', nIndex ); + // Assume all have the "*.<extn>" syntax + aToken = aToken.copy( aToken.lastIndexOf( aStarDot ) + 2 ); + if (aToken.getLength()) + { + if (aTokens.getLength()) + aTokens += OUString(RTL_CONSTASCII_USTRINGPARAM(",")); + aTokens = aTokens += aToken; + gtk_file_filter_add_custom (filter, GTK_FILE_FILTER_URI, + case_insensitive_filter, + g_strdup( rtl::OUStringToOString( aToken, RTL_TEXTENCODING_UTF8 ) ), + (GDestroyNotify) g_free ); + + OSL_TRACE( "fustering with %s\n", rtl::OUStringToOString( aToken, RTL_TEXTENCODING_UTF8 ).getStr()); + } +#ifdef DEBUG + else + { + g_warning( "Duff filter token '%s'\n", + (const sal_Char *) rtl::OUStringToOString( + rType.getToken( 0, ';', nIndex ), RTL_TEXTENCODING_UTF8 ) ); + } +#endif + } + while( nIndex >= 0 ); + } + + gtk_file_chooser_add_filter( GTK_FILE_CHOOSER( m_pDialog ), filter ); + + if (!bAllGlob) + { + GtkTreeIter iter; + gtk_list_store_append (m_pFilterStore, &iter); + gtk_list_store_set (m_pFilterStore, &iter, + 0, OUStringToOString(shrinkFilterName( rFilter, true ), RTL_TEXTENCODING_UTF8).getStr(), + 1, OUStringToOString(aTokens, RTL_TEXTENCODING_UTF8).getStr(), + 2, aFilterName.getStr(), + 3, OUStringToOString(rType, RTL_TEXTENCODING_UTF8).getStr(), + -1); + } + return filter; +} + +void SalGtkFilePicker::implAddFilterGroup( const OUString& /*_rFilter*/, const Sequence< StringPair >& _rFilters ) +{ + // Gtk+ has no filter group concept I think so ... + // implAddFilter( _rFilter, String() ); + const StringPair* pSubFilters = _rFilters.getConstArray(); + const StringPair* pSubFiltersEnd = pSubFilters + _rFilters.getLength(); + for( ; pSubFilters != pSubFiltersEnd; ++pSubFilters ) + implAddFilter( pSubFilters->First, pSubFilters->Second ); +} + +void SalGtkFilePicker::SetFilters() +{ + GdkThreadLock aLock; + + if (!m_aInitialFilter.getLength()) + m_aInitialFilter = m_aCurrentFilter; + + rtl::OUString sPseudoFilter; + if( GTK_FILE_CHOOSER_ACTION_SAVE == gtk_file_chooser_get_action( GTK_FILE_CHOOSER( m_pDialog ) ) ) + { + std::set<OUString> aAllFormats; + if( m_pFilterList && !m_pFilterList->empty() ) + { + for ( FilterList::iterator aListIter = m_pFilterList->begin(); + aListIter != m_pFilterList->end(); + ++aListIter + ) + { + if( aListIter->hasSubFilters() ) + { // it's a filter group + UnoFilterList aSubFilters; + aListIter->getSubFilters( aSubFilters ); + const StringPair* pSubFilters = aSubFilters.getConstArray(); + const StringPair* pSubFiltersEnd = pSubFilters + aSubFilters.getLength(); + for( ; pSubFilters != pSubFiltersEnd; ++pSubFilters ) + aAllFormats.insert(pSubFilters->Second); + } + else + aAllFormats.insert(aListIter->getFilter()); + } + } + if (aAllFormats.size() > 1) + { + rtl::OUString sAllFilter; + std::set<OUString>::const_iterator aEnd = aAllFormats.end(); + for (std::set<OUString>::const_iterator aIter = aAllFormats.begin(); aIter != aEnd; ++aIter) + { + if (sAllFilter.getLength()) + sAllFilter += OUString(sal_Unicode(';')); + sAllFilter += *aIter; + } + CResourceProvider aResProvider; + sPseudoFilter = aResProvider.getResString(FILE_PICKER_ALLFORMATS); + m_pPseudoFilter = implAddFilter( sPseudoFilter, sAllFilter ); + } + } + + if( m_pFilterList && !m_pFilterList->empty() ) + { + for ( FilterList::iterator aListIter = m_pFilterList->begin(); + aListIter != m_pFilterList->end(); + ++aListIter + ) + { + if( aListIter->hasSubFilters() ) + { // it's a filter group + + UnoFilterList aSubFilters; + aListIter->getSubFilters( aSubFilters ); + + implAddFilterGroup( aListIter->getTitle(), aSubFilters ); + } + else + { + // it's a single filter + + implAddFilter( aListIter->getTitle(), aListIter->getFilter() ); + } + } + } + + if (gtk_tree_model_iter_n_children(GTK_TREE_MODEL(m_pFilterStore), NULL)) //If m_pFilterStore is not empty + gtk_widget_show( m_pFilterExpander ); + else + gtk_widget_hide( m_pFilterExpander ); + + // set the default filter + if (sPseudoFilter.getLength()) + SetCurFilter( sPseudoFilter ); + else if(m_aCurrentFilter.getLength()) + SetCurFilter( m_aCurrentFilter ); + + OSL_TRACE( "end setting filters\n"); +} + +SalGtkFilePicker::~SalGtkFilePicker() +{ + int i; + + for( i = 0; i < TOGGLE_LAST; i++ ) + gtk_widget_destroy( m_pToggles[i] ); + + for( i = 0; i < LIST_LAST; i++ ) + { + gtk_widget_destroy( m_pListLabels[i] ); + gtk_widget_destroy( m_pAligns[i] ); //m_pAligns[i] owns m_pLists[i] + gtk_widget_destroy( m_pHBoxs[i] ); + } + + delete m_pFilterList; + + gtk_widget_destroy( m_pVBox ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/gnome/SalGtkFilePicker.hxx b/fpicker/source/unx/gnome/SalGtkFilePicker.hxx new file mode 100644 index 000000000000..b7faf522e550 --- /dev/null +++ b/fpicker/source/unx/gnome/SalGtkFilePicker.hxx @@ -0,0 +1,356 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SALGTKFILEPICKER_HXX_ +#define _SALGTKFILEPICKER_HXX_ + +//_______________________________________________________________________________________________________________________ +// includes of other projects +//_______________________________________________________________________________________________________________________ + +#include <cppuhelper/compbase10.hxx> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerNotifier.hpp> +#include <com/sun/star/ui/dialogs/XFilterManager.hpp> +#include <com/sun/star/ui/dialogs/XFilterGroupManager.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp> +#include <com/sun/star/ui/dialogs/XFilePreview.hpp> +#include <com/sun/star/beans/StringPair.hpp> + +#include "SalGtkPicker.hxx" + +#include <memory> + +#include <rtl/ustring.hxx> + +#include <list> + +//---------------------------------------------------------- +// Implementation class for the XFilePicker Interface +//---------------------------------------------------------- + +//---------------------------------------------------------- +// forward declarations +//---------------------------------------------------------- + +using namespace rtl; + +struct FilterEntry; +struct ElementEntry_Impl; + +typedef ::std::list < FilterEntry > FilterList; +typedef ::std::list < ElementEntry_Impl > ElementList; +typedef ::com::sun::star::beans::StringPair UnoFilterEntry; +typedef ::com::sun::star::uno::Sequence< UnoFilterEntry > UnoFilterList; // can be transported more effectively + + +//---------------------------------------------------------- +// class declaration +//---------------------------------------------------------- + +class SalGtkFilePicker : + public SalGtkPicker, + public cppu::WeakComponentImplHelper10< + ::com::sun::star::ui::dialogs::XFilterManager, + ::com::sun::star::ui::dialogs::XFilterGroupManager, + ::com::sun::star::ui::dialogs::XFilePickerControlAccess, + ::com::sun::star::ui::dialogs::XFilePickerNotifier, + ::com::sun::star::ui::dialogs::XFilePreview, + ::com::sun::star::ui::dialogs::XFilePicker2, + ::com::sun::star::lang::XInitialization, + ::com::sun::star::util::XCancellable, + ::com::sun::star::lang::XEventListener, + ::com::sun::star::lang::XServiceInfo > +{ + public: + + // constructor + SalGtkFilePicker( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceMgr ); + + //------------------------------------------------------------------------------------ + // XFilePickerNotifier + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL addFilePickerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener >& xListener ) + throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL removeFilePickerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener >& xListener ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XExecutableDialog functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setTitle( const ::rtl::OUString& aTitle ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual sal_Int16 SAL_CALL execute( ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFilePicker functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setMultiSelectionMode( sal_Bool bMode ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setDefaultName( const ::rtl::OUString& aName ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setDisplayDirectory( const ::rtl::OUString& aDirectory ) + throw( com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::uno::RuntimeException ); + + virtual ::rtl::OUString SAL_CALL getDisplayDirectory( ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getFiles( ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFilePicker2 functions + //------------------------------------------------------------------------------------ + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSelectedFiles() + throw (::com::sun::star::uno::RuntimeException); + + //------------------------------------------------------------------------------------ + // XFilterManager functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL appendFilter( const ::rtl::OUString& aTitle, const ::rtl::OUString& aFilter ) + throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setCurrentFilter( const ::rtl::OUString& aTitle ) + throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + + virtual ::rtl::OUString SAL_CALL getCurrentFilter( ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFilterGroupManager functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL appendFilterGroup( const ::rtl::OUString& sGroupTitle, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::StringPair >& aFilters ) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + //------------------------------------------------------------------------------------ + // XFilePickerControlAccess functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setValue( sal_Int16 nControlId, sal_Int16 nControlAction, const ::com::sun::star::uno::Any& aValue ) + throw (::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Any SAL_CALL getValue( sal_Int16 aControlId, sal_Int16 aControlAction ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL enableControl( sal_Int16 nControlId, sal_Bool bEnable ) + throw(::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setLabel( sal_Int16 nControlId, const ::rtl::OUString& aLabel ) + throw (::com::sun::star::uno::RuntimeException); + + virtual ::rtl::OUString SAL_CALL getLabel( sal_Int16 nControlId ) + throw (::com::sun::star::uno::RuntimeException); + + //------------------------------------------------ + // XFilePreview + //------------------------------------------------ + + virtual ::com::sun::star::uno::Sequence< sal_Int16 > SAL_CALL getSupportedImageFormats( ) + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL getTargetColorDepth( ) + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL getAvailableWidth( ) + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL getAvailableHeight( ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL setImage( sal_Int16 aImageFormat, const ::com::sun::star::uno::Any& aImage ) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL setShowState( sal_Bool bShowState ) + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL getShowState( ) + throw (::com::sun::star::uno::RuntimeException); + + //------------------------------------------------ + // XInitialization + //------------------------------------------------ + + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) + throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + //------------------------------------------------ + // XCancellable + //------------------------------------------------ + + virtual void SAL_CALL cancel( ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------ + // XEventListener + //------------------------------------------------ + + using cppu::WeakComponentImplHelperBase::disposing; + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& aEvent ) + throw(::com::sun::star::uno::RuntimeException); + + //------------------------------------------------ + // XServiceInfo + //------------------------------------------------ + + virtual ::rtl::OUString SAL_CALL getImplementationName( ) + throw(::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) + throw(::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) + throw(::com::sun::star::uno::RuntimeException); + + //------------------------------------------------------------------------------------ + // FilePicker Event functions + //------------------------------------------------------------------------------------ + + void SAL_CALL fileSelectionChanged( ::com::sun::star::ui::dialogs::FilePickerEvent aEvent ); + void SAL_CALL directoryChanged( ::com::sun::star::ui::dialogs::FilePickerEvent aEvent ); + rtl::OUString SAL_CALL helpRequested( ::com::sun::star::ui::dialogs::FilePickerEvent aEvent ) const; + void SAL_CALL controlStateChanged( ::com::sun::star::ui::dialogs::FilePickerEvent aEvent ); + + private: + // prevent copy and assignment + SalGtkFilePicker( const SalGtkFilePicker& ); + SalGtkFilePicker& operator=( const SalGtkFilePicker& ); + + sal_Bool FilterNameExists( const ::rtl::OUString& rTitle ); + sal_Bool FilterNameExists( const UnoFilterList& _rGroupedFilters ); + + void ensureFilterList( const ::rtl::OUString& _rInitialCurrentFilter ); + + // to instanciate own services + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xServiceMgr; + + private: + ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener > + m_xListener; + ::rtl::OUString msPlayLabel; + FilterList *m_pFilterList; + GtkWidget *m_pVBox; + + GtkWidget *m_pFilterExpander; + GtkWidget *m_pFilterView; + GtkListStore *m_pFilterStore; + + enum { + AUTOEXTENSION, + PASSWORD, + FILTEROPTIONS, + READONLY, + LINK, + PREVIEW, + SELECTION, + TOGGLE_LAST + }; + + GtkWidget *m_pToggles[ TOGGLE_LAST ]; + + bool mbToggleVisibility[TOGGLE_LAST]; + bool mbToggleChecked[TOGGLE_LAST]; + + static const rtl::OString m_ToggleLabels[TOGGLE_LAST]; + + enum { + PLAY, + BUTTON_LAST }; + + GtkWidget *m_pButtons[ BUTTON_LAST ]; + + enum { + VERSION, + TEMPLATE, + IMAGE_TEMPLATE, + LIST_LAST + }; + + GtkWidget *m_pHBoxs[ LIST_LAST ]; + GtkWidget *m_pAligns[ LIST_LAST ]; + GtkWidget *m_pLists[ LIST_LAST ]; + GtkWidget *m_pListLabels[ LIST_LAST ]; + bool mbListVisibility[ LIST_LAST ]; + bool mbButtonVisibility[ BUTTON_LAST ]; + gulong mnHID_FolderChange; + gulong mnHID_SelectionChange; + + ::rtl::OUString m_aCurrentFilter; + ::rtl::OUString m_aInitialFilter; + + bool bVersionWidthUnset; + sal_Bool mbPreviewState; + gulong mHID_Preview; + GtkWidget* m_pPreview; + GtkFileFilter* m_pPseudoFilter; + sal_Int32 m_PreviewImageWidth; + sal_Int32 m_PreviewImageHeight; + + GtkWidget *getWidget( sal_Int16 nControlId, GType *pType = NULL); + + void SetCurFilter( const OUString& rFilter ); + void SetFilters(); + void UpdateFilterfromUI(); + + void implChangeType( GtkTreeSelection *selection ); + GtkFileFilter * implAddFilter( const OUString& rFilter, const OUString& rType ); + void implAddFilterGroup( const OUString& rFilter, + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::StringPair>& _rFilters ); + void updateCurrentFilterFromName(const gchar* filtername); + void unselect_type(); + void InitialMapping(); + + void HandleSetListValue(GtkComboBox *pWidget, sal_Int16 nControlAction, + const ::com::sun::star::uno::Any& rValue); + ::com::sun::star::uno::Any HandleGetListValue(GtkComboBox *pWidget, sal_Int16 nControlAction) const; + + static void expander_changed_cb( GtkExpander *expander, SalGtkFilePicker *pobjFP ); + static void preview_toggled_cb (GtkObject *cb, SalGtkFilePicker *pobjFP); + static void filter_changed_cb (GtkFileChooser *file_chooser, GParamSpec *pspec, SalGtkFilePicker *pobjFP); + static void type_changed_cb( GtkTreeSelection *selection, SalGtkFilePicker *pobjFP ); + static void folder_changed_cb (GtkFileChooser *file_chooser, SalGtkFilePicker *pobjFP); + static void selection_changed_cb (GtkFileChooser *file_chooser, SalGtkFilePicker *pobjFP); + static void update_preview_cb (GtkFileChooser *file_chooser, SalGtkFilePicker *pobjFP); + static void dialog_mapped_cb(GtkWidget *widget, SalGtkFilePicker *pobjFP); + public: + virtual ~SalGtkFilePicker(); + +}; +#endif // _SALGTKFILEPICKER_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/gnome/SalGtkFolderPicker.cxx b/fpicker/source/unx/gnome/SalGtkFolderPicker.cxx new file mode 100644 index 000000000000..0a3c807066d6 --- /dev/null +++ b/fpicker/source/unx/gnome/SalGtkFolderPicker.cxx @@ -0,0 +1,253 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +#ifdef AIX +#define _LINUX_SOURCE_COMPAT +#include <sys/timer.h> +#undef _LINUX_SOURCE_COMPAT +#endif + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#include <cppuhelper/interfacecontainer.h> +#include <osl/diagnose.h> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <FPServiceInfo.hxx> +#include <osl/mutex.hxx> +#include <vcl/svapp.hxx> +#include "SalGtkFolderPicker.hxx" + +#include <tools/urlobj.hxx> + +#include <iostream> +#include "resourceprovider.hxx" +#include <tools/rc.hxx> + +//------------------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------------------ + +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; + +//------------------------------------------------------------------------ +// helper functions +//------------------------------------------------------------------------ + +namespace +{ + // controling event notifications + uno::Sequence<rtl::OUString> SAL_CALL FolderPicker_getSupportedServiceNames() + { + uno::Sequence<rtl::OUString> aRet(2); + aRet[0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.SystemFolderPicker" )); + aRet[1] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.GtkFolderPicker" )); + return aRet; + } +} + +//----------------------------------------------------------------------------------------- +// constructor +//----------------------------------------------------------------------------------------- +SalGtkFolderPicker::SalGtkFolderPicker( const uno::Reference<lang::XMultiServiceFactory>& xServiceMgr ) : + SalGtkPicker(xServiceMgr), + m_xServiceMgr(xServiceMgr) +{ + CResourceProvider aResProvider; + + GdkThreadLock aLock; + + m_pDialog = gtk_file_chooser_dialog_new( + OUStringToOString( aResProvider.getResString( FOLDERPICKER_TITLE ), RTL_TEXTENCODING_UTF8 ).getStr(), + NULL, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, (char *)NULL ); + + gtk_dialog_set_default_response( GTK_DIALOG (m_pDialog), GTK_RESPONSE_ACCEPT ); + gtk_file_chooser_set_local_only( GTK_FILE_CHOOSER( m_pDialog ), FALSE ); + gtk_file_chooser_set_select_multiple( GTK_FILE_CHOOSER( m_pDialog ), FALSE ); +} + +// ------------------------------------------------- +// XEventListener +// ------------------------------------------------- + +void SAL_CALL SalGtkFolderPicker::disposing( const lang::EventObject& ) + throw( uno::RuntimeException ) +{ +} + +void SAL_CALL SalGtkFolderPicker::setDisplayDirectory( const rtl::OUString& aDirectory ) + throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + OString aTxt = unicodetouri( aDirectory ); + + if( aTxt.lastIndexOf('/') == aTxt.getLength() - 1 ) + aTxt = aTxt.copy( 0, aTxt.getLength() - 1 ); + + OSL_TRACE( "setting path to %s\n", aTxt.getStr() ); + + GdkThreadLock aLock; + + gtk_file_chooser_set_current_folder_uri( GTK_FILE_CHOOSER( m_pDialog ), + aTxt.getStr() ); +} + +rtl::OUString SAL_CALL SalGtkFolderPicker::getDisplayDirectory() throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + GdkThreadLock aLock; + + gchar* pCurrentFolder = + gtk_file_chooser_get_current_folder_uri( GTK_FILE_CHOOSER( m_pDialog ) ); + ::rtl::OUString aCurrentFolderName = uritounicode(pCurrentFolder); + g_free( pCurrentFolder ); + + return aCurrentFolderName; +} + +rtl::OUString SAL_CALL SalGtkFolderPicker::getDirectory() throw( uno::RuntimeException ) +{ + return getDisplayDirectory(); +} + +void SAL_CALL SalGtkFolderPicker::setDescription( const rtl::OUString& rDescription ) + throw( uno::RuntimeException ) +{ + ::rtl::OString aDescription = OUStringToOString( rDescription, RTL_TEXTENCODING_UTF8 ); +} + + + +//----------------------------------------------------------------------------------------- +// XExecutableDialog functions +//----------------------------------------------------------------------------------------- + +void SAL_CALL SalGtkFolderPicker::setTitle( const rtl::OUString& aTitle ) throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + ::rtl::OString aWindowTitle = OUStringToOString( aTitle, RTL_TEXTENCODING_UTF8 ); + + GdkThreadLock aLock; + gtk_window_set_title( GTK_WINDOW( m_pDialog ), aWindowTitle.getStr() ); +} + +sal_Int16 SAL_CALL SalGtkFolderPicker::execute() throw( uno::RuntimeException ) +{ + OSL_TRACE( "1: HERE WE ARE\n"); + OSL_ASSERT( m_pDialog != NULL ); + + sal_Int16 retVal = 0; + + uno::Reference< awt::XExtendedToolkit > xToolkit( + m_xServiceMgr->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.Toolkit")) ), uno::UNO_QUERY); + + RunDialog* pRunDialog = new RunDialog(m_pDialog, xToolkit); + uno::Reference < awt::XTopWindowListener > xLifeCycle(pRunDialog); + gint nStatus = pRunDialog->run(); + switch( nStatus ) + { + case GTK_RESPONSE_ACCEPT: + retVal = ExecutableDialogResults::OK; + break; + case GTK_RESPONSE_CANCEL: + retVal = ExecutableDialogResults::CANCEL; + break; + default: + retVal = 0; + break; + } + + return retVal; +} + +//------------------------------------------------------------------------------------ +// XCancellable +//------------------------------------------------------------------------------------ + +void SAL_CALL SalGtkFolderPicker::cancel() throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + // TODO m_pImpl->cancel(); +} + +// ------------------------------------------------- +// XServiceInfo +// ------------------------------------------------- + +rtl::OUString SAL_CALL SalGtkFolderPicker::getImplementationName() + throw( uno::RuntimeException ) +{ + return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( FOLDER_PICKER_IMPL_NAME )); +} + +// ------------------------------------------------- +// XServiceInfo +// ------------------------------------------------- + +sal_Bool SAL_CALL SalGtkFolderPicker::supportsService( const rtl::OUString& ServiceName ) + throw( uno::RuntimeException ) +{ + uno::Sequence <rtl::OUString> SupportedServicesNames = FolderPicker_getSupportedServiceNames(); + + for( sal_Int32 n = SupportedServicesNames.getLength(); n--; ) + if( SupportedServicesNames[n].compareTo( ServiceName ) == 0) + return sal_True; + + return sal_False; +} + +// ------------------------------------------------- +// XServiceInfo +// ------------------------------------------------- + +uno::Sequence<rtl::OUString> SAL_CALL SalGtkFolderPicker::getSupportedServiceNames() + throw( uno::RuntimeException ) +{ + return FolderPicker_getSupportedServiceNames(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/gnome/SalGtkFolderPicker.hxx b/fpicker/source/unx/gnome/SalGtkFolderPicker.hxx new file mode 100644 index 000000000000..5110ea86a0f6 --- /dev/null +++ b/fpicker/source/unx/gnome/SalGtkFolderPicker.hxx @@ -0,0 +1,127 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SALGTKFOLDERPICKER_HXX_ +#define _SALGTKFOLDERPICKER_HXX_ + +//_______________________________________________________________________________________________________________________ +// includes of other projects +//_______________________________________________________________________________________________________________________ + +#include <cppuhelper/implbase3.hxx> + +#include "SalGtkPicker.hxx" + +#include <memory> + +#include <rtl/ustring.hxx> + +#include <list> + +//---------------------------------------------------------- +// class declaration +//---------------------------------------------------------- + +class SalGtkFolderPicker : + public SalGtkPicker, + public cppu::WeakImplHelper3< + ::com::sun::star::ui::dialogs::XFolderPicker, + ::com::sun::star::lang::XServiceInfo, + ::com::sun::star::util::XCancellable > +{ + public: + + // constructor + SalGtkFolderPicker( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceMgr ); + + //------------------------------------------------------------------------------------ + // XExecutableDialog functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setTitle( const ::rtl::OUString& aTitle ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual sal_Int16 SAL_CALL execute( ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFolderPicker functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setDisplayDirectory( const rtl::OUString& rDirectory ) + throw( com::sun::star::lang::IllegalArgumentException, com::sun::star::uno::RuntimeException ); + + virtual rtl::OUString SAL_CALL getDisplayDirectory( ) + throw( com::sun::star::uno::RuntimeException ); + + virtual rtl::OUString SAL_CALL getDirectory( ) + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setDescription( const rtl::OUString& rDescription ) + throw( com::sun::star::uno::RuntimeException ); + + + //------------------------------------------------ + // XServiceInfo + //------------------------------------------------ + + virtual ::rtl::OUString SAL_CALL getImplementationName( ) + throw(::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) + throw(::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) + throw(::com::sun::star::uno::RuntimeException); + + //------------------------------------------------ + // XCancellable + //------------------------------------------------ + + virtual void SAL_CALL cancel( ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------ + // XEventListener + //------------------------------------------------ + + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& aEvent ) + throw(::com::sun::star::uno::RuntimeException); + + private: + // prevent copy and assignment + SalGtkFolderPicker( const SalGtkFolderPicker& ); + SalGtkFolderPicker& operator=( const SalGtkFolderPicker& ); + private: + // to instanciate own services + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xServiceMgr; +}; + +#endif // _SALGTKFOLDERPICKER_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/gnome/SalGtkPicker.cxx b/fpicker/source/unx/gnome/SalGtkPicker.cxx new file mode 100644 index 000000000000..782b44d11e7c --- /dev/null +++ b/fpicker/source/unx/gnome/SalGtkPicker.cxx @@ -0,0 +1,303 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +#ifdef AIX +#define _LINUX_SOURCE_COMPAT +#include <sys/timer.h> +#undef _LINUX_SOURCE_COMPAT +#endif + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/uri/XExternalUriReferenceTranslator.hpp> +#include <com/sun/star/lang/SystemDependent.hpp> +#include <com/sun/star/awt/XSystemDependentWindowPeer.hpp> +#include <com/sun/star/awt/SystemDependentXWindow.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <comphelper/processfactory.hxx> +#include <cppuhelper/interfacecontainer.h> +#include <rtl/process.h> +#include <osl/diagnose.h> +#include <com/sun/star/uno/Any.hxx> +#include <FPServiceInfo.hxx> +#include <osl/mutex.hxx> +#include <vcl/svapp.hxx> +#include "SalGtkPicker.hxx" +#include <tools/urlobj.hxx> +#include <stdio.h> + +//------------------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------------------ + +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; + +rtl::OUString SalGtkPicker::uritounicode(const gchar* pIn) +{ + if (!pIn) + return rtl::OUString(); + + rtl::OUString sURL( const_cast<const sal_Char *>(pIn), strlen(pIn), + RTL_TEXTENCODING_UTF8 ); + + INetURLObject aURL(sURL); + if (INET_PROT_FILE == aURL.GetProtocol()) + { + // all the URLs are handled by office in UTF-8 + // so the Gnome FP related URLs should be converted accordingly + gchar *pEncodedFileName = g_filename_from_uri(pIn, NULL, NULL); + if ( pEncodedFileName ) + { + rtl::OUString sEncoded(pEncodedFileName, strlen(pEncodedFileName), + osl_getThreadTextEncoding()); + INetURLObject aCurrentURL(sEncoded, INetURLObject::FSYS_UNX); + aCurrentURL.SetHost(aURL.GetHost()); + sURL = aCurrentURL.getExternalURL(); + } + else + { + OUString aNewURL = Reference<uri::XExternalUriReferenceTranslator>(Reference<XMultiServiceFactory>(comphelper::getProcessServiceFactory(), UNO_QUERY_THROW)->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uri.ExternalUriReferenceTranslator"))), UNO_QUERY_THROW)->translateToInternal(sURL); + if( aNewURL.getLength() ) + sURL = aNewURL; + } + } + return sURL; +} + +rtl::OString SalGtkPicker::unicodetouri(const rtl::OUString &rURL) +{ + // all the URLs are handled by office in UTF-8 ( and encoded with "%xx" codes based on UTF-8 ) + // so the Gnome FP related URLs should be converted accordingly + OString sURL = OUStringToOString(rURL, RTL_TEXTENCODING_UTF8); + INetURLObject aURL(rURL); + if (INET_PROT_FILE == aURL.GetProtocol()) + { + OUString aNewURL = Reference<uri::XExternalUriReferenceTranslator>(Reference<XMultiServiceFactory>(comphelper::getProcessServiceFactory(), UNO_QUERY_THROW)->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uri.ExternalUriReferenceTranslator"))), UNO_QUERY_THROW)->translateToExternal( rURL ); + + if( aNewURL.getLength() ) + { + // At this point the URL should contain ascii characters only actually + sURL = OUStringToOString( aNewURL, osl_getThreadTextEncoding() ); + } + } + return sURL; +} + +gboolean canceldialog(RunDialog *pDialog) +{ + pDialog->cancel(); + return false; +} + +extern "C" +{ + struct Display; + extern GdkDisplay* gdk_x11_lookup_xdisplay (void*xdisplay); +} + +RunDialog::RunDialog( GtkWidget *pDialog, uno::Reference< awt::XExtendedToolkit >& rToolkit ) : + cppu::WeakComponentImplHelper1< awt::XTopWindowListener >( maLock ), + mpDialog(pDialog), mpCreatedParent(NULL), mxToolkit(rToolkit) +{ + awt::SystemDependentXWindow aWindowHandle; + + if (mxToolkit.is()) + { + uno::Reference< awt::XTopWindow > xWindow(mxToolkit->getActiveTopWindow()); + if (xWindow.is()) + { + uno::Reference< awt::XSystemDependentWindowPeer > xSystemDepParent(xWindow, uno::UNO_QUERY); + if (xSystemDepParent.is()) + { + + sal_Int8 processID[16]; + + rtl_getGlobalProcessId( (sal_uInt8*)processID ); + uno::Sequence<sal_Int8> processIdSeq(processID, 16); + uno::Any anyHandle = xSystemDepParent->getWindowHandle(processIdSeq, SystemDependent::SYSTEM_XWINDOW); + + anyHandle >>= aWindowHandle; + } + } + } + + GdkThreadLock aLock; + + GdkDisplay *pDisplay = aWindowHandle.DisplayPointer ? gdk_x11_lookup_xdisplay(reinterpret_cast<void*>(static_cast<sal_IntPtr>(aWindowHandle.DisplayPointer))) : NULL; + GdkWindow* pParent = pDisplay ? gdk_window_lookup_for_display(pDisplay, aWindowHandle.WindowHandle) : NULL; + if (!pParent && pDisplay) + pParent = mpCreatedParent = gdk_window_foreign_new_for_display( pDisplay, aWindowHandle.WindowHandle); + if (pParent) + { + gtk_widget_realize(mpDialog); + gdk_window_set_transient_for(mpDialog->window, pParent); + } +} + + +RunDialog::~RunDialog() +{ + if (mpCreatedParent) + { + GdkThreadLock aLock; + gdk_window_destroy (mpCreatedParent); + } +} + +void SAL_CALL RunDialog::windowOpened( const ::com::sun::star::lang::EventObject& ) + throw (::com::sun::star::uno::RuntimeException) +{ + GdkThreadLock aLock; + g_timeout_add_full(G_PRIORITY_HIGH_IDLE, 0, (GSourceFunc)canceldialog, this, NULL); +} + +void RunDialog::cancel() +{ + GdkThreadLock aLock; + gtk_dialog_response( GTK_DIALOG( mpDialog ), GTK_RESPONSE_CANCEL ); + gtk_widget_hide( mpDialog ); +} + +gint RunDialog::run() +{ + if (mxToolkit.is()) + mxToolkit->addTopWindowListener(this); + + GdkThreadLock aLock; + gint nStatus = gtk_dialog_run( GTK_DIALOG( mpDialog ) ); + + if (mxToolkit.is()) + mxToolkit->removeTopWindowListener(this); + + if (nStatus != 1) //PLAY + gtk_widget_hide( mpDialog ); + + return nStatus; +} + +static void lcl_setGTKLanguage(const uno::Reference<lang::XMultiServiceFactory>& xServiceMgr) +{ + static bool bSet = false; + if (bSet) + return; + + OUString sUILocale; + try + { + uno::Reference<lang::XMultiServiceFactory> xConfigMgr = + uno::Reference<lang::XMultiServiceFactory>(xServiceMgr->createInstance( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationProvider"))), + UNO_QUERY_THROW ); + + Sequence< Any > theArgs(1); + theArgs[ 0 ] <<= OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.Linguistic/General")); + + uno::Reference< container::XNameAccess > xNameAccess = + uno::Reference< container::XNameAccess >(xConfigMgr->createInstanceWithArguments( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationAccess")), theArgs ), + UNO_QUERY_THROW ); + + if (xNameAccess.is()) + xNameAccess->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("UILocale"))) >>= sUILocale; + } catch (...) {} + + if (sUILocale.getLength()) + { + sUILocale = sUILocale.replace('-', '_'); + rtl::OUString envVar(RTL_CONSTASCII_USTRINGPARAM("LANGUAGE")); + osl_setEnvironment(envVar.pData, sUILocale.pData); + } + bSet = true; +} + +SalGtkPicker::SalGtkPicker(const uno::Reference<lang::XMultiServiceFactory>& xServiceMgr) : m_pDialog(0) +{ + lcl_setGTKLanguage(xServiceMgr); +} + +SalGtkPicker::~SalGtkPicker() +{ + if (m_pDialog) + { + GdkThreadLock aLock; + gtk_widget_destroy(m_pDialog); + } +} + +void SAL_CALL SalGtkPicker::implsetDisplayDirectory( const rtl::OUString& aDirectory ) + throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + OString aTxt = unicodetouri(aDirectory); + + if( aTxt.lastIndexOf('/') == aTxt.getLength() - 1 ) + aTxt = aTxt.copy( 0, aTxt.getLength() - 1 ); + + OSL_TRACE( "setting path to %s\n", aTxt.getStr() ); + + GdkThreadLock aLock; + gtk_file_chooser_set_current_folder_uri( GTK_FILE_CHOOSER( m_pDialog ), + aTxt.getStr() ); +} + +rtl::OUString SAL_CALL SalGtkPicker::implgetDisplayDirectory() throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + GdkThreadLock aLock; + + gchar* pCurrentFolder = + gtk_file_chooser_get_current_folder_uri( GTK_FILE_CHOOSER( m_pDialog ) ); + ::rtl::OUString aCurrentFolderName = uritounicode(pCurrentFolder); + g_free( pCurrentFolder ); + + return aCurrentFolderName; +} + +void SAL_CALL SalGtkPicker::implsetTitle( const rtl::OUString& aTitle ) throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + ::rtl::OString aWindowTitle = OUStringToOString( aTitle, RTL_TEXTENCODING_UTF8 ); + + GdkThreadLock aLock; + gtk_window_set_title( GTK_WINDOW( m_pDialog ), aWindowTitle.getStr() ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/gnome/SalGtkPicker.hxx b/fpicker/source/unx/gnome/SalGtkPicker.hxx new file mode 100644 index 000000000000..7b6a2e4850f7 --- /dev/null +++ b/fpicker/source/unx/gnome/SalGtkPicker.hxx @@ -0,0 +1,124 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SALGTKFPICKER_HXX_ +#define _SALGTKFPICKER_HXX_ + +//_____________________________________________________________________________ +// includes of other projects +//_____________________________________________________________________________ + +#include <osl/mutex.hxx> +#include <cppuhelper/compbase1.hxx> +#include <com/sun/star/ui/dialogs/XFilePicker.hpp> +#include <com/sun/star/ui/dialogs/XFilePicker2.hpp> +#include <com/sun/star/ui/dialogs/XFolderPicker.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/util/XCancellable.hpp> + +#include <com/sun/star/awt/XTopWindowListener.hpp> +#include <com/sun/star/awt/XExtendedToolkit.hpp> + +#include <gtk/gtk.h> +#include <gdk/gdkkeysyms.h> + +//---------------------------------------------------------- +// class declaration +//---------------------------------------------------------- + +class SalGtkPicker +{ + public: + SalGtkPicker(const ::com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory>& xServiceMgr); + virtual ~SalGtkPicker(); + protected: + osl::Mutex m_rbHelperMtx; + GtkWidget *m_pDialog; + protected: + virtual void SAL_CALL implsetTitle( const ::rtl::OUString& aTitle ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL implsetDisplayDirectory( const rtl::OUString& rDirectory ) + throw( com::sun::star::lang::IllegalArgumentException, com::sun::star::uno::RuntimeException ); + + virtual rtl::OUString SAL_CALL implgetDisplayDirectory( ) + throw( com::sun::star::uno::RuntimeException ); + static rtl::OUString uritounicode(const gchar *pIn); + static rtl::OString unicodetouri(const rtl::OUString &rURL); +}; + +class GdkThreadLock +{ +public: + GdkThreadLock() { gdk_threads_enter(); } + ~GdkThreadLock() { gdk_threads_leave(); } +}; + +//Run the Gtk Dialog. Watch for any "new windows" created while we're +//executing and consider that a CANCEL event to avoid e.g. "file cannot be opened" +//modal dialogs and this one getting locked if some other API call causes this +//to happen while we're opened waiting for user input, e.g. +//https://bugzilla.redhat.com/show_bug.cgi?id=441108 +class RunDialog : + public cppu::WeakComponentImplHelper1< ::com::sun::star::awt::XTopWindowListener > +{ +private: + osl::Mutex maLock; + GtkWidget *mpDialog; + GdkWindow *mpCreatedParent; + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XExtendedToolkit> mxToolkit; +public: + + // XTopWindowListener + using cppu::WeakComponentImplHelperBase::disposing; + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& ) + throw(::com::sun::star::uno::RuntimeException) {} + virtual void SAL_CALL windowOpened( const ::com::sun::star::lang::EventObject& e ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL windowClosing( const ::com::sun::star::lang::EventObject& ) + throw (::com::sun::star::uno::RuntimeException) {} + virtual void SAL_CALL windowClosed( const ::com::sun::star::lang::EventObject& ) + throw (::com::sun::star::uno::RuntimeException) {} + virtual void SAL_CALL windowMinimized( const ::com::sun::star::lang::EventObject& ) + throw (::com::sun::star::uno::RuntimeException) {} + virtual void SAL_CALL windowNormalized( const ::com::sun::star::lang::EventObject& ) + throw (::com::sun::star::uno::RuntimeException) {} + virtual void SAL_CALL windowActivated( const ::com::sun::star::lang::EventObject& ) + throw (::com::sun::star::uno::RuntimeException) {} + virtual void SAL_CALL windowDeactivated( const ::com::sun::star::lang::EventObject& ) + throw (::com::sun::star::uno::RuntimeException) {} +public: + RunDialog(GtkWidget *pDialog, ::com::sun::star::uno::Reference< ::com::sun::star::awt::XExtendedToolkit > &rToolkit); + gint run(); + void cancel(); + ~RunDialog(); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/gnome/eventnotification.hxx b/fpicker/source/unx/gnome/eventnotification.hxx new file mode 100644 index 000000000000..3866ca59946f --- /dev/null +++ b/fpicker/source/unx/gnome/eventnotification.hxx @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _EVENTNOTIFICATION_HXX_ +#define _EVENTNOTIFICATION_HXX_ + +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/uno/Reference.hxx> + +//----------------------------------- +// encapsulate a filepicker event +// notification, because there are +// two types of filepicker notifications +// with and without parameter +// this is an application of the +// "command" pattern see GoF +//----------------------------------- + +class CEventNotification +{ +public: + virtual ~CEventNotification() { }; + + virtual void SAL_CALL notifyEventListener( com::sun::star::uno::Reference< com::sun::star::uno::XInterface > xListener ) = 0; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/gnome/fps-gnome-ucd.txt b/fpicker/source/unx/gnome/fps-gnome-ucd.txt new file mode 100644 index 000000000000..4a84215dc960 --- /dev/null +++ b/fpicker/source/unx/gnome/fps-gnome-ucd.txt @@ -0,0 +1,13 @@ +[ComponentDescriptor] +ImplementationName=com.sun.star.ui.dialogs.SalGtkFilePicker +ComponentName=fps_gnome.uno.so +LoaderName=com.sun.star.loader.SharedLibrary +[SupportedServices] +com.sun.star.ui.dialogs.GtkFilePicker + +[ComponentDescriptor] +ImplementationName=com.sun.star.ui.dialogs.SalGtkFolderPicker +ComponentName=fps_gnome.uno.so +LoaderName=com.sun.star.loader.SharedLibrary +[SupportedServices] +com.sun.star.ui.dialogs.GtkFolderPicker diff --git a/fpicker/source/unx/gnome/fps_gnome.xml b/fpicker/source/unx/gnome/fps_gnome.xml new file mode 100644 index 000000000000..d4dd4f9231d6 --- /dev/null +++ b/fpicker/source/unx/gnome/fps_gnome.xml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + <module-name>fps</module-name> + <component-description> + <author> Jan Holesovsky </author> + <name> com.sun.star.comp.ui.dialogs.FilePicker </name> + <description> + The Gnome implementation of the FilePicker service. + </description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language> c++ </language> + <status value="beta"/> + <supported-service> com.sun.star.ui.dialogs.FilePicker </supported-service> + <service-dependency>...</service-dependency> + <type> com.sun.star.ui.dialogs.XExecutableDialog </type> + <type> com.sun.star.ui.dialogs.XFilePicker </type> + <type> com.sun.star.ui.dialogs.XFilterManager </type> + <type> com.sun.star.ui.dialogs.XFilterGroupManager </type> + <type> com.sun.star.ui.dialogs.XFilePickerListener </type> + <type> com.sun.star.ui.dialogs.ExecutableDialogException </type> + <type> com.sun.star.ui.dialogs.XFilePickerNotifier </type> + <type> com.sun.star.ui.dialogs.XFilePickerControlAccess </type> + <type> com.sun.star.ui.dialogs.XFilePreview </type> + <type> com.sun.star.ui.dialogs.ExtendedFilePickerElementIds </type> + <type> com.sun.star.ui.dialogs.ExecutableDialogResults </type> + <type> com.sun.star.ui.dialogs.FilePickerEvent </type> + <type> com.sun.star.ui.dialogs.CommonFilePickerElementIds </type> + <type> com.sun.star.ui.dialogs.ListboxControlActions </type> + <type> com.sun.star.ui.dialogs.TemplateDescription </type> + <type> com.sun.star.ui.dialogs.FilePreviewImageFormats </type> + <type> com.sun.star.util.XCancellable </type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.lang.IllegalArgumentException </type> + <type> com.sun.star.uno.TypeClass </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.uno.XAggregation </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.container.XSet </type> + </component-description> + <component-description> + <author> Caolan McNamara </author> + <name> com.sun.star.comp.ui.dialogs.FolderPicker </name> + <description> + The Gnome implementation of the FolderPicker service. + </description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language> c++ </language> + <status value="beta"/> + <supported-service> com.sun.star.ui.dialogs.FolderPicker </supported-service> + <service-dependency>...</service-dependency> + <type> com.sun.star.ui.dialogs.XExecutableDialog </type> + <type> com.sun.star.ui.dialogs.XFolderPicker </type> + <type> com.sun.star.ui.dialogs.ExecutableDialogException </type> + <type> com.sun.star.ui.dialogs.ExecutableDialogResults </type> + <type> com.sun.star.util.XCancellable </type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.lang.IllegalArgumentException </type> + <type> com.sun.star.uno.TypeClass </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.uno.XAggregation </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.container.XSet </type> + </component-description> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> sal </project-build-dependency> + <runtime-module-dependency> cppuhelper </runtime-module-dependency> + <runtime-module-dependency> cppu2 </runtime-module-dependency> + <runtime-module-dependency> sal2 </runtime-module-dependency> +</module-description> diff --git a/fpicker/source/unx/gnome/makefile.mk b/fpicker/source/unx/gnome/makefile.mk new file mode 100644 index 000000000000..04c6e650ff6f --- /dev/null +++ b/fpicker/source/unx/gnome/makefile.mk @@ -0,0 +1,98 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=fpicker +TARGET=fps_gnome.uno +LIBTARGET=NO +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +DLLPRE= + +# ------------------------------------------------------------------ + +.IF "$(ENABLE_GTK)" != "TRUE" + +dummy: + @echo "Nothing to build. GUIBASE == $(GUIBASE), WITH_WIDGETSET == $(WITH_WIDGETSET)" + +.ELSE # we build for GNOME + +PKGCONFIG_MODULES=gtk+-2.0 +.INCLUDE : pkg_config.mk + +# check gtk version +GTK_TWO_FOUR:=$(shell @$(PKG_CONFIG) --exists 'gtk+-2.0 >= 2.4.0' && echo ok) +.IF "$(GTK_TWO_FOUR)" != "ok" + +dummy: + @echo "Cannot build gtk filepicker because" + @$(PKG_CONFIG) --print-errors --exists 'gtk+-2.0 >= 2.4.0' + +.ELSE + +CFLAGS+= $(WIDGETSET_CFLAGS) +CFLAGS+= $(PKGCONFIG_CFLAGS) + +# --- Files -------------------------------------------------------- + +SLOFILES =\ + $(SLO)$/SalGtkPicker.obj \ + $(SLO)$/SalGtkFilePicker.obj \ + $(SLO)$/SalGtkFolderPicker.obj \ + $(SLO)$/resourceprovider.obj \ + $(SLO)$/FPentry.obj + +SHL1NOCHECK=TRUE +SHL1TARGET= $(TARGET) +SHL1OBJS= $(SLOFILES) +SHL1STDLIBS=\ + $(VCLLIB) \ + $(TOOLSLIB) \ + $(CPPUHELPERLIB) \ + $(COMPHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) \ + $(PKGCONFIG_LIBS) + +.IF "$(OS)"=="SOLARIS" +LINKFLAGSDEFS= +.ENDIF # "$(OS)"=="SOLARIS" + +SHL1VERSIONMAP=$(SOLARENV)/src/component.map +DEF1NAME=$(SHL1TARGET) + +.ENDIF # GTK_TWO_FOUR +.ENDIF # "$(GUIBASE)" != "unx" || "$(WITH_WIDGETSET)" != "gnome" + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/fpicker/source/unx/gnome/resourceprovider.cxx b/fpicker/source/unx/gnome/resourceprovider.cxx new file mode 100644 index 000000000000..2fe687937103 --- /dev/null +++ b/fpicker/source/unx/gnome/resourceprovider.cxx @@ -0,0 +1,229 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ +#include <osl/diagnose.h> +#include <rtl/ustrbuf.hxx> +#include "resourceprovider.hxx" +#include <osl/mutex.hxx> +#include <vcl/svapp.hxx> +#include <tools/resmgr.hxx> +#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> + +#include <svtools/svtools.hrc> +#include <svtools/filedlg2.hrc> + +//------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------ + +using rtl::OUString; +using namespace ::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds; +using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds; + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +static const char* RES_NAME = "fps_office"; +static const char* OTHER_RES_NAME = "svt"; + +//------------------------------------------------------------ +// we have to translate control ids to resource ids +//------------------------------------------------------------ + +struct _Entry +{ + sal_Int32 ctrlId; + sal_Int16 resId; +}; + +_Entry CtrlIdToResIdTable[] = { + { CHECKBOX_AUTOEXTENSION, STR_SVT_FILEPICKER_AUTO_EXTENSION }, + { CHECKBOX_PASSWORD, STR_SVT_FILEPICKER_PASSWORD }, + { CHECKBOX_FILTEROPTIONS, STR_SVT_FILEPICKER_FILTER_OPTIONS }, + { CHECKBOX_READONLY, STR_SVT_FILEPICKER_READONLY }, + { CHECKBOX_LINK, STR_SVT_FILEPICKER_INSERT_AS_LINK }, + { CHECKBOX_PREVIEW, STR_SVT_FILEPICKER_SHOW_PREVIEW }, + { PUSHBUTTON_PLAY, STR_SVT_FILEPICKER_PLAY }, + { LISTBOX_VERSION_LABEL, STR_SVT_FILEPICKER_VERSION }, + { LISTBOX_TEMPLATE_LABEL, STR_SVT_FILEPICKER_TEMPLATES }, + { LISTBOX_IMAGE_TEMPLATE_LABEL, STR_SVT_FILEPICKER_IMAGE_TEMPLATE }, + { CHECKBOX_SELECTION, STR_SVT_FILEPICKER_SELECTION }, + { FOLDERPICKER_TITLE, STR_SVT_FOLDERPICKER_DEFAULT_TITLE }, + { FOLDER_PICKER_DEF_DESCRIPTION, STR_SVT_FOLDERPICKER_DEFAULT_DESCRIPTION }, + { FILE_PICKER_OVERWRITE, STR_SVT_ALREADYEXISTOVERWRITE }, + { FILE_PICKER_ALLFORMATS, STR_SVT_ALLFORMATS } +}; + +_Entry OtherCtrlIdToResIdTable[] = { + { FILE_PICKER_TITLE_OPEN, STR_FILEDLG_OPEN }, + { FILE_PICKER_TITLE_SAVE, STR_FILEDLG_SAVE }, + { FILE_PICKER_FILE_TYPE, STR_FILEDLG_TYPE }, +}; + + +const sal_Int32 SIZE_TABLE = sizeof( CtrlIdToResIdTable ) / sizeof( _Entry ); +const sal_Int32 OTHER_SIZE_TABLE = sizeof( OtherCtrlIdToResIdTable ) / sizeof( _Entry ); + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +sal_Int16 CtrlIdToResId( sal_Int32 aControlId ) +{ + sal_Int16 aResId = -1; + + for ( sal_Int32 i = 0; i < SIZE_TABLE; i++ ) + { + if ( CtrlIdToResIdTable[i].ctrlId == aControlId ) + { + aResId = CtrlIdToResIdTable[i].resId; + break; + } + } + + return aResId; +} + +sal_Int16 OtherCtrlIdToResId( sal_Int32 aControlId ) +{ + sal_Int16 aResId = -1; + + for ( sal_Int32 i = 0; i < OTHER_SIZE_TABLE; i++ ) + { + if ( OtherCtrlIdToResIdTable[i].ctrlId == aControlId ) + { + aResId = OtherCtrlIdToResIdTable[i].resId; + break; + } + } + + return aResId; +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +class CResourceProvider_Impl +{ +public: + + //------------------------------------- + // + //------------------------------------- + + CResourceProvider_Impl( ) + { + m_ResMgr = ResMgr::CreateResMgr( RES_NAME ); + m_OtherResMgr = ResMgr::CreateResMgr( OTHER_RES_NAME ); + } + + //------------------------------------- + // + //------------------------------------- + + ~CResourceProvider_Impl( ) + { + delete m_ResMgr; + delete m_OtherResMgr; + } + + //------------------------------------- + // + //------------------------------------- + + OUString getResString( sal_Int16 aId ) + { + String aResString; + OUString aResOUString; + + try + { + OSL_ASSERT( m_ResMgr && m_OtherResMgr ); + + // translate the control id to a resource id + sal_Int16 aResId = CtrlIdToResId( aId ); + if ( aResId > -1 ) + aResString = String( ResId( aResId, *m_ResMgr ) ); + else + { + aResId = OtherCtrlIdToResId( aId ); + if ( aResId > -1 ) + aResString = String( ResId( aResId, *m_OtherResMgr ) ); + } + if ( aResId > -1 ) + aResOUString = OUString( aResString ); + } + catch(...) + { + } + + return aResOUString; + } + +public: + ResMgr* m_ResMgr; + ResMgr* m_OtherResMgr; +}; + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +CResourceProvider::CResourceProvider( ) : + m_pImpl( new CResourceProvider_Impl() ) +{ +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +CResourceProvider::~CResourceProvider( ) +{ + delete m_pImpl; +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +OUString CResourceProvider::getResString( sal_Int32 aId ) +{ + return m_pImpl->getResString( aId ).replace('~', '_'); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/gnome/resourceprovider.hxx b/fpicker/source/unx/gnome/resourceprovider.hxx new file mode 100644 index 000000000000..5bbbbfd68e7e --- /dev/null +++ b/fpicker/source/unx/gnome/resourceprovider.hxx @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _RESOURCEPROVIDER_HXX_ +#define _RESOURCEPROVIDER_HXX_ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <sal/types.h> + +#include <rtl/ustring.hxx> + +#define FOLDERPICKER_TITLE 500 +#define FOLDER_PICKER_DEF_DESCRIPTION 501 +#define FILE_PICKER_TITLE_OPEN 502 +#define FILE_PICKER_TITLE_SAVE 503 +#define FILE_PICKER_FILE_TYPE 504 +#define FILE_PICKER_OVERWRITE 505 +#define FILE_PICKER_ALLFORMATS 506 + +//------------------------------------------------------------------------ +// deklarations +//------------------------------------------------------------------------ + +class CResourceProvider_Impl; + +class CResourceProvider +{ +public: + CResourceProvider( ); + ~CResourceProvider( ); + + rtl::OUString getResString( sal_Int32 aId ); + +private: + CResourceProvider_Impl* m_pImpl; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/kde/kdecommandthread.cxx b/fpicker/source/unx/kde/kdecommandthread.cxx new file mode 100644 index 000000000000..3e7df60a4751 --- /dev/null +++ b/fpicker/source/unx/kde/kdecommandthread.cxx @@ -0,0 +1,177 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <kdecommandthread.hxx> + +#include <qstringlist.h> + +#include <kapplication.h> + +#include <iostream> + +////////////////////////////////////////////////////////////////////////// +// CommandEvent +////////////////////////////////////////////////////////////////////////// + +KDECommandEvent::KDECommandEvent( const QString &qCommand, QStringList *pStringList ) + : QCustomEvent( TypeId, pStringList ), + m_eCommand( Unknown ) +{ + struct { + const char *pName; + CommandEventType eType; + } *pIdx, pMapping[] = + { + { "appendControl", AppendControl }, + { "enableControl", EnableControl }, + { "getValue", GetValue }, + { "setValue", SetValue }, + { "appendFilter", AppendFilter }, + { "appendFilterGroup", AppendFilterGroup }, + { "getCurrentFilter", GetCurrentFilter }, + { "setCurrentFilter", SetCurrentFilter }, + { "getDirectory", GetDirectory }, + { "setDirectory", SetDirectory }, + { "getFiles", GetFiles }, + { "setTitle", SetTitle }, + { "setType", SetType }, + { "setDefaultName", SetDefaultName }, + { "setMultiSelection", SetMultiSelection }, + { "exec", Exec }, + { 0, Unknown } + }; + + for ( pIdx = pMapping; pIdx->pName && qCommand != pIdx->pName; ++pIdx ) + ; + + m_eCommand = pIdx->eType; +} + +////////////////////////////////////////////////////////////////////////// +// CommandThread +////////////////////////////////////////////////////////////////////////// + +KDECommandThread::KDECommandThread( QWidget *pObject ) + : m_pObject( pObject ) +{ +} + +KDECommandThread::~KDECommandThread() +{ +} + +void KDECommandThread::run() +{ + QTextIStream qStream( stdin ); + qStream.setEncoding( QTextStream::UnicodeUTF8 ); + + QString qLine; + bool bQuit = false; + while ( !bQuit && !qStream.atEnd() ) + { + qLine = qStream.readLine(); + handleCommand( qLine, bQuit ); + } +} + +void KDECommandThread::handleCommand( const QString &rString, bool &bQuit ) +{ + QMutexLocker qMutexLocker( &m_aMutex ); + +#if OSL_DEBUG_LEVEL > 0 + ::std::cerr << "kdefilepicker received: " << rString.latin1() << ::std::endl; +#endif + + bQuit = false; + QStringList *pTokens = tokenize( rString ); + + if ( !pTokens ) + return; + if ( pTokens->empty() ) + { + delete pTokens, pTokens = NULL; + return; + } + + QString qCommand = pTokens->front(); + pTokens->pop_front(); + + if ( qCommand == "exit" ) + { + bQuit = true; + kapp->exit(); + kapp->wakeUpGuiThread(); + } + else + kapp->postEvent( m_pObject, new KDECommandEvent( qCommand, pTokens ) ); +} + +QStringList* KDECommandThread::tokenize( const QString &rString ) +{ + // Commands look like: + // command arg1 arg2 arg3 ... + // Args may be enclosed in '"', if they contain spaces. + + QStringList *pList = new QStringList(); + + QString qBuffer; + qBuffer.reserve( 1024 ); + + const QChar *pUnicode = rString.unicode(); + const QChar *pEnd = pUnicode + rString.length(); + bool bQuoted = false; + + for ( ; pUnicode != pEnd; ++pUnicode ) + { + if ( *pUnicode == '\\' ) + { + ++pUnicode; + if ( pUnicode != pEnd ) + { + if ( *pUnicode == 'n' ) + qBuffer.append( '\n' ); + else + qBuffer.append( *pUnicode ); + } + } + else if ( *pUnicode == '"' ) + bQuoted = !bQuoted; + else if ( *pUnicode == ' ' && !bQuoted ) + { + pList->push_back( qBuffer ); + qBuffer.setLength( 0 ); + } + else + qBuffer.append( *pUnicode ); + } + pList->push_back( qBuffer ); + + return pList; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/kde/kdecommandthread.hxx b/fpicker/source/unx/kde/kdecommandthread.hxx new file mode 100644 index 000000000000..7486bf9192f6 --- /dev/null +++ b/fpicker/source/unx/kde/kdecommandthread.hxx @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _KDECOMMANDTHREAD_HXX_ +#define _KDECOMMANDTHREAD_HXX_ + +#include <qevent.h> +#include <qmutex.h> +#include <qthread.h> + +class KDECommandEvent : public QCustomEvent +{ +public: + enum CommandEventType { + Unknown = 0, + + AppendControl, + EnableControl, + GetValue, + SetValue, + + AppendFilter, + AppendFilterGroup, + UpdateFilters, + GetCurrentFilter, + SetCurrentFilter, + + GetDirectory, + SetDirectory, + + GetFiles, + + SetTitle, + SetType, + SetDefaultName, + SetMultiSelection, + + Exec + }; + static const QEvent::Type TypeId = (QEvent::Type) ( (int) QEvent::User + 42 /*random magic value*/ ); + +protected: + CommandEventType m_eCommand; + +public: + KDECommandEvent( const QString &qCommand, QStringList *pStringList ); + + CommandEventType command() const { return m_eCommand; } + QStringList* stringList() { return static_cast< QStringList* >( data() ); } +}; + +class KDECommandThread : public QThread +{ +protected: + QObject *m_pObject; + + QMutex m_aMutex; + +public: + KDECommandThread( QWidget *pObject ); + virtual ~KDECommandThread(); + + virtual void run(); + +protected: + void handleCommand( const QString &rString, bool &bQuit ); + QStringList* tokenize( const QString &rString ); +}; + +#endif // _KDECOMMANDTHREAD_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/kde/kdefilepicker.cxx b/fpicker/source/unx/kde/kdefilepicker.cxx new file mode 100644 index 000000000000..35e60d256d2f --- /dev/null +++ b/fpicker/source/unx/kde/kdefilepicker.cxx @@ -0,0 +1,732 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <kdecommandthread.hxx> +#include <kdefilepicker.hxx> + +#include <qcheckbox.h> +#include <qcombobox.h> +#include <qgrid.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qobjectlist.h> +#include <qpushbutton.h> +#include <qregexp.h> +#include <qvbox.h> + +#ifdef QT_NO_EMIT +#define emit +#endif + +#include <kdeversion.h> +#include <kdiroperator.h> +#include <kfiledialog.h> +#include <kfilefiltercombo.h> +#include <kio/netaccess.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <ktempfile.h> + +#include <algorithm> +#include <iostream> + +////////////////////////////////////////////////////////////////////////// +// KDEFileDialog +////////////////////////////////////////////////////////////////////////// + +KDEFileDialog::KDEFileDialog( const QString &startDir, const QString &filter, + QWidget *parent, const char *name ) + : KFileDialog( startDir, filter, parent, name, true, m_pCustomWidget = new QVBox() ), + m_pCombosAndButtons( new QHBox( m_pCustomWidget ) ), + m_pLabels( new QVBox( m_pCombosAndButtons ) ), + m_pComboBoxes( new QVBox( m_pCombosAndButtons ) ), + m_pPushButtons( new QVBox( m_pCombosAndButtons ) ), + m_pCheckBoxes( new QGrid( 2, m_pCustomWidget ) ), + m_bIsSave( false ), + m_bIsExecuting( false ), + m_bCanNotifySelection( true ) +{ + connect( this, SIGNAL( fileHighlighted( const QString & ) ), + this, SLOT( fileHighlightedCommand( const QString & ) ) ); + + connect( this, SIGNAL( selectionChanged() ), + this, SLOT( selectionChangedCommand() ) ); + + m_pCustomWidget->setSpacing( KDialog::spacingHint() ); + m_pCombosAndButtons->setSpacing( KDialog::spacingHint() ); + + updateCustomWidgetLayout(); +} + +KDEFileDialog::~KDEFileDialog() +{ +} + +void KDEFileDialog::resizeEvent( QResizeEvent *pEvent ) +{ + KFileDialog::resizeEvent( pEvent ); + + updateCustomWidgetLayout(); +} + +void KDEFileDialog::showEvent( QShowEvent *pEvent ) +{ + KFileDialog::showEvent( pEvent ); + + updateCustomWidgetLayout(); +} + +void KDEFileDialog::updateCustomWidgetLayout() +{ + QPoint qReferencePoint = filterWidget->mapTo( this, QPoint( 0, 0 ) ); + QPoint qCustomPoint = m_pCustomWidget->mapTo( this, QPoint( 0, 0 ) ); + + int nLeft = qReferencePoint.x() - qCustomPoint.x(); + int nRight = m_pCustomWidget->width() - filterWidget->width() - nLeft; + + nLeft -= KDialog::spacingHint(); + nRight -= KDialog::spacingHint(); + m_pLabels->setFixedWidth( ( nLeft > 0 )? nLeft: 80 ); + // FIXME The following call sets the width of m_pPushButtons all right, + // but it also increases the width of m_pComboBoxes rapidly. Can we do + // anything about it? + m_pPushButtons->setFixedWidth( ( nRight > 0 )? nRight: 100 ); +} + +void KDEFileDialog::customEvent( QCustomEvent *pEvent ) +{ + if ( pEvent && pEvent->type() == KDECommandEvent::TypeId ) + { + KDECommandEvent *pCommandEvent = static_cast< KDECommandEvent* >( pEvent ); + QStringList *pStringList = pCommandEvent->stringList(); + + int nListSize = -1; + if ( pStringList ) + nListSize = pStringList->size(); + + switch ( pCommandEvent->command() ) + { + case KDECommandEvent::AppendControl: + if ( nListSize >= 3 ) + { + appendControl( (*pStringList)[0], (*pStringList)[1], (*pStringList)[2] ); + } + break; + case KDECommandEvent::EnableControl: + if ( nListSize >= 2 ) + { + enableControl( (*pStringList)[0], (*pStringList)[1] ); + } + break; + case KDECommandEvent::GetValue: + if ( nListSize >= 2 ) + { + getValue( (*pStringList)[0], (*pStringList)[1] ); + } + break; + case KDECommandEvent::SetValue: + if ( nListSize >= 2 ) + { + QStringList qStringList = (*pStringList); + qStringList.pop_front(); + qStringList.pop_front(); + + setValue( (*pStringList)[0], (*pStringList)[1], qStringList ); + } + break; + case KDECommandEvent::AppendFilter: + if ( nListSize >= 2 ) + { + appendFilter( (*pStringList)[0], (*pStringList)[1] ); + + // update the filters widget + setFilter( filters() ); + } + break; + case KDECommandEvent::AppendFilterGroup: + if ( nListSize >= 1 ) + { + QStringList::const_iterator it = pStringList->begin(); + ++it; // We ignore the filter group name + + while ( it != pStringList->end() ) + { + QString qTitle = *it; + ++it; + if ( it != pStringList->end() ) + { + appendFilter( qTitle, (*it) ); + ++it; + } + } + + // update the filters widget + setFilter( filters() ); + } + break; + case KDECommandEvent::GetCurrentFilter: + { + QString qCurrentFilter = filterWidget->currentText(); + sendCommand( "currentFilter " + escapeString( qCurrentFilter ) ); + } + break; + case KDECommandEvent::SetCurrentFilter: + if ( nListSize >= 1 ) + { + static_cast< KDEFileFilterComboHack* >( filterWidget )->setCurrentFilter( pStringList->front() ); + } + break; + case KDECommandEvent::GetDirectory: + { + QString qDirectory = baseURL().url(); + if ( qDirectory.startsWith( "file:/" ) && qDirectory.mid( 6, 1 ) != "/" ) + qDirectory.replace( "file:/", "file:///" ); + sendCommand( "currentDirectory " + escapeString( qDirectory ) ); + } + break; + case KDECommandEvent::SetDirectory: + if ( nListSize >= 1 ) + { + setURL( pStringList->front() ); + } + break; + case KDECommandEvent::GetFiles: + { + QString qString; + qString.reserve( 1024 ); + + qString.append( "files" ); + + if ( result() == QDialog::Accepted ) + { + KURL::List qList( selectedURLs() ); + for ( KURL::List::const_iterator it = qList.begin(); it != qList.end(); ++it ) + appendURL( qString, (*it) ); + } + else + { + // we have to return the selected files anyway + const KFileItemList *pItems = ops->selectedItems(); + for ( KFileItemListIterator it( *pItems ); it.current(); ++it ) + appendURL( qString, (*it)->url() ); + } + + sendCommand( qString ); + setCanNotifySelection( true ); + } + break; + case KDECommandEvent::SetTitle: + if ( nListSize >= 1 ) + { + setCaption( pStringList->front() ); + } + break; + case KDECommandEvent::SetType: + if ( nListSize >= 1 ) + { + QString qType( pStringList->front() ); + if ( qType == "open" ) + { + setIsSave( false ); + setCaption( i18n( "Open" ) ); + } + else if ( qType == "save" ) + { + setIsSave( true ); + setCaption( i18n( "Save As" ) ); + } + } + break; + case KDECommandEvent::SetDefaultName: + if ( nListSize >= 1 ) + { + setKeepLocation( true ); + setSelection( pStringList->front() ); + } + break; + case KDECommandEvent::SetMultiSelection: + if ( nListSize >= 1 ) + { + if ( pStringList->front() == "true" ) + setMode( KFile::Files ); + else + setMode( KFile::File ); + } + break; + case KDECommandEvent::Exec: + { + filterWidget->setEditable( false ); + setIsExecuting( true ); + bool bCanExit = false; + do { + setCanNotifySelection( true ); + exec(); + + KURL qLocalSelectedURL = mostLocalURL( selectedURL() ); + QString qProtocol( qLocalSelectedURL.protocol() ); + + if ( isSave() && result() == QDialog::Accepted ) + { + if ( qProtocol == "file" ) + { + QString qFileName( addExtension( qLocalSelectedURL.path() ) ); + bCanExit = + !QFile::exists( qFileName ) || + ( KMessageBox::warningYesNo( 0, + i18n( "A file named \"%1\" already exists. " + "Are you sure you want to overwrite it?" ).arg( qFileName ), + i18n( "Overwrite File?" ), + i18n( "Overwrite" ), KStdGuiItem::cancel() ) == KMessageBox::Yes ); + } + else if ( !isSupportedProtocol( qProtocol ) ) + { + KMessageBox::sorry( 0, + i18n( "Saving using protocol \"%1\" is not supported." ).arg( qProtocol ) ); + bCanExit = false; + } + else + bCanExit = true; + } + else if ( !isSave() && result() == QDialog::Accepted && !isSupportedProtocol( qProtocol ) ) + { + KMessageBox::information( 0, + i18n( "Protocol \"%1\" is supported only partially. " + "Local copy of the file will be created." ).arg( qProtocol ) ); + bCanExit = true; + } + else + bCanExit = true; + } while ( !bCanExit ); + setIsExecuting( false ); + + if ( result() == QDialog::Accepted ) + sendCommand( "accept" ); + else + sendCommand( "reject" ); + } + break; + default: + break; + } + + // FIXME Some cleanup of pEvent? delete something, etc.? + } +} + +void KDEFileDialog::appendControl( const QString &rId, const QString &rType, const QString &rTitle ) +{ + QString qLabel( rTitle ); + qLabel.replace( '~', '&' ); + + if ( rType == "checkbox" ) + { + QCheckBox *pCheckBox = new QCheckBox( qLabel, m_pCheckBoxes, rId.utf8() ); + + pCheckBox->setEnabled( true ); + pCheckBox->setChecked( false ); + } + else if ( rType == "listbox" ) + { + QLabel *pComboLabel = new QLabel( qLabel, m_pLabels ); + QComboBox *pComboBox = new QComboBox( m_pComboBoxes, rId.utf8() ); + + pComboLabel->setBuddy( pComboBox ); + pComboBox->setEnabled( true ); + } + else if ( rType == "pushbutton" ) + { + QPushButton *pPushButton = new QPushButton( qLabel, m_pPushButtons, rId.utf8() ); + pPushButton->setEnabled( true ); + } +} + +QWidget* KDEFileDialog::findControl( const QString &rId ) const +{ + QObjectList *pList = m_pCustomWidget->queryList(); + QCString qName( rId.utf8() ); + QObjectList::const_iterator it = pList->begin(); + + for ( ; it != pList->end() && qName != (*it)->name(); ++it ) + ; + + QWidget *pWidget = NULL; + if ( it != pList->end() ) + pWidget = static_cast< QWidget* >( *it ); + + delete pList; + + return pWidget; +} + +void KDEFileDialog::enableControl( const QString &rId, const QString &rValue ) +{ + QWidget *pWidget = findControl( rId ); + + if ( pWidget ) + pWidget->setEnabled( rValue.lower() == "true" ); +} + +void KDEFileDialog::getValue( const QString &rId, const QString &rAction ) +{ + QWidget *pWidget = findControl( rId ); + QString qString; + qString.reserve( 1024 ); + qString.append( "value" ); + + if ( pWidget ) + { + QCString qClassName = pWidget->className(); + if ( qClassName == "QCheckBox" ) + { + QCheckBox *pCheckBox = static_cast< QCheckBox* >( pWidget ); + + if ( pCheckBox->isChecked() ) + qString.append( " bool true" ); + else + qString.append( " bool false" ); + } + else if ( qClassName == "QComboBox" ) + { + QComboBox *pComboBox = static_cast< QComboBox* >( pWidget ); + if ( rAction == "getItems" ) + { + qString.append( " stringList" ); + for ( int nIdx = 0; nIdx < pComboBox->count(); ++nIdx ) + { + qString.append( ' ' ); + appendEscaped( qString, pComboBox->text( nIdx ) ); + } + } + else if ( rAction == "getSelectedItem" ) + { + qString.append( " string " ); + appendEscaped( qString, pComboBox->currentText() ); + } + else if ( rAction == "getSelectedItemIndex" ) + { + qString.append( " int " ); + qString.append( QString().setNum( pComboBox->currentItem() ) ); + } + // TODO getHelpURL + } + // TODO push button + } + + sendCommand( qString ); +} + +void KDEFileDialog::setValue( const QString &rId, const QString &rAction, const QStringList &rValue ) +{ + QWidget *pWidget = findControl( rId ); + + if ( pWidget ) + { + QCString qClassName = pWidget->className(); + if ( qClassName == "QCheckBox" ) + { + QCheckBox *pCheckBox = static_cast< QCheckBox* >( pWidget ); + + bool bValue = ( !rValue.isEmpty() ) && ( rValue.front().lower() == "true" ); + pCheckBox->setChecked( bValue ); + } + else if ( qClassName == "QComboBox" ) + { + QComboBox *pComboBox = static_cast< QComboBox* >( pWidget ); + if ( rAction == "addItem" ) + { + if ( !rValue.isEmpty() ) + pComboBox->insertItem( rValue.front() ); + } + else if ( rAction == "addItems" ) + { + pComboBox->insertStringList( rValue ); + } + else if ( rAction == "deleteItem" ) + { + if ( !rValue.isEmpty() ) + pComboBox->removeItem( rValue.front().toInt() ); + } + else if ( rAction == "deleteItems" ) + { + pComboBox->clear(); + } + else if ( rAction == "setSelectedItem" ) + { + if ( !rValue.isEmpty() ) + pComboBox->setCurrentItem( rValue.front().toInt() ); + } + // FIXME setHelpURL is ignored + } + // TODO push button + } +} + +void KDEFileDialog::appendFilter( const QString &rTitle, const QString &rFilter ) +{ + // Filters are separated by ';' + QString qFilter( rFilter ); + qFilter.replace( QChar( ';' ), QChar( ' ' ) ).replace( "*.*", "*" ); + + // Workaround for too wide <All formats> (*.bmp;...) entry + QString qTitle( rTitle ); + qTitle.replace( QRegExp( "^<([^>]*)> \\(.*" ), "<\\1>" ); + + m_aFilters.push_back( qMakePair( qTitle, qFilter ) ); +} + +QString KDEFileDialog::filters() const +{ + QString qString, qTmp; + bool bFirstFilter = true; + + for ( FilterList::const_iterator it = m_aFilters.begin(); it != m_aFilters.end(); ++it ) + { + if ( bFirstFilter ) + bFirstFilter = false; + else + qString.append( '\n' ); + + qString.append( (*it).second ); + qString.append( '|' ); + + qTmp = (*it).first; + qString.append( qTmp.replace( '/', "\\/" ) ); + } + + return qString; +} + +QString KDEFileDialog::addExtension( const QString &rFileName ) const +{ + if ( !isSave() ) + return rFileName; + + QString qExtension; + + QWidget *pExtensionWidget = findControl( "100" ); // CHECKBOX_AUTOEXTENSION + QCheckBox *pExtensionCB = pExtensionWidget? static_cast< QCheckBox* >( pExtensionWidget->qt_cast( "QCheckBox" ) ): NULL; + if ( pExtensionCB && pExtensionCB->isChecked() ) + { + // FIXME: qFilter can be a MIME; we ignore it now... + QStringList qFilterList = QStringList::split( " ", currentFilter() ); + for ( QStringList::const_iterator it = qFilterList.begin(); + qExtension.isEmpty() && it != qFilterList.end(); + ++it ) + { + int nUnwanted = (*it).findRev( '*' ); + if ( nUnwanted < 0 ) + nUnwanted = (*it).findRev( '?' ); + else + nUnwanted = ::std::max( nUnwanted, (*it).find( '?', nUnwanted ) ); + + int nIdx = (*it).find( '.', ::std::max( nUnwanted, 0 ) ); + if ( nIdx >= 0 ) + qExtension = (*it).mid( nIdx ).lower(); + } + } + + if ( qExtension.isEmpty() || qExtension == "." || rFileName.endsWith( qExtension ) ) + return rFileName; + else + return rFileName + qExtension; +} + +bool KDEFileDialog::isSupportedProtocol( const QString &rProtocol ) const +{ + // TODO Get this information directly from OOo + const char * pOOoProtocols[] = { "", "smb", "ftp", "http", "file", "mailto", + "vnd.sun.star.webdav", "news", "private", "vnd.sun.star.help", + "https", "slot", "macro", "javascript", "imap", "pop3", "data", + "cid", "out", "vnd.sun.star.wfs", "vnd.sun.star.hier", "vim", + ".uno", ".component", "vnd.sun.star.pkg", "ldap", "db", + "vnd.sun.star.cmd", "vnd.sun.star.script", "vnd.sun.star.odma", + "telnet", + NULL }; + + for ( const char **pIndex = pOOoProtocols; *pIndex != NULL; ++pIndex ) + { + if ( rProtocol == *pIndex ) + return true; + } + + // TODO gnome-vfs bits here + + return false; +} + +KURL KDEFileDialog::mostLocalURL( const KURL &rURL ) const +{ +#if KDE_IS_VERSION(3,5,0) + KURL qMostLocalURL( KIO::NetAccess::mostLocalURL( rURL, const_cast<KDEFileDialog*>( this ) ) ); + if ( qMostLocalURL.isLocalFile() ) + return qMostLocalURL; + else + { + // Terrible hack to get even non-existing media:// files right + qMostLocalURL.cd( ".." ); + KURL qMostLocalPath( KIO::NetAccess::mostLocalURL( qMostLocalURL, const_cast<KDEFileDialog*>( this ) ) ); + if ( qMostLocalPath.isLocalFile() ) + { + qMostLocalPath.addPath( rURL.fileName() ); + return qMostLocalPath; + } + } +#endif + + return rURL; +} + +QString KDEFileDialog::localCopy( const QString &rFileName ) const +{ + // 106 == MIB enum for UTF-8 + KURL qLocalURL = mostLocalURL( KURL( rFileName, 106 ) ); + if ( qLocalURL.isLocalFile() ) + return qLocalURL.url(); + + int nExtensionPos = rFileName.findRev( '/' ); + if ( nExtensionPos >= 0 ) + nExtensionPos = rFileName.find( '.', nExtensionPos ); + else + nExtensionPos = rFileName.find( '.' ); + + KTempFile qTempFile( QString::null, ( nExtensionPos < 0 )? QString(): rFileName.mid( nExtensionPos ) ); + KURL qDestURL; + qDestURL.setPath( qTempFile.name() ); + + if ( !KIO::NetAccess::file_copy( rFileName, qDestURL, 0600, true, false, NULL ) ) + { + KMessageBox::error( 0, KIO::NetAccess::lastErrorString() ); + return QString::null; + } + + return qDestURL.url(); +} + +void KDEFileDialog::fileHighlightedCommand( const QString & ) +{ + if ( canNotifySelection() ) + { + sendCommand( "fileSelectionChanged" ); + setCanNotifySelection( false ); + } +} + +void KDEFileDialog::selectionChangedCommand() +{ + if ( canNotifySelection() ) + { + sendCommand( "fileSelectionChanged" ); + setCanNotifySelection( false ); + } +} + +void KDEFileDialog::sendCommand( const QString &rCommand ) +{ +#if OSL_DEBUG_LEVEL > 0 + ::std::cerr << "kdefilepicker sent: " << rCommand.latin1() << ::std::endl; +#endif + + //m_aOutputStream << rCommand << endl; + ::std::cout << rCommand.utf8() << ::std::endl; +} + +void KDEFileDialog::appendURL( QString &rBuffer, const KURL &rURL ) +{ + // From Martin Kretzschmar: + // file:///path/to/test%E0.odt is not a valid URL from OOo's point of + // view. (?Most modern parts of?) OOo assume(s) that the URL contains only + // ASCII characters (which test%E0.odt does) and is UTF-8 after unescaping + // (which file:///path/test%E0.odt is not). + // Cf. the comment in sal/inc/osl/file.h. + // 106 == MIB enum for UTF-8 + QString qUrlStr = addExtension( rURL.url( 0, 106 ) ); + + if ( !isExecuting() && !isSupportedProtocol( rURL.protocol() ) ) + qUrlStr = localCopy( qUrlStr ); + + if ( qUrlStr.startsWith( "file:/" ) && qUrlStr.mid( 6, 1 ) != "/" ) + qUrlStr.replace( "file:/", "file:///" ); + + rBuffer.append( " " ); + if ( !qUrlStr.isEmpty() ) + appendEscaped( rBuffer, qUrlStr ); +} + +void KDEFileDialog::appendEscaped( QString &rBuffer, const QString &rString ) +{ + const QChar *pUnicode = rString.unicode(); + const QChar *pEnd = pUnicode + rString.length(); + + rBuffer.append( '"' ); + for ( ; pUnicode != pEnd; ++pUnicode ) + { + if ( *pUnicode == '\\' ) + rBuffer.append( "\\\\" ); + else if ( *pUnicode == '"' ) + rBuffer.append( "\\\"" ); + else if ( *pUnicode == '\n' ) + rBuffer.append( "\\\n" ); + else + rBuffer.append( *pUnicode ); + } + rBuffer.append( '"' ); +} + +QString KDEFileDialog::escapeString( const QString &rString ) +{ + QString qString; + qString.reserve( 2*rString.length() + 2 ); // every char escaped + quotes + + appendEscaped( qString, rString ); + + return qString; +} + + +void KDEFileFilterComboHack::setCurrentFilter( const QString& filter ) +{ + setCurrentText( filter ); + filterChanged(); + + // Workaround for 'Filter name (*.blah)' vs. 'Filter name' + if ( currentText() != text( currentItem() ) ) + { + int nItem = 0; + for ( ; nItem < count() && !text( nItem ).startsWith( filter ); ++nItem ); + + if ( nItem < count() ) + setCurrentItem( nItem ); + else + setCurrentItem( 0 ); + + filterChanged(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/kde/kdefilepicker.hxx b/fpicker/source/unx/kde/kdefilepicker.hxx new file mode 100644 index 000000000000..d0e0330f2941 --- /dev/null +++ b/fpicker/source/unx/kde/kdefilepicker.hxx @@ -0,0 +1,125 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _KDEFILEPICKER_HXX_ +#define _KDEFILEPICKER_HXX_ + +#include <kfiledialog.h> +#include <kfilefiltercombo.h> + +class QGrid; +class QHBox; +class QVBox; + +class KDEFileDialog : public KFileDialog +{ + Q_OBJECT + +protected: + typedef QPair< QString, QString > FilterEntry; + typedef QValueList< FilterEntry > FilterList; + + QVBox *m_pCustomWidget; + QHBox *m_pCombosAndButtons; + + QVBox *m_pLabels; + QVBox *m_pComboBoxes; + QVBox *m_pPushButtons; + + QGrid *m_pCheckBoxes; + + FilterList m_aFilters; + + /** Are we a "Save As" dialog? + * + * We cannot use KFileDialog::setOperationMode() here, because then + * it automatically adds an "Automatically select filename extension" + * check box, and completely destroys the dialog's layout + * (custom list boxes are under this check box, which looks ugly). + */ + bool m_bIsSave; + bool m_bIsExecuting; + + bool m_bCanNotifySelection; + +public: + KDEFileDialog( const QString &startDir, const QString &filter, + QWidget *parent, const char *name ); + virtual ~KDEFileDialog(); + +protected: + virtual void resizeEvent( QResizeEvent *pEvent ); + virtual void showEvent( QShowEvent *pEvent ); + void updateCustomWidgetLayout(); + + virtual void customEvent( QCustomEvent *pEvent ); + +protected: + void appendControl( const QString &rId, const QString &rType, const QString &rTitle ); + QWidget* findControl( const QString &rId ) const; + void enableControl( const QString &rId, const QString &rValue ); + void getValue( const QString &rId, const QString &rAction ); + void setValue( const QString &rId, const QString &rAction, const QStringList &rValue ); + + void appendFilter( const QString &rTitle, const QString &rFilter ); + QString filters() const; + QString addExtension( const QString &rFileName ) const; + + void setIsSave( bool bIsSave ) { m_bIsSave = bIsSave; } + bool isSave( void ) const { return m_bIsSave; } + + void setIsExecuting( bool bIsExecuting ) { m_bIsExecuting = bIsExecuting; } + bool isExecuting( void ) const { return m_bIsExecuting; } + + bool isSupportedProtocol( const QString &rProtocol ) const; + KURL mostLocalURL( const KURL &rURL ) const; + QString localCopy( const QString &rFileName ) const; + + void setCanNotifySelection( bool bCanNotifySelection ) { m_bCanNotifySelection = bCanNotifySelection; } + bool canNotifySelection( void ) const { return m_bCanNotifySelection; } + +protected slots: + void fileHighlightedCommand( const QString & ); + void selectionChangedCommand(); + +protected: + void sendCommand( const QString &rCommand ); + void appendURL( QString &rBuffer, const KURL &rURL ); + void appendEscaped( QString &rBuffer, const QString &rString ); + QString escapeString( const QString &rString ); +}; + +class KDEFileFilterComboHack : public KFileFilterCombo +{ +public: + void setCurrentFilter( const QString& filter ); +}; + +#endif // _KDEFILEPICKER_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/kde/kdefpmain.cxx b/fpicker/source/unx/kde/kdefpmain.cxx new file mode 100644 index 000000000000..002eb802576d --- /dev/null +++ b/fpicker/source/unx/kde/kdefpmain.cxx @@ -0,0 +1,92 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <kdemodalityfilter.hxx> +#include <kdefilepicker.hxx> +#include <kdecommandthread.hxx> + +#include <kaboutdata.h> +#include <kapplication.h> +#include <kcmdlineargs.h> + +#include <iostream> +#include <stdlib.h> + +////////////////////////////////////////////////////////////////////////// +// Main +////////////////////////////////////////////////////////////////////////// + +static KCmdLineOptions sOptions[] = +{ + { "winid <argument>", I18N_NOOP("Window ID to which is the fpicker modal"), "0" }, + KCmdLineLastOption +}; + +int main( int argc, char* argv[] ) +{ + // we fake the name of the application to have "OpenOffice.org" in the + // title + KAboutData qAboutData( "kdefilepicker", I18N_NOOP( "OpenOffice.org" ), + "0.1", I18N_NOOP( "kdefilepicker is an implementation of the KDE file dialog for OpenOffice.org." ), + KAboutData::License_LGPL, + "(c) 2004, Jan Holesovsky" ); + qAboutData.addAuthor( "Jan Holesovsky", I18N_NOOP("Original author and current maintainer"), "kendy@openoffice.org" ); + + // Let the user see that this does something... + ::std::cerr << "kdefilepicker, an implementation of KDE file dialog for OOo." << ::std::endl + << "Type 'exit' and press Enter to finish." << ::std::endl; + + KCmdLineArgs::addCmdLineOptions( sOptions ); + KCmdLineArgs::init( argc, argv, &qAboutData ); + + KLocale::setMainCatalogue( "kdialog" ); + + KApplication kApplication; + + // Setup the modality + KCmdLineArgs *pArgs = KCmdLineArgs::parsedArgs(); + long nWinId = atol( pArgs->getOption( "winid" ) ); + pArgs->clear(); + + KDEModalityFilter qModalityFilter( nWinId ); + + KDEFileDialog aFileDialog( NULL, QString(), NULL, "kdefiledialog" ); + + KDECommandThread qCommandThread( &aFileDialog ); + qCommandThread.start(); + + kApplication.exec(); + + qCommandThread.wait(); + + ::std::cout << "exited" << ::std::endl; + + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/kde/kdemodalityfilter.cxx b/fpicker/source/unx/kde/kdemodalityfilter.cxx new file mode 100644 index 000000000000..99fbf92b8e96 --- /dev/null +++ b/fpicker/source/unx/kde/kdemodalityfilter.cxx @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <kdemodalityfilter.hxx> + +#include <kapplication.h> +#include <kdialogbase.h> + +#include <netwm.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> + +////////////////////////////////////////////////////////////////////////// +// Modality filter +////////////////////////////////////////////////////////////////////////// + +KDEModalityFilter::KDEModalityFilter( WId nWinId ) + : m_nWinId( nWinId ) +{ + kapp->installEventFilter( this ); +} + +KDEModalityFilter::~KDEModalityFilter() +{ + kapp->removeEventFilter( this ); +} + +bool KDEModalityFilter::eventFilter( QObject *pObject, QEvent *pEvent ) +{ + if ( pObject->isWidgetType() && pEvent->type() == QEvent::Show ) + { + KDialogBase* pDlg = ::qt_cast< KDialogBase* >( pObject ); + if ( pDlg != NULL && m_nWinId != 0 ) + { + XSetTransientForHint( qt_xdisplay(), pDlg->winId(), m_nWinId ); + m_nWinId = 0; + } + } + return false; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/kde/kdemodalityfilter.hxx b/fpicker/source/unx/kde/kdemodalityfilter.hxx new file mode 100644 index 000000000000..8635694a39e1 --- /dev/null +++ b/fpicker/source/unx/kde/kdemodalityfilter.hxx @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _KDEMODALITYFILTER_HXX_ +#define _KDEMODALITYFILTER_HXX_ + +#include <qobject.h> + +class KDEModalityFilter : public QObject +{ +private: + WId m_nWinId; + +public: + KDEModalityFilter( WId nWinId ); + virtual ~KDEModalityFilter(); + + virtual bool eventFilter( QObject *pObject, QEvent *pEvent ); +}; + +#endif // _KDEMODALITYFILTER_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/kde/makefile.mk b/fpicker/source/unx/kde/makefile.mk new file mode 100644 index 000000000000..dcb16d9f232f --- /dev/null +++ b/fpicker/source/unx/kde/makefile.mk @@ -0,0 +1,76 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2010 Novell, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=fpicker +TARGET=kdefilepicker +LIBTARGET=NO +ENABLE_EXCEPTIONS=TRUE +#COMP1TYPELIST=$(TARGET) +#COMPRDB=$(SOLARBINDIR)$/types.rdb + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# ------------------------------------------------------------------ + +.IF "$(GUIBASE)" != "unx" || "$(ENABLE_KDE)" != "TRUE" + +dummy: + @echo "Nothing to build. GUIBASE == $(GUIBASE), ENABLE_KDE is not set" + +.ELSE # we build for KDE + +CFLAGS+= $(KDE_CFLAGS) + +# --- Files -------------------------------------------------------- + +SLOFILES =\ + $(SLO)$/kdecommandthread.obj \ + $(SLO)$/kdefilepicker.obj \ + $(SLO)$/kdefilepicker.moc.obj \ + $(SLO)$/kdefpmain.obj \ + $(SLO)$/kdemodalityfilter.obj + +APP1TARGET=$(TARGET) +APP1OBJS=$(SLOFILES) +APP1RPATH=BRAND +APP1STDLIBS=\ + $(SALLIB) \ + $(KDE_LIBS) -lkio -lX11 + + +.ENDIF # "$(GUIBASE)" != "unx" || "$(ENABLE_KDE)" != "TRUE" + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +$(MISC)$/kdefilepicker.moc.cxx : kdefilepicker.hxx + $(MOC) $< -o $@ diff --git a/fpicker/source/unx/kde4/FPServiceInfo.hxx b/fpicker/source/unx/kde4/FPServiceInfo.hxx new file mode 100644 index 000000000000..6dfb50e5d1ef --- /dev/null +++ b/fpicker/source/unx/kde4/FPServiceInfo.hxx @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#pragma once + +// the service names +#define FILE_PICKER_SERVICE_NAME "com.sun.star.ui.dialogs.KDE4FilePicker" + +// the implementation names +#define FILE_PICKER_IMPL_NAME "com.sun.star.ui.dialogs.KDE4FilePicker" + +// the registry key names +// a key under which this service will be registered, +// Format: -> "/ImplName/UNO/SERVICES/ServiceName" +// <Implementation-Name></UNO/SERVICES/><Service-Name> +#define FILE_PICKER_REGKEY_NAME "/com.sun.star.ui.dialogs.KDE4FilePickerImpl/UNO/SERVICES/com.sun.star.ui.dialogs.KDE4FilePicker" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/kde4/KDE4FPEntry.cxx b/fpicker/source/unx/kde4/KDE4FPEntry.cxx new file mode 100644 index 000000000000..6587930bcba9 --- /dev/null +++ b/fpicker/source/unx/kde4/KDE4FPEntry.cxx @@ -0,0 +1,105 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <cppuhelper/factory.hxx> + +#include <com/sun/star/container/XSet.hpp> + +#include <osl/diagnose.h> + +#include "KDE4FilePicker.hxx" +#include "FPServiceInfo.hxx" + +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::registry; +using namespace ::cppu; +using ::com::sun::star::ui::dialogs::XFilePicker; + +static Reference< XInterface > SAL_CALL createInstance( const Reference< XMultiServiceFactory >& serviceManager ) +{ + return Reference< XInterface >(static_cast< XFilePicker* >( new KDE4FilePicker( serviceManager ) ) ); +} + +// the three uno functions that will be exported +extern "C" +{ + void SAL_CALL component_getImplementationEnvironment( const sal_Char ** ppEnvTypeName, uno_Environment ** ) + { + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; + } + + sal_Bool SAL_CALL component_writeInfo( void*, void* pRegistryKey ) + { + sal_Bool bRetVal = sal_True; + + if ( pRegistryKey ) + { + try + { + Reference< XRegistryKey > pXNewKey( static_cast< XRegistryKey* >( pRegistryKey ) ); + pXNewKey->createKey( OUString(RTL_CONSTASCII_USTRINGPARAM( FILE_PICKER_REGKEY_NAME ) )); + } + catch( InvalidRegistryException& ) + { + OSL_ENSURE( sal_False, "InvalidRegistryException caught" ); + bRetVal = sal_False; + } + } + + return bRetVal; + } + + void* SAL_CALL component_getFactory( const sal_Char* pImplName, uno_Interface* pSrvManager, uno_Interface* ) + { + void* pRet = 0; + + if ( pSrvManager && ( 0 == rtl_str_compare( pImplName, FILE_PICKER_IMPL_NAME ) ) ) + { + Sequence< OUString > aSNS( 1 ); + aSNS.getArray( )[0] = OUString(RTL_CONSTASCII_USTRINGPARAM( FILE_PICKER_SERVICE_NAME )); + + Reference< XSingleServiceFactory > xFactory ( createSingleFactory( + reinterpret_cast< XMultiServiceFactory* > ( pSrvManager ), + OUString::createFromAscii( pImplName ), + createInstance, + aSNS ) ); + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + } + + return pRet; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/kde4/KDE4FilePicker.cxx b/fpicker/source/unx/kde4/KDE4FilePicker.cxx new file mode 100644 index 000000000000..fa4d3daede21 --- /dev/null +++ b/fpicker/source/unx/kde4/KDE4FilePicker.cxx @@ -0,0 +1,752 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// includes +////////////////////////////////////////////////////////////////////////// + +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <cppuhelper/interfacecontainer.h> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/ControlActions.hpp> +#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> + +#include <svtools/svtools.hrc> + +#include <osl/mutex.hxx> + +#include <vcl/svapp.hxx> +#include <vcl/sysdata.hxx> +#include <vcl/syswin.hxx> + +#include "osl/file.h" + +#include "KDE4FilePicker.hxx" +#include "FPServiceInfo.hxx" + +/* ********* Hack, but needed because of conflicting types... */ +#define Region QtXRegion + +//kde has an enum that uses this...OO does too +#undef SETTINGS_MOUSE + +#include <kfiledialog.h> +#include <kwindowsystem.h> +#include <kapplication.h> +#include <kfilefiltercombo.h> + +#include <qclipboard.h> +#include <QWidget> +#include <QCheckBox> +#include <QGridLayout> + +#undef Region + +using namespace ::com::sun::star; + +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::ui::dialogs::TemplateDescription; + +using namespace ::com::sun::star; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::ui::dialogs::TemplateDescription; +using namespace ::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds; +using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; + +////////////////////////////////////////////////////////////////////////// +// helper functions +////////////////////////////////////////////////////////////////////////// + +#include <QDebug> + +namespace +{ + // controling event notifications + const bool STARTUP_SUSPENDED = true; + const bool STARTUP_ALIVE = false; + + uno::Sequence<rtl::OUString> SAL_CALL FilePicker_getSupportedServiceNames() + { + uno::Sequence<rtl::OUString> aRet(3); + aRet[0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ui.dialogs.FilePicker")); + aRet[1] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ui.dialogs.SystemFilePicker")); + aRet[2] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ui.dialogs.KDE4FilePicker")); + return aRet; + } +} + +rtl::OUString toOUString(const QString& s) +{ + // QString stores UTF16, just like OUString + return rtl::OUString(reinterpret_cast<const sal_Unicode*>(s.data()), s.length()); +} + +QString toQString(const rtl::OUString& s) +{ + return QString::fromUtf16(s.getStr(), s.getLength()); +} + +////////////////////////////////////////////////////////////////////////// +// KDE4FilePicker +////////////////////////////////////////////////////////////////////////// + +KDE4FilePicker::KDE4FilePicker( const uno::Reference<lang::XMultiServiceFactory>& xServiceMgr ) + : cppu::WeakComponentImplHelper8< + XFilterManager, + XFilterGroupManager, + XFilePickerControlAccess, + XFilePickerNotifier, +// TODO XFilePreview, + lang::XInitialization, + util::XCancellable, + lang::XEventListener, + lang::XServiceInfo>( _helperMutex ), + m_xServiceMgr( xServiceMgr ), + _resMgr( CREATEVERSIONRESMGR( fps_office ) ) +{ + _extraControls = new QWidget(); + _layout = new QGridLayout(_extraControls); + + _dialog = new KFileDialog(KUrl("~"), QString(""), 0, _extraControls); + _dialog->setMode(KFile::File | KFile::LocalOnly); + + //default mode + _dialog->setOperationMode(KFileDialog::Opening); +} + +KDE4FilePicker::~KDE4FilePicker() +{ + delete _resMgr; + delete _dialog; +} + +void SAL_CALL KDE4FilePicker::addFilePickerListener( const uno::Reference<XFilePickerListener>& xListener ) + throw( uno::RuntimeException ) +{ + SolarMutexGuard aGuard; + m_xListener = xListener; +} + +void SAL_CALL KDE4FilePicker::removeFilePickerListener( const uno::Reference<XFilePickerListener>& ) + throw( uno::RuntimeException ) +{ + SolarMutexGuard aGuard; + m_xListener.clear(); +} + +void SAL_CALL KDE4FilePicker::setTitle( const rtl::OUString &title ) + throw( uno::RuntimeException ) +{ + _dialog->setCaption(toQString(title)); +} + +sal_Int16 SAL_CALL KDE4FilePicker::execute() + throw( uno::RuntimeException ) +{ + //get the window id of the main OO window to set it for the dialog as a parent + Window *pParentWin = Application::GetDefDialogParent(); + if ( pParentWin ) + { + const SystemEnvData* pSysData = ((SystemWindow *)pParentWin)->GetSystemData(); + if ( pSysData ) + { + KWindowSystem::setMainWindow( _dialog, pSysData->aWindow); // unx only + } + } + + _dialog->clearFilter(); + _dialog->setFilter(_filter); + _dialog->filterWidget()->setEditable(false); + + // At this point, SolarMutex is held. Opening the KDE file dialog here + // can lead to QClipboard asking for clipboard contents. If LO core + // is the owner of the clipboard content, this will block for 5 seconds + // and timeout, since the clipboard thread will not be able to acquire + // SolarMutex and thus won't be able to respond. If the event loops + // are properly integrated and QClipboard can use a nested event loop + // (see the KDE VCL plug), then this won't happen, but otherwise + // simply release the SolarMutex here. The KDE file dialog does not + // call back to the core, so this should be safe (and if it does, + // SolarMutex will need to be re-acquired. + ULONG mutexrelease = 0; + if( !qApp->clipboard()->property( "useEventLoopWhenWaiting" ).toBool()) + mutexrelease = Application::ReleaseSolarMutex(); + //block and wait for user input + int result = _dialog->exec(); + if( !qApp->clipboard()->property( "useEventLoopWhenWaiting" ).toBool()) + Application::AcquireSolarMutex( mutexrelease ); + if( result == KFileDialog::Accepted) + return ExecutableDialogResults::OK; + + return ExecutableDialogResults::CANCEL; +} + +void SAL_CALL KDE4FilePicker::setMultiSelectionMode( sal_Bool multiSelect ) + throw( uno::RuntimeException ) +{ + if (multiSelect) + _dialog->setMode(KFile::Files | KFile::LocalOnly); + else + _dialog->setMode(KFile::File | KFile::LocalOnly); +} + +void SAL_CALL KDE4FilePicker::setDefaultName( const ::rtl::OUString &name ) + throw( uno::RuntimeException ) +{ + const QString url = toQString(name); + _dialog->setSelection(url); +} + +void SAL_CALL KDE4FilePicker::setDisplayDirectory( const rtl::OUString &dir ) + throw( uno::RuntimeException ) +{ + const QString url = toQString(dir); + _dialog->setUrl(KUrl(url)); +} + +rtl::OUString SAL_CALL KDE4FilePicker::getDisplayDirectory() + throw( uno::RuntimeException ) +{ + QString dir = _dialog->baseUrl().url(); + return toOUString(dir); +} + +uno::Sequence< ::rtl::OUString > SAL_CALL KDE4FilePicker::getFiles() + throw( uno::RuntimeException ) +{ + QStringList rawFiles = _dialog->selectedFiles(); + QStringList files; + + // Workaround for the double click selection KDE4 bug + // kde file picker returns the file and directories for selectedFiles() + // when a file is double clicked + // make a true list of files + const QString dir = KUrl(rawFiles[0]).directory(); + + bool singleFile = true; + if (rawFiles.size() > 1) + { + singleFile = false; + //for multi file sequences, oo expects the first param to be the directory + //can't treat all cases like multi file because in some instances (inserting image) + //oo WANTS only one entry in the final list + files.append(dir); + } + + for (USHORT i = 0; i < rawFiles.size(); ++i) + { + // if the raw file is not the base directory (see above kde bug) + // we add the file to list of avail files + if ((dir + "/") != ( rawFiles[i])) + { + QString filename = KUrl(rawFiles[i]).fileName(); + + if (singleFile) + filename.prepend(dir + "/"); + files.append(filename); + } + } + + // add all files and leading directory to outgoing OO sequence + uno::Sequence< ::rtl::OUString > seq(files.size()); + for (int i = 0; i < files.size(); ++i) + { + rtl::OUString aFile(toOUString(files[i])), aURL; + osl_getFileURLFromSystemPath(aFile.pData, &aURL.pData ); + seq[i] = aURL; + } + + return seq; +} + +void SAL_CALL KDE4FilePicker::appendFilter( const ::rtl::OUString &title, const ::rtl::OUString &filter ) + throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + QString t = toQString(title); + QString f = toQString(filter); + + if (!_filter.isNull()) + _filter.append("\n"); + + //add to hash map for reverse lookup in getCurrentFilter + _filters.insert(f, t); + + // '/' meed to be escaped to else they are assumed to be mime types by kfiledialog + //see the docs + t.replace("/", "\\/"); + + // openoffice gives us filters separated by ';' qt dialogs just want space separated + f.replace(";", " "); + + _filter.append(QString("%1|%2").arg(f).arg(t)); +} + +void SAL_CALL KDE4FilePicker::setCurrentFilter( const rtl::OUString &title ) + throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + QString t = toQString(title); + t.replace("/", "\\/"); + _dialog->filterWidget()->setCurrentFilter(t); +} + +rtl::OUString SAL_CALL KDE4FilePicker::getCurrentFilter() + throw( uno::RuntimeException ) +{ + QString filter = _filters[_dialog->currentFilter()]; + + //default if not found + if (filter.isNull()) + filter = "ODF Text Document (.odt)"; + + return toOUString(filter); +} + +void SAL_CALL KDE4FilePicker::appendFilterGroup( const rtl::OUString& , const uno::Sequence<beans::StringPair>& filters) + throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + if (!_filter.isNull()) + _filter.append(QString("\n")); + + const USHORT length = filters.getLength(); + for (USHORT i = 0; i < length; ++i) + { + beans::StringPair aPair = filters[i]; + + _filter.append(QString("%1|%2").arg( + toQString(aPair.Second).replace(";", " ")).arg( + toQString(aPair.First).replace("/","\\/"))); + + if (i != length - 1) + _filter.append('\n'); + } +} + +void SAL_CALL KDE4FilePicker::setValue( sal_Int16 controlId, sal_Int16, const uno::Any &value ) + throw( uno::RuntimeException ) +{ + QWidget* widget = _customWidgets[controlId]; + + if (widget) + { + switch (controlId) + { + case ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION: + // we actually rely on KFileDialog and ignore CHECKBOX_AUTOEXTENSION completely, + // otherwise the checkbox would be duplicated + break; + case ExtendedFilePickerElementIds::CHECKBOX_PASSWORD: + case ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS: + case ExtendedFilePickerElementIds::CHECKBOX_READONLY: + case ExtendedFilePickerElementIds::CHECKBOX_LINK: + case ExtendedFilePickerElementIds::CHECKBOX_PREVIEW: + case ExtendedFilePickerElementIds::CHECKBOX_SELECTION: + { + QCheckBox* cb = dynamic_cast<QCheckBox*>(widget); + cb->setChecked(value.getValue()); + break; + } + case ExtendedFilePickerElementIds::PUSHBUTTON_PLAY: + case ExtendedFilePickerElementIds::LISTBOX_VERSION: + case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE: + case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE: + case ExtendedFilePickerElementIds::LISTBOX_VERSION_LABEL: + case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE_LABEL: + case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE_LABEL: + case ExtendedFilePickerElementIds::LISTBOX_FILTER_SELECTOR: + break; + } + } +} + +uno::Any SAL_CALL KDE4FilePicker::getValue( sal_Int16 controlId, sal_Int16 ) + throw( uno::RuntimeException ) +{ + uno::Any res(false); + + QWidget* widget = _customWidgets[controlId]; + + if (widget) + { + switch (controlId) + { + case ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION: + // we ignore this one and rely on KFileDialog to provide the function, + // always return true, here meaning "it's been taken care of" + res = uno::Any( true ); + break; + case ExtendedFilePickerElementIds::CHECKBOX_PASSWORD: + case ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS: + case ExtendedFilePickerElementIds::CHECKBOX_READONLY: + case ExtendedFilePickerElementIds::CHECKBOX_LINK: + case ExtendedFilePickerElementIds::CHECKBOX_PREVIEW: + case ExtendedFilePickerElementIds::CHECKBOX_SELECTION: + { + QCheckBox* cb = dynamic_cast<QCheckBox*>(widget); + res = uno::Any(cb->isChecked()); + break; + } + case ExtendedFilePickerElementIds::PUSHBUTTON_PLAY: + case ExtendedFilePickerElementIds::LISTBOX_VERSION: + case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE: + case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE: + case ExtendedFilePickerElementIds::LISTBOX_VERSION_LABEL: + case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE_LABEL: + case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE_LABEL: + case ExtendedFilePickerElementIds::LISTBOX_FILTER_SELECTOR: + break; + } + } + + return res; +} + +void SAL_CALL KDE4FilePicker::enableControl( sal_Int16 controlId, sal_Bool enable ) + throw( uno::RuntimeException ) +{ + QWidget* widget = _customWidgets[controlId]; + + if (widget) + { + widget->setEnabled(enable); + } +} + +void SAL_CALL KDE4FilePicker::setLabel( sal_Int16 controlId, const ::rtl::OUString &label ) + throw( uno::RuntimeException ) +{ + QWidget* widget = _customWidgets[controlId]; + + if (widget) + { + switch (controlId) + { + case ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION: // ignored + case ExtendedFilePickerElementIds::CHECKBOX_PASSWORD: + case ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS: + case ExtendedFilePickerElementIds::CHECKBOX_READONLY: + case ExtendedFilePickerElementIds::CHECKBOX_LINK: + case ExtendedFilePickerElementIds::CHECKBOX_PREVIEW: + case ExtendedFilePickerElementIds::CHECKBOX_SELECTION: + { + QCheckBox* cb = dynamic_cast<QCheckBox*>(widget); + cb->setText(toQString(label)); + break; + } + case ExtendedFilePickerElementIds::PUSHBUTTON_PLAY: + case ExtendedFilePickerElementIds::LISTBOX_VERSION: + case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE: + case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE: + case ExtendedFilePickerElementIds::LISTBOX_VERSION_LABEL: + case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE_LABEL: + case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE_LABEL: + case ExtendedFilePickerElementIds::LISTBOX_FILTER_SELECTOR: + break; + } + } +} + +rtl::OUString SAL_CALL KDE4FilePicker::getLabel(sal_Int16 controlId) + throw ( uno::RuntimeException ) +{ + QWidget* widget = _customWidgets[controlId]; + QString label; + + if (widget) + { + switch (controlId) + { + case ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION: // ignored + case ExtendedFilePickerElementIds::CHECKBOX_PASSWORD: + case ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS: + case ExtendedFilePickerElementIds::CHECKBOX_READONLY: + case ExtendedFilePickerElementIds::CHECKBOX_LINK: + case ExtendedFilePickerElementIds::CHECKBOX_PREVIEW: + case ExtendedFilePickerElementIds::CHECKBOX_SELECTION: + { + QCheckBox* cb = dynamic_cast<QCheckBox*>(widget); + label = cb->text(); + break; + } + case ExtendedFilePickerElementIds::PUSHBUTTON_PLAY: + case ExtendedFilePickerElementIds::LISTBOX_VERSION: + case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE: + case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE: + case ExtendedFilePickerElementIds::LISTBOX_VERSION_LABEL: + case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE_LABEL: + case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE_LABEL: + case ExtendedFilePickerElementIds::LISTBOX_FILTER_SELECTOR: + break; + } + } + return toOUString(label); +} + +void KDE4FilePicker::addCustomControl(sal_Int16 controlId) +{ + QWidget* widget = 0; + sal_Int32 resId = -1; + + switch (controlId) + { + case ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION: + resId = STR_SVT_FILEPICKER_AUTO_EXTENSION; + break; + case ExtendedFilePickerElementIds::CHECKBOX_PASSWORD: + resId = STR_SVT_FILEPICKER_PASSWORD; + break; + case ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS: + resId = STR_SVT_FILEPICKER_FILTER_OPTIONS; + break; + case ExtendedFilePickerElementIds::CHECKBOX_READONLY: + resId = STR_SVT_FILEPICKER_READONLY; + break; + case ExtendedFilePickerElementIds::CHECKBOX_LINK: + resId = STR_SVT_FILEPICKER_INSERT_AS_LINK; + break; + case ExtendedFilePickerElementIds::CHECKBOX_PREVIEW: + resId = STR_SVT_FILEPICKER_SHOW_PREVIEW; + break; + case ExtendedFilePickerElementIds::CHECKBOX_SELECTION: + resId = STR_SVT_FILEPICKER_SELECTION; + break; + case ExtendedFilePickerElementIds::PUSHBUTTON_PLAY: + resId = STR_SVT_FILEPICKER_PLAY; + break; + case ExtendedFilePickerElementIds::LISTBOX_VERSION: + resId = STR_SVT_FILEPICKER_VERSION; + break; + case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE: + resId = STR_SVT_FILEPICKER_TEMPLATES; + break; + case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE: + resId = STR_SVT_FILEPICKER_IMAGE_TEMPLATE; + break; + case ExtendedFilePickerElementIds::LISTBOX_VERSION_LABEL: + case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE_LABEL: + case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE_LABEL: + case ExtendedFilePickerElementIds::LISTBOX_FILTER_SELECTOR: + break; + } + + switch (controlId) + { + case ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION: + case ExtendedFilePickerElementIds::CHECKBOX_PASSWORD: + case ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS: + case ExtendedFilePickerElementIds::CHECKBOX_READONLY: + case ExtendedFilePickerElementIds::CHECKBOX_LINK: + case ExtendedFilePickerElementIds::CHECKBOX_PREVIEW: + case ExtendedFilePickerElementIds::CHECKBOX_SELECTION: + { + QString label; + + if (_resMgr && resId != -1) + { + rtl::OUString s = String(ResId( resId, *_resMgr )); + label = toQString(s); + label.replace("~", "&"); + } + + widget = new QCheckBox(label, _extraControls); + // the checkbox is created even for CHECKBOX_AUTOEXTENSION to simplify + // code, but the checkbox is hidden and ignored + if( controlId == ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION ) + widget->hide(); + + break; + } + case ExtendedFilePickerElementIds::PUSHBUTTON_PLAY: + case ExtendedFilePickerElementIds::LISTBOX_VERSION: + case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE: + case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE: + case ExtendedFilePickerElementIds::LISTBOX_VERSION_LABEL: + case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE_LABEL: + case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE_LABEL: + case ExtendedFilePickerElementIds::LISTBOX_FILTER_SELECTOR: + break; + } + + if (widget) + { + _layout->addWidget(widget); + _customWidgets.insert(controlId, widget); + } +} + +void SAL_CALL KDE4FilePicker::initialize( const uno::Sequence<uno::Any> &args ) + throw( uno::Exception, uno::RuntimeException ) +{ + _filter.clear(); + _filters.clear(); + + // parameter checking + uno::Any arg; + if (args.getLength() == 0) + { + throw lang::IllegalArgumentException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "no arguments" )), + static_cast< XFilePicker* >( this ), 1 ); + } + + arg = args[0]; + + if (( arg.getValueType() != ::getCppuType((sal_Int16*)0)) && + ( arg.getValueType() != ::getCppuType((sal_Int8*)0))) + { + throw lang::IllegalArgumentException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "invalid argument type" )), + static_cast< XFilePicker* >( this ), 1 ); + } + + sal_Int16 templateId = -1; + arg >>= templateId; + + //default is opening + KFileDialog::OperationMode operationMode = KFileDialog::Opening; + + switch ( templateId ) + { + case FILEOPEN_SIMPLE: + break; + + case FILESAVE_SIMPLE: + operationMode = KFileDialog::Saving; + break; + + case FILESAVE_AUTOEXTENSION: + operationMode = KFileDialog::Saving; + addCustomControl( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION ); + break; + + case FILESAVE_AUTOEXTENSION_PASSWORD: + { + operationMode = KFileDialog::Saving; + addCustomControl( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD ); + break; + } + case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS: + { + operationMode = KFileDialog::Saving; + addCustomControl( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION ); + addCustomControl( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD ); + addCustomControl( ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS ); + break; + } + case FILESAVE_AUTOEXTENSION_SELECTION: + operationMode = KFileDialog::Saving; + addCustomControl( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION ); + addCustomControl( ExtendedFilePickerElementIds::CHECKBOX_SELECTION ); + break; + + case FILESAVE_AUTOEXTENSION_TEMPLATE: + operationMode = KFileDialog::Saving; + addCustomControl( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION ); + addCustomControl( ExtendedFilePickerElementIds::LISTBOX_TEMPLATE ); + break; + + case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE: + addCustomControl( ExtendedFilePickerElementIds::CHECKBOX_LINK ); + addCustomControl( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW ); + addCustomControl( ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE ); + break; + + case FILEOPEN_PLAY: + addCustomControl( ExtendedFilePickerElementIds::PUSHBUTTON_PLAY ); + break; + + case FILEOPEN_READONLY_VERSION: + addCustomControl( ExtendedFilePickerElementIds::CHECKBOX_READONLY ); + addCustomControl( ExtendedFilePickerElementIds::LISTBOX_VERSION ); + break; + + case FILEOPEN_LINK_PREVIEW: + addCustomControl( ExtendedFilePickerElementIds::CHECKBOX_LINK ); + addCustomControl( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW ); + break; + + default: + throw lang::IllegalArgumentException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Unknown template" )), + static_cast< XFilePicker* >( this ), + 1 ); + } + + _dialog->setOperationMode(operationMode); + _dialog->setConfirmOverwrite(true); +} + +void SAL_CALL KDE4FilePicker::cancel() + throw ( uno::RuntimeException ) +{ + +} + +void SAL_CALL KDE4FilePicker::disposing( const lang::EventObject &rEvent ) + throw( uno::RuntimeException ) +{ + uno::Reference<XFilePickerListener> xFilePickerListener( rEvent.Source, uno::UNO_QUERY ); + + if ( xFilePickerListener.is() ) + { + removeFilePickerListener( xFilePickerListener ); + } +} + +rtl::OUString SAL_CALL KDE4FilePicker::getImplementationName() + throw( uno::RuntimeException ) +{ + return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( FILE_PICKER_IMPL_NAME )); +} + +sal_Bool SAL_CALL KDE4FilePicker::supportsService( const rtl::OUString& ServiceName ) + throw( uno::RuntimeException ) +{ + uno::Sequence< ::rtl::OUString > SupportedServicesNames = FilePicker_getSupportedServiceNames(); + + for ( sal_Int32 n = SupportedServicesNames.getLength(); n--; ) + { + if ( SupportedServicesNames[n].compareTo( ServiceName ) == 0 ) + return sal_True; + } + + return sal_False; +} + +uno::Sequence< ::rtl::OUString > SAL_CALL KDE4FilePicker::getSupportedServiceNames() + throw( uno::RuntimeException ) +{ + return FilePicker_getSupportedServiceNames(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/kde4/KDE4FilePicker.hxx b/fpicker/source/unx/kde4/KDE4FilePicker.hxx new file mode 100644 index 000000000000..6f73cc36ff9a --- /dev/null +++ b/fpicker/source/unx/kde4/KDE4FilePicker.hxx @@ -0,0 +1,173 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#pragma once + +#include <cppuhelper/compbase8.hxx> + +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerNotifier.hpp> +#include <com/sun/star/ui/dialogs/XFilterManager.hpp> +#include <com/sun/star/ui/dialogs/XFilterGroupManager.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp> +#include <com/sun/star/util/XCancellable.hpp> + +#include <osl/conditn.hxx> +#include <osl/mutex.hxx> + +#include <rtl/ustrbuf.hxx> + +#include <QString> +#include <QHash> + +class KFileDialog; +class QWidget; +class QLayout; + +class ResMgr; + +class KDE4FilePicker : + public cppu::WeakComponentImplHelper8< + ::com::sun::star::ui::dialogs::XFilterManager, + ::com::sun::star::ui::dialogs::XFilterGroupManager, + ::com::sun::star::ui::dialogs::XFilePickerControlAccess, + ::com::sun::star::ui::dialogs::XFilePickerNotifier, +// TODO ::com::sun::star::ui::dialogs::XFilePreview, + ::com::sun::star::lang::XInitialization, + ::com::sun::star::util::XCancellable, + ::com::sun::star::lang::XEventListener, + ::com::sun::star::lang::XServiceInfo > +{ +protected: + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xServiceMgr; // to instanciate own services + + ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener > m_xListener; + + ResMgr *_resMgr; + + //the dialog to display + KFileDialog* _dialog; + + osl::Mutex _helperMutex; + + //running filter string to add to dialog + QString _filter; + + //filter for reverse lookup of filter text + QHash<QString, QString> _filters; + + //mapping of SAL control ID's to created custom controls + QHash<sal_Int16, QWidget*> _customWidgets; + + //widget to contain extra custom controls + QWidget* _extraControls; + + //layout for extra custom controls + QLayout* _layout; + +public: + KDE4FilePicker( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceMgr ); + virtual ~KDE4FilePicker(); + + // XFilePickerNotifier + + virtual void SAL_CALL addFilePickerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener >& xListener ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL removeFilePickerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener >& xListener ) throw( ::com::sun::star::uno::RuntimeException ); + + // XExecutableDialog functions + + virtual void SAL_CALL setTitle( const ::rtl::OUString &rTitle ) throw( ::com::sun::star::uno::RuntimeException ); + virtual sal_Int16 SAL_CALL execute() throw( ::com::sun::star::uno::RuntimeException ); + + // XFilePicker functions + + virtual void SAL_CALL setMultiSelectionMode( sal_Bool bMode ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setDefaultName( const ::rtl::OUString &rName ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setDisplayDirectory( const ::rtl::OUString &rDirectory ) throw( ::com::sun::star::uno::RuntimeException ); + virtual ::rtl::OUString SAL_CALL getDisplayDirectory() throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getFiles() throw( ::com::sun::star::uno::RuntimeException ); + + // XFilterManager functions + + virtual void SAL_CALL appendFilter( const ::rtl::OUString &rTitle, const ::rtl::OUString &rFilter ) throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setCurrentFilter( const ::rtl::OUString &rTitle ) throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + virtual ::rtl::OUString SAL_CALL getCurrentFilter() throw( ::com::sun::star::uno::RuntimeException ); + + // XFilterGroupManager functions + + virtual void SAL_CALL appendFilterGroup( const ::rtl::OUString &rGroupTitle, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::StringPair > &rFilters ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + // XFilePickerControlAccess functions + + virtual void SAL_CALL setValue( sal_Int16 nControlId, sal_Int16 nControlAction, const ::com::sun::star::uno::Any &rValue ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getValue( sal_Int16 nControlId, sal_Int16 nControlAction ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL enableControl( sal_Int16 nControlId, sal_Bool bEnable ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setLabel( sal_Int16 nControlId, const ::rtl::OUString &rLabel ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getLabel( sal_Int16 nControlId ) throw (::com::sun::star::uno::RuntimeException); + + /* TODO XFilePreview + + virtual ::com::sun::star::uno::Sequence< sal_Int16 > SAL_CALL getSupportedImageFormats( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getTargetColorDepth( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getAvailableWidth( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getAvailableHeight( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setImage( sal_Int16 aImageFormat, const ::com::sun::star::uno::Any &rImage ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL setShowState( sal_Bool bShowState ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL getShowState( ) throw (::com::sun::star::uno::RuntimeException); + */ + + // XInitialization + + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > &rArguments ) throw( ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException ); + + // XCancellable + + virtual void SAL_CALL cancel( ) throw( ::com::sun::star::uno::RuntimeException ); + + // XEventListener + + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject &rEvent ) throw( ::com::sun::star::uno::RuntimeException ); + + // XServiceInfo + + virtual ::rtl::OUString SAL_CALL getImplementationName() throw( ::com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString &rServiceName ) throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw( ::com::sun::star::uno::RuntimeException ); + +private: + // prevent copy and assignment + KDE4FilePicker( const KDE4FilePicker& ); + KDE4FilePicker& operator=( const KDE4FilePicker& ); + + //add a custom control widget to the file dialog + void addCustomControl(sal_Int16 controlId); + +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/kde4/fps-kde4-ucd.txt b/fpicker/source/unx/kde4/fps-kde4-ucd.txt new file mode 100644 index 000000000000..8ecc4e0a0a52 --- /dev/null +++ b/fpicker/source/unx/kde4/fps-kde4-ucd.txt @@ -0,0 +1,6 @@ +[ComponentDescriptor] +ImplementationName=com.sun.star.ui.dialogs.KDE4FilePicker +ComponentName=fps_kde4.uno.so +LoaderName=com.sun.star.loader.SharedLibrary +[SupportedServices] +com.sun.star.ui.dialogs.KDE4FilePicker diff --git a/fpicker/source/unx/kde4/fps_kde4.xml b/fpicker/source/unx/kde4/fps_kde4.xml new file mode 100644 index 000000000000..a12bf894186a --- /dev/null +++ b/fpicker/source/unx/kde4/fps_kde4.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + <module-name>fps_kde4</module-name> + <component-description> + <author> Jan Holesovsky </author> + <name> com.sun.star.comp.ui.dialogs.FilePicker </name> + <description> + The KDE implementation of the FilePicker service. + </description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language> c++ </language> + <status value="beta"/> + <supported-service> com.sun.star.ui.dialogs.FilePicker </supported-service> + <service-dependency>...</service-dependency> + <type> com.sun.star.ui.dialogs.XExecutableDialog </type> + <type> com.sun.star.ui.dialogs.XFilePicker </type> + <type> com.sun.star.ui.dialogs.XFilterManager </type> + <type> com.sun.star.ui.dialogs.XFilterGroupManager </type> + <type> com.sun.star.ui.dialogs.XFilePickerListener </type> + <type> com.sun.star.ui.dialogs.ExecutableDialogException </type> + <type> com.sun.star.ui.dialogs.XFilePickerNotifier </type> + <type> com.sun.star.ui.dialogs.XFilePickerControlAccess </type> + <type> com.sun.star.ui.dialogs.XFilePreview </type> + <type> com.sun.star.ui.dialogs.ExtendedFilePickerElementIds </type> + <type> com.sun.star.ui.dialogs.ExecutableDialogResults </type> + <type> com.sun.star.ui.dialogs.FilePickerEvent </type> + <type> com.sun.star.ui.dialogs.CommonFilePickerElementIds </type> + <type> com.sun.star.ui.dialogs.ListboxControlActions </type> + <type> com.sun.star.ui.dialogs.TemplateDescription </type> + <type> com.sun.star.ui.dialogs.FilePreviewImageFormats </type> + <type> com.sun.star.util.XCancellable </type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.lang.IllegalArgumentException </type> + <type> com.sun.star.uno.TypeClass </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.uno.XAggregation </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.container.XSet </type> + </component-description> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> sal </project-build-dependency> + <runtime-module-dependency> cppuhelper </runtime-module-dependency> + <runtime-module-dependency> cppu2 </runtime-module-dependency> + <runtime-module-dependency> sal2 </runtime-module-dependency> +</module-description> diff --git a/fpicker/source/unx/kde4/makefile.mk b/fpicker/source/unx/kde4/makefile.mk new file mode 100644 index 000000000000..e245e6618465 --- /dev/null +++ b/fpicker/source/unx/kde4/makefile.mk @@ -0,0 +1,82 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=fpicker +TARGET=fps_kde4.uno +LIBTARGET=NO +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +DLLPRE= + +# ------------------------------------------------------------------ + +# Currently just KDE is supported... +.IF "$(GUIBASE)" != "unx" || "$(ENABLE_KDE4)" != "TRUE" + +dummy: + @echo "Nothing to build. GUIBASE == $(GUIBASE), ENABLE_KDE4 is not set" + +.ELSE # we build for KDE + +CFLAGS+= $(KDE4_CFLAGS) + +# --- Files -------------------------------------------------------- + +SLOFILES =\ + $(SLO)$/KDE4FilePicker.obj \ + $(SLO)$/KDE4FilePicker.moc.obj \ + $(SLO)$/KDE4FPEntry.obj + +SHL1NOCHECK=TRUE +SHL1TARGET=$(TARGET) +SHL1STDLIBS=$(CPPULIB)\ + $(CPPUHELPERLIB)\ + $(SALLIB)\ + $(VCLLIB)\ + $(TOOLSLIB) \ + $(KDE4_LIBS) -lkio -lkfile + + +SHL1OBJS=$(SLOFILES) +SHL1DEF=$(MISC)$/$(SHL1TARGET).def + +DEF1NAME=$(SHL1TARGET) +DEF1VERSIONMAP=exports.map + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +$(MISC)$/KDE4FilePicker.moc.cxx : KDE4FilePicker.hxx + $(MOC4) $< -o $@ diff --git a/fpicker/source/unx/kde_unx/FPServiceInfo.hxx b/fpicker/source/unx/kde_unx/FPServiceInfo.hxx new file mode 100644 index 000000000000..9e4cbf1ac44d --- /dev/null +++ b/fpicker/source/unx/kde_unx/FPServiceInfo.hxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FPSERVICEINFO_HXX_ +#define _FPSERVICEINFO_HXX_ + +// the service names +#define FILE_PICKER_SERVICE_NAME "com.sun.star.ui.dialogs.KDEFilePicker" + +// the implementation names +#define FILE_PICKER_IMPL_NAME "com.sun.star.ui.dialogs.UnxFilePicker" + +// the registry key names +// a key under which this service will be registered, +// Format: -> "/ImplName/UNO/SERVICES/ServiceName" +// <Implementation-Name></UNO/SERVICES/><Service-Name> +#define FILE_PICKER_REGKEY_NAME "/com.sun.star.ui.dialogs.UnxFilePicker/UNO/SERVICES/com.sun.star.ui.dialogs.KDEFilePicker" + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/kde_unx/UnxCommandThread.cxx b/fpicker/source/unx/kde_unx/UnxCommandThread.cxx new file mode 100644 index 000000000000..cc19ae3f62a5 --- /dev/null +++ b/fpicker/source/unx/kde_unx/UnxCommandThread.cxx @@ -0,0 +1,314 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <UnxCommandThread.hxx> +#include <UnxNotifyThread.hxx> + +#include <rtl/ustring.hxx> +#include <rtl/ustrbuf.hxx> + +#include <unistd.h> +#include <string.h> +#include <iostream> + +using namespace ::com::sun::star; + +////////////////////////////////////////////////////////////////////////// +// UnxFilePickerCommandThread +////////////////////////////////////////////////////////////////////////// + +UnxFilePickerCommandThread::UnxFilePickerCommandThread( UnxFilePickerNotifyThread *pNotifyThread, int nReadFD ) + : m_pNotifyThread( pNotifyThread ), + m_nReadFD( nReadFD ) +{ +} + +UnxFilePickerCommandThread::~UnxFilePickerCommandThread() +{ +} + +sal_Bool SAL_CALL UnxFilePickerCommandThread::result() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + return m_aResult; +} + +::rtl::OUString SAL_CALL UnxFilePickerCommandThread::getCurrentFilter() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + return m_aGetCurrentFilter; +} + +::rtl::OUString SAL_CALL UnxFilePickerCommandThread::getDirectory() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + return m_aGetDirectory; +} + +uno::Sequence< ::rtl::OUString > SAL_CALL UnxFilePickerCommandThread::getFiles() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + sal_Int32 nSize = m_aGetFiles.size(); + uno::Sequence< ::rtl::OUString > aFiles( ( nSize > 1 )? nSize + 1: nSize ); + + if ( nSize == 1 ) + aFiles[0] = m_aGetFiles.front(); + else if ( nSize > 1 ) + { + // First entry in the sequence must be the dirname, the others are the + // filenames, so we have to rearrange the list... + + ::rtl::OUString aFront = m_aGetFiles.front(); + sal_Int32 nLastSlash = aFront.lastIndexOf( '/' ); + + aFiles[0] = ( nLastSlash >= 0 )? aFront.copy( 0, nLastSlash ): ::rtl::OUString(); + ++nLastSlash; + + sal_Int32 nIdx = 1; + for ( ::std::list< ::rtl::OUString >::const_iterator it = m_aGetFiles.begin(); + it != m_aGetFiles.end(); ++it, ++nIdx ) + { + sal_Int32 nLength = (*it).getLength() - nLastSlash; + aFiles[nIdx] = ( nLength >= 0 )? (*it).copy( nLastSlash, nLength ): ::rtl::OUString(); + } + } + + return aFiles; +} + +uno::Any SAL_CALL UnxFilePickerCommandThread::getValue() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + return m_aGetValue; +} + +void SAL_CALL UnxFilePickerCommandThread::run() +{ + if ( m_nReadFD < 0 ) + return; + + sal_Int32 nBufferSize = 1024; // 1 is for testing, 1024 for real use + sal_Char *pBuffer = new sal_Char[nBufferSize]; + sal_Char *pBufferEnd = pBuffer + nBufferSize; + + sal_Char *pWhereToRead = pBuffer; + sal_Char *pEntryBegin = pBuffer; + sal_Int32 nBytesRead = 0; + sal_Bool bShouldExit = sal_False; + while ( !bShouldExit && ( nBytesRead = read( m_nReadFD, pWhereToRead, pBufferEnd - pWhereToRead ) ) > 0 ) + { + sal_Bool bFoundNL = sal_False; + sal_Char *pWhereToReadEnd = pWhereToRead + nBytesRead; + sal_Char *pEntryEnd = pWhereToRead; + do { + for ( ; pEntryEnd < pWhereToReadEnd && *pEntryEnd != '\n'; ++pEntryEnd ) + ; + + if ( pEntryEnd < pWhereToReadEnd ) + { + bFoundNL = sal_True; + *pEntryEnd = 0; + + if ( strcmp( pEntryBegin, "exited" ) == 0 ) + bShouldExit = sal_True; + else + handleCommand( ::rtl::OUString( pEntryBegin, pEntryEnd - pEntryBegin, RTL_TEXTENCODING_UTF8 )/*, bQuit*/ ); + + pEntryBegin = pEntryEnd + 1; + } + } while ( pEntryEnd < pWhereToReadEnd ); + + if ( bFoundNL ) + { + if ( pEntryBegin < pBufferEnd ) + memmove( pBuffer, pEntryBegin, pWhereToReadEnd - pEntryBegin ); + } + else + { + // enlarge the buffer size + nBufferSize *= 2; + sal_Char *pNewBuffer = new sal_Char[nBufferSize]; + if ( pEntryBegin < pBufferEnd ) + memmove( pNewBuffer, pEntryBegin, pWhereToReadEnd - pEntryBegin ); + + delete[] pBuffer; + pBuffer = pNewBuffer; + pBufferEnd = pBuffer + nBufferSize; + } + + pWhereToRead = pBuffer + ( pWhereToReadEnd - pEntryBegin ); + pEntryBegin = pBuffer; + } +} + +void SAL_CALL UnxFilePickerCommandThread::handleCommand( const ::rtl::OUString &rCommand ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + +#if OSL_DEBUG_LEVEL > 0 + ::std::cerr << "UnxFilePicker received: \"" << + OUStringToOString( rCommand, RTL_TEXTENCODING_ASCII_US ).getStr() << "\"" << ::std::endl; +#endif + + ::std::list< ::rtl::OUString > aList = tokenize( rCommand ); + + if ( aList.size() == 0 ) + return; + + ::rtl::OUString aCommandName = aList.front(); + aList.pop_front(); + + if ( aCommandName.equalsAscii( "accept" ) ) + { + m_aResult = sal_True; + m_aExecCondition.set(); + } + else if ( aCommandName.equalsAscii( "reject" ) ) + { + m_aResult = sal_False; + m_aExecCondition.set(); + } + else if ( aCommandName.equalsAscii( "fileSelectionChanged" ) ) + { + if ( m_pNotifyThread ) + m_pNotifyThread->fileSelectionChanged(); + } + else if ( aCommandName.equalsAscii( "files" ) ) + { + m_aGetFiles = aList; + m_aGetFilesCondition.set(); + } + else if ( aCommandName.equalsAscii( "value" ) ) + { + ::rtl::OUString aType; + if ( !aList.empty() ) + { + aType = aList.front(); + aList.pop_front(); + } + + if ( aType.equalsAscii( "bool" ) ) + { + sal_Bool bValue = !aList.empty() && aList.front().equalsIgnoreAsciiCaseAscii( "true" ); + + m_aGetValue <<= bValue; + m_aGetValueCondition.set(); + } + else if ( aType.equalsAscii( "int" ) ) + { + sal_Int32 nValue = 0; + if ( !aList.empty() ) + nValue = aList.front().toInt32(); + + m_aGetValue <<= nValue; + m_aGetValueCondition.set(); + } + else if ( aType.equalsAscii( "string" ) ) + { + ::rtl::OUString aValue; + if ( !aList.empty() ) + aValue = aList.front(); + + m_aGetValue <<= aValue; + m_aGetValueCondition.set(); + } + else if ( aType.equalsAscii( "stringList" ) ) + { + uno::Sequence< ::rtl::OUString > aSequence( aList.size() ); + sal_Int32 nIdx = 0; + for ( ::std::list< ::rtl::OUString >::const_iterator it = aList.begin(); it != aList.end(); ++it, ++nIdx ) + aSequence[nIdx] = (*it); + + m_aGetValue <<= aSequence; + m_aGetValueCondition.set(); + } + else + { + m_aGetValue = uno::Any(); + m_aGetValueCondition.set(); + } + } + else if ( aCommandName.equalsAscii( "currentFilter" ) ) + { + m_aGetCurrentFilter = aList.empty()? ::rtl::OUString(): aList.front(); + m_aGetCurrentFilterCondition.set(); + } + else if ( aCommandName.equalsAscii( "currentDirectory" ) ) + { + m_aGetDirectory = aList.empty()? ::rtl::OUString(): aList.front(); + m_aGetDirectoryCondition.set(); + } + else + { +#if OSL_DEBUG_LEVEL > 0 + ::std::cerr << "Unrecognized command: " + << OUStringToOString( aCommandName, RTL_TEXTENCODING_ASCII_US ).getStr() << "\"" << ::std::endl; +#endif + } +} + +::std::list< ::rtl::OUString > SAL_CALL UnxFilePickerCommandThread::tokenize( const ::rtl::OUString &rCommand ) +{ + ::std::list< ::rtl::OUString > aList; + ::rtl::OUStringBuffer aBuffer( 1024 ); + + const sal_Unicode *pUnicode = rCommand.getStr(); + const sal_Unicode *pEnd = pUnicode + rCommand.getLength(); + sal_Bool bQuoted = sal_False; + + for ( ; pUnicode != pEnd; ++pUnicode ) + { + if ( *pUnicode == '\\' ) + { + ++pUnicode; + if ( pUnicode != pEnd ) + { + if ( *pUnicode == 'n' ) + aBuffer.appendAscii( "\n", 1 ); + else + aBuffer.append( *pUnicode ); + } + } + else if ( *pUnicode == '"' ) + bQuoted = !bQuoted; + else if ( *pUnicode == ' ' && !bQuoted ) + aList.push_back( aBuffer.makeStringAndClear() ); + else + aBuffer.append( *pUnicode ); + } + aList.push_back( aBuffer.makeStringAndClear() ); + + return aList; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/kde_unx/UnxCommandThread.hxx b/fpicker/source/unx/kde_unx/UnxCommandThread.hxx new file mode 100644 index 000000000000..b8c6aaaaf97c --- /dev/null +++ b/fpicker/source/unx/kde_unx/UnxCommandThread.hxx @@ -0,0 +1,135 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _UNXCOMMANDTHREAD_HXX_ +#define _UNXCOMMANDTHREAD_HXX_ + +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Sequence.hxx> + +#include <osl/conditn.hxx> +#include <osl/mutex.hxx> +#include <osl/thread.hxx> +#include <rtl/ustring.hxx> + +#include <vcl/svapp.hxx> + +#include <list> + +class UnxFilePickerNotifyThread; + +/** Synchronization for the 'thread-less' version of the fpicker. + + Something like osl::Condition, but calls Application::Yield() while in + wait(). +*/ +class YieldingCondition +{ + ::osl::Mutex m_aMutex; + bool m_bValue; + + bool get() + { + ::osl::MutexGuard aGuard( m_aMutex ); + return m_bValue; + } + +public: + YieldingCondition() { reset(); } + + void reset() + { + ::osl::MutexGuard aGuard( m_aMutex ); + m_bValue = false; + } + + void set() + { + ::osl::MutexGuard aGuard( m_aMutex ); + m_bValue = true; + } + + void wait() + { + while ( !get() ) + Application::Yield(); + } +}; + +class UnxFilePickerCommandThread : public ::osl::Thread +{ +protected: + UnxFilePickerNotifyThread *m_pNotifyThread; + int m_nReadFD; + + ::osl::Mutex m_aMutex; + + YieldingCondition m_aExecCondition; + sal_Bool m_aResult; + + ::osl::Condition m_aGetCurrentFilterCondition; + ::rtl::OUString m_aGetCurrentFilter; + + ::osl::Condition m_aGetDirectoryCondition; + ::rtl::OUString m_aGetDirectory; + + ::osl::Condition m_aGetFilesCondition; + ::std::list< ::rtl::OUString > m_aGetFiles; + + ::osl::Condition m_aGetValueCondition; + ::com::sun::star::uno::Any m_aGetValue; + +public: + UnxFilePickerCommandThread( UnxFilePickerNotifyThread *pNotifyThread, int nReadFD ); + ~UnxFilePickerCommandThread(); + + YieldingCondition& SAL_CALL execCondition() { return m_aExecCondition; } + sal_Bool SAL_CALL result(); + + ::osl::Condition& SAL_CALL getCurrentFilterCondition() { return m_aGetCurrentFilterCondition; } + ::rtl::OUString SAL_CALL getCurrentFilter(); + + ::osl::Condition& SAL_CALL getDirectoryCondition() { return m_aGetDirectoryCondition; } + ::rtl::OUString SAL_CALL getDirectory(); + + ::osl::Condition& SAL_CALL getFilesCondition() { return m_aGetFilesCondition; } + ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getFiles(); + + ::osl::Condition& SAL_CALL getValueCondition() { return m_aGetValueCondition; } + ::com::sun::star::uno::Any SAL_CALL getValue(); + +protected: + virtual void SAL_CALL run(); + + virtual void SAL_CALL handleCommand( const ::rtl::OUString &rCommand/*, sal_Bool &rQuit*/ ); + ::std::list< ::rtl::OUString > SAL_CALL tokenize( const ::rtl::OUString &rCommand ); +}; + +#endif // _UNXCOMMANDTHREAD_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/kde_unx/UnxFPentry.cxx b/fpicker/source/unx/kde_unx/UnxFPentry.cxx new file mode 100644 index 000000000000..c577440cde0b --- /dev/null +++ b/fpicker/source/unx/kde_unx/UnxFPentry.cxx @@ -0,0 +1,127 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <com/sun/star/container/XSet.hpp> + +#include <cppuhelper/factory.hxx> +#include <osl/diagnose.h> + +#include "UnxFilePicker.hxx" +#include "FPServiceInfo.hxx" + +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::registry; +using namespace ::cppu; +using ::com::sun::star::ui::dialogs::XFilePicker; + +////////////////////////////////////////////////////////////////////////// +// +////////////////////////////////////////////////////////////////////////// + +static Reference< XInterface > SAL_CALL createInstance( const Reference< XMultiServiceFactory >& rServiceManager ) +{ + return Reference< XInterface >( + static_cast< XFilePicker* >( new UnxFilePicker( rServiceManager ) ) ); +} + +////////////////////////////////////////////////////////////////////////// +// the three uno functions that will be exported +////////////////////////////////////////////////////////////////////////// + +extern "C" +{ + +////////////////////////////////////////////////////////////////////////// +// component_getImplementationEnvironment +////////////////////////////////////////////////////////////////////////// + +void SAL_CALL component_getImplementationEnvironment( const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +////////////////////////////////////////////////////////////////////////// +// +////////////////////////////////////////////////////////////////////////// + +sal_Bool SAL_CALL component_writeInfo( void* pServiceManager, void* pRegistryKey ) +{ + sal_Bool bRetVal = sal_True; + + if ( pRegistryKey ) + { + try + { + Reference< XRegistryKey > pXNewKey( static_cast< XRegistryKey* >( pRegistryKey ) ); + pXNewKey->createKey( OUString(RTL_CONSTASCII_USTRINGPARAM( FILE_PICKER_REGKEY_NAME ) )); + } + catch( InvalidRegistryException& ) + { + OSL_ENSURE( sal_False, "InvalidRegistryException caught" ); + bRetVal = sal_False; + } + } + + return bRetVal; +} + +////////////////////////////////////////////////////////////////////////// +// +////////////////////////////////////////////////////////////////////////// + +void* SAL_CALL component_getFactory( const sal_Char* pImplName, uno_Interface* pSrvManager, uno_Interface* pRegistryKey ) +{ + void* pRet = 0; + + if ( pSrvManager && ( 0 == rtl_str_compare( pImplName, FILE_PICKER_IMPL_NAME ) ) ) + { + Sequence< OUString > aSNS( 1 ); + aSNS.getArray( )[0] = OUString(RTL_CONSTASCII_USTRINGPARAM( FILE_PICKER_SERVICE_NAME )); + + Reference< XSingleServiceFactory > xFactory ( createSingleFactory( + reinterpret_cast< XMultiServiceFactory* > ( pSrvManager ), + OUString::createFromAscii( pImplName ), + createInstance, + aSNS ) ); + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + } + + return pRet; +} + +} // extern "C" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/kde_unx/UnxFilePicker.cxx b/fpicker/source/unx/kde_unx/UnxFilePicker.cxx new file mode 100644 index 000000000000..e280d837fc3c --- /dev/null +++ b/fpicker/source/unx/kde_unx/UnxFilePicker.cxx @@ -0,0 +1,931 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/ControlActions.hpp> + +#include <FPServiceInfo.hxx> + +#include <cppuhelper/interfacecontainer.h> +#include <osl/diagnose.h> +#include <rtl/ustring.hxx> +#include <rtl/ustrbuf.hxx> +#include <tools/resmgr.hxx> + +#include <svtools/svtools.hrc> +#include <UnxFilePicker.hxx> +#include <UnxCommandThread.hxx> +#include <UnxNotifyThread.hxx> + +#include <vcl/svapp.hxx> +#include <vcl/sysdata.hxx> +#include <vcl/syswin.hxx> +#include <vcl/window.hxx> + +#include <sys/wait.h> +#include <unistd.h> +#include <fcntl.h> +#include <stdio.h> + +#include <iostream> + +using namespace ::com::sun::star; + +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::ui::dialogs::TemplateDescription; + +////////////////////////////////////////////////////////////////////////// +// helper functions +////////////////////////////////////////////////////////////////////////// + +namespace +{ + // controling event notifications + const bool STARTUP_SUSPENDED = true; + const bool STARTUP_ALIVE = false; + + uno::Sequence<rtl::OUString> SAL_CALL FilePicker_getSupportedServiceNames() + { + uno::Sequence<rtl::OUString> aRet(3); + aRet[0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ui.dialogs.FilePicker")); + aRet[1] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ui.dialogs.SystemFilePicker")); + aRet[2] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ui.dialogs.KDEFilePicker")); + return aRet; + } +} + +////////////////////////////////////////////////////////////////////////// +// UnxFilePicker +////////////////////////////////////////////////////////////////////////// + +UnxFilePicker::UnxFilePicker( const uno::Reference<lang::XMultiServiceFactory>& xServiceMgr ) + : cppu::WeakComponentImplHelper8< + XFilterManager, + XFilterGroupManager, + XFilePickerControlAccess, + XFilePickerNotifier, +// TODO XFilePreview, + lang::XInitialization, + util::XCancellable, + lang::XEventListener, + lang::XServiceInfo>( m_rbHelperMtx ), + m_xServiceMgr( xServiceMgr ), + m_nFilePickerPid( -1 ), + m_nFilePickerWrite( -1 ), + m_nFilePickerRead( -1 ), + m_pNotifyThread( NULL ), + m_pCommandThread( NULL ), + m_pResMgr( CREATEVERSIONRESMGR( fps_office ) ) +{ +} + +UnxFilePicker::~UnxFilePicker() +{ + if ( m_nFilePickerPid > 0 ) + { + sendCommand( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "exit" )) ); + waitpid( m_nFilePickerPid, NULL, 0 ); + } + + if ( m_pCommandThread ) + { + m_pCommandThread->join(); + + delete m_pCommandThread, m_pCommandThread = NULL; + } + + if ( m_pNotifyThread ) + { + m_pNotifyThread->exit(); + + m_pNotifyThread->join(); + + delete m_pNotifyThread, m_pNotifyThread = NULL; + } + + if ( m_nFilePickerWrite >= 0 ) + close( m_nFilePickerWrite ); + + if ( m_nFilePickerRead >= 0 ) + close( m_nFilePickerRead ); + + delete m_pResMgr, m_pResMgr = NULL; +} + +void SAL_CALL UnxFilePicker::addFilePickerListener( const uno::Reference<XFilePickerListener>& xListener ) + throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pNotifyThread ); + osl::MutexGuard aGuard( m_aMutex ); + + m_pNotifyThread->addFilePickerListener( xListener ); +} + +void SAL_CALL UnxFilePicker::removeFilePickerListener( const uno::Reference<XFilePickerListener>& xListener ) + throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pNotifyThread ); + osl::MutexGuard aGuard( m_aMutex ); + + m_pNotifyThread->removeFilePickerListener( xListener ); +} + +void SAL_CALL UnxFilePicker::setTitle( const rtl::OUString &rTitle ) + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUStringBuffer aBuffer( 1024 ); + + aBuffer.appendAscii( "setTitle " ); + appendEscaped( aBuffer, rTitle ); + + sendCommand( aBuffer.makeStringAndClear() ); +} + +sal_Int16 SAL_CALL UnxFilePicker::execute() + throw( uno::RuntimeException ) +{ + checkFilePicker(); + + // this is _not_ an osl::Condition, see i#93366 + m_pCommandThread->execCondition().reset(); + + sendCommand( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "exec" ) )); + + m_pCommandThread->execCondition().wait(); + + return m_pCommandThread->result(); +} + +void SAL_CALL UnxFilePicker::setMultiSelectionMode( sal_Bool bMode ) + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUString aString = bMode? + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "setMultiSelection true" )): + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "setMultiSelection false" )); + + sendCommand( aString ); +} + +void SAL_CALL UnxFilePicker::setDefaultName( const ::rtl::OUString &rName ) + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUStringBuffer aBuffer( 1024 ); + + aBuffer.appendAscii( "setDefaultName " ); + appendEscaped( aBuffer, rName ); + + sendCommand( aBuffer.makeStringAndClear() ); +} + +void SAL_CALL UnxFilePicker::setDisplayDirectory( const rtl::OUString &rDirectory ) + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUStringBuffer aBuffer( 1024 ); + + aBuffer.appendAscii( "setDirectory " ); + appendEscaped( aBuffer, rDirectory ); + + sendCommand( aBuffer.makeStringAndClear() ); +} + +rtl::OUString SAL_CALL UnxFilePicker::getDisplayDirectory() + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + sendCommand( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "getDirectory" )), + m_pCommandThread->getDirectoryCondition() ); + + return m_pCommandThread->getDirectory(); +} + +uno::Sequence< ::rtl::OUString > SAL_CALL UnxFilePicker::getFiles() + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + sendCommand( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "getFiles" )), + m_pCommandThread->getFilesCondition() ); + + return m_pCommandThread->getFiles(); +} + +void SAL_CALL UnxFilePicker::appendFilter( const ::rtl::OUString &rTitle, const ::rtl::OUString &rFilter ) + throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUStringBuffer aBuffer( 1024 ); + + aBuffer.appendAscii( "appendFilter " ); + appendEscaped( aBuffer, rTitle ); + aBuffer.appendAscii( " ", 1 ); + appendEscaped( aBuffer, rFilter ); + + sendCommand( aBuffer.makeStringAndClear() ); +} + +void SAL_CALL UnxFilePicker::setCurrentFilter( const rtl::OUString &rTitle ) + throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUStringBuffer aBuffer( 1024 ); + + aBuffer.appendAscii( "setCurrentFilter " ); + appendEscaped( aBuffer, rTitle ); + + sendCommand( aBuffer.makeStringAndClear() ); +} + +rtl::OUString SAL_CALL UnxFilePicker::getCurrentFilter() + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + sendCommand( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "getCurrentFilter" )), + m_pCommandThread->getCurrentFilterCondition() ); + + return m_pCommandThread->getCurrentFilter(); +} + +void SAL_CALL UnxFilePicker::appendFilterGroup( const rtl::OUString &rGroupTitle, const uno::Sequence<beans::StringPair> &rFilters ) + throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUStringBuffer aBuffer( 1024 ); + + aBuffer.appendAscii( "appendFilterGroup " ); + appendEscaped( aBuffer, rGroupTitle ); + + for ( sal_Int32 i = 0; i < rFilters.getLength(); ++i ) + { + beans::StringPair aPair = rFilters[i]; + + aBuffer.appendAscii( " ", 1 ); + appendEscaped( aBuffer, aPair.First ); + aBuffer.appendAscii( " ", 1 ); + appendEscaped( aBuffer, aPair.Second ); + } + + sendCommand( aBuffer.makeStringAndClear() ); +} + +void SAL_CALL UnxFilePicker::setValue( sal_Int16 nControlId, sal_Int16 nControlAction, const uno::Any &rValue ) + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUString aType; + ::rtl::OUString aAction; + sal_Int32 nTitleId; + + if ( controlIdInfo( nControlId, aType, nTitleId ) && controlActionInfo( nControlAction, aAction ) ) + { + ::rtl::OUStringBuffer aBuffer( 1024 ); + + aBuffer.appendAscii( "setValue " ); + aBuffer.append( static_cast< sal_Int32 >( nControlId ) ); + aBuffer.appendAscii( " ", 1 ); + aBuffer.append( aAction ); + + if ( aType.equalsAscii( "checkbox" ) ) + { + sal_Bool bControlValue; + if ( ( rValue >>= bControlValue ) && bControlValue ) + aBuffer.appendAscii( " true" ); + else + aBuffer.appendAscii( " false" ); + } + else if ( aType.equalsAscii( "listbox" ) ) + { + switch ( nControlAction ) + { + case ControlActions::ADD_ITEM: + case ControlActions::SET_HELP_URL: + { + ::rtl::OUString aString; + if ( rValue >>= aString ) + { + aBuffer.appendAscii( " ", 1 ); + appendEscaped( aBuffer, aString ); + } + } + break; + + case ControlActions::ADD_ITEMS: + { + uno::Sequence< ::rtl::OUString > aSequence; + if ( rValue >>= aSequence ) + { + for ( sal_Int32 nIdx = 0; nIdx < aSequence.getLength(); ++nIdx ) + { + aBuffer.appendAscii( " ", 1 ); + appendEscaped( aBuffer, aSequence[nIdx] ); + } + + } + } + break; + + case ControlActions::DELETE_ITEM: + case ControlActions::SET_SELECT_ITEM: + { + sal_Int32 nInt; + if ( rValue >>= nInt ) + { + aBuffer.appendAscii( " ", 1 ); + aBuffer.append( nInt ); + } + } + break; + + default: + // nothing + break; + } + } + // TODO else if push button... + + sendCommand( aBuffer.makeStringAndClear() ); + } +} + +uno::Any SAL_CALL UnxFilePicker::getValue( sal_Int16 nControlId, sal_Int16 nControlAction ) + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUString aAction; + + if ( controlActionInfo( nControlAction, aAction ) ) + { + ::rtl::OUStringBuffer aBuffer( 1024 ); + + aBuffer.appendAscii( "getValue " ); + aBuffer.append( static_cast< sal_Int32 >( nControlId ) ); + aBuffer.appendAscii( " ", 1 ); + aBuffer.append( aAction ); + + sendCommand( aBuffer.makeStringAndClear(), + m_pCommandThread->getValueCondition() ); + + return m_pCommandThread->getValue(); + } + + return uno::Any(); +} + +void SAL_CALL UnxFilePicker::enableControl( sal_Int16 nControlId, sal_Bool bEnable ) + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUStringBuffer aBuffer( 1024 ); + + aBuffer.appendAscii( "enableControl " ); + aBuffer.append( static_cast< sal_Int32 >( nControlId ) ); + aBuffer.appendAscii( bEnable? " true": " false" ); + + sendCommand( aBuffer.makeStringAndClear() ); +} + +void SAL_CALL UnxFilePicker::setLabel( sal_Int16 nControlId, const ::rtl::OUString &rLabel ) + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUStringBuffer aBuffer( 1024 ); + + aBuffer.appendAscii( "setLabel " ); + aBuffer.append( static_cast< sal_Int32 >( nControlId ) ); + aBuffer.appendAscii( " ", 1 ); + appendEscaped( aBuffer, rLabel ); + + sendCommand( aBuffer.makeStringAndClear() ); +} + +rtl::OUString SAL_CALL UnxFilePicker::getLabel(sal_Int16 /*nControlId*/) + throw ( uno::RuntimeException ) +{ + // FIXME getLabel() is not yet implemented + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + // TODO return m_pImpl->getLabel(nControlId); + return ::rtl::OUString(); +} + +/* TODO +uno::Sequence<sal_Int16> SAL_CALL UnxFilePicker::getSupportedImageFormats() + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + return m_pImpl->getSupportedImageFormats(); +} + +sal_Int32 SAL_CALL UnxFilePicker::getTargetColorDepth() + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + return m_pImpl->getTargetColorDepth(); +} + +sal_Int32 SAL_CALL UnxFilePicker::getAvailableWidth() + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + return m_pImpl->getAvailableWidth(); +} + +sal_Int32 SAL_CALL UnxFilePicker::getAvailableHeight() + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + return m_pImpl->getAvailableHeight(); +} + +void SAL_CALL UnxFilePicker::setImage( sal_Int16 aImageFormat, const uno::Any &rImage ) + throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + m_pImpl->setImage( aImageFormat, aImage ); +} + +sal_Bool SAL_CALL UnxFilePicker::setShowState( sal_Bool bShowState ) + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + return m_pImpl->setShowState( bShowState ); +} + +sal_Bool SAL_CALL UnxFilePicker::getShowState() + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + return m_pImpl->getShowState(); +} +*/ + +void SAL_CALL UnxFilePicker::initialize( const uno::Sequence<uno::Any> &rArguments ) + throw( uno::Exception, uno::RuntimeException ) +{ + initFilePicker(); + + // parameter checking + uno::Any aAny; + if ( 0 == rArguments.getLength( ) ) + throw lang::IllegalArgumentException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "no arguments" )), + static_cast< XFilePicker* >( this ), 1 ); + + aAny = rArguments[0]; + + if ( ( aAny.getValueType() != ::getCppuType( (sal_Int16*)0 ) ) && ( aAny.getValueType() != ::getCppuType( (sal_Int8*)0 ) ) ) + throw lang::IllegalArgumentException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "invalid argument type" )), + static_cast< XFilePicker* >( this ), 1 ); + + sal_Int16 templateId = -1; + aAny >>= templateId; + + ::rtl::OUString aTypeOpen(RTL_CONSTASCII_USTRINGPARAM( "setType \"open\"" )); + ::rtl::OUString aTypeSaveAs(RTL_CONSTASCII_USTRINGPARAM( "setType \"save\"" )); + + switch ( templateId ) + { + case FILEOPEN_SIMPLE: + sendCommand( aTypeOpen ); + break; + + case FILESAVE_SIMPLE: + sendCommand( aTypeSaveAs ); + break; + + case FILESAVE_AUTOEXTENSION_PASSWORD: + sendCommand( aTypeSaveAs ); + + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION ); + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD ); + break; + + case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS: + sendCommand( aTypeSaveAs ); + + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION ); + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD ); + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS ); + break; + + case FILESAVE_AUTOEXTENSION_SELECTION: + sendCommand( aTypeSaveAs ); + + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION ); + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_SELECTION ); + break; + + case FILESAVE_AUTOEXTENSION_TEMPLATE: + sendCommand( aTypeSaveAs ); + + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION ); + sendAppendControlCommand( ExtendedFilePickerElementIds::LISTBOX_TEMPLATE ); + break; + + case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE: + sendCommand( aTypeOpen ); + + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_LINK ); + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW ); + sendAppendControlCommand( ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE ); + break; + + case FILEOPEN_PLAY: + sendCommand( aTypeOpen ); + + sendAppendControlCommand( ExtendedFilePickerElementIds::PUSHBUTTON_PLAY ); + break; + + case FILEOPEN_READONLY_VERSION: + sendCommand( aTypeOpen ); + + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_READONLY ); + sendAppendControlCommand( ExtendedFilePickerElementIds::LISTBOX_VERSION ); + break; + + case FILEOPEN_LINK_PREVIEW: + sendCommand( aTypeOpen ); + + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_LINK ); + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW ); + break; + + case FILESAVE_AUTOEXTENSION: + sendCommand( aTypeSaveAs ); + + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION ); + break; + + default: + throw lang::IllegalArgumentException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Unknown template" )), + static_cast< XFilePicker* >( this ), + 1 ); + } +} + +void SAL_CALL UnxFilePicker::cancel() + throw ( uno::RuntimeException ) +{ + // FIXME cancel() is not implemented + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + // TODO m_pImpl->cancel(); +} + +void SAL_CALL UnxFilePicker::disposing( const lang::EventObject &rEvent ) + throw( uno::RuntimeException ) +{ + uno::Reference<XFilePickerListener> xFilePickerListener( rEvent.Source, uno::UNO_QUERY ); + + if ( xFilePickerListener.is() ) + removeFilePickerListener( xFilePickerListener ); +} + +rtl::OUString SAL_CALL UnxFilePicker::getImplementationName() + throw( uno::RuntimeException ) +{ + return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( FILE_PICKER_IMPL_NAME )); +} + +sal_Bool SAL_CALL UnxFilePicker::supportsService( const rtl::OUString& ServiceName ) + throw( uno::RuntimeException ) +{ + uno::Sequence< ::rtl::OUString > SupportedServicesNames = FilePicker_getSupportedServiceNames(); + + for ( sal_Int32 n = SupportedServicesNames.getLength(); n--; ) + { + if ( SupportedServicesNames[n].compareTo( ServiceName ) == 0 ) + return sal_True; + } + + return sal_False; +} + +uno::Sequence< ::rtl::OUString > SAL_CALL UnxFilePicker::getSupportedServiceNames() + throw( uno::RuntimeException ) +{ + return FilePicker_getSupportedServiceNames(); +} + +void UnxFilePicker::initFilePicker() +{ + int aFiledesStdin[2], aFiledesStdout[2]; + if ( pipe( aFiledesStdin ) < 0 || pipe( aFiledesStdout ) < 0 ) + return; + + m_nFilePickerPid = fork(); + if ( m_nFilePickerPid < 0 ) + return; + + if ( m_nFilePickerPid == 0 ) + { + // Child... + close( aFiledesStdin[1] ); // write end of the pipe + dup2( aFiledesStdin[0], 0 ); + close( aFiledesStdin[0] ); + + close( aFiledesStdout[0] ); // read end of the pipe + dup2( aFiledesStdout[1], 1 ); + close( aFiledesStdout[1] ); + +#if OSL_DEBUG_LEVEL == 0 + int nRedirect = open( "/dev/null", O_WRONLY ); + if( nRedirect != -1 ) + { + dup2( nRedirect, 2 ); + } +#endif + + // The executable name + const char *pFname = "kdefilepicker"; + + // ID of the main window + const int nIdLen = 20; + char pWinId[nIdLen] = "0"; + + // TODO pass here the real parent (not possible for system dialogs + // yet), and default to GetDefDialogParent() only when the real parent + // is NULL + Window *pParentWin = Application::GetDefDialogParent(); + if ( pParentWin ) + { + const SystemEnvData* pSysData = ((SystemWindow *)pParentWin)->GetSystemData(); + if ( pSysData ) + { + snprintf( pWinId, nIdLen, "%ld", pSysData->aWindow ); // unx only + pWinId[nIdLen-1] = 0; + } + } + + // Execute the fpicker implementation + execlp( pFname, pFname, "--winid", pWinId, NULL ); + + // Error, finish the child + exit( -1 ); + } + + // Parent continues + close( aFiledesStdin[0] ); + m_nFilePickerWrite = aFiledesStdin[1]; + + close( aFiledesStdout[1] ); + m_nFilePickerRead = aFiledesStdout[0]; + + // Create the notify thread + if ( !m_pNotifyThread ) + m_pNotifyThread = new UnxFilePickerNotifyThread( this ); + + // Create the command thread + if ( !m_pCommandThread ) + m_pCommandThread = new UnxFilePickerCommandThread( m_pNotifyThread, m_nFilePickerRead ); + + // Start the threads + m_pNotifyThread->create(); + m_pCommandThread->create(); + + return; +} + +void UnxFilePicker::checkFilePicker() throw( ::com::sun::star::uno::RuntimeException ) +{ + if ( m_nFilePickerPid > 0 ) + { + // TODO check if external file picker is runnning + } + else + { + throw uno::RuntimeException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "the external file picker does not run" )), + *this ); + } +} + +void UnxFilePicker::sendCommand( const ::rtl::OUString &rCommand ) +{ + if ( m_nFilePickerWrite < 0 ) + return; + + ::rtl::OString aUtfString = OUStringToOString( rCommand + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "\n" )), RTL_TEXTENCODING_UTF8 ); + +#if OSL_DEBUG_LEVEL > 0 + ::std::cerr << "UnxFilePicker sent: \"" << aUtfString.getStr() << "\"" << ::std::endl; +#endif + + write( m_nFilePickerWrite, aUtfString.getStr(), aUtfString.getLength() ); +} + +void UnxFilePicker::sendCommand( const ::rtl::OUString &rCommand, ::osl::Condition &rCondition ) +{ + rCondition.reset(); + + sendCommand( rCommand ); + + rCondition.wait(); +} + +void UnxFilePicker::appendEscaped( ::rtl::OUStringBuffer &rBuffer, const ::rtl::OUString &rString ) +{ + const sal_Unicode *pUnicode = rString.getStr(); + const sal_Unicode *pEnd = pUnicode + rString.getLength(); + + rBuffer.appendAscii( "\"" , 1 ); + + for ( ; pUnicode != pEnd; ++pUnicode ) + { + if ( *pUnicode == '\\' ) + rBuffer.appendAscii( "\\\\", 2 ); + else if ( *pUnicode == '"' ) + rBuffer.appendAscii( "\\\"", 2 ); + else if ( *pUnicode == '\n' ) + rBuffer.appendAscii( "\\n", 2 ); + else + rBuffer.append( *pUnicode ); + } + + rBuffer.appendAscii( "\"", 1 ); +} + +sal_Bool UnxFilePicker::controlIdInfo( sal_Int16 nControlId, ::rtl::OUString &rType, sal_Int32 &rTitleId ) +{ + typedef struct { + sal_Int16 nId; + const ::rtl::OUString *pType; + sal_Int32 nTitle; + } ElementToName; + + const ::rtl::OUString aCheckBox( RTL_CONSTASCII_USTRINGPARAM( "checkbox" ) ); + const ::rtl::OUString aControl( RTL_CONSTASCII_USTRINGPARAM( "control" ) ); + const ::rtl::OUString aEdit( RTL_CONSTASCII_USTRINGPARAM( "edit" ) ); + const ::rtl::OUString aLabel( RTL_CONSTASCII_USTRINGPARAM( "label" ) ); + const ::rtl::OUString aListBox( RTL_CONSTASCII_USTRINGPARAM( "listbox" ) ); + const ::rtl::OUString aPushButton( RTL_CONSTASCII_USTRINGPARAM( "pushbutton" ) ); + + const ElementToName *pPtr; + const ElementToName pArray[] = + { + { CommonFilePickerElementIds::PUSHBUTTON_OK, &aPushButton, 0/*FIXME?*/ }, + { CommonFilePickerElementIds::PUSHBUTTON_CANCEL, &aPushButton, 0/*FIXME?*/ }, + { CommonFilePickerElementIds::LISTBOX_FILTER, &aListBox, 0/*FIXME?*/ }, + { CommonFilePickerElementIds::CONTROL_FILEVIEW, &aControl, 0/*FIXME?*/ }, + { CommonFilePickerElementIds::EDIT_FILEURL, &aEdit, 0/*FIXME?*/ }, + { CommonFilePickerElementIds::LISTBOX_FILTER_LABEL, &aLabel, 0/*FIXME?*/ }, + { CommonFilePickerElementIds::EDIT_FILEURL_LABEL, &aLabel, 0/*FIXME?*/ }, + + { ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, &aCheckBox, STR_SVT_FILEPICKER_AUTO_EXTENSION }, + { ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, &aCheckBox, STR_SVT_FILEPICKER_PASSWORD }, + { ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS, &aCheckBox, STR_SVT_FILEPICKER_FILTER_OPTIONS }, + { ExtendedFilePickerElementIds::CHECKBOX_READONLY, &aCheckBox, STR_SVT_FILEPICKER_READONLY }, + { ExtendedFilePickerElementIds::CHECKBOX_LINK, &aCheckBox, STR_SVT_FILEPICKER_INSERT_AS_LINK }, + { ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, &aCheckBox, STR_SVT_FILEPICKER_SHOW_PREVIEW }, + { ExtendedFilePickerElementIds::PUSHBUTTON_PLAY, &aPushButton, STR_SVT_FILEPICKER_PLAY }, + { ExtendedFilePickerElementIds::LISTBOX_VERSION, &aListBox, STR_SVT_FILEPICKER_VERSION }, + { ExtendedFilePickerElementIds::LISTBOX_TEMPLATE, &aListBox, STR_SVT_FILEPICKER_TEMPLATES }, + { ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE, &aListBox, STR_SVT_FILEPICKER_IMAGE_TEMPLATE }, + { ExtendedFilePickerElementIds::CHECKBOX_SELECTION, &aCheckBox, STR_SVT_FILEPICKER_SELECTION }, + { 0, 0, 0 } + }; + + for ( pPtr = pArray; pPtr->nId && ( pPtr->nId != nControlId ); ++pPtr ) + ; + + if ( pPtr->nId == nControlId ) + { + rType = *(pPtr->pType); + rTitleId = pPtr->nTitle; + + return sal_True; + } + + return sal_False; +} + +sal_Bool UnxFilePicker::controlActionInfo( sal_Int16 nControlAction, ::rtl::OUString &rType ) +{ + typedef struct { + sal_Int16 nId; + const ::rtl::OUString pType; + } ElementToName; + + const ElementToName *pPtr; + const ElementToName pArray[] = + { + { ControlActions::ADD_ITEM, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "addItem" ) ) }, + { ControlActions::ADD_ITEMS, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "addItems" ) ) }, + { ControlActions::DELETE_ITEM, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "deleteItem" ) ) }, + { ControlActions::DELETE_ITEMS, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "deleteItems" ) ) }, + { ControlActions::SET_SELECT_ITEM, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "setSelectedItem" ) ) }, + { ControlActions::GET_ITEMS, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getItems" ) ) }, + { ControlActions::GET_SELECTED_ITEM, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getSelectedItem" ) ) }, + { ControlActions::GET_SELECTED_ITEM_INDEX, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getSelectedItemIndex" ) ) }, + { ControlActions::SET_HELP_URL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "setHelpURL" ) ) }, + { ControlActions::GET_HELP_URL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getHelpURL" ) ) }, + { 0, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "noAction" ) ) } + }; + + for ( pPtr = pArray; pPtr->nId && ( pPtr->nId != nControlAction ); ++pPtr ) + ; + + rType = pPtr->pType; + + return sal_True; +} + +void UnxFilePicker::sendAppendControlCommand( sal_Int16 nControlId ) +{ + ::rtl::OUString aType; + sal_Int32 nTitleId; + + if ( controlIdInfo( nControlId, aType, nTitleId ) ) + { + ::rtl::OUStringBuffer aBuffer( 1024 ); + + aBuffer.appendAscii( "appendControl " ); + aBuffer.append( static_cast< sal_Int32 >( nControlId ) ); + aBuffer.appendAscii( " ", 1 ); + appendEscaped( aBuffer, aType ); + aBuffer.appendAscii( " ", 1 ); + appendEscaped( aBuffer, m_pResMgr? String( ResId( nTitleId, *m_pResMgr ) ): String() ); + + sendCommand( aBuffer.makeStringAndClear() ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/kde_unx/UnxFilePicker.hxx b/fpicker/source/unx/kde_unx/UnxFilePicker.hxx new file mode 100644 index 000000000000..d48af8567d45 --- /dev/null +++ b/fpicker/source/unx/kde_unx/UnxFilePicker.hxx @@ -0,0 +1,177 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _UNXFILEPICKER_HXX_ +#define _UNXFILEPICKER_HXX_ + +#include <cppuhelper/compbase8.hxx> +#include <osl/conditn.hxx> +#include <osl/mutex.hxx> +#include <rtl/ustrbuf.hxx> + +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerNotifier.hpp> +#include <com/sun/star/ui/dialogs/XFilterManager.hpp> +#include <com/sun/star/ui/dialogs/XFilterGroupManager.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp> +#include <com/sun/star/ui/dialogs/XFilePreview.hpp> +#include <com/sun/star/util/XCancellable.hpp> + +#include <list> + +class UnxFilePickerCommandThread; +class UnxFilePickerNotifyThread; +class ResMgr; + +class UnxFilePickerDummy +{ +protected: + osl::Mutex m_aMutex; + osl::Mutex m_rbHelperMtx; +}; + +class UnxFilePicker : + public UnxFilePickerDummy, + public cppu::WeakComponentImplHelper8< + ::com::sun::star::ui::dialogs::XFilterManager, + ::com::sun::star::ui::dialogs::XFilterGroupManager, + ::com::sun::star::ui::dialogs::XFilePickerControlAccess, + ::com::sun::star::ui::dialogs::XFilePickerNotifier, +// TODO ::com::sun::star::ui::dialogs::XFilePreview, + ::com::sun::star::lang::XInitialization, + ::com::sun::star::util::XCancellable, + ::com::sun::star::lang::XEventListener, + ::com::sun::star::lang::XServiceInfo > +{ +protected: + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xServiceMgr; // to instanciate own services + + pid_t m_nFilePickerPid; + int m_nFilePickerWrite; // (kde|...)filepicker gets it as stdin + int m_nFilePickerRead; // (kde|...)filepicker gets it as stdout + + UnxFilePickerNotifyThread *m_pNotifyThread; + UnxFilePickerCommandThread *m_pCommandThread; + + ResMgr *m_pResMgr; + +public: + UnxFilePicker( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceMgr ); + virtual ~UnxFilePicker(); + + // XFilePickerNotifier + + virtual void SAL_CALL addFilePickerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener >& xListener ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL removeFilePickerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener >& xListener ) throw( ::com::sun::star::uno::RuntimeException ); + + // XExecutableDialog functions + + virtual void SAL_CALL setTitle( const ::rtl::OUString &rTitle ) throw( ::com::sun::star::uno::RuntimeException ); + virtual sal_Int16 SAL_CALL execute() throw( ::com::sun::star::uno::RuntimeException ); + + // XFilePicker functions + + virtual void SAL_CALL setMultiSelectionMode( sal_Bool bMode ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setDefaultName( const ::rtl::OUString &rName ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setDisplayDirectory( const ::rtl::OUString &rDirectory ) throw( ::com::sun::star::uno::RuntimeException ); + virtual ::rtl::OUString SAL_CALL getDisplayDirectory() throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getFiles() throw( ::com::sun::star::uno::RuntimeException ); + + // XFilterManager functions + + virtual void SAL_CALL appendFilter( const ::rtl::OUString &rTitle, const ::rtl::OUString &rFilter ) throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setCurrentFilter( const ::rtl::OUString &rTitle ) throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + virtual ::rtl::OUString SAL_CALL getCurrentFilter() throw( ::com::sun::star::uno::RuntimeException ); + + // XFilterGroupManager functions + + virtual void SAL_CALL appendFilterGroup( const ::rtl::OUString &rGroupTitle, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::StringPair > &rFilters ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + // XFilePickerControlAccess functions + + virtual void SAL_CALL setValue( sal_Int16 nControlId, sal_Int16 nControlAction, const ::com::sun::star::uno::Any &rValue ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getValue( sal_Int16 nControlId, sal_Int16 nControlAction ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL enableControl( sal_Int16 nControlId, sal_Bool bEnable ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setLabel( sal_Int16 nControlId, const ::rtl::OUString &rLabel ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getLabel( sal_Int16 nControlId ) throw (::com::sun::star::uno::RuntimeException); + + /* TODO XFilePreview + + virtual ::com::sun::star::uno::Sequence< sal_Int16 > SAL_CALL getSupportedImageFormats( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getTargetColorDepth( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getAvailableWidth( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getAvailableHeight( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setImage( sal_Int16 aImageFormat, const ::com::sun::star::uno::Any &rImage ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL setShowState( sal_Bool bShowState ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL getShowState( ) throw (::com::sun::star::uno::RuntimeException); + */ + + // XInitialization + + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > &rArguments ) throw( ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException ); + + // XCancellable + + virtual void SAL_CALL cancel( ) throw( ::com::sun::star::uno::RuntimeException ); + + // XEventListener + + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject &rEvent ) throw( ::com::sun::star::uno::RuntimeException ); + + // XServiceInfo + + virtual ::rtl::OUString SAL_CALL getImplementationName() throw( ::com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString &rServiceName ) throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw( ::com::sun::star::uno::RuntimeException ); + +private: + // prevent copy and assignment + UnxFilePicker( const UnxFilePicker& ); + UnxFilePicker& operator=( const UnxFilePicker& ); + +protected: + void initFilePicker(); + void checkFilePicker() throw( ::com::sun::star::uno::RuntimeException ); + + // Async sendCommand + void sendCommand( const ::rtl::OUString &rCommand ); + // Synchronized sendCommand + void sendCommand( const ::rtl::OUString &rCommand, ::osl::Condition &rCondition ); + void appendEscaped( ::rtl::OUStringBuffer &rBuffer, const ::rtl::OUString &rString ); + +private: + sal_Bool controlIdInfo( sal_Int16 nControlId, ::rtl::OUString &rType, sal_Int32 &rTitleId ); + sal_Bool controlActionInfo( sal_Int16 nControlId, ::rtl::OUString &rType ); + void sendAppendControlCommand( sal_Int16 nControlId ); +}; + +#endif // _UNXFILEPICKER_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/kde_unx/UnxNotifyThread.cxx b/fpicker/source/unx/kde_unx/UnxNotifyThread.cxx new file mode 100644 index 000000000000..657029025089 --- /dev/null +++ b/fpicker/source/unx/kde_unx/UnxNotifyThread.cxx @@ -0,0 +1,115 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <UnxNotifyThread.hxx> +#include <UnxFilePicker.hxx> + +using namespace ::com::sun::star; + +////////////////////////////////////////////////////////////////////////// +// UnxFilePickerNotifyThread +////////////////////////////////////////////////////////////////////////// + +UnxFilePickerNotifyThread::UnxFilePickerNotifyThread( UnxFilePicker *pUnxFilePicker ) + : m_pUnxFilePicker( pUnxFilePicker ), + m_bExit( sal_False ), + m_eNotifyType( Nothing ), + m_nControlId( 0 ) +{ +} + +void SAL_CALL UnxFilePickerNotifyThread::addFilePickerListener( const uno::Reference< ui::dialogs::XFilePickerListener >& xListener ) + throw( uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + m_xListener = xListener; +} + +void SAL_CALL UnxFilePickerNotifyThread::removeFilePickerListener( const uno::Reference< ui::dialogs::XFilePickerListener >& xListener ) + throw( uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + m_xListener.clear(); +} + +void SAL_CALL UnxFilePickerNotifyThread::exit() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + m_bExit = sal_True; + + m_aExitCondition.reset(); + m_aNotifyCondition.set(); + + m_aExitCondition.wait(); +} + +void SAL_CALL UnxFilePickerNotifyThread::fileSelectionChanged() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + m_eNotifyType = FileSelectionChanged; + m_nControlId = 0; + + m_aNotifyCondition.set(); +} + +void SAL_CALL UnxFilePickerNotifyThread::run() +{ + do { + m_aNotifyCondition.reset(); + m_aNotifyCondition.wait(); + + if ( m_xListener.is() && m_pUnxFilePicker ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + ui::dialogs::FilePickerEvent aEvent( *m_pUnxFilePicker, m_nControlId ); + + switch ( m_eNotifyType ) + { + case FileSelectionChanged: + m_xListener->fileSelectionChanged( aEvent ); + break; + + // TODO More to come... + + default: + // nothing + break; + } + } + } while ( !m_bExit ); + + m_aExitCondition.set(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/kde_unx/UnxNotifyThread.hxx b/fpicker/source/unx/kde_unx/UnxNotifyThread.hxx new file mode 100644 index 000000000000..b60d7b475871 --- /dev/null +++ b/fpicker/source/unx/kde_unx/UnxNotifyThread.hxx @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _UNXNOTIFYTHREAD_HXX_ +#define _UNXNOTIFYTHREAD_HXX_ + +#include <com/sun/star/ui/dialogs/XFilePickerListener.hpp> +#include <com/sun/star/uno/Reference.hxx> + +#include <osl/conditn.hxx> +#include <osl/mutex.hxx> +#include <osl/thread.hxx> + +class UnxFilePicker; + +class UnxFilePickerNotifyThread : public ::osl::Thread +{ +protected: + enum NotifyType + { + Nothing = 0, + FileSelectionChanged + // TODO More to come... + }; + + UnxFilePicker *m_pUnxFilePicker; + + ::osl::Mutex m_aMutex; + + ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener > m_xListener; + + sal_Bool m_bExit; + ::osl::Condition m_aExitCondition; + + NotifyType m_eNotifyType; + ::osl::Condition m_aNotifyCondition; + sal_Int16 m_nControlId; + +public: + UnxFilePickerNotifyThread( UnxFilePicker *pUnxFilePicker ); + + virtual void SAL_CALL addFilePickerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener >& xListener ) + throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL removeFilePickerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener >& xListener ) + throw( ::com::sun::star::uno::RuntimeException ); + + void SAL_CALL exit(); + + void SAL_CALL fileSelectionChanged(); + /* TODO + void SAL_CALL directoryChanged( ::com::sun::star::ui::dialogs::FilePickerEvent aEvent ); + rtl::OUString SAL_CALL helpRequested( ::com::sun::star::ui::dialogs::FilePickerEvent aEvent ) const; + void SAL_CALL controlStateChanged( ::com::sun::star::ui::dialogs::FilePickerEvent aEvent ); + void SAL_CALL dialogSizeChanged( ); + */ + +protected: + virtual void SAL_CALL run(); +}; + +#endif // _UNXNOTIFYTHREAD_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/unx/kde_unx/fps-kde-ucd.txt b/fpicker/source/unx/kde_unx/fps-kde-ucd.txt new file mode 100644 index 000000000000..28aa49d97bea --- /dev/null +++ b/fpicker/source/unx/kde_unx/fps-kde-ucd.txt @@ -0,0 +1,6 @@ +[ComponentDescriptor] +ImplementationName=com.sun.star.ui.dialogs.UnxFilePicker +ComponentName=fps_kde.uno.so +LoaderName=com.sun.star.loader.SharedLibrary +[SupportedServices] +com.sun.star.ui.dialogs.KDEFilePicker diff --git a/fpicker/source/unx/kde_unx/fps_kde.xml b/fpicker/source/unx/kde_unx/fps_kde.xml new file mode 100644 index 000000000000..99683bfecacf --- /dev/null +++ b/fpicker/source/unx/kde_unx/fps_kde.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + <module-name>fps_kde</module-name> + <component-description> + <author> Jan Holesovsky </author> + <name> com.sun.star.comp.ui.dialogs.FilePicker </name> + <description> + The KDE implementation of the FilePicker service. + </description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language> c++ </language> + <status value="beta"/> + <supported-service> com.sun.star.ui.dialogs.FilePicker </supported-service> + <service-dependency>...</service-dependency> + <type> com.sun.star.ui.dialogs.XExecutableDialog </type> + <type> com.sun.star.ui.dialogs.XFilePicker </type> + <type> com.sun.star.ui.dialogs.XFilterManager </type> + <type> com.sun.star.ui.dialogs.XFilterGroupManager </type> + <type> com.sun.star.ui.dialogs.XFilePickerListener </type> + <type> com.sun.star.ui.dialogs.ExecutableDialogException </type> + <type> com.sun.star.ui.dialogs.XFilePickerNotifier </type> + <type> com.sun.star.ui.dialogs.XFilePickerControlAccess </type> + <type> com.sun.star.ui.dialogs.XFilePreview </type> + <type> com.sun.star.ui.dialogs.ExtendedFilePickerElementIds </type> + <type> com.sun.star.ui.dialogs.ExecutableDialogResults </type> + <type> com.sun.star.ui.dialogs.FilePickerEvent </type> + <type> com.sun.star.ui.dialogs.CommonFilePickerElementIds </type> + <type> com.sun.star.ui.dialogs.ListboxControlActions </type> + <type> com.sun.star.ui.dialogs.TemplateDescription </type> + <type> com.sun.star.ui.dialogs.FilePreviewImageFormats </type> + <type> com.sun.star.util.XCancellable </type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.lang.IllegalArgumentException </type> + <type> com.sun.star.uno.TypeClass </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.uno.XAggregation </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.container.XSet </type> + </component-description> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> sal </project-build-dependency> + <runtime-module-dependency> cppuhelper </runtime-module-dependency> + <runtime-module-dependency> cppu2 </runtime-module-dependency> + <runtime-module-dependency> sal2 </runtime-module-dependency> +</module-description> diff --git a/fpicker/source/unx/kde_unx/makefile.mk b/fpicker/source/unx/kde_unx/makefile.mk new file mode 100644 index 000000000000..067399bf0837 --- /dev/null +++ b/fpicker/source/unx/kde_unx/makefile.mk @@ -0,0 +1,77 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# Copyright 2010 Novell, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=fpicker +TARGET=fps_kde.uno +LIBTARGET=NO +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +DLLPRE= + +# ------------------------------------------------------------------ + +# Currently just KDE is supported... +.IF "$(GUIBASE)" != "unx" || "$(ENABLE_KDE)" != "TRUE" + +dummy: + @echo "Nothing to build. GUIBASE == $(GUIBASE), ENABLE_KDE is not set" + +.ELSE # we build for KDE + +# --- Files -------------------------------------------------------- + +SLOFILES =\ + $(SLO)$/UnxCommandThread.obj \ + $(SLO)$/UnxFilePicker.obj \ + $(SLO)$/UnxNotifyThread.obj \ + $(SLO)$/UnxFPentry.obj + +SHL1NOCHECK=TRUE +SHL1TARGET=fps_kde.uno +SHL1STDLIBS=$(CPPULIB)\ + $(CPPUHELPERLIB)\ + $(SALLIB)\ + $(VCLLIB)\ + $(TOOLSLIB) + +SHL1OBJS=$(SLOFILES) +SHL1DEF=$(MISC)$/$(SHL1TARGET).def + +DEF1NAME=$(SHL1TARGET) +DEF1VERSIONMAP=$(SOLARENV)/src/component.map + +.ENDIF # "$(GUIBASE)" != "unx" || "$(ENABLE_KDE)" != "TRUE" + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/fpicker/source/win32/filepicker/FPServiceInfo.hxx b/fpicker/source/win32/filepicker/FPServiceInfo.hxx new file mode 100644 index 000000000000..33a27f683494 --- /dev/null +++ b/fpicker/source/win32/filepicker/FPServiceInfo.hxx @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _FPSERVICEINFO_HXX_ +#define _FPSERVICEINFO_HXX_ + +//------------------------------------------------------------------------ +// defines +//------------------------------------------------------------------------ + +// the service name is a description of a set of +// interfaces (is the same as component categories in COM) + +#define TMPL95_FILEOPEN_READONLY_VERSION_BOX_ID 1000 +#define TMPL2000_FILEOPEN_READONLY_VERSION_BOX_ID 1001 + +#define TMPL95_FILEOPEN_LINK_PREVIEW_BOX_ID 2000 +#define TMPL2000_FILEOPEN_LINK_PREVIEW_BOX_ID 2001 + +#define TMPL95_FILEOPEN_AUTOEXT_TEMPLATE_BOX_ID 3000 +#define TMPL2000_FILEOPEN_AUTOEXT_TEMPLATE_BOX_ID 3001 + +#define TMPL95_FILESAVE_AUTOEXT_PASSWORD_BOX_ID 4000 +#define TMPL2000_FILESAVE_AUTOEXT_PASSWORD_BOX_ID 4001 + +#define TMPL95_AUTOEXT_PASSWORD_FILTEROPTION_BOX 5000 +#define TMPL2000_AUTOEXT_PASSWORD_FILTEROPTION_BOX 5001 + +#define TMPL95_PLAY_PUSHBUTTON 6000 +#define TMPL2000_PLAY_PUSHBUTTON 6001 + +#define TMPL95_AUTOEXT_SELECTION_BOX 7000 +#define TMPL2000_AUTOEXT_SELECTION_BOX 7001 + +#define TMPL95_FILEOPEN_LINK_PREVIEW_BOX_SIMPLE_ID 8000 +#define TMPL2000_FILEOPEN_LINK_PREVIEW_BOX_SIMPLE_ID 8001 + +#define TMPL95_FILESAVE_AUTOEXT 9000 +#define TMPL2000_FILESAVE_AUTOEXT 9001 + +// the service names +#define FILE_PICKER_SERVICE_NAME "com.sun.star.ui.dialogs.SystemFilePicker" + +// the implementation names +#define FILE_PICKER_IMPL_NAME "com.sun.star.ui.dialogs.Win32FilePicker" + +// the registry key names +// a key under which this service will be registered, Format: -> "/ImplName/UNO/SERVICES/ServiceName" +// < Implementation-Name ></UNO/SERVICES/>< Service-Name > +#define FILE_PICKER_REGKEY_NAME "/com.sun.star.ui.dialogs.Win32FilePicker/UNO/SERVICES/com.sun.star.ui.dialogs.SystemFilePicker" + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/FPentry.cxx b/fpicker/source/win32/filepicker/FPentry.cxx new file mode 100644 index 000000000000..82eadcc4eb84 --- /dev/null +++ b/fpicker/source/win32/filepicker/FPentry.cxx @@ -0,0 +1,160 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +//---------------------------------------------- +// includes of other projects +//---------------------------------------------- +#include <cppuhelper/factory.hxx> +#include <com/sun/star/container/XSet.hpp> +#include <osl/diagnose.h> +#include "FilePicker.hxx" +#include "FPServiceInfo.hxx" + +#pragma warning (disable:4917) +#include "VistaFilePicker.hxx" +#include "..\misc\WinImplHelper.hxx" +#include <stdio.h> + +//----------------------------------------------- +// namespace directives +//----------------------------------------------- + +using namespace ::rtl ; +using namespace ::com::sun::star::uno ; +using namespace ::com::sun::star::container ; +using namespace ::com::sun::star::lang ; +using namespace ::com::sun::star::registry ; +using namespace ::cppu ; +using ::com::sun::star::ui::dialogs::XFilePicker; +using ::com::sun::star::ui::dialogs::XFilePicker2; + +//------------------------------------------------ +// +//------------------------------------------------ + +static Reference< XInterface > SAL_CALL createInstance( + const Reference< XMultiServiceFactory >& rServiceManager ) +{ + Reference< XInterface > xDlg; + bool bVistaOrNewer = IsWindowsVistaOrNewer(); + + if (bVistaOrNewer) + { + OSL_TRACE("use special (vista) system file picker ..."); + xDlg.set( + static_cast< XFilePicker2* >( + new ::fpicker::win32::vista::VistaFilePicker( rServiceManager ) ) ); + } + else + { + OSL_TRACE("use normal system file picker ..."); + xDlg.set( + static_cast< XFilePicker2* >( + new CFilePicker( rServiceManager ) ) ); + } + + return xDlg; +} + +//------------------------------------------------ +// the three uno functions that will be exported +//------------------------------------------------ + +extern "C" +{ + +//------------------------------------------------ +// component_getImplementationEnvironment +//------------------------------------------------ + +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +//------------------------------------------------ +// +//------------------------------------------------ + +sal_Bool SAL_CALL component_writeInfo( void*, void* pRegistryKey ) +{ + sal_Bool bRetVal = sal_True; + + if ( pRegistryKey ) + { + try + { + Reference< XRegistryKey > pXNewKey( static_cast< XRegistryKey* >( pRegistryKey ) ); + pXNewKey->createKey( OUString(RTL_CONSTASCII_USTRINGPARAM( FILE_PICKER_REGKEY_NAME ) )); + } + catch( InvalidRegistryException& ) + { + OSL_ENSURE( sal_False, "InvalidRegistryException caught" ); + bRetVal = sal_False; + } + } + + return bRetVal; +} + +//------------------------------------------------ +// +//------------------------------------------------ + +void* SAL_CALL component_getFactory( + const sal_Char* pImplName, uno_Interface* pSrvManager, uno_Interface* ) +{ + void* pRet = 0; + + if ( pSrvManager && ( 0 == rtl_str_compare( pImplName, FILE_PICKER_IMPL_NAME ) ) ) + { + Sequence< OUString > aSNS( 1 ); + aSNS.getArray( )[0] = OUString(RTL_CONSTASCII_USTRINGPARAM( FILE_PICKER_SERVICE_NAME )); + + Reference< XSingleServiceFactory > xFactory ( createSingleFactory( + reinterpret_cast< XMultiServiceFactory* > ( pSrvManager ), + OUString::createFromAscii( pImplName ), + createInstance, + aSNS ) ); + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + } + + return pRet; +} + +} // extern "C" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/FileOpenDlg.cxx b/fpicker/source/win32/filepicker/FileOpenDlg.cxx new file mode 100644 index 000000000000..125dd4e41eec --- /dev/null +++ b/fpicker/source/win32/filepicker/FileOpenDlg.cxx @@ -0,0 +1,700 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#define _WIN32_WINNT 0x0500 + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <tchar.h> +#include <osl/diagnose.h> +#include "../misc/WinImplHelper.hxx" +#include "FileOpenDlg.hxx" + +//------------------------------------------------------------------------ +// constants +//------------------------------------------------------------------------ + +namespace /* private */ +{ + // we choose such large buffers because the size of + // an single line edit field can be up to 32k; if + // a user has a multi selection FilePicker and selects + // a lot of files in a large directory we may reach this + // limit and don't want to get out of memory; + // another much more elegant way would be to subclass the + // FileOpen dialog and overload the BM_CLICK event of the + // OK button so that we determine the size of the text + // currently in the edit field and resize our buffer + // appropriately - in the future we will do this + const size_t MAX_FILENAME_BUFF_SIZE = 32000; + const size_t MAX_FILETITLE_BUFF_SIZE = 32000; + const size_t MAX_FILTER_BUFF_SIZE = 4096; + + const LPTSTR CURRENT_INSTANCE = TEXT("CurrInst"); + + //------------------------------------------ + // find an appropriate parent window + //------------------------------------------ + + inline bool is_current_process_window(HWND hwnd) + { + DWORD pid; + GetWindowThreadProcessId(hwnd, &pid); + return (pid == GetCurrentProcessId()); + } + + HWND choose_parent_window() + { + HWND hwnd_parent = GetForegroundWindow(); + if (!is_current_process_window(hwnd_parent)) + hwnd_parent = GetDesktopWindow(); + + return hwnd_parent; + } +}; + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +CFileOpenDialog::CFileOpenDialog( + bool bFileOpenDialog, + sal_uInt32 dwFlags, + sal_uInt32 dwTemplateId, + HINSTANCE hInstance) : + m_hwndFileOpenDlg(0), + m_hwndFileOpenDlgChild(0), + m_bFileOpenDialog(bFileOpenDialog), + m_filterBuffer(MAX_FILTER_BUFF_SIZE), + m_fileTitleBuffer(MAX_FILETITLE_BUFF_SIZE), + m_helperBuffer(MAX_FILENAME_BUFF_SIZE), + m_fileNameBuffer(MAX_FILENAME_BUFF_SIZE), + m_pfnBaseDlgProc(0) +{ + // initialize the OPENFILENAME struct + if (IsWindows2000Platform() || IsWindowsME()) + { + ZeroMemory(&m_ofn, sizeof(m_ofn)); + m_ofn.lStructSize = sizeof(m_ofn); + } + else // OSVER < Win2000 + { + // the size of the OPENFILENAME structure is different + // under windows < win2000 + ZeroMemory(&m_ofn, _OPENFILENAME_SIZE_VERSION_400); + m_ofn.lStructSize = _OPENFILENAME_SIZE_VERSION_400; + } + + // 0x02000000 for #97681, sfx will make the entry into + // the recent document list + m_ofn.Flags |= dwFlags | + OFN_EXPLORER | + OFN_ENABLEHOOK | + OFN_HIDEREADONLY | + OFN_PATHMUSTEXIST | + OFN_FILEMUSTEXIST | + OFN_OVERWRITEPROMPT | + OFN_ENABLESIZING | + OFN_DONTADDTORECENT; // 0x02000000 -> OFN_DONTADDTORECENT only available with new platform sdk + + // it is a little hack but how else could + // we get a parent window (using a vcl window?) + m_ofn.hwndOwner = choose_parent_window(); + + m_ofn.lpstrFile = reinterpret_cast<LPTSTR>(const_cast<sal_Unicode*>(m_fileNameBuffer.getStr())); + m_ofn.nMaxFile = m_fileNameBuffer.getCapacity(); + + m_ofn.lpstrFileTitle = reinterpret_cast<LPTSTR>(const_cast<sal_Unicode*>(m_fileTitleBuffer.getStr())); + m_ofn.nMaxFileTitle = m_fileTitleBuffer.getCapacity(); + + m_ofn.lpfnHook = CFileOpenDialog::ofnHookProc; + + // set a custom template + + if (dwTemplateId) + { + OSL_ASSERT(hInstance); + + m_ofn.Flags |= OFN_ENABLETEMPLATE; + m_ofn.lpTemplateName = MAKEINTRESOURCE(dwTemplateId); + m_ofn.hInstance = hInstance; + } + + // set a pointer to myself as ofn parameter + m_ofn.lCustData = reinterpret_cast<long>(this); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +CFileOpenDialog::~CFileOpenDialog() +{ +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void SAL_CALL CFileOpenDialog::setTitle(const rtl::OUString& aTitle) +{ + m_dialogTitle = aTitle; + m_ofn.lpstrTitle = reinterpret_cast<LPCTSTR>(m_dialogTitle.getStr()); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void CFileOpenDialog::setFilter(const rtl::OUString& aFilter) +{ + // Format is like + // "*.TXT" or multiple separate by ';' like "*.TXT;*.DOC;*.SXW" + // Do not include spaces in the pattern string + m_filterBuffer.ensureCapacity(aFilter.getLength()); + m_filterBuffer.setLength(0); + m_filterBuffer.append(aFilter); + m_ofn.lpstrFilter = reinterpret_cast<LPCTSTR>(m_filterBuffer.getStr()); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +bool CFileOpenDialog::setFilterIndex(sal_uInt32 aIndex) +{ + OSL_ASSERT(aIndex > 0); + m_ofn.nFilterIndex = aIndex; + return sal_True; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_uInt32 CFileOpenDialog::getSelectedFilterIndex() const +{ + return m_ofn.nFilterIndex; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void SAL_CALL CFileOpenDialog::setDefaultName(const rtl::OUString& aName) +{ + m_fileNameBuffer.setLength(0); + m_fileNameBuffer.append(aName); + m_ofn.lpstrFile = reinterpret_cast<LPTSTR>(const_cast<sal_Unicode*>(m_fileNameBuffer.getStr())); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void SAL_CALL CFileOpenDialog::setDisplayDirectory(const rtl::OUString& aDirectory) +{ + m_displayDirectory = aDirectory; + m_ofn.lpstrInitialDir = reinterpret_cast<LPCTSTR>(m_displayDirectory.getStr()); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +rtl::OUString SAL_CALL CFileOpenDialog::getLastDisplayDirectory() const +{ + return m_displayDirectory; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +rtl::OUString SAL_CALL CFileOpenDialog::getFullFileName() const +{ + return rtl::OUString(m_fileNameBuffer.getStr(), + _wcslenex(m_fileNameBuffer.getStr())); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +rtl::OUString SAL_CALL CFileOpenDialog::getFileName() const +{ + return rtl::OUString(m_fileTitleBuffer); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +rtl::OUString CFileOpenDialog::getFileExtension() +{ + if (m_ofn.nFileExtension) + return rtl::OUString(m_fileNameBuffer.getStr() + m_ofn.nFileExtension, + rtl_ustr_getLength(m_fileNameBuffer.getStr() + m_ofn.nFileExtension)); + + return rtl::OUString(); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void CFileOpenDialog::setDefaultFileExtension(const rtl::OUString& aExtension) +{ + m_defaultExtension = aExtension; + m_ofn.lpstrDefExt = reinterpret_cast<LPCTSTR>(m_defaultExtension.getStr()); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void SAL_CALL CFileOpenDialog::setMultiSelectionMode(bool bMode) +{ + if (bMode) + m_ofn.Flags |= OFN_ALLOWMULTISELECT; + else + m_ofn.Flags &= ~OFN_ALLOWMULTISELECT; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +bool SAL_CALL CFileOpenDialog::getMultiSelectionMode() const +{ + return ((m_ofn.Flags & OFN_ALLOWMULTISELECT) > 0); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_Int16 SAL_CALL CFileOpenDialog::doModal() +{ + sal_Int16 nRC = -1; + + // pre-processing + if (preModal()) + { + bool bRet; + + if (m_bFileOpenDialog) + bRet = m_GetFileNameWrapper.getOpenFileName( + reinterpret_cast<LPOPENFILENAME>(&m_ofn)); + else + bRet = m_GetFileNameWrapper.getSaveFileName( + reinterpret_cast<LPOPENFILENAME>(&m_ofn)); + + nRC = 1; + + if (!bRet) + nRC = (0 == m_GetFileNameWrapper.commDlgExtendedError()) ? 0 : -1; + + // post-processing + postModal(nRC); + } + + return nRC; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_uInt32 SAL_CALL CFileOpenDialog::getLastDialogError() const +{ + return CommDlgExtendedError(); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +bool SAL_CALL CFileOpenDialog::preModal() +{ + return sal_True; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void SAL_CALL CFileOpenDialog::postModal(sal_Int16 nDialogResult) +{ + OSL_ASSERT((-1 <= nDialogResult) && (nDialogResult <= 1)); + + if (1 == nDialogResult) + { + // Attention: assuming that nFileOffset is always greater 0 because under + // Windows there is always a drive letter or a server in a complete path + // the OPENFILENAME docu never says that nFileOffset can be 0 + m_displayDirectory = rtl::OUString(reinterpret_cast<const sal_Unicode*>(m_ofn.lpstrFile),m_ofn.nFileOffset); + } +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +rtl::OUString SAL_CALL CFileOpenDialog::getCurrentFilePath() const +{ + OSL_ASSERT(IsWindow(m_hwndFileOpenDlg)); + + LPARAM nLen = SendMessage( + m_hwndFileOpenDlg, + CDM_GETFILEPATH, + m_helperBuffer.getCapacity(), + reinterpret_cast<LPARAM>(m_helperBuffer.getStr())); + + if (nLen > 0) + { + m_helperBuffer.setLength((nLen * sizeof(sal_Unicode)) - 1); + return rtl::OUString(m_helperBuffer); + } + return rtl::OUString(); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +rtl::OUString SAL_CALL CFileOpenDialog::getCurrentFolderPath() const +{ + OSL_ASSERT(IsWindow(m_hwndFileOpenDlg)); + + LPARAM nLen = SendMessage( + m_hwndFileOpenDlg, + CDM_GETFOLDERPATH, + m_helperBuffer.getCapacity(), + reinterpret_cast<LPARAM>(m_helperBuffer.getStr())); + + if (nLen > 0) + { + m_helperBuffer.setLength((nLen * sizeof(sal_Unicode)) - 1); + return rtl::OUString(m_helperBuffer); + } + return rtl::OUString(); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +rtl::OUString SAL_CALL CFileOpenDialog::getCurrentFileName() const +{ + OSL_ASSERT(IsWindow(m_hwndFileOpenDlg)); + + LPARAM nLen = SendMessage( + m_hwndFileOpenDlg, + CDM_GETSPEC, + m_helperBuffer.getCapacity(), + reinterpret_cast<LPARAM>(m_helperBuffer.getStr())); + + if (nLen > 0) + { + m_helperBuffer.setLength((nLen * sizeof(sal_Unicode)) - 1); + return rtl::OUString(m_helperBuffer); + } + return rtl::OUString(); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_uInt32 SAL_CALL CFileOpenDialog::onShareViolation(const rtl::OUString&) +{ + return 0; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_uInt32 SAL_CALL CFileOpenDialog::onFileOk() +{ + return 0; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void SAL_CALL CFileOpenDialog::onSelChanged(HWND) +{ +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void SAL_CALL CFileOpenDialog::onHelp() +{ +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void SAL_CALL CFileOpenDialog::onInitDone() +{ + centerPositionToParent(); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void SAL_CALL CFileOpenDialog::onFolderChanged() +{ +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void SAL_CALL CFileOpenDialog::onTypeChanged(sal_uInt32) +{ +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_uInt32 SAL_CALL CFileOpenDialog::onCtrlCommand(HWND, sal_uInt16, sal_uInt16) +{ + return 0; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_uInt32 SAL_CALL CFileOpenDialog::onWMNotify( HWND, LPOFNOTIFY lpOfNotify ) +{ + switch(lpOfNotify->hdr.code) + { + case CDN_SHAREVIOLATION: + return onShareViolation(reinterpret_cast<const sal_Unicode*>(lpOfNotify->pszFile)); + + case CDN_FILEOK: + return onFileOk(); + + case CDN_SELCHANGE: + onSelChanged(lpOfNotify->hdr.hwndFrom); + break; + + case CDN_HELP: + onHelp(); + break; + + case CDN_INITDONE: + onInitDone(); + break; + + case CDN_FOLDERCHANGE: + onFolderChanged(); + break; + + case CDN_TYPECHANGE: + m_ofn.nFilterIndex = lpOfNotify->lpOFN->nFilterIndex; + onTypeChanged(lpOfNotify->lpOFN->nFilterIndex); + break; + } + + return 0; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void SAL_CALL CFileOpenDialog::handleInitDialog(HWND hwndDlg, HWND hwndChild) +{ + m_hwndFileOpenDlg = hwndDlg; + m_hwndFileOpenDlgChild = hwndChild; + + OSL_ASSERT(GetParent(hwndChild) == hwndDlg); + + // calling virtual function which the + // client can overload + onInitDialog(hwndDlg); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +unsigned int CALLBACK CFileOpenDialog::ofnHookProc( + HWND hChildDlg, unsigned int uiMsg, WPARAM wParam, LPARAM lParam) +{ + HWND hwndDlg = GetParent(hChildDlg); + CFileOpenDialog* pImpl = NULL; + + switch( uiMsg ) + { + case WM_INITDIALOG: + { + _LPOPENFILENAME lpofn = reinterpret_cast<_LPOPENFILENAME>(lParam); + pImpl = reinterpret_cast<CFileOpenDialog*>(lpofn->lCustData); + OSL_ASSERT(pImpl); + + // subclass the base dialog for WM_NCDESTROY processing + pImpl->m_pfnBaseDlgProc = + reinterpret_cast<WNDPROC>( + SetWindowLong( + hwndDlg, + GWL_WNDPROC, + reinterpret_cast<LONG>(CFileOpenDialog::BaseDlgProc))); + // connect the instance handle to the window + SetProp(hwndDlg, CURRENT_INSTANCE, pImpl); + pImpl->handleInitDialog(hwndDlg, hChildDlg); + } + return 0; + + case WM_NOTIFY: + { + pImpl = getCurrentInstance(hwndDlg); + return pImpl->onWMNotify( + hChildDlg, reinterpret_cast<LPOFNOTIFY>(lParam)); + } + + case WM_COMMAND: + { + pImpl = getCurrentInstance(hwndDlg); + OSL_ASSERT(pImpl); + + return pImpl->onCtrlCommand( + hChildDlg, LOWORD(wParam), HIWORD(lParam)); + } + } + + return 0; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +LRESULT CALLBACK CFileOpenDialog::BaseDlgProc( + HWND hWnd, UINT wMessage, WPARAM wParam, LPARAM lParam) +{ + CFileOpenDialog* pImpl = 0; + + if (WM_NCDESTROY == wMessage) + { + pImpl = reinterpret_cast<CFileOpenDialog*>( + RemoveProp(hWnd,CURRENT_INSTANCE)); + + SetWindowLong(hWnd, GWL_WNDPROC, + reinterpret_cast<LONG>(pImpl->m_pfnBaseDlgProc)); + } + else + { + pImpl = getCurrentInstance(hWnd); + } + + OSL_ASSERT(pImpl); + + return CallWindowProc( + reinterpret_cast<WNDPROC>(pImpl->m_pfnBaseDlgProc), + hWnd,wMessage,wParam,lParam); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +CFileOpenDialog* SAL_CALL CFileOpenDialog::getCurrentInstance(HWND hwnd) +{ + OSL_ASSERT(IsWindow( hwnd)); + return reinterpret_cast<CFileOpenDialog*>( + GetProp(hwnd, CURRENT_INSTANCE)); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void SAL_CALL CFileOpenDialog::centerPositionToParent() const +{ + OSL_PRECOND(IsWindow(m_hwndFileOpenDlg), "no dialog window, call method only after or in onInitDone"); + + HWND hwndParent = m_ofn.hwndOwner; + + if (!IsWindow(hwndParent)) + hwndParent = GetDesktopWindow(); + + OSL_ASSERT(IsWindow(hwndParent)); + + RECT rcPar; + GetWindowRect(hwndParent, &rcPar); + + RECT rcDlg; + GetWindowRect(m_hwndFileOpenDlg, &rcDlg); + + int lDlgW = rcDlg.right - rcDlg.left; + int lDlgH = rcDlg.bottom - rcDlg.top; + + int x = (rcPar.left + rcPar.right - lDlgW) / 2; + int y = (rcPar.top + rcPar.bottom - lDlgH) / 2; + + HDC hdc = GetDC(m_hwndFileOpenDlg); + + int hResol = GetDeviceCaps(hdc, HORZRES); + int vResol = GetDeviceCaps(hdc, VERTRES); + + ReleaseDC(m_hwndFileOpenDlg, hdc); + + if (x < 0) + x = 0; + else if ((x + lDlgW) > hResol) + x = hResol - lDlgW; + + if (y < 0) + y = 0; + else if ((y + lDlgH) > vResol) + y = vResol - lDlgH; + + SetWindowPos( + m_hwndFileOpenDlg, + NULL, x, y, 0, 0, + SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/FileOpenDlg.hxx b/fpicker/source/win32/filepicker/FileOpenDlg.hxx new file mode 100644 index 000000000000..a5297e7b07cf --- /dev/null +++ b/fpicker/source/win32/filepicker/FileOpenDlg.hxx @@ -0,0 +1,328 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FILEOPENDLG_HXX_ +#define _FILEOPENDLG_HXX_ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <sal/types.h> + +#include <rtl/ustring.hxx> +#include <rtl/ustrbuf.hxx> + +#include "platform_xp.h" +#include "getfilenamewrapper.hxx" + +// because we don't want to import the new W2k platform skd +// into our build environment if have stolen the definition +// for the new OPENFILENAME structure from the new headers + +#ifndef _CDSIZEOF_STRUCT +#define _CDSIZEOF_STRUCT(structname, member) (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member)) +#endif + +typedef struct _tagOFNA { + DWORD lStructSize; + HWND hwndOwner; + HINSTANCE hInstance; + LPCSTR lpstrFilter; + LPSTR lpstrCustomFilter; + DWORD nMaxCustFilter; + DWORD nFilterIndex; + LPSTR lpstrFile; + DWORD nMaxFile; + LPSTR lpstrFileTitle; + DWORD nMaxFileTitle; + LPCSTR lpstrInitialDir; + LPCSTR lpstrTitle; + DWORD Flags; + WORD nFileOffset; + WORD nFileExtension; + LPCSTR lpstrDefExt; + LPARAM lCustData; + LPOFNHOOKPROC lpfnHook; + LPCSTR lpTemplateName; +#ifdef _MAC + LPEDITMENU lpEditInfo; + LPCSTR lpstrPrompt; +#endif +#if (_WIN32_WINNT >= 0x0500) + void * pvReserved; + DWORD dwReserved; + DWORD FlagsEx; +#endif // (_WIN32_WINNT >= 0x0500) +} _OPENFILENAMEA, *_LPOPENFILENAMEA; + +typedef struct _tagOFNW { + DWORD lStructSize; + HWND hwndOwner; + HINSTANCE hInstance; + LPCWSTR lpstrFilter; + LPWSTR lpstrCustomFilter; + DWORD nMaxCustFilter; + DWORD nFilterIndex; + LPWSTR lpstrFile; + DWORD nMaxFile; + LPWSTR lpstrFileTitle; + DWORD nMaxFileTitle; + LPCWSTR lpstrInitialDir; + LPCWSTR lpstrTitle; + DWORD Flags; + WORD nFileOffset; + WORD nFileExtension; + LPCWSTR lpstrDefExt; + LPARAM lCustData; + LPOFNHOOKPROC lpfnHook; + LPCWSTR lpTemplateName; +#if (_WIN32_WINNT >= 0x0500) + void * pvReserved; + DWORD dwReserved; + DWORD FlagsEx; +#endif // (_WIN32_WINNT >= 0x0500) +} _OPENFILENAMEW, *_LPOPENFILENAMEW; + +#ifdef UNICODE +typedef _OPENFILENAMEW _OPENFILENAME; +typedef _LPOPENFILENAMEW _LPOPENFILENAME; +#else +typedef _OPENFILENAMEA _OPENFILENAME; +typedef _LPOPENFILENAMEA _LPOPENFILENAME; +#endif // UNICODE + +#if (_WIN32_WINNT >= 0x0500) + #define _OPENFILENAME_SIZE_VERSION_400A _CDSIZEOF_STRUCT(_OPENFILENAMEA,lpTemplateName) + #define _OPENFILENAME_SIZE_VERSION_400W _CDSIZEOF_STRUCT(_OPENFILENAMEW,lpTemplateName) + #ifdef UNICODE + #define _OPENFILENAME_SIZE_VERSION_400 _OPENFILENAME_SIZE_VERSION_400W + #else + #define _OPENFILENAME_SIZE_VERSION_400 _OPENFILENAME_SIZE_VERSION_400A + #endif // !UNICODE +#else + #error _WIN32_WINNT seams not to be valid. +#endif // (_WIN32_WINNT >= 0x0500) + + +//------------------------------------------------------------- +// A simple wrapper class around the Win32 GetOpenFileName API. +// This class is not thread-safe and only one instance at a +// time is allowed +//------------------------------------------------------------- + +class CFileOpenDialog +{ +public: + // ctor + // bFileOpenDialog idicates if we want a FileOpen or FileSave + // dialog + // dwFlags see OPENFILENAME + // dwTemplateId - an ID for custom templates + // hInstance - an instance handle for the module + // which provides the custom template, unused if dwTemplateId + // is 0 + CFileOpenDialog( + bool bFileOpenDialog = sal_True, + sal_uInt32 dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + sal_uInt32 dwTemplateId = 0, + HINSTANCE hInstance = 0); + + virtual ~CFileOpenDialog(); + + virtual void SAL_CALL setTitle(const rtl::OUString& aTitle); + + // to set a filter string using the M$ format + // e.g. FltName\0*.txt;*.rtf\0...\0\0 + void SAL_CALL setFilter(const rtl::OUString& aFilter); + + // set the index of the current filter when the + // dialog is about to shown, the index starts with 1 + // the function succeeded if the given filter index + // is greater than zero and is a valid position + // within filter string that was previously set + bool SAL_CALL setFilterIndex(sal_uInt32 aIndex); + + // get the index of the currently selected filter + // the index of the returned filter starts with 1 + sal_uInt32 SAL_CALL getSelectedFilterIndex() const; + + // set the name and optional the path of the + // file that will be initially be shown when + // the dialog will be displayed + virtual void SAL_CALL setDefaultName(const rtl::OUString& aName); + + // set the initial directory + virtual void SAL_CALL setDisplayDirectory(const rtl::OUString& aDirectory); + + // returns only the path of the selected file + virtual rtl::OUString SAL_CALL getLastDisplayDirectory() const; + + // returns the full file name including drive letter, path + // file name and file extension + virtual rtl::OUString SAL_CALL getFullFileName() const; + + // returns the file name and the file extension without + // drive letter and path + rtl::OUString SAL_CALL getFileName() const; + + // returns the file extension of the selected file + rtl::OUString SAL_CALL getFileExtension(); + + // set a default extension, only the first three letters of + // the given extension will be used; the given extension + // should not contain a '.' + void SAL_CALL setDefaultFileExtension(const rtl::OUString& aExtension); + + // enables or disables the multiselection mode for + // the FileOpen/FileSave dialog + void SAL_CALL setMultiSelectionMode(bool bMode); + + // returns whether multi-selection mode is enabled or not + bool SAL_CALL getMultiSelectionMode() const; + + // shows the dialog, calls preModal before + // showing the dialog and postModal after + // showing the dialog + // the method returns: + // 0 - when the dialog was canceled by the user + // 1 - when the dialog was closed with ok + // -1 - when an error occured + sal_Int16 SAL_CALL doModal(); + + // returns the last dialog error that occured + sal_uInt32 SAL_CALL getLastDialogError() const; + + // retrievs the currently selected file + // including path and drive information + // can be called only if the dialog is + // already displayed + rtl::OUString SAL_CALL getCurrentFilePath() const; + + // retrievs the currently selected folder + rtl::OUString SAL_CALL getCurrentFolderPath() const; + + // retrievs the currently selected file name + // without drive and path + rtl::OUString SAL_CALL getCurrentFileName() const; + +protected: + // have to be overwritten when subclasses + // want to do special pre- and post-modal + // processing + + // if preModal return true processing will + // continue else doModal exit without showing + // a dialog and returns -1 + virtual bool SAL_CALL preModal(); + + // post modal processing + // the function should accept only values returned from + // doModal and act appropriately + virtual void SAL_CALL postModal(sal_Int16 nDialogResult); + + // message handler, to be overwritten by subclasses + virtual sal_uInt32 SAL_CALL onShareViolation(const rtl::OUString& aPathName); + virtual sal_uInt32 SAL_CALL onFileOk(); + virtual void SAL_CALL onSelChanged(HWND hwndListBox); + virtual void SAL_CALL onHelp(); + + // only called back if OFN_EXPLORER is set + virtual void SAL_CALL onInitDone(); + virtual void SAL_CALL onFolderChanged(); + virtual void SAL_CALL onTypeChanged(sal_uInt32 nFilterIndex); + + virtual void SAL_CALL onInitDialog(HWND hwndDlg) = 0; + + virtual sal_uInt32 SAL_CALL onCtrlCommand(HWND hwndDlg, sal_uInt16 ctrlId, sal_uInt16 notifyCode); + + sal_uInt32 SAL_CALL onWMNotify(HWND hwndChild, LPOFNOTIFYW lpOfNotify); + + // we use non-virtual functions to do necessary work before + // calling the virtual funtions (see Gamma: Template method) + void SAL_CALL handleInitDialog(HWND hwndDlg, HWND hwndChild); + +protected: + + // handle to the window of the + // FileOpen/FileSave dialog + // will be set on message + // WM_INITDIALOG, before this + // value is undefined + HWND m_hwndFileOpenDlg; + HWND m_hwndFileOpenDlgChild; + + _OPENFILENAME m_ofn; + + // we connect the instance with the dialog window using + // SetProp, with this function we can reconnect from + // callback functions to this instance + static CFileOpenDialog* SAL_CALL getCurrentInstance(HWND hwnd); + + void SAL_CALL centerPositionToParent() const; + +private: + // FileOpen or FileSaveDialog + bool m_bFileOpenDialog; + rtl::OUString m_dialogTitle; + rtl::OUString m_displayDirectory; + rtl::OUString m_defaultExtension; + + mutable rtl::OUStringBuffer m_filterBuffer; + mutable rtl::OUStringBuffer m_fileTitleBuffer; + mutable rtl::OUStringBuffer m_helperBuffer; + mutable rtl::OUStringBuffer m_fileNameBuffer; + + CGetFileNameWrapper m_GetFileNameWrapper; + + WNDPROC m_pfnBaseDlgProc; + + // callback function + static unsigned int CALLBACK ofnHookProc( + HWND hChildDlg, // handle to child dialog box + unsigned int uiMsg, // message identifier + WPARAM wParam, // message parameter + LPARAM lParam // message parameter + ); + + // we have to subclass the dialog in order + // to clean up the window property we are + // using to connect the window with a class + // instance in WM_NCDESTROY + static LRESULT CALLBACK BaseDlgProc( + HWND hWnd, UINT wMessage, WPARAM wParam, LPARAM lParam ); + +private: + // avoid copy and assignment + CFileOpenDialog(const CFileOpenDialog&); + CFileOpenDialog& operator=(const CFileOpenDialog&); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/FilePicker.cxx b/fpicker/source/win32/filepicker/FilePicker.cxx new file mode 100644 index 000000000000..545c54b9fa3f --- /dev/null +++ b/fpicker/source/win32/filepicker/FilePicker.cxx @@ -0,0 +1,800 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <tchar.h> +#include <com/sun/star/lang/DisposedException.hpp> +#include <cppuhelper/interfacecontainer.h> +#include <osl/diagnose.h> + +#include "filepicker.hxx" +#include "WinFileOpenImpl.hxx" + +#include "FPServiceInfo.hxx" +#include "..\misc\WinImplHelper.hxx" +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include "filepickereventnotification.hxx" + +#include <comphelper/sequenceasvector.hxx> + +//------------------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------------------ + +using namespace com::sun::star; + +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::ui::dialogs::TemplateDescription; + +//------------------------------------------------------------------------ +// defines +//------------------------------------------------------------------------ + +#define FILE_PICKER_DLL_NAME TEXT("fps.dll") + +//------------------------------------------------------------------------ +// helper functions +//------------------------------------------------------------------------ + +namespace +{ + // controling event notifications + const bool STARTUP_SUSPENDED = true; + const bool STARTUP_ALIVE = false; + + uno::Sequence<rtl::OUString> SAL_CALL FilePicker_getSupportedServiceNames() + { + uno::Sequence<rtl::OUString> aRet(2); + aRet[0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ui.dialogs.FilePicker")); + aRet[1] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ui.dialogs.SystemFilePicker")); + return aRet; + } +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +CFilePicker::CFilePicker( const uno::Reference<lang::XMultiServiceFactory>& xServiceMgr) : + cppu::WeakComponentImplHelper10< + XFilterManager, + XFilterGroupManager, + XFilePickerControlAccess, + XFilePickerNotifier, + XFilePreview, + XFilePicker2, + lang::XInitialization, + util::XCancellable, + lang::XEventListener, + lang::XServiceInfo>(m_rbHelperMtx), + m_xServiceMgr(xServiceMgr), + m_aAsyncEventNotifier(rBHelper) +{ + HINSTANCE hInstance = GetModuleHandle(FILE_PICKER_DLL_NAME); + OSL_POSTCOND( hInstance, "The name of the service dll must have changed" ); + + // create a default FileOpen dialog without any additional ui elements + m_pImpl = std::auto_ptr< CWinFileOpenImpl >( + new CWinFileOpenImpl( + this, + true, + 0, + 0, + hInstance ) ); +} + +//------------------------------------------------------------------------------------ +// XFPEventListenerManager +//------------------------------------------------------------------------------------ + +void SAL_CALL CFilePicker::addFilePickerListener(const uno::Reference<XFilePickerListener>& xListener) + throw(uno::RuntimeException) +{ + if ( rBHelper.bDisposed ) + throw lang::DisposedException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "object is already disposed" )), + static_cast< XFilePicker2* >( this ) ); + + if ( !rBHelper.bInDispose && !rBHelper.bDisposed ) + rBHelper.aLC.addInterface( getCppuType( &xListener ), xListener ); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL CFilePicker::removeFilePickerListener(const uno::Reference<XFilePickerListener>& xListener ) + throw(uno::RuntimeException) +{ + if ( rBHelper.bDisposed ) + throw lang::DisposedException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "object is already disposed" )), + static_cast< XFilePicker2* >( this ) ); + + rBHelper.aLC.removeInterface( getCppuType( &xListener ), xListener ); +} + +// ------------------------------------------------- +// XEventListener +// ------------------------------------------------- + +void SAL_CALL CFilePicker::disposing(const lang::EventObject& aEvent) throw(uno::RuntimeException) +{ + uno::Reference<XFilePickerListener> xFilePickerListener(aEvent.Source, ::com::sun::star::uno::UNO_QUERY); + + if (xFilePickerListener.is()) + removeFilePickerListener(xFilePickerListener); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL CFilePicker::fileSelectionChanged(FilePickerEvent aEvent) +{ + aEvent.Source = uno::Reference<uno::XInterface>(static_cast<XFilePickerNotifier*>(this)); + m_aAsyncEventNotifier.notifyEvent( + new CFilePickerParamEventNotification(&XFilePickerListener::fileSelectionChanged,aEvent)); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL CFilePicker::directoryChanged(FilePickerEvent aEvent) +{ + aEvent.Source = uno::Reference<uno::XInterface>(static_cast<XFilePickerNotifier*>(this)); + m_aAsyncEventNotifier.notifyEvent( + new CFilePickerParamEventNotification(&XFilePickerListener::directoryChanged,aEvent)); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL CFilePicker::controlStateChanged(FilePickerEvent aEvent) +{ + aEvent.Source = uno::Reference<uno::XInterface>(static_cast<XFilePickerNotifier*>(this)); + m_aAsyncEventNotifier.notifyEvent( + new CFilePickerParamEventNotification(&XFilePickerListener::controlStateChanged,aEvent)); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL CFilePicker::dialogSizeChanged() +{ + m_aAsyncEventNotifier.notifyEvent( + new CFilePickerEventNotification(&XFilePickerListener::dialogSizeChanged)); +} + +//----------------------------------------------------------------------------------------- +// If there are more then one listener the return value of the last one wins +//----------------------------------------------------------------------------------------- + +rtl::OUString SAL_CALL CFilePicker::helpRequested(FilePickerEvent aEvent) const +{ + rtl::OUString aHelpText; + + ::cppu::OInterfaceContainerHelper* pICHelper = + rBHelper.getContainer( getCppuType((uno::Reference<XFilePickerListener>*)0)); + + if (pICHelper) + { + ::cppu::OInterfaceIteratorHelper iter(*pICHelper); + + while(iter.hasMoreElements()) + { + try + { + /* + if there are multiple listeners responding + to this notification the next response + overwrittes the one before if it is not empty + */ + + rtl::OUString temp; + + uno::Reference<XFilePickerListener> xFPListener(iter.next(), uno::UNO_QUERY); + if (xFPListener.is()) + { + temp = xFPListener->helpRequested(aEvent); + if (temp.getLength()) + aHelpText = temp; + } + + } + catch(uno::RuntimeException&) + { + OSL_ENSURE( false, "RuntimeException during event dispatching" ); + } + } + } + + return aHelpText; +} + +//------------------------------------- +// +//------------------------------------- + +bool CFilePicker::startupEventNotification(bool bStartupSuspended) +{ + return m_aAsyncEventNotifier.startup(bStartupSuspended); +} + +//------------------------------------- +// +//------------------------------------- + +void CFilePicker::shutdownEventNotification() +{ + m_aAsyncEventNotifier.shutdown(); +} + +//------------------------------------- +// +//------------------------------------- + +void CFilePicker::suspendEventNotification() +{ + m_aAsyncEventNotifier.suspend(); +} + +//------------------------------------- +// +//------------------------------------- + +void CFilePicker::resumeEventNotification() +{ + m_aAsyncEventNotifier.resume(); +} + +//------------------------------------------------------------------------------------ +// XFilePicker functions +//------------------------------------------------------------------------------------ + +void SAL_CALL CFilePicker::setMultiSelectionMode(sal_Bool bMode) throw(uno::RuntimeException) +{ + OSL_ASSERT(0 != m_pImpl.get()); + osl::MutexGuard aGuard(m_aMutex); + m_pImpl->setMultiSelectionMode(bMode); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL CFilePicker::setTitle(const rtl::OUString& aTitle) throw(uno::RuntimeException) +{ + OSL_ASSERT(0 != m_pImpl.get()); + osl::MutexGuard aGuard(m_aMutex); + m_pImpl->setTitle(aTitle); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL CFilePicker::appendFilter(const rtl::OUString& aTitle, const rtl::OUString& aFilter) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + OSL_ASSERT(0 != m_pImpl.get()); + osl::MutexGuard aGuard(m_aMutex); + m_pImpl->appendFilter(aTitle, aFilter); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL CFilePicker::setCurrentFilter(const rtl::OUString& aTitle) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + OSL_ASSERT(0 != m_pImpl.get()); + osl::MutexGuard aGuard(m_aMutex); + m_pImpl->setCurrentFilter(aTitle); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +rtl::OUString SAL_CALL CFilePicker::getCurrentFilter() throw(uno::RuntimeException) +{ + OSL_ASSERT(0 != m_pImpl.get()); + osl::MutexGuard aGuard(m_aMutex); + return m_pImpl->getCurrentFilter(); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL CFilePicker::appendFilterGroup(const rtl::OUString& sGroupTitle, const uno::Sequence<beans::StringPair>& aFilters) + throw (lang::IllegalArgumentException, uno::RuntimeException) +{ + OSL_ASSERT(0 != m_pImpl.get()); + osl::MutexGuard aGuard(m_aMutex); + m_pImpl->appendFilterGroup(sGroupTitle, aFilters); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL CFilePicker::setDefaultName(const rtl::OUString& aName) + throw(uno::RuntimeException) +{ + OSL_ASSERT(0 != m_pImpl.get()); + osl::MutexGuard aGuard(m_aMutex); + m_pImpl->setDefaultName(aName); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL CFilePicker::setDisplayDirectory(const rtl::OUString& aDirectory) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + OSL_ASSERT(0 != m_pImpl.get()); + osl::MutexGuard aGuard(m_aMutex); + m_pImpl->setDisplayDirectory(aDirectory); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +rtl::OUString SAL_CALL CFilePicker::getDisplayDirectory() throw(uno::RuntimeException) +{ + OSL_ASSERT(0 != m_pImpl.get()); + osl::MutexGuard aGuard(m_aMutex); + return m_pImpl->getDisplayDirectory(); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +uno::Sequence<rtl::OUString> SAL_CALL CFilePicker::getFiles() throw(uno::RuntimeException) +{ + OSL_ASSERT(0 != m_pImpl.get()); + osl::MutexGuard aGuard(m_aMutex); + return m_pImpl->getFiles(); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- +uno::Sequence< ::rtl::OUString > SAL_CALL CFilePicker::getSelectedFiles() throw (uno::RuntimeException) +{ + OSL_ASSERT(0 != m_pImpl.get()); + osl::MutexGuard aGuard(m_aMutex); + + const uno::Sequence< ::rtl::OUString > lSource = m_pImpl->getFiles(); + const ::sal_Int32 c = lSource.getLength(); + if (c < 2) + return lSource; + + const ::rtl::OUString sPath = lSource[0]; + ::comphelper::SequenceAsVector< ::rtl::OUString > lTarget; + ::sal_Int32 i = 1; + for (i=1; i<c; ++i) + { + const ::rtl::OUString sFile = lSource[i]; + if (sFile.indexOf ('/') > 0) + { + // a) file contains own path ! + lTarget.push_back(sFile); + } + else + { + // b) file is relative to given path + ::rtl::OUStringBuffer sFull(256); + + sFull.append (sPath); + sFull.appendAscii("/" ); + sFull.append (sFile); + + lTarget.push_back(sFull.makeStringAndClear()); + } + } + + return lTarget.getAsConstList(); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +sal_Int16 SAL_CALL CFilePicker::execute() throw(uno::RuntimeException) +{ + OSL_ASSERT(0 != m_pImpl.get()); + + sal_Int16 ret; + + if (startupEventNotification(STARTUP_SUSPENDED)) + { + // we should not block in this call else + // in the case of an event the client can't + // call another function an we run into a + // deadlock !!!!! + ret = m_pImpl->execute( ); + + shutdownEventNotification(); + } + else + { + OSL_ENSURE(sal_False, "Could not start event notifier thread!"); + + throw uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Error executing dialog")), + static_cast<XFilePicker2*>(this)); + } + + return ret; +} + +//------------------------------------------------------------------------------------ +// XFilePicker functions +//------------------------------------------------------------------------------------ + +void SAL_CALL CFilePicker::setValue(sal_Int16 aControlId, sal_Int16 aControlAction, const uno::Any& aValue) + throw(uno::RuntimeException) +{ + OSL_ASSERT(0 != m_pImpl.get()); + + osl::MutexGuard aGuard(m_aMutex); + m_pImpl->setValue(aControlId, aControlAction, aValue); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +uno::Any SAL_CALL CFilePicker::getValue(sal_Int16 aControlId, sal_Int16 aControlAction) + throw(uno::RuntimeException) +{ + OSL_ASSERT(0 != m_pImpl.get()); + + osl::MutexGuard aGuard(m_aMutex); + return m_pImpl->getValue(aControlId, aControlAction); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL CFilePicker::enableControl(sal_Int16 aControlId, sal_Bool bEnable) +throw(uno::RuntimeException) +{ + OSL_ASSERT( 0 != m_pImpl.get( ) ); + + osl::MutexGuard aGuard( m_aMutex ); + m_pImpl->enableControl( aControlId, bEnable ); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL CFilePicker::setLabel(sal_Int16 aControlId, const ::rtl::OUString& aLabel) + throw (uno::RuntimeException) +{ + OSL_ASSERT(0 != m_pImpl.get()); + + osl::MutexGuard aGuard(m_aMutex); + m_pImpl->setLabel(aControlId, aLabel); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +rtl::OUString SAL_CALL CFilePicker::getLabel(sal_Int16 aControlId) + throw (uno::RuntimeException) +{ + OSL_ASSERT(0 != m_pImpl.get()); + + osl::MutexGuard aGuard(m_aMutex); + return m_pImpl->getLabel(aControlId); +} + +//------------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------------ + +uno::Sequence<sal_Int16> SAL_CALL CFilePicker::getSupportedImageFormats() throw (uno::RuntimeException) +{ + OSL_ASSERT(0 != m_pImpl.get()); + + osl::MutexGuard aGuard(m_aMutex); + return m_pImpl->getSupportedImageFormats(); +} + +//------------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------------ + +sal_Int32 SAL_CALL CFilePicker::getTargetColorDepth() throw (uno::RuntimeException) +{ + OSL_ASSERT(0 != m_pImpl.get()); + + osl::MutexGuard aGuard(m_aMutex); + return m_pImpl->getTargetColorDepth(); +} + +//------------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------------ + +sal_Int32 SAL_CALL CFilePicker::getAvailableWidth() throw (uno::RuntimeException) +{ + OSL_ASSERT(0 != m_pImpl.get()); + + osl::MutexGuard aGuard(m_aMutex); + return m_pImpl->getAvailableWidth(); +} + +//------------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------------ + +sal_Int32 SAL_CALL CFilePicker::getAvailableHeight() throw (uno::RuntimeException) +{ + OSL_ASSERT(0 != m_pImpl.get()); + + osl::MutexGuard aGuard(m_aMutex); + return m_pImpl->getAvailableHeight(); +} + +//------------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------------ + +void SAL_CALL CFilePicker::setImage(sal_Int16 aImageFormat, const uno::Any& aImage) + throw (lang::IllegalArgumentException, uno::RuntimeException) +{ + OSL_ASSERT(0 != m_pImpl.get()); + + osl::MutexGuard aGuard(m_aMutex); + m_pImpl->setImage(aImageFormat, aImage); +} + +//------------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------------ + +sal_Bool SAL_CALL CFilePicker::setShowState(sal_Bool bShowState) throw (uno::RuntimeException) +{ + OSL_ASSERT(0 != m_pImpl.get()); + + osl::MutexGuard aGuard(m_aMutex); + return m_pImpl->setShowState(bShowState); +} + +//------------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------------ + +sal_Bool SAL_CALL CFilePicker::getShowState() throw (uno::RuntimeException) +{ + OSL_ASSERT(0 != m_pImpl.get()); + + osl::MutexGuard aGuard(m_aMutex); + return m_pImpl->getShowState(); +} + +//------------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------------ + +void SAL_CALL CFilePicker::initialize(const uno::Sequence<uno::Any>& aArguments) + throw( uno::Exception, uno::RuntimeException) +{ + // parameter checking + uno::Any aAny; + if ( 0 == aArguments.getLength( ) ) + throw lang::IllegalArgumentException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "no arguments" )), + static_cast<XFilePicker2*>(this), 1); + + aAny = aArguments[0]; + + if ( (aAny.getValueType() != ::getCppuType((sal_Int16*)0)) && + (aAny.getValueType() != ::getCppuType((sal_Int8*)0)) ) + throw lang::IllegalArgumentException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("invalid argument type")), + static_cast<XFilePicker2*>(this), 1); + + sal_Int16 templateId = -1; + aAny >>= templateId; + + sal_Bool bFileOpenDialog = sal_True; + sal_uInt32 winResTemplateId = 0; + sal_Bool bIsWin2000 = IsWindows2000Platform(); + + switch ( templateId ) + { + case FILEOPEN_SIMPLE: + bFileOpenDialog = sal_True; + break; + + case FILESAVE_SIMPLE: + bFileOpenDialog = sal_False; + break; + + case FILESAVE_AUTOEXTENSION_PASSWORD: + bFileOpenDialog = sal_False; + if ( bIsWin2000 ) + winResTemplateId = TMPL2000_FILESAVE_AUTOEXT_PASSWORD_BOX_ID; + else + winResTemplateId = TMPL95_FILESAVE_AUTOEXT_PASSWORD_BOX_ID; + break; + + case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS: + bFileOpenDialog = sal_False; + if ( bIsWin2000 ) + winResTemplateId = TMPL2000_AUTOEXT_PASSWORD_FILTEROPTION_BOX; + else + winResTemplateId = TMPL95_AUTOEXT_PASSWORD_FILTEROPTION_BOX; + break; + + case FILESAVE_AUTOEXTENSION_SELECTION: + bFileOpenDialog = sal_False; + if ( bIsWin2000 ) + winResTemplateId = TMPL2000_AUTOEXT_SELECTION_BOX; + else + winResTemplateId = TMPL95_AUTOEXT_SELECTION_BOX; + break; + + case FILESAVE_AUTOEXTENSION_TEMPLATE: + bFileOpenDialog = sal_False; + if ( bIsWin2000 ) + winResTemplateId = TMPL2000_FILEOPEN_AUTOEXT_TEMPLATE_BOX_ID; + else + winResTemplateId = TMPL95_FILEOPEN_AUTOEXT_TEMPLATE_BOX_ID; + break; + + case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE: + if ( bIsWin2000 ) + winResTemplateId = TMPL2000_FILEOPEN_LINK_PREVIEW_BOX_ID; + else + winResTemplateId = TMPL95_FILEOPEN_LINK_PREVIEW_BOX_ID; + break; + + case FILEOPEN_PLAY: + if ( bIsWin2000 ) + winResTemplateId = TMPL2000_PLAY_PUSHBUTTON; + else + winResTemplateId = TMPL95_PLAY_PUSHBUTTON; + break; + + case FILEOPEN_READONLY_VERSION: + if ( bIsWin2000 ) + winResTemplateId = TMPL2000_FILEOPEN_READONLY_VERSION_BOX_ID; + else + winResTemplateId = TMPL95_FILEOPEN_READONLY_VERSION_BOX_ID; + break; + + case FILEOPEN_LINK_PREVIEW: + if ( bIsWin2000 ) + winResTemplateId = TMPL2000_FILEOPEN_LINK_PREVIEW_BOX_SIMPLE_ID; + else + winResTemplateId = TMPL95_FILEOPEN_LINK_PREVIEW_BOX_SIMPLE_ID; + break; + + case FILESAVE_AUTOEXTENSION: + bFileOpenDialog = sal_False; + if ( bIsWin2000 ) + winResTemplateId = TMPL2000_FILESAVE_AUTOEXT; + else + winResTemplateId = TMPL95_FILESAVE_AUTOEXT; + break; + + default: + throw lang::IllegalArgumentException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Unknown template" )), + static_cast< XFilePicker2* >( this ), + 1 ); + } + + HINSTANCE hInstance = GetModuleHandle( FILE_PICKER_DLL_NAME ); + OSL_POSTCOND( hInstance, "The name of the service dll must have changed" ); + + // create a new impl-class here based on the + // given string, if the given string is empty + // we do nothing + m_pImpl = std::auto_ptr< CWinFileOpenImpl >( + new CWinFileOpenImpl( + this, + bFileOpenDialog, + 0, + winResTemplateId, + hInstance ) ); +} + +//------------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------------ + +void SAL_CALL CFilePicker::cancel() + throw(uno::RuntimeException) +{ + OSL_ASSERT(m_pImpl.get()); + + osl::MutexGuard aGuard(m_aMutex); + m_pImpl->cancel(); +} + +// ------------------------------------------------- +// XServiceInfo +// ------------------------------------------------- + +rtl::OUString SAL_CALL CFilePicker::getImplementationName() + throw(uno::RuntimeException) +{ + return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(FILE_PICKER_IMPL_NAME)); +} + +// ------------------------------------------------- +// XServiceInfo +// ------------------------------------------------- + +sal_Bool SAL_CALL CFilePicker::supportsService(const rtl::OUString& ServiceName) + throw(uno::RuntimeException ) +{ + uno::Sequence <rtl::OUString> SupportedServicesNames = FilePicker_getSupportedServiceNames(); + + for (sal_Int32 n = SupportedServicesNames.getLength(); n--;) + if (SupportedServicesNames[n].compareTo(ServiceName) == 0) + return sal_True; + + return sal_False; +} + +// ------------------------------------------------- +// XServiceInfo +// ------------------------------------------------- + +uno::Sequence<rtl::OUString> SAL_CALL CFilePicker::getSupportedServiceNames() + throw(uno::RuntimeException) +{ + return FilePicker_getSupportedServiceNames(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/FilePicker.hxx b/fpicker/source/win32/filepicker/FilePicker.hxx new file mode 100644 index 000000000000..cb9722198fb6 --- /dev/null +++ b/fpicker/source/win32/filepicker/FilePicker.hxx @@ -0,0 +1,258 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FILEPICKER_HXX_ +#define _FILEPICKER_HXX_ + +//_______________________________________________________________________________________________________________________ +// includes of other projects +//_______________________________________________________________________________________________________________________ + + +#include <cppuhelper/compbase10.hxx> +#include <osl/mutex.hxx> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/ui/dialogs/XFilePicker2.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerNotifier.hpp> +#include <com/sun/star/ui/dialogs/XFilterManager.hpp> +#include <com/sun/star/ui/dialogs/XFilterGroupManager.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp> +#include <com/sun/star/ui/dialogs/XFilePreview.hpp> +#include <com/sun/star/util/XCancellable.hpp> +#include "asynceventnotifier.hxx" +#include "eventnotification.hxx" + +#include <memory> + +//---------------------------------------------------------- +// Implementation class for the XFilePicker Interface +//---------------------------------------------------------- + +//---------------------------------------------------------- +// forward declarations +//---------------------------------------------------------- + +class CWinFileOpenImpl; + +//---------------------------------------------------------- +// class declaration +//---------------------------------------------------------- + +class CFilePickerDummy +{ +protected: + osl::Mutex m_aMutex; + osl::Mutex m_rbHelperMtx; +}; + +class CFilePicker : + public CFilePickerDummy, + public cppu::WeakComponentImplHelper10< + ::com::sun::star::ui::dialogs::XFilterManager, + ::com::sun::star::ui::dialogs::XFilterGroupManager, + ::com::sun::star::ui::dialogs::XFilePickerControlAccess, + ::com::sun::star::ui::dialogs::XFilePickerNotifier, + ::com::sun::star::ui::dialogs::XFilePreview, + ::com::sun::star::ui::dialogs::XFilePicker2, + ::com::sun::star::lang::XInitialization, + ::com::sun::star::util::XCancellable, + ::com::sun::star::lang::XEventListener, + ::com::sun::star::lang::XServiceInfo > +{ +public: + + // ctor + CFilePicker( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceMgr ); + + //------------------------------------------------------------------------------------ + // XFilePickerNotifier + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL addFilePickerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener >& xListener ) + throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL removeFilePickerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener >& xListener ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XExecutableDialog functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setTitle( const ::rtl::OUString& aTitle ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual sal_Int16 SAL_CALL execute( ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFilePicker functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setMultiSelectionMode( sal_Bool bMode ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setDefaultName( const ::rtl::OUString& aName ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setDisplayDirectory( const ::rtl::OUString& aDirectory ) + throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + + virtual ::rtl::OUString SAL_CALL getDisplayDirectory( ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getFiles( ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFilePicker2 functions + //------------------------------------------------------------------------------------ + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSelectedFiles( ) + throw (::com::sun::star::uno::RuntimeException); + + //------------------------------------------------------------------------------------ + // XFilterManager functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL appendFilter( const ::rtl::OUString& aTitle, const ::rtl::OUString& aFilter ) + throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setCurrentFilter( const ::rtl::OUString& aTitle ) + throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + + virtual ::rtl::OUString SAL_CALL getCurrentFilter( ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFilterGroupManager functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL appendFilterGroup( const ::rtl::OUString& sGroupTitle, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::StringPair >& aFilters ) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + //------------------------------------------------------------------------------------ + // XFilePickerControlAccess functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setValue( sal_Int16 aControlId, sal_Int16 aControlAction, const ::com::sun::star::uno::Any& aValue ) + throw (::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Any SAL_CALL getValue( sal_Int16 aControlId, sal_Int16 aControlAction ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL enableControl( sal_Int16 aControlId, sal_Bool bEnable ) + throw(::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setLabel( sal_Int16 aControlId, const ::rtl::OUString& aLabel ) + throw (::com::sun::star::uno::RuntimeException); + + virtual ::rtl::OUString SAL_CALL getLabel( sal_Int16 aControlId ) + throw (::com::sun::star::uno::RuntimeException); + + //------------------------------------------------ + // XFilePreview + //------------------------------------------------ + + virtual ::com::sun::star::uno::Sequence< sal_Int16 > SAL_CALL getSupportedImageFormats( ) throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL getTargetColorDepth( ) throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL getAvailableWidth( ) throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL getAvailableHeight( ) throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL setImage( sal_Int16 aImageFormat, const ::com::sun::star::uno::Any& aImage ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL setShowState( sal_Bool bShowState ) throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL getShowState( ) throw (::com::sun::star::uno::RuntimeException); + + //------------------------------------------------ + // XInitialization + //------------------------------------------------ + + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) + throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + //------------------------------------------------ + // XCancellable + //------------------------------------------------ + + virtual void SAL_CALL cancel( ) + throw(::com::sun::star::uno::RuntimeException); + + //------------------------------------------------ + // XEventListener + //------------------------------------------------ + + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& aEvent ) + throw(::com::sun::star::uno::RuntimeException); + + //------------------------------------------------ + // XServiceInfo + //------------------------------------------------ + + virtual ::rtl::OUString SAL_CALL getImplementationName( ) + throw(::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) + throw(::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) + throw(::com::sun::star::uno::RuntimeException); + + //------------------------------------------------------------------------------------ + // FilePicker Event functions + //------------------------------------------------------------------------------------ + + void SAL_CALL fileSelectionChanged( ::com::sun::star::ui::dialogs::FilePickerEvent aEvent ); + void SAL_CALL directoryChanged( ::com::sun::star::ui::dialogs::FilePickerEvent aEvent ); + rtl::OUString SAL_CALL helpRequested( ::com::sun::star::ui::dialogs::FilePickerEvent aEvent ) const; + void SAL_CALL controlStateChanged( ::com::sun::star::ui::dialogs::FilePickerEvent aEvent ); + void SAL_CALL dialogSizeChanged( ); + + bool startupEventNotification(bool bStartupSuspended); + void shutdownEventNotification(); + void suspendEventNotification(); + void resumeEventNotification(); + +private: + // prevent copy and assignment + CFilePicker( const CFilePicker& ); + CFilePicker& operator=( const CFilePicker& ); + + using WeakComponentImplHelperBase::disposing; + +private: + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xServiceMgr; // to instanciate own services + CAsyncEventNotifier m_aAsyncEventNotifier; + std::auto_ptr<CWinFileOpenImpl> m_pImpl; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/FilterContainer.cxx b/fpicker/source/win32/filepicker/FilterContainer.cxx new file mode 100644 index 000000000000..d2de0ac6d74b --- /dev/null +++ b/fpicker/source/win32/filepicker/FilterContainer.cxx @@ -0,0 +1,339 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + + +#include <stdexcept> +#include <osl/diagnose.h> +#include "FilterContainer.hxx" + +#include <utility> + +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +//------------------------------------------------------------------- +// namespace directives +//------------------------------------------------------------------- + +using ::rtl::OUString; + +//------------------------------------------------------------------------------------- +// ctor +//------------------------------------------------------------------------------------- + +CFilterContainer::CFilterContainer( sal_Int32 initSize ) : + m_vFilters( initSize ), + m_bIterInitialized( sal_False ) +{ +} + +//----------------------------------------------------------------------------------------- +// add a name/filter pair +//----------------------------------------------------------------------------------------- + +sal_Bool SAL_CALL CFilterContainer::addFilter( + const OUString& aName, const OUString& aFilter, sal_Bool bAllowDuplicates ) +{ + // check if the filter is already in the container + sal_Int32 pos = -1; + + if ( !bAllowDuplicates ) + { + pos = getFilterTagPos( aName ); + if ( pos < 0 ) // if not there, append + { + m_vFilters.push_back( std::make_pair( aName, aFilter ) ); + m_bIterInitialized = sal_False; + } + } + else + { + m_vFilters.push_back( std::make_pair( aName, aFilter ) ); + m_bIterInitialized = sal_False; + } + + return ( pos < 0 ) ? sal_True : sal_False; +} + +//----------------------------------------------------------------------------------------- +// delete a filter +// Precondition: the container is not empty +// there is a filter identified by the given name +//----------------------------------------------------------------------------------------- + +sal_Bool SAL_CALL CFilterContainer::delFilter( const OUString& aName ) +{ + OSL_ASSERT( m_vFilters.size() > 0 ); + + sal_Int32 pos = getFilterTagPos( aName ); + if ( pos > -1 ) + { + m_vFilters.erase( ( m_vFilters.begin() + pos ) ); + m_bIterInitialized = sal_False; + } + + return ( pos > -1 ) ? sal_True : sal_False; +} + +//----------------------------------------------------------------------------------------- +// return the number of filters currently in the container +//----------------------------------------------------------------------------------------- + +sal_Int32 SAL_CALL CFilterContainer::numFilter( ) +{ + return m_vFilters.size( ); +} + +//----------------------------------------------------------------------------------------- +// clear all entries +//----------------------------------------------------------------------------------------- + +void SAL_CALL CFilterContainer::empty() +{ + m_vFilters.clear( ); +} + +//----------------------------------------------------------------------------------------- +// get a filter by name +// Precondition: the container is not empty +// there is a filter identified by the name +//----------------------------------------------------------------------------------------- + +sal_Bool SAL_CALL CFilterContainer::getFilter( const OUString& aName, OUString& theFilter ) const +{ + OSL_PRECOND( m_vFilters.size() > 0, "Empty filter container" ); + + sal_Int32 pos = getFilterTagPos( aName ); + + try + { + if ( pos > -1 ) + theFilter = m_vFilters.at( pos ).second; + } + catch( std::out_of_range& ) + { + OSL_ENSURE( sal_False, "Filter not in filter container" ); + pos = -1; + } + + return (pos > -1 ) ? sal_True : sal_False; +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +sal_Bool SAL_CALL CFilterContainer::getFilter( sal_Int32 aIndex, OUString& theFilter ) const +{ + sal_Bool bRet = sal_True; + + try + { + theFilter = m_vFilters.at( aIndex ).first; + } + catch( std::out_of_range& ) + { + OSL_ENSURE( sal_False, "Filter index out of range" ); + bRet = sal_False; + } + + return bRet; +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +sal_Int32 SAL_CALL CFilterContainer::getFilterPos( const OUString& aName ) const +{ + return getFilterTagPos( aName ); +} + +//----------------------------------------------------------------------------------------- +// returns the index of the filter identified by name +//----------------------------------------------------------------------------------------- + +sal_Int32 SAL_CALL CFilterContainer::getFilterTagPos( const OUString& aName ) const +{ + if ( m_vFilters.size( ) > 0 ) + { + sal_Int32 i = 0; + FILTER_VECTOR_T::const_iterator iter; + FILTER_VECTOR_T::const_iterator iter_end = m_vFilters.end( ); + + for ( iter = m_vFilters.begin( ); iter != iter_end; ++iter, ++i ) + if ( ( *iter ).first.equalsIgnoreAsciiCase( aName ) ) + return i; + } + + return -1; +} + +//----------------------------------------------------------------------------------------- +// starts enumerating the filter in the container +//----------------------------------------------------------------------------------------- + +void SAL_CALL CFilterContainer::beginEnumFilter( ) +{ + m_iter = m_vFilters.begin( ); + m_bIterInitialized = sal_True; +} + +//----------------------------------------------------------------------------------------- +// returns true if another filter has been retrieved +//----------------------------------------------------------------------------------------- + +sal_Bool SAL_CALL CFilterContainer::getNextFilter( FILTER_ENTRY_T& nextFilterEntry ) +{ + OSL_ASSERT( m_bIterInitialized ); + + sal_Bool bRet = ( m_iter != m_vFilters.end( ) ); + + if ( bRet ) + nextFilterEntry = *m_iter++; + else + m_bIterInitialized = sal_False; + + return bRet; +} + +//----------------------------------------------------------------------------------------- +void SAL_CALL CFilterContainer::setCurrentFilter( const ::rtl::OUString& aName ) +{ + m_sCurrentFilter = aName; +} + +//----------------------------------------------------------------------------------------- +::rtl::OUString SAL_CALL CFilterContainer::getCurrentFilter() const +{ + return m_sCurrentFilter; +} + +//################################################################### + + +//------------------------------------------------------------------- +// calculates the length of a '\0' separated filter, that means +// length of the name + '\0' + length of the filter string + +// a trailing '\0' +//------------------------------------------------------------------- + +static sal_uInt32 _getLengthFilter( CFilterContainer::FILTER_ENTRY_T aFilterEntry ) +{ + return ( + aFilterEntry.first.getLength( ) + 1 + + aFilterEntry.second.getLength( ) + 1 ); +} + +//------------------------------------------------------------------- +// calculates the length of all filters currently in the container +//------------------------------------------------------------------- + +static sal_uInt32 _getTotalFilterLength( CFilterContainer& aFilterContainer ) +{ + CFilterContainer::FILTER_ENTRY_T nextFilter; + + aFilterContainer.beginEnumFilter( ); + + sal_uInt32 totalLength = 0; + while( aFilterContainer.getNextFilter( nextFilter ) ) + totalLength += _getLengthFilter( nextFilter ); + + return ( totalLength > 0 ) ? totalLength + 1 : totalLength; +} + +//------------------------------------------------------------------- +// +//------------------------------------------------------------------- + +inline +void _wcsmemcpy( sal_Unicode* pDest, const sal_Unicode* pSrc, sal_uInt32 nLength ) +{ + memcpy( pDest, pSrc, nLength * sizeof( sal_Unicode ) ); +} + +//------------------------------------------------------------------- +// a helper trivial helper function to create a filter buffer in the +// format the Win32 API requires, +// e.g. "Text\0*.txt\0Doc\0*.doc;*xls\0\0" +//------------------------------------------------------------------- + +rtl::OUString SAL_CALL makeWinFilterBuffer( CFilterContainer& aFilterContainer ) +{ + // calculate the required buffer size + sal_uInt32 reqBuffSize = _getTotalFilterLength( aFilterContainer ); + + // return if there are no filters + if ( !reqBuffSize ) + return OUString( ); + + sal_Unicode* pBuff = new sal_Unicode[reqBuffSize]; + + // initialize the buffer with 0 + ZeroMemory( pBuff, sizeof( sal_Unicode ) * reqBuffSize ); + + OUString winFilterBuff; + CFilterContainer::FILTER_ENTRY_T nextFilter; + sal_uInt32 memPos = 0; + + aFilterContainer.beginEnumFilter( ); + + while( aFilterContainer.getNextFilter( nextFilter ) ) + { + _wcsmemcpy( + pBuff + memPos, + nextFilter.first.getStr( ), + nextFilter.first.getLength( ) ); + + memPos += nextFilter.first.getLength( ) + 1; + + _wcsmemcpy( + pBuff + memPos, + nextFilter.second.getStr( ), + nextFilter.second.getLength( ) ); + + memPos += nextFilter.second.getLength( ) + 1 ; + } + + winFilterBuff = OUString( pBuff, reqBuffSize ); + + // remove the allocated buffer + delete [] pBuff; + + return winFilterBuff; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/FilterContainer.hxx b/fpicker/source/win32/filepicker/FilterContainer.hxx new file mode 100644 index 000000000000..91ee54571418 --- /dev/null +++ b/fpicker/source/win32/filepicker/FilterContainer.hxx @@ -0,0 +1,118 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FILTER_CONTAINER_HXX_ +#define _FILTER_CONTAINER_HXX_ + +#include <sal/types.h> +#include <rtl/ustring.hxx> + +#include <vector> + +//------------------------------------------------------ +// helper class, only useable by OFilterContainer +//------------------------------------------------------ + +class CFilterContainer +{ +public: + // defines a filter entry which is made of a name and a filter value + // e.g. 'Text *.txt' + typedef std::pair< rtl::OUString, rtl::OUString > FILTER_ENTRY_T; + +public: + explicit CFilterContainer( sal_Int32 initSize = 0 ); + + // add a new filter + // returns true if the filter was successfully added + // returns false if duplicates are not allowed and + // the filter is already in the container + sal_Bool SAL_CALL addFilter( + const ::rtl::OUString& aName, + const ::rtl::OUString& aFilter, + sal_Bool bAllowDuplicates = sal_False ); + + // delete the specified filter returns true on + // success and false if the filter was not found + sal_Bool SAL_CALL delFilter( const ::rtl::OUString& aName ); + + // the number of filter already added + sal_Int32 SAL_CALL numFilter( ); + + // clear all entries + void SAL_CALL empty( ); + + // retrieve a filter from the container both methods + // return true on success and false if the specified + // filter was not found + sal_Bool SAL_CALL getFilter( const ::rtl::OUString& aName, ::rtl::OUString& theFilter ) const; + sal_Bool SAL_CALL getFilter( sal_Int32 aIndex, ::rtl::OUString& theFilter ) const; + + // returns the position of the specified filter or -1 + // if the filter was not found + sal_Int32 SAL_CALL getFilterPos( const ::rtl::OUString& aName ) const; + + // starts enumerating the filter in the container + void SAL_CALL beginEnumFilter( ); + + // returns true if another filter has been retrieved + sal_Bool SAL_CALL getNextFilter( FILTER_ENTRY_T& nextFilterEntry ); + + // cache current filter + void SAL_CALL setCurrentFilter( const ::rtl::OUString& aName ); + + // returns cached current filter + ::rtl::OUString SAL_CALL getCurrentFilter() const; + +protected: + typedef std::vector< FILTER_ENTRY_T > FILTER_VECTOR_T; + +private: + // prevent copy and assignment + CFilterContainer( const CFilterContainer& ); + CFilterContainer& SAL_CALL operator=( const CFilterContainer& ); + + sal_Int32 SAL_CALL getFilterTagPos( const ::rtl::OUString& aName ) const; + +private: + FILTER_VECTOR_T m_vFilters; + FILTER_VECTOR_T::const_iterator m_iter; + sal_Bool m_bIterInitialized; + ::rtl::OUString m_sCurrentFilter; +}; + +//---------------------------------------------------------------- +// a helper function to create a filter buffer in the format +// the Win32 API requires, e.g. "Text\0*.txt\0Doc\0*.doc;*xls\0\0" +//---------------------------------------------------------------- + +rtl::OUString SAL_CALL makeWinFilterBuffer( CFilterContainer& aFilterContainer ); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/Fps.rc b/fpicker/source/win32/filepicker/Fps.rc new file mode 100644 index 000000000000..ad08ad06698e --- /dev/null +++ b/fpicker/source/win32/filepicker/Fps.rc @@ -0,0 +1,438 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// German (Germany) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +1000 DIALOG DISCARDABLE 0, 0, 200, 37 +STYLE DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS +FONT 8, "Andale Sans UI" +BEGIN + CONTROL "Mit Schreibschutz öffnen",103,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 52,24,148,10 + COMBOBOX 107,52,8,148,52,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Version:",207,0,10,52,11 + LTEXT "",1119,0,0,200,8 +END + +1001 DIALOG DISCARDABLE 0, 0, 338, 67 +STYLE DS_3DLOOK | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "Mit Schreibschutz öffnen",103,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 130,51,161,14 + COMBOBOX 107,130,35,164,52,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Version:",207,68,37,56,11 + LTEXT "",1119,0,0,336,35 +END + +2000 DIALOG DISCARDABLE 0, 0, 210, 53 +STYLE DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS +FONT 8, "Andale Sans UI" +BEGIN + CONTROL "Vorschau",105,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 52,40,157,10 + CONTROL "Als Link einfügen",104,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 52,28,157,10 + COMBOBOX 109,52,12,156,54,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Bildvorlage:",209,4,14,48,10 + LTEXT "",1119,0,0,210,12 +END + +2001 DIALOG DISCARDABLE 0, 0, 280, 72 +STYLE DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "Vorschau",105,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 130,58,144,16 + CONTROL "Als Link einfügen",104,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 130,45,144,14 + COMBOBOX 109,130,28,164,62,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + LTEXT "Bildvorlage:",209,67,30,47,11 + LTEXT "",1119,0,0,281,28 +END + +3000 DIALOG DISCARDABLE 0, 0, 208, 49 +STYLE DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS +FONT 8, "Andale Sans UI" +BEGIN + CONTROL "Automatische Dateinamenserweiterung",100,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,52,36,156,10 + COMBOBOX 108,52,20,156,52,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + LTEXT "Vorlagen:",208,4,22,47,11 + LTEXT "",1119,0,0,208,20 +END + +3001 DIALOG DISCARDABLE 0, 0, 296, 72 +STYLE DS_3DLOOK | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "Automatische Dateinamenserweiterung",100,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,130,58,157,14 + COMBOBOX 108,130,41,164,100,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + LTEXT "Vorlagen:",208,67,42,58,8 + LTEXT "",1119,0,0,293,41 +END + +4000 DIALOG DISCARDABLE 0, 0, 196, 41 +STYLE DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS +FONT 8, "Andale Sans UI" +BEGIN + CONTROL "Mit Kennwort speichern",101,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,52,28,141,10 + CONTROL "Automatische Dateinamenserweiterung",100,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,52,16,141,10 + LTEXT "",1119,0,0,195,16 +END + +4001 DIALOG DISCARDABLE 0, 0, 278, 67 +STYLE DS_3DLOOK | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "Mit Kennwort speichern",101,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,130,51,144,16 + CONTROL "Automatische Dateinamenserweiterung",100,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,130,38,144,14 + LTEXT "",1119,0,0,277,38 +END + +5000 DIALOG DISCARDABLE 0, 0, 192, 57 +STYLE DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS +FONT 8, "Andale Sans UI" +BEGIN + CONTROL "Filtereinstellungen bearbeiten",102,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,52,44,140,10 + CONTROL "Mit Kennwort speichern",101,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,52,32,140,10 + CONTROL "Automatische Dateinamenserweiterung",100,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,52,20,140,10 + LTEXT "",1119,0,0,192,20 +END + +5001 DIALOG DISCARDABLE 0, 0, 278, 79 +STYLE DS_3DLOOK | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "Filtereinstellungen bearbeiten",102,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,130,66,144,13 + CONTROL "Mit Kennwort speichern",101,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,130,52,144,13 + CONTROL "Automatische Dateinamenserweiterung",100,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,130,38,144,14 + LTEXT "",1119,0,0,277,38 +END + +6000 DIALOG DISCARDABLE 0, 0, 212, 25 +STYLE DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS +FONT 8, "Andale Sans UI" +BEGIN + LTEXT "",1119,0,0,212,8,NOT WS_VISIBLE + PUSHBUTTON "Abspielen",106,156,8,50,15 +END + +6001 DIALOG DISCARDABLE 0, 0, 366, 40 +STYLE DS_3DLOOK | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "",1119,0,0,364,18,NOT WS_VISIBLE + PUSHBUTTON "Abspielen",106,316,18,50,14 +END + +7000 DIALOG DISCARDABLE 0, 0, 196, 45 +STYLE DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS +FONT 8, "Andale Sans UI" +BEGIN + CONTROL "Selektion",110,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,52, + 32,143,10 + CONTROL "Automatische Dateinamenserweiterung",100,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,52,20,143,10 + LTEXT "",1119,0,0,195,20 +END + +7001 DIALOG DISCARDABLE 0, 0, 278, 65 +STYLE DS_3DLOOK | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "Selektion",110,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 130,51,144,16 + CONTROL "Automatische Dateinamenserweiterung",100,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,130,38,144,14 + LTEXT "",1119,0,0,277,38 +END + +8000 DIALOG DISCARDABLE 0, 0, 152, 41 +STYLE DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS +FONT 8, "Andale Sans UI" +BEGIN + CONTROL "Vorschau",105,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,0, + 28,150,10 + CONTROL "Als Link einfügen",104,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,0,16,152,10 + LTEXT "",1119,0,0,149,16 +END + +8001 DIALOG DISCARDABLE 0, 0, 278, 65 +STYLE DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "Vorschau",105,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,130, + 51,144,16 + CONTROL "Als Link einfügen",104,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,130,38,144,14 + LTEXT "",1119,0,0,277,38 +END + +9000 DIALOG DISCARDABLE 0, 0, 196, 29 +STYLE DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS +FONT 8, "Andale Sans UI" +BEGIN + CONTROL "Automatische Dateinamenserweiterung",100,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,0,16,196,10 + LTEXT "",1119,0,0,196,16 +END + +9001 DIALOG DISCARDABLE 0, 0, 278, 54 +STYLE DS_3DLOOK | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "Automatische Dateinamenserweiterung",100,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,130,38,144,14 + LTEXT "",1119,0,0,277,38 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + 1000, DIALOG + BEGIN + VERTGUIDE, 5 + VERTGUIDE, 54 + BOTTOMMARGIN, 34 + END + + 1001, DIALOG + BEGIN + RIGHTMARGIN, 336 + VERTGUIDE, 124 + VERTGUIDE, 130 + HORZGUIDE, 37 + END + + 2000, DIALOG + BEGIN + RIGHTMARGIN, 209 + VERTGUIDE, 61 + HORZGUIDE, 25 + END + + 3000, DIALOG + BEGIN + VERTGUIDE, 51 + BOTTOMMARGIN, 48 + HORZGUIDE, 38 + END + + 3001, DIALOG + BEGIN + RIGHTMARGIN, 294 + VERTGUIDE, 67 + HORZGUIDE, 41 + END + + 4000, DIALOG + BEGIN + RIGHTMARGIN, 194 + VERTGUIDE, 54 + BOTTOMMARGIN, 37 + HORZGUIDE, 34 + END + + 4001, DIALOG + BEGIN + RIGHTMARGIN, 277 + VERTGUIDE, 76 + HORZGUIDE, 52 + END + + 5000, DIALOG + BEGIN + VERTGUIDE, 61 + BOTTOMMARGIN, 56 + HORZGUIDE, 25 + END + + 5001, DIALOG + BEGIN + RIGHTMARGIN, 277 + VERTGUIDE, 76 + HORZGUIDE, 52 + END + + 6000, DIALOG + BEGIN + RIGHTMARGIN, 59 + BOTTOMMARGIN, 20 + END + + 6001, DIALOG + BEGIN + RIGHTMARGIN, 361 + BOTTOMMARGIN, 36 + HORZGUIDE, 20 + END + + 7000, DIALOG + BEGIN + VERTGUIDE, 54 + HORZGUIDE, 34 + END + + 7001, DIALOG + BEGIN + RIGHTMARGIN, 277 + VERTGUIDE, 76 + HORZGUIDE, 52 + END + + 8000, DIALOG + BEGIN + RIGHTMARGIN, 151 + VERTGUIDE, 61 + BOTTOMMARGIN, 37 + END + + 9000, DIALOG + BEGIN + BOTTOMMARGIN, 25 + END + + 9001, DIALOG + BEGIN + RIGHTMARGIN, 277 + VERTGUIDE, 76 + HORZGUIDE, 52 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog Info +// + +1000 DLGINIT +BEGIN + 107, 0x403, 15, 0 +0x7453, 0x7261, 0x7257, 0x7469, 0x7265, 0x3520, 0x322e, "\000" + 107, 0x403, 15, 0 +0x7453, 0x7261, 0x7257, 0x7469, 0x7265, 0x3420, 0x302e, "\000" + 107, 0x403, 15, 0 +0x7453, 0x7261, 0x7257, 0x7469, 0x7265, 0x3320, 0x302e, "\000" + 0 +END + +1001 DLGINIT +BEGIN + 107, 0x403, 15, 0 +0x7453, 0x7261, 0x7257, 0x7469, 0x7265, 0x3520, 0x322e, "\000" + 107, 0x403, 15, 0 +0x7453, 0x7261, 0x7257, 0x7469, 0x7265, 0x3420, 0x302e, "\000" + 107, 0x403, 15, 0 +0x7453, 0x7261, 0x7257, 0x7469, 0x7265, 0x3320, 0x302e, "\000" + 0 +END + +3000 DLGINIT +BEGIN + 108, 0x403, 15, 0 +0x7453, 0x7261, 0x7257, 0x7469, 0x7265, 0x3520, 0x322e, "\000" + 108, 0x403, 15, 0 +0x7453, 0x7261, 0x7257, 0x7469, 0x7265, 0x3420, 0x302e, "\000" + 108, 0x403, 15, 0 +0x7453, 0x7261, 0x7257, 0x7469, 0x7265, 0x3320, 0x302e, "\000" + 0 +END + +3001 DLGINIT +BEGIN + 108, 0x403, 15, 0 +0x7453, 0x7261, 0x7257, 0x7469, 0x7265, 0x3520, 0x322e, "\000" + 108, 0x403, 15, 0 +0x7453, 0x7261, 0x7257, 0x7469, 0x7265, 0x3420, 0x302e, "\000" + 108, 0x403, 15, 0 +0x7453, 0x7261, 0x7257, 0x7469, 0x7265, 0x3320, 0x302e, "\000" + 0 +END + +#endif // German (Germany) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/fpicker/source/win32/filepicker/IVistaFilePickerInternalNotify.hxx b/fpicker/source/win32/filepicker/IVistaFilePickerInternalNotify.hxx new file mode 100644 index 000000000000..a03e6f3fe23c --- /dev/null +++ b/fpicker/source/win32/filepicker/IVistaFilePickerInternalNotify.hxx @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FPICKER_WIN32_VISTA_FILEPICKER_INTERNALNOTIFY_HXX +#define FPICKER_WIN32_VISTA_FILEPICKER_INTERNALNOTIFY_HXX + +//----------------------------------------------------------------------------- +// includes +//----------------------------------------------------------------------------- + +#include "comptr.hxx" +#include "vistatypes.h" + +#include <cppuhelper/basemutex.hxx> +#include <osl/interlck.h> + +#include <shobjidl.h> + +//----------------------------------------------------------------------------- +// namespace +//----------------------------------------------------------------------------- + +#ifdef css + #error "Clash on using CSS as namespace define." +#else + #define css ::com::sun::star +#endif + +namespace fpicker{ +namespace win32{ +namespace vista{ + +//----------------------------------------------------------------------------- +// types, const etcpp. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +/** todo document me + */ +class IVistaFilePickerInternalNotify +{ + public: + + virtual void onAutoExtensionChanged (bool bChecked) = 0; +}; + +}}} + +#undef css + +#endif FPICKER_WIN32_VISTA_FILEPICKER_INTERNALNOTIFY_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/PreviewCtrl.cxx b/fpicker/source/win32/filepicker/PreviewCtrl.cxx new file mode 100644 index 000000000000..9dd419d5a19d --- /dev/null +++ b/fpicker/source/win32/filepicker/PreviewCtrl.cxx @@ -0,0 +1,617 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <tchar.h> +#include "PreviewCtrl.hxx" +#include <osl/diagnose.h> + +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif +#include <ocidl.h> +#include <olectl.h> + +//------------------------------------------------------------------------ +// defines +//------------------------------------------------------------------------ + +#define PREVIEWWND_CLASS_NAME TEXT("PreviewWnd###") + +#define HIMETRIC_INCH 2540 + +// means 3 pixel left and 3 pixel right +#define HORZ_BODER_SPACE 6 + +// means 3 pixel top and 3 pixel bottom +#define VERT_BORDER_SPACE 6 + +//--------------------------------------------------- +// static member initialization +//--------------------------------------------------- + +CFilePreview* CFilePreview::s_FilePreviewInst = NULL; +CFilePreview::FILEPREVIEW_SINGLETON_DESTROYER_T CFilePreview::s_SingletonDestroyer; + +//--------------------------------------------------- +// some useful helper functions +//--------------------------------------------------- + +namespace // private +{ + class CPreviewException + { + // used when registering or creation + // of the preview window failed + }; + + //------------------------------------------------------------ + // + //------------------------------------------------------------ + + inline + sal_Int32 SubDiv( sal_Int32 nNumber, sal_Int32 nMinuend, sal_Int32 nDenominator ) + { + return ( static_cast<sal_Int32>( ( nNumber - nMinuend ) / nDenominator ) ); + } + + //------------------------------------------------------------ + // convert himetric to pixel + //------------------------------------------------------------ + + inline + sal_Int32 Himetric2Pixel( HDC hDC, sal_Int32 hmSize, sal_Int32 nIndex ) + { + return MulDiv( hmSize, GetDeviceCaps( hDC, nIndex), HIMETRIC_INCH ); + } + + //------------------------------------------------------------ + // + //------------------------------------------------------------ + + inline + sal_uInt32 _getWidthRect( const RECT& aRect ) + { + return ( aRect.right - aRect.left ); + } + + //------------------------------------------------------------ + // + //------------------------------------------------------------ + + inline + sal_uInt32 _getHeightRect( const RECT& aRect ) + { + return ( aRect.bottom - aRect.top ); + } + + //------------------------------------------------------------ + // calc the upper left corner so that a given window will be + // displayed centered within the given window + //------------------------------------------------------------ + + inline + POINT _calcULCorner( HWND hwnd, const CDimension& aPicSize ) + { + RECT rect; + GetClientRect( hwnd, &rect ); + + sal_Int32 nWidthWnd = _getWidthRect( rect ); + sal_Int32 nHeightWnd = _getHeightRect( rect ); + + POINT ulCorner; + ulCorner.x = SubDiv( nWidthWnd, aPicSize.m_cx, 2 ); + ulCorner.y = SubDiv( nHeightWnd, aPicSize.m_cy, 2 ); + + return ulCorner; + } + + //------------------------------------------------------------ + // test if a picture with the given dimensions fits into an + // arbitrary window + // we expect the width and height to be in pixel + //------------------------------------------------------------ + + inline + sal_Bool _pictureSizeFitsWindowSize( HWND hwnd, const CDimension& aPicSize ) + { + RECT rect; + GetClientRect( hwnd, &rect ); + + sal_Int32 nWidthWnd = _getWidthRect( rect ); + sal_Int32 nHeightWnd = _getHeightRect( rect ); + + return ( ( ( nWidthWnd - HORZ_BODER_SPACE ) >= aPicSize.m_cx ) && + ( ( nHeightWnd - VERT_BORDER_SPACE ) >= aPicSize.m_cy ) ); + } + + //------------------------------------------------------------ + // calc the dimemsions so that a given picture fits into a + // given window, if the picture fits into the given window + // the original CDimension will be returned + //------------------------------------------------------------ + + inline + CDimension _scalePictureSize( HWND hwnd, const CDimension& aPicSize ) + { + CDimension scaledPicSize = aPicSize; + + if ( !_pictureSizeFitsWindowSize( hwnd, aPicSize ) ) + { + RECT rect; + GetClientRect( hwnd, &rect ); + + // the dimensions of the preview wnd are not equal + // that's why we equalize it + sal_Int32 nHeightWnd = _getHeightRect( rect ) - VERT_BORDER_SPACE; + sal_Int32 nWidthWnd = nHeightWnd; + + if ( aPicSize.m_cx >= aPicSize.m_cy ) + { + scaledPicSize.m_cx = nWidthWnd; + scaledPicSize.m_cy = + static_cast< sal_Int32 >( + aPicSize.m_cy * nWidthWnd / aPicSize.m_cx ); + } + else + { + scaledPicSize.m_cx = + static_cast< sal_Int32 >( + aPicSize.m_cx * nHeightWnd / aPicSize.m_cy ); + scaledPicSize.m_cy = nHeightWnd; + } + } + + return scaledPicSize; + } + +} // end namespace + + +//--------------------------------------------------- +// to ensure only one instance (singleton) +//--------------------------------------------------- + +CFilePreview* CFilePreview::createInstance( + HWND aParent, + POINT ulCorner, + const CDimension& aSize, + HINSTANCE hInstance, + sal_Bool bShow, + sal_Bool bEnabled ) +{ + if ( !s_FilePreviewInst ) + { + try + { + s_FilePreviewInst = new CFilePreview( + aParent, ulCorner, aSize, hInstance, bShow, bEnabled ); + s_SingletonDestroyer.reset( s_FilePreviewInst ); + } + catch( CPreviewException& ) + { + OSL_ASSERT( !s_FilePreviewInst ); + OSL_ENSURE( sal_False, "Creation of the preview window failed" ); + } + catch( CAutoOleInit::COleInitException& ) + { + OSL_ASSERT( !s_FilePreviewInst ); + OSL_ENSURE( sal_False, "OleInitalize failed" ); + } + } + + return s_FilePreviewInst; +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +CFilePreview::CFilePreview( + HWND aParent, + POINT ulCorner, + const CDimension& aSize, + HINSTANCE hInstance, + sal_Bool bShow, + sal_Bool bEnabled ) : + m_hInstance( hInstance ), + m_bEnabled( bEnabled ) +{ + // register the preview window class + WNDCLASSEX wndClsEx; + ZeroMemory(&wndClsEx, sizeof(wndClsEx)); + + wndClsEx.cbSize = sizeof(wndClsEx); + wndClsEx.style = CS_HREDRAW | CS_VREDRAW; + wndClsEx.lpfnWndProc = CFilePreview::WndProc; + wndClsEx.hInstance = m_hInstance; + wndClsEx.hbrBackground = (HBRUSH)( COLOR_INACTIVEBORDER + 1 ); + wndClsEx.lpszClassName = PREVIEWWND_CLASS_NAME; + + // register the preview window class + // !!! Win95 - the window class will be unregistered automaticly + // if the dll is unloaded + // Win2000 - the window class must be unregistered manually + // if the dll is unloaded + m_atomPrevWndClass = RegisterClassEx(&wndClsEx); + if ( !m_atomPrevWndClass ) + throw CPreviewException( ); + + // create the preview window in invisible state + sal_uInt32 dwStyle = bShow ? (WS_CHILD | WS_VISIBLE) : WS_CHILD; + m_hwnd = CreateWindowEx( + WS_EX_CLIENTEDGE, + PREVIEWWND_CLASS_NAME, + TEXT(""), + dwStyle, + ulCorner.x, + ulCorner.y, + aSize.m_cx, + aSize.m_cy, + aParent, + (HMENU)100, // for child windows this will + // be used as child window identifier + m_hInstance, + 0 ); + if (!IsWindow(m_hwnd)) + throw CPreviewException( ); +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +CFilePreview::~CFilePreview( ) +{ + // unregister preview window class + sal_Bool bRet = UnregisterClass( + (LPCTSTR)MAKELONG( m_atomPrevWndClass, 0 ), + m_hInstance ); + OSL_POSTCOND( bRet, "Unregister preview window class failed" ); +} + +//--------------------------------------------------- +// sets the size of the preview window +//--------------------------------------------------- + +sal_Bool SAL_CALL CFilePreview::setSize( const CDimension& aSize ) +{ + OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" ); + + // resize the fileopen file listbox + return SetWindowPos( + m_hwnd, + NULL, + 0, + 0, + aSize.m_cx, + aSize.m_cy, + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); +} + +//--------------------------------------------------- +// returns the dimension of the preview +//--------------------------------------------------- + +sal_Bool SAL_CALL CFilePreview::getSize( CDimension& theSize ) const +{ + OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" ); + + RECT rect; + sal_Bool bRet = GetWindowRect( m_hwnd, &rect ); + + theSize.m_cx = _getWidthRect( rect ); + theSize.m_cy = _getHeightRect( rect ); + + return bRet; +} + +//--------------------------------------------------- +// sets the position of the upper left corner +// of the preview window relative to the +// upper left corner of the parent window +//--------------------------------------------------- + +sal_Bool SAL_CALL CFilePreview::setPos( POINT ulCorner ) +{ + OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" ); + + // resize the fileopen file listbox + return SetWindowPos( + m_hwnd, + NULL, + ulCorner.x, + ulCorner.y, + 0, + 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE ); +} + +//--------------------------------------------------- +// returns the current position of the preview +// relative to the upper left corner of the +// parent window +//--------------------------------------------------- + +sal_Bool SAL_CALL CFilePreview::getPos( POINT& ulCorner ) const +{ + OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" ); + + POINT pt = { 0, 0 }; + RECT rect; + + sal_Bool bRet = GetWindowRect( m_hwnd, &rect ); + + ulCorner.x = rect.left; + ulCorner.y = rect.top; + + ScreenToClient( m_hwnd, &ulCorner ); + + return bRet; +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +void SAL_CALL CFilePreview::enable( sal_Bool bEnable ) +{ + m_bEnabled = bEnable; + + // force a redraw + InvalidateRect( m_hwnd, NULL, TRUE ); + UpdateWindow( m_hwnd ); +} + +//--------------------------------------------------- +// shows the preview window +// possible values see SHOW_STATE +// SS_SHOW - make the window visible +// SS_HIDE - hide the window +// SS_ENABLED - enable the window +// SS_DISABLED - disable the window +//--------------------------------------------------- + +sal_Bool SAL_CALL CFilePreview::show( sal_Bool bShow ) +{ + OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" ); + + sal_Int32 showState = bShow ? SW_SHOW : SW_HIDE; + return ShowWindow( m_hwnd, showState ); +} + +//--------------------------------------------------- +// if the preview is shown and enabled +// preview of the given file will be shown +// returns true on success or false if an error +// occured (the file in not there or not accessible etc.) +//--------------------------------------------------- + +sal_Bool SAL_CALL CFilePreview::update( const rtl::OUString& aFileName ) +{ + OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" ); + + try + { + if ( m_bEnabled ) + { + if ( m_IPicture ) + m_IPicture.Release( ); + + loadFile( aFileName ); + + // force a complete window redraw + InvalidateRect( m_hwnd, NULL, TRUE ); + UpdateWindow( m_hwnd ); + } + } + catch( _com_error& ) + { + } + + return sal_True; +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +void SAL_CALL CFilePreview::onPaint( HWND hWnd, HDC hDC ) +{ + OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" ); + + try + { + if ( m_bEnabled ) + { + // get width and height of picture + long cxPicHIMETRIC; + long cyPicHIMETRIC; + + m_IPicture->get_Width( &cxPicHIMETRIC ); + m_IPicture->get_Height( &cyPicHIMETRIC ); + + // convert himetric to pixels + int cxPicPIXEL = Himetric2Pixel( hDC, cxPicHIMETRIC, LOGPIXELSX ); + int cyPicPIXEL = Himetric2Pixel( hDC, cyPicHIMETRIC, LOGPIXELSY ); + + // scale the picture based on the size of the preview window + RECT rcPrevWnd; + GetClientRect(hWnd, &rcPrevWnd); + + CDimension scaledPicSize = _scalePictureSize( + hWnd, CDimension( cxPicPIXEL, cyPicPIXEL ) ); + + // calc the upper left corner so that the picture + // is centered within the window + POINT ulCorner = _calcULCorner( hWnd, scaledPicSize ); + + // render the picture + HRESULT hr = m_IPicture->Render( + hDC, + ulCorner.x, + ulCorner.y, + scaledPicSize.m_cx, + scaledPicSize.m_cy, + 0, + cyPicHIMETRIC, + cxPicHIMETRIC, + -cyPicHIMETRIC, + &rcPrevWnd ); + } // end if ( m_bEnabled ) + } + catch( _com_error& ) + { + } +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +sal_Bool CFilePreview::loadFile( const rtl::OUString& aFileName ) +{ + HANDLE hFile = 0; + HGLOBAL hGlobal = 0; + LPVOID pData = NULL; + IStreamPtr pIStream; + HRESULT hr = E_FAIL; + sal_Bool bRet; + sal_uInt32 nBytesRead; + sal_uInt32 fszExtra; + sal_uInt32 fsize; + + hFile = CreateFile( + aFileName.getStr( ), + GENERIC_READ, + 0, + NULL, + OPEN_EXISTING, + 0, + NULL ); + if ( INVALID_HANDLE_VALUE == hFile ) + goto CLEANUP_AND_EXIT; + + fszExtra = 0; + fsize = GetFileSize( hFile, &fszExtra ); + + // empty file, error or file to big + if ( -1 == fsize || 0 == fsize || fszExtra ) + goto CLEANUP_AND_EXIT; + + hGlobal = GlobalAlloc( GMEM_MOVEABLE, fsize ); + if ( !hGlobal ) + goto CLEANUP_AND_EXIT; + + pData = GlobalLock( hGlobal ); + if ( !pData ) + goto CLEANUP_AND_EXIT; + + bRet = ReadFile( + hFile, pData, fsize, &nBytesRead, NULL ); + + if ( !bRet ) + goto CLEANUP_AND_EXIT; + + hr = CreateStreamOnHGlobal( + hGlobal, FALSE, &pIStream ); + + if ( SUCCEEDED( hr ) ) + { + hr = OleLoadPicture( + pIStream, fsize, FALSE, + __uuidof( IPicture ), (LPVOID*)&m_IPicture ); + } + +CLEANUP_AND_EXIT: + if ( hFile ) + CloseHandle( hFile ); + + if ( pData ) + GlobalUnlock( hGlobal ); + + if ( hGlobal ) + GlobalFree( hGlobal ); + + return ( SUCCEEDED( hr ) ); +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +LRESULT CALLBACK CFilePreview::WndProc( + HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + LRESULT lResult = 0; + + switch( uMsg ) + { + case WM_PAINT: + { + OSL_PRECOND( s_FilePreviewInst, "Static member not initialized" ); + + HDC hDC; + PAINTSTRUCT ps; + + hDC = BeginPaint( hWnd, &ps ); + s_FilePreviewInst->onPaint( hWnd, hDC ); + EndPaint( hWnd, &ps ); + } + break; + + // under windows 95/98 the creation of the + // hidden target request window fails if + // we don't handle this message ourself + // because the DefWindowProc returns 0 as + // a result of handling WM_NCCREATE what + // leads to a failure of CreateWindow[Ex]!!! + case WM_NCCREATE: + lResult = TRUE; + break; + + default: + return DefWindowProc( hWnd, uMsg, wParam, lParam ); + } + + return lResult; +} + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/PreviewCtrl.hxx b/fpicker/source/win32/filepicker/PreviewCtrl.hxx new file mode 100644 index 000000000000..5cde69e5fa65 --- /dev/null +++ b/fpicker/source/win32/filepicker/PreviewCtrl.hxx @@ -0,0 +1,202 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _PREVIEWCTRL_HXX_ +#define _PREVIEWCTRL_HXX_ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <sal/types.h> +#include <rtl/ustring.hxx> + +#include <comdef.h> + +#include <memory> + +//--------------------------------------------- +// declaration +//--------------------------------------------- + +class CDimension +{ +public: + CDimension( ) : + m_cx( 0 ), + m_cy( 0 ) + { + } + + CDimension( sal_Int32 cx, sal_Int32 cy ) : + m_cx( cx ), + m_cy( cy ) + { + } + + sal_Int32 m_cx; + sal_Int32 m_cy; +}; + +//-------------------------------------------------- +// we use OleInitialize here because we are calling +// some Ole functions to realize the picture preview +// and we expect to be called from the main thread +// so that there will be no problem calling +// OleInitialize (the main thread should be an STA) +// When OleInitialize should fail at worst the +// preview doesn't work +//-------------------------------------------------- + +class CAutoOleInit +{ +public: + + // used to communicate ole + // initialzation failures + class COleInitException { }; + + CAutoOleInit( ) + { + HRESULT hr = OleInitialize( NULL ); + if ( FAILED( hr ) ) + throw COleInitException( ); + } + + ~CAutoOleInit( ) + { + OleUninitialize( ); + } +}; + +//--------------------------------------------- +// A simple file preview class to preview some +// common picture formats like *.gif, *jpg, etc. +// This class is not thread-safe and is +// implmented as singleton, because the class +// has only one static member to reconnect +// from callback functions +// we use a singleton-destroyer to get rid off +// the singleton instance, but this happens +// only on shutdown (unloading of the dll) - +// it's a question of taste (other solutions +// are possible) +//--------------------------------------------- + +class CFilePreview +{ +public: + // to ensure only one instance (singleton) + static CFilePreview* createInstance( + HWND aParent, + POINT ulCorner, + const CDimension& aSize, + HINSTANCE hInstance, + sal_Bool bShow = sal_True, + sal_Bool bEnabled = sal_True ); + + // sets the size of the preview window + sal_Bool SAL_CALL setSize( const CDimension& aSize ); + + // returns the CDimension of the preview + sal_Bool SAL_CALL getSize( CDimension& theSize ) const; + + // sets the position of the upper left corner + // of the preview window relative to the + // upper left corner of the parent window + sal_Bool SAL_CALL setPos( POINT ulCorner ); + + // returns the current position of the preview + // relative to the upper left corner of the + // parent window + sal_Bool SAL_CALL getPos( POINT& ulCorner ) const; + + // enables or disables the preview window + // bEnable - true the window is enabled and updates its + // view when update is called + // bEnable - false the window shows itself in disabled + // mode and does not update its view when update is + // called + void SAL_CALL enable( sal_Bool bEnable ); + + // shows the preview window + // possible values see SHOW_STATE + sal_Bool SAL_CALL show( sal_Bool bShow ); + + + // if the preview is shown and enabled + // preview of the given file will be shown + // returns true on success or false if an error + // occured (the file in not there or not accessible etc.) + virtual sal_Bool SAL_CALL update( const rtl::OUString& aFileName ); + +protected: + // clients can create instances only through the static create method + CFilePreview( + HWND aParent, + POINT ulCorner, + const CDimension& aSize, + HINSTANCE hInstance, + sal_Bool bShow = sal_True, + sal_Bool bEnabled = sal_True ); + + // only the singleton destroyer class is allowed to delete the + // singleton instance of this class + virtual ~CFilePreview( ); + + // we use the stl auto_ptr class as singleton destroyer + typedef std::auto_ptr< CFilePreview > FILEPREVIEW_SINGLETON_DESTROYER_T; + +protected: + virtual void SAL_CALL onPaint( HWND hWnd, HDC hDC ); + + sal_Bool loadFile( const rtl::OUString& aFileName ); + +private: + CAutoOleInit m_autoOleInit; + POINT m_pt; + CDimension m_dim; + HWND m_hwnd; + sal_Bool m_bEnabled; + IPicturePtr m_IPicture; + ATOM m_atomPrevWndClass; + HINSTANCE m_hInstance; + + static LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); + + static CFilePreview* s_FilePreviewInst; + static FILEPREVIEW_SINGLETON_DESTROYER_T s_SingletonDestroyer; + +private: + friend FILEPREVIEW_SINGLETON_DESTROYER_T; +}; + + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/SolarMutex.cxx b/fpicker/source/win32/filepicker/SolarMutex.cxx new file mode 100644 index 000000000000..b11d35a16aaf --- /dev/null +++ b/fpicker/source/win32/filepicker/SolarMutex.cxx @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +#include <vcl/svapp.hxx> +#include <osl/mutex.hxx> +#include <osl/thread.hxx> + +int ReleaseSolarMutexOnMainThreadContext(unsigned nThreadId) +{ + int nAcquireCount = 0; + osl::SolarMutex& rSolarMutex = Application::GetSolarMutex(); + oslThreadIdentifier nMainThreadId = Application::GetMainThreadIdentifier(); + + if ( nMainThreadId == nThreadId ) + { + ::osl::SolarMutex& rMutex = Application::GetSolarMutex(); + if ( rMutex.tryToAcquire() ) + nAcquireCount = Application::ReleaseSolarMutex() - 1; + } + + return nAcquireCount; +} + +void AcquireSolarMutex(int nAcquireCount) +{ + if ( nAcquireCount ) + Application::AcquireSolarMutex( nAcquireCount ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/SolarMutex.hxx b/fpicker/source/win32/filepicker/SolarMutex.hxx new file mode 100644 index 000000000000..d9c73ba6fe02 --- /dev/null +++ b/fpicker/source/win32/filepicker/SolarMutex.hxx @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +int ReleaseSolarMutexOnMainThreadContext(unsigned nThreadId); + +void AcquireSolarMutex(int nAcquireCount); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/VistaFilePicker.cxx b/fpicker/source/win32/filepicker/VistaFilePicker.cxx new file mode 100644 index 000000000000..83b040f7edff --- /dev/null +++ b/fpicker/source/win32/filepicker/VistaFilePicker.cxx @@ -0,0 +1,720 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#ifdef _MSC_VER +#pragma warning (disable:4917) +#endif + +#include "VistaFilePicker.hxx" +#include "WinFileOpenImpl.hxx" +#include "..\misc\WinImplHelper.hxx" +#include "shared.hxx" + +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerNotifier.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerListener.hpp> +#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> + +#include <cppuhelper/interfacecontainer.h> +#include <comphelper/configurationhelper.hxx> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> +#include <osl/file.hxx> +#include <tchar.h> + +#ifdef _MSC_VER +#pragma warning (push, 1) +#endif +#include <shlobj.h> +#ifdef _MSC_VER +#pragma warning (pop) +#endif + +//------------------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------------------ + +namespace css = ::com::sun::star; + +namespace fpicker{ +namespace win32{ +namespace vista{ + +//------------------------------------------------------------------------ +// defines +//------------------------------------------------------------------------ + +#define FILE_PICKER_DLL_NAME TEXT("fps.dll") + +//------------------------------------------------------------------------ +// helper functions +//------------------------------------------------------------------------ + +namespace +{ + // controling event notifications + const bool STARTUP_SUSPENDED = true; + const bool STARTUP_ALIVE = false; + + css::uno::Sequence< ::rtl::OUString > SAL_CALL VistaFilePicker_getSupportedServiceNames() + { + css::uno::Sequence< ::rtl::OUString > aRet(2); + aRet[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ui.dialogs.FilePicker")); + aRet[1] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ui.dialogs.SystemFilePicker")); + return aRet; + } +} + +//----------------------------------------------------------------------------------------- +#define ENABLE_LOGGING + +#define LOGFILE_VISTA "c:\\temp\\vistafiledialog.log" + +#ifdef ENABLE_LOGGING + + #define LOG_FILE(PARAM_MESSAGE) \ + { \ + FILE* pFile = fopen(LOGFILE_VISTA, "a"); \ + fprintf(pFile, PARAM_MESSAGE); \ + fclose(pFile); \ + } + + #define LOG_FILE_1_PARAM(PARAM_MESSAGE, PARAM_1) \ + { \ + FILE* pFile = fopen(LOGFILE_VISTA, "a"); \ + fprintf(pFile, PARAM_MESSAGE, PARAM_1); \ + fclose(pFile); \ + } + + #define LOG_FILE_2_PARAM(PARAM_MESSAGE, PARAM_1, PARAM_2) \ + { \ + FILE* pFile = fopen(LOGFILE_VISTA, "a"); \ + fprintf(pFile, PARAM_MESSAGE, PARAM_1, PARAM_2); \ + fclose(pFile); \ + } + +#else + + #define LOG_FILE(PARAM_MESSAGE) + #define LOG_FILE_1_PARAM(PARAM_MESSAGE, PARAM_1) + #define LOG_FILE_2_PARAM(PARAM_MESSAGE, PARAM_1, PARAM_2) + +#endif + +//----------------------------------------------------------------------------------------- +#define VISTAFILEDIALOG_CHECKED_COMCALL(PARAM_CODE, PARAM_LOGMESSAGE, PARAM_ERRORMESSAGE) \ + { \ + HRESULT aResult; \ + VISTAFILEDIALOG_CHECKED_COMCALL_WITH_RETURN(aResult, PARAM_CODE, PARAM_LOGMESSAGE, PARAM_ERRORMESSAGE) \ + } + +//----------------------------------------------------------------------------------------- +#define VISTAFILEDIALOG_CHECKED_COMCALL_WITH_RETURN(RETURN_HR, PARAM_CODE, PARAM_LOGMESSAGE, PARAM_ERRORMESSAGE) \ + { \ + LOG_FILE(PARAM_LOGMESSAGE) \ + RETURN_HR = PARAM_CODE; \ + if ( FAILED(RETURN_HR) ) \ + { \ + LOG_FILE_1_PARAM("will throw exception for checked COM call:\n%s", PARAM_ERRORMESSAGE) \ + throw css::uno::RuntimeException( \ + ::rtl::OUString::createFromAscii(PARAM_ERRORMESSAGE), \ + css::uno::Reference< css::ui::dialogs::XFilePicker >()); \ + } \ + } + + + +//----------------------------------------------------------------------------------------- +VistaFilePicker::VistaFilePicker(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) + : TVistaFilePickerBase (m_aMutex ) + , m_xSMGR (xSMGR ) + , m_rDialog (new VistaFilePickerImpl()) + , m_aAsyncExecute (m_rDialog ) + , m_nFilePickerThreadId (0 ) + , m_bInitialized (false ) +{ +} + +//----------------------------------------------------------------------------------------- +VistaFilePicker::~VistaFilePicker() +{ +} + +//------------------------------------------------------------------------------------ +void SAL_CALL VistaFilePicker::addFilePickerListener(const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener) + throw(css::uno::RuntimeException) +{ + RequestRef rRequest(new Request()); + rRequest->setRequest (VistaFilePickerImpl::E_ADD_PICKER_LISTENER); + rRequest->setArgument(PROP_PICKER_LISTENER, xListener); + + m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED); +} + +//----------------------------------------------------------------------------------------- +void SAL_CALL VistaFilePicker::removeFilePickerListener(const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener ) + throw(css::uno::RuntimeException) +{ + RequestRef rRequest(new Request()); + rRequest->setRequest (VistaFilePickerImpl::E_REMOVE_PICKER_LISTENER); + rRequest->setArgument(PROP_PICKER_LISTENER, xListener); + + m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED); +} + +// ------------------------------------------------- +void SAL_CALL VistaFilePicker::disposing(const css::lang::EventObject& /*aEvent*/) + throw(css::uno::RuntimeException) +{ +} + +//------------------------------------------------------------------------------------ +void SAL_CALL VistaFilePicker::setMultiSelectionMode(::sal_Bool bMode) + throw(css::uno::RuntimeException) +{ + RequestRef rRequest(new Request()); + rRequest->setRequest (VistaFilePickerImpl::E_SET_MULTISELECTION_MODE); + rRequest->setArgument(PROP_MULTISELECTION_MODE, bMode); + + m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED); +} + +//----------------------------------------------------------------------------------------- +void SAL_CALL VistaFilePicker::setTitle(const ::rtl::OUString& sTitle) + throw(css::uno::RuntimeException) +{ + RequestRef rRequest(new Request()); + rRequest->setRequest (VistaFilePickerImpl::E_SET_TITLE); + rRequest->setArgument(PROP_TITLE, sTitle); + + m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED); +} + +//----------------------------------------------------------------------------------------- +void SAL_CALL VistaFilePicker::appendFilter(const ::rtl::OUString& sTitle , + const ::rtl::OUString& sFilter) + throw(css::lang::IllegalArgumentException, + css::uno::RuntimeException ) +{ + RequestRef rRequest(new Request()); + rRequest->setRequest (VistaFilePickerImpl::E_APPEND_FILTER); + rRequest->setArgument(PROP_FILTER_TITLE, sTitle ); + rRequest->setArgument(PROP_FILTER_VALUE, sFilter); + + m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED); +} + +//----------------------------------------------------------------------------------------- +void SAL_CALL VistaFilePicker::setCurrentFilter(const ::rtl::OUString& sTitle) + throw(css::lang::IllegalArgumentException, + css::uno::RuntimeException ) +{ + RequestRef rRequest(new Request()); + rRequest->setRequest (VistaFilePickerImpl::E_SET_CURRENT_FILTER); + rRequest->setArgument(PROP_FILTER_TITLE, sTitle); + + m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED); +} + +//----------------------------------------------------------------------------------------- +::rtl::OUString SAL_CALL VistaFilePicker::getCurrentFilter() + throw(css::uno::RuntimeException) +{ + RequestRef rRequest(new Request()); + rRequest->setRequest (VistaFilePickerImpl::E_GET_CURRENT_FILTER); + + m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::BLOCKED); + + const ::rtl::OUString sTitle = rRequest->getArgumentOrDefault(PROP_FILTER_TITLE, ::rtl::OUString()); + return sTitle; +} + +//----------------------------------------------------------------------------------------- +void SAL_CALL VistaFilePicker::appendFilterGroup(const ::rtl::OUString& /*sGroupTitle*/, + const css::uno::Sequence< css::beans::StringPair >& lFilters ) + throw (css::lang::IllegalArgumentException, + css::uno::RuntimeException ) +{ + ::sal_Int32 c = lFilters.getLength(); + ::sal_Int32 i = 0; + for (i=0; i<c; ++i) + { + const css::beans::StringPair& rFilter = lFilters[i]; + appendFilter(rFilter.First, rFilter.Second); + } +} + +//----------------------------------------------------------------------------------------- +void SAL_CALL VistaFilePicker::setDefaultName(const ::rtl::OUString& sName ) + throw(css::uno::RuntimeException) +{ + RequestRef rRequest(new Request()); + rRequest->setRequest (VistaFilePickerImpl::E_SET_DEFAULT_NAME); + rRequest->setArgument(PROP_FILENAME, sName); + + m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED); +} + +//----------------------------------------------------------------------------------------- +void SAL_CALL VistaFilePicker::setDisplayDirectory(const ::rtl::OUString& sDirectory) + throw (css::lang::IllegalArgumentException, + css::uno::RuntimeException ) +{ + const ::rtl::OUString aPackage( RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.Common/")); + const ::rtl::OUString aRelPath( RTL_CONSTASCII_USTRINGPARAM("Path/Info")); + const ::rtl::OUString aKey( RTL_CONSTASCII_USTRINGPARAM("WorkPathChanged")); + + css::uno::Any aValue = ::comphelper::ConfigurationHelper::readDirectKey( + m_xSMGR, aPackage, aRelPath, aKey, ::comphelper::ConfigurationHelper::E_READONLY); + + bool bChanged(false); + if (( aValue >>= bChanged ) && bChanged ) + { + ::comphelper::ConfigurationHelper::writeDirectKey( + m_xSMGR, aPackage, aRelPath, aKey, css::uno::makeAny(false), ::comphelper::ConfigurationHelper::E_STANDARD); + } + + RequestRef rRequest(new Request()); + rRequest->setRequest (VistaFilePickerImpl::E_SET_DIRECTORY); + rRequest->setArgument(PROP_DIRECTORY, sDirectory); + rRequest->setArgument(PROP_FORCE, bChanged); + + m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED); +} + +//----------------------------------------------------------------------------------------- +::rtl::OUString SAL_CALL VistaFilePicker::getDisplayDirectory() + throw(css::uno::RuntimeException) +{ + RequestRef rRequest(new Request()); + rRequest->setRequest (VistaFilePickerImpl::E_GET_DIRECTORY); + m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED); + const ::rtl::OUString sDirectory = rRequest->getArgumentOrDefault(PROP_FILENAME, ::rtl::OUString()); + + return sDirectory; +} + +//----------------------------------------------------------------------------------------- +// @deprecated cant be supported any longer ... see IDL description for further details +css::uno::Sequence< ::rtl::OUString > SAL_CALL VistaFilePicker::getFiles() + throw(css::uno::RuntimeException) +{ + RequestRef rRequest(new Request()); + rRequest->setRequest (VistaFilePickerImpl::E_GET_SELECTED_FILES); + + m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::BLOCKED); + + const css::uno::Sequence< ::rtl::OUString > lFiles = rRequest->getArgumentOrDefault(PROP_SELECTED_FILES, css::uno::Sequence< ::rtl::OUString >()); + m_lLastFiles = lFiles; + return lFiles; +} + +//----------------------------------------------------------------------------------------- +css::uno::Sequence< ::rtl::OUString > SAL_CALL VistaFilePicker::getSelectedFiles() + throw(css::uno::RuntimeException) +{ + RequestRef rRequest(new Request()); + rRequest->setRequest (VistaFilePickerImpl::E_GET_SELECTED_FILES); + + m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::BLOCKED); + + const css::uno::Sequence< ::rtl::OUString > lFiles = rRequest->getArgumentOrDefault(PROP_SELECTED_FILES, css::uno::Sequence< ::rtl::OUString >()); + m_lLastFiles = lFiles; + return lFiles; +} + +//----------------------------------------------------------------------------------------- +::sal_Int16 SAL_CALL VistaFilePicker::execute() + throw(css::uno::RuntimeException) +{ + bool bInitialized(false); + { + osl::MutexGuard aGuard(m_aMutex); + bInitialized = m_bInitialized; + } + + if ( !bInitialized ) + { + sal_Int16 nTemplateDescription = css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE; + css::uno::Sequence < css::uno::Any > aInitArguments(1); + aInitArguments[0] <<= nTemplateDescription; + initialize(aInitArguments); + } + + RequestRef rRequest(new Request()); + rRequest->setRequest (VistaFilePickerImpl::E_SHOW_DIALOG_MODAL); + + // if we want to show a modal window, the calling thread needs to process messages + m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::PROCESS_MESSAGES); + + const ::sal_Bool bOK = rRequest->getArgumentOrDefault(PROP_DIALOG_SHOW_RESULT, (::sal_Bool)sal_False ); + m_lLastFiles = rRequest->getArgumentOrDefault(PROP_SELECTED_FILES , css::uno::Sequence< ::rtl::OUString >()); + + ::sal_Int16 nResult = css::ui::dialogs::ExecutableDialogResults::CANCEL; + if (bOK) + nResult = css::ui::dialogs::ExecutableDialogResults::OK; + return nResult; +} + +//------------------------------------------------------------------------------------ +// XFilePicker functions +//------------------------------------------------------------------------------------ + +void SAL_CALL VistaFilePicker::setValue( ::sal_Int16 nControlId , + ::sal_Int16 nControlAction, + const css::uno::Any& aValue ) + throw(css::uno::RuntimeException) +{ + RequestRef rRequest(new Request()); + rRequest->setRequest (VistaFilePickerImpl::E_SET_CONTROL_VALUE); + rRequest->setArgument(PROP_CONTROL_ID , nControlId ); + rRequest->setArgument(PROP_CONTROL_ACTION, nControlAction); + rRequest->setArgument(PROP_CONTROL_VALUE , aValue ); + + m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +css::uno::Any SAL_CALL VistaFilePicker::getValue(::sal_Int16 nControlId , + ::sal_Int16 nControlAction) + throw(css::uno::RuntimeException) +{ + RequestRef rRequest(new Request()); + rRequest->setRequest (VistaFilePickerImpl::E_GET_CONTROL_VALUE); + rRequest->setArgument(PROP_CONTROL_ID , nControlId ); + rRequest->setArgument(PROP_CONTROL_ACTION, nControlAction); + + m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::BLOCKED); + const css::uno::Any aValue = rRequest->getArgumentOrDefault(PROP_CONTROL_VALUE, css::uno::Any()); + return aValue; +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL VistaFilePicker::enableControl(::sal_Int16 nControlId, + ::sal_Bool bEnable ) + throw(css::uno::RuntimeException) +{ + RequestRef rRequest(new Request()); + rRequest->setRequest (VistaFilePickerImpl::E_ENABLE_CONTROL); + rRequest->setArgument(PROP_CONTROL_ID , nControlId); + rRequest->setArgument(PROP_CONTROL_ENABLE, bEnable ); + + m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL VistaFilePicker::setLabel( ::sal_Int16 nControlId, + const ::rtl::OUString& sLabel ) + throw (css::uno::RuntimeException) +{ + RequestRef rRequest(new Request()); + rRequest->setRequest (VistaFilePickerImpl::E_SET_CONTROL_LABEL); + rRequest->setArgument(PROP_CONTROL_ID , nControlId); + rRequest->setArgument(PROP_CONTROL_LABEL, sLabel ); + + m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +::rtl::OUString SAL_CALL VistaFilePicker::getLabel(::sal_Int16 nControlId) + throw (css::uno::RuntimeException) +{ + RequestRef rRequest(new Request()); + rRequest->setRequest (VistaFilePickerImpl::E_GET_CONTROL_LABEL); + rRequest->setArgument(PROP_CONTROL_ID, nControlId); + + m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::BLOCKED); + const ::rtl::OUString sLabel = rRequest->getArgumentOrDefault(PROP_CONTROL_LABEL, ::rtl::OUString()); + return sLabel; +} + +//------------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------------ + +css::uno::Sequence< ::sal_Int16 > SAL_CALL VistaFilePicker::getSupportedImageFormats() + throw (css::uno::RuntimeException) +{ + return css::uno::Sequence< sal_Int16 >(); +} + +//------------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------------ + +sal_Int32 SAL_CALL VistaFilePicker::getTargetColorDepth() + throw (css::uno::RuntimeException) +{ + return 0; +} + +//------------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------------ + +sal_Int32 SAL_CALL VistaFilePicker::getAvailableWidth() + throw (css::uno::RuntimeException) +{ + return 0; +} + +//------------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------------ + +sal_Int32 SAL_CALL VistaFilePicker::getAvailableHeight() + throw (css::uno::RuntimeException) +{ + return 0; +} + +//------------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------------ + +void SAL_CALL VistaFilePicker::setImage( sal_Int16 /*nImageFormat*/, + const css::uno::Any& /*aImage */) + throw (css::lang::IllegalArgumentException, + css::uno::RuntimeException ) +{ +} + +//------------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------------ + +sal_Bool SAL_CALL VistaFilePicker::setShowState(sal_Bool /*bShowState*/) + throw (css::uno::RuntimeException) +{ + return sal_False; +} + +//------------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------------ + +sal_Bool SAL_CALL VistaFilePicker::getShowState() + throw (css::uno::RuntimeException) +{ + return sal_False; +} + +//------------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------------ + +void SAL_CALL VistaFilePicker::initialize(const css::uno::Sequence< css::uno::Any >& lArguments) + throw(css::uno::Exception , + css::uno::RuntimeException) +{ + if (lArguments.getLength() < 1) + throw css::lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "XInitialization::initialize() called without arguments." )), + static_cast< css::ui::dialogs::XFilePicker2* >( this ), + 1); + + sal_Int32 nTemplate = -1; + lArguments[0] >>= nTemplate; + + ::sal_Bool bFileOpenDialog = sal_True; + ::sal_Int32 nFeatures = 0; + + switch(nTemplate) + { + case css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE : + { + bFileOpenDialog = sal_True; + } + break; + + case css::ui::dialogs::TemplateDescription::FILESAVE_SIMPLE : + { + bFileOpenDialog = sal_False; + } + break; + + case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD : + { + bFileOpenDialog = sal_False; + nFeatures |= FEATURE_AUTOEXTENSION; + nFeatures |= FEATURE_PASSWORD; + } + break; + + case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS : + { + bFileOpenDialog = sal_False; + nFeatures |= FEATURE_AUTOEXTENSION; + nFeatures |= FEATURE_PASSWORD; + nFeatures |= FEATURE_FILTEROPTIONS; + } + break; + + case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_SELECTION : + { + bFileOpenDialog = sal_False; + nFeatures |= FEATURE_AUTOEXTENSION; + nFeatures |= FEATURE_SELECTION; + } + break; + + case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_TEMPLATE : + { + bFileOpenDialog = sal_False; + nFeatures |= FEATURE_AUTOEXTENSION; + nFeatures |= FEATURE_TEMPLATE; + } + break; + + case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE : + { + bFileOpenDialog = sal_True; + nFeatures |= FEATURE_LINK; + nFeatures |= FEATURE_PREVIEW; + nFeatures |= FEATURE_IMAGETEMPLATE; + } + break; + + case css::ui::dialogs::TemplateDescription::FILEOPEN_PLAY : + { + bFileOpenDialog = sal_True; + nFeatures |= FEATURE_PLAY; + } + break; + + case css::ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION : + { + bFileOpenDialog = sal_True; + nFeatures |= FEATURE_READONLY; + nFeatures |= FEATURE_VERSION; + } + break; + + case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW : + { + bFileOpenDialog = sal_True; + nFeatures |= FEATURE_LINK; + nFeatures |= FEATURE_PREVIEW; + } + break; + + case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION : + { + bFileOpenDialog = sal_False; + nFeatures |= FEATURE_AUTOEXTENSION; + } + break; + } + + RequestRef rRequest(new Request()); + if (bFileOpenDialog) + rRequest->setRequest (VistaFilePickerImpl::E_CREATE_OPEN_DIALOG); + else + rRequest->setRequest (VistaFilePickerImpl::E_CREATE_SAVE_DIALOG); + rRequest->setArgument(PROP_FEATURES, nFeatures); + rRequest->setArgument(PROP_TEMPLATE_DESCR, nTemplate); + if ( ! m_aAsyncExecute.isRunning()) + m_aAsyncExecute.create(); + m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED); + + { + osl::MutexGuard aGuard(m_aMutex); + m_bInitialized = true; + } +} + +//------------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------------ + +void SAL_CALL VistaFilePicker::cancel() + throw(css::uno::RuntimeException) +{ +} + +// ------------------------------------------------- +// XServiceInfo +// ------------------------------------------------- + +::rtl::OUString SAL_CALL VistaFilePicker::getImplementationName() + throw(css::uno::RuntimeException) +{ + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.fpicker.VistaFileDialog")); +} + +// ------------------------------------------------- +// XServiceInfo +// ------------------------------------------------- + +sal_Bool SAL_CALL VistaFilePicker::supportsService(const ::rtl::OUString& sServiceName) + throw(css::uno::RuntimeException ) +{ + css::uno::Sequence< ::rtl::OUString > lSupportedServicesNames = VistaFilePicker_getSupportedServiceNames(); + + for (sal_Int32 n = lSupportedServicesNames.getLength(); n--;) + if (lSupportedServicesNames[n].compareTo(sServiceName) == 0) + return sal_True; + + return sal_False; +} + +// ------------------------------------------------- +// XServiceInfo +// ------------------------------------------------- + +css::uno::Sequence< ::rtl::OUString > SAL_CALL VistaFilePicker::getSupportedServiceNames() + throw(css::uno::RuntimeException) +{ + return VistaFilePicker_getSupportedServiceNames(); +} + +} // namespace vista +} // namespace win32 +} // namespace fpicker + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/VistaFilePicker.hxx b/fpicker/source/win32/filepicker/VistaFilePicker.hxx new file mode 100644 index 000000000000..1a46ca0e1504 --- /dev/null +++ b/fpicker/source/win32/filepicker/VistaFilePicker.hxx @@ -0,0 +1,318 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FPICKER_WIN32_VISTA_FILEPICKER_HXX +#define FPICKER_WIN32_VISTA_FILEPICKER_HXX + +//----------------------------------------------------------------------------- +// includes +//----------------------------------------------------------------------------- + +#include "asyncrequests.hxx" +#include "VistaFilePickerImpl.hxx" +#include "VistaFilePickerEventHandler.hxx" + +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/ui/dialogs/XFilePicker.hpp> +#include <com/sun/star/ui/dialogs/XFilePicker2.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerNotifier.hpp> +#include <com/sun/star/ui/dialogs/XFilterManager.hpp> +#include <com/sun/star/ui/dialogs/XFilterGroupManager.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp> +#include <com/sun/star/ui/dialogs/XFilePreview.hpp> +#include <com/sun/star/util/XCancellable.hpp> + +#include <cppuhelper/compbase10.hxx> +#include <cppuhelper/basemutex.hxx> +#include <rtl/ustring.hxx> + +//----------------------------------------------------------------------------- +// namespace +//----------------------------------------------------------------------------- + +#ifdef css + #error "Clash on using CSS as namespace define." +#else + #define css ::com::sun::star +#endif + +namespace fpicker{ +namespace win32{ +namespace vista{ + +//----------------------------------------------------------------------------- +// types +//----------------------------------------------------------------------------- + +typedef ::cppu::WeakComponentImplHelper10< + css::ui::dialogs::XFilePicker2, + css::ui::dialogs::XFilterManager, + css::ui::dialogs::XFilterGroupManager, + css::ui::dialogs::XFilePickerControlAccess, + css::ui::dialogs::XFilePickerNotifier, + css::ui::dialogs::XFilePreview, + css::lang::XInitialization, + css::util::XCancellable, + css::lang::XEventListener, + css::lang::XServiceInfo > TVistaFilePickerBase; + +//----------------------------------------------------------------------------- +/** Implements the XFilePicker & friends interface(s) + for Windos Vista and upcoming versions. + + Note: This will be an UNO wrapper for the real file picker + implementation oly. The real implementation is done in class + VistaFilePickerImpl. + */ +class VistaFilePicker : public ::cppu::BaseMutex + , public TVistaFilePickerBase +{ +public: + + //------------------------------------------------------------------------------------ + // ctor/dtor + //------------------------------------------------------------------------------------ + + VistaFilePicker( const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR ); + virtual ~VistaFilePicker(); + + //------------------------------------------------------------------------------------ + // XFilePickerNotifier + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL addFilePickerListener( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener ) + throw( css::uno::RuntimeException ); + + virtual void SAL_CALL removeFilePickerListener( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener ) + throw( css::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XExecutableDialog functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setTitle( const ::rtl::OUString& sTitle ) + throw( css::uno::RuntimeException ); + + virtual sal_Int16 SAL_CALL execute( ) + throw( css::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFilePicker functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setMultiSelectionMode( sal_Bool bMode ) + throw( css::uno::RuntimeException ); + + virtual void SAL_CALL setDefaultName( const ::rtl::OUString& sName ) + throw( css::uno::RuntimeException ); + + virtual void SAL_CALL setDisplayDirectory( const ::rtl::OUString& sDirectory ) + throw (css::lang::IllegalArgumentException, + css::uno::RuntimeException ); + + virtual ::rtl::OUString SAL_CALL getDisplayDirectory( ) + throw( css::uno::RuntimeException ); + + virtual css::uno::Sequence< ::rtl::OUString > SAL_CALL getFiles( ) + throw( css::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFilePicker2 functions + //------------------------------------------------------------------------------------ + + virtual css::uno::Sequence< ::rtl::OUString > SAL_CALL getSelectedFiles( ) + throw( css::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFilterManager functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL appendFilter( const ::rtl::OUString& sTitle , + const ::rtl::OUString& sFilter ) + throw (css::lang::IllegalArgumentException, + css::uno::RuntimeException ); + + virtual void SAL_CALL setCurrentFilter( const ::rtl::OUString& sTitle ) + throw (css::lang::IllegalArgumentException, + css::uno::RuntimeException ); + + virtual ::rtl::OUString SAL_CALL getCurrentFilter( ) + throw( css::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFilterGroupManager functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL appendFilterGroup( const ::rtl::OUString& sGroupTitle, + const css::uno::Sequence< css::beans::StringPair >& lFilters ) + throw (css::lang::IllegalArgumentException, + css::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFilePickerControlAccess functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setValue( sal_Int16 nControlId , + sal_Int16 nControlAction, + const css::uno::Any& aValue ) + throw (css::uno::RuntimeException); + + virtual css::uno::Any SAL_CALL getValue( sal_Int16 nControlId , + sal_Int16 nControlAction ) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL enableControl( sal_Int16 nControlId, + sal_Bool bEnable ) + throw(css::uno::RuntimeException ); + + virtual void SAL_CALL setLabel( sal_Int16 nControlId, + const ::rtl::OUString& sLabel ) + throw (css::uno::RuntimeException); + + virtual ::rtl::OUString SAL_CALL getLabel( sal_Int16 nControlId ) + throw (css::uno::RuntimeException); + + //------------------------------------------------ + // XFilePreview + //------------------------------------------------ + + virtual css::uno::Sequence< sal_Int16 > SAL_CALL getSupportedImageFormats( ) + throw (css::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL getTargetColorDepth( ) + throw (css::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL getAvailableWidth( ) + throw (css::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL getAvailableHeight( ) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL setImage( sal_Int16 nImageFormat, + const css::uno::Any& aImage ) + throw (css::lang::IllegalArgumentException, css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL setShowState( sal_Bool bShowState ) + throw (css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL getShowState( ) + throw (css::uno::RuntimeException); + + //------------------------------------------------ + // XInitialization + //------------------------------------------------ + + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& lArguments ) + throw(css::uno::Exception , + css::uno::RuntimeException); + + //------------------------------------------------ + // XCancellable + //------------------------------------------------ + + virtual void SAL_CALL cancel( ) + throw(css::uno::RuntimeException); + + //------------------------------------------------ + // XEventListener + //------------------------------------------------ + + virtual void SAL_CALL disposing( const css::lang::EventObject& aEvent ) + throw(css::uno::RuntimeException); + + //------------------------------------------------ + // XServiceInfo + //------------------------------------------------ + + virtual ::rtl::OUString SAL_CALL getImplementationName( ) + throw(css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) + throw(css::uno::RuntimeException); + + virtual css::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) + throw(css::uno::RuntimeException); + + /* + //------------------------------------------------------------------------------------ + // FilePicker Event functions + //------------------------------------------------------------------------------------ + + void SAL_CALL fileSelectionChanged(const css::ui::dialogs::FilePickerEvent& aEvent ); + void SAL_CALL directoryChanged(const css::ui::dialogs::FilePickerEvent& aEvent ); + ::rtl::OUString SAL_CALL helpRequested(const css::ui::dialogs::FilePickerEvent& aEvent ) const; + void SAL_CALL controlStateChanged(const css::ui::dialogs::FilePickerEvent& aEvent ); + void SAL_CALL dialogSizeChanged( ); + + bool startupEventNotification(bool bStartupSuspended); + void shutdownEventNotification(); + void suspendEventNotification(); + void resumeEventNotification(); + */ + + private: + + // prevent copy and assignment + VistaFilePicker( const VistaFilePicker& ); + VistaFilePicker& operator=( const VistaFilePicker& ); + + using WeakComponentImplHelperBase::disposing; + + private: + + //--------------------------------------------------------------------- + /// service manager to create own used uno services + css::uno::Reference< css::lang::XMultiServiceFactory > m_xSMGR; + + //--------------------------------------------------------------------- + css::uno::Sequence< ::rtl::OUString > m_lLastFiles; + + //--------------------------------------------------------------------- + /** execute the COM dialog within a STA thread + * Must be used on the heap ... because it's implemented as OSL thread .-) + */ + RequestHandlerRef m_rDialog; + AsyncRequests m_aAsyncExecute; + + //--------------------------------------------------------------------- + oslThreadIdentifier m_nFilePickerThreadId; + + bool m_bInitialized; +}; + +} // namespace vista +} // namespace win32 +} // namespace fpicker + +#undef css + +#endif // FPICKER_WIN32_VISTA_FILEPICKER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/VistaFilePickerEventHandler.cxx b/fpicker/source/win32/filepicker/VistaFilePickerEventHandler.cxx new file mode 100644 index 000000000000..541d1a166687 --- /dev/null +++ b/fpicker/source/win32/filepicker/VistaFilePickerEventHandler.cxx @@ -0,0 +1,504 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +#include "VistaFilePickerEventHandler.hxx" +#include "asyncrequests.hxx" + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/document/XDocumentRevisionListPersistence.hpp> +#include <com/sun/star/util/RevisionTag.hpp> +#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> + +#include <comphelper/processfactory.hxx> +#include <comphelper/storagehelper.hxx> + +#include <osl/file.hxx> + +//------------------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------------------ + +namespace css = ::com::sun::star; + +namespace fpicker{ +namespace win32{ +namespace vista{ + +//------------------------------------------------------------------------ +// defines +//------------------------------------------------------------------------ + +//----------------------------------------------------------------------------------------- +VistaFilePickerEventHandler::VistaFilePickerEventHandler(IVistaFilePickerInternalNotify* pInternalNotify) + : m_nRefCount (0 ) + , m_nListenerHandle (0 ) + , m_pDialog ( ) + , m_lListener (m_aMutex) + , m_pInternalNotify (pInternalNotify) +{ +} + +//----------------------------------------------------------------------------------------- +VistaFilePickerEventHandler::~VistaFilePickerEventHandler() +{ +} + +//----------------------------------------------------------------------------------------- +HRESULT STDMETHODCALLTYPE VistaFilePickerEventHandler::QueryInterface(REFIID rIID , + void** ppObject) +{ + *ppObject=NULL; + + if ( rIID == IID_IUnknown ) + *ppObject = (IUnknown*)(IFileDialogEvents*)this; + + if ( rIID == IID_IFileDialogEvents ) + *ppObject = (IFileDialogEvents*)this; + + if ( rIID == IID_IFileDialogControlEvents ) + *ppObject = (IFileDialogControlEvents*)this; + + if ( *ppObject != NULL ) + { + ((IUnknown*)*ppObject)->AddRef(); + return S_OK; + } + + return E_NOINTERFACE; +} + +//----------------------------------------------------------------------------------------- +ULONG STDMETHODCALLTYPE VistaFilePickerEventHandler::AddRef() +{ + return osl_incrementInterlockedCount(&m_nRefCount); +} + +//----------------------------------------------------------------------------------------- +ULONG STDMETHODCALLTYPE VistaFilePickerEventHandler::Release() +{ + ULONG nReturn = --m_nRefCount; + if ( m_nRefCount == 0 ) + delete this; + + return nReturn; +} + +//----------------------------------------------------------------------------------------- +STDMETHODIMP VistaFilePickerEventHandler::OnFileOk(IFileDialog* /*pDialog*/) +{ + return E_NOTIMPL; +} + +//----------------------------------------------------------------------------------------- +STDMETHODIMP VistaFilePickerEventHandler::OnFolderChanging(IFileDialog* /*pDialog*/, + IShellItem* /*pFolder*/) +{ + return E_NOTIMPL; +} + +//----------------------------------------------------------------------------------------- +STDMETHODIMP VistaFilePickerEventHandler::OnFolderChange(IFileDialog* /*pDialog*/) +{ + impl_sendEvent(E_DIRECTORY_CHANGED, 0); + return S_OK; +} + +//----------------------------------------------------------------------------- +::rtl::OUString lcl_getURLFromShellItem2 (IShellItem* pItem) +{ + LPOLESTR pStr = NULL; + ::rtl::OUString sURL; + + SIGDN eConversion = SIGDN_FILESYSPATH; + HRESULT hr = pItem->GetDisplayName ( eConversion, &pStr ); + + if ( FAILED(hr) ) + { + eConversion = SIGDN_URL; + hr = pItem->GetDisplayName ( eConversion, &pStr ); + + if ( FAILED(hr) ) + return ::rtl::OUString(); + + sURL = ::rtl::OUString(reinterpret_cast<sal_Unicode*>(pStr)); + } + else + { + ::osl::FileBase::getFileURLFromSystemPath( reinterpret_cast<sal_Unicode*>(pStr), sURL ); + } + + CoTaskMemFree (pStr); + return sURL; +} + +//----------------------------------------------------------------------------------------- +void lcl_updateVersionListDirectly(IFileDialog* pDialog) +{ + static const ::rtl::OUString SERVICENAME_REVISIONPERSISTENCE(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.document.DocumentRevisionListPersistence")); + static const ::sal_Int16 CONTROL_VERSIONLIST = css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_VERSION; + + TFileDialog iDialog (pDialog); + TFileOpenDialog iOpen ; + TFileDialogCustomize iCustomize; + +#ifdef __MINGW32__ + iDialog->QueryInterface(IID_IFileOpenDialog, (void**)(&iOpen)); + iDialog->QueryInterface(IID_IFileDialogCustomize, (void**)(&iCustomize)); +#else + iDialog.query(&iOpen ); + iDialog.query(&iCustomize); +#endif + + // make sure version list match to the current selection always ... + // at least an empty version list will be better then the wrong one .-) + iCustomize->RemoveAllControlItems(CONTROL_VERSIONLIST); + + HRESULT hResult = E_FAIL; + ComPtr< IShellItemArray > iItems; + ComPtr< IShellItem > iItem; + + if (iOpen.is()) + { + hResult = iOpen->GetSelectedItems(&iItems); + if (FAILED(hResult)) + return; + + DWORD nCount; + hResult = iItems->GetCount(&nCount); + if ( FAILED(hResult) ) + return; + + // we can show one version list only within control + if (nCount != 1) + return; + + hResult = iItems->GetItemAt(0, &iItem); + } + else + if (iDialog.is()) + hResult = iDialog->GetCurrentSelection(&iItem); + + if ( FAILED(hResult) ) + return; + + const ::rtl::OUString sURL = lcl_getURLFromShellItem2(iItem); + if (sURL.getLength() < 1) + return; +/* + INetURLObject aURL(sURL); + if (aURL.GetProtocol() != INET_PROT_FILE) + return; + + ::rtl::OUString sMain = aURL.GetMainURL(INetURLObject::NO_DECODE); + if ( ! ::utl::UCBContentHelper::IsDocument(sURL)) + return; +*/ + try + { + css::uno::Reference< css::embed::XStorage > xStorage = ::comphelper::OStorageHelper::GetStorageFromURL(sURL, css::embed::ElementModes::READ); + if ( ! xStorage.is() ) + return; + + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); + css::uno::Reference< css::document::XDocumentRevisionListPersistence > xReader (xSMGR->createInstance(SERVICENAME_REVISIONPERSISTENCE), css::uno::UNO_QUERY_THROW); + css::uno::Sequence< css::util::RevisionTag > lVersions = xReader->load(xStorage); + + for (::sal_Int32 i=0; i<lVersions.getLength(); ++i) + { + const css::util::RevisionTag& aTag = lVersions[i]; + iCustomize->AddControlItem(CONTROL_VERSIONLIST, i, reinterpret_cast<LPCTSTR>(aTag.Identifier.getStr())); + } + iCustomize->SetSelectedControlItem(CONTROL_VERSIONLIST, 0); + } + catch(const css::uno::Exception&) + {} +} + +//----------------------------------------------------------------------------------------- +STDMETHODIMP VistaFilePickerEventHandler::OnSelectionChange(IFileDialog* /*pDialog*/) +{ + impl_sendEvent(E_FILE_SELECTION_CHANGED, 0); + //lcl_updateVersionListDirectly(pDialog); + return S_OK; +} + +//----------------------------------------------------------------------------------------- +STDMETHODIMP VistaFilePickerEventHandler::OnShareViolation(IFileDialog* /*pDialog*/ , + + IShellItem* /*pItem*/ , + + FDE_SHAREVIOLATION_RESPONSE* /*pResponse*/) +{ + impl_sendEvent(E_CONTROL_STATE_CHANGED, css::ui::dialogs::CommonFilePickerElementIds::LISTBOX_FILTER); + return S_OK; +} + +//----------------------------------------------------------------------------------------- +STDMETHODIMP VistaFilePickerEventHandler::OnTypeChange(IFileDialog* /*pDialog*/) +{ + /* + IFileDialogCustomize *iCustomize; + pDialog->QueryInterface(IID_IFileDialogCustomize, (void**)(&iCustomize)); + + BOOL bValue = FALSE; + HRESULT hResult = iCustomize->GetCheckButtonState( css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, &bValue); + + if ( bValue ) + { + UINT nIndex; + + pDialog->GetFileTypeIndex( &nIndex ); + + LPCWSTR lpFilterExt = lFilters[nIndex].pszSpec; + + lpFilterExt = wcschr( lpFilterExt, '.' ); + if ( lpFilterExt ) + lpFilterExt++; + pDialog->SetDefaultExtension( lpFilterExt ); + } + return S_OK; + + */ + + impl_sendEvent(E_CONTROL_STATE_CHANGED, css::ui::dialogs::CommonFilePickerElementIds::LISTBOX_FILTER); + + return S_OK; +} + +//----------------------------------------------------------------------------------------- +STDMETHODIMP VistaFilePickerEventHandler::OnOverwrite(IFileDialog* /*pDialog*/ , + IShellItem* /*pItem*/ , + FDE_OVERWRITE_RESPONSE* /*pResponse*/) +{ + return E_NOTIMPL; +} + +//----------------------------------------------------------------------------------------- +STDMETHODIMP VistaFilePickerEventHandler::OnItemSelected(IFileDialogCustomize* /*pCustomize*/, + + DWORD nIDCtl , + + DWORD /*nIDItem*/ ) +{ + + impl_sendEvent(E_CONTROL_STATE_CHANGED, static_cast<sal_Int16>( nIDCtl )); + return S_OK; +} + +//----------------------------------------------------------------------------------------- +STDMETHODIMP VistaFilePickerEventHandler::OnButtonClicked(IFileDialogCustomize* /*pCustomize*/, + DWORD nIDCtl ) +{ + + impl_sendEvent(E_CONTROL_STATE_CHANGED, static_cast<sal_Int16>( nIDCtl)); + return S_OK; +} + +//----------------------------------------------------------------------------------------- +STDMETHODIMP VistaFilePickerEventHandler::OnCheckButtonToggled(IFileDialogCustomize* /*pCustomize*/, + DWORD nIDCtl , + BOOL bChecked ) +{ + /* + if (nIDCtl == css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION) + { + LPCWSTR lpFilterExt = 0; + if ( bChecked ) + { + UINT nIndex; + if (m_pDialog) + { + m_pDialog->GetFileTypeIndex( &nIndex ); + lpFilterExt = lFilters[nIndex].pszSpec; + lpFilterExt = wcschr( lpFilterExt, '.' ); + if ( lpFilterExt ) + lpFilterExt++; + } + } + + if (m_pDialog) + m_pDialog->SetDefaultExtension( lpFilterExt ); + } + */ + + if (nIDCtl == css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION) + m_pInternalNotify->onAutoExtensionChanged(bChecked); + + + impl_sendEvent(E_CONTROL_STATE_CHANGED, static_cast<sal_Int16>( nIDCtl)); + + return S_OK; +} + +//----------------------------------------------------------------------------------------- +STDMETHODIMP VistaFilePickerEventHandler::OnControlActivating(IFileDialogCustomize* /*pCustomize*/, + DWORD nIDCtl ) +{ + impl_sendEvent(E_CONTROL_STATE_CHANGED, static_cast<sal_Int16>( nIDCtl)); + return S_OK; +} + +//----------------------------------------------------------------------------------------- +void SAL_CALL VistaFilePickerEventHandler::addFilePickerListener( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener ) + throw( css::uno::RuntimeException ) +{ + m_lListener.addInterface(::getCppuType( (const css::uno::Reference< css::ui::dialogs::XFilePickerListener >*)NULL ), xListener); +} + +//----------------------------------------------------------------------------------------- +void SAL_CALL VistaFilePickerEventHandler::removeFilePickerListener( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener ) + throw( css::uno::RuntimeException ) +{ + m_lListener.removeInterface(::getCppuType( (const css::uno::Reference< css::ui::dialogs::XFilePickerListener >*)NULL ), xListener); +} + +//----------------------------------------------------------------------------------------- +void VistaFilePickerEventHandler::startListening( const TFileDialog& pBroadcaster ) +{ + static const sal_Bool STARTUP_SUSPENDED = sal_True; + static const sal_Bool STARTUP_WORKING = sal_False; + + if (m_pDialog.is()) + return; + + m_pDialog = pBroadcaster; + m_pDialog->Advise(this, &m_nListenerHandle); +} + +//----------------------------------------------------------------------------------------- +void VistaFilePickerEventHandler::stopListening() +{ + if (m_pDialog.is()) + { + m_pDialog->Unadvise(m_nListenerHandle); + m_pDialog.release(); + } +} + +static const ::rtl::OUString PROP_CONTROL_ID(RTL_CONSTASCII_USTRINGPARAM("control_id")); +static const ::rtl::OUString PROP_PICKER_LISTENER(RTL_CONSTASCII_USTRINGPARAM("picker_listener")); + +//----------------------------------------------------------------------------------------- +class AsyncPickerEvents : public RequestHandler +{ +public: + + AsyncPickerEvents() + {} + + virtual ~AsyncPickerEvents() + {} + + virtual void before() + {} + + virtual void doRequest(const RequestRef& rRequest) + { + const ::sal_Int32 nEventID = rRequest->getRequest(); + const ::sal_Int16 nControlID = rRequest->getArgumentOrDefault(PROP_CONTROL_ID, (::sal_Int16)0); + const css::uno::Reference< css::ui::dialogs::XFilePickerListener > xListener = rRequest->getArgumentOrDefault(PROP_PICKER_LISTENER, css::uno::Reference< css::ui::dialogs::XFilePickerListener >()); + + if ( ! xListener.is()) + return; + + css::ui::dialogs::FilePickerEvent aEvent; + aEvent.ElementId = nControlID; + + switch (nEventID) + { + case VistaFilePickerEventHandler::E_FILE_SELECTION_CHANGED : + xListener->fileSelectionChanged(aEvent); + break; + + case VistaFilePickerEventHandler::E_DIRECTORY_CHANGED : + xListener->directoryChanged(aEvent); + break; + + case VistaFilePickerEventHandler::E_HELP_REQUESTED : + xListener->helpRequested(aEvent); + break; + + case VistaFilePickerEventHandler::E_CONTROL_STATE_CHANGED : + xListener->controlStateChanged(aEvent); + break; + + case VistaFilePickerEventHandler::E_DIALOG_SIZE_CHANGED : + xListener->dialogSizeChanged(); + break; + + // no default here. Let compiler detect changes on enum set ! + } + } + + virtual void after() + {} +}; + +//----------------------------------------------------------------------------------------- +void VistaFilePickerEventHandler::impl_sendEvent( EEventType eEventType, + ::sal_Int16 nControlID) +{ + static AsyncRequests aNotify(RequestHandlerRef(new AsyncPickerEvents())); + + ::cppu::OInterfaceContainerHelper* pContainer = m_lListener.getContainer( ::getCppuType( ( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >*) NULL ) ); + if ( ! pContainer) + return; + + ::cppu::OInterfaceIteratorHelper pIterator(*pContainer); + while (pIterator.hasMoreElements()) + { + try + { + css::uno::Reference< css::ui::dialogs::XFilePickerListener > xListener (pIterator.next(), css::uno::UNO_QUERY); + + RequestRef rRequest(new Request()); + rRequest->setRequest (eEventType); + rRequest->setArgument(PROP_PICKER_LISTENER, xListener); + if ( nControlID ) + rRequest->setArgument(PROP_CONTROL_ID, nControlID); + + aNotify.triggerRequestDirectly(rRequest); + //aNotify.triggerRequestNonBlocked(rRequest); + } + catch(const css::uno::RuntimeException&) + { + pIterator.remove(); + } + } +} + +} // namespace vista +} // namespace win32 +} // namespace fpicker + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/VistaFilePickerEventHandler.hxx b/fpicker/source/win32/filepicker/VistaFilePickerEventHandler.hxx new file mode 100644 index 000000000000..85eed3ca39e0 --- /dev/null +++ b/fpicker/source/win32/filepicker/VistaFilePickerEventHandler.hxx @@ -0,0 +1,228 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FPICKER_WIN32_VISTA_FILEPICKER_EVENTHANDLER_HXX +#define FPICKER_WIN32_VISTA_FILEPICKER_EVENTHANDLER_HXX + +//----------------------------------------------------------------------------- +// includes +//----------------------------------------------------------------------------- + +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#pragma warning( disable : 4917 ) +#endif + +#include "comptr.hxx" +#include "vistatypes.h" +#include "IVistaFilePickerInternalNotify.hxx" + +#include <com/sun/star/ui/dialogs/XFilePickerListener.hpp> +#include <com/sun/star/uno/Reference.hxx> + +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/interfacecontainer.h> +#include <osl/interlck.h> + +#include <shobjidl.h> + +//----------------------------------------------------------------------------- +// namespace +//----------------------------------------------------------------------------- + +#ifdef css + #error "Clash on using CSS as namespace define." +#else + #define css ::com::sun::star +#endif + +namespace fpicker{ +namespace win32{ +namespace vista{ + +//----------------------------------------------------------------------------- +// types, const etcpp. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +/** todo document me + */ +class VistaFilePickerEventHandler : public ::cppu::BaseMutex + , public IFileDialogEvents + , public IFileDialogControlEvents +{ + public: + + //------------------------------------------------------------------------------------ + // ctor/dtor + //------------------------------------------------------------------------------------ + + VistaFilePickerEventHandler(IVistaFilePickerInternalNotify* pInternalNotify); + virtual ~VistaFilePickerEventHandler(); + + //------------------------------------------------------------------------------------ + // IUnknown + //------------------------------------------------------------------------------------ + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID rIID , + void** ppObject); + virtual ULONG STDMETHODCALLTYPE AddRef(); + virtual ULONG STDMETHODCALLTYPE Release(); + + //------------------------------------------------------------------------------------ + // IFileDialogEvents + //------------------------------------------------------------------------------------ + + STDMETHODIMP OnFileOk(IFileDialog* pDialog); + + STDMETHODIMP OnFolderChanging(IFileDialog* pDialog, + IShellItem* pFolder); + + STDMETHODIMP OnFolderChange(IFileDialog* pDialog); + + STDMETHODIMP OnSelectionChange(IFileDialog* pDialog); + + STDMETHODIMP OnShareViolation(IFileDialog* pDialog , + IShellItem* pItem , + FDE_SHAREVIOLATION_RESPONSE* pResponse); + + STDMETHODIMP OnTypeChange(IFileDialog* pDialog); + + STDMETHODIMP OnOverwrite(IFileDialog* pDialog , + IShellItem* pItem , + FDE_OVERWRITE_RESPONSE* pResponse); + + //------------------------------------------------------------------------------------ + // IFileDialogControlEvents + //------------------------------------------------------------------------------------ + + STDMETHODIMP OnItemSelected(IFileDialogCustomize* pCustomize, + DWORD nIDCtl , + DWORD nIDItem ); + + STDMETHODIMP OnButtonClicked(IFileDialogCustomize* pCustomize, + DWORD nIDCtl ); + + STDMETHODIMP OnCheckButtonToggled(IFileDialogCustomize* pCustomize, + DWORD nIDCtl , + BOOL bChecked ); + + STDMETHODIMP OnControlActivating(IFileDialogCustomize* pCustomize, + DWORD nIDCtl ); + + //------------------------------------------------------------------------------------ + // XFilePickerNotifier + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL addFilePickerListener( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener ) + throw( css::uno::RuntimeException ); + + virtual void SAL_CALL removeFilePickerListener( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener ) + throw( css::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // native interface + //------------------------------------------------------------------------------------ + + //------------------------------------------------------------------------------------ + /** start listening for file picker events on the given file open dialog COM object. + * + * The broadcaster will be cached internaly so deregistration will be easy. + * Further all needed informations are capsulated within this class (e.g. the listener handler). + * Nobody outside must know such informations. + * + * Nothing will happen if an inconsistent state will be detected + * (means: double registration will be ignored). + * + * @param pBroadcaster + * reference to the dialog, where we should start listening. + */ + void startListening( const TFileDialog& pBroadcaster ); + + //------------------------------------------------------------------------------------ + /** stop listening for file picker events on the internaly cached dialog COM object. + * + * The COM dialog provided on the startListeneing() call was cached internaly. + * And now its used to deregister this listener. Doing so the also internaly cached + * listener handle is used. If listener was not already registered - nothing will happen. + */ + void stopListening(); + + public: + + enum EEventType + { + E_FILE_SELECTION_CHANGED, + E_DIRECTORY_CHANGED, + E_HELP_REQUESTED, + E_CONTROL_STATE_CHANGED, + E_DIALOG_SIZE_CHANGED + }; + + private: + + //------------------------------------------------------------------------------------ + /// @todo document me + void impl_sendEvent( EEventType eEventType, + ::sal_Int16 nControlID); + + private: + + //------------------------------------------------------------------------------------ + /// ref count for AddRef/Release() + oslInterlockedCount m_nRefCount; + + //------------------------------------------------------------------------------------ + /// unique handle for this listener provided by the broadcaster on registration time + DWORD m_nListenerHandle; + + //------------------------------------------------------------------------------------ + /// cached file dialog instance (there we listen for events) + TFileDialog m_pDialog; + + //--------------------------------------------------------------------- + IVistaFilePickerInternalNotify* m_pInternalNotify; + + //--------------------------------------------------------------------- + /** used to inform file picker listener asynchronously. + * Those listener must be called asynchronously .. because + * every request will block the caller thread. Mostly that will be + * the main thread of the office. Further the global SolarMutex will + * be locked during this time. If we call our listener back now synchronously .. + * we will block on SolarMutex.acquire() forever .-)) + */ + ::cppu::OMultiTypeInterfaceContainerHelper m_lListener; +}; + +} // namespace vista +} // namespace win32 +} // namespace fpicker + +#undef css + +#endif // FPICKER_WIN32_VISTA_FILEPICKER_EVENTHANDLER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/VistaFilePickerImpl.cxx b/fpicker/source/win32/filepicker/VistaFilePickerImpl.cxx new file mode 100644 index 000000000000..5c9760b26d7c --- /dev/null +++ b/fpicker/source/win32/filepicker/VistaFilePickerImpl.cxx @@ -0,0 +1,1215 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +//----------------------------------------------------------------------------- +// includes +//----------------------------------------------------------------------------- + +#include "VistaFilePickerImpl.hxx" + +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/ControlActions.hpp> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include <comphelper/sequenceasvector.hxx> +#include <osl/file.hxx> +#include <osl/mutex.hxx> +#ifdef __MINGW32__ +#include <limits.h> +#endif +#include "..\misc\WinImplHelper.hxx" + + inline bool is_current_process_window(HWND hwnd) +{ + DWORD pid; + GetWindowThreadProcessId(hwnd, &pid); + return (pid == GetCurrentProcessId()); +} + +HWND choose_parent_window() +{ + HWND hwnd_parent = GetForegroundWindow(); + if (!is_current_process_window(hwnd_parent)) + hwnd_parent = GetDesktopWindow(); + return hwnd_parent; +} + +//----------------------------------------------------------------------------- +// namespace +//----------------------------------------------------------------------------- + +namespace fpicker{ +namespace win32{ +namespace vista{ + +namespace css = ::com::sun::star; + +//----------------------------------------------------------------------------- +// types, const etcpp. +//----------------------------------------------------------------------------- + + +static const ::sal_Int16 INVALID_CONTROL_ID = -1; +static const ::sal_Int16 INVALID_CONTROL_ACTION = -1; + +typedef ::comphelper::SequenceAsVector< ::rtl::OUString > TStringList; + +// Guids used for IFileDialog::SetClientGuid +static const GUID CLIENTID_FILEDIALOG_SIMPLE = {0xB8628FD3, 0xA3F5, 0x4845, 0x9B, 0x62, 0xD5, 0x1E, 0xDF, 0x97, 0xC4, 0x83}; +static const GUID CLIENTID_FILEDIALOG_OPTIONS = {0x93ED486F, 0x0D04, 0x4807, 0x8C, 0x44, 0xAC, 0x26, 0xCB, 0x6C, 0x5D, 0x36}; +static const GUID CLIENTID_FILESAVE = {0x3B2E2261, 0x402D, 0x4049, 0xB0, 0xC0, 0x91, 0x13, 0xF8, 0x6E, 0x84, 0x7C}; +static const GUID CLIENTID_FILESAVE_PASSWORD = {0xC12D4F4C, 0x4D41, 0x4D4F, 0x97, 0xEF, 0x87, 0xF9, 0x8D, 0xB6, 0x1E, 0xA6}; +static const GUID CLIENTID_FILESAVE_SELECTION = {0x5B2482B3, 0x0358, 0x4E09, 0xAA, 0x64, 0x2B, 0x76, 0xB2, 0xA0, 0xDD, 0xFE}; +static const GUID CLIENTID_FILESAVE_TEMPLATE = {0x9996D877, 0x20D5, 0x424B, 0x9C, 0x2E, 0xD3, 0xB6, 0x31, 0xEC, 0xF7, 0xCE}; +static const GUID CLIENTID_FILEOPEN_LINK_TEMPLATE = {0x32237796, 0x1509, 0x49D1, 0xBB, 0x7E, 0x63, 0xAD, 0x36, 0xAE, 0x86, 0x8C}; +static const GUID CLIENTID_FILEOPEN_PLAY = {0x32CFB147, 0xF5AE, 0x4F90, 0xA1, 0xF1, 0x81, 0x20, 0x72, 0xBB, 0x2F, 0xC5}; +static const GUID CLIENTID_FILEOPEN_LINK = {0x39AC4BAE, 0x7D2D, 0x46BC, 0xBE, 0x2E, 0xF8, 0x8C, 0xB5, 0x65, 0x5E, 0x6A}; + +//----------------------------------------------------------------------------- +::rtl::OUString lcl_getURLFromShellItem (IShellItem* pItem) +{ + LPOLESTR pStr = NULL; + ::rtl::OUString sURL; + + SIGDN eConversion = SIGDN_FILESYSPATH; + HRESULT hr = pItem->GetDisplayName ( eConversion, &pStr ); + + if ( FAILED(hr) ) + { + eConversion = SIGDN_URL; + hr = pItem->GetDisplayName ( eConversion, &pStr ); + + if ( FAILED(hr) ) + return ::rtl::OUString(); + + sURL = ::rtl::OUString(reinterpret_cast<sal_Unicode*>(pStr)); + } + else + { + ::osl::FileBase::getFileURLFromSystemPath( reinterpret_cast<sal_Unicode*>(pStr), sURL ); + } + + CoTaskMemFree (pStr); + return sURL; +} + +//----------------------------------------------------------------------------------------- +::std::vector< COMDLG_FILTERSPEC > lcl_buildFilterList(CFilterContainer& rContainer) +{ + const sal_Int32 c = rContainer.numFilter(); + sal_Int32 i = 0; + ::std::vector< COMDLG_FILTERSPEC > lList ; + CFilterContainer::FILTER_ENTRY_T aFilter; + + rContainer.beginEnumFilter( ); + while( rContainer.getNextFilter(aFilter) ) + { + COMDLG_FILTERSPEC aSpec; + + aSpec.pszName = reinterpret_cast<LPCTSTR>(aFilter.first.getStr()) ; + aSpec.pszSpec = reinterpret_cast<LPCTSTR>(aFilter.second.getStr()); + + lList.push_back(aSpec); + } + + return lList; +} + +//----------------------------------------------------------------------------------------- +VistaFilePickerImpl::VistaFilePickerImpl() + : m_iDialogOpen () + , m_iDialogSave () + , m_hLastResult () + , m_lFilters () + , m_lLastFiles () + , m_iEventHandler(new VistaFilePickerEventHandler(this)) + , m_bInExecute (sal_False) + , m_bWasExecuted (sal_False) + , m_sDirectory () + , m_sFilename () +{ + m_hParentWindow = choose_parent_window(); +} + +//------------------------------------------------------------------------------- +VistaFilePickerImpl::~VistaFilePickerImpl() +{ +} + +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::before() +{ + // SYNCHRONIZED-> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + // TRICKY .-) + // osl::Thread class initializes COm already in MTA mode because it's needed + // by VCL and UNO so. There is no way to change that from outside ... + // but we need a STA environment ... + // So we make it by try-and-error ... + // If first CoInitialize will fail .. we unitialize COM initialize it new .-) + + m_hLastResult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + if ( FAILED(m_hLastResult) ) + { + CoUninitialize(); + m_hLastResult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + } +} + +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::doRequest(const RequestRef& rRequest) +{ + try + { + switch(rRequest->getRequest()) + { + case E_ADD_PICKER_LISTENER : + impl_sta_addFilePickerListener(rRequest); + break; + + case E_REMOVE_PICKER_LISTENER : + impl_sta_removeFilePickerListener(rRequest); + break; + + case E_APPEND_FILTER : + impl_sta_appendFilter(rRequest); + break; + + case E_SET_CURRENT_FILTER : + impl_sta_setCurrentFilter(rRequest); + break; + + case E_GET_CURRENT_FILTER : + impl_sta_getCurrentFilter(rRequest); + break; + + case E_CREATE_OPEN_DIALOG : + impl_sta_CreateOpenDialog(rRequest); + break; + + case E_CREATE_SAVE_DIALOG : + impl_sta_CreateSaveDialog(rRequest); + break; + + case E_SET_MULTISELECTION_MODE : + impl_sta_SetMultiSelectionMode(rRequest); + break; + + case E_SET_TITLE : + impl_sta_SetTitle(rRequest); + break; + + case E_SET_FILENAME: + impl_sta_SetFileName(rRequest); + break; + + case E_SET_DIRECTORY : + impl_sta_SetDirectory(rRequest); + break; + + case E_GET_DIRECTORY : + impl_sta_GetDirectory(rRequest); + break; + + case E_SET_DEFAULT_NAME : + impl_sta_SetDefaultName(rRequest); + break; + + case E_GET_SELECTED_FILES : + impl_sta_getSelectedFiles(rRequest); + break; + + case E_SHOW_DIALOG_MODAL : + impl_sta_ShowDialogModal(rRequest); + break; + + case E_SET_CONTROL_VALUE : + impl_sta_SetControlValue(rRequest); + break; + + case E_GET_CONTROL_VALUE : + impl_sta_GetControlValue(rRequest); + break; + + case E_SET_CONTROL_LABEL : + impl_sta_SetControlLabel(rRequest); + break; + + case E_GET_CONTROL_LABEL : + impl_sta_GetControlLabel(rRequest); + break; + + case E_ENABLE_CONTROL : + impl_sta_EnableControl(rRequest); + break; + + // no default: let the compiler detect changes on enum ERequest ! + } + } + catch(...) + {} +} + +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::after() +{ + CoUninitialize(); +} + +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::impl_sta_addFilePickerListener(const RequestRef& rRequest) +{ + // SYNCHRONIZED outside ! + const css::uno::Reference< css::ui::dialogs::XFilePickerListener > xListener = rRequest->getArgumentOrDefault(PROP_PICKER_LISTENER, css::uno::Reference< css::ui::dialogs::XFilePickerListener >()); + if ( ! xListener.is()) + return; + + // SYNCHRONIZED-> + ::osl::ResettableMutexGuard aLock(m_aMutex); + TFileDialogEvents iHandler = m_iEventHandler; + aLock.clear(); + // <- SYNCHRONIZED + + VistaFilePickerEventHandler* pHandlerImpl = (VistaFilePickerEventHandler*)iHandler.get(); + if (pHandlerImpl) + pHandlerImpl->addFilePickerListener(xListener); +} + +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::impl_sta_removeFilePickerListener(const RequestRef& rRequest) +{ + // SYNCHRONIZED outside ! + const css::uno::Reference< css::ui::dialogs::XFilePickerListener > xListener = rRequest->getArgumentOrDefault(PROP_PICKER_LISTENER, css::uno::Reference< css::ui::dialogs::XFilePickerListener >()); + if ( ! xListener.is()) + return; + + // SYNCHRONIZED-> + ::osl::ResettableMutexGuard aLock(m_aMutex); + TFileDialogEvents iHandler = m_iEventHandler; + aLock.clear(); + // <- SYNCHRONIZED + + VistaFilePickerEventHandler* pHandlerImpl = (VistaFilePickerEventHandler*)iHandler.get(); + if (pHandlerImpl) + pHandlerImpl->removeFilePickerListener(xListener); +} + +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::impl_sta_appendFilter(const RequestRef& rRequest) +{ + const ::rtl::OUString sTitle = rRequest->getArgumentOrDefault(PROP_FILTER_TITLE, ::rtl::OUString()); + const ::rtl::OUString sFilter = rRequest->getArgumentOrDefault(PROP_FILTER_VALUE, ::rtl::OUString()); + + // SYNCHRONIZED-> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + m_lFilters.addFilter(sTitle, sFilter); +} + +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::impl_sta_setCurrentFilter(const RequestRef& rRequest) +{ + const ::rtl::OUString sTitle = rRequest->getArgumentOrDefault(PROP_FILTER_TITLE, ::rtl::OUString()); + + // SYNCHRONIZED-> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + m_lFilters.setCurrentFilter(sTitle); +} + +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::impl_sta_getCurrentFilter(const RequestRef& rRequest) +{ + TFileDialog iDialog = impl_getBaseDialogInterface(); + UINT nIndex = UINT_MAX; + HRESULT hResult = iDialog->GetFileTypeIndex(&nIndex); + if ( + ( FAILED(hResult) ) || + ( nIndex == UINT_MAX ) // COM dialog sometimes return S_OK for empty filter lists .-( + ) + return; + + // SYNCHRONIZED-> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + ::rtl::OUString sTitle; + ::sal_Int32 nRealIndex = (nIndex-1); // COM dialog base on 1 ... filter container on 0 .-) + if ( + (nRealIndex >= 0 ) && + (m_lFilters.getFilter(nRealIndex, sTitle)) + ) + rRequest->setArgument(PROP_FILTER_TITLE, sTitle); + else if ( nRealIndex == -1 ) // Dialog not visible yet + { + sTitle = m_lFilters.getCurrentFilter(); + rRequest->setArgument(PROP_FILTER_TITLE, sTitle); + } + + aLock.clear(); + // <- SYNCHRONIZED +} + +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::impl_sta_CreateOpenDialog(const RequestRef& rRequest) +{ + // SYNCHRONIZED-> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + m_hLastResult = m_iDialogOpen.create(); + if (FAILED(m_hLastResult)) + return; + + TFileDialog iDialog; +#ifdef __MINGW32__ + m_iDialogOpen->QueryInterface(IID_IFileDialog, (void **)(&iDialog)); +#else + m_iDialogOpen.query(&iDialog); +#endif + + TFileDialogEvents iHandler = m_iEventHandler; + + aLock.clear(); + // <- SYNCHRONIZED + + DWORD nFlags = 0; + iDialog->GetOptions ( &nFlags ); + + nFlags &= ~FOS_FORCESHOWHIDDEN; + nFlags |= FOS_PATHMUSTEXIST; + nFlags |= FOS_FILEMUSTEXIST; + nFlags |= FOS_OVERWRITEPROMPT; + nFlags |= FOS_DONTADDTORECENT; + + iDialog->SetOptions ( nFlags ); + + ::sal_Int32 nFeatures = rRequest->getArgumentOrDefault(PROP_FEATURES, (::sal_Int32)0); + ::sal_Int32 nTemplate = rRequest->getArgumentOrDefault(PROP_TEMPLATE_DESCR, (::sal_Int32)0); + impl_sta_enableFeatures(nFeatures, nTemplate); + + VistaFilePickerEventHandler* pHandlerImpl = (VistaFilePickerEventHandler*)iHandler.get(); + if (pHandlerImpl) + pHandlerImpl->startListening(iDialog); +} + +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::impl_sta_CreateSaveDialog(const RequestRef& rRequest) +{ + // SYNCHRONIZED-> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + m_hLastResult = m_iDialogSave.create(); + if (FAILED(m_hLastResult)) + return; + + TFileDialogEvents iHandler = m_iEventHandler; + TFileDialog iDialog; +#ifdef __MINGW32__ + m_iDialogSave->QueryInterface(IID_IFileDialog, (void **)(&iDialog)); +#else + m_iDialogSave.query(&iDialog); +#endif + + aLock.clear(); + // <- SYNCHRONIZED + + DWORD nFlags = 0; + iDialog->GetOptions ( &nFlags ); + + nFlags &= ~FOS_FORCESHOWHIDDEN; + nFlags |= FOS_PATHMUSTEXIST; + nFlags |= FOS_FILEMUSTEXIST; + nFlags |= FOS_OVERWRITEPROMPT; + nFlags |= FOS_DONTADDTORECENT; + + iDialog->SetOptions ( nFlags ); + + ::sal_Int32 nFeatures = rRequest->getArgumentOrDefault(PROP_FEATURES, (::sal_Int32)0); + ::sal_Int32 nTemplate = rRequest->getArgumentOrDefault(PROP_TEMPLATE_DESCR, (::sal_Int32)0); + impl_sta_enableFeatures(nFeatures, nTemplate); + + VistaFilePickerEventHandler* pHandlerImpl = (VistaFilePickerEventHandler*)iHandler.get(); + if (pHandlerImpl) + pHandlerImpl->startListening(iDialog); +} + +//------------------------------------------------------------------------------- +static const ::sal_Int32 GROUP_VERSION = 1; +static const ::sal_Int32 GROUP_TEMPLATE = 2; +static const ::sal_Int32 GROUP_IMAGETEMPLATE = 3; +static const ::sal_Int32 GROUP_CHECKBOXES = 4; + +//------------------------------------------------------------------------------- +static void setLabelToControl(CResourceProvider& rResourceProvider, TFileDialogCustomize iCustom, sal_uInt16 nControlId) +{ + ::rtl::OUString aLabel = rResourceProvider.getResString(nControlId); + aLabel = SOfficeToWindowsLabel(aLabel); + iCustom->SetControlLabel(nControlId, reinterpret_cast<LPCWSTR>(aLabel.getStr()) ); +} + +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::impl_sta_enableFeatures(::sal_Int32 nFeatures, ::sal_Int32 nTemplate) +{ + GUID aGUID = {}; + switch (nTemplate) + { + case css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE : + case css::ui::dialogs::TemplateDescription::FILESAVE_SIMPLE : + aGUID = CLIENTID_FILEDIALOG_SIMPLE; + break; + + case css::ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION : + case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS : + aGUID = CLIENTID_FILEDIALOG_OPTIONS; + break; + + case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION : + aGUID = CLIENTID_FILESAVE; + break; + + case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD : + aGUID = CLIENTID_FILESAVE_PASSWORD; + break; + + case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_SELECTION : + aGUID = CLIENTID_FILESAVE_SELECTION; + break; + + case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_TEMPLATE : + aGUID = CLIENTID_FILESAVE_TEMPLATE; + break; + + case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE : + aGUID = CLIENTID_FILEOPEN_LINK_TEMPLATE; + break; + + case css::ui::dialogs::TemplateDescription::FILEOPEN_PLAY : + aGUID = CLIENTID_FILEOPEN_PLAY; + break; + + case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW : + aGUID = CLIENTID_FILEOPEN_LINK; + break; + } + TFileDialog iDialog = impl_getBaseDialogInterface(); + iDialog->SetClientGuid ( aGUID ); + + TFileDialogCustomize iCustom = impl_getCustomizeInterface(); + + if ((nFeatures & FEATURE_VERSION) == FEATURE_VERSION) + { + iCustom->StartVisualGroup (GROUP_VERSION, L"Version"); + iCustom->AddComboBox (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_VERSION); + iCustom->EndVisualGroup (); + iCustom->MakeProminent (GROUP_VERSION); + } + + if ((nFeatures & FEATURE_TEMPLATE) == FEATURE_TEMPLATE) + { + iCustom->StartVisualGroup (GROUP_TEMPLATE, L"Template"); + iCustom->AddComboBox (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_TEMPLATE); + iCustom->EndVisualGroup (); + iCustom->MakeProminent (GROUP_TEMPLATE); + } + + if ((nFeatures & FEATURE_IMAGETEMPLATE) == FEATURE_IMAGETEMPLATE) + { + iCustom->StartVisualGroup (GROUP_IMAGETEMPLATE, L"Style"); + iCustom->AddComboBox (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE); + iCustom->EndVisualGroup (); + iCustom->MakeProminent (GROUP_IMAGETEMPLATE); + } + + iCustom->StartVisualGroup (GROUP_CHECKBOXES, L""); + + sal_uInt16 nControlId(0); + if ((nFeatures & FEATURE_AUTOEXTENSION) == FEATURE_AUTOEXTENSION) + { + nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION; + iCustom->AddCheckButton (nControlId, L"Auto Extension", true); + setLabelToControl(m_ResProvider, iCustom, nControlId); + } + + if ((nFeatures & FEATURE_PASSWORD) == FEATURE_PASSWORD) + { + nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD; + iCustom->AddCheckButton (nControlId, L"Password", false); + setLabelToControl(m_ResProvider, iCustom, nControlId); + } + + if ((nFeatures & FEATURE_READONLY) == FEATURE_READONLY) + { + nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY; + iCustom->AddCheckButton (nControlId, L"Readonly", false); + setLabelToControl(m_ResProvider, iCustom, nControlId); + } + + if ((nFeatures & FEATURE_FILTEROPTIONS) == FEATURE_FILTEROPTIONS) + { + nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS; + iCustom->AddCheckButton (nControlId, L"Filter Options", false); + setLabelToControl(m_ResProvider, iCustom, nControlId); + } + + if ((nFeatures & FEATURE_LINK) == FEATURE_LINK) + { + nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK; + iCustom->AddCheckButton (nControlId, L"Link", false); + setLabelToControl(m_ResProvider, iCustom, nControlId); + } + + if ((nFeatures & FEATURE_SELECTION) == FEATURE_SELECTION) + { + nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_SELECTION; + iCustom->AddCheckButton (nControlId, L"Selection", false); + setLabelToControl(m_ResProvider, iCustom, nControlId); + } + + /* can be ignored ... new COM dialog supports preview native now ! + if ((nFeatures & FEATURE_PREVIEW) == FEATURE_PREVIEW) + iCustom->AddCheckButton (css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, L"Preview", false); + */ + + iCustom->EndVisualGroup(); + + if ((nFeatures & FEATURE_PLAY) == FEATURE_PLAY) + iCustom->AddPushButton (css::ui::dialogs::ExtendedFilePickerElementIds::PUSHBUTTON_PLAY, L"Play"); + +} + +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::impl_sta_SetMultiSelectionMode(const RequestRef& rRequest) +{ + const ::sal_Bool bMultiSelection = rRequest->getArgumentOrDefault(PROP_MULTISELECTION_MODE, (::sal_Bool)sal_True); + + // SYNCHRONIZED-> + ::osl::ResettableMutexGuard aLock(m_aMutex); + TFileDialog iDialog = impl_getBaseDialogInterface(); + aLock.clear(); + // <- SYNCHRONIZED + + DWORD nFlags = 0; + m_hLastResult = iDialog->GetOptions ( &nFlags ); + + if (bMultiSelection) + nFlags |= FOS_ALLOWMULTISELECT; + else + nFlags &= ~FOS_ALLOWMULTISELECT; + + iDialog->SetOptions ( nFlags ); +} + +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::impl_sta_SetTitle(const RequestRef& rRequest) +{ + ::rtl::OUString sTitle = rRequest->getArgumentOrDefault(PROP_TITLE, ::rtl::OUString()); + + // SYNCHRONIZED-> + ::osl::ResettableMutexGuard aLock(m_aMutex); + TFileDialog iDialog = impl_getBaseDialogInterface(); + aLock.clear(); + // <- SYNCHRONIZED + + iDialog->SetTitle(reinterpret_cast<LPCTSTR>(sTitle.getStr())); +} + +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::impl_sta_SetFileName(const RequestRef& rRequest) +{ + ::rtl::OUString sFileName = rRequest->getArgumentOrDefault(PROP_FILENAME, ::rtl::OUString()); + + // SYNCHRONIZED-> + ::osl::ResettableMutexGuard aLock(m_aMutex); + TFileDialog iDialog = impl_getBaseDialogInterface(); + aLock.clear(); + // <- SYNCHRONIZED + + iDialog->SetFileName(reinterpret_cast<LPCTSTR>(sFileName.getStr())); +} + +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::impl_sta_SetDirectory(const RequestRef& rRequest) +{ + ::rtl::OUString sDirectory = rRequest->getArgumentOrDefault(PROP_DIRECTORY, ::rtl::OUString()); + bool bForce = rRequest->getArgumentOrDefault(PROP_FORCE, false); + + if( !m_bInExecute) + { + // Vista stores last used folders for file dialogs + // so we don't want the application to change the folder + // in most cases. + // Store the requested folder in the mean time and decide later + // what to do + m_sDirectory = sDirectory; + } + + // SYNCHRONIZED-> + ::osl::ResettableMutexGuard aLock(m_aMutex); + TFileDialog iDialog = impl_getBaseDialogInterface(); + aLock.clear(); + // <- SYNCHRONIZED + + ComPtr< IShellItem > pFolder; +#ifdef __MINGW32__ + HRESULT hResult = SHCreateItemFromParsingName ( reinterpret_cast<LPCTSTR>(sDirectory.getStr()), NULL, IID_IShellItem, (void**)(&pFolder) ); +#else + HRESULT hResult = SHCreateItemFromParsingName ( sDirectory, NULL, IID_PPV_ARGS(&pFolder) ); +#endif + if ( FAILED(hResult) ) + return; + + if ( m_bInExecute || bForce ) + iDialog->SetFolder(pFolder); + else + { + // Use set default folder as Microsoft recommends in the IFileDialog documentation. + iDialog->SetDefaultFolder(pFolder); + } +} + +void VistaFilePickerImpl::impl_sta_GetDirectory(const RequestRef& rRequest) +{ + TFileDialog iDialog = impl_getBaseDialogInterface(); + ComPtr< IShellItem > pFolder; + HRESULT hResult = iDialog->GetFolder( &pFolder ); + if ( FAILED(hResult) ) + return; + ::rtl::OUString sFolder = lcl_getURLFromShellItem ( pFolder ); + if( sFolder.getLength()) + rRequest->setArgument( PROP_DIRECTORY, sFolder ); +} + +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::impl_sta_SetDefaultName(const RequestRef& rRequest) +{ + ::rtl::OUString sFilename = rRequest->getArgumentOrDefault(PROP_FILENAME, ::rtl::OUString()); + TFileDialog iDialog = impl_getBaseDialogInterface(); + + TFileDialogCustomize iCustom = impl_getCustomizeInterface(); + if ( ! iCustom.is()) + return; + + // if we have the autoextension check box set, remove (or change ???) the extension of the filename + // so that the autoextension mechanism can do its job + BOOL bValue = FALSE; + HRESULT hResult = iCustom->GetCheckButtonState( css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, &bValue); + if ( bValue ) + { + sal_Int32 nSepPos = sFilename.lastIndexOf( '.' ); + if ( -1 != nSepPos ) + sFilename = sFilename.copy(0, nSepPos); + } + + iDialog->SetFileName ( reinterpret_cast<LPCTSTR>(sFilename.getStr())); + m_sFilename = sFilename; +} + +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::impl_sta_setFiltersOnDialog() +{ + // SYNCHRONIZED-> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + ::std::vector< COMDLG_FILTERSPEC > lFilters = lcl_buildFilterList(m_lFilters); + ::rtl::OUString sCurrentFilter = m_lFilters.getCurrentFilter(); + sal_Int32 nCurrentFilter = m_lFilters.getFilterPos(sCurrentFilter); + TFileDialog iDialog = impl_getBaseDialogInterface(); + TFileDialogCustomize iCustomize = impl_getCustomizeInterface(); + + aLock.clear(); + // <- SYNCHRONIZED + + COMDLG_FILTERSPEC *pFilt = &lFilters[0]; + iDialog->SetFileTypes(lFilters.size(), pFilt/*&lFilters[0]*/); + iDialog->SetFileTypeIndex(nCurrentFilter + 1); + + BOOL bValue = FALSE; + HRESULT hResult = iCustomize->GetCheckButtonState( css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, &bValue); + + if ( bValue ) + { + LPCWSTR lpFilterExt = lFilters[0].pszSpec; + + lpFilterExt = wcsrchr( lpFilterExt, '.' ); + if ( lpFilterExt ) + lpFilterExt++; + iDialog->SetDefaultExtension( lpFilterExt ); + } + +} + +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::impl_sta_getSelectedFiles(const RequestRef& rRequest) +{ + // SYNCHRONIZED-> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + TFileOpenDialog iOpen = m_iDialogOpen; + TFileSaveDialog iSave = m_iDialogSave; + ::sal_Bool bInExecute = m_bInExecute; + + aLock.clear(); + // <- SYNCHRONIZED + + // ask dialog for results + // Note : we must differ between single/multi selection ! + // Note further: we must react different if dialog is in execute or not .-( + ComPtr< IShellItem > iItem; + ComPtr< IShellItemArray > iItems; + HRESULT hResult = E_FAIL; + + if (iOpen.is()) + { + if (bInExecute) + hResult = iOpen->GetSelectedItems(&iItems); + else + { + hResult = iOpen->GetResults(&iItems); + if (FAILED(hResult)) + hResult = iOpen->GetResult(&iItem); + } + } + else + if (iSave.is()) + { + if (bInExecute) + hResult = iSave->GetCurrentSelection(&iItem); + else + hResult = iSave->GetResult(&iItem); + } + + if (FAILED(hResult)) + return; + + // convert and pack results + TStringList lFiles; + if (iItem.is()) + { + const ::rtl::OUString sURL = lcl_getURLFromShellItem(iItem); + if (sURL.getLength() > 0) + lFiles.push_back(sURL); + } + + if (iItems.is()) + { + DWORD nCount; + hResult = iItems->GetCount(&nCount); + if ( SUCCEEDED(hResult) ) + { + for (DWORD i=0; i<nCount; ++i) + { + hResult = iItems->GetItemAt(i, &iItem); + if ( SUCCEEDED(hResult) ) + { + const ::rtl::OUString sURL = lcl_getURLFromShellItem(iItem); + if (sURL.getLength() > 0) + lFiles.push_back(sURL); + } + } + } + } + + rRequest->setArgument(PROP_SELECTED_FILES, lFiles.getAsConstList()); +} + +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::impl_sta_ShowDialogModal(const RequestRef& rRequest) +{ + impl_sta_setFiltersOnDialog(); + + // SYNCHRONIZED-> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + TFileDialog iDialog = impl_getBaseDialogInterface(); + TFileOpenDialog iOpen = m_iDialogOpen; + TFileSaveDialog iSave = m_iDialogSave; + + // it's important to know if we are showing the dialog. + // Some dialog interface methods cant be called then or some + // tasks must be done differently .-) (e.g. see impl_sta_getSelectedFiles()) + m_bInExecute = sal_True; + + m_bWasExecuted = sal_True; + + aLock.clear(); + // <- SYNCHRONIZED + + // we set the directory only if we have a save dialog and a filename + // for the other cases, the file dialog remembers its last location + // according to its client guid. + if( m_sDirectory.getLength()) + { + ComPtr< IShellItem > pFolder; + #ifdef __MINGW32__ + HRESULT hResult = SHCreateItemFromParsingName ( reinterpret_cast<LPCTSTR>(m_sDirectory.getStr()), NULL, IID_IShellItem, (void**)(&pFolder) ); + #else + HRESULT hResult = SHCreateItemFromParsingName ( m_sDirectory, NULL, IID_PPV_ARGS(&pFolder) ); + #endif + if ( SUCCEEDED(hResult) ) + { + if (m_sFilename.getLength()) + { + ::rtl::OUString aFileURL(m_sDirectory); + sal_Int32 nIndex = aFileURL.lastIndexOf('/'); + if (nIndex != aFileURL.getLength()-1) + aFileURL += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/")); + aFileURL += m_sFilename; + + TFileDialogCustomize iCustom = impl_getCustomizeInterface(); + + BOOL bValue = FALSE; + HRESULT hResult = iCustom->GetCheckButtonState( css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, &bValue); + if ( bValue ) + { + ::rtl::OUString aExt; + UINT nFileType; + hResult = iDialog->GetFileTypeIndex(&nFileType); + if ( SUCCEEDED(hResult) ) + { + ::sal_Int32 nRealIndex = (nFileType-1); // COM dialog base on 1 ... filter container on 0 .-) + ::std::vector< COMDLG_FILTERSPEC > lFilters = lcl_buildFilterList(m_lFilters); + LPCWSTR lpFilterExt = lFilters[nRealIndex].pszSpec; + + lpFilterExt = wcsrchr( lpFilterExt, '.' ); + if ( lpFilterExt ) + aFileURL += reinterpret_cast<const sal_Unicode*>(lpFilterExt); + } + } + + // Check existence of file. Set folder only for this special case + ::rtl::OUString aSystemPath; + osl_getSystemPathFromFileURL( aFileURL.pData, &aSystemPath.pData ); + + WIN32_FIND_DATA aFindFileData; + HANDLE hFind = FindFirstFile( reinterpret_cast<LPCWSTR>(aSystemPath.getStr()), &aFindFileData ); + if (hFind != INVALID_HANDLE_VALUE) + iDialog->SetFolder(pFolder); + else + hResult = iDialog->AddPlace(pFolder, FDAP_TOP); + + FindClose( hFind ); + } + else + hResult = iDialog->AddPlace(pFolder, FDAP_TOP); + } + } + + + HRESULT hResult = E_FAIL; + try + { + // show dialog and wait for user decision + if (iOpen.is()) + hResult = iOpen->Show( m_hParentWindow ); // parent window needed + else + if (iSave.is()) + hResult = iSave->Show( m_hParentWindow ); // parent window needed + } + catch(...) + {} + + // SYNCHRONIZED-> + aLock.reset(); + m_bInExecute = sal_False; + aLock.clear(); + // <- SYNCHRONIZED + + if ( FAILED(hResult) ) + return; + + impl_sta_getSelectedFiles(rRequest); + rRequest->setArgument(PROP_DIALOG_SHOW_RESULT, (::sal_Bool)sal_True); +} + +//------------------------------------------------------------------------------- +TFileDialog VistaFilePickerImpl::impl_getBaseDialogInterface() +{ + TFileDialog iDialog; + + // SYNCHRONIZED-> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + if (m_iDialogOpen.is()) +#ifdef __MINGW32__ + m_iDialogOpen->QueryInterface(IID_IFileDialog, (void**)(&iDialog)); +#else + m_iDialogOpen.query(&iDialog); +#endif + if (m_iDialogSave.is()) +#ifdef __MINGW32__ + m_iDialogSave->QueryInterface(IID_IFileDialog, (void**)(&iDialog)); +#else + m_iDialogSave.query(&iDialog); +#endif + + return iDialog; +} + +//------------------------------------------------------------------------------- +TFileDialogCustomize VistaFilePickerImpl::impl_getCustomizeInterface() +{ + TFileDialogCustomize iCustom; + + // SYNCHRONIZED-> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + if (m_iDialogOpen.is()) +#ifdef __MINGW32__ + m_iDialogOpen->QueryInterface(IID_IFileDialogCustomize, (void**)(&iCustom)); +#else + m_iDialogOpen.query(&iCustom); +#endif + else + if (m_iDialogSave.is()) +#ifdef __MINGW32__ + m_iDialogSave->QueryInterface(IID_IFileDialogCustomize, (void**)(&iCustom)); +#else + m_iDialogSave.query(&iCustom); +#endif + + return iCustom; +} + +//------------------------------------------------------------------------------- +void lcl_removeControlItemsWorkaround(const TFileDialogCustomize& iCustom , + ::sal_Int16 nControlId) +{ + ::sal_Int32 i = 0; + HRESULT hResult; + + hResult = iCustom->SetSelectedControlItem(nControlId, 1000); + hResult = S_OK; + while ( SUCCEEDED(hResult) ) + hResult = iCustom->RemoveControlItem(nControlId, i++); +} + +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::impl_sta_SetControlValue(const RequestRef& rRequest) +{ + ::sal_Int16 nId = rRequest->getArgumentOrDefault(PROP_CONTROL_ID , INVALID_CONTROL_ID ); + ::sal_Int16 nAction = rRequest->getArgumentOrDefault(PROP_CONTROL_ACTION, INVALID_CONTROL_ACTION); + css::uno::Any aValue = rRequest->getArgumentOrDefault(PROP_CONTROL_VALUE , css::uno::Any() ); + + // dont check for right values here ... + // most parameters are optional ! + + TFileDialogCustomize iCustom = impl_getCustomizeInterface(); + if ( ! iCustom.is()) + return; + + switch (nId) + { + case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION : + case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD : + case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY : + case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS : + case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK : + //case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW : // can be ignored ... preview is supported native now ! + case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_SELECTION : + { + ::sal_Bool bValue = sal_False; + aValue >>= bValue; + iCustom->SetCheckButtonState(nId, bValue); + } + break; + + case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_VERSION : + case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_TEMPLATE : + case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE : + { + HRESULT hResult; + switch (nAction) + { + case css::ui::dialogs::ControlActions::DELETE_ITEMS : + { + hResult = iCustom->RemoveAllControlItems(nId); + if ( FAILED(hResult) ) + lcl_removeControlItemsWorkaround(iCustom, nId); + } + break; + + case css::ui::dialogs::ControlActions::ADD_ITEMS : + { + css::uno::Sequence< ::rtl::OUString > lItems; + aValue >>= lItems; + for (::sal_Int32 i=0; i<lItems.getLength(); ++i) + { + const ::rtl::OUString& sItem = lItems[i]; + hResult = iCustom->AddControlItem(nId, i, reinterpret_cast<LPCTSTR>(sItem.getStr())); + } + } + break; + + case css::ui::dialogs::ControlActions::SET_SELECT_ITEM : + { + ::sal_Int32 nItem = 0; + aValue >>= nItem; + hResult = iCustom->SetSelectedControlItem(nId, nItem); + } + break; + } + } + break; + + case css::ui::dialogs::ExtendedFilePickerElementIds::PUSHBUTTON_PLAY : + { + } + break; + } +} + +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::impl_sta_GetControlValue(const RequestRef& rRequest) +{ + ::sal_Int16 nId = rRequest->getArgumentOrDefault(PROP_CONTROL_ID , INVALID_CONTROL_ID ); + ::sal_Int16 nAction = rRequest->getArgumentOrDefault(PROP_CONTROL_ACTION, INVALID_CONTROL_ACTION); + + // dont check for right values here ... + // most parameters are optional ! + + TFileDialogCustomize iCustom = impl_getCustomizeInterface(); + if ( ! iCustom.is()) + return; + + css::uno::Any aValue; + if( m_bWasExecuted ) + switch (nId) + { + case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD : + case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY : + case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS : + case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK : + //case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW : // can be ignored ... preview is supported native now ! + case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_SELECTION : + { + BOOL bValue = sal_False; + HRESULT hResult = iCustom->GetCheckButtonState(nId, &bValue); + if ( SUCCEEDED(hResult) ) + aValue = css::uno::makeAny((sal_Bool)bValue); + } + break; + } + + if (aValue.hasValue()) + rRequest->setArgument(PROP_CONTROL_VALUE, aValue); +} + +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::impl_sta_SetControlLabel(const RequestRef& rRequest) +{ + ::sal_Int16 nId = rRequest->getArgumentOrDefault(PROP_CONTROL_ID , INVALID_CONTROL_ID ); + ::rtl::OUString sLabel = rRequest->getArgumentOrDefault(PROP_CONTROL_LABEL, ::rtl::OUString() ); + + // dont check for right values here ... + // most parameters are optional ! + + TFileDialogCustomize iCustom = impl_getCustomizeInterface(); + if ( ! iCustom.is()) + return; + iCustom->SetControlLabel ( nId, reinterpret_cast<LPCTSTR>(sLabel.getStr())); +} + +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::impl_sta_GetControlLabel(const RequestRef& /*rRequest*/) +{ +} + +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::impl_sta_EnableControl(const RequestRef& rRequest) +{ + ::sal_Int16 nId = rRequest->getArgumentOrDefault(PROP_CONTROL_ID , INVALID_CONTROL_ID ); + ::sal_Bool bEnabled = rRequest->getArgumentOrDefault(PROP_CONTROL_ENABLE, (::sal_Bool)sal_True); + + // dont check for right values here ... + // most parameters are optional ! + + TFileDialogCustomize iCustom = impl_getCustomizeInterface(); + if ( ! iCustom.is()) + return; + + CDCONTROLSTATEF eState = CDCS_VISIBLE; + if (bEnabled) + eState |= CDCS_ENABLED; + else + eState |= CDCS_INACTIVE; + + iCustom->SetControlState(nId, eState); +} +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::impl_SetDefaultExtension( const rtl::OUString& currentFilter ) +{ + TFileDialog iDialog = impl_getBaseDialogInterface(); + if (currentFilter.getLength()) + { + rtl::OUString FilterExt; + m_lFilters.getFilter(currentFilter, FilterExt); + + sal_Int32 posOfPoint = FilterExt.indexOf(L'.'); + const sal_Unicode* pFirstExtStart = FilterExt.getStr() + posOfPoint + 1; + + sal_Int32 posOfSemiColon = FilterExt.indexOf(L';') - 1; + if (posOfSemiColon < 0) + posOfSemiColon = FilterExt.getLength() - 1; + + FilterExt = rtl::OUString(pFirstExtStart, posOfSemiColon - posOfPoint); + iDialog->SetDefaultExtension ( reinterpret_cast<LPCTSTR>(FilterExt.getStr()) ); + } +} + + +//------------------------------------------------------------------------------- +void VistaFilePickerImpl::onAutoExtensionChanged (bool bChecked) +{ + // SYNCHRONIZED-> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + const ::rtl::OUString sFilter = m_lFilters.getCurrentFilter (); + ::rtl::OUString sExt ; + if ( !m_lFilters.getFilter (sFilter, sExt)) + return; + + TFileDialog iDialog = impl_getBaseDialogInterface(); + + aLock.clear(); + // <- SYNCHRONIZED + + LPCWSTR pExt = 0; + if ( bChecked ) + { + pExt = reinterpret_cast<LPCTSTR>(sExt.getStr()); + pExt = wcsrchr( pExt, '.' ); + if ( pExt ) + pExt++; + } + iDialog->SetDefaultExtension( pExt ); +} + +} // namespace vista +} // namespace win32 +} // namespace fpicker + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/VistaFilePickerImpl.hxx b/fpicker/source/win32/filepicker/VistaFilePickerImpl.hxx new file mode 100644 index 000000000000..1149c9657f22 --- /dev/null +++ b/fpicker/source/win32/filepicker/VistaFilePickerImpl.hxx @@ -0,0 +1,356 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FPICKER_WIN32_VISTA_FILEPICKERIMPL_HXX +#define FPICKER_WIN32_VISTA_FILEPICKERIMPL_HXX + +//----------------------------------------------------------------------------- +// includes +//----------------------------------------------------------------------------- + +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#pragma warning( disable : 4917 ) +#endif + +#include "platform_vista.h" +#include "asyncrequests.hxx" +#include "comptr.hxx" +#include "vistatypes.h" +#include "FilterContainer.hxx" +#include "VistaFilePickerEventHandler.hxx" +#include "IVistaFilePickerInternalNotify.hxx" +#include "..\misc\resourceprovider.hxx" + +#include <com/sun/star/uno/Sequence.hxx> + +#include <comphelper/sequenceashashmap.hxx> +#include <cppuhelper/interfacecontainer.h> +#include <cppuhelper/basemutex.hxx> +#include <osl/thread.hxx> +#include <osl/conditn.hxx> +#include <rtl/ustring.hxx> + +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <shobjidl.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +//----------------------------------------------------------------------------- +// namespace +//----------------------------------------------------------------------------- + +#ifdef css + #error "Clash on using CSS as namespace define." +#else + #define css ::com::sun::star +#endif + +namespace fpicker{ +namespace win32{ +namespace vista{ + +//----------------------------------------------------------------------------- +// types, const etcpp +//----------------------------------------------------------------------------- + +static const ::sal_Int32 FEATURE_AUTOEXTENSION = 1; +static const ::sal_Int32 FEATURE_PASSWORD = 2; +static const ::sal_Int32 FEATURE_FILTEROPTIONS = 4; +static const ::sal_Int32 FEATURE_SELECTION = 8; +static const ::sal_Int32 FEATURE_TEMPLATE = 16; +static const ::sal_Int32 FEATURE_LINK = 32; +static const ::sal_Int32 FEATURE_PREVIEW = 64; +static const ::sal_Int32 FEATURE_IMAGETEMPLATE = 128; +static const ::sal_Int32 FEATURE_PLAY = 256; +static const ::sal_Int32 FEATURE_READONLY = 512; +static const ::sal_Int32 FEATURE_VERSION = 1024; + +static const ::rtl::OUString PROP_PICKER_LISTENER(RTL_CONSTASCII_USTRINGPARAM("picker_listener" ) ); // [XFilePickerListenert] +static const ::rtl::OUString PROP_DIALOG_SHOW_RESULT(RTL_CONSTASCII_USTRINGPARAM("dialog_show_result" )); // [sal_Bool] true=OK, false=CANCEL +static const ::rtl::OUString PROP_SELECTED_FILES(RTL_CONSTASCII_USTRINGPARAM("selected_files" )); // [seq< OUString >] contains all user selected files (can be empty!) +static const ::rtl::OUString PROP_MULTISELECTION_MODE(RTL_CONSTASCII_USTRINGPARAM("multiselection_mode")); // [sal_Bool] true=ON, false=OFF +static const ::rtl::OUString PROP_TITLE(RTL_CONSTASCII_USTRINGPARAM("title" )); // [OUString] +static const ::rtl::OUString PROP_FILENAME(RTL_CONSTASCII_USTRINGPARAM("filename" ) ); // [OUString] +static const ::rtl::OUString PROP_DIRECTORY(RTL_CONSTASCII_USTRINGPARAM("directory" )); // [OUString] +static const ::rtl::OUString PROP_FEATURES(RTL_CONSTASCII_USTRINGPARAM("features" )); // [sal_Int32] +static const ::rtl::OUString PROP_TEMPLATE_DESCR(RTL_CONSTASCII_USTRINGPARAM("templatedescription")); // [sal_Int32] +static const ::rtl::OUString PROP_FILTER_TITLE(RTL_CONSTASCII_USTRINGPARAM("filter_title" )); // [OUString] +static const ::rtl::OUString PROP_FILTER_VALUE(RTL_CONSTASCII_USTRINGPARAM("filter_value" )); // [OUString] +static const ::rtl::OUString PROP_FORCE(RTL_CONSTASCII_USTRINGPARAM("force" )); // [sal_Bool] + +static const ::rtl::OUString PROP_CONTROL_ID(RTL_CONSTASCII_USTRINGPARAM("control_id" )); // [sal_Int16] +static const ::rtl::OUString PROP_CONTROL_ACTION(RTL_CONSTASCII_USTRINGPARAM("control_action" )); // [sal_Int16] +static const ::rtl::OUString PROP_CONTROL_VALUE(RTL_CONSTASCII_USTRINGPARAM("control_value" )); // [Any] +static const ::rtl::OUString PROP_CONTROL_LABEL(RTL_CONSTASCII_USTRINGPARAM("control_label" )); // [OUString] +static const ::rtl::OUString PROP_CONTROL_ENABLE(RTL_CONSTASCII_USTRINGPARAM("control_enable" )); // [sal_Bool] true=ON, false=OFF + +//----------------------------------------------------------------------------- +/** native implementation of the file picker on Vista and upcoming windows versions. + * This dialog uses COM internaly. Further it marshall every request so it will + * be executed within it's own STA thread ! + */ +//----------------------------------------------------------------------------- +class VistaFilePickerImpl : private ::cppu::BaseMutex + , public RequestHandler + , public IVistaFilePickerInternalNotify +{ + public: + + //--------------------------------------------------------------------- + /** used for marshalling requests. + * Will be used to map requests to the right implementations. + */ + enum ERequest + { + E_NO_REQUEST, + E_ADD_PICKER_LISTENER, + E_REMOVE_PICKER_LISTENER, + E_APPEND_FILTER, + E_SET_CURRENT_FILTER, + E_GET_CURRENT_FILTER, + E_CREATE_OPEN_DIALOG, + E_CREATE_SAVE_DIALOG, + E_SET_MULTISELECTION_MODE, + E_SET_TITLE, + E_SET_FILENAME, + E_GET_DIRECTORY, + E_SET_DIRECTORY, + E_SET_DEFAULT_NAME, + E_GET_SELECTED_FILES, + E_SHOW_DIALOG_MODAL, + E_SET_CONTROL_VALUE, + E_GET_CONTROL_VALUE, + E_SET_CONTROL_LABEL, + E_GET_CONTROL_LABEL, + E_ENABLE_CONTROL + }; + + public: + + //--------------------------------------------------------------------- + // ctor/dtor - nothing special + //--------------------------------------------------------------------- + VistaFilePickerImpl(); + virtual ~VistaFilePickerImpl(); + + //--------------------------------------------------------------------- + // RequestHandler + //--------------------------------------------------------------------- + + virtual void before(); + virtual void doRequest(const RequestRef& rRequest); + virtual void after(); + + //--------------------------------------------------------------------- + virtual void onAutoExtensionChanged (bool bChecked); + + private: + + //--------------------------------------------------------------------- + /// implementation of request E_ADD_FILEPICKER_LISTENER + void impl_sta_addFilePickerListener(const RequestRef& rRequest); + + //--------------------------------------------------------------------- + /// implementation of request E_REMOVE_FILEPICKER_LISTENER + void impl_sta_removeFilePickerListener(const RequestRef& rRequest); + + //--------------------------------------------------------------------- + /// implementation of request E_APPEND_FILTER + void impl_sta_appendFilter(const RequestRef& rRequest); + + //--------------------------------------------------------------------- + /// implementation of request E_SET_CURRENT_FILTER + void impl_sta_setCurrentFilter(const RequestRef& rRequest); + + //--------------------------------------------------------------------- + /// implementation of request E_GET_CURRENT_FILTER + void impl_sta_getCurrentFilter(const RequestRef& rRequest); + + //--------------------------------------------------------------------- + /// implementation of request E_CREATE_OPEN_DIALOG + void impl_sta_CreateOpenDialog(const RequestRef& rRequest); + + //--------------------------------------------------------------------- + /// implementation of request E_CREATE_SAVE_DIALOG + void impl_sta_CreateSaveDialog(const RequestRef& rRequest); + + //--------------------------------------------------------------------- + /// implementation of request E_SET_MULTISELECTION_MODE + void impl_sta_SetMultiSelectionMode(const RequestRef& rRequest); + + //--------------------------------------------------------------------- + /// implementation of request E_SET_TITLE + void impl_sta_SetTitle(const RequestRef& rRequest); + + //--------------------------------------------------------------------- + /// implementation of request E_SET_FILENAME + void impl_sta_SetFileName(const RequestRef& rRequest); + + //--------------------------------------------------------------------- + /// implementation of request E_SET_DIRECTORY + void impl_sta_SetDirectory(const RequestRef& rRequest); + + //--------------------------------------------------------------------- + /// implementation of request E_GET_DIRECTORY + void impl_sta_GetDirectory(const RequestRef& rRequest); + + //--------------------------------------------------------------------- + /// implementation of request E_SET_DEFAULT_NAME + void impl_sta_SetDefaultName(const RequestRef& rRequest); + + //--------------------------------------------------------------------- + /// implementation of request E_GET_SELECTED_FILES + void impl_sta_getSelectedFiles(const RequestRef& rRequest); + + //--------------------------------------------------------------------- + /// implementation of request E_SHOW_DIALOG_MODAL + void impl_sta_ShowDialogModal(const RequestRef& rRequest); + + //--------------------------------------------------------------------- + /// implementation of request E_SET_CONTROL_VALUE + void impl_sta_SetControlValue(const RequestRef& rRequest); + + //--------------------------------------------------------------------- + /// implementation of request E_GET_CONTROL_VALUE + void impl_sta_GetControlValue(const RequestRef& rRequest); + + //--------------------------------------------------------------------- + /// implementation of request E_SET_CONTROL_LABEL + void impl_sta_SetControlLabel(const RequestRef& rRequest); + + //--------------------------------------------------------------------- + /// implementation of request E_GET_CONTROL_LABEL + void impl_sta_GetControlLabel(const RequestRef& rRequest); + + //--------------------------------------------------------------------- + /// implementation of request E_ENABLE_CONTROL + void impl_sta_EnableControl(const RequestRef& rRequest); + + //--------------------------------------------------------------------- + /** create all needed (optional!) UI controls adressed by the field nFeatures. + * The given number nFeatures is used as a flag field. Use const values FEATURE_XXX + * to adress it. + * + * Internal new controls will be added to the dialog. Every control can be accessed + * by it's own control id. Those control ID must be one of the const set + * css::ui::dialogs::ExtendedFilePickerElementIds. + * + * @see setControlValue() + * @see getControlValue() + * @see setControlLabel() + * @see getControlLabel() + * @see enableControl() + * + * @param nFeatures + * flag field(!) knows all features wich must be enabled. + */ + void impl_sta_enableFeatures(::sal_Int32 nFeatures, ::sal_Int32 nTemplate); + + //--------------------------------------------------------------------- + /** returns an interface, which can be used to customize the internaly used + * COM dialog. + * + * Because we use two member (open/save dialog) internaly, this method + * ask the current active one for it's customization interface. + * + * @return the customization interface for the current used dialog. + * Must not be null. + */ + TFileDialogCustomize impl_getCustomizeInterface(); + TFileDialog impl_getBaseDialogInterface(); + + //--------------------------------------------------------------------- + /// fill filter list of internal used dialog. + void impl_sta_setFiltersOnDialog(); + + void impl_SetDefaultExtension( const rtl::OUString& currentFilter ); + + private: + + //--------------------------------------------------------------------- + /// COM object representing a file open dialog + TFileOpenDialog m_iDialogOpen; + + //--------------------------------------------------------------------- + /// COM object representing a file save dialog + TFileSaveDialog m_iDialogSave; + + //--------------------------------------------------------------------- + /// knows the return state of the last COM call + HRESULT m_hLastResult; + + //--------------------------------------------------------------------- + /// @todo document me + CFilterContainer m_lFilters; + + //--------------------------------------------------------------------- + /** cache last selected list of files + * Because those list must be retrieved directly after closing the dialog + * (and only in case it was finished successfully) we cache it internaly. + * Because the outside provided UNO API decouple showing the dialog + * and asking for results .-) + */ + css::uno::Sequence< ::rtl::OUString > m_lLastFiles; + + //--------------------------------------------------------------------- + /** help us to handle dialog events and provide them to interested office + * listener. + */ + TFileDialogEvents m_iEventHandler; + + //--------------------------------------------------------------------- + /// @todo document me + ::sal_Bool m_bInExecute; + + ::sal_Bool m_bWasExecuted; + + // handle to parent window + HWND m_hParentWindow; + + // + ::rtl::OUString m_sDirectory; + + // + ::rtl::OUString m_sFilename; + + // Resource provider + CResourceProvider m_ResProvider; +}; + +} // namespace vista +} // namespace win32 +} // namespace fpicker + +#undef css + +#endif // FPICKER_WIN32_VISTA_FILEPICKERIMPL_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/WinFileOpenImpl.cxx b/fpicker/source/win32/filepicker/WinFileOpenImpl.cxx new file mode 100644 index 000000000000..00c41cdfe30a --- /dev/null +++ b/fpicker/source/win32/filepicker/WinFileOpenImpl.cxx @@ -0,0 +1,997 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include "shared.hxx" +#include "WinFileOpenImpl.hxx" +#include <osl/diagnose.h> +#include <osl/file.hxx> +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/FilePickerEvent.hpp> +#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> +#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/FilePreviewImageFormats.hpp> +#include <com/sun/star/ui/dialogs/ListBoxControlActions.hpp> +#include "..\misc\WinImplHelper.hxx" + +#include "filepicker.hxx" +#include "controlaccess.hxx" +#include <rtl/ustrbuf.hxx> +#include <rtl/string.hxx> +#include <osl/thread.hxx> +#include "filepickerstate.hxx" + +//------------------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------------------ + +using namespace com::sun::star; + +using com::sun::star::ui::dialogs::FilePickerEvent; +using com::sun::star::lang::IllegalArgumentException; +using com::sun::star::ui::dialogs::XFilePicker2; + +using namespace ::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds; +using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds; +using namespace ::com::sun::star::ui::dialogs::ListboxControlActions; + +//------------------------------------------------------------------------- +// to distinguish what to do in the enum child window callback function +//------------------------------------------------------------------------- + +enum ECW_ACTION_T +{ + INIT_CUSTOM_CONTROLS, + CACHE_CONTROL_VALUES +}; + +struct EnumParam +{ + ECW_ACTION_T m_action; + CWinFileOpenImpl* m_instance; + + EnumParam( ECW_ACTION_T action, CWinFileOpenImpl* instance ): + m_action( action ), + m_instance( instance ) + {} +}; + +//------------------------------------------------------------------------- +// ctor +//------------------------------------------------------------------------- + +CWinFileOpenImpl::CWinFileOpenImpl( + CFilePicker* aFilePicker, + sal_Bool bFileOpenDialog, + sal_uInt32 dwFlags, + sal_uInt32 dwTemplateId, + HINSTANCE hInstance) : + CFileOpenDialog(bFileOpenDialog, dwFlags, dwTemplateId, hInstance), + m_filterContainer(new CFilterContainer()), + m_Preview(new CPreviewAdapter(hInstance)), + m_CustomControlFactory(new CCustomControlFactory()), + m_CustomControls(m_CustomControlFactory->CreateCustomControlContainer()), + m_FilePicker(aFilePicker), + m_bInitialSelChanged(sal_True), + m_HelpPopupWindow(hInstance, m_hwndFileOpenDlg), + m_ExecuteFilePickerState(new CExecuteFilePickerState()), + m_NonExecuteFilePickerState(new CNonExecuteFilePickerState()) +{ + m_FilePickerState = m_NonExecuteFilePickerState; +} + +//------------------------------------------------------------------------ +// dtor +//------------------------------------------------------------------------ + +CWinFileOpenImpl::~CWinFileOpenImpl() +{ + delete m_ExecuteFilePickerState; + delete m_NonExecuteFilePickerState; +} + +//------------------------------------------------------------------------ +// we expect the directory in URL format +//------------------------------------------------------------------------ + +void CWinFileOpenImpl::setDisplayDirectory(const rtl::OUString& aDirectory) + throw( IllegalArgumentException, uno::RuntimeException ) +{ + rtl::OUString aSysDirectory; + if( aDirectory.getLength() > 0) + { + if ( ::osl::FileBase::E_None != + ::osl::FileBase::getSystemPathFromFileURL(aDirectory,aSysDirectory)) + throw IllegalArgumentException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Invalid directory")), + static_cast<XFilePicker2*>(m_FilePicker), 1); + + // we ensure that there is a trailing '/' at the end of + // he given file url, because the windows functions only + // works correctly when providing "c:\" or an environment + // variable like "=c:=c:\.." etc. is set, else the + // FolderPicker would stand in the root of the shell + // hierarchie which is the desktop folder + if ( aSysDirectory.lastIndexOf(BACKSLASH) != (aSysDirectory.getLength() - 1)) + aSysDirectory += BACKSLASH; + } + + // call base class method + CFileOpenDialog::setDisplayDirectory(aSysDirectory); +} + +//------------------------------------------------------------------------ +// we return the directory in URL format +//------------------------------------------------------------------------ + +rtl::OUString CWinFileOpenImpl::getDisplayDirectory() throw(uno::RuntimeException) +{ + return m_FilePickerState->getDisplayDirectory(this); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL CWinFileOpenImpl::setDefaultName(const rtl::OUString& aName) + throw( IllegalArgumentException, uno::RuntimeException ) +{ + // we don't set the default name directly + // because this influences how the file open + // dialog sets the initial path when it is about + // to open (see MSDN: OPENFILENAME) + // so we save the default name which should + // appear in the file-name-box and set + // this name when processing onInitDone + m_defaultName = aName; +} + +//----------------------------------------------------------------------------------------- +// return format: URL +// if multiselection is allowed there are two different cases +// 1. one file selected: the sequence contains one entry path\filename.ext +// 2. multiple files selected: the sequence contains multiple entries +// the first entry is the path url, all other entries are file names +//----------------------------------------------------------------------------------------- + +uno::Sequence<rtl::OUString> SAL_CALL CWinFileOpenImpl::getFiles() + throw(uno::RuntimeException) +{ + return m_FilePickerState->getFiles(this); +} + +//----------------------------------------------------------------------------------------- +// shows the FileOpen/FileSave dialog +//----------------------------------------------------------------------------------------- + +sal_Int16 SAL_CALL CWinFileOpenImpl::execute( ) throw(uno::RuntimeException) +{ + sal_Int16 rc = CFileOpenDialog::doModal(); + + if (1 == rc) + rc = ::com::sun::star::ui::dialogs::ExecutableDialogResults::OK; + else if (0 == rc) + rc = ::com::sun::star::ui::dialogs::ExecutableDialogResults::CANCEL; + else + throw uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Error executing dialog")), + static_cast<XFilePicker2*>(m_FilePicker)); + + return rc; +} + +//----------------------------------------------------------------------------------------- +// appends a new filter +// returns false if the title (aTitle) was already added or the title or the filter are +// empty +//----------------------------------------------------------------------------------------- + +void SAL_CALL CWinFileOpenImpl::appendFilter(const rtl::OUString& aTitle, const rtl::OUString& aFilter) + throw(IllegalArgumentException, uno::RuntimeException) +{ + sal_Bool bRet = m_filterContainer->addFilter(aTitle, aFilter); + + if (!bRet) + throw IllegalArgumentException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("filter already exists")), + static_cast<XFilePicker2*>(m_FilePicker), 1); + + // #95345# see MSDN OPENFILENAME + // If nFilterIndex is zero and lpstrCustomFilter is NULL, + // the system uses the first filter in the lpstrFilter buffer. + // to reflect this we must set the filter index so that calls + // to getSelectedFilterIndex without explicitly calling + // setFilterIndex before does not return 0 which leads to a + // false state + if (0 == getSelectedFilterIndex()) + CFileOpenDialog::setFilterIndex(1); +} + +//----------------------------------------------------------------------------------------- +// sets a current filter +//----------------------------------------------------------------------------------------- + +void SAL_CALL CWinFileOpenImpl::setCurrentFilter(const rtl::OUString& aTitle) + throw( IllegalArgumentException, uno::RuntimeException) +{ + sal_Int32 filterPos = m_filterContainer->getFilterPos(aTitle); + + if (filterPos < 0) + throw IllegalArgumentException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("filter doesn't exist")), + static_cast<XFilePicker2*>(m_FilePicker), 1); + + // filter index of the base class starts with 1 + CFileOpenDialog::setFilterIndex(filterPos + 1); +} + +//----------------------------------------------------------------------------------------- +// returns the currently selected filter +//----------------------------------------------------------------------------------------- + +rtl::OUString SAL_CALL CWinFileOpenImpl::getCurrentFilter() throw(uno::RuntimeException) +{ + sal_uInt32 nIndex = getSelectedFilterIndex(); + + rtl::OUString currentFilter; + if (nIndex > 0) + { + // filter index of the base class starts with 1 + if (!m_filterContainer->getFilter(nIndex - 1, currentFilter)) { + OSL_ASSERT(false); + } + } + + return currentFilter; +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +inline void SAL_CALL CWinFileOpenImpl::appendFilterGroupSeparator() +{ + m_filterContainer->addFilter(FILTER_SEPARATOR, ALL_FILES_WILDCARD, ALLOW_DUPLICATES); +} + +//----------------------------------------------------------------------------------------- +// XFilterGroupManager +//----------------------------------------------------------------------------------------- + +void SAL_CALL CWinFileOpenImpl::appendFilterGroup(const rtl::OUString& sGroupTitle, const uno::Sequence<beans::StringPair>& aFilters) + throw (IllegalArgumentException, uno::RuntimeException) +{ + (void) sGroupTitle; // avoid warning + OSL_ENSURE(0 == sGroupTitle.getLength(), "appendFilterGroup: Parameter 'GroupTitle' currently ignored"); + + sal_Int32 nFilters = aFilters.getLength(); + + OSL_PRECOND(nFilters > 0, "Empty filter list"); + + if (nFilters > 0) + { + // append a separator before the next group if + // there is already a group of filters + if (m_filterContainer->numFilter() > 0) + appendFilterGroupSeparator(); + + for (int i = 0; i < nFilters; i++) + appendFilter(aFilters[i].First, aFilters[i].Second); + } +} + +//================================================================================================================= +// XExtendedFilePicker +//================================================================================================================= + +void SAL_CALL CWinFileOpenImpl::setValue(sal_Int16 aControlId, sal_Int16 aControlAction, const uno::Any& aValue) + throw(uno::RuntimeException) +{ + OSL_ASSERT(m_FilePickerState); + m_FilePickerState->setValue(aControlId, aControlAction, aValue); +} + +//----------------------------------------------------------------------------------------- +// returns the value of an custom template element +// we assume that there are only checkboxes or comboboxes +//----------------------------------------------------------------------------------------- + +uno::Any SAL_CALL CWinFileOpenImpl::getValue(sal_Int16 aControlId, sal_Int16 aControlAction) + throw(uno::RuntimeException) +{ + OSL_ASSERT(m_FilePickerState); + return m_FilePickerState->getValue(aControlId, aControlAction); +} + +//----------------------------------------------------------------------------------------- +// enables a custom template element +//----------------------------------------------------------------------------------------- + +void SAL_CALL CWinFileOpenImpl::enableControl(sal_Int16 ControlID, sal_Bool bEnable) + throw(uno::RuntimeException) +{ + OSL_ASSERT(m_FilePickerState); + m_FilePickerState->enableControl(ControlID, bEnable); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL CWinFileOpenImpl::setLabel( sal_Int16 aControlId, const rtl::OUString& aLabel ) + throw (uno::RuntimeException) +{ + m_FilePickerState->setLabel(aControlId, aLabel); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +rtl::OUString SAL_CALL CWinFileOpenImpl::getLabel( sal_Int16 aControlId ) + throw (uno::RuntimeException) +{ + return m_FilePickerState->getLabel(aControlId); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +uno::Sequence<sal_Int16> SAL_CALL CWinFileOpenImpl::getSupportedImageFormats() + throw (uno::RuntimeException) +{ + return m_Preview->getSupportedImageFormats(); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +sal_Int32 SAL_CALL CWinFileOpenImpl::getTargetColorDepth() + throw (uno::RuntimeException) +{ + return m_Preview->getTargetColorDepth(); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +sal_Int32 SAL_CALL CWinFileOpenImpl::getAvailableWidth() + throw (uno::RuntimeException) +{ + return m_Preview->getAvailableWidth(); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +sal_Int32 SAL_CALL CWinFileOpenImpl::getAvailableHeight() + throw (uno::RuntimeException) +{ + return m_Preview->getAvailableHeight(); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL CWinFileOpenImpl::setImage(sal_Int16 aImageFormat, const uno::Any& aImage) + throw (IllegalArgumentException, uno::RuntimeException) +{ + m_Preview->setImage(aImageFormat,aImage); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +sal_Bool SAL_CALL CWinFileOpenImpl::setShowState(sal_Bool bShowState) + throw (uno::RuntimeException) +{ + return m_Preview->setShowState(bShowState); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +sal_Bool SAL_CALL CWinFileOpenImpl::getShowState() + throw (uno::RuntimeException) +{ + return m_Preview->getShowState(); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL CWinFileOpenImpl::cancel() +{ + if (IsWindow(m_hwndFileOpenDlg)) + { + // simulate a mouse click to the + // cancel button + PostMessage( + m_hwndFileOpenDlg, + WM_COMMAND, + MAKEWPARAM(IDCANCEL,BN_CLICKED), + (LPARAM)GetDlgItem(m_hwndFileOpenDlg, IDCANCEL)); + } +} + +//----------------------------------------------------------------------------------------- +// returns the id of a custom template element +//----------------------------------------------------------------------------------------- + +sal_Int16 SAL_CALL CWinFileOpenImpl::getFocused() +{ + int nID = GetDlgCtrlID(GetFocus()); + + // we don't forward id's of standard file open + // dialog elements (ctlFirst is defined in dlgs.h + // in MS Platform SDK) + if (nID >= ctlFirst) + nID = 0; + + return sal::static_int_cast< sal_Int16 >(nID); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +inline sal_Bool SAL_CALL CWinFileOpenImpl::IsCustomControlHelpRequested(LPHELPINFO lphi) const +{ + return ((lphi->iCtrlId != IDOK) && (lphi->iCtrlId != IDCANCEL) && (lphi->iCtrlId < ctlFirst)); +} + +//----------------------------------------------------------------------------------------- +// our own DlgProc because we do subclass the dialog +// we catch the WM_NCDESTROY message in order to erase an entry in our static map +// if one instance dies +//----------------------------------------------------------------------------------------- + +LRESULT CALLBACK CWinFileOpenImpl::SubClassFunc( + HWND hWnd, UINT wMessage, WPARAM wParam, LPARAM lParam) +{ + unsigned int lResult = 0; + + CWinFileOpenImpl* pImpl = dynamic_cast<CWinFileOpenImpl*>(getCurrentInstance(hWnd)); + + switch(wMessage) + { + case WM_HELP: + { + LPHELPINFO lphi = reinterpret_cast<LPHELPINFO>(lParam); + + if (pImpl->IsCustomControlHelpRequested(lphi)) + pImpl->onCustomControlHelpRequest(lphi); + else + lResult = CallWindowProc( + reinterpret_cast<WNDPROC>(pImpl->m_pfnOldDlgProc), + hWnd,wMessage,wParam,lParam); + } + break; + + case WM_SIZE: + lResult = CallWindowProc( + reinterpret_cast<WNDPROC>(pImpl->m_pfnOldDlgProc), + hWnd,wMessage,wParam,lParam); + + pImpl->onWMSize(); + break; + + case WM_WINDOWPOSCHANGED: + lResult = CallWindowProc( + reinterpret_cast<WNDPROC>(pImpl->m_pfnOldDlgProc), + hWnd,wMessage,wParam,lParam); + + pImpl->onWMWindowPosChanged(); + break; + + case WM_SHOWWINDOW: + lResult = CallWindowProc( + reinterpret_cast<WNDPROC>(pImpl->m_pfnOldDlgProc), + hWnd,wMessage,wParam,lParam); + + pImpl->onWMShow((BOOL)wParam); + break; + + case WM_NCDESTROY: + // restore the old window proc + SetWindowLong(hWnd, GWL_WNDPROC, + reinterpret_cast<LONG>(pImpl->m_pfnOldDlgProc)); + + lResult = CallWindowProc( + reinterpret_cast<WNDPROC>(pImpl->m_pfnOldDlgProc), + hWnd,wMessage,wParam,lParam); + break; + + default: + lResult = CallWindowProc( + reinterpret_cast<WNDPROC>(pImpl->m_pfnOldDlgProc), + hWnd,wMessage,wParam,lParam); + break; + + } // switch + + return lResult; +} + +//----------------------------------------------------------------- +// +//----------------------------------------------------------------- + +void SAL_CALL CWinFileOpenImpl::InitControlLabel(HWND hWnd) +{ + //----------------------------------------- + // set the labels for all extendet controls + //----------------------------------------- + + sal_Int16 aCtrlId = sal::static_int_cast< sal_Int16 >(GetDlgCtrlID(hWnd)); + rtl::OUString aLabel = m_ResProvider.getResString(aCtrlId); + if (aLabel.getLength()) + setLabel(aCtrlId, aLabel); +} + +//----------------------------------------------------------------- +// There may be problems with the layout of our custom controls, +// so that they are not aligned with the standard controls of the +// FileOpen dialog. +// We use a simple algorithm to move the custom controls to their +// proper position and resize them. +// Our approach is to align all static text controls with the +// static text control "File name" of the FileOpen dialog, +// all checkboxes and all list/comboboxes will be left aligned with +// the standard combobox edt1 (defined in MS platform sdk dlgs.h) +// and all push buttons will be left aligned with the standard +// "OK" button +//----------------------------------------------------------------- + +void SAL_CALL CWinFileOpenImpl::InitCustomControlContainer(HWND hCustomControl) +{ + m_CustomControls->AddControl( + m_CustomControlFactory->CreateCustomControl(hCustomControl,m_hwndFileOpenDlg)); +} + +//----------------------------------------------------------------- +// +//----------------------------------------------------------------- + +void SAL_CALL CWinFileOpenImpl::CacheControlState(HWND hWnd) +{ + OSL_ASSERT(m_FilePickerState && m_NonExecuteFilePickerState); + m_ExecuteFilePickerState->cacheControlState(hWnd, m_NonExecuteFilePickerState); +} + +//----------------------------------------------------------------- +// +//----------------------------------------------------------------- + +BOOL CALLBACK CWinFileOpenImpl::EnumChildWndProc(HWND hWnd, LPARAM lParam) +{ + EnumParam* enumParam = (EnumParam*)lParam; + CWinFileOpenImpl* pImpl = enumParam->m_instance; + + OSL_ASSERT(pImpl); + + BOOL bRet = TRUE; + + switch(enumParam->m_action) + { + case INIT_CUSTOM_CONTROLS: + pImpl->InitControlLabel(hWnd); + pImpl->InitCustomControlContainer(hWnd); + break; + + case CACHE_CONTROL_VALUES: + pImpl->CacheControlState(hWnd); + break; + + default: + // should not end here + OSL_ASSERT(sal_False); + } + + return bRet; +} + +//----------------------------------------------------------------- +// +//----------------------------------------------------------------- + +sal_uInt32 SAL_CALL CWinFileOpenImpl::onFileOk() +{ + m_NonExecuteFilePickerState->reset(); + + EnumParam enumParam(CACHE_CONTROL_VALUES,this); + + EnumChildWindows( + m_hwndFileOpenDlgChild, + CWinFileOpenImpl::EnumChildWndProc, + (LPARAM)&enumParam); + + return 0; +} + +//----------------------------------------------------------------- +// +//----------------------------------------------------------------- + +void SAL_CALL CWinFileOpenImpl::onSelChanged(HWND) +{ + // the windows file open dialog sends an initial + // SelChanged message after the InitDone message + // when the dialog is about to be opened + // if the lpstrFile buffer of the OPENFILENAME is + // empty (zero length string) the windows file open + // dialog sends a WM_SETTEXT message with an empty + // string to the file name edit line + // this would overwritte our text when we would set + // the default name in onInitDone, so we have to + // remeber that this is the first SelChanged message + // and set the default name here to overwrite the + // windows setting + InitialSetDefaultName(); + + FilePickerEvent evt; + m_FilePicker->fileSelectionChanged(evt); +} + +// #i40865# The size of the standard labels 'File name' +// and 'File type' is to short in some cases when the +// label will be changed (e.g. in the Brazil version). +// We just make sure that the labels are using the maximum +// available space. +void CWinFileOpenImpl::EnlargeStdControlLabels() const +{ + HWND hFilterBoxLabel = GetDlgItem(m_hwndFileOpenDlg, stc2); + HWND hFileNameBoxLabel = GetDlgItem(m_hwndFileOpenDlg, stc3); + HWND hFileNameBox = GetDlgItem(m_hwndFileOpenDlg, cmb13); + if (!hFileNameBox) + hFileNameBox = GetDlgItem(m_hwndFileOpenDlg, edt1); // under Win98 it is edt1 instead of cmb13 + + HWND hFilterBox = GetDlgItem(m_hwndFileOpenDlg, cmb1); + HWND hOkButton = GetDlgItem(m_hwndFileOpenDlg, IDOK); + + // Move filter and file name box nearer to OK and Cancel button + RECT rcOkButton; + GetWindowRect(hOkButton, &rcOkButton); + + const int MAX_GAP = IsWindows98() ? 5 : 10; + const int OFFSET = IsWindows98() ? 10 : 0; + + RECT rcFileNameBox; + GetWindowRect(hFileNameBox, &rcFileNameBox); + int w = rcFileNameBox.right - rcFileNameBox.left; + int h = rcFileNameBox.bottom - rcFileNameBox.top; + + int gap = rcOkButton.left - rcFileNameBox.right; + gap = (gap > MAX_GAP) ? gap - MAX_GAP : gap; + + ScreenToClient(m_hwndFileOpenDlg, (LPPOINT)&rcFileNameBox); + MoveWindow(hFileNameBox, rcFileNameBox.left + gap + OFFSET, rcFileNameBox.top, w - OFFSET, h, true); + + RECT rcFilterBox; + GetWindowRect(hFilterBox, &rcFilterBox); + w = rcFilterBox.right - rcFilterBox.left; + h = rcFilterBox.bottom - rcFilterBox.top; + ScreenToClient(m_hwndFileOpenDlg, (LPPOINT)&rcFilterBox); + MoveWindow(hFilterBox, rcFilterBox.left + gap + OFFSET, rcFilterBox.top, w - OFFSET, h, true); + + // get the new window rect + GetWindowRect(hFileNameBox, &rcFileNameBox); + + RECT rcFilterBoxLabel; + GetWindowRect(hFilterBoxLabel, &rcFilterBoxLabel); + int offset = rcFileNameBox.left - rcFilterBoxLabel.right - 1; + + w = rcFilterBoxLabel.right - rcFilterBoxLabel.left + offset; + h = rcFilterBoxLabel.bottom - rcFilterBoxLabel.top; + ScreenToClient(m_hwndFileOpenDlg, (LPPOINT)&rcFilterBoxLabel); + MoveWindow(hFilterBoxLabel, rcFilterBoxLabel.left, rcFilterBoxLabel.top, w, h, true); + + RECT rcFileNameBoxLabel; + GetWindowRect(hFileNameBoxLabel, &rcFileNameBoxLabel); + w = rcFileNameBoxLabel.right - rcFileNameBoxLabel.left + offset; + h = rcFileNameBoxLabel.bottom - rcFileNameBoxLabel.top; + ScreenToClient(m_hwndFileOpenDlg, (LPPOINT)&rcFileNameBoxLabel); + MoveWindow(hFileNameBoxLabel, rcFileNameBoxLabel.left, rcFileNameBoxLabel.top, w, h, true); +} + +void SAL_CALL CWinFileOpenImpl::onInitDone() +{ + m_Preview->setParent(m_hwndFileOpenDlg); + + // but now we have a valid parent handle + m_HelpPopupWindow.setParent(m_hwndFileOpenDlg); + + EnlargeStdControlLabels(); + + // #99826 + // Set the online filepicker state before initializing + // the control labels from the resource else we are + // overriding the offline settings + m_ExecuteFilePickerState->setHwnd(m_hwndFileOpenDlgChild); + + m_FilePickerState = m_ExecuteFilePickerState; + + // initialize controls from cache + + EnumParam enumParam(INIT_CUSTOM_CONTROLS,this); + + EnumChildWindows( + m_hwndFileOpenDlgChild, + CWinFileOpenImpl::EnumChildWndProc, + (LPARAM)&enumParam); + + m_ExecuteFilePickerState->initFilePickerControls( + m_NonExecuteFilePickerState->getControlCommand()); + + SetDefaultExtension(); + + m_CustomControls->Align(); + + m_CustomControls->SetFont( + reinterpret_cast<HFONT>(SendMessage(m_hwndFileOpenDlg, WM_GETFONT, 0, 0))); + + // resume event notification that was + // defered in onInitDialog + m_FilePicker->resumeEventNotification(); + + //#105996 let vcl know that now a system window is active + PostMessage( + HWND_BROADCAST, + RegisterWindowMessage(TEXT("SYSTEM_WINDOW_ACTIVATED")), + 0, + 0); + + // call the parent function to center the + // dialog to it's parent + CFileOpenDialog::onInitDone(); +} + +//----------------------------------------------------------------- +// +//----------------------------------------------------------------- + +void SAL_CALL CWinFileOpenImpl::onFolderChanged() +{ + FilePickerEvent evt; + m_FilePicker->directoryChanged(evt); +} + +//----------------------------------------------------------------- +// +//----------------------------------------------------------------- + +void SAL_CALL CWinFileOpenImpl::onTypeChanged(sal_uInt32) +{ + SetDefaultExtension(); + + FilePickerEvent evt; + evt.ElementId = LISTBOX_FILTER; + m_FilePicker->controlStateChanged(evt); +} + +//----------------------------------------------------------------------------------------- +// onMessageCommand handler +//----------------------------------------------------------------------------------------- + +sal_uInt32 SAL_CALL CWinFileOpenImpl::onCtrlCommand( + HWND, sal_uInt16 ctrlId, sal_uInt16) +{ + SetDefaultExtension(); + + if (ctrlId < ctlFirst) + { + FilePickerEvent evt; + evt.ElementId = ctrlId; + m_FilePicker->controlStateChanged(evt); + } + + return 0; +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void CWinFileOpenImpl::onWMSize() +{ + m_Preview->notifyParentSizeChanged(); + m_CustomControls->Align(); + m_FilePicker->dialogSizeChanged(); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void CWinFileOpenImpl::onWMShow(BOOL bShow) +{ + m_Preview->notifyParentShow(bShow); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void CWinFileOpenImpl::onWMWindowPosChanged() +{ + m_Preview->notifyParentWindowPosChanged(); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void CWinFileOpenImpl::onCustomControlHelpRequest(LPHELPINFO lphi) +{ + FilePickerEvent evt; + evt.ElementId = sal::static_int_cast< sal_Int16 >(lphi->iCtrlId); + + rtl::OUString aPopupHelpText = m_FilePicker->helpRequested(evt); + + if (aPopupHelpText.getLength()) + { + m_HelpPopupWindow.setText(aPopupHelpText); + + DWORD dwMsgPos = GetMessagePos(); + m_HelpPopupWindow.show(LOWORD(dwMsgPos),HIWORD(dwMsgPos)); + } +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL CWinFileOpenImpl::onInitDialog(HWND hwndDlg) +{ + // subclass the dialog window + m_pfnOldDlgProc = + reinterpret_cast<WNDPROC>( + SetWindowLong( hwndDlg, GWL_WNDPROC, + reinterpret_cast<LONG>(SubClassFunc))); +} + +//----------------------------------------------------------------------------------------- +// processing before showing the dialog +//----------------------------------------------------------------------------------------- + +bool SAL_CALL CWinFileOpenImpl::preModal() +{ + CFileOpenDialog::setFilter( + makeWinFilterBuffer(*m_filterContainer.get())); + + return true; +} + +//----------------------------------------------------------------------------------------- +// processing after showing the dialog +//----------------------------------------------------------------------------------------- + +void CWinFileOpenImpl::postModal(sal_Int16 nDialogResult) +{ + CFileOpenDialog::postModal(nDialogResult); + + // empty the container in order to get rid off + // invalid controls in case someone calls execute + // twice in sequence with the same instance + m_CustomControls->RemoveAllControls(); + + m_FilePickerState = m_NonExecuteFilePickerState; +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL CWinFileOpenImpl::SetDefaultExtension() +{ + HWND hwndChkSaveWithExt = GetDlgItem(m_hwndFileOpenDlgChild, 100); + + if (hwndChkSaveWithExt) + { + uno::Any aAny = CheckboxGetState(hwndChkSaveWithExt); + sal_Bool bChecked = *reinterpret_cast<const sal_Bool*>(aAny.getValue()); + + if (bChecked) + { + sal_uInt32 nIndex = getSelectedFilterIndex(); + + rtl::OUString currentFilter; + if (nIndex > 0) + { + // filter index of the base class starts with 1 + m_filterContainer->getFilter(nIndex - 1, currentFilter); + + if (currentFilter.getLength()) + { + rtl::OUString FilterExt; + m_filterContainer->getFilter(currentFilter, FilterExt); + + sal_Int32 posOfPoint = FilterExt.indexOf(L'.'); + const sal_Unicode* pFirstExtStart = FilterExt.getStr() + posOfPoint + 1; + + sal_Int32 posOfSemiColon = FilterExt.indexOf(L';') - 1; + if (posOfSemiColon < 0) + posOfSemiColon = FilterExt.getLength() - 1; + + FilterExt = rtl::OUString(pFirstExtStart, posOfSemiColon - posOfPoint); + + SendMessage(m_hwndFileOpenDlg, CDM_SETDEFEXT, 0, reinterpret_cast<LPARAM>(FilterExt.getStr())); + } + } + } + else + { + SendMessage(m_hwndFileOpenDlg, CDM_SETDEFEXT, 0, reinterpret_cast<LPARAM>(TEXT(""))); + } + } + + // !!! HACK !!! +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL CWinFileOpenImpl::InitialSetDefaultName() +{ + // manually setting the file name that appears + // initially in the file-name-box of the file + // open dialog (reason: see above setDefaultName) + if (m_bInitialSelChanged && m_defaultName.getLength()) + { + sal_Int32 edt1Id = edt1; + + // under W2k the there is a combobox instead + // of an edit field for the file name edit field + // the control id of this box is cmb13 and not + // edt1 as before so we must use this id + if (IsWindows2000Platform()) + edt1Id = cmb13; + + HWND hwndEdt1 = GetDlgItem(m_hwndFileOpenDlg, edt1Id); + SetWindowText(hwndEdt1, reinterpret_cast<LPCTSTR>(m_defaultName.getStr())); + } + + m_bInitialSelChanged = sal_False; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/WinFileOpenImpl.hxx b/fpicker/source/win32/filepicker/WinFileOpenImpl.hxx new file mode 100644 index 000000000000..e20fbf58ff1a --- /dev/null +++ b/fpicker/source/win32/filepicker/WinFileOpenImpl.hxx @@ -0,0 +1,235 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _WINFILEOPENIMPL_HXX_ +#define _WINFILEOPENIMPL_HXX_ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp> +#include <com/sun/star/ui/dialogs/FilePickerEvent.hpp> +#include <com/sun/star/ui/dialogs/XFilterGroupManager.hpp> +#include "FilterContainer.hxx" +#include "FileOpenDlg.hxx" +#include "previewadapter.hxx" +#include "helppopupwindow.hxx" +#include "customcontrol.hxx" +#include "customcontrolfactory.hxx" +#include "..\misc\resourceprovider.hxx" + +#include <utility> +#include <memory> +#include <vector> +#include <osl/conditn.hxx> + +//------------------------------------------------------------------------ +// deklarations +//------------------------------------------------------------------------ + +// forward declaration +class CFilePicker; +class CFilePickerState; +class CExecuteFilePickerState; +class CNonExecuteFilePickerState; + +class CWinFileOpenImpl : public CFileOpenDialog +{ +public: + CWinFileOpenImpl( + CFilePicker* aFilePicker, + sal_Bool bFileOpenDialog = sal_True, + sal_uInt32 dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + sal_uInt32 dwTemplateId = 0, + HINSTANCE hInstance = 0 ); + + virtual ~CWinFileOpenImpl( ); + + //----------------------------------------------------------------------------------------- + // XExecutableDialog + //----------------------------------------------------------------------------------------- + + virtual sal_Int16 SAL_CALL execute( ) throw( ::com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------------------------------------------- + // XFilePicker + //----------------------------------------------------------------------------------------- + + virtual void SAL_CALL setDefaultName( const ::rtl::OUString& aName ) + throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getFiles( ) + throw(::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setDisplayDirectory( const ::rtl::OUString& aDirectory ) + throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + + virtual ::rtl::OUString SAL_CALL getDisplayDirectory( ) throw ( ::com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------------------------------------------- + // XFilterManager + //----------------------------------------------------------------------------------------- + + virtual void SAL_CALL appendFilter( const ::rtl::OUString& aTitle, const ::rtl::OUString& aFilter ) + throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setCurrentFilter( const ::rtl::OUString& aTitle ) + throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + + virtual ::rtl::OUString SAL_CALL getCurrentFilter( ) + throw( ::com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------------------------------------------- + // XFilterGroupManager + //----------------------------------------------------------------------------------------- + + virtual void SAL_CALL appendFilterGroup( const ::rtl::OUString& sGroupTitle, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::StringPair >& aFilters ) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + //----------------------------------------------------------------------------------------- + // XFilePickerControlAccess + //----------------------------------------------------------------------------------------- + + virtual void SAL_CALL setValue( sal_Int16 aControlId, sal_Int16 aControlAction, const ::com::sun::star::uno::Any& aValue ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual ::com::sun::star::uno::Any SAL_CALL getValue( sal_Int16 aControlId, sal_Int16 aControlAction ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL enableControl( sal_Int16 aControlId, sal_Bool bEnable ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setLabel( sal_Int16 aControlId, const ::rtl::OUString& aLabel ) + throw (::com::sun::star::uno::RuntimeException); + + virtual ::rtl::OUString SAL_CALL getLabel( sal_Int16 aControlId ) + throw ( ::com::sun::star::uno::RuntimeException); + + //------------------------------------------------ + // XFilePreview + //------------------------------------------------ + + virtual ::com::sun::star::uno::Sequence< sal_Int16 > SAL_CALL getSupportedImageFormats( ) + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL getTargetColorDepth( ) + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL getAvailableWidth( ) + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL getAvailableHeight( ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL setImage( sal_Int16 aImageFormat, const ::com::sun::star::uno::Any& aImage ) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL setShowState( sal_Bool bShowState ) + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL getShowState( ) + throw (::com::sun::star::uno::RuntimeException); + + //------------------------------------------------ + // XCancelable + //------------------------------------------------ + + virtual void SAL_CALL cancel( ); + + //------------------------------------------------ + // Implementation details + //------------------------------------------------ + +protected: + sal_Int16 SAL_CALL getFocused( ); + + virtual bool SAL_CALL preModal( ); + virtual void SAL_CALL postModal( sal_Int16 nDialogResult ); + + virtual sal_uInt32 SAL_CALL onFileOk(); + virtual void SAL_CALL onSelChanged( HWND hwndListBox ); + + // only called back if OFN_EXPLORER is set + virtual void SAL_CALL onInitDone(); + virtual void SAL_CALL onFolderChanged(); + virtual void SAL_CALL onTypeChanged( sal_uInt32 nFilterIndex ); + + // call base class method first when overloading + virtual void SAL_CALL onInitDialog( HWND hwndDlg ); + + virtual sal_uInt32 SAL_CALL onCtrlCommand( HWND hwndDlg, sal_uInt16 ctrlId, sal_uInt16 notifyCode ); + + + void onWMSize(); + void onWMShow(BOOL bShow); + void onWMWindowPosChanged(); + void onCustomControlHelpRequest(LPHELPINFO lphi); + +private: + inline void SAL_CALL appendFilterGroupSeparator( ); + + inline sal_Bool SAL_CALL IsCustomControlHelpRequested(LPHELPINFO lphi) const; + + void EnlargeStdControlLabels() const; + + // initialize all controls from cache + void SAL_CALL InitControlLabel( HWND hWnd ); + void SAL_CALL InitCustomControlContainer(HWND hCustomControl); + + // save the control state + void SAL_CALL CacheControlState(HWND hWnd); + + void SAL_CALL SetDefaultExtension(); + void SAL_CALL InitialSetDefaultName(); + + static LRESULT CALLBACK SubClassFunc(HWND hWnd, UINT wMessage, WPARAM wParam, LPARAM lParam); + + static BOOL CALLBACK EnumChildWndProc( HWND hWnd, LPARAM lParam ); + +private: + std::auto_ptr<CFilterContainer> m_filterContainer; + std::auto_ptr<CPreviewAdapter> m_Preview; + std::auto_ptr<CCustomControlFactory> m_CustomControlFactory; + std::auto_ptr<CCustomControl> m_CustomControls; + CFilePicker* m_FilePicker; + WNDPROC m_pfnOldDlgProc; + rtl::OUString m_defaultName; + sal_Bool m_bInitialSelChanged; + CHelpPopupWindow m_HelpPopupWindow; + CFilePickerState* m_FilePickerState; + CExecuteFilePickerState* m_ExecuteFilePickerState; + CNonExecuteFilePickerState* m_NonExecuteFilePickerState; + CResourceProvider m_ResProvider; +}; + + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/afxres.h b/fpicker/source/win32/filepicker/afxres.h new file mode 100644 index 000000000000..61f5ab91ce4c --- /dev/null +++ b/fpicker/source/win32/filepicker/afxres.h @@ -0,0 +1,5 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#include <windows.h> +#include <dlgs.h> + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/asynceventnotifier.cxx b/fpicker/source/win32/filepicker/asynceventnotifier.cxx new file mode 100644 index 000000000000..02805f007a8e --- /dev/null +++ b/fpicker/source/win32/filepicker/asynceventnotifier.cxx @@ -0,0 +1,330 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ +#include <osl/diagnose.h> +#include "asynceventnotifier.hxx" +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerListener.hpp> + +#include <process.h> +#include <memory> +#include "SolarMutex.hxx" + +//------------------------------------------------ +// +//------------------------------------------------ + +using namespace com::sun::star; +using ::com::sun::star::ui::dialogs::XFilePickerListener; + +//------------------------------------------------ +// +//------------------------------------------------ + +CAsyncEventNotifier::CAsyncEventNotifier(cppu::OBroadcastHelper& rBroadcastHelper) : + m_hThread(0), + m_bRun(false), + m_ThreadId(0), + m_rBroadcastHelper(rBroadcastHelper), + m_NotifyEvent(m_hEvents[0]), + m_ResumeNotifying(m_hEvents[1]) +{ + // m_NotifyEvent + m_hEvents[0] = CreateEvent(0, /* no security */ + true, /* manual reset */ + false, /* initial state not signaled */ + 0); /* automatic name */ + + // m_ResumeNotifying + m_hEvents[1] = CreateEvent(0, /* no security */ + true, /* manual reset */ + false, /* initial state not signaled */ + 0); /* automatic name */ +} + +//------------------------------------------------ +// +//------------------------------------------------ + +CAsyncEventNotifier::~CAsyncEventNotifier() +{ + OSL_ENSURE(0 == m_hThread,"Thread not stopped, destroying this instance leads to desaster"); + + CloseHandle(m_hEvents[0]); + CloseHandle(m_hEvents[1]); +} + +//------------------------------------------------ +// +//------------------------------------------------ + +void SAL_CALL CAsyncEventNotifier::addListener(const uno::Type& aType , + const uno::Reference< uno::XInterface >& xListener) +{ + if ( m_rBroadcastHelper.bDisposed ) + throw lang::DisposedException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "FilePicker is already disposed" )), + uno::Reference< uno::XInterface >() ); + + if ( m_rBroadcastHelper.bInDispose ) + throw lang::DisposedException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "FilePicker will be disposed now." )), + uno::Reference< uno::XInterface >() ); + + m_rBroadcastHelper.aLC.addInterface( aType, xListener ); +} + +//------------------------------------------------ +// +//------------------------------------------------ + +void SAL_CALL CAsyncEventNotifier::removeListener(const uno::Type& aType , + const uno::Reference< uno::XInterface >& xListener) +{ + if ( m_rBroadcastHelper.bDisposed ) + throw lang::DisposedException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "FilePicker is already disposed." )), + uno::Reference< uno::XInterface >() ); + + m_rBroadcastHelper.aLC.removeInterface( aType, xListener ); +} + +//------------------------------------------------ +// +//------------------------------------------------ + +bool SAL_CALL CAsyncEventNotifier::startup(bool bCreateSuspended) +{ + osl::MutexGuard aGuard(m_Mutex); + + // m_bRun may already be false because of a + // call to stop but the thread did not yet + // terminate so m_hEventNotifierThread is + // yet a valid thread handle that should + // not be overwritten + if (!m_bRun) + { + if (!bCreateSuspended) + SetEvent(m_ResumeNotifying); + + m_hThread = (HANDLE)_beginthreadex( + NULL, 0, CAsyncEventNotifier::ThreadProc, this, 0, &m_ThreadId); + + OSL_ASSERT(0 != m_hThread); + + if (m_hThread) + m_bRun = true; + } + + OSL_POSTCOND(m_bRun,"Could not start event notifier!"); + + return m_bRun; +} + +//------------------------------------------------ +// +//------------------------------------------------ + +void SAL_CALL CAsyncEventNotifier::shutdown() +{ + unsigned nThreadId = GetCurrentThreadId(); + + OSL_PRECOND(nThreadId != m_ThreadId, "Method called in wrong thread context!"); + + osl::ResettableMutexGuard aGuard(m_Mutex); + + OSL_PRECOND(m_bRun,"Event notifier does not run!"); + + m_bRun = false; + m_EventList.clear(); + + // awake the the notifier thread + SetEvent(m_ResumeNotifying); + SetEvent(m_NotifyEvent); + + // releas the mutex here because the event + // notifier thread may need it to finish + aGuard.clear(); + + // we are waiting infinite, so error will + // be better detected in form of deadlocks + if (WaitForSingleObject(m_hThread, INFINITE) == WAIT_FAILED) { + OSL_ENSURE(false, "Waiting for thread termination failed!"); + } + + // lock mutex again to reset m_hThread + // and prevent a race with start() + aGuard.reset(); + + CloseHandle(m_hThread); + m_hThread = 0; +} + +//------------------------------------------------ +// +//------------------------------------------------ + +void CAsyncEventNotifier::suspend() +{ + ResetEvent(m_ResumeNotifying); +} + +//------------------------------------------------ +// +//------------------------------------------------ + +void CAsyncEventNotifier::resume() +{ + SetEvent(m_ResumeNotifying); +} + +//------------------------------------------------ +// +//------------------------------------------------ + +void SAL_CALL CAsyncEventNotifier::notifyEvent(CEventNotification* EventNotification) +{ + osl::MutexGuard aGuard(m_Mutex); + + OSL_ENSURE(m_bRun,"Event notifier is not running!"); + + if (m_bRun) + { + m_EventList.push_back(EventNotification); + SetEvent(m_NotifyEvent); + } +} + +//------------------------------------------------ +// +//------------------------------------------------ + +size_t SAL_CALL CAsyncEventNotifier::getEventListSize() +{ + osl::MutexGuard aGuard(m_Mutex); + return m_EventList.size(); +} + +//------------------------------------------------ +// +//------------------------------------------------ + +void SAL_CALL CAsyncEventNotifier::resetNotifyEvent() +{ + osl::MutexGuard aGuard(m_Mutex); + if (0 == m_EventList.size()) + ResetEvent(m_NotifyEvent); +} + +//------------------------------------------------ +// +//------------------------------------------------ + +CEventNotification* SAL_CALL CAsyncEventNotifier::getNextEventRecord() +{ + osl::MutexGuard aGuard(m_Mutex); + return m_EventList.front(); +} + +//------------------------------------------------ +// +//------------------------------------------------ + +void SAL_CALL CAsyncEventNotifier::removeNextEventRecord() +{ + osl::MutexGuard aGuard(m_Mutex); + m_EventList.pop_front(); +} + +//------------------------------------------------ +// +//------------------------------------------------ + +void SAL_CALL CAsyncEventNotifier::run() +{ + while (m_bRun) + { + WaitForMultipleObjects(2, m_hEvents, true, INFINITE); + + if (m_bRun) + { + while (getEventListSize() > 0) + { + std::auto_ptr<CEventNotification> EventNotification(getNextEventRecord()); + removeNextEventRecord(); + + ::cppu::OInterfaceContainerHelper* pICHelper = + m_rBroadcastHelper.getContainer(getCppuType((uno::Reference<XFilePickerListener>*)0)); + + if (pICHelper) + { + ::cppu::OInterfaceIteratorHelper iter(*pICHelper); + + while(iter.hasMoreElements()) + { + try + { + EventNotification->notifyEventListener(iter.next()); + } + catch(uno::RuntimeException&) + { + OSL_ENSURE(sal_False,"RuntimeException during event dispatching"); + } + } + } + + } // while(getEventListSize() > 0) + + resetNotifyEvent(); + + } // if (m_bRun) + + } // while(m_bRun) +} + +//------------------------------------------------ +// +//------------------------------------------------ + +unsigned int WINAPI CAsyncEventNotifier::ThreadProc(LPVOID pParam) +{ + CAsyncEventNotifier* pInst = reinterpret_cast< CAsyncEventNotifier* >(pParam); + OSL_ASSERT(pInst); + + pInst->run(); + + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/asynceventnotifier.hxx b/fpicker/source/win32/filepicker/asynceventnotifier.hxx new file mode 100644 index 000000000000..d7fd8ea0cefb --- /dev/null +++ b/fpicker/source/win32/filepicker/asynceventnotifier.hxx @@ -0,0 +1,112 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _ASYNCEVENTNOTIFIER_HXX_ +#define _ASYNCEVENTNOTIFIER_HXX_ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <osl/mutex.hxx> +#include <osl/conditn.hxx> +#include <cppuhelper/interfacecontainer.h> + +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#include <list> +#include <utility> +#include "eventnotification.hxx" + +//--------------------------------------------- +// +//--------------------------------------------- + +class CAsyncEventNotifier +{ +public: + CAsyncEventNotifier(cppu::OBroadcastHelper& rBroadcastHelper); + ~CAsyncEventNotifier(); + + bool SAL_CALL startup(bool bCreateSuspended = true); + void SAL_CALL shutdown(); + + // notifications may be added the + // the event queue but will only + // be notified to the clients after + // resume was called + void suspend(); + + // resume notifying events + void resume(); + + // this class is responsible for the memory management of + // the CEventNotification instance + void SAL_CALL notifyEvent(CEventNotification* EventNotification); + + void SAL_CALL addListener (const ::com::sun::star::uno::Type& aType , + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& xListener); + void SAL_CALL removeListener(const ::com::sun::star::uno::Type& aType , + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& xListener); + +private: + size_t SAL_CALL getEventListSize(); + void SAL_CALL resetNotifyEvent(); + CEventNotification* SAL_CALL getNextEventRecord(); + void SAL_CALL removeNextEventRecord(); + + void SAL_CALL run( ); + + static unsigned int WINAPI ThreadProc(LPVOID pParam); + +private: + std::list<CEventNotification*> m_EventList; + HANDLE m_hThread; + bool m_bRun; + unsigned m_ThreadId; + ::cppu::OBroadcastHelper& m_rBroadcastHelper; + HANDLE m_hEvents[2]; + HANDLE& m_NotifyEvent; + HANDLE& m_ResumeNotifying; + osl::Mutex m_Mutex; + +// prevent copy and assignment +private: + CAsyncEventNotifier( const CAsyncEventNotifier& ); + CAsyncEventNotifier& operator=( const CAsyncEventNotifier& ); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/asyncrequests.cxx b/fpicker/source/win32/filepicker/asyncrequests.cxx new file mode 100644 index 000000000000..7dcf6dac9a0f --- /dev/null +++ b/fpicker/source/win32/filepicker/asyncrequests.cxx @@ -0,0 +1,231 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "asyncrequests.hxx" +#include <vcl/svapp.hxx> +#include <osl/mutex.hxx> + +//----------------------------------------------------------------------------- +// namespace +//----------------------------------------------------------------------------- + +namespace fpicker{ +namespace win32{ +namespace vista{ + +namespace css = ::com::sun::star; + +//----------------------------------------------------------------------------- +void lcl_sleep(::osl::Condition& aCondition , + ::sal_Int32 nMilliSeconds) +{ + ULONG nAcquireCount = Application::ReleaseSolarMutex(); + + if (nMilliSeconds < 1) + aCondition.wait(0); + else + { + TimeValue aTime; + aTime.Seconds = (nMilliSeconds / 1000); + aTime.Nanosec = (nMilliSeconds % 1000) * 1000000; + aCondition.wait(&aTime); + } + + Application::AcquireSolarMutex( nAcquireCount ); +} + +//----------------------------------------------------------------------------- +void Request::wait(::sal_Int32 nMilliSeconds) +{ + lcl_sleep(m_aJoiner, nMilliSeconds); +} + +void Request::waitProcessMessages() +{ + SolarMutexGuard aGuard; + while (!m_aJoiner.check()) + Application::Yield(); +} + +//----------------------------------------------------------------------------- +void Request::notify() +{ + m_aJoiner.set(); +} + +//----------------------------------------------------------------------------- +AsyncRequests::AsyncRequests(const RequestHandlerRef& rHandler) + : ::cppu::BaseMutex( ) + , ::osl::Thread ( ) + , m_bFinish (sal_False) + , m_rHandler (rHandler ) + , m_lRequests ( ) +{ +} + +//----------------------------------------------------------------------------- +AsyncRequests::~AsyncRequests() +{ + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + m_bFinish = sal_True; + aLock.clear(); + // <- SYNCHRONIZED + + join(); +} + +void AsyncRequests::triggerRequestProcessMessages (const RequestRef& rRequest) +{ + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + m_lRequests.push(rRequest); + aLock.clear(); + // <- SYNCHRONIZED + + if ( ! isRunning()) + create(); + + rRequest->waitProcessMessages(); +} + +//----------------------------------------------------------------------------- +void AsyncRequests::triggerRequestBlocked(const RequestRef& rRequest) +{ + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + m_lRequests.push(rRequest); + aLock.clear(); + // <- SYNCHRONIZED + + if ( ! isRunning()) + create(); + + rRequest->wait(Request::WAIT_INFINITE); +} + +//----------------------------------------------------------------------------- +void AsyncRequests::triggerRequestNonBlocked(const RequestRef& rRequest) +{ + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + m_lRequests.push(rRequest); + aLock.clear(); + // <- SYNCHRONIZED + + if ( ! isRunning()) + create(); +} + +//----------------------------------------------------------------------------- +void AsyncRequests::triggerRequestDirectly(const RequestRef& rRequest) +{ + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + RequestHandlerRef rHandler = m_rHandler; + aLock.clear(); + // <- SYNCHRONIZED + + if (rHandler != NULL) + rHandler->doRequest(rRequest); +} + +//----------------------------------------------------------------------------- +void AsyncRequests::triggerRequestThreadAware(const RequestRef& rRequest, + ::sal_Int16 nWait ) +{ + oslThreadIdentifier nOurThreadId = getIdentifier(); + oslThreadIdentifier nCallerThreadId = ::osl::Thread::getCurrentIdentifier(); + if (nOurThreadId == nCallerThreadId) + triggerRequestDirectly(rRequest); + else if (nWait == BLOCKED) + triggerRequestBlocked(rRequest); + else if (nWait == PROCESS_MESSAGES) + triggerRequestProcessMessages(rRequest); + else + triggerRequestNonBlocked(rRequest); +} + +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +void SAL_CALL AsyncRequests::run() +{ + static const ::sal_Int32 TIME_TO_WAIT_FOR_NEW_REQUESTS = 250; + + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + RequestHandlerRef rHandler = m_rHandler; + ::sal_Bool bFinished = m_bFinish; + aLock.clear(); + // <- SYNCHRONIZED + + if (rHandler != NULL) + rHandler->before(); + + ::osl::Condition aWait; + + while ( ! bFinished) + { + // SYNCHRONIZED -> + aLock.reset(); + + RequestRef rRequest; + if ( ! m_lRequests.empty()) + { + rRequest = m_lRequests.front(); + m_lRequests.pop(); + } + bFinished = m_bFinish; + + aLock.clear(); + // <- SYNCHRONIZED + + if (rRequest == NULL) + { + lcl_sleep(aWait, TIME_TO_WAIT_FOR_NEW_REQUESTS); + continue; + } + + if (rHandler != NULL) + { + rHandler->doRequest(rRequest); + rRequest->notify(); + } + } + + if (rHandler != NULL) + rHandler->after(); +} + +} // namespace vista +} // namespace win32 +} // namespace fpicker + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/asyncrequests.hxx b/fpicker/source/win32/filepicker/asyncrequests.hxx new file mode 100644 index 000000000000..ba9b07eae995 --- /dev/null +++ b/fpicker/source/win32/filepicker/asyncrequests.hxx @@ -0,0 +1,230 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FPICKER_WIN32_VISTA_ASYNCREQUESTS_HXX +#define FPICKER_WIN32_VISTA_ASYNCREQUESTS_HXX + +//----------------------------------------------------------------------------- +// includes +//----------------------------------------------------------------------------- + +#include <cppuhelper/basemutex.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <osl/conditn.hxx> +#include <osl/thread.hxx> +#include <osl/time.h> +#include <queue> +#include <boost/shared_ptr.hpp> + +//----------------------------------------------------------------------------- +// namespace +//----------------------------------------------------------------------------- + +#ifdef css + #error "Clash on using CSS as namespace define." +#else + #define css ::com::sun::star +#endif + +namespace fpicker{ +namespace win32{ +namespace vista{ + +//----------------------------------------------------------------------------- +/** @todo document me + */ +class Request +{ + //------------------------------------------------------------------------- + public: + + static const ::sal_Int32 WAIT_INFINITE = 0; + + //------------------------------------------------------------------------- + // interface + //------------------------------------------------------------------------- + + public: + + //--------------------------------------------------------------------- + explicit Request() + : m_aJoiner ( ) + , m_nRequest (-1) + , m_lArguments( ) + { + m_aJoiner.reset(); + } + + //--------------------------------------------------------------------- + virtual ~Request() {}; + + //--------------------------------------------------------------------- + void setRequest(::sal_Int32 nRequest) + { + m_nRequest = nRequest; + } + + //--------------------------------------------------------------------- + ::sal_Int32 getRequest() + { + return m_nRequest; + } + + //--------------------------------------------------------------------- + void clearArguments() + { + m_lArguments.clear(); + } + + //--------------------------------------------------------------------- + template< class TArgumentType > + void setArgument(const ::rtl::OUString& sName , + const TArgumentType& aValue) + { + m_lArguments[sName] <<= aValue; + } + + //--------------------------------------------------------------------- + template< class TArgumentType > + TArgumentType getArgumentOrDefault(const ::rtl::OUString& sName , + const TArgumentType& aDefault) + { + return m_lArguments.getUnpackedValueOrDefault(sName, aDefault); + } + + //--------------------------------------------------------------------- + void wait(::sal_Int32 nMilliSeconds = WAIT_INFINITE); + + void waitProcessMessages(); + + //--------------------------------------------------------------------- + void notify(); + + //------------------------------------------------------------------------- + // member + //------------------------------------------------------------------------- + + private: + + ::osl::Condition m_aJoiner; + ::sal_Int32 m_nRequest; + ::comphelper::SequenceAsHashMap m_lArguments; +}; + +typedef ::boost::shared_ptr< Request > RequestRef; +typedef ::std::queue< RequestRef > RequestQueue; + +//----------------------------------------------------------------------------- +class RequestHandler +{ + public: + virtual void before() = 0; + virtual void doRequest(const RequestRef& rRequest) = 0; + virtual void after() = 0; +}; + +typedef ::boost::shared_ptr< RequestHandler > RequestHandlerRef; + +//----------------------------------------------------------------------------- +/** @todo docuemnt me + */ +class AsyncRequests : private ::cppu::BaseMutex + , public ::osl::Thread +{ + public: + static const ::sal_Int16 PROCESS_MESSAGES = 2; + static const ::sal_Int16 BLOCKED = 1; + static const ::sal_Int16 NON_BLOCKED = 0; + + //--------------------------------------------------------------------- + /** creates the new asynchronous request executor. + */ + explicit AsyncRequests(const RequestHandlerRef& rHandler); + + void setHandler(const RequestHandlerRef& rHandler) + { + m_rHandler = rHandler; + } + + //--------------------------------------------------------------------- + /** does nothing special / excepting to make sure our class wont be inline .-) + */ + virtual ~AsyncRequests(); + + //--------------------------------------------------------------------- + /** @todo document me + */ + void triggerRequestProcessMessages (const RequestRef& rRequest); + + //--------------------------------------------------------------------- + /** @todo document me + */ + void triggerRequestBlocked(const RequestRef& rRequest); + + //--------------------------------------------------------------------- + /** @todo document me + */ + void triggerRequestNonBlocked(const RequestRef& rRequest); + + //--------------------------------------------------------------------- + /** @todo document me + */ + void triggerRequestDirectly(const RequestRef& rRequest); + + //--------------------------------------------------------------------- + /** @todo document me + */ + void triggerRequestThreadAware(const RequestRef& rRequest, + ::sal_Int16 nWait ); + + private: + + //--------------------------------------------------------------------- + /** our STA .-) + * Will run between start() & finish(). Internaly it runs a loop ... + * waiting for requests. Every request will be executed synchronously + * in blocked mode. + */ + virtual void SAL_CALL run(); + + private: + + ::sal_Bool m_bFinish; + RequestHandlerRef m_rHandler; + RequestQueue m_lRequests; +}; + +} // namespace vista +} // namespace win32 +} // namespace fpicker + +#undef css + +#endif // FPICKER_WIN32_VISTA_ASYNCREQUESTS_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/comptr.hxx b/fpicker/source/win32/filepicker/comptr.hxx new file mode 100644 index 000000000000..2eb4796921c2 --- /dev/null +++ b/fpicker/source/win32/filepicker/comptr.hxx @@ -0,0 +1,225 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef COMPTR_HXX +#define COMPTR_HXX + +#include <sal/types.h> +#include <osl/diagnose.h> +#include <shobjidl.h> + +template< class T_INTERFACE , + REFIID P_IID = IID_NULL , + REFCLSID P_CLSID = CLSID_NULL > +class ComPtr +{ + public: + + //--------------------------------------------------------------------- + /** initialize com ptr with null. + */ + ComPtr() + { + m_pInterface = NULL; + } + + //--------------------------------------------------------------------- + /** initialize com ptr with given interface. + */ + ComPtr(T_INTERFACE* pInterface) + { + m_pInterface = pInterface; + if (m_pInterface) + m_pInterface->AddRef(); + } + + //--------------------------------------------------------------------- + /** copy ctor. + */ + ComPtr(const ComPtr< T_INTERFACE, P_IID, P_CLSID >& aCopy) + { + m_pInterface = aCopy.m_pInterface; + if (m_pInterface) + m_pInterface->AddRef(); + } + + //--------------------------------------------------------------------- + /** initialize object by quering external object for the right interface. + */ + ComPtr(IUnknown* pIUnknown) + { + if (pIUnknown) + pIUnknown->QueryInterface(P_IID, (void**)&m_pInterface); + } + + //--------------------------------------------------------------------- + /** deinitialize com object right. + */ + ~ComPtr() + { + release(); + } + + public: + + //--------------------------------------------------------------------- + HRESULT create() + { + return CoCreateInstance(P_CLSID, NULL, CLSCTX_ALL, P_IID, (void**)&m_pInterface); + } + + //--------------------------------------------------------------------- + operator T_INTERFACE*() const + { + return m_pInterface; + } + + //--------------------------------------------------------------------- + T_INTERFACE& operator*() const + { + return *m_pInterface; + } + + //--------------------------------------------------------------------- + T_INTERFACE** operator&() + { + return &m_pInterface; + } + + //--------------------------------------------------------------------- + T_INTERFACE* operator->() const + { + return m_pInterface; + } + + //--------------------------------------------------------------------- + T_INTERFACE* operator=(T_INTERFACE* pInterface) + { + if ( equals(pInterface) ) + return m_pInterface; + + m_pInterface->Release(); + m_pInterface = pInterface; + if (m_pInterface) + m_pInterface->AddRef(); + + return m_pInterface; + } + + //--------------------------------------------------------------------- + T_INTERFACE* operator=(IUnknown* pIUnknown) + { + if (pIUnknown) + pIUnknown->QueryInterface(P_IID, (void**)&m_pInterface); + return m_pInterface; + } + + //--------------------------------------------------------------------- + T_INTERFACE* operator=(const ComPtr< T_INTERFACE, P_IID, P_CLSID >& aCopy) + { + m_pInterface = aCopy.m_pInterface; + if (m_pInterface) + m_pInterface->AddRef(); + + return m_pInterface; + } + + //--------------------------------------------------------------------- + T_INTERFACE* get() const + { + return m_pInterface; + } + + //--------------------------------------------------------------------- + void attach(T_INTERFACE* pInterface) + { + if (pInterface) + { + m_pInterface->Release(); + m_pInterface = pInterface; + } + } + + //--------------------------------------------------------------------- + T_INTERFACE* detach() + { + T_INTERFACE* pInterface = m_pInterface; + m_pInterface = NULL; + return pInterface; + } + + //--------------------------------------------------------------------- + void release() + { + if (m_pInterface) + { + m_pInterface->Release(); + m_pInterface = NULL; + } + } + +#ifndef __MINGW32__ + //--------------------------------------------------------------------- + template< class T_QUERYINTERFACE > + HRESULT query(T_QUERYINTERFACE** pQuery) + { + return m_pInterface->QueryInterface(__uuidof(T_QUERYINTERFACE), (void**)pQuery); + } +#endif + + //--------------------------------------------------------------------- + ::sal_Bool equals(IUnknown* pCheck) + { + if ( + ( ! m_pInterface ) && + ( ! pCheck ) + ) + return sal_True; + + IUnknown* pCurrent = NULL; + m_pInterface->QueryInterface(IID_IUnknown, (void**)&pCurrent); + + ::sal_Bool bEquals = (pCheck == pCurrent); + pCurrent->Release(); + + return bEquals; + } + + //--------------------------------------------------------------------- + ::sal_Bool is() + { + return (m_pInterface != 0); + } + + private: + T_INTERFACE* m_pInterface; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/controlaccess.cxx b/fpicker/source/win32/filepicker/controlaccess.cxx new file mode 100644 index 000000000000..8831d017f82d --- /dev/null +++ b/fpicker/source/win32/filepicker/controlaccess.cxx @@ -0,0 +1,264 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <tchar.h> +#include <sal/macros.h> +#include <osl/diagnose.h> +#include "controlaccess.hxx" +#include "..\misc\WinImplHelper.hxx" + +//------------------------------------------------------------ +// we are using a table based algorithm to dispatch control +// actions there is one table containing one action table for +// each control class and one action table per control class +// which contains function pointer to control action functions +//------------------------------------------------------------ + +//------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------ + +using rtl::OUString; + +namespace // private +{ + + //------------------------------------------------------------ + // table setup + //------------------------------------------------------------ + + CTRL_SETVALUE_FUNCTION_T CheckboxSetValueFunctionTable[] = + { + CheckboxSetState + }; + const size_t SIZE_CHECKBOX_SETVALUE_FUNCTION_TABLE = + sizeof( CheckboxSetValueFunctionTable ) / sizeof( CTRL_SETVALUE_FUNCTION_T ); + + CTRL_GETVALUE_FUNCTION_T CheckboxGetValueFunctionTable[] = + { + CheckboxGetState + }; + const size_t SIZE_CHECKBOX_GETVALUE_FUNCTION_TABLE = + sizeof( CheckboxGetValueFunctionTable ) / sizeof( CTRL_GETVALUE_FUNCTION_T ); + + CTRL_SETVALUE_FUNCTION_T ListboxSetValueFunctionTable[] = + { + NULL, + ListboxAddItem, + ListboxAddItems, + ListboxDeleteItem, + ListboxDeleteItems, + ListboxSetSelectedItem + }; + const size_t SIZE_LISTBOX_SETVALUE_FUNCTION_TABLE = + sizeof( ListboxSetValueFunctionTable ) / sizeof( CTRL_SETVALUE_FUNCTION_T ); + + CTRL_GETVALUE_FUNCTION_T ListboxGetValueFunctionTable[] = + { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + ListboxGetItems, + ListboxGetSelectedItem, + ListboxGetSelectedItemIndex + }; + const size_t SIZE_LISTBOX_GETVALUE_ACTION_TABLE = + sizeof( ListboxGetValueFunctionTable ) / sizeof( CTRL_GETVALUE_FUNCTION_T ); + + struct _ENTRY + { + LPVOID lpFunctionTable; + size_t TableSize; + }; + + // an array of function tables, one for each control class + _ENTRY CtrlClassSetValueFunctionTable[] = + { + { NULL, 0 }, + { CheckboxSetValueFunctionTable, SIZE_CHECKBOX_SETVALUE_FUNCTION_TABLE }, + { ListboxSetValueFunctionTable, SIZE_LISTBOX_SETVALUE_FUNCTION_TABLE }, + { NULL, 0 } + }; + + // an array of function tables, one for each control class + _ENTRY CtrlClassGetValueFunctionTable[] = + { + { NULL, 0 }, + { CheckboxGetValueFunctionTable, SIZE_CHECKBOX_GETVALUE_FUNCTION_TABLE }, + { ListboxGetValueFunctionTable, SIZE_LISTBOX_GETVALUE_ACTION_TABLE }, + { NULL, 0 } + }; + + //------------------------------------------------------------ + // + //------------------------------------------------------------ + + CTRL_SETVALUE_FUNCTION_T SAL_CALL GetCtrlSetValueFunction( + CTRL_SETVALUE_FUNCTION_T* aCtrlSetValueFunctionTable, size_t aTableSize, sal_Int16 aCtrlAction ) + { + if ( !aCtrlSetValueFunctionTable || + aCtrlAction < 0 + || sal::static_int_cast< sal_uInt16 >(aCtrlAction) >= aTableSize ) + return NULL; + + return aCtrlSetValueFunctionTable[aCtrlAction]; + } + + //------------------------------------------------------------ + // + //------------------------------------------------------------ + + CTRL_GETVALUE_FUNCTION_T SAL_CALL GetCtrlGetValueFunction( + CTRL_GETVALUE_FUNCTION_T* aCtrlGetValueFunctionTable, size_t aTableSize, sal_Int16 aCtrlAction ) + { + if ( !aCtrlGetValueFunctionTable || + aCtrlAction < 0 || + sal::static_int_cast< sal_uInt16 >(aCtrlAction) >= aTableSize ) + return NULL; + + return aCtrlGetValueFunctionTable[aCtrlAction]; + } + + //------------------------------------------------------------ + // + //------------------------------------------------------------ + + inline + _ENTRY SAL_CALL GetCtrlClassSetValueFunctionTable( CTRL_CLASS aCtrlClass ) + { + return CtrlClassSetValueFunctionTable[aCtrlClass]; + } + + //------------------------------------------------------------ + // + //------------------------------------------------------------ + + inline + _ENTRY SAL_CALL GetCtrlClassGetValueFunctionTable( CTRL_CLASS aCtrlClass ) + { + return CtrlClassGetValueFunctionTable[aCtrlClass]; + } + + int WindowsFileOpenCtrlIds[] = + { + 0, + IDOK, // PUSHBUTTON_OK + IDCANCEL, // PUSHBUTTON_CANCEL + cmb1, // LISTBOX_FILTER + 0, // CONTROL_FILEVIEW + 0, // not available in system file picker + stc2, // LISTBOX_FILTER_LABEL + stc3 // LISTBOX_FILE_NAME_LABEL + }; + const int SIZE_WINDOWS_FILEOPEN_CTRL_IDS = SAL_N_ELEMENTS(WindowsFileOpenCtrlIds); + +}; // end namespace + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +CTRL_SETVALUE_FUNCTION_T SAL_CALL GetCtrlSetValueFunction( CTRL_CLASS aCtrlClass, sal_Int16 aCtrlAction ) +{ + _ENTRY aEntry = + GetCtrlClassSetValueFunctionTable( aCtrlClass ); + + return GetCtrlSetValueFunction( + reinterpret_cast< CTRL_SETVALUE_FUNCTION_T* >( aEntry.lpFunctionTable ), + aEntry.TableSize, + aCtrlAction ); +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +CTRL_GETVALUE_FUNCTION_T SAL_CALL GetCtrlGetValueFunction( CTRL_CLASS aCtrlClass, sal_Int16 aCtrlAction ) +{ + _ENTRY aEntry = + GetCtrlClassGetValueFunctionTable( aCtrlClass ); + + return GetCtrlGetValueFunction( + reinterpret_cast< CTRL_GETVALUE_FUNCTION_T* >( aEntry.lpFunctionTable ), + aEntry.TableSize, + aCtrlAction ); +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +CTRL_CLASS SAL_CALL GetCtrlClass( HWND hwndCtrl ) +{ + CTRL_CLASS aCtrlClass = UNKNOWN; + TCHAR aClassName[256]; + + int nRet = GetClassName(hwndCtrl,aClassName,(sizeof(aClassName)/sizeof(TCHAR))); + if (nRet) + { + if (0 == _tcsicmp(aClassName,TEXT("button"))) + { + // button means many things so we have + // to find out what button it is + LONG lBtnStyle = GetWindowLong(hwndCtrl,GWL_STYLE); + if (lBtnStyle & BS_CHECKBOX) + aCtrlClass = CHECKBOX; + else if (((lBtnStyle & BS_PUSHBUTTON) == 0) || (lBtnStyle & BS_DEFPUSHBUTTON)) + aCtrlClass = PUSHBUTTON; + } + else if (0 == _tcsicmp(aClassName,TEXT("listbox")) || + 0 == _tcsicmp(aClassName,TEXT("combobox"))) + aCtrlClass = LISTBOX; + } + + return aCtrlClass; +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +int SAL_CALL CommonFilePickerCtrlIdToWinFileOpenCtrlId( sal_Int16 aControlId ) +{ + if ( aControlId < 0 || aControlId > SIZE_WINDOWS_FILEOPEN_CTRL_IDS ) + return aControlId; + + return WindowsFileOpenCtrlIds[aControlId]; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/controlaccess.hxx b/fpicker/source/win32/filepicker/controlaccess.hxx new file mode 100644 index 000000000000..d62819286b52 --- /dev/null +++ b/fpicker/source/win32/filepicker/controlaccess.hxx @@ -0,0 +1,83 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _CONTROLACCESS_HXX_ +#define _CONTROLACCESS_HXX_ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <sal/types.h> +#include <rtl/ustring.hxx> + +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif +#include <com/sun/star/uno/Any.hxx> + +//------------------------------------------------------------------------ +// deklarations +//------------------------------------------------------------------------ + +typedef void ( SAL_CALL *CTRL_SETVALUE_FUNCTION_T)( HWND, const ::com::sun::star::uno::Any&, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >&, sal_Int16 ); +typedef ::com::sun::star::uno::Any ( SAL_CALL *CTRL_GETVALUE_FUNCTION_T )( HWND ); + +// the currently supported control classes +enum CTRL_CLASS +{ + UNKNOWN = 0, + CHECKBOX, + LISTBOX, + PUSHBUTTON +}; + +// returns the class of a control +CTRL_CLASS SAL_CALL GetCtrlClass( HWND hwndCtrl ); + +// returns a pointer to a setValue function based on the control class +// and the control action, if no function was found NULL will be returned +CTRL_SETVALUE_FUNCTION_T SAL_CALL GetCtrlSetValueFunction( CTRL_CLASS aCtrlClass, sal_Int16 aCtrlAction ); + +// returns a pointer to a getValue function based on the control class +// and the control action, if no function was found NULL will be returned +CTRL_GETVALUE_FUNCTION_T SAL_CALL GetCtrlGetValueFunction( CTRL_CLASS aCtrlClass, sal_Int16 aCtrlAction ); + +// translates a CommonFilePickerElementId as defined in CommonFilePickerElementIds.idl +// to a control id that is valid for the FileOpen dialog under windows as defined +// in dlgs.h in the Windows Platform SDK +int SAL_CALL CommonFilePickerCtrlIdToWinFileOpenCtrlId( sal_Int16 aControlId ); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/controlcommand.cxx b/fpicker/source/win32/filepicker/controlcommand.cxx new file mode 100644 index 000000000000..464d7c72df3f --- /dev/null +++ b/fpicker/source/win32/filepicker/controlcommand.cxx @@ -0,0 +1,285 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ +#include "controlcommand.hxx" +#include "controlcommandrequest.hxx" +#include "controlcommandresult.hxx" +#include "filepickerstate.hxx" + +//--------------------------------------------- +// +//--------------------------------------------- + +CControlCommand::CControlCommand( sal_Int16 aControlId ) : + m_NextCommand( NULL ), + m_aControlId( aControlId ) +{ +} + +//--------------------------------------------- +// +//--------------------------------------------- + +CControlCommand::~CControlCommand( ) +{ +} + +//--------------------------------------------- +// +//--------------------------------------------- + +CControlCommandResult* SAL_CALL CControlCommand::handleRequest( CControlCommandRequest* pRequest ) +{ + // if the command does not support handleRequest, it should at least + // redirect the request to the next element + // so the base class implementation has to do it + + OSL_ENSURE( pRequest, "inavlid parameter" ); + + CControlCommandResult* result; + CControlCommand* nextCommand; + + nextCommand = getNextCommand( ); + if ( nextCommand ) + { + result = nextCommand->handleRequest( pRequest ); + } + else + { + result = new CControlCommandResult(); + } + + return result; +} + +//--------------------------------------------- +// +//--------------------------------------------- + +CControlCommand* SAL_CALL CControlCommand::getNextCommand( ) const +{ + return m_NextCommand; +} + +//--------------------------------------------- +// +//--------------------------------------------- + +void SAL_CALL CControlCommand::setNextCommand( CControlCommand* nextCommand ) +{ + m_NextCommand = nextCommand; +} + +//--------------------------------------------- +// +//--------------------------------------------- + +sal_Int16 SAL_CALL CControlCommand::getControlId( ) const +{ + return m_aControlId; +} + + +//--------------------------------------------- +// +//--------------------------------------------- + +CValueControlCommand::CValueControlCommand( + sal_Int16 aControlId, + sal_Int16 aControlAction, + const ::com::sun::star::uno::Any& aValue ) : + CControlCommand( aControlId ), + m_aControlAction( aControlAction ), + m_aValue( aValue ) +{ +} + +//--------------------------------------------- +// +//--------------------------------------------- + +void SAL_CALL CValueControlCommand::exec( CFilePickerState* aFilePickerState ) +{ + OSL_ENSURE( aFilePickerState, "empty reference" ); + + aFilePickerState->setValue( + getControlId( ), + m_aControlAction, + m_aValue ); +} + +//--------------------------------------------- +// +//--------------------------------------------- + +CControlCommandResult* SAL_CALL CValueControlCommand::handleRequest( CControlCommandRequest* aRequest ) +{ + CValueControlCommandRequest* value_request = + dynamic_cast< CValueControlCommandRequest* >( aRequest ); + + CControlCommandResult* result; + CControlCommand* nextCommand; + + if ( value_request && + (value_request->getControlId( ) == getControlId( )) && + (value_request->getControlAction( ) == m_aControlAction) ) + { + result = new CValueCommandResult( sal_True, m_aValue ); + } + else + { + nextCommand = getNextCommand( ); + if ( nextCommand ) + { + result = nextCommand->handleRequest( aRequest ); + } + else + { + result = new CControlCommandResult( ); + } + } + + return result; +} + +//--------------------------------------------- +// +//--------------------------------------------- + +sal_Int16 SAL_CALL CValueControlCommand::getControlAction( ) const +{ + return m_aControlAction; +} + +//--------------------------------------------- +// +//--------------------------------------------- + +::com::sun::star::uno::Any SAL_CALL CValueControlCommand::getValue( ) const +{ + return m_aValue; +} + + +//--------------------------------------------- +// +//--------------------------------------------- + +CLabelControlCommand::CLabelControlCommand( + sal_Int16 aControlId, + const rtl::OUString& aLabel ) : + CControlCommand( aControlId ), + m_aLabel( aLabel ) +{ +} + +//--------------------------------------------- +// +//--------------------------------------------- + +void SAL_CALL CLabelControlCommand::exec( CFilePickerState* aFilePickerState ) +{ + OSL_ENSURE( aFilePickerState, "empty reference" ); + + aFilePickerState->setLabel( getControlId( ), m_aLabel ); +} + +//--------------------------------------------- +// +//--------------------------------------------- + +CControlCommandResult* SAL_CALL CLabelControlCommand::handleRequest( CControlCommandRequest* aRequest ) +{ + OSL_ENSURE( aRequest, "inavlid parameter" ); + + CControlCommandResult* result; + CControlCommand* nextCommand; + + CValueControlCommandRequest* value_request = + dynamic_cast< CValueControlCommandRequest* >( aRequest ); + + if ( !value_request && + (aRequest->getControlId( ) == getControlId( )) ) + { + result = new CLabelCommandResult( sal_True, m_aLabel ); + } + else + { + nextCommand = getNextCommand( ); + if ( nextCommand ) + { + result = nextCommand->handleRequest( aRequest ); + } + else + { + result = new CControlCommandResult( ); + } + } + + return result; +} + +//--------------------------------------------- +// +//--------------------------------------------- + +rtl::OUString SAL_CALL CLabelControlCommand::getLabel( ) const +{ + return m_aLabel; +} + +//--------------------------------------------- +// +//--------------------------------------------- + +CEnableControlCommand::CEnableControlCommand( + sal_Int16 aControlId, + sal_Bool bEnable ) : + CControlCommand( aControlId ), + m_bEnable( bEnable ) +{ +} + +//--------------------------------------------- +// +//--------------------------------------------- + +void SAL_CALL CEnableControlCommand::exec( CFilePickerState* aFilePickerState ) +{ + OSL_ENSURE( aFilePickerState, "empty reference" ); + + aFilePickerState->enableControl( getControlId( ), m_bEnable ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/controlcommand.hxx b/fpicker/source/win32/filepicker/controlcommand.hxx new file mode 100644 index 000000000000..f44050cf8842 --- /dev/null +++ b/fpicker/source/win32/filepicker/controlcommand.hxx @@ -0,0 +1,146 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _CONTROLCOMMAND_HXX_ +#define _CONTROLCOMMAND_HXX_ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <sal/types.h> +#include <com/sun/star/uno/Any.hxx> +#include <rtl/ustring.hxx> + +//--------------------------------------------- +// +//--------------------------------------------- + +class CFilePickerState; +class CControlCommandRequest; +class CControlCommandResult; + +//--------------------------------------------- +// +//--------------------------------------------- + +class CControlCommand +{ +public: + CControlCommand( sal_Int16 aControlId ); + virtual ~CControlCommand( ); + + virtual void SAL_CALL exec( CFilePickerState* aFilePickerState ) = 0; + + // the client inherits the ownership of the returned + // CControlCommandResult and has to delete it or he may + // use the auto_ptr template for automatic deletion + virtual CControlCommandResult* SAL_CALL handleRequest( CControlCommandRequest* aRequest ); + + // clients of this method should use the returned + // pointer only temporary because it's not ref-counted + // and the ownerhsip belongs to this instance + CControlCommand* SAL_CALL getNextCommand( ) const; + + // transfers the ownership to this class + void SAL_CALL setNextCommand( CControlCommand* nextCommand ); + +protected: + sal_Int16 SAL_CALL getControlId( ) const; + +private: + CControlCommand* m_NextCommand; + sal_Int16 m_aControlId; +}; + +//--------------------------------------------- +// +//--------------------------------------------- + +class CValueControlCommand : public CControlCommand +{ +public: + CValueControlCommand( + sal_Int16 aControlId, + sal_Int16 aControlAction, + const ::com::sun::star::uno::Any& aValue ); + + virtual void SAL_CALL exec( CFilePickerState* aFilePickerState ); + + virtual CControlCommandResult* SAL_CALL handleRequest( CControlCommandRequest* aRequest ); + + sal_Int16 SAL_CALL getControlAction( ) const; + + ::com::sun::star::uno::Any SAL_CALL getValue( ) const; + +private: + sal_Int16 m_aControlAction; + ::com::sun::star::uno::Any m_aValue; +}; + +//--------------------------------------------- +// +//--------------------------------------------- + +class CLabelControlCommand : public CControlCommand +{ +public: + CLabelControlCommand( + sal_Int16 aControlId, + const rtl::OUString& aLabel ); + + virtual void SAL_CALL exec( CFilePickerState* aFilePickerState ); + + virtual CControlCommandResult* SAL_CALL handleRequest( CControlCommandRequest* aRequest ); + + rtl::OUString SAL_CALL getLabel( ) const; + +private: + rtl::OUString m_aLabel; +}; + +//--------------------------------------------- +// +//--------------------------------------------- + +class CEnableControlCommand : public CControlCommand +{ +public: + CEnableControlCommand( + sal_Int16 controlId, + sal_Bool bEnable ); + + virtual void SAL_CALL exec( CFilePickerState* aFilePickerState ); + +private: + sal_Bool m_bEnable; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/controlcommandrequest.hxx b/fpicker/source/win32/filepicker/controlcommandrequest.hxx new file mode 100644 index 000000000000..53c28c69ebfd --- /dev/null +++ b/fpicker/source/win32/filepicker/controlcommandrequest.hxx @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _CONTROLCOMMANDREQUEST_HXX_ +#define _CONTROLCOMMANDREQUEST_HXX_ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <sal/types.h> + +//--------------------------------------------- +// declaration +//--------------------------------------------- + +class CControlCommandRequest +{ +public: + CControlCommandRequest( sal_Int16 aControlId ) : + m_aControlId( aControlId ) + { + } + + virtual ~CControlCommandRequest( ) + { + } + + sal_Int16 SAL_CALL getControlId( ) const + { + return m_aControlId; + } + +private: + sal_Int16 m_aControlId; +}; + +//--------------------------------------------- +// +//--------------------------------------------- + +class CValueControlCommandRequest : public CControlCommandRequest +{ +public: + CValueControlCommandRequest( + sal_Int16 aControlId, + sal_Int16 aControlAction ) : + CControlCommandRequest( aControlId ), + m_aControlAction( aControlAction ) + { + } + + sal_Int16 SAL_CALL getControlAction( ) const + { + return m_aControlAction; + } + +private: + sal_Int16 m_aControlAction; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/controlcommandresult.hxx b/fpicker/source/win32/filepicker/controlcommandresult.hxx new file mode 100644 index 000000000000..99fc66d5bfe1 --- /dev/null +++ b/fpicker/source/win32/filepicker/controlcommandresult.hxx @@ -0,0 +1,111 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _CONTROLCOMMANDRESULT_HXX_ +#define _CONTROLCOMMANDRESULT_HXX_ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <sal/types.h> +#include <com/sun/star/uno/Any.hxx> +#include <rtl/ustring.hxx> + +//--------------------------------------------- +// declaration +//--------------------------------------------- + +class CControlCommandResult +{ +public: + CControlCommandResult( sal_Bool bResult = sal_False ) : + m_bResult( bResult ) + { + } + + virtual ~CControlCommandResult( ) + { + } + + sal_Bool SAL_CALL hasResult( ) const + { + return m_bResult; + } + +private: + sal_Bool m_bResult; +}; + +//--------------------------------------------- +// +//--------------------------------------------- + +class CValueCommandResult : public CControlCommandResult +{ +public: + CValueCommandResult( sal_Bool bResult, const ::com::sun::star::uno::Any& aValue ) : + CControlCommandResult( bResult ), + m_aValue( aValue ) + { + } + + ::com::sun::star::uno::Any SAL_CALL getValue( ) const + { + return m_aValue; + } + +private: + ::com::sun::star::uno::Any m_aValue; +}; + +//--------------------------------------------- +// +//--------------------------------------------- + +class CLabelCommandResult : public CControlCommandResult +{ +public: + CLabelCommandResult( sal_Bool bResult, const rtl::OUString& aLabel ) : + CControlCommandResult( bResult ), + m_aLabel( aLabel ) + { + } + + rtl::OUString SAL_CALL getLabel( ) const + { + return m_aLabel; + } + +private: + rtl::OUString m_aLabel; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/customcontrol.cxx b/fpicker/source/win32/filepicker/customcontrol.cxx new file mode 100644 index 000000000000..c7d78fa8b294 --- /dev/null +++ b/fpicker/source/win32/filepicker/customcontrol.cxx @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" +#include "customcontrol.hxx" + +//----------------------------------- +// +//----------------------------------- + +CCustomControl::~CCustomControl() +{ +} + +//----------------------------------- +// +//----------------------------------- + +void SAL_CALL CCustomControl::AddControl(CCustomControl*) +{ + // will be implemented by custom control containers +} + +//----------------------------------- +// +//----------------------------------- + +void SAL_CALL CCustomControl::RemoveControl(CCustomControl*) +{ + // will be implemented by custom control containers +} + +//----------------------------------- +// +//----------------------------------- + +void SAL_CALL CCustomControl::RemoveAllControls() +{ + // will be implemented by custom control containers +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/customcontrol.hxx b/fpicker/source/win32/filepicker/customcontrol.hxx new file mode 100644 index 000000000000..ea74c7c4710d --- /dev/null +++ b/fpicker/source/win32/filepicker/customcontrol.hxx @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _CUSTOMCONTROL_HXX_ +#define _CUSTOMCONTROL_HXX_ + +#include <sal/types.h> + +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +//----------------------------------- +// +//----------------------------------- + +class CCustomControl +{ +public: + virtual ~CCustomControl(); + + // align the control to a reference object/control + virtual void SAL_CALL Align() = 0; + + virtual void SAL_CALL SetFont(HFONT hFont) = 0; + + virtual void SAL_CALL AddControl(CCustomControl* aCustomControl); + virtual void SAL_CALL RemoveControl(CCustomControl* aCustomControl); + virtual void SAL_CALL RemoveAllControls(); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/customcontrolcontainer.cxx b/fpicker/source/win32/filepicker/customcontrolcontainer.cxx new file mode 100644 index 000000000000..24ea12111990 --- /dev/null +++ b/fpicker/source/win32/filepicker/customcontrolcontainer.cxx @@ -0,0 +1,146 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" +#include "customcontrolcontainer.hxx" + +#include <algorithm> +#include <functional> + +//----------------------------------- +// +//----------------------------------- + +namespace /* private */ +{ + void DeleteCustomControl(CCustomControl* aCustomControl) + { + delete aCustomControl; + }; + + void AlignCustomControl(CCustomControl* aCustomControl) + { + aCustomControl->Align(); + }; + + class CSetFontHelper + { + public: + CSetFontHelper(HFONT hFont) : + m_hFont(hFont) + { + } + + void SAL_CALL operator()(CCustomControl* aCustomControl) + { + aCustomControl->SetFont(m_hFont); + } + + private: + HFONT m_hFont; + }; +} + +//----------------------------------- +// +//----------------------------------- + +CCustomControlContainer::~CCustomControlContainer() +{ + RemoveAllControls(); +} + +//----------------------------------- +// +//----------------------------------- + +void SAL_CALL CCustomControlContainer::Align() +{ + std::for_each( + m_ControlContainer.begin(), + m_ControlContainer.end(), + AlignCustomControl); +} + +//----------------------------------- +// +//----------------------------------- + +void SAL_CALL CCustomControlContainer::SetFont(HFONT hFont) +{ + CSetFontHelper aSetFontHelper(hFont); + + std::for_each( + m_ControlContainer.begin(), + m_ControlContainer.end(), + aSetFontHelper); +} + +//----------------------------------- +// +//----------------------------------- + +void SAL_CALL CCustomControlContainer::AddControl(CCustomControl* aCustomControl) +{ + m_ControlContainer.push_back(aCustomControl); +} + +//----------------------------------- +// +//----------------------------------- + +void SAL_CALL CCustomControlContainer::RemoveControl(CCustomControl* aCustomControl) +{ + ControlContainer_t::iterator iter_end = m_ControlContainer.end(); + + ControlContainer_t::iterator iter = + std::find(m_ControlContainer.begin(),iter_end,aCustomControl); + + if (iter != iter_end) + { + delete *iter; + m_ControlContainer.remove(aCustomControl); + } +} + +//----------------------------------- +// +//----------------------------------- + +void SAL_CALL CCustomControlContainer::RemoveAllControls() +{ + std::for_each( + m_ControlContainer.begin(), + m_ControlContainer.end(), + DeleteCustomControl); + + m_ControlContainer.clear(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/customcontrolcontainer.hxx b/fpicker/source/win32/filepicker/customcontrolcontainer.hxx new file mode 100644 index 000000000000..dc63c8cb355f --- /dev/null +++ b/fpicker/source/win32/filepicker/customcontrolcontainer.hxx @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _CUSTOMCONTROLCONTAINER_HXX_ +#define _CUSTOMCONTROLCONTAINER_HXX_ + +#include "customcontrol.hxx" + +#include <list> + +//----------------------------------- +// A container for custom controls +// the container is resposible for +// the destruction of the custom +// controls +//----------------------------------- + +class CCustomControlContainer : public CCustomControl +{ +public: + virtual ~CCustomControlContainer(); + + virtual void SAL_CALL Align(); + virtual void SAL_CALL SetFont(HFONT hFont); + + virtual void SAL_CALL AddControl(CCustomControl* aCustomControl); + virtual void SAL_CALL RemoveControl(CCustomControl* aCustomControl); + virtual void SAL_CALL RemoveAllControls(); + +private: + typedef std::list<CCustomControl*> ControlContainer_t; + + ControlContainer_t m_ControlContainer; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/customcontrolfactory.cxx b/fpicker/source/win32/filepicker/customcontrolfactory.cxx new file mode 100644 index 000000000000..d21afa49a7c9 --- /dev/null +++ b/fpicker/source/win32/filepicker/customcontrolfactory.cxx @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +#include <tchar.h> +#include "customcontrolfactory.hxx" +#include "customcontrolcontainer.hxx" +#include "dialogcustomcontrols.hxx" +#include <osl/diagnose.h> + +//----------------------------------- +// +//----------------------------------- + +CCustomControl* CCustomControlFactory::CreateCustomControl(HWND aControlHandle, HWND aParentHandle) +{ + OSL_PRECOND(IsWindow(aControlHandle),"Invalid control handle"); + OSL_PRECOND(IsWindow(aControlHandle),"Invalid parent handle"); + + // get window class + // if static text create static text control etc. + + TCHAR aClsName[256]; + ZeroMemory(aClsName,sizeof(aClsName)); + if (GetClassName(aControlHandle,aClsName,sizeof(aClsName)) == 0) { + OSL_ENSURE(false,"Invalid window handle"); + } + + if (0 == _tcsicmp(aClsName,TEXT("button"))) + { + // button means many things so we have + // to find out what button it is + LONG lBtnStyle = GetWindowLong(aControlHandle,GWL_STYLE); + + if (lBtnStyle & BS_CHECKBOX) + return new CCheckboxCustomControl(aControlHandle,aParentHandle); + + if ( ((lBtnStyle & BS_PUSHBUTTON) == 0) || (lBtnStyle & BS_DEFPUSHBUTTON)) + return new CPushButtonCustomControl(aControlHandle,aParentHandle); + + return new CDummyCustomControl(aControlHandle,aParentHandle); + } + + if (0 == _tcsicmp(aClsName,TEXT("listbox")) || 0 == _tcsicmp(aClsName,TEXT("combobox"))) + return new CComboboxCustomControl(aControlHandle,aParentHandle); + + if (0 == _tcsicmp(aClsName,TEXT("static"))) + return new CStaticCustomControl(aControlHandle,aParentHandle); + + return new CDummyCustomControl(aControlHandle,aParentHandle); +} + +//----------------------------------- +// +//----------------------------------- + +CCustomControl* CCustomControlFactory::CreateCustomControlContainer() +{ + return new CCustomControlContainer(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/customcontrolfactory.hxx b/fpicker/source/win32/filepicker/customcontrolfactory.hxx new file mode 100644 index 000000000000..8222531f72e7 --- /dev/null +++ b/fpicker/source/win32/filepicker/customcontrolfactory.hxx @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _CUSTOMCONTROLFACTORY_HXX_ +#define _CUSTOMCONTROLFACTORY_HXX_ + +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +//----------------------------------- +// forward declaration +//----------------------------------- + +class CCustomControl; + +//----------------------------------- +// +//----------------------------------- + +class CCustomControlFactory +{ +public: + + // The CCustomControl instances will be created on the heap + // and the client is responsible for deleting this instances + // (he adopts ownership) + virtual CCustomControl* CreateCustomControl(HWND aControlHandle, HWND aParentHandle); + + virtual CCustomControl* CreateCustomControlContainer(); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/dialogcustomcontrols.cxx b/fpicker/source/win32/filepicker/dialogcustomcontrols.cxx new file mode 100644 index 000000000000..0be7a7e72b93 --- /dev/null +++ b/fpicker/source/win32/filepicker/dialogcustomcontrols.cxx @@ -0,0 +1,198 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +#ifndef _DIALOGCUSTOMCONTROLS_CXX_ +#include "dialogcustomcontrols.hxx" +#endif +#include <osl/diagnose.h> + +//----------------------------------- +// +//----------------------------------- + +CDialogCustomControlBase::CDialogCustomControlBase(HWND aControlHandle, HWND aParentHandle) : + m_CustomControlHandle(aControlHandle), + m_ParentHandle(aParentHandle) +{ +} + +//----------------------------------- +// +//----------------------------------- + +void SAL_CALL CDialogCustomControlBase::SetFont(HFONT hFont) +{ + SendMessage( + m_CustomControlHandle, + WM_SETFONT, + (WPARAM)hFont, + (LPARAM)TRUE); +} + +//----------------------------------- +// +//----------------------------------- + +void SAL_CALL CDialogCustomControlBase::AlignToBuddy(HWND aBuddyHandle) +{ + OSL_PRECOND(IsWindow(aBuddyHandle),"Invalid buddy window handle"); + + RECT rcBuddy; + GetWindowRect(aBuddyHandle,&rcBuddy); + + POINT pt = {rcBuddy.left,rcBuddy.top}; + ScreenToClient(m_ParentHandle,&pt); + + int cx_new = rcBuddy.right - rcBuddy.left; + int cy_new = rcBuddy.bottom - rcBuddy.top; + + // keep the vertical position because + // the Windows dialog controler does + // this job + RECT rcMe; + GetWindowRect(m_CustomControlHandle,&rcMe); + + POINT ptMe = {rcMe.left,rcMe.top}; + ScreenToClient(m_ParentHandle,&ptMe); + + SetWindowPos( + m_CustomControlHandle, + HWND_TOP, + pt.x, + ptMe.y, + cx_new, + cy_new, + SWP_NOACTIVATE); +} + +//----------------------------------- +// +//----------------------------------- + +CDummyCustomControl::CDummyCustomControl(HWND, HWND) +{ +} + +//----------------------------------- +// +//----------------------------------- + +void SAL_CALL CDummyCustomControl::Align() +{ + // do nothing +} + +//----------------------------------- +// +//----------------------------------- + +void SAL_CALL CDummyCustomControl::SetFont(HFONT) +{ + // do nothing +} + +//----------------------------------- +// +//----------------------------------- + +CStaticCustomControl::CStaticCustomControl(HWND aControlHandle, HWND aParentHandle) : + CDialogCustomControlBase(aControlHandle,aParentHandle) +{ +} + +//----------------------------------- +// Align to the "File name" static +// text of the standard FileOpen dlg +//----------------------------------- + +void SAL_CALL CStaticCustomControl::Align() +{ + AlignToBuddy(GetDlgItem(m_ParentHandle,stc3)); +} + +//----------------------------------- +// +//----------------------------------- + +CPushButtonCustomControl::CPushButtonCustomControl(HWND aControlHandle, HWND aParentHandle) : + CDialogCustomControlBase(aControlHandle,aParentHandle) +{ +} + +//----------------------------------- +// Align to the "OK" button of the +// standard FileOpen dlg +//----------------------------------- + +void SAL_CALL CPushButtonCustomControl::Align() +{ + AlignToBuddy(GetDlgItem(m_ParentHandle,IDCANCEL)); +} + +//----------------------------------- +// +//----------------------------------- + +CComboboxCustomControl::CComboboxCustomControl(HWND aControlHandle, HWND aParentHandle) : + CDialogCustomControlBase(aControlHandle,aParentHandle) +{ +} + +//----------------------------------- +// Align to the "File name" combobox +// of the standard FileOpen dlg +//----------------------------------- + +void SAL_CALL CComboboxCustomControl::Align() +{ + AlignToBuddy(GetDlgItem(m_ParentHandle,cmb1)); +} + +//----------------------------------- +// +//----------------------------------- + +CCheckboxCustomControl::CCheckboxCustomControl(HWND aControlHandle, HWND aParentHandle) : + CDialogCustomControlBase(aControlHandle,aParentHandle) +{ +} + +//----------------------------------- +// Align to the "File name" combobox +// of the standard FileOpen dlg +//----------------------------------- + +void SAL_CALL CCheckboxCustomControl::Align() +{ + AlignToBuddy(GetDlgItem(m_ParentHandle,cmb1)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/dialogcustomcontrols.hxx b/fpicker/source/win32/filepicker/dialogcustomcontrols.hxx new file mode 100644 index 000000000000..b7f64dc13ef2 --- /dev/null +++ b/fpicker/source/win32/filepicker/dialogcustomcontrols.hxx @@ -0,0 +1,126 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _DIALOGCUSTOMCONTROLS_HXX_ +#define _DIALOGCUSTOMCONTROLS_HXX_ + +#include "customcontrol.hxx" + +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +//----------------------------------- +// +//----------------------------------- + +class CDummyCustomControl : public CCustomControl +{ +public: + CDummyCustomControl(HWND aControlHandle, HWND aParentHandle); + + virtual void SAL_CALL Align(); + virtual void SAL_CALL SetFont(HFONT hFont); +}; + +//----------------------------------- +// +//----------------------------------- + +class CDialogCustomControlBase : public CCustomControl +{ +protected: + CDialogCustomControlBase(HWND aControlHandle, HWND aParentHandle); + + virtual void SAL_CALL SetFont(HFONT hFont); + + // aligns the specific control class to a reference + // buddy + // + void SAL_CALL AlignToBuddy(HWND aBuddyHandle); + +protected: + HWND m_CustomControlHandle; + HWND m_ParentHandle; +}; + +//----------------------------------- +// +//----------------------------------- + +class CStaticCustomControl : public CDialogCustomControlBase +{ +public: + CStaticCustomControl(HWND aControlHandle, HWND aParentHandle); + + virtual void SAL_CALL Align(); +}; + +//----------------------------------- +// +//----------------------------------- + +class CPushButtonCustomControl : public CDialogCustomControlBase +{ +public: + CPushButtonCustomControl(HWND aControlHandle, HWND aParentHandle); + + virtual void SAL_CALL Align(); +}; + +//----------------------------------- +// +//----------------------------------- + +class CComboboxCustomControl : public CDialogCustomControlBase +{ +public: + CComboboxCustomControl(HWND aControlHandle, HWND aParentHandle); + + virtual void SAL_CALL Align(); +}; + +//----------------------------------- +// +//----------------------------------- + +class CCheckboxCustomControl : public CDialogCustomControlBase +{ +public: + CCheckboxCustomControl(HWND aControlHandle, HWND aParentHandle); + + virtual void SAL_CALL Align(); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/dibpreview.cxx b/fpicker/source/win32/filepicker/dibpreview.cxx new file mode 100644 index 000000000000..2ba23b0fa38f --- /dev/null +++ b/fpicker/source/win32/filepicker/dibpreview.cxx @@ -0,0 +1,471 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <tchar.h> +#include "dibpreview.hxx" +#include <osl/diagnose.h> + +#include <com/sun/star/ui/dialogs/FilePreviewImageFormats.hpp> + +#include <rtl/ustring.hxx> + +#include <stdexcept> +#include <string> + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::RuntimeException; +using ::com::sun::star::uno::Any; +using ::com::sun::star::lang::IllegalArgumentException; +using rtl::OUString; + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +namespace /* private */ +{ + const LPTSTR CURRENT_INSTANCE = TEXT("CurrInst"); +}; + +//------------------------------------------------------------------------ +// defines +//------------------------------------------------------------------------ + +#define PREVIEWWND_CLASS_NAME TEXT("DIBPreviewWnd###") + +// means 3 pixel left and 3 pixel right +#define HORZ_BODER_SPACE 6 + +// means 3 pixel top and 3 pixel bottom +#define VERT_BORDER_SPACE 6 + +//--------------------------------------------------- +// static member initialization +//--------------------------------------------------- + +osl::Mutex CDIBPreview::s_Mutex; +ATOM CDIBPreview::s_ClassAtom = 0; +sal_Int32 CDIBPreview::s_RegisterDibPreviewWndCount = 0; + +//--------------------------------------------------- +// +//--------------------------------------------------- + +CDIBPreview::CDIBPreview(HINSTANCE instance,HWND parent,sal_Bool bShowWindow) : + m_Instance(instance) +{ + RegisterDibPreviewWindowClass(); + + DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; + + if (bShowWindow) + dwStyle |= WS_VISIBLE; + + m_Hwnd = CreateWindowEx( + WS_EX_CLIENTEDGE, + PREVIEWWND_CLASS_NAME, + TEXT(""), + dwStyle, + 0, 0, 0, 0, + parent, + (HMENU)0x0, // for child windows this will + // be used as child window identifier + m_Instance, + (LPVOID)this // pass a pointer to the current + // instance of this class + ); + + bool bSuccess = IsWindow(m_Hwnd); + + OSL_POSTCOND(bSuccess,"Coud not create preview window"); + + if (!bSuccess) + { + UnregisterDibPreviewWindowClass(); + throw std::runtime_error("Could not create preview window"); + } +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +CDIBPreview::~CDIBPreview( ) +{ + // remember: we don't have to destroy the + // preview window because it will be destroyed + // by it's parent window (the FileOpen dialog) + // but we have to unregister the window class + //if ( m_bWndClassRegistered ) + UnregisterDibPreviewWindowClass(); +} + +//------------------------------- +// +//------------------------------- + +sal_Int32 SAL_CALL CDIBPreview::getTargetColorDepth() throw (RuntimeException) +{ + HDC hdc = GetDC(m_Hwnd); + int clrRes = 0; + + if (hdc) + clrRes = GetDeviceCaps(hdc, COLORRES); + + return clrRes; +} + +//------------------------------- +// +//------------------------------- + +sal_Int32 SAL_CALL CDIBPreview::getAvailableWidth() throw (RuntimeException) +{ + RECT rect; + bool bRet = GetClientRect(m_Hwnd,&rect); + + sal_Int32 cx = 0; + + if ( bRet ) + cx = rect.right; + + return cx; +} + +//------------------------------- +// +//------------------------------- + +sal_Int32 SAL_CALL CDIBPreview::getAvailableHeight() throw (RuntimeException) +{ + RECT rect; + bool bRet = GetClientRect(m_Hwnd,&rect); + + sal_Int32 cy = 0; + + if ( bRet ) + cy = rect.bottom; + + return cy; +} + +//------------------------------- +// +//------------------------------- + +void SAL_CALL CDIBPreview::setImage(sal_Int16 aImageFormat, const Any& aImage) + throw (IllegalArgumentException, RuntimeException) +{ + PreviewBase::setImage(aImageFormat,aImage); + + // if the any has no value we have an + // empty Sequence which clears the + // preview window + osl::ClearableMutexGuard aGuard(m_PaintLock); + + m_Image.realloc(0); + m_ImageData >>= m_Image; + + aGuard.clear(); + + InvalidateRect(m_Hwnd,NULL,FALSE); + UpdateWindow(m_Hwnd); +} + +//------------------------------- +// +//------------------------------- + +sal_Bool SAL_CALL CDIBPreview::setShowState(sal_Bool bShowState) throw (RuntimeException) +{ + PreviewBase::setShowState(bShowState); + ShowWindow(m_Hwnd, m_bShowState ? SW_SHOW : SW_HIDE); + return sal_True; +} + +//------------------------------- +// +//------------------------------- + +sal_Bool SAL_CALL CDIBPreview::getShowState() throw (RuntimeException) +{ + return (sal_Bool)IsWindowVisible(m_Hwnd); +} + +//------------------------------- +// +//------------------------------- + +HWND SAL_CALL CDIBPreview::getWindowHandle() const +{ + return m_Hwnd; +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +void SAL_CALL CDIBPreview::onPaint(HWND hWnd, HDC hDC) +{ + BITMAPFILEHEADER* pbmfh; + BITMAPINFO * pbmi; + BYTE * pBits; + int cxDib; + int cyDib; + + osl::MutexGuard aGuard(m_PaintLock); + + try + { + pbmfh = reinterpret_cast<BITMAPFILEHEADER*>(m_Image.getArray()); + + if ( !IsBadReadPtr( pbmfh, sizeof(BITMAPFILEHEADER)) && + (pbmfh->bfType == ('B' | ('M' << 8))) ) + { + pbmi = reinterpret_cast<BITMAPINFO*>((pbmfh + 1)); + pBits = reinterpret_cast<BYTE*>(((DWORD)pbmfh) + pbmfh->bfOffBits); + + cxDib = pbmi->bmiHeader.biWidth; + cyDib = abs (pbmi->bmiHeader.biHeight); + + SetStretchBltMode(hDC, COLORONCOLOR); + + int nWidth = getAvailableWidth(); + int nHeight = getAvailableHeight(); + + int nX = abs(nWidth - cxDib) / 2; + int nY = abs(nHeight - cyDib) / 2; + + int GDIError = GDI_ERROR; + GDIError = StretchDIBits( + hDC, nX, nY, cxDib, cyDib, + 0, 0, cxDib, cyDib, pBits, pbmi, + DIB_RGB_COLORS, SRCCOPY); + + OSL_ASSERT(GDI_ERROR != GDIError); + + // paint the border + RECT rc; + + if (nY > 0) + { + // top + rc.left = 0; + rc.top = 0; + rc.right = nWidth; + rc.bottom = nY; + FillRect(hDC,&rc,(HBRUSH)(COLOR_INACTIVEBORDER + 1)); + + // bottom + rc.left = 0; + rc.top = nHeight - nY - 1; + rc.right = nWidth; + rc.bottom = nHeight; + FillRect(hDC,&rc,(HBRUSH)(COLOR_INACTIVEBORDER + 1)); + } + + if (nX > 0) + { + // left + rc.left = 0; + rc.top = nY; + rc.right = nX; + rc.bottom = nHeight - nY; + FillRect(hDC,&rc,(HBRUSH)(COLOR_INACTIVEBORDER + 1)); + + // right + rc.left = nWidth - nX - 1; + rc.top = nY; + rc.right = nWidth; + rc.bottom = nHeight - nY; + FillRect(hDC,&rc,(HBRUSH)(COLOR_INACTIVEBORDER + 1)); + } + } + else // clear background + { + RECT rc; + GetClientRect(hWnd,&rc); + FillRect(hDC,&rc,(HBRUSH)(COLOR_INACTIVEBORDER + 1)); + } + } + catch(...) + { + OSL_ASSERT(sal_False); + } +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +LRESULT CALLBACK CDIBPreview::WndProc( + HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + LRESULT lResult = 0; + + switch(uMsg) + { + + // we connect a pointer to the current instance + // with a window instance via SetProp + case WM_CREATE: + { + LPCREATESTRUCT lpcs = + reinterpret_cast< LPCREATESTRUCT >(lParam); + + OSL_ASSERT(lpcs->lpCreateParams); + + // connect the instance handle to the window + SetProp(hWnd, CURRENT_INSTANCE, lpcs->lpCreateParams); + } + break; + + // we remove the window property which connects + // a class instance with a window class + case WM_NCDESTROY: + { + // RemoveProp returns the saved value on success + if (reinterpret_cast<CDIBPreview*>( + RemoveProp(hWnd, CURRENT_INSTANCE)) == NULL) + { + OSL_ASSERT(false); + } + } + break; + + case WM_PAINT: + { + CDIBPreview* pImpl = reinterpret_cast<CDIBPreview*>( + GetProp(hWnd, CURRENT_INSTANCE)); + + OSL_ASSERT(pImpl); + + HDC hDC; + PAINTSTRUCT ps; + + hDC = BeginPaint(hWnd,&ps); + pImpl->onPaint(hWnd,hDC); + EndPaint(hWnd,&ps); + } + break; + + // ignore this message in order to + // avoid flickering during paint + case WM_ERASEBKGND: + lResult = 1; + break; + + default: + return DefWindowProc(hWnd, uMsg, wParam, lParam); + } + + return lResult; +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +ATOM SAL_CALL CDIBPreview::RegisterDibPreviewWindowClass() +{ + osl::MutexGuard aGuard( s_Mutex ); + + if (0 == s_ClassAtom) + { + // register the preview window class + WNDCLASSEX wndClsEx; + ZeroMemory(&wndClsEx, sizeof(wndClsEx)); + + wndClsEx.cbSize = sizeof(wndClsEx); + wndClsEx.style = CS_HREDRAW | CS_VREDRAW; + wndClsEx.lpfnWndProc = CDIBPreview::WndProc; + wndClsEx.hInstance = m_Instance; + wndClsEx.hbrBackground = (HBRUSH)(COLOR_INACTIVEBORDER + 1); + wndClsEx.lpszClassName = PREVIEWWND_CLASS_NAME; + + // register the preview window class + // !!! Win95 - the window class will be unregistered automaticly + // if the dll is unloaded + // Win2000 - the window class must be unregistered manually + // if the dll is unloaded + s_ClassAtom = RegisterClassEx(&wndClsEx); + + OSL_POSTCOND(s_ClassAtom,"Could not register preview window class"); + + if (0 == s_ClassAtom) + throw std::runtime_error("Preview window class could not be registered"); + } + + // increment the register class counter + // so that we keep track of the number + // of class registrations + //if ( 0 != s_ClassAtom ) + s_RegisterDibPreviewWndCount++; + + return s_ClassAtom; +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +void SAL_CALL CDIBPreview::UnregisterDibPreviewWindowClass() +{ + osl::MutexGuard aGuard( s_Mutex ); + + OSL_ASSERT( ( (0 != s_ClassAtom) && (s_RegisterDibPreviewWndCount > 0)) || + ( (0 == s_ClassAtom) && (0 == s_RegisterDibPreviewWndCount) ) ); + + // update the register class counter + // and unregister the window class if + // counter drops to zero + if (0 != s_ClassAtom) + { + s_RegisterDibPreviewWndCount--; + OSL_ASSERT(s_RegisterDibPreviewWndCount >= 0); + } + + if (0 == s_RegisterDibPreviewWndCount) + { + UnregisterClass((LPCTSTR)MAKELONG(s_ClassAtom,0),m_Instance); + s_ClassAtom = 0; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/dibpreview.hxx b/fpicker/source/win32/filepicker/dibpreview.hxx new file mode 100644 index 000000000000..2269fce065c7 --- /dev/null +++ b/fpicker/source/win32/filepicker/dibpreview.hxx @@ -0,0 +1,119 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _DIBPREVIEW_HXX_ +#define _DIBPREVIEW_HXX_ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include "previewbase.hxx" +#include <osl/mutex.hxx> + +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +//--------------------------------------------- +// A very simple wrapper for a window that does +// display DIBs. +// Maybe it would be better and more extensible +// to create another class that is responsible +// for rendering a specific image format into +// the area of the window, but for our purpose +// it's enough to go the simple way - KISS. +//--------------------------------------------- + +class CDIBPreview : public PreviewBase +{ +public: + + // ctor + CDIBPreview(HINSTANCE instance,HWND parent,sal_Bool bShowWindow = sal_False); + + // dtor + virtual ~CDIBPreview( ); + + // preview interface implementation + + virtual sal_Int32 SAL_CALL getTargetColorDepth() + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL getAvailableWidth() + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL getAvailableHeight() + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL setImage(sal_Int16 aImageFormat, const ::com::sun::star::uno::Any& aImage) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL setShowState(sal_Bool bShowState) + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL getShowState() + throw (::com::sun::star::uno::RuntimeException); + + virtual HWND SAL_CALL getWindowHandle() const; + +private: + virtual void SAL_CALL onPaint( HWND hWnd, HDC hDC ); + + ATOM SAL_CALL RegisterDibPreviewWindowClass( ); + void SAL_CALL UnregisterDibPreviewWindowClass( ); + + static LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); + +private: + HINSTANCE m_Instance; + HWND m_Hwnd; + com::sun::star::uno::Sequence<sal_Int8> m_Image; + osl::Mutex m_PaintLock; + + // the preview window class has to be registered only + // once per process, so multiple instance of this class + // share the registered window class + static ATOM s_ClassAtom; + static osl::Mutex s_Mutex; + static sal_Int32 s_RegisterDibPreviewWndCount; + +// prevent copy and assignment +private: + CDIBPreview(const CDIBPreview&); + CDIBPreview& operator=(const CDIBPreview&); +}; + + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/eventnotification.hxx b/fpicker/source/win32/filepicker/eventnotification.hxx new file mode 100644 index 000000000000..3866ca59946f --- /dev/null +++ b/fpicker/source/win32/filepicker/eventnotification.hxx @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _EVENTNOTIFICATION_HXX_ +#define _EVENTNOTIFICATION_HXX_ + +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/uno/Reference.hxx> + +//----------------------------------- +// encapsulate a filepicker event +// notification, because there are +// two types of filepicker notifications +// with and without parameter +// this is an application of the +// "command" pattern see GoF +//----------------------------------- + +class CEventNotification +{ +public: + virtual ~CEventNotification() { }; + + virtual void SAL_CALL notifyEventListener( com::sun::star::uno::Reference< com::sun::star::uno::XInterface > xListener ) = 0; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/filepickereventnotification.cxx b/fpicker/source/win32/filepicker/filepickereventnotification.cxx new file mode 100644 index 000000000000..13001fdcd81a --- /dev/null +++ b/fpicker/source/win32/filepicker/filepickereventnotification.cxx @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" +#include "filepickereventnotification.hxx" +#include <sal/types.h> + +//----------------------------------- +// namespace directives +//----------------------------------- + +using namespace com::sun::star::uno; +using namespace com::sun::star::ui::dialogs; + +//----------------------------------- +// A FilePicker event without +// parameter +//----------------------------------- + +CFilePickerEventNotification::CFilePickerEventNotification(EventListenerMethod_t EventListenerMethod) : + m_EventListenerMethod(EventListenerMethod) +{ +} + +//---------------------------------- +// +//---------------------------------- + +void SAL_CALL CFilePickerEventNotification::notifyEventListener( Reference< XInterface > xListener ) +{ + Reference<XFilePickerListener> xFilePickerListener(xListener,UNO_QUERY); + if (xFilePickerListener.is()) + (xFilePickerListener.get()->*m_EventListenerMethod)(); +} + + +//################################################## + + +//---------------------------------- +// A FilePicker event with parameter +//---------------------------------- + +CFilePickerParamEventNotification::CFilePickerParamEventNotification(EventListenerMethod_t EventListenerMethod, const FilePickerEvent& FilePickerEvent) : + m_EventListenerMethod(EventListenerMethod), + m_FilePickerEvent(FilePickerEvent) +{ +} + +//---------------------------------- +// A FilePicker event with parameter +//---------------------------------- + +void SAL_CALL CFilePickerParamEventNotification::notifyEventListener( Reference< XInterface > xListener ) +{ + Reference<XFilePickerListener> xFilePickerListener(xListener,UNO_QUERY); + if (xFilePickerListener.is()) + (xFilePickerListener.get()->*m_EventListenerMethod)(m_FilePickerEvent); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/filepickereventnotification.hxx b/fpicker/source/win32/filepicker/filepickereventnotification.hxx new file mode 100644 index 000000000000..4a64c0ffcf80 --- /dev/null +++ b/fpicker/source/win32/filepicker/filepickereventnotification.hxx @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FILEPICKEREVENTNOTIFICATION_HXX_ +#define _FILEPICKEREVENTNOTIFICATION_HXX_ + +#include "eventnotification.hxx" +#include <com/sun/star/ui/dialogs/XFilePickerListener.hpp> +#include <com/sun/star/ui/dialogs/FilePickerEvent.hpp> + +//----------------------------------- +// A FilePicker event without +// parameter +//----------------------------------- + +class CFilePickerEventNotification : public CEventNotification +{ +public: + typedef void (SAL_CALL ::com::sun::star::ui::dialogs::XFilePickerListener::*EventListenerMethod_t)(); + +public: + CFilePickerEventNotification(EventListenerMethod_t EventListenerMethod); + + virtual void SAL_CALL notifyEventListener( com::sun::star::uno::Reference< com::sun::star::uno::XInterface > xListener ); + +private: + EventListenerMethod_t m_EventListenerMethod; +}; + +//---------------------------------- +// A FilePicker event with parameter +//---------------------------------- + +class CFilePickerParamEventNotification : public CEventNotification +{ +public: + typedef void (SAL_CALL ::com::sun::star::ui::dialogs::XFilePickerListener::*EventListenerMethod_t)(const ::com::sun::star::ui::dialogs::FilePickerEvent&); + + CFilePickerParamEventNotification(EventListenerMethod_t EventListenerMethod, const ::com::sun::star::ui::dialogs::FilePickerEvent& FilePickerEvent); + + virtual void SAL_CALL notifyEventListener( com::sun::star::uno::Reference< com::sun::star::uno::XInterface > xListener ); + +private: + EventListenerMethod_t m_EventListenerMethod; + com::sun::star::ui::dialogs::FilePickerEvent m_FilePickerEvent; +}; + + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/filepickerstate.cxx b/fpicker/source/win32/filepicker/filepickerstate.cxx new file mode 100644 index 000000000000..dedc63b3458a --- /dev/null +++ b/fpicker/source/win32/filepicker/filepickerstate.cxx @@ -0,0 +1,720 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ +#include "filepickerstate.hxx" +#include <osl/diagnose.h> +#include "controlaccess.hxx" +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/ListBoxControlActions.hpp> +#include <com/sun/star/ui/dialogs/ControlActions.hpp> +#include "controlcommandrequest.hxx" +#include "controlcommandresult.hxx" +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/XInterface.hpp> +#include <osl/file.hxx> +#include "FileOpenDlg.hxx" + +#include <memory> +#include "..\misc\WinImplHelper.hxx" +//--------------------------------------------- +// +//--------------------------------------------- + +using rtl::OUString; +using com::sun::star::uno::Any; +using com::sun::star::uno::Sequence; +using com::sun::star::uno::Reference; +using com::sun::star::uno::XInterface; + +using namespace ::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds; +using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds; +using namespace ::com::sun::star::ui::dialogs::ListboxControlActions; + +//--------------------------------------------- +// +//--------------------------------------------- + +const sal_Int32 MAX_LABEL = 256; +const sal_Int16 LISTBOX_LABEL_OFFSET = 100; + +//--------------------------------------------- +// declaration +//--------------------------------------------- + +CFilePickerState::~CFilePickerState( ) +{ +} + +//--------------------------------------------- +// +//--------------------------------------------- + +CNonExecuteFilePickerState::CNonExecuteFilePickerState( ) : + m_FirstControlCommand( NULL ) +{ +} + +//--------------------------------------------- +// +//--------------------------------------------- + +CNonExecuteFilePickerState::~CNonExecuteFilePickerState( ) +{ + reset( ); +} + +//--------------------------------------------- +// +//--------------------------------------------- + +void SAL_CALL CNonExecuteFilePickerState::setValue( sal_Int16 aControlId, sal_Int16 aControlAction, const Any& aValue ) +{ + CValueControlCommand* value_command = new CValueControlCommand( + aControlId, aControlAction, aValue ); + + addControlCommand( value_command ); +} + +//--------------------------------------------- +// +//--------------------------------------------- + +Any SAL_CALL CNonExecuteFilePickerState::getValue( sal_Int16 aControlId, sal_Int16 aControlAction ) +{ + CValueControlCommandRequest value_request( aControlId, aControlAction ); + Any aAny; + + if (m_FirstControlCommand) + { + // pass the request along the command-chain + std::auto_ptr< CControlCommandResult > result( m_FirstControlCommand->handleRequest( &value_request ) ); + + OSL_ENSURE( result.get(), "invalid getValue request" ); + + if ( result.get() ) + { + // #101753 must remove assertion else running into deadlock + // because getValue may be called asynchronously from main thread + // with locked SOLAR_MUTEX but we also need SOLAR_MUTEX in + // WinFileOpenDialog::onInitDone ... but we cannot dismiss the + // assertion dialog because at this point the FileOpen Dialog + // has aleady the focus but is not yet visible :-( + // The real cure is to remove the VCL/SOLAR_MUTEX dependency + // cause by the use of our resource manager and not being able to + // generate native windows resources + //OSL_ENSURE( result->hasResult( ), "invalid getValue request" ); + + if ( result->hasResult( ) ) + { + CValueCommandResult* value_result = dynamic_cast< CValueCommandResult* >( result.get( ) ); + OSL_ENSURE( value_result, "should have be a CValueCommandResult" ); + + aAny = value_result->getValue( ); + OSL_ENSURE( aAny.hasValue( ), "empty any" ); + } + } + } + + return aAny; +} + +//--------------------------------------------- +// +//--------------------------------------------- + +void SAL_CALL CNonExecuteFilePickerState::enableControl( sal_Int16 aControlId, sal_Bool bEnable ) +{ + CEnableControlCommand* enable_command = new CEnableControlCommand( + aControlId, bEnable ); + + addControlCommand( enable_command ); +} + +//--------------------------------------------- +// +//--------------------------------------------- + +void SAL_CALL CNonExecuteFilePickerState::setLabel( sal_Int16 aControlId, const ::rtl::OUString& aLabel ) +{ + CLabelControlCommand* label_command = new CLabelControlCommand( + aControlId, aLabel ); + + addControlCommand( label_command ); +} + +//--------------------------------------------- +// +//--------------------------------------------- + +OUString SAL_CALL CNonExecuteFilePickerState::getLabel( sal_Int16 aControlId ) +{ + CControlCommandRequest label_request( aControlId ); + + // pass the request along the command-chain + std::auto_ptr< CControlCommandResult > result( m_FirstControlCommand->handleRequest( &label_request ) ); + + OSL_ENSURE( result->hasResult( ), "invalid getValue request" ); + + OUString aLabel; + + if ( result->hasResult( ) ) + { + CLabelCommandResult* label_result = dynamic_cast< CLabelCommandResult* >( result.get( ) ); + OSL_ENSURE( label_result, "should have be a CLabelCommandResult" ); + + aLabel = label_result->getLabel( ); + } + + return aLabel; +} + +/* #i26224# + When typing file names with drive letter but without '\' + in the "File name" box of the FileOpen dialog the FileOpen + dialog makes strange paths out of them e.g. "d:.\test.sxw". + Such file names will not be accepted by sal so we fix these + somehow broken paths here. */ +OUString MatchFixBrokenPath(const OUString& path) +{ + OSL_ASSERT(path.getLength() >= 4); + + if (path[1] == ':' && path[2] == '.' && path[3] == '\\') + { + // skip the '.' + return OUString(path, 2) + path.copy(3, path.getLength() - 3); + } + return path; +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- +static ::rtl::OUString trimTrailingSpaces(const ::rtl::OUString& rString) +{ + rtl::OUString aResult(rString); + + sal_Int32 nIndex = rString.lastIndexOf(' '); + if (nIndex == rString.getLength()-1) + { + while (nIndex >= 0 && rString[nIndex] == ' ') + nIndex--; + if (nIndex >= 0) + aResult = rString.copy(0,nIndex+1); + else + aResult = ::rtl::OUString(); + } + return aResult; +} + +Sequence< OUString > SAL_CALL CNonExecuteFilePickerState::getFiles( CFileOpenDialog* aFileOpenDialog ) +{ + OSL_PRECOND( aFileOpenDialog, "invalid parameter" ); + + Sequence< OUString > aFilePathList; + OUString aFilePathURL; + OUString aFilePath; + ::osl::FileBase::RC rc; + + aFilePath = aFileOpenDialog->getFullFileName( ); + + if ( aFilePath.getLength( ) ) + { + // tokenize the returned string and copy the + // sub-strings separately into a sequence + const sal_Unicode* pTemp = aFilePath.getStr(); + const sal_Unicode* pStrEnd = pTemp + aFilePath.getLength(); + sal_uInt32 lSubStr; + + while (pTemp < pStrEnd) + { + // detect the length of the next sub string + lSubStr = rtl_ustr_getLength(pTemp); + + aFilePathList.realloc(aFilePathList.getLength() + 1); + + aFilePathList[aFilePathList.getLength() - 1] = + MatchFixBrokenPath(OUString(pTemp, lSubStr)); + + pTemp += (lSubStr + 1); + } + + // change all entries to file URLs + sal_Int32 lenFileList = aFilePathList.getLength( ); + OSL_ASSERT( lenFileList >= 1 ); + + for ( sal_Int32 i = 0; i < lenFileList; i++ ) + { + aFilePath = trimTrailingSpaces(aFilePathList[i]); + rc = ::osl::FileBase::getFileURLFromSystemPath( + aFilePath, aFilePathURL ); + + // we do return all or nothing, that means + // in case of failures we destroy the sequence + // and return an empty sequence + if ( rc != ::osl::FileBase::E_None ) + { + aFilePathList.realloc( 0 ); + break; + } + + aFilePathList[i] = aFilePathURL; + } + } + + return aFilePathList; +} + +//--------------------------------------------- +// +//--------------------------------------------- + +OUString SAL_CALL CNonExecuteFilePickerState::getDisplayDirectory( CFileOpenDialog* aFileOpenDialog ) +{ + OSL_PRECOND( aFileOpenDialog, "invalid parameter" ); + + OUString pathURL; + OUString displayDir; + + displayDir = aFileOpenDialog->getLastDisplayDirectory( ); + + if ( displayDir.getLength( ) ) + ::osl::FileBase::getFileURLFromSystemPath( displayDir, pathURL ); + + return pathURL; +} + +//--------------------------------------------- +// +//--------------------------------------------- + +void SAL_CALL CNonExecuteFilePickerState::reset( ) +{ + CControlCommand* nextCommand; + CControlCommand* currentCommand = m_FirstControlCommand; + + while( currentCommand ) + { + nextCommand = currentCommand->getNextCommand( ); + delete currentCommand; + currentCommand = nextCommand; + } + + m_FirstControlCommand = NULL; +} + +//--------------------------------------------- +// +//--------------------------------------------- + +CControlCommand* SAL_CALL CNonExecuteFilePickerState::getControlCommand( ) const +{ + return m_FirstControlCommand; +} + +//--------------------------------------------- +// we append new control commands to the end +// of the list so that we are sure the commands +// will be executed as the client issued it +//--------------------------------------------- + +void SAL_CALL CNonExecuteFilePickerState::addControlCommand( CControlCommand* aControlCommand ) +{ + OSL_ASSERT( aControlCommand ); + + if ( NULL == m_FirstControlCommand ) + { + m_FirstControlCommand = aControlCommand; + } + else + { + CControlCommand* pNextControlCommand = m_FirstControlCommand; + + while ( pNextControlCommand->getNextCommand( ) != NULL ) + pNextControlCommand = pNextControlCommand->getNextCommand( ); + + pNextControlCommand->setNextCommand( aControlCommand ); + } +} + +//####################################################################### + +//--------------------------------------------- +// +//--------------------------------------------- + +CExecuteFilePickerState::CExecuteFilePickerState( HWND hwndDlg ) : + m_hwndDlg( hwndDlg ) +{ +} + +//--------------------------------------------- +// +//--------------------------------------------- + +void SAL_CALL CExecuteFilePickerState::setValue( sal_Int16 aControlId, sal_Int16 aControlAction, const Any& aValue ) +{ + // we do not support SET_HELP_URL/GET_HELP_URL + if ( com::sun::star::ui::dialogs::ControlActions::SET_HELP_URL == aControlAction ) + return; + + HWND hwndCtrl = GetHwndDlgItem( aControlId ); + + // the filter listbox can be manipulated via this + // method the caller should use XFilterManager + if ( !hwndCtrl || (aControlId == LISTBOX_FILTER) ) + { + OSL_ENSURE( sal_False, "invalid control id" ); + return; + } + + CTRL_CLASS aCtrlClass = GetCtrlClass( hwndCtrl ); + if ( UNKNOWN == aCtrlClass ) + { + OSL_ENSURE( sal_False, "unsupported control class" ); + return; + } + + CTRL_SETVALUE_FUNCTION_T lpfnSetValue = + GetCtrlSetValueFunction( aCtrlClass, aControlAction ); + + if ( !lpfnSetValue ) + { + OSL_ENSURE( sal_False, "unsupported control action" ); + return; + } + + // the function that we call should throw an IllegalArgumentException if + // the given value is invalid or empty, that's why we provide a Reference + // to an XInterface and a argument position + lpfnSetValue( hwndCtrl, aValue, Reference< XInterface >( ), 3 ); +} + +//--------------------------------------------- +// +//--------------------------------------------- + +Any SAL_CALL CExecuteFilePickerState::getValue( sal_Int16 aControlId, sal_Int16 aControlAction ) +{ + // we do not support SET_HELP_URL/GET_HELP_URL + if ( com::sun::star::ui::dialogs::ControlActions::GET_HELP_URL == aControlAction ) + return Any( ); + + HWND hwndCtrl = GetHwndDlgItem( aControlId ); + + // the filter listbox can be manipulated via this + // method the caller should use XFilterManager + if ( !hwndCtrl || (aControlId == LISTBOX_FILTER) ) + { + OSL_ENSURE( sal_False, "invalid control id" ); + return Any( ); + } + + CTRL_CLASS aCtrlClass = GetCtrlClass( hwndCtrl ); + if ( UNKNOWN == aCtrlClass ) + { + OSL_ENSURE( sal_False, "unsupported control class" ); + return Any( ); + } + + CTRL_GETVALUE_FUNCTION_T lpfnGetValue = + GetCtrlGetValueFunction( aCtrlClass, aControlAction ); + + if ( !lpfnGetValue ) + { + OSL_ENSURE( sal_False, "unsupported control action" ); + return Any( ); + } + + return lpfnGetValue( hwndCtrl ); +} + +//--------------------------------------------- +// +//--------------------------------------------- + +void SAL_CALL CExecuteFilePickerState::enableControl( sal_Int16 aControlId, sal_Bool bEnable ) +{ + HWND hwndCtrl = GetHwndDlgItem( aControlId ); + + OSL_ENSURE( IsWindow( hwndCtrl ), "invalid element id"); + + EnableWindow( hwndCtrl, bEnable ); +} + +//--------------------------------------------- +// +//--------------------------------------------- + +void SAL_CALL CExecuteFilePickerState::setLabel( sal_Int16 aControlId, const OUString& aLabel ) +{ + HWND hwndCtrl = GetHwndDlgItem( aControlId ); + + OSL_ENSURE( IsWindow( hwndCtrl ), "invalid element id"); + + if ( IsListboxControl( hwndCtrl ) ) + hwndCtrl = GetListboxLabelItem( aControlId ); + + OUString aWinLabel = SOfficeToWindowsLabel( aLabel ); + + // somewhat risky because we don't know if OUString + // has a terminating '\0' + SetWindowText( hwndCtrl, reinterpret_cast<LPCTSTR>(aWinLabel.getStr( )) ); +} + +//--------------------------------------------- +// +//--------------------------------------------- + +OUString SAL_CALL CExecuteFilePickerState::getLabel( sal_Int16 aControlId ) +{ + HWND hwndCtrl = GetHwndDlgItem( aControlId ); + + OSL_ENSURE( IsWindow( hwndCtrl ), "invalid element id"); + + if ( IsListboxControl( hwndCtrl ) ) + hwndCtrl = GetListboxLabelItem( aControlId ); + + sal_Unicode aLabel[MAX_LABEL]; + int nRet = GetWindowText( hwndCtrl, reinterpret_cast<LPTSTR>(aLabel), MAX_LABEL ); + + OUString ctrlLabel; + if ( nRet ) + { + ctrlLabel = OUString( aLabel, rtl_ustr_getLength( aLabel ) ); + ctrlLabel = WindowsToSOfficeLabel( aLabel ); + } + + return ctrlLabel; +} + +//--------------------------------------------- +// +//--------------------------------------------- + +Sequence< OUString > SAL_CALL CExecuteFilePickerState::getFiles( CFileOpenDialog* aFileOpenDialog ) +{ + OSL_POSTCOND( aFileOpenDialog, "invalid parameter" ); + + Sequence< OUString > aFilePathList; + OUString aFilePathURL; + OUString aFilePath; + ::osl::FileBase::RC rc; + + // in execution mode getFullFileName doesn't + // return anything, so we must use another way + + // returns the currently selected file(s) + // including path information + aFilePath = aFileOpenDialog->getCurrentFilePath( ); + + // if multiple files are selected or the user + // typed anything that doesn't seem to be a valid + // file name getFileURLFromSystemPath fails + // and we return an empty file list + rc = ::osl::FileBase::getFileURLFromSystemPath( + aFilePath, aFilePathURL ); + + if ( ::osl::FileBase::E_None == rc ) + { + aFilePathList.realloc( 1 ); + aFilePathList[0] = aFilePathURL; + } + + return aFilePathList; +} + +//--------------------------------------------- +// +//--------------------------------------------- + +OUString SAL_CALL CExecuteFilePickerState::getDisplayDirectory( CFileOpenDialog* aFileOpenDialog ) +{ + OSL_POSTCOND( aFileOpenDialog, "invalid parameter" ); + + OUString pathURL; + OUString displayDir; + + displayDir = aFileOpenDialog->getCurrentFolderPath( ); + + if ( displayDir.getLength( ) ) + ::osl::FileBase::getFileURLFromSystemPath( displayDir, pathURL ); + + return pathURL; +} + +//--------------------------------------------- +// +//--------------------------------------------- + +void SAL_CALL CExecuteFilePickerState::initFilePickerControls( CControlCommand* firstControlCommand ) +{ + CControlCommand* aControlCommand = firstControlCommand; + + while ( aControlCommand ) + { + aControlCommand->exec( this ); + aControlCommand = aControlCommand->getNextCommand( ); + } +} + +//--------------------------------------------- +// +//--------------------------------------------- + +void SAL_CALL CExecuteFilePickerState::cacheControlState( HWND hwndControl, CFilePickerState* aNonExecFilePickerState ) +{ + OSL_ENSURE( hwndControl && aNonExecFilePickerState, "invalid parameters" ); + + CTRL_CLASS aCtrlClass = GetCtrlClass( hwndControl ); + + sal_Int16 aControlAction; + CTRL_GETVALUE_FUNCTION_T lpfnGetValue; + + if ( CHECKBOX == aCtrlClass ) + { + aControlAction = 0; + + lpfnGetValue = GetCtrlGetValueFunction( aCtrlClass, aControlAction ); + + OSL_ASSERT( lpfnGetValue ); + + aNonExecFilePickerState->setValue( + sal::static_int_cast< sal_Int16 >( GetDlgCtrlID( hwndControl ) ), + aControlAction, + lpfnGetValue( hwndControl ) ); + + aNonExecFilePickerState->setLabel( + sal::static_int_cast< sal_Int16 >( GetDlgCtrlID( hwndControl ) ), + getLabel( + sal::static_int_cast< sal_Int16 >( + GetDlgCtrlID( hwndControl ) ) ) ); + } + else if ( LISTBOX == aCtrlClass ) + { + // for listboxes we save only the + // last selected item and the last + // selected item index + + aControlAction = GET_SELECTED_ITEM; + + lpfnGetValue = GetCtrlGetValueFunction( aCtrlClass, aControlAction ); + + aNonExecFilePickerState->setValue( + sal::static_int_cast< sal_Int16 >( GetDlgCtrlID( hwndControl ) ), + aControlAction, + lpfnGetValue( hwndControl ) ); + + aControlAction = ::com::sun::star::ui::dialogs::ControlActions::GET_SELECTED_ITEM_INDEX; + + lpfnGetValue = GetCtrlGetValueFunction( aCtrlClass, aControlAction ); + + aNonExecFilePickerState->setValue( + sal::static_int_cast< sal_Int16 >( GetDlgCtrlID( hwndControl ) ), + aControlAction, + lpfnGetValue( hwndControl ) ); + } +} + +//--------------------------------------------- +// +//--------------------------------------------- + +void SAL_CALL CExecuteFilePickerState::setHwnd( HWND hwndDlg ) +{ + m_hwndDlg = hwndDlg; +} + +//--------------------------------------------- +// +//--------------------------------------------- + +inline sal_Bool SAL_CALL CExecuteFilePickerState::IsListboxControl( HWND hwndControl ) const +{ + OSL_PRECOND( IsWindow( hwndControl ), "invalid parameter" ); + + CTRL_CLASS aCtrlClass = GetCtrlClass( hwndControl ); + return ( LISTBOX == aCtrlClass ); +} + +//--------------------------------------------- +// because listboxes (comboboxes) and their labels +// are seperated we have to translate the listbox +// id to their corresponding label id +// the convention is that the label id of a listbox +// is the id of the listbox + 100 +//--------------------------------------------- + +inline sal_Int16 SAL_CALL CExecuteFilePickerState::ListboxIdToListboxLabelId( sal_Int16 aListboxId ) const +{ + return ( aListboxId + LISTBOX_LABEL_OFFSET ); +} + +//--------------------------------------------- +// +//--------------------------------------------- + +inline HWND SAL_CALL CExecuteFilePickerState::GetListboxLabelItem( sal_Int16 aControlId ) const +{ + sal_Int16 aLabelId = ListboxIdToListboxLabelId( aControlId ); + HWND hwndCtrl = GetHwndDlgItem( aLabelId ); + + OSL_ASSERT( IsWindow( hwndCtrl ) ); + + return hwndCtrl; +} + +//--------------------------------------------- +// +//--------------------------------------------- + +HWND SAL_CALL CExecuteFilePickerState::GetHwndDlgItem( sal_Int16 aControlId, sal_Bool bIncludeStdCtrls ) const +{ + OSL_ENSURE( IsWindow( m_hwndDlg ), "no valid parent window set before" ); + + HWND hwndCtrl = GetDlgItem( m_hwndDlg, aControlId ); + + // maybe it's a control of the dialog itself for instance + // the ok and cancel button + if ( !hwndCtrl && bIncludeStdCtrls ) + { + hwndCtrl = GetDlgItem( + GetParent( m_hwndDlg ), + CommonFilePickerCtrlIdToWinFileOpenCtrlId( aControlId ) ); + } + + return hwndCtrl; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/filepickerstate.hxx b/fpicker/source/win32/filepicker/filepickerstate.hxx new file mode 100644 index 000000000000..1255e9325619 --- /dev/null +++ b/fpicker/source/win32/filepicker/filepickerstate.hxx @@ -0,0 +1,165 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FILEPICKERSTATE_HXX_ +#define _FILEPICKERSTATE_HXX_ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <sal/types.h> +#include "controlcommand.hxx" +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <rtl/ustring.hxx> + +#define WIN32_LEAN_AND_MEAN +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif +//--------------------------------------------- +// +//--------------------------------------------- + +class CControlCommand; +class CFileOpenDialog; + +//--------------------------------------------- +// declaration +//--------------------------------------------- + +class CFilePickerState +{ +public: + virtual ~CFilePickerState( ); + + virtual void SAL_CALL setValue( sal_Int16 aControlId, sal_Int16 aControlAction, const ::com::sun::star::uno::Any& aValue ) = 0; + + virtual ::com::sun::star::uno::Any SAL_CALL getValue( sal_Int16 aControlId, sal_Int16 aControlAction ) = 0; + + virtual void SAL_CALL enableControl( sal_Int16 aControlId, sal_Bool bEnable ) = 0; + + virtual void SAL_CALL setLabel( sal_Int16 aControlId, const ::rtl::OUString& aLabel ) = 0; + + virtual ::rtl::OUString SAL_CALL getLabel( sal_Int16 aControlId ) = 0; + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getFiles( CFileOpenDialog* aFileOpenDialog ) = 0; + + virtual rtl::OUString SAL_CALL getDisplayDirectory( CFileOpenDialog* aFileOpenDialog ) = 0; +}; + +//--------------------------------------------- +// this class is not thread-safe +//--------------------------------------------- + +class CNonExecuteFilePickerState : public CFilePickerState +{ +public: + CNonExecuteFilePickerState( ); + + virtual ~CNonExecuteFilePickerState( ); + + virtual void SAL_CALL setValue( sal_Int16 aControlId, sal_Int16 aControlAction, const ::com::sun::star::uno::Any& aValue ); + + virtual ::com::sun::star::uno::Any SAL_CALL getValue( sal_Int16 aControlId, sal_Int16 aControlAction ); + + virtual void SAL_CALL enableControl( sal_Int16 aControlId, sal_Bool bEnable ); + + virtual void SAL_CALL setLabel( sal_Int16 aControlId, const ::rtl::OUString& aLabel ); + + virtual ::rtl::OUString SAL_CALL getLabel( sal_Int16 aControlId ); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getFiles( CFileOpenDialog* aFileOpenDialog ); + + virtual rtl::OUString SAL_CALL getDisplayDirectory( CFileOpenDialog* aFileOpenDialog ); + + void SAL_CALL reset( ); + + CControlCommand* SAL_CALL getControlCommand( ) const; + +protected: + void SAL_CALL addControlCommand( CControlCommand* aControlCommand ); + +private: + CControlCommand* m_FirstControlCommand; +}; + +//--------------------------------------------- +// this class is not thread-safe +//--------------------------------------------- + +class CExecuteFilePickerState : public CFilePickerState +{ +public: + CExecuteFilePickerState( HWND hwndDlg = NULL ); + + virtual void SAL_CALL setValue( sal_Int16 aControlId, sal_Int16 aControlAction, const ::com::sun::star::uno::Any& aValue ); + + virtual ::com::sun::star::uno::Any SAL_CALL getValue( sal_Int16 aControlId, sal_Int16 aControlAction ); + + virtual void SAL_CALL enableControl( sal_Int16 aControlId, sal_Bool bEnable ); + + virtual void SAL_CALL setLabel( sal_Int16 aControlId, const ::rtl::OUString& aLabel ); + + virtual ::rtl::OUString SAL_CALL getLabel( sal_Int16 aControlId ); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getFiles( CFileOpenDialog* aFileOpenDialog ); + + virtual rtl::OUString SAL_CALL getDisplayDirectory( CFileOpenDialog* aFileOpenDialog ); + + void SAL_CALL initFilePickerControls( CControlCommand* firstControlCommand ); + + void SAL_CALL cacheControlState( HWND hwndControl, CFilePickerState* aFilePickerState ); + + void SAL_CALL setHwnd( HWND hwndDlg ); + +private: + + inline sal_Bool SAL_CALL IsListboxControl( HWND hwndControl ) const; + + inline sal_Int16 SAL_CALL ListboxIdToListboxLabelId( sal_Int16 aListboxId ) const; + + inline HWND SAL_CALL GetListboxLabelItem( sal_Int16 aControlId ) const; + + // returns a hwnd for a control if successful + // if bIncludeStdCtrls is false, the standard file dialog + // controls like OK button, etc. will not be considered + // the function return 0 on failure + HWND SAL_CALL GetHwndDlgItem( sal_Int16 aControlId, sal_Bool bIncludeStdCtrls = sal_True ) const; + + HWND m_hwndDlg; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/fps.xml b/fpicker/source/win32/filepicker/fps.xml new file mode 100644 index 000000000000..93530780956b --- /dev/null +++ b/fpicker/source/win32/filepicker/fps.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + <module-name>fps</module-name> + <component-description> + <author> Tino Rachui </author> + <name> com.sun.star.comp.ui.dialogs.FilePicker </name> + <description> + The win32 implementation of the FilePicker service. +</description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language> c++ </language> + <status value="beta"/> + <supported-service> com.sun.star.ui.dialogs.FilePicker </supported-service> + <service-dependency>...</service-dependency> + <type> com.sun.star.ui.dialogs.XExecutableDialog </type> + <type> com.sun.star.ui.dialogs.XFilePicker </type> + <type> com.sun.star.ui.dialogs.XFilterManager </type> + <type> com.sun.star.ui.dialogs.XFilterGroupManager </type> + <type> com.sun.star.ui.dialogs.XFilePickerListener </type> + <type> com.sun.star.ui.dialogs.ExecutableDialogException </type> + <type> com.sun.star.ui.dialogs.XFilePickerNotifier </type> + <type> com.sun.star.ui.dialogs.XFilePickerControlAccess </type> + <type> com.sun.star.ui.dialogs.XFilePreview </type> + <type> com.sun.star.ui.dialogs.ExtendedFilePickerElementIds </type> + <type> com.sun.star.ui.dialogs.ExecutableDialogResults </type> + <type> com.sun.star.ui.dialogs.FilePickerEvent </type> + <type> com.sun.star.ui.dialogs.CommonFilePickerElementIds </type> + <type> com.sun.star.ui.dialogs.ListboxControlActions </type> + <type> com.sun.star.ui.dialogs.TemplateDescription </type> + <type> com.sun.star.ui.dialogs.FilePreviewImageFormats </type> + <type> com.sun.star.util.XCancellable </type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.lang.IllegalArgumentException </type> + <type> com.sun.star.uno.TypeClass </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.uno.XAggregation </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.container.XSet </type> + </component-description> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> sal </project-build-dependency> + <runtime-module-dependency> cppuhelper </runtime-module-dependency> + <runtime-module-dependency> cppu2 </runtime-module-dependency> + <runtime-module-dependency> sal2 </runtime-module-dependency> +</module-description> diff --git a/fpicker/source/win32/filepicker/getfilenamewrapper.cxx b/fpicker/source/win32/filepicker/getfilenamewrapper.cxx new file mode 100644 index 000000000000..107112a1b1b7 --- /dev/null +++ b/fpicker/source/win32/filepicker/getfilenamewrapper.cxx @@ -0,0 +1,298 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <stdio.h> +#include <osl/diagnose.h> +#include "getfilenamewrapper.hxx" + +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <objbase.h> +#include <process.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +namespace /* private */ +{ + + //----------------------------------------------- + // This class prevents changing of the working + // directory. + //----------------------------------------------- + class CurDirGuard + { + BOOL m_bValid; + wchar_t* m_pBuffer; + DWORD m_nBufLen; + + public: + CurDirGuard() + : m_bValid( FALSE ) + , m_pBuffer( NULL ) + , m_nBufLen( 0 ) + { + m_nBufLen = GetCurrentDirectoryW( 0, NULL ); + if ( m_nBufLen ) + { + m_pBuffer = new wchar_t[m_nBufLen]; + m_bValid = ( GetCurrentDirectoryW( m_nBufLen, m_pBuffer ) == ( m_nBufLen - 1 ) ); + } + } + + ~CurDirGuard() + { + BOOL bDirSet = FALSE; + + if ( m_pBuffer ) + { + if ( m_bValid ) + { + if ( m_nBufLen - 1 > MAX_PATH ) + { + if ( (LONG32)GetVersion() < 0 ) + { + // this is Win 98/ME branch, such a long path can not be set + // use the system path as fallback later + } + else + { + DWORD nNewLen = m_nBufLen + 8; + wchar_t* pNewBuffer = new wchar_t[nNewLen]; + if ( m_nBufLen > 3 && m_pBuffer[0] == (wchar_t)'\\' && m_pBuffer[1] == (wchar_t)'\\' ) + { + if ( m_pBuffer[2] == (wchar_t)'?' ) + _snwprintf( pNewBuffer, nNewLen, L"%s", m_pBuffer ); + else + _snwprintf( pNewBuffer, nNewLen, L"\\\\?\\UNC\\%s", m_pBuffer+2 ); + } + else + _snwprintf( pNewBuffer, nNewLen, L"\\\\?\\%s", m_pBuffer ); + bDirSet = SetCurrentDirectoryW( pNewBuffer ); + + delete [] pNewBuffer; + } + } + else + bDirSet = SetCurrentDirectoryW( m_pBuffer ); + } + + delete [] m_pBuffer; + m_pBuffer = NULL; + } + + if ( !bDirSet ) + { + // the fallback solution + wchar_t pPath[MAX_PATH+1]; + if ( GetWindowsDirectoryW( pPath, MAX_PATH+1 ) <= MAX_PATH ) + { + SetCurrentDirectoryW( pPath ); + } + else + { + // the system path is also too long?!! + } + } + } + }; + + //----------------------------------------------- + // + //----------------------------------------------- + + struct GetFileNameParam + { + GetFileNameParam(bool bOpen, LPOPENFILENAME lpofn) : + m_bOpen(bOpen), + m_lpofn(lpofn), + m_bRet(false), + m_ExtErr(0) + {} + + bool m_bOpen; + LPOPENFILENAME m_lpofn; + bool m_bRet; + int m_ExtErr; + }; + + //----------------------------------------------- + // + //----------------------------------------------- + + unsigned __stdcall ThreadProc(void* pParam) + { + CurDirGuard aGuard; + + GetFileNameParam* lpgfnp = + reinterpret_cast<GetFileNameParam*>(pParam); + + HRESULT hr = OleInitialize( NULL ); + + if (lpgfnp->m_bOpen) + lpgfnp->m_bRet = GetOpenFileName(lpgfnp->m_lpofn); + else + lpgfnp->m_bRet = GetSaveFileName(lpgfnp->m_lpofn); + + lpgfnp->m_ExtErr = CommDlgExtendedError(); + + if ( SUCCEEDED( hr ) ) + OleUninitialize(); + + return 0; + } + + //----------------------------------------------- + // exceutes GetOpenFileName/GetSaveFileName in + // a separat thread + //----------------------------------------------- + + bool ThreadExecGetFileName(LPOPENFILENAME lpofn, bool bOpen, /*out*/ int& ExtErr) + { + GetFileNameParam gfnp(bOpen,lpofn); + unsigned id; + + HANDLE hThread = reinterpret_cast<HANDLE>( + _beginthreadex(0, 0, ThreadProc, &gfnp, 0, &id)); + + OSL_POSTCOND(hThread, "could not create STA thread"); + + WaitForSingleObject(hThread, INFINITE); + CloseHandle(hThread); + + ExtErr = gfnp.m_ExtErr; + + return gfnp.m_bRet; + } + + //----------------------------------------------- + // This function returns true if the calling + // thread belongs to a Multithreaded Appartment + // (MTA) + //----------------------------------------------- + + bool IsMTA() + { + HRESULT hr = CoInitialize(NULL); + + if (RPC_E_CHANGED_MODE == hr) + return true; + + if(SUCCEEDED(hr)) + CoUninitialize(); + + return false; + } + +} // namespace private + + +//----------------------------------------------- +// +//----------------------------------------------- + +CGetFileNameWrapper::CGetFileNameWrapper() : + m_ExtendedDialogError(0) +{ +} + +//----------------------------------------------- +// +//----------------------------------------------- + +bool CGetFileNameWrapper::getOpenFileName(LPOPENFILENAME lpofn) +{ + OSL_PRECOND(lpofn,"invalid parameter"); + + bool bRet = false; + + if (IsMTA()) + { + bRet = ThreadExecGetFileName( + lpofn, true, m_ExtendedDialogError); + } + else + { + CurDirGuard aGuard; + + HRESULT hr = OleInitialize( NULL ); + + bRet = GetOpenFileName(lpofn); + m_ExtendedDialogError = CommDlgExtendedError(); + + if ( SUCCEEDED( hr ) ) + OleUninitialize(); + } + + return bRet; +} + +//----------------------------------------------- +// +//----------------------------------------------- + +bool CGetFileNameWrapper::getSaveFileName(LPOPENFILENAME lpofn) +{ + OSL_PRECOND(lpofn,"invalid parameter"); + + bool bRet = false; + + if (IsMTA()) + { + bRet = ThreadExecGetFileName( + lpofn, false, m_ExtendedDialogError); + } + else + { + CurDirGuard aGuard; + + bRet = GetSaveFileName(lpofn); + m_ExtendedDialogError = CommDlgExtendedError(); + } + + return bRet; +} + +//----------------------------------------------- +// +//----------------------------------------------- + +int CGetFileNameWrapper::commDlgExtendedError( ) +{ + return m_ExtendedDialogError; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/getfilenamewrapper.hxx b/fpicker/source/win32/filepicker/getfilenamewrapper.hxx new file mode 100644 index 000000000000..2e028b4df210 --- /dev/null +++ b/fpicker/source/win32/filepicker/getfilenamewrapper.hxx @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _GETFILENAMEWRAPPER_HXX_ +#define _GETFILENAMEWRAPPER_HXX_ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <sal/types.h> + +#define WIN32_LEAN_AND_MEAN +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#include <commdlg.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +/* + A simple wrapper around the GetOpenFileName/GetSaveFileName API. + Because currently the Win32 API functions GetOpenFileName/GetSaveFileName + work only properly in an Single Threaded Appartment. +*/ + +class CGetFileNameWrapper +{ +public: + CGetFileNameWrapper(); + + bool getOpenFileName(LPOPENFILENAME lpofn); + bool getSaveFileName(LPOPENFILENAME lpofn); + int commDlgExtendedError(); + +private: + int m_ExtendedDialogError; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/helppopupwindow.cxx b/fpicker/source/win32/filepicker/helppopupwindow.cxx new file mode 100644 index 000000000000..f1faf3928416 --- /dev/null +++ b/fpicker/source/win32/filepicker/helppopupwindow.cxx @@ -0,0 +1,618 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <tchar.h> +#include "helppopupwindow.hxx" +#include <osl/diagnose.h> + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +using rtl::OUString; +using osl::Mutex; + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +namespace /* private */ +{ + + const LPTSTR CURRENT_INSTANCE = TEXT("CurrInst"); + +}; + +//------------------------------------------------------------------------ +// defines +//------------------------------------------------------------------------ + +#define HELPPOPUPWND_CLASS_NAME TEXT("hlppopupwnd###") + +const sal_Int32 MAX_CHARS_PER_LINE = 55; + +const sal_Int32 SHADOW_WIDTH = 6; +const sal_Int32 SHADOW_HEIGHT = 6; +const sal_Int32 SHADOW_OFFSET = 6; +const sal_Int32 YOFFSET = 20; + +const DWORD OUTER_FRAME_COLOR = 0; // black +const sal_Int32 OUTER_FRAME_WIDTH = 1; // pixel + +// it's the standard windows color of an inactive window border +const DWORD INNER_FRAME_COLOR = 0xC8D0D4; +const sal_Int32 INNER_FRAME_WIDTH = 1; // pixel + +//--------------------------------------------------- +// static member initialization +//--------------------------------------------------- + +osl::Mutex CHelpPopupWindow::s_Mutex; +ATOM CHelpPopupWindow::s_ClassAtom = 0; +sal_Int32 CHelpPopupWindow::s_RegisterWndClassCount = 0; + +//--------------------------------------------------- +// +//--------------------------------------------------- + +CHelpPopupWindow::CHelpPopupWindow( + HINSTANCE hInstance, + HWND hwndParent ) : + m_hMargins( 0 ), + m_vMargins( 0 ), + m_avCharWidth( 0 ), + m_avCharHeight( 0 ), + m_hwnd( NULL ), + m_hwndParent( hwndParent ), + m_hInstance( hInstance ), + m_hBitmapShadow( NULL ), + m_hBrushShadow( NULL ) +{ + m_bWndClassRegistered = RegisterWindowClass( ) ? sal_True : sal_False; + + // create a pattern brush for the window shadow + WORD aPattern[] = { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 }; + + m_hBitmapShadow = CreateBitmap( 8, 8, 1, 1, aPattern ); + m_hBrushShadow = CreatePatternBrush( m_hBitmapShadow ); +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +CHelpPopupWindow::~CHelpPopupWindow( ) +{ + // remember: we don't have to destroy the + // preview window because it will be destroyed + // by it's parent window (the FileOpen dialog) + // but we have to unregister the window class + if ( m_bWndClassRegistered ) + UnregisterWindowClass( ); + + DeleteObject( m_hBitmapShadow ); + DeleteObject( m_hBrushShadow ); +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +void SAL_CALL CHelpPopupWindow::setText( const rtl::OUString& aHelpText ) +{ + m_HelpText = aHelpText; +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +void SAL_CALL CHelpPopupWindow::show( sal_Int32 x, sal_Int32 y ) +{ + OSL_ENSURE( NULL == m_hwnd, "method should not be called twice in sequence" ); + + // we create a window with length and heigth of 0 + // first in order to get a device context of this + // window, then we calculate the upper left corner + // and the dimensions and resize the window + + m_hwnd = CreateWindowEx( + NULL, + HELPPOPUPWND_CLASS_NAME, + NULL, + WS_POPUP, + 0, + 0, + 0, + 0, + m_hwndParent, + NULL, + m_hInstance, + (LPVOID)this ); + + OSL_ENSURE( m_hwnd, "creating help popup window failed" ); + + sal_Int32 cx_new; + sal_Int32 cy_new; + + adjustWindowSize( &cx_new, &cy_new ); + adjustWindowPos( x, y, cx_new, cy_new ); + + UpdateWindow( m_hwnd ); + ShowWindow( m_hwnd, SW_SHOW ); +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +HWND SAL_CALL CHelpPopupWindow::setParent( HWND hwndNewParent ) +{ + HWND oldParent = m_hwndParent; + + m_hwndParent = hwndNewParent; + + return oldParent; +} + +//--------------------------------------------------- +// calculates the necessary dimensions of the popup +// window including the margins etc. +//--------------------------------------------------- + +void SAL_CALL CHelpPopupWindow::calcWindowRect( LPRECT lprect ) +{ + OSL_ASSERT( m_hwnd && lprect ); + + SetRect( lprect, 0, 0, MAX_CHARS_PER_LINE * m_avCharWidth, 0 ); + + HDC hdc = GetDC( m_hwnd ); + + // set the font we are using later + HGDIOBJ oldFont = SelectObject( + hdc, GetStockObject( DEFAULT_GUI_FONT ) ); + + UINT nFormat = DT_WORDBREAK | DT_CALCRECT | DT_EXTERNALLEADING | DT_LEFT; + + if ( m_HelpText.getLength( ) <= MAX_CHARS_PER_LINE ) + nFormat |= DT_SINGLELINE; + + DrawText( + hdc, + reinterpret_cast<LPCTSTR>(m_HelpText.getStr( )), + m_HelpText.getLength( ), + lprect, + nFormat ); + + // add the necessary space for the frames + // and margins + + lprect->bottom += + m_vMargins + + SHADOW_HEIGHT + + OUTER_FRAME_WIDTH * 2 + + INNER_FRAME_WIDTH * 2; + + lprect->right += + SHADOW_WIDTH + + 2 * m_avCharWidth + + OUTER_FRAME_WIDTH * 2 + + INNER_FRAME_WIDTH * 2; + + SelectObject( hdc, oldFont ); + + ReleaseDC( m_hwnd, hdc ); +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +void SAL_CALL CHelpPopupWindow::adjustWindowSize( sal_Int32* cx_new, sal_Int32* cy_new ) +{ + OSL_ASSERT( cx_new && cy_new ); + + RECT rect; + calcWindowRect( &rect ); + + // adjust the window size + SetWindowPos( + m_hwnd, + NULL, + 0, + 0, + rect.right, + rect.bottom, + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER ); + + *cx_new = rect.right; + *cy_new = rect.bottom; +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +void SAL_CALL CHelpPopupWindow::adjustWindowPos( + sal_Int32 x, sal_Int32 y, sal_Int32 cx, sal_Int32 cy ) +{ + int popX; + int popY; + int popWidth; + int popHeight; + + OSL_ASSERT( m_hwnd ); + + HDC hdc = GetDC( m_hwnd ); + + // assuming these are screen coordinates + popWidth = cx; + popHeight = cy; + popX = x - ( popWidth / 2 ); + popY = y - YOFFSET; + + int xScreen = GetDeviceCaps( hdc, HORZRES ); + int yScreen = GetDeviceCaps( hdc, VERTRES ); + + if (popX < 0) + popX = 0; + + if (popY < 0) + popY = 0; + + if ((popX + popWidth) > xScreen) + popX = xScreen - popWidth; + + if ((popY + popHeight) > yScreen) + popY = yScreen - popHeight; + + SetWindowPos( + m_hwnd, + NULL, + popX, + popY, + 0, + 0, + SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE ); + + ReleaseDC( m_hwnd, hdc ); +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +void SAL_CALL CHelpPopupWindow::onPaint( HWND hWnd, HDC hdc ) +{ + RECT rc; + RECT rect; + HGDIOBJ hpen, hpenOld; + HGDIOBJ hbrOld; + COLORREF oldBkColor; + COLORREF oldTextColor; + HGDIOBJ oldFont; + HGDIOBJ oldBrush; + HGDIOBJ hBrush; + + GetClientRect( hWnd, &rc ); + + // draw the black border + + hBrush = CreateSolidBrush( GetSysColor( COLOR_INFOBK ) ); + oldBrush = SelectObject( hdc, hBrush ); + + hpen = CreatePen( PS_SOLID, 0, OUTER_FRAME_COLOR ); + hpenOld = SelectObject( hdc, hpen ); + + Rectangle( hdc, + rc.left + OUTER_FRAME_WIDTH, + rc.top + OUTER_FRAME_WIDTH, + rc.right - SHADOW_WIDTH, + rc.bottom - SHADOW_HEIGHT); + + SelectObject( hdc, oldBrush ); + SelectObject( hdc, hpenOld ); + + DeleteObject( hBrush ); + DeleteObject( hpen ); + + // draw a light gray border + + hBrush = CreateSolidBrush( GetSysColor( COLOR_INFOBK ) ); + oldBrush = SelectObject( hdc, hBrush ); + + hpen = CreatePen( PS_SOLID, 0, INNER_FRAME_COLOR ); + hpenOld = SelectObject( hdc, hpen ); + + Rectangle( hdc, + rc.left + OUTER_FRAME_WIDTH + 1, + rc.top + OUTER_FRAME_WIDTH + 1, + rc.right - SHADOW_WIDTH - OUTER_FRAME_WIDTH, + rc.bottom - SHADOW_HEIGHT - OUTER_FRAME_WIDTH ); + + SelectObject( hdc, oldBrush ); + SelectObject( hdc, hpenOld ); + + DeleteObject( hBrush ); + DeleteObject( hpen ); + + // Write some text to this window + + rect.left = rc.left + OUTER_FRAME_WIDTH + INNER_FRAME_WIDTH + 1 + m_hMargins; + rect.top = rc.top + OUTER_FRAME_WIDTH + INNER_FRAME_WIDTH + 1 + m_vMargins / 2; + rect.right = rc.right - SHADOW_WIDTH - OUTER_FRAME_WIDTH - INNER_FRAME_WIDTH - m_hMargins; + rect.bottom = rc.bottom - SHADOW_HEIGHT - OUTER_FRAME_WIDTH - INNER_FRAME_WIDTH - m_vMargins / 2; + + oldBkColor = SetBkColor( hdc, GetSysColor( COLOR_INFOBK ) ); + oldTextColor = SetTextColor( hdc, COLOR_INFOTEXT ); + + oldFont = SelectObject( hdc, GetStockObject( DEFAULT_GUI_FONT ) ); + + UINT nFormat = DT_WORDBREAK | DT_EXTERNALLEADING | DT_LEFT; + + if ( m_HelpText.getLength( ) <= MAX_CHARS_PER_LINE ) + nFormat |= DT_SINGLELINE; + + DrawText( + hdc, + (LPWSTR)m_HelpText.getStr( ), + m_HelpText.getLength( ), + &rect, + nFormat ); + + SelectObject( hdc, oldFont ); + SetTextColor( hdc, oldTextColor ); + SetBkColor( hdc, oldBkColor ); + + // set text color and text background color + // see MSDN PatBlt + + oldBkColor = SetBkColor( hdc, RGB( 0, 0, 0 ) ); + oldTextColor = SetTextColor( hdc, RGB( 255, 255, 255 ) ); + + // Get our brush for the shadow + + UnrealizeObject( m_hBrushShadow ); + hbrOld = SelectObject( hdc, m_hBrushShadow ); + + // bottom shadow + + PatBlt(hdc, + rc.left + SHADOW_OFFSET, + rc.bottom - SHADOW_HEIGHT, + rc.right - SHADOW_OFFSET - SHADOW_WIDTH, + SHADOW_HEIGHT, + 0xA000C9); + + // right-side shadow + + PatBlt(hdc, + rc.right - SHADOW_WIDTH, + rc.top + SHADOW_OFFSET, + SHADOW_WIDTH, + rc.bottom - SHADOW_OFFSET, + 0xA000C9); + + SelectObject(hdc, hbrOld); + SetTextColor( hdc, oldTextColor ); + SetBkColor( hdc, oldBkColor ); +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +void SAL_CALL CHelpPopupWindow::onNcDestroy() +{ + m_hwnd = NULL; +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +void SAL_CALL CHelpPopupWindow::onCreate( HWND hwnd ) +{ + m_hwnd = hwnd; + + HDC hdc = GetDC( m_hwnd ); + + HGDIOBJ oldFont = SelectObject( + hdc, GetStockObject( DEFAULT_GUI_FONT ) ); + + TEXTMETRIC tm; + GetTextMetrics( hdc, &tm ); + + m_avCharWidth = tm.tmAveCharWidth; + m_avCharHeight = tm.tmHeight; + + if ( 0 == m_hMargins ) + m_hMargins = m_avCharWidth; + + if ( 0 == m_vMargins ) + m_vMargins = m_avCharHeight; + + SelectObject( hdc, oldFont ); + + ReleaseDC( m_hwnd, hdc ); +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +LRESULT CALLBACK CHelpPopupWindow::WndProc( + HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + LRESULT lResult = 0; + + switch ( uMsg ) + { + case WM_CREATE: + { + LPCREATESTRUCT lpcs = + reinterpret_cast< LPCREATESTRUCT >( lParam ); + + OSL_ASSERT( lpcs->lpCreateParams ); + + CHelpPopupWindow* pImpl = reinterpret_cast< CHelpPopupWindow* >( + lpcs->lpCreateParams ); + + // connect the instance handle to the window + SetProp( hWnd, CURRENT_INSTANCE, pImpl ); + + pImpl->onCreate( hWnd ); + + // capture mouse and keybord events + SetCapture( hWnd ); + } + break; + + case WM_PAINT: + { + CHelpPopupWindow* pImpl = reinterpret_cast< CHelpPopupWindow* >( + GetProp( hWnd, CURRENT_INSTANCE ) ); + + OSL_ASSERT( pImpl ); + + PAINTSTRUCT ps; + + BeginPaint(hWnd, &ps); + pImpl->onPaint( hWnd, ps.hdc ); + EndPaint(hWnd, &ps); + } + break; + + case WM_NCDESTROY: + { + // RemoveProp returns the saved value on success + CHelpPopupWindow* pImpl = reinterpret_cast< CHelpPopupWindow* >( + RemoveProp( hWnd, CURRENT_INSTANCE ) ); + + OSL_ASSERT( pImpl ); + + pImpl->onNcDestroy(); + } + break; + + case WM_LBUTTONDOWN: + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + ReleaseCapture(); + DestroyWindow(hWnd); + break; + + default: + return DefWindowProc(hWnd, uMsg, wParam, lParam); + } + + return lResult; +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +ATOM SAL_CALL CHelpPopupWindow::RegisterWindowClass( ) +{ + osl::MutexGuard aGuard( s_Mutex ); + + if ( 0 == s_ClassAtom ) + { + // register the window class + WNDCLASSEX wndClsEx; + + ZeroMemory(&wndClsEx, sizeof(wndClsEx)); + + wndClsEx.cbSize = sizeof(wndClsEx); + wndClsEx.lpfnWndProc = CHelpPopupWindow::WndProc; + wndClsEx.hInstance = m_hInstance; + wndClsEx.hCursor = LoadCursor(NULL, IDC_ARROW); + wndClsEx.hbrBackground = (HBRUSH)GetStockObject( NULL_BRUSH ); + wndClsEx.lpszClassName = HELPPOPUPWND_CLASS_NAME; + + // register the preview window class + // !!! Win95 - the window class will be unregistered automaticly + // if the dll is unloaded + // Win2000 - the window class must be unregistered manually + // if the dll is unloaded + s_ClassAtom = RegisterClassEx( &wndClsEx ); + OSL_ASSERT(s_ClassAtom); + } + + // increment the register class counter + // so that we keep track of the number + // of class registrations + if (0 != s_ClassAtom) + s_RegisterWndClassCount++; + + return s_ClassAtom; +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +void SAL_CALL CHelpPopupWindow::UnregisterWindowClass( ) +{ + osl::MutexGuard aGuard( s_Mutex ); + + OSL_ASSERT( ( (0 != s_ClassAtom) && (s_RegisterWndClassCount > 0)) || + ( (0 == s_ClassAtom) && (0 == s_RegisterWndClassCount) ) ); + + // update the register class counter + // and unregister the window class if + // counter drops to zero + if ( 0 != s_ClassAtom ) + { + s_RegisterWndClassCount--; + OSL_ASSERT( s_RegisterWndClassCount >= 0 ); + } + + if ( 0 == s_RegisterWndClassCount ) + { + if ( !UnregisterClass( + (LPCTSTR)MAKELONG( s_ClassAtom, 0 ), m_hInstance ) ) + { + OSL_ENSURE( false, "unregister window class failed" ); + } + + s_ClassAtom = 0; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/helppopupwindow.hxx b/fpicker/source/win32/filepicker/helppopupwindow.hxx new file mode 100644 index 000000000000..71f74ad5a055 --- /dev/null +++ b/fpicker/source/win32/filepicker/helppopupwindow.hxx @@ -0,0 +1,146 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _HELPPOPUPWINDOW_HXX_ +#define _HELPPOPUPWINDOW_HXX_ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <sal/types.h> +#include <rtl/ustring.hxx> +#include <osl/mutex.hxx> + +#define WIN32_LEAN_AND_MEAN +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +//--------------------------------------------- +// declaration +//--------------------------------------------- + +/* + A simple popup window similary to the one the + windows help (using WinHelp) creates when called + with the option HELP_CONTEXTPOPUP. + + The interface is very simple but necessary for our + needs. + The window automaticaly calculates the necessary + dimensions of the window and a appropriate show + position based on the position the client provides. + When the user click any mouse button or hits any key + the window closes itself and disappears. +*/ + +class CHelpPopupWindow +{ +public: + + /* + The client may set some parameter of the window. + When the client omits to set one or more values + a default value will be taken. + The values are in pixel. + */ + CHelpPopupWindow( + HINSTANCE hInstance, + HWND hwndParent ); + + /* + dtor + */ + ~CHelpPopupWindow( ); + + /* + The client may set the text the window is showing + on next activation. + */ + void SAL_CALL setText( const rtl::OUString& aHelpText ); + + /* + Shows the window with the text that was last set. + The posistion is the prefered position. The window + may itself show at a slightly different position + if it fits not at the prefered position. + */ + void SAL_CALL show( sal_Int32 x, sal_Int32 y ); + + HWND SAL_CALL setParent( HWND hwndNewParent ); + +private: + void SAL_CALL onPaint( HWND, HDC ); + void SAL_CALL onNcDestroy(); + void SAL_CALL onCreate( HWND ); + + POINT SAL_CALL calcUpperLeftCorner( ); + void SAL_CALL calcWindowRect( LPRECT lprect ); + + void SAL_CALL adjustWindowSize( sal_Int32*, sal_Int32* ); + void SAL_CALL adjustWindowPos( sal_Int32 x, sal_Int32 y, sal_Int32 cx, sal_Int32 cy ); + + ATOM SAL_CALL RegisterWindowClass( ); + void SAL_CALL UnregisterWindowClass( ); + + static LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); + +private: + sal_Int32 m_hMargins; + sal_Int32 m_vMargins; + sal_Int32 m_avCharWidth; + sal_Int32 m_avCharHeight; + HWND m_hwnd; + HWND m_hwndParent; + HINSTANCE m_hInstance; + sal_Bool m_bWndClassRegistered; + ::rtl::OUString m_HelpText; + HBITMAP m_hBitmapShadow; + HBRUSH m_hBrushShadow; + + // the window class has to be registered only + // once per process, so multiple instance of this class + // share the registered window class + static ATOM s_ClassAtom; + static osl::Mutex s_Mutex; + static sal_Int32 s_RegisterWndClassCount; + +// prevent copy and assignment +private: + CHelpPopupWindow( const CHelpPopupWindow& ); + CHelpPopupWindow& operator=( const CHelpPopupWindow& ); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/makefile.mk b/fpicker/source/win32/filepicker/makefile.mk new file mode 100644 index 000000000000..17e4f2609069 --- /dev/null +++ b/fpicker/source/win32/filepicker/makefile.mk @@ -0,0 +1,84 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=fpicker +TARGET=fps +#LIBTARGET=NO +ENABLE_EXCEPTIONS=TRUE +COMP1TYPELIST=$(TARGET) + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# ------------------------------------------------------------------ + +CDEFS+=-D_UNICODE +CDEFS+=-DUNICODE +#CDEFS+=-DWIN32_LEAN_AND_MEAN +#CDEFS+=-DWIN32 +CDEFS+=-U_WIN32_WINNT -D_WIN32_WINNT=0x0600 + + +# --- Resources ---------------------------------------------------- + +.IF "$(GUI)" == "WNT" +RCFILES=fps.rc +.ENDIF + +# --- Files -------------------------------------------------------- + +SLOFILES=$(SLO)$/FileOpenDlg.obj\ + $(SLO)$/FPentry.obj\ + $(SLO)$/FilePicker.obj\ + $(SLO)$/WinFileOpenImpl.obj\ + $(SLO)$/FilterContainer.obj\ + $(SLO)$/controlaccess.obj\ + $(SLO)$/dibpreview.obj\ + $(SLO)$/helppopupwindow.obj\ + $(SLO)$/controlcommand.obj\ + $(SLO)$/filepickerstate.obj\ + $(SLO)$/getfilenamewrapper.obj\ + $(SLO)$/asynceventnotifier.obj\ + $(SLO)$/previewadapter.obj\ + $(SLO)$/previewbase.obj\ + $(SLO)$/filepickereventnotification.obj\ + $(SLO)$/customcontrol.obj\ + $(SLO)$/customcontrolcontainer.obj\ + $(SLO)$/customcontrolfactory.obj\ + $(SLO)$/dialogcustomcontrols.obj\ + $(SLO)$/asyncrequests.obj\ + $(SLO)$/VistaFilePickerEventHandler.obj\ + $(SLO)$/VistaFilePickerImpl.obj\ + $(SLO)$/VistaFilePicker.obj\ + $(SLO)$/SolarMutex.obj + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/fpicker/source/win32/filepicker/platform_vista.h b/fpicker/source/win32/filepicker/platform_vista.h new file mode 100644 index 000000000000..c6fd8688bbd7 --- /dev/null +++ b/fpicker/source/win32/filepicker/platform_vista.h @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _PLATFORM_VISTA_H_ +#define _PLATFORM_VISTA_H_ + +#pragma once + +// Change these values to use different versions +#undef WINVER +#undef _WIN32_WINNT +#undef _WIN32_IE +#undef _WTL_NO_CSTRING + +#define WINVER 0x0600 +#define _WIN32_WINNT 0x0600 +#define _WIN32_IE 0x0700 +#define _WTL_NO_CSTRING + +#if defined _MSC_VER +#pragma warning(push, 1) +#include <comip.h> +#pragma warning(pop) +#endif + + +#if defined _M_IX86 + #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") +#elif defined _M_IA64 + #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"") +#elif defined _M_X64 + #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") +#else + #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") +#endif + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/platform_xp.h b/fpicker/source/win32/filepicker/platform_xp.h new file mode 100644 index 000000000000..41b034070425 --- /dev/null +++ b/fpicker/source/win32/filepicker/platform_xp.h @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _PLATFORM_XP_H_ +#define _PLATFORM_XP_H_ + +#pragma once + +// Change these values to use different versions +#undef WINVER +#undef _WIN32_WINNT +#undef _WIN32_IE +#undef _WTL_NO_CSTRING + +#define WINVER 0x0500 +#define _WIN32_WINNT 0x0500 +#define _WIN32_IE 0x0600 +#define _WTL_NO_CSTRING + +#if defined _MSC_VER + #pragma warning(push, 1) +#endif + +#include <windows.h> + +#if defined _MSC_VER + #pragma warning(pop) +#endif + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/previewadapter.cxx b/fpicker/source/win32/filepicker/previewadapter.cxx new file mode 100644 index 000000000000..407f000a7e6c --- /dev/null +++ b/fpicker/source/win32/filepicker/previewadapter.cxx @@ -0,0 +1,714 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +#include <tchar.h> +#include "previewadapter.hxx" + +#include <com/sun/star/ui/dialogs/FilePreviewImageFormats.hpp> +#include "dibpreview.hxx" +#include "../misc/WinImplHelper.hxx" + +#include <memory> +#include <stdexcept> + +//--------------------------------------------- +// +//--------------------------------------------- + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; + +//--------------------------------------------- +// An impl class to hide implementation details +// from clients +//--------------------------------------------- + +class CPreviewAdapterImpl +{ +public: + CPreviewAdapterImpl(HINSTANCE instance); + + virtual ~CPreviewAdapterImpl(); + + virtual sal_Int32 SAL_CALL getTargetColorDepth(); + + virtual sal_Int32 SAL_CALL getAvailableWidth(); + + virtual sal_Int32 SAL_CALL getAvailableHeight(); + + virtual void SAL_CALL setImage( sal_Int16 aImageFormat, const Any& aImage ) + throw (IllegalArgumentException,RuntimeException); + + virtual sal_Bool SAL_CALL setShowState(sal_Bool bShowState); + + virtual sal_Bool SAL_CALL getShowState(); + + virtual void SAL_CALL setParent(HWND parent); + + virtual HWND SAL_CALL getParent(); + + //------------------------------------- + // parent notification handler + //------------------------------------- + + virtual void SAL_CALL notifyParentShow(sal_Bool bShow); + + virtual void SAL_CALL notifyParentSizeChanged(); + + virtual void SAL_CALL notifyParentWindowPosChanged(); + +protected: + virtual void SAL_CALL calcRightMargin(); + + virtual void SAL_CALL rearrangeLayout(); + + void SAL_CALL initializeActivePreview() throw(std::runtime_error); + + HWND SAL_CALL findFileListbox() const; + +// member +protected: + HINSTANCE m_Instance; + std::auto_ptr<PreviewBase> m_Preview; + HWND m_FileDialog; + int m_RightMargin; + +//prevent copy/assignment +private: + CPreviewAdapterImpl(const CPreviewAdapterImpl&); + CPreviewAdapterImpl& operator=(const CPreviewAdapterImpl&); +}; + +//----------------------------------------- +// +//----------------------------------------- + +CPreviewAdapterImpl::CPreviewAdapterImpl(HINSTANCE instance) : + m_Instance(instance), + m_Preview(new PreviewBase()), // create dummy preview (NULL-Object pattern) + m_FileDialog(0), + m_RightMargin(0) +{ +} + +//----------------------------------------- +// +//----------------------------------------- + +CPreviewAdapterImpl::~CPreviewAdapterImpl() +{ +} + +//----------------------------------------- +// +//----------------------------------------- + +sal_Int32 SAL_CALL CPreviewAdapterImpl::getTargetColorDepth() +{ + return m_Preview->getTargetColorDepth(); +} + +//----------------------------------------- +// +//----------------------------------------- + +sal_Int32 SAL_CALL CPreviewAdapterImpl::getAvailableWidth() +{ + return m_Preview->getAvailableWidth(); +} + +//----------------------------------------- +// +//----------------------------------------- + +sal_Int32 SAL_CALL CPreviewAdapterImpl::getAvailableHeight() +{ + return m_Preview->getAvailableHeight(); +} + +//----------------------------------------- +// +//----------------------------------------- + +void SAL_CALL CPreviewAdapterImpl::setImage( sal_Int16 aImageFormat, const Any& aImage ) + throw (IllegalArgumentException,RuntimeException) +{ + m_Preview->setImage(aImageFormat,aImage); +} + +//----------------------------------------- +// +//----------------------------------------- + +sal_Bool SAL_CALL CPreviewAdapterImpl::setShowState( sal_Bool bShowState ) +{ + sal_Bool bRet = m_Preview->setShowState(bShowState); + rearrangeLayout(); + return bRet; +} + +//----------------------------------------- +// +//----------------------------------------- + +sal_Bool SAL_CALL CPreviewAdapterImpl::getShowState() +{ + return m_Preview->getShowState(); +} + +//----------------------------------------- +// +//----------------------------------------- + +void SAL_CALL CPreviewAdapterImpl::setParent(HWND parent) +{ + OSL_PRECOND(IsWindow(parent),"Invalid FileDialog handle"); + + m_FileDialog = parent; + calcRightMargin(); +} + +//----------------------------------------- +// +//----------------------------------------- + +HWND SAL_CALL CPreviewAdapterImpl::getParent() +{ + return m_FileDialog; +} + +//----------------------------------------- +// +//----------------------------------------- + +void SAL_CALL CPreviewAdapterImpl::calcRightMargin() +{ + // Calculate the right reference margin + // + // Assumtions: + // 1. This method will be called before the dialog becomes + // visible + // 2. There exist a FileListbox with the id lst1 even + // if it is not visible like under Win2000/XP + // 3. Initially this FileListbox has the appropriate size + // to fit within the FileListbox + // 4. The margin between the right edge of the FileListbox + // and the right edge of the FileDialog will be constant + // even if the size of the dialog changes + + HWND flb = GetDlgItem(m_FileDialog,lst1); + + OSL_ENSURE(IsWindow(flb),"Filelistbox not found"); + + RECT rcFlb; + GetWindowRect(flb,&rcFlb); + + RECT rcFileDlg; + GetWindowRect(m_FileDialog,&rcFileDlg); + + m_RightMargin = rcFileDlg.right - rcFlb.right; +} + +//----------------------------------------- +// +//----------------------------------------- + +void SAL_CALL CPreviewAdapterImpl::notifyParentShow(sal_Bool) +{ +} + +//----------------------------------------- +// +//----------------------------------------- + +void SAL_CALL CPreviewAdapterImpl::notifyParentSizeChanged() +{ + rearrangeLayout(); +} + +//----------------------------------------- +// +//----------------------------------------- + +void SAL_CALL CPreviewAdapterImpl::notifyParentWindowPosChanged() +{ +} + +//----------------------------------------- +// +//----------------------------------------- + +void SAL_CALL CPreviewAdapterImpl::rearrangeLayout() +{ + // try to get a handle to the filelistbox + // if there is no new-style filelistbox like + // in Win2000/XP there should be at least the + // old listbox, so we take this one + // lst1 - identifies the old-style filelistbox + // lst2 - identifies the new-style filelistbox + // see dlgs.h + HWND flb_new = findFileListbox(); + + // under Windows NT 4.0 the size of the old + // filelistbox will be used as reference for + // sizing the new filelistbox, so we have + // to change the size of it too + HWND flb_old = GetDlgItem(m_FileDialog,lst1); + + RECT rcFlbNew; + GetWindowRect(flb_new,&rcFlbNew); + + RECT rcFileDlg; + GetWindowRect(m_FileDialog,&rcFileDlg); + rcFileDlg.right -= m_RightMargin; + + // the available area for the filelistbox should be + // the left edge of the filelistbox and the right + // edge of the OK button, we take this as reference + int height = rcFlbNew.bottom - rcFlbNew.top; + int width = rcFileDlg.right - rcFlbNew.left; + + HWND prvwnd = m_Preview->getWindowHandle(); + + // we use GetWindowLong to ask for the visibility + // of the preview window because IsWindowVisible + // only returns true the specified window including + // its parent windows are visible + // this is not the case when we are called in response + // to the WM_SHOWWINDOW message, somehow the WS_VISIBLE + // style bit of the FileOpen dialog must be set after that + // message + LONG lStyle = GetWindowLong(prvwnd,GWL_STYLE); + BOOL bIsVisible = (BOOL)(lStyle & WS_VISIBLE); + + int cx = 0; + + if (IsWindow(prvwnd) && bIsVisible) + { + cx = width/2; + + // resize the filelistbox to the half of the + // available space + BOOL bRet = SetWindowPos(flb_new, + NULL, 0, 0, cx, height, + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); + + bRet = SetWindowPos(flb_old, + NULL, 0, 0, cx, height, + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); + + // get the new dimensions of the filelistbox after + // resizing and take the right,top corner as starting + // point for the preview window + GetWindowRect(flb_new,&rcFlbNew); + POINT pt = { rcFlbNew.right, rcFlbNew.top }; + ScreenToClient(m_FileDialog,&pt); + + // resize the preview window to fit within + // the available space and set the window + // to the top of the z-order else it will + // be invisible + SetWindowPos(prvwnd, + HWND_TOP, pt.x, pt.y, cx, height, SWP_NOACTIVATE); + } + else + { + // resize the filelistbox to the maximum available + // space + cx = rcFileDlg.right - rcFlbNew.left; + + // resize the old filelistbox + SetWindowPos(flb_old, + NULL, 0, 0, cx, height, + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); + + // resize the new filelistbox + SetWindowPos(flb_new, + NULL, 0, 0, cx, height, + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); + } +} + +//----------------------------------------- +// +//----------------------------------------- + +void SAL_CALL CPreviewAdapterImpl::initializeActivePreview() throw(std::runtime_error) +{ + sal_Bool bShowState = m_Preview->getImaginaryShowState(); + + sal_Int16 aImgFrmt; + Any aImg; + m_Preview->getImage(aImgFrmt,aImg); + + HWND flb = findFileListbox(); + + PreviewBase* prv = new CDIBPreview( + m_Instance, GetParent(flb), bShowState); + + m_Preview.reset(prv); + + m_Preview->setImage(aImgFrmt,aImg); +} + +//----------------------------------------- +// +//----------------------------------------- + +HWND SAL_CALL CPreviewAdapterImpl::findFileListbox() const +{ + // try to get a handle to the filelistbox + // if there is no new-style filelistbox like + // in Win2000/XP there should be at least the + // old listbox, so we take this one + // lst1 - identifies the old-style filelistbox + // lst2 - identifies the new-style filelistbox + // see dlgs.h + HWND flb = GetDlgItem(m_FileDialog,lst2); + if (!IsWindow(flb)) + flb = GetDlgItem(m_FileDialog,lst1); + + return flb; +} + + +//############################################################## + + +//----------------------------------------- +// Special implementation for Win98 +// because: +// +//----------------------------------------- + +class CWin98PreviewAdapterImpl : public CPreviewAdapterImpl +{ +public: + CWin98PreviewAdapterImpl(HINSTANCE instance); + + virtual void SAL_CALL notifyParentWindowPosChanged(); + +protected: + virtual void SAL_CALL rearrangeLayout(); + + bool isValidToolbarDimension() const; + +private: + sal_Bool m_PreviewActive; + int m_ToolbarPosX; + int m_ToolbarPosY; + int m_ToolbarWidth; + int m_ToolbarHeight; +}; + +//-------------------------------------------- +// +//-------------------------------------------- + +CWin98PreviewAdapterImpl::CWin98PreviewAdapterImpl(HINSTANCE instance) : + CPreviewAdapterImpl(instance), + m_PreviewActive(sal_False), + m_ToolbarPosX(0), + m_ToolbarPosY(0), + m_ToolbarWidth(0), + m_ToolbarHeight(0) +{ +} + +//-------------------------------------------- +// +//-------------------------------------------- + +void SAL_CALL CWin98PreviewAdapterImpl::notifyParentWindowPosChanged() +{ + try + { + // the reason for this condition is + // Windows 98 + // Under Windows 98 the message WM_SHOWWINDOW + // will be sent only the first time the + // GetOpenFileName function is called within + // the same process + // so we must use another message to initialize + // the preview window + if (IsWindow(m_FileDialog) && !m_PreviewActive) + { + initializeActivePreview(); + m_PreviewActive = sal_True; + rearrangeLayout(); + } + + if (IsWindow(m_FileDialog) && !isValidToolbarDimension()) + { + RECT rcStc1; + GetWindowRect(GetDlgItem(m_FileDialog,stc1),&rcStc1); + + RECT rcCmb2; + GetWindowRect(GetDlgItem(m_FileDialog,cmb2),&rcCmb2); + + // Assumption: + // the toolbar position is only valid + // if the left edge is greater or equal + // than the right edge of the drives listbox + // the stc1 static text is invisible at runtime + // but will be used as reference for the position + // and dimension of the toolbar + if (rcStc1.left >= rcCmb2.right) + { + // important: save the upper left corner in + // client coordinates + POINT pt = {rcStc1.left,rcStc1.top}; + ScreenToClient(m_FileDialog,&pt); + + m_ToolbarPosX = pt.x; + m_ToolbarPosY = pt.y; + m_ToolbarWidth = rcStc1.right - rcStc1.left; + m_ToolbarHeight = rcStc1.bottom - rcStc1.top; + } + } + } + catch(std::runtime_error&) + { + } +} + +//-------------------------------------------- +// +//-------------------------------------------- + +void SAL_CALL CWin98PreviewAdapterImpl::rearrangeLayout() +{ + CPreviewAdapterImpl::rearrangeLayout(); + + // fix the position of the upper toolbar + // because the FileDialog moves all windows + // that are to the right of the FileListbox + // so if we have changed the size of the + // FileListbox we would run into trouble else + if (isValidToolbarDimension()) + { + HWND hwndTlb = FindWindowEx( + m_FileDialog,NULL,TEXT("ToolbarWindow32"),NULL); + + SetWindowPos(hwndTlb, + HWND_TOP, + m_ToolbarPosX, + m_ToolbarPosY, + m_ToolbarWidth, + m_ToolbarHeight, + SWP_NOACTIVATE); + } +} + +//-------------------------------------------- +// +//-------------------------------------------- + +bool CWin98PreviewAdapterImpl::isValidToolbarDimension() const +{ + return (m_ToolbarPosX > 0 && + m_ToolbarPosY > 0 && + m_ToolbarWidth > 0 && + m_ToolbarHeight > 0); +} + +//############################################################## + + +//-------------------------------------------- +// Implementation for Windows 95/NT/ME/2000/XP +// because: +// +//-------------------------------------------- + +class CWin95NTPreviewAdapterImpl : public CPreviewAdapterImpl +{ +public: + CWin95NTPreviewAdapterImpl(HINSTANCE instance); + + virtual void SAL_CALL notifyParentShow(sal_Bool bShow); +}; + +//-------------------------------------------- +// +//-------------------------------------------- + +CWin95NTPreviewAdapterImpl::CWin95NTPreviewAdapterImpl(HINSTANCE instance) : + CPreviewAdapterImpl(instance) +{ +} + +//-------------------------------------------- +// +//-------------------------------------------- + +void SAL_CALL CWin95NTPreviewAdapterImpl::notifyParentShow(sal_Bool bShow) +{ + try + { + if (bShow) + { + initializeActivePreview(); + rearrangeLayout(); + } + } + catch(std::runtime_error&) + { + } +} + + +//############################################################## + + +//------------------------------- +// ctor +//------------------------------- + +CPreviewAdapter::CPreviewAdapter(HINSTANCE instance) +{ + if (!IsWindows98()) + m_pImpl.reset(new CWin95NTPreviewAdapterImpl(instance)); + else + m_pImpl.reset(new CWin98PreviewAdapterImpl(instance)); +} + +//------------------------------- +// +//------------------------------- + +CPreviewAdapter::~CPreviewAdapter() +{ +} + +//------------------------------- +// +//------------------------------- + +Sequence<sal_Int16> SAL_CALL CPreviewAdapter::getSupportedImageFormats() +{ + com::sun::star::uno::Sequence<sal_Int16> imgFormats(1); + imgFormats[0] = ::com::sun::star::ui::dialogs::FilePreviewImageFormats::BITMAP; + return imgFormats; +} + +//------------------------------- +// +//------------------------------- + +sal_Int32 SAL_CALL CPreviewAdapter::getTargetColorDepth() +{ + return m_pImpl->getTargetColorDepth(); +} + +//------------------------------- +// +//------------------------------- + +sal_Int32 SAL_CALL CPreviewAdapter::getAvailableWidth() +{ + return m_pImpl->getAvailableWidth(); +} + +//------------------------------- +// +//------------------------------- + +sal_Int32 SAL_CALL CPreviewAdapter::getAvailableHeight() +{ + return m_pImpl->getAvailableHeight(); +} + +//------------------------------- +// +//------------------------------- + +void SAL_CALL CPreviewAdapter::setImage( sal_Int16 aImageFormat, const Any& aImage ) + throw (IllegalArgumentException, RuntimeException) +{ + m_pImpl->setImage(aImageFormat,aImage); +} + +//------------------------------- +// +//------------------------------- + +sal_Bool SAL_CALL CPreviewAdapter::setShowState( sal_Bool bShowState ) +{ + return m_pImpl->setShowState(bShowState); +} + +//------------------------------- +// +//------------------------------- + +sal_Bool SAL_CALL CPreviewAdapter::getShowState() +{ + return m_pImpl->getShowState(); +} + +//------------------------------- +// +//------------------------------- + +void SAL_CALL CPreviewAdapter::setParent(HWND parent) +{ + m_pImpl->setParent(parent); +} + +//------------------------------- +// +//------------------------------- + +void SAL_CALL CPreviewAdapter::notifyParentShow(bool bShow) +{ + m_pImpl->notifyParentShow(bShow); +} + +//------------------------------- +// +//------------------------------- + +void SAL_CALL CPreviewAdapter::notifyParentSizeChanged() +{ + m_pImpl->notifyParentSizeChanged(); +} + +//------------------------------- +// +//------------------------------- + +void SAL_CALL CPreviewAdapter::notifyParentWindowPosChanged() +{ + m_pImpl->notifyParentWindowPosChanged(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/previewadapter.hxx b/fpicker/source/win32/filepicker/previewadapter.hxx new file mode 100644 index 000000000000..0efc2e60245a --- /dev/null +++ b/fpicker/source/win32/filepicker/previewadapter.hxx @@ -0,0 +1,110 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _PREVIEWADAPTER_HXX_ +#define _PREVIEWADAPTER_HXX_ + +#include <sal/types.h> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/uno/Any.hxx> + +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif +#include <memory> + +// forward declaration +class CPreviewAdapterImpl; + +//--------------------------------------------- +// A kind of a facade for the preview class. +// We want to hide the fact that the preview +// window may only become visible if there is +// a valid parent window (means, the FilePicker) +// is in execution mode. So unless someone sets +// the preview active with a valid parent +// window the preview may not be visible +//--------------------------------------------- + +class CPreviewAdapter +{ +public: + + // ctor + CPreviewAdapter(HINSTANCE instance); + + ~CPreviewAdapter(); + + ::com::sun::star::uno::Sequence<sal_Int16> SAL_CALL getSupportedImageFormats(); + + sal_Int32 SAL_CALL getTargetColorDepth(); + + sal_Int32 SAL_CALL getAvailableWidth(); + + sal_Int32 SAL_CALL getAvailableHeight(); + + void SAL_CALL setImage(sal_Int16 aImageFormat, const ::com::sun::star::uno::Any& aImage) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + sal_Bool SAL_CALL setShowState(sal_Bool bShowState); + + sal_Bool SAL_CALL getShowState(); + + void SAL_CALL setParent(HWND parent); + + //-------------------------------------- + // notification from parent + //-------------------------------------- + + void SAL_CALL notifyParentShow(bool bShow); + + void SAL_CALL notifyParentSizeChanged(); + + void SAL_CALL notifyParentWindowPosChanged(); + +private: + // hide implementation details using the + // bridge pattern + std::auto_ptr<CPreviewAdapterImpl> m_pImpl; + +// prevent copy and assignment +private: + CPreviewAdapter(const CPreviewAdapter&); + CPreviewAdapter& operator=(const CPreviewAdapter&); +}; + + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/previewbase.cxx b/fpicker/source/win32/filepicker/previewbase.cxx new file mode 100644 index 000000000000..2c26ad2750e6 --- /dev/null +++ b/fpicker/source/win32/filepicker/previewbase.cxx @@ -0,0 +1,151 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" +#include "previewbase.hxx" + +#include <com/sun/star/ui/dialogs/FilePreviewImageFormats.hpp> + +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace rtl; + +//------------------------------- +// +//------------------------------- + +PreviewBase::PreviewBase() : + m_ImageFormat(::com::sun::star::ui::dialogs::FilePreviewImageFormats::BITMAP), + m_bShowState(sal_False) +{ +} + +//------------------------------- +// +//------------------------------- + +PreviewBase::~PreviewBase() +{ +} + +//------------------------------- +// +//------------------------------- + +sal_Int32 SAL_CALL PreviewBase::getTargetColorDepth() throw (RuntimeException) +{ + return 0; +} + +//------------------------------- +// +//------------------------------- + +sal_Int32 SAL_CALL PreviewBase::getAvailableWidth() throw (RuntimeException) +{ + return 0; +} + +//------------------------------- +// +//------------------------------- + +sal_Int32 SAL_CALL PreviewBase::getAvailableHeight() throw (RuntimeException) +{ + return 0; +} + +//------------------------------- +// +//------------------------------- + +void SAL_CALL PreviewBase::setImage( sal_Int16 aImageFormat, const ::com::sun::star::uno::Any& aImage ) + throw (IllegalArgumentException, RuntimeException) +{ + if (aImageFormat != ::com::sun::star::ui::dialogs::FilePreviewImageFormats::BITMAP) + throw IllegalArgumentException( + OUString(RTL_CONSTASCII_USTRINGPARAM("unsupported image format")), 0, 1); + + if (aImage.hasValue() && (aImage.getValueType() != getCppuType((Sequence<sal_Int8>*)0))) + throw IllegalArgumentException( + OUString(RTL_CONSTASCII_USTRINGPARAM("invalid image data")), 0, 2); + + // save the new image data and force a redraw + m_ImageData = aImage; + m_ImageFormat = aImageFormat; +} + +//------------------------------- +// +//------------------------------- + +void SAL_CALL PreviewBase::getImage(sal_Int16& aImageFormat,com::sun::star::uno::Any& aImage) +{ + aImageFormat = m_ImageFormat; + aImage = m_ImageData; +} + +//------------------------------- +// +//------------------------------- + +sal_Bool SAL_CALL PreviewBase::setShowState( sal_Bool bShowState ) throw (RuntimeException) +{ + m_bShowState = bShowState; + return sal_True; +} + +//------------------------------- +// +//------------------------------- + +sal_Bool SAL_CALL PreviewBase::getShowState() throw (RuntimeException) +{ + return sal_False; +} + +//------------------------------- +// +//------------------------------- + +sal_Bool SAL_CALL PreviewBase::getImaginaryShowState() const +{ + return m_bShowState; +} + +//------------------------------- +// +//------------------------------- + +HWND SAL_CALL PreviewBase::getWindowHandle() const +{ + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/previewbase.hxx b/fpicker/source/win32/filepicker/previewbase.hxx new file mode 100644 index 000000000000..d4b36a618c7f --- /dev/null +++ b/fpicker/source/win32/filepicker/previewbase.hxx @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _PREVIEWBASE_HXX_ +#define _PREVIEWBASE_HXX_ + +#include <sal/types.h> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/uno/Any.hxx> + +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +//--------------------------------------------- +// Common interface for previews +//--------------------------------------------- + +class PreviewBase +{ +public: + PreviewBase(); + + // dtor + virtual ~PreviewBase(); + + virtual sal_Int32 SAL_CALL getTargetColorDepth() + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL getAvailableWidth() + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL getAvailableHeight() + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL setImage( sal_Int16 aImageFormat, const ::com::sun::star::uno::Any& aImage ) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL setShowState( sal_Bool bShowState ) + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL getShowState() + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL getImage(sal_Int16& aImageFormat,com::sun::star::uno::Any& aImage); + + sal_Bool SAL_CALL getImaginaryShowState() const; + + virtual HWND SAL_CALL getWindowHandle() const; + +protected: + ::com::sun::star::uno::Any m_ImageData; + sal_Int16 m_ImageFormat; + sal_Bool m_bShowState; +}; + + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/propmap.hxx b/fpicker/source/win32/filepicker/propmap.hxx new file mode 100644 index 000000000000..a37cfefd0fcd --- /dev/null +++ b/fpicker/source/win32/filepicker/propmap.hxx @@ -0,0 +1,104 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _PROPMAP_HXX_ +#define _PROPMAP_HXX_ + +#include <hash_map> +#include <rtl/ustring.hxx> +#include <sal/types.h> + +typedef ::std::hash_map< ::rtl::OUString , + void* , + ::rtl::OUStringHash , + ::std::equal_to< ::rtl::OUString > > TPropMapBase; + +class TPropMap +{ + private: + + TPropMapBase m_aMap; + + public: + + template< class TValueType > + void put(const ::rtl::OUString& sKey , + const TValueType& rValue) + { + void* pValue = (void*)&rValue; + m_aMap[sKey] = pValue; + } + + template< class TValueType > + void put_copy(const ::rtl::OUString& sKey , + const TValueType& rValue) + { + TValueType* pCopy = new TValueType(rValue); + m_aMap[sKey] = (void*)pCopy; + } + + template< class TValueType > + sal_Bool get(const ::rtl::OUString& sKey , + TValueType** pValue) + { + TPropMapBase::iterator pIt = m_aMap.find(sKey); + if (pIt == m_aMap.end()) + return sal_False; + + void* pItem = pIt->second; + *pValue = (TValueType*)pItem; + return (pItem != 0); + } + + template< class TValueType > + sal_Bool get_copy(const ::rtl::OUString& sKey , + TValueType& rValue) + { + TPropMapBase::iterator pIt = m_aMap.find(sKey); + if (pIt == m_aMap.end()) + return sal_False; + + void* pValue = pIt->second; + if ( ! pValue) + return sal_False; + + rValue = *((TValueType*)pValue); + //delete pValue; + m_aMap.erase(pIt); + return sal_True; + } + + void clear() + { + m_aMap.clear(); + } +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/resource.h b/fpicker/source/win32/filepicker/resource.h new file mode 100644 index 000000000000..f99ffe34cf5a --- /dev/null +++ b/fpicker/source/win32/filepicker/resource.h @@ -0,0 +1,24 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Fps.rc +// +#define IDD_DIALOG1 101 +#define IDB_BITMAP1 117 +#define IDB_BITMAP2 118 +#define IDC_BUTTON1 1008 +#define stc32 -1 +#define IDC_STATIC -1 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 119 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1014 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/shared.hxx b/fpicker/source/win32/filepicker/shared.hxx new file mode 100644 index 000000000000..38580770515a --- /dev/null +++ b/fpicker/source/win32/filepicker/shared.hxx @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FPICKER_WIN32_FILEPICKER_SHARED_HXX +#define FPICKER_WIN32_FILEPICKER_SHARED_HXX + +#include <rtl/ustring.hxx> + +const ::rtl::OUString BACKSLASH(RTL_CONSTASCII_USTRINGPARAM( "\\" )); +const ::rtl::OUString FILTER_SEPARATOR(RTL_CONSTASCII_USTRINGPARAM( "------------------------------------------" )); +const ::rtl::OUString ALL_FILES_WILDCARD(RTL_CONSTASCII_USTRINGPARAM( "*.*" )); +const ::sal_Bool ALLOW_DUPLICATES = sal_True; + +#endif +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/vistatypes.h b/fpicker/source/win32/filepicker/vistatypes.h new file mode 100644 index 000000000000..08b4613f6d25 --- /dev/null +++ b/fpicker/source/win32/filepicker/vistatypes.h @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FPICKER_WIN32_VISTA_TYPES_HXX +#define FPICKER_WIN32_VISTA_TYPES_HXX + +//----------------------------------------------------------------------------- +// includes +//----------------------------------------------------------------------------- + +#include "comptr.hxx" +#include <shobjidl.h> + +//----------------------------------------------------------------------------- +// namespace +//----------------------------------------------------------------------------- + +#ifdef css + #error "Clash on using CSS as namespace define." +#else + #define css ::com::sun::star +#endif + +namespace fpicker{ +namespace win32{ +namespace vista{ + +//----------------------------------------------------------------------------- +// types, const etcpp. +//----------------------------------------------------------------------------- + +typedef ComPtr< IFileDialog , IID_IFileDialog > TFileDialog; +typedef ComPtr< IFileOpenDialog , IID_IFileOpenDialog , CLSID_FileOpenDialog > TFileOpenDialog; +typedef ComPtr< IFileSaveDialog , IID_IFileSaveDialog , CLSID_FileSaveDialog > TFileSaveDialog; +typedef ComPtr< IFileDialogEvents , IID_IFileDialogEvents > TFileDialogEvents; +typedef ComPtr< IFileDialogCustomize, IID_IFileDialogCustomize > TFileDialogCustomize; + +} // namespace vista +} // namespace win32 +} // namespace fpicker + +#undef css + +#endif // FPICKER_WIN32_VISTA_TYPES_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/workbench/Test_fps.cxx b/fpicker/source/win32/filepicker/workbench/Test_fps.cxx new file mode 100644 index 000000000000..a0d3aa974a0b --- /dev/null +++ b/fpicker/source/win32/filepicker/workbench/Test_fps.cxx @@ -0,0 +1,388 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + + +//_________________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________________ +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/registry/XSimpleRegistry.hpp> +#include <osl/file.hxx> + +//_________________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________________ +#include <cppuhelper/servicefactory.hxx> + +#ifndef _RTL_USTRING_ +#include <rtl/ustring.hxx> +#endif +#include <sal/types.h> +#include <osl/diagnose.h> +#include <com/sun/star/ui/dialogs/XFilePicker.hpp> +#include <com/sun/star/ui/dialogs/XFilterManager.hpp> + +#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> +#include <cppuhelper/implbase1.hxx> +#include <com/sun/star/ui/dialogs/XFilePickerListener.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerNotifier.hpp> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/ListboxControlActions.hpp> +#include <com/sun/star/ui/dialogs/XFilePreview.hpp> + +#include <osl/thread.h> + +#include <stdio.h> +#include <windows.h> + +#include "..\FPServiceInfo.hxx" + +// +// namesapces +// + +using namespace ::rtl ; +using namespace ::cppu ; +using namespace ::com::sun::star::uno ; +using namespace ::com::sun::star::lang ; +using namespace ::com::sun::star::ui::dialogs ; +using namespace ::com::sun::star::ui::dialogs::TemplateDescription; + +using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds; +using namespace ::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds; +using namespace ::com::sun::star::ui::dialogs::ListboxControlActions; + +using namespace std ; + +// forward + +void TestFilterManager( Reference< XFilePicker > xFilePicker ); + + +#define RDB_SYSPATH "D:\\Projects\\gsl\\sysui\\wntmsci7\\bin\\applicat.rdb" + +//_________________________________________________________________________________________________________________________ +// global variables +//_________________________________________________________________________________________________________________________ + +Reference< XMultiServiceFactory > g_xFactory; + +const OUString BMP_EXTENSION(RTL_CONSTASCII_USTRINGPARAM( "bmp" )); + +//------------------------------------------------------------------------------------------------------------------------- +// a test client +//------------------------------------------------------------------------------------------------------------------------- + +class FilePickerListener : public WeakImplHelper1< XFilePickerListener > +{ +public: + + // XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) + throw(::com::sun::star::uno::RuntimeException); + + // XFilePickerListener + virtual void SAL_CALL fileSelectionChanged( const ::com::sun::star::ui::dialogs::FilePickerEvent& aEvent ) + throw(::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL directoryChanged( const ::com::sun::star::ui::dialogs::FilePickerEvent& aEvent ) + throw(::com::sun::star::uno::RuntimeException); + + virtual OUString SAL_CALL helpRequested( const ::com::sun::star::ui::dialogs::FilePickerEvent& aEvent ) + throw(::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL controlStateChanged( const ::com::sun::star::ui::dialogs::FilePickerEvent& aEvent ) + throw(::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL dialogSizeChanged( ) + throw (::com::sun::star::uno::RuntimeException); +}; + +void SAL_CALL FilePickerListener::disposing( const ::com::sun::star::lang::EventObject& Source ) + throw(::com::sun::star::uno::RuntimeException) +{ +} + +void SAL_CALL FilePickerListener::fileSelectionChanged( const ::com::sun::star::ui::dialogs::FilePickerEvent& aEvent ) + throw(::com::sun::star::uno::RuntimeException) +{ + try + { + Reference< XFilePicker > rXFilePicker( aEvent.Source, UNO_QUERY ); + Reference< XFilePreview > rXFilePreview( rXFilePicker, UNO_QUERY ); + + if ( !rXFilePreview.is( ) ) + return; + + Sequence< OUString > aFileList = rXFilePicker->getFiles( ); + if ( 1 == aFileList.getLength( ) ) + { + OUString FilePath = aFileList[0]; + + // detect file extension + sal_Int32 nIndex = FilePath.lastIndexOf( BMP_EXTENSION ); + if ( (FilePath.getLength( ) - 3) == nIndex ) + { + OUString FileSysPath; + ::osl::FileBase::getSystemPathFromFileURL( + FilePath, FileSysPath ); + + HANDLE hFile = CreateFileW( + FileSysPath.getStr( ), + GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL) ; + + if (hFile == INVALID_HANDLE_VALUE) + return; + + DWORD dwHighSize; + DWORD dwFileSize = GetFileSize (hFile, &dwHighSize) ; + + if (dwHighSize) + { + CloseHandle (hFile) ; + return; + } + + Sequence< sal_Int8 > aDIB( dwFileSize ); + + DWORD dwBytesRead; + BOOL bSuccess = ReadFile (hFile, aDIB.getArray( ), dwFileSize, &dwBytesRead, NULL) ; + CloseHandle (hFile); + + BITMAPFILEHEADER* pbmfh = (BITMAPFILEHEADER*)aDIB.getConstArray( ); + if (!bSuccess || (dwBytesRead != dwFileSize) + || (pbmfh->bfType != * (WORD *) "BM") + || (pbmfh->bfSize != dwFileSize)) + { + return; + } + + Any aAny; + + aAny <<= aDIB; + rXFilePreview->setImage( 1, aAny ); + } + } + } + catch( IllegalArgumentException& ex ) + { + ex = ex; + } +} + +void SAL_CALL FilePickerListener::directoryChanged( const ::com::sun::star::ui::dialogs::FilePickerEvent& aEvent ) + throw(::com::sun::star::uno::RuntimeException) +{ + Reference< XFilePickerControlAccess > rFilePickerCtrlAccess( aEvent.Source, UNO_QUERY ); +} + +OUString SAL_CALL FilePickerListener::helpRequested( const ::com::sun::star::ui::dialogs::FilePickerEvent& aEvent ) + throw(::com::sun::star::uno::RuntimeException) +{ + return OUString( ); +} + +void SAL_CALL FilePickerListener::controlStateChanged( const ::com::sun::star::ui::dialogs::FilePickerEvent& aEvent ) + throw(::com::sun::star::uno::RuntimeException) +{ + try + { + Reference< XFilePickerControlAccess > rFPCtrlAccess( aEvent.Source, UNO_QUERY ); + + Any aValue; + + OUString lbString( L"Ein Eintrag 1" ); + aValue <<= lbString; + rFPCtrlAccess->setValue( LISTBOX_VERSION, ADD_ITEM, aValue ); + + lbString = OUString( L"Ein Eintrag 2" ); + aValue <<= lbString; + rFPCtrlAccess->setValue( LISTBOX_VERSION, ADD_ITEM, aValue ); + + lbString = OUString( L"Ein Eintrag 3" ); + aValue <<= lbString; + rFPCtrlAccess->setValue( LISTBOX_VERSION, ADD_ITEM, aValue ); + + sal_Int16 nSel = 1; + aValue <<= nSel; + rFPCtrlAccess->setValue( LISTBOX_VERSION, SET_SELECT_ITEM, aValue ); + + sal_Int32 nDel = 0; + aValue <<= nDel; + rFPCtrlAccess->setValue( LISTBOX_VERSION, DELETE_ITEM, aValue ); + } + catch( ... ) + { + } +} + +void SAL_CALL FilePickerListener::dialogSizeChanged( ) + throw(::com::sun::star::uno::RuntimeException) +{ +} + +//-------------------------------------------------------- +// main +//-------------------------------------------------------- + + +int SAL_CALL main(int nArgc, char* Argv[], char* Env[] ) +{ + printf("Starting test of FPS-Service\n"); + + //------------------------------------------------- + // get the global service-manager + //------------------------------------------------- + + // Get global factory for uno services. + OUString rdbName = OUString( RTL_CONSTASCII_USTRINGPARAM( RDB_SYSPATH ) ); + Reference< XMultiServiceFactory > g_xFactory( createRegistryServiceFactory( rdbName ) ); + + // Print a message if an error occured. + if ( g_xFactory.is() == sal_False ) + { + OSL_ENSURE(sal_False, "Can't create RegistryServiceFactory"); + return(-1); + } + + //------------------------------------------------- + // try to get an Interface to a XFilePicker Service + //------------------------------------------------- + + Sequence< Any > arguments(1); + //arguments[0] = makeAny( FILEOPEN_SIMPLE ); + //arguments[0] = makeAny( FILESAVE_SIMPLE ); + //arguments[0] = makeAny( FILESAVE_AUTOEXTENSION_PASSWORD ); + //arguments[0] = makeAny( FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS ); + //arguments[0] = makeAny( FILESAVE_AUTOEXTENSION_SELECTION ); + //arguments[0] = makeAny( FILESAVE_AUTOEXTENSION_TEMPLATE ); + //arguments[0] = makeAny( FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE ); + //arguments[0] = makeAny( FILEOPEN_PLAY ); + arguments[0] = makeAny( FILEOPEN_READONLY_VERSION ); + + Reference< XFilePicker > xFilePicker = Reference< XFilePicker >( + g_xFactory->createInstanceWithArguments( + OUString(RTL_CONSTASCII_USTRINGPARAM( FILE_PICKER_SERVICE_NAME )), arguments ), UNO_QUERY ); + + // install a FilePicker notifier + Reference< XFilePickerListener > xFPListener( + static_cast< XFilePickerListener* >( new FilePickerListener()), UNO_QUERY ); + + Reference< XFilePickerNotifier > xFPNotifier( xFilePicker, UNO_QUERY ); + if ( xFPNotifier.is( ) ) + xFPNotifier->addFilePickerListener( xFPListener ); + + xFilePicker->setTitle( OUString(RTL_CONSTASCII_USTRINGPARAM("FileOpen Simple..."))); + xFilePicker->setMultiSelectionMode( sal_True ); + xFilePicker->setDefaultName( OUString(RTL_CONSTASCII_USTRINGPARAM("d:\\test2.sxw"))); + + OUString aDirURL; + OUString aSysPath = OStringToOUString( "d:\\ueaeoe", osl_getThreadTextEncoding( ) ); + ::osl::FileBase::getFileURLFromSystemPath( aSysPath, aDirURL ); + xFilePicker->setDisplayDirectory( aDirURL ); + + Reference< XFilterManager > xFilterMgr( xFilePicker, UNO_QUERY ); + if ( xFilterMgr.is( ) ) + { + xFilterMgr->appendFilter( L"Alle", L"*.*" ); + xFilterMgr->appendFilter( L"BMP", L"*.bmp" ); + xFilterMgr->appendFilter( L"SDW", L"*.sdw;*.sdc;*.sdi" ); + xFilterMgr->appendFilter( L"SXW", L"*.sxw;*.sxi" ); + } + + Reference< XFilePickerControlAccess > xFPControlAccess( xFilePicker, UNO_QUERY ); + + Any aAny; + sal_Bool bChkState = sal_False; + + aAny.setValue( &bChkState, getCppuType( (sal_Bool*)0 ) ); + xFPControlAccess->setValue( CHECKBOX_AUTOEXTENSION, 0, aAny ); + + OUString aVersion( L"Version 1" ); + aAny <<= aVersion; + xFPControlAccess->setValue( LISTBOX_VERSION, ADD_ITEM, aAny ); + xFPControlAccess->setValue( LISTBOX_VERSION, ADD_ITEM, aAny ); + xFPControlAccess->setValue( LISTBOX_VERSION, ADD_ITEM, aAny ); + + xFilePicker->execute( ); + + sal_Bool bCheckState; + aAny = xFPControlAccess->getValue( CHECKBOX_AUTOEXTENSION, 0 ); + if ( aAny.hasValue( ) ) + bCheckState = *reinterpret_cast< const sal_Bool* >( aAny.getValue( ) ); + + aAny = xFPControlAccess->getValue( CHECKBOX_READONLY, 0 ); + if ( aAny.hasValue( ) ) + bCheckState = *reinterpret_cast< const sal_Bool* >( aAny.getValue( ) ); + + aAny = xFPControlAccess->getValue( LISTBOX_VERSION, GET_SELECTED_ITEM ); + sal_Int32 nSel; + if ( aAny.hasValue( ) ) + aAny >>= nSel; + + aDirURL = xFilePicker->getDisplayDirectory( ); + Sequence< OUString > aFileList = xFilePicker->getFiles( ); + for ( int i = 0; i < aFileList.getLength( ); i++ ) + { + OUString nextPath = aFileList[i]; + } + + if ( xFPNotifier.is( ) ) + xFPNotifier->removeFilePickerListener( xFPListener ); + + //-------------------------------------------------- + // shutdown + //-------------------------------------------------- + + // Cast factory to XComponent + Reference< XComponent > xComponent( g_xFactory, UNO_QUERY ); + + // Print a message if an error occured. + if ( xComponent.is() == sal_False ) + { + OSL_ENSURE(sal_False, "Error shuting down"); + } + + // Dispose and clear factory + xComponent->dispose(); + g_xFactory.clear(); + g_xFactory = Reference< XMultiServiceFactory >(); + + printf("Test successful\n"); + + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/filepicker/workbench/makefile.mk b/fpicker/source/win32/filepicker/workbench/makefile.mk new file mode 100644 index 000000000000..926e2c22a0ed --- /dev/null +++ b/fpicker/source/win32/filepicker/workbench/makefile.mk @@ -0,0 +1,62 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/..$/.. + +PRJNAME=sysui +TARGET=testfps +LIBTARGET=NO +TARGETTYPE=CUI + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +CFLAGS+=-GR -GX + +# --- Files -------------------------------------------------------- + + +OBJFILES=$(OBJ)$/test_fps.obj + +APP1TARGET=$(TARGET) +APP1OBJS=$(OBJFILES) + +APP1STDLIBS+=\ + $(CPPULIB)\ + $(CPPUHELPERLIB)\ + $(SALLIB)\ + $(USER32LIB)\ + $(OLE32LIB) + +APP1DEF=$(MISC)$/$(APP1TARGET).def + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + + diff --git a/fpicker/source/win32/folderpicker/FOPServiceInfo.hxx b/fpicker/source/win32/folderpicker/FOPServiceInfo.hxx new file mode 100644 index 000000000000..0f1dd0c0eeb4 --- /dev/null +++ b/fpicker/source/win32/folderpicker/FOPServiceInfo.hxx @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _FOPSERVICEINFO_HXX_ +#define _FOPSERVICEINFO_HXX_ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +//------------------------------------------------------------------------ +// defines +//------------------------------------------------------------------------ + +// the service name is a description of a set of +// interfaces (is the same as component categories in COM) + +// the service names +#define FOLDER_PICKER_SERVICE_NAME "com.sun.star.ui.dialogs.SystemFolderPicker" + +// the implementation names +#define FOLDER_PICKER_IMPL_NAME "com.sun.star.ui.dialogs.Win32FolderPicker" + +// the registry key names +// a key under which this service will be registered, Format: -> "/ImplName/UNO/SERVICES/ServiceName" +// < Implementation-Name ></UNO/SERVICES/>< Service-Name > +#define FOLDER_PICKER_REGKEY_NAME "/com.sun.star.ui.dialogs.Win32FolderPicker/UNO/SERVICES/com.sun.star.ui.dialogs.SystemFolderPicker" + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/folderpicker/FolderPicker.cxx b/fpicker/source/win32/folderpicker/FolderPicker.cxx new file mode 100644 index 000000000000..5483b7d78ee9 --- /dev/null +++ b/fpicker/source/win32/folderpicker/FolderPicker.cxx @@ -0,0 +1,219 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ +#include <osl/diagnose.h> + +#include "folderpicker.hxx" +#include <com/sun/star/lang/DisposedException.hpp> +#include "WinFOPImpl.hxx" + +//------------------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------------------ + +using com::sun::star::uno::Reference; +using com::sun::star::uno::RuntimeException; +using com::sun::star::uno::Sequence; +using com::sun::star::uno::XInterface; +using com::sun::star::lang::XMultiServiceFactory; +using com::sun::star::lang::XServiceInfo; +using com::sun::star::lang::DisposedException; +using com::sun::star::lang::IllegalArgumentException; +using rtl::OUString; +using osl::MutexGuard; + +using namespace cppu; +using namespace com::sun::star::ui::dialogs; + +//------------------------------------------------------------------------ +// defines +//------------------------------------------------------------------------ + +#define FOLDERPICKER_IMPL_NAME "com.sun.star.ui.dialogs.Win32FolderPicker" + +//------------------------------------------------------------------------ +// helper functions +//------------------------------------------------------------------------ + +namespace +{ + Sequence< OUString > SAL_CALL FolderPicker_getSupportedServiceNames() + { + Sequence< OUString > aRet(1); + aRet[0] = OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ui.dialogs.SystemFolderPicker")); + return aRet; + } +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +CFolderPicker::CFolderPicker( const Reference< XMultiServiceFactory >& xServiceMgr ) : + m_xServiceMgr( xServiceMgr ) +{ + m_pFolderPickerImpl = std::auto_ptr< CWinFolderPickerImpl > ( new CWinFolderPickerImpl( this ) ); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL CFolderPicker::setTitle( const OUString& aTitle ) throw( RuntimeException ) +{ + OSL_ASSERT( m_pFolderPickerImpl.get( ) ); + MutexGuard aGuard( m_aMutex ); + m_pFolderPickerImpl->setTitle( aTitle ); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL CFolderPicker::setDisplayDirectory( const OUString& aDirectory ) + throw( IllegalArgumentException, RuntimeException ) +{ + OSL_ASSERT( m_pFolderPickerImpl.get( ) ); + MutexGuard aGuard( m_aMutex ); + m_pFolderPickerImpl->setDisplayDirectory( aDirectory ); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +OUString SAL_CALL CFolderPicker::getDisplayDirectory( ) + throw( RuntimeException ) +{ + OSL_ASSERT( m_pFolderPickerImpl.get( ) ); + MutexGuard aGuard( m_aMutex ); + return m_pFolderPickerImpl->getDisplayDirectory( ); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +OUString SAL_CALL CFolderPicker::getDirectory( ) throw( RuntimeException ) +{ + OSL_ASSERT( m_pFolderPickerImpl.get( ) ); + MutexGuard aGuard( m_aMutex ); + return m_pFolderPickerImpl->getDirectory( ); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +void SAL_CALL CFolderPicker::setDescription( const OUString& aDescription ) throw( RuntimeException ) +{ + OSL_ASSERT( m_pFolderPickerImpl.get( ) ); + MutexGuard aGuard( m_aMutex ); + m_pFolderPickerImpl->setDescription( aDescription ); +} + +//----------------------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------------------- + +sal_Int16 SAL_CALL CFolderPicker::execute( ) + throw( RuntimeException ) +{ + OSL_ASSERT( m_pFolderPickerImpl.get( ) ); + + // we should not block in this call else + // in the case of an event the client can'tgetPImplFromHandle( hWnd ) + // call another function an we run into a + // deadlock !!!!! + return m_pFolderPickerImpl->execute( ); +} + +// ------------------------------------------------- +// XServiceInfo +// ------------------------------------------------- + +OUString SAL_CALL CFolderPicker::getImplementationName( ) + throw( RuntimeException ) +{ + return OUString(RTL_CONSTASCII_USTRINGPARAM( FOLDERPICKER_IMPL_NAME )); +} + +// ------------------------------------------------- +// XServiceInfo +// ------------------------------------------------- + +sal_Bool SAL_CALL CFolderPicker::supportsService( const OUString& ServiceName ) + throw( RuntimeException ) +{ + Sequence < OUString > SupportedServicesNames = FolderPicker_getSupportedServiceNames(); + + for ( sal_Int32 n = SupportedServicesNames.getLength(); n--; ) + if (SupportedServicesNames[n].compareTo(ServiceName) == 0) + return sal_True; + + return sal_False; +} + +// ------------------------------------------------- +// XServiceInfo +// ------------------------------------------------- + +Sequence< OUString > SAL_CALL CFolderPicker::getSupportedServiceNames( ) + throw( RuntimeException ) +{ + return FolderPicker_getSupportedServiceNames(); +} + +// ------------------------------------------------- +// XCancellable +// ------------------------------------------------- + +void SAL_CALL CFolderPicker::cancel( ) + throw(RuntimeException) +{ + OSL_ASSERT( m_pFolderPickerImpl.get( ) ); + MutexGuard aGuard( m_aMutex ); + m_pFolderPickerImpl->cancel( ); +} + +//------------------------------------------------ +// overwrite base class method, which is called +// by base class dispose function +//------------------------------------------------ + +void SAL_CALL CFolderPicker::disposing() +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/folderpicker/FolderPicker.hxx b/fpicker/source/win32/folderpicker/FolderPicker.hxx new file mode 100644 index 000000000000..0aed9df40630 --- /dev/null +++ b/fpicker/source/win32/folderpicker/FolderPicker.hxx @@ -0,0 +1,128 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FOLDERPICKER_HXX_ +#define _FOLDERPICKER_HXX_ + +//--------------------------------------------------------- +// includes of other projects +//--------------------------------------------------------- + +#include <cppuhelper/implbase3.hxx> +#include <osl/mutex.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> + +#include <com/sun/star/ui/dialogs/XFolderPicker.hpp> +#include <com/sun/star/util/XCancellable.hpp> + +#include <memory> + +#include "WinFOPImpl.hxx" + +//---------------------------------------------------------- +// class declaration +//---------------------------------------------------------- + +class CFolderPicker : + public cppu::WeakImplHelper3< + com::sun::star::ui::dialogs::XFolderPicker, + com::sun::star::lang::XServiceInfo, + com::sun::star::util::XCancellable > +{ +public: + + // ctor/dtor + CFolderPicker( const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& xServiceMgr ); + + //------------------------------------------------------------------------------------ + // XExecutableDialog + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setTitle( const rtl::OUString& aTitle ) + throw( com::sun::star::uno::RuntimeException ); + + virtual sal_Int16 SAL_CALL execute( ) + throw( com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFolderPicker functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setDisplayDirectory( const rtl::OUString& aDirectory ) + throw( com::sun::star::lang::IllegalArgumentException, com::sun::star::uno::RuntimeException ); + + virtual rtl::OUString SAL_CALL getDisplayDirectory( ) + throw( com::sun::star::uno::RuntimeException ); + + virtual rtl::OUString SAL_CALL getDirectory( ) + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setDescription( const rtl::OUString& aDescription ) + throw( com::sun::star::uno::RuntimeException ); + + //------------------------------------------------ + // XServiceInfo + //------------------------------------------------ + + virtual ::rtl::OUString SAL_CALL getImplementationName( ) + throw(::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) + throw(::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) + throw(::com::sun::star::uno::RuntimeException); + + //------------------------------------------------ + // XCancellable + //------------------------------------------------ + + virtual void SAL_CALL cancel( ) + throw(::com::sun::star::uno::RuntimeException); + + //------------------------------------------------ + // overwrite base class method, which is called + // by base class dispose function + //------------------------------------------------ + + virtual void SAL_CALL disposing(); + +private: + com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > m_xServiceMgr; + std::auto_ptr< CWinFolderPickerImpl > m_pFolderPickerImpl; + osl::Mutex m_aMutex; + +// prevent copy and assignment +private: + CFolderPicker( const CFolderPicker& ); + CFolderPicker& operator=( const CFolderPicker& ); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/folderpicker/FopEvtDisp.hxx b/fpicker/source/win32/folderpicker/FopEvtDisp.hxx new file mode 100644 index 000000000000..3da34d8f6bf6 --- /dev/null +++ b/fpicker/source/win32/folderpicker/FopEvtDisp.hxx @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _FOPEVENTDISPATCHER_HXX_ +#define _FOPEVENTDISPATCHER_HXX_ + +#include <com/sun/star/lang/EventObject.hpp> + +//------------------------------------------------------------------------ +// deklarations +//------------------------------------------------------------------------ +class CFOPEventDispatcher +{ +public: + + // dispatches a FilePickerEvent to wherever + virtual void SAL_CALL helpRequested( ::com::sun::star::lang::EventObject aEvent ) const = 0; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/folderpicker/Fopentry.cxx b/fpicker/source/win32/folderpicker/Fopentry.cxx new file mode 100644 index 000000000000..d86fff151a2a --- /dev/null +++ b/fpicker/source/win32/folderpicker/Fopentry.cxx @@ -0,0 +1,143 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +//----------------------------------------------------------------------- +// includes of other projects +//----------------------------------------------------------------------- +#include <cppuhelper/factory.hxx> +#include <com/sun/star/container/XSet.hpp> +#include <osl/diagnose.h> + +#include "folderpicker.hxx" + +#include "FOPServiceInfo.hxx" +#include "WinFOPImpl.hxx" + +//----------------------------------------------------------------------- +// namespace directives +//----------------------------------------------------------------------- + +using namespace ::rtl ; +using namespace ::com::sun::star::uno ; +using namespace ::com::sun::star::container ; +using namespace ::com::sun::star::lang ; +using namespace ::com::sun::star::registry ; +using namespace ::cppu ; +using com::sun::star::ui::dialogs::XFolderPicker; + + +namespace +{ + + //----------------------------------------------------------------------- + // + //----------------------------------------------------------------------- + + Reference< XInterface > SAL_CALL createInstance( const Reference< XMultiServiceFactory >& rServiceManager ) + { + return Reference< XInterface >( static_cast< XFolderPicker* >( new CFolderPicker( rServiceManager ) ) ); + } +} + +//----------------------------------------------------------------------- +// the 3 important functions which will be exported +//----------------------------------------------------------------------- + +extern "C" +{ + +//---------------------------------------------------------------------- +// component_getImplementationEnvironment +//---------------------------------------------------------------------- + +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +//----------------------------------------------------------------------- +// +//----------------------------------------------------------------------- + +sal_Bool SAL_CALL component_writeInfo( void*, void* pRegistryKey ) +{ + sal_Bool bRetVal = sal_True; + + if ( pRegistryKey ) + { + try + { + Reference< XRegistryKey > pXNewKey( static_cast< XRegistryKey* >( pRegistryKey ) ); + pXNewKey->createKey( OUString( RTL_CONSTASCII_USTRINGPARAM( FOLDER_PICKER_REGKEY_NAME ) ) ); + } + catch( InvalidRegistryException& ) + { + OSL_ENSURE(sal_False, "InvalidRegistryException caught"); + bRetVal = sal_False; + } + } + + return bRetVal; +} + +//---------------------------------------------------------------------- +// component_getFactory +// returns a factory to create XFilePicker-Services +//---------------------------------------------------------------------- + +void* SAL_CALL component_getFactory( const sal_Char* pImplName, uno_Interface* pSrvManager, uno_Interface* ) +{ + void* pRet = 0; + + if ( pSrvManager && ( 0 == rtl_str_compare( pImplName, FOLDER_PICKER_IMPL_NAME ) ) ) + { + Sequence< OUString > aSNS( 1 ); + aSNS.getArray( )[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( FOLDER_PICKER_SERVICE_NAME ) ); + + Reference< XSingleServiceFactory > xFactory ( createSingleFactory( + reinterpret_cast< XMultiServiceFactory* > ( pSrvManager ), + OUString::createFromAscii( pImplName ), + createInstance, + aSNS ) ); + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + } + + return pRet; +} + +} // extern "C" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/folderpicker/MtaFop.cxx b/fpicker/source/win32/folderpicker/MtaFop.cxx new file mode 100644 index 000000000000..2933b0e6614e --- /dev/null +++ b/fpicker/source/win32/folderpicker/MtaFop.cxx @@ -0,0 +1,842 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" +#include <osl/diagnose.h> +#include <osl/conditn.hxx> + +#include "MtaFop.hxx" +#include <wchar.h> +#include <process.h> +#include "..\misc\resourceprovider.hxx" + +#include <systools/win32/comtools.hxx> + +using rtl::OUString; +using osl::Condition; + +const sal_uInt32 MSG_BROWSEFORFOLDER = WM_USER + 1; +const sal_uInt32 MSG_SHUTDOWN = WM_USER + 2; + +const sal_uInt32 MAX_WAITTIME = 2000; // msec + +const sal_Bool MANUAL_RESET = sal_True; +const sal_Bool AUTO_RESET = sal_False; +const sal_Bool INIT_NONSIGNALED = sal_False; + +typedef sal::systools::COMReference<IMalloc> IMallocPtr; +typedef sal::systools::COMReference<IShellFolder> IShellFolderPtr; + +namespace +{ + const char* FOLDERPICKER_SRV_DLL_NAME = "fop.dll"; + const char g_szWndClsName[] = "FopStaReqWnd###"; + const char* CURRENT_INSTANCE = "CurrInst"; + + typedef struct _RequestContext + { + HANDLE hEvent; + sal_Bool bRet; + } RequestContext; + + inline sal_Bool InitializeRequestContext( RequestContext* aRequestContext ) + { + OSL_ASSERT( aRequestContext ); + + aRequestContext->hEvent = CreateEventA( + 0, AUTO_RESET, INIT_NONSIGNALED, NULL ); + + aRequestContext->bRet = sal_False; + + return ( 0 != aRequestContext->hEvent ); + } + + inline void DeinitializeRequestContext( RequestContext* aRequestContext ) + { + OSL_ASSERT( aRequestContext && aRequestContext->hEvent ); + CloseHandle( aRequestContext->hEvent ); + } + + //------------------------------- + // Determine if current thread is + // an MTA or STA thread + //------------------------------- + bool IsMTA() + { + HRESULT hr = CoInitialize(NULL); + + if (RPC_E_CHANGED_MODE == hr) + return true; + + if(SUCCEEDED(hr)) + CoUninitialize(); + + return false; + } +} + +//---------------------------------------------------------------- +// static member initialization +//---------------------------------------------------------------- + +ATOM CMtaFolderPicker::s_ClassAtom = 0; +osl::Mutex CMtaFolderPicker::s_Mutex; +sal_Int32 CMtaFolderPicker::s_StaRequestWndRegisterCount = 0; + +//-------------------------------------------------------------------- +// ctor +//-------------------------------------------------------------------- + +CMtaFolderPicker::CMtaFolderPicker( sal_uInt32 Flags ) : + m_hStaThread( NULL ), + m_uStaThreadId( 0 ), + m_hEvtThrdReady( NULL ), + m_hwndStaRequestWnd( NULL ) +{ + m_hInstance = GetModuleHandleA( FOLDERPICKER_SRV_DLL_NAME ); + OSL_ENSURE( m_hInstance, "The name of the FolderPicker service dll must have changed" ); + + ZeroMemory( &m_bi, sizeof( m_bi ) ); + + // !!!!!!!!!!!!!!!!! IMPORTANT !!!!!!!!!!!!!!!!!!! + // + // Remember: This HACK prevents you from stepping + // through your code in the debugger because if you + // set a break point in the ctor here the debugger + // may become the owner of the FolderBrowse dialog + // and so it seems that the Visual Studio and the + // office are hanging + m_bi.hwndOwner = GetForegroundWindow( ); + + /* + Flag Available + -------------------------------- + BIF_EDITBOX Version 4.71 + BIF_NEWDIALOGSTYLE Version 5.0 + BIF_SHAREABLE Version 5.0 + BIF_VALIDATE Version 4.71 + + Version 4.71 - Internet Explorer 4.0 + Version 5.0 - Internet Explorer 5.0 + Windows 2000 + */ + m_bi.ulFlags = Flags; + + m_bi.lpfn = CMtaFolderPicker::FolderPickerCallback; + m_bi.lParam = reinterpret_cast< LPARAM >( this ); + + //--------------------------------------- + // read the default strings for title and + // description from a resource file + + CResourceProvider ResProvider; + + m_dialogTitle = ResProvider.getResString( 500 ); + m_Description = ResProvider.getResString( 501 ); + + // signals that the thread was successfully set up + m_hEvtThrdReady = CreateEventA( + 0, + MANUAL_RESET, + INIT_NONSIGNALED, + NULL ); + + if ( m_hEvtThrdReady ) + { + // setup the sta thread + m_hStaThread = (HANDLE)_beginthreadex( + NULL, + 0, + CMtaFolderPicker::StaThreadProc, + this, + 0, + &m_uStaThreadId ); + + OSL_ASSERT( m_hStaThread ); + } + + OSL_ASSERT( m_hEvtThrdReady ); +} + +//-------------------------------------------------------------------- +// dtor +//-------------------------------------------------------------------- + +CMtaFolderPicker::~CMtaFolderPicker( ) +{ + // only if the is a valid event handle + // there may also be a thread a hidden + // target request window and so on + // see ctor + if ( m_hEvtThrdReady ) + { + // block calling threads because we + // are about to shutdown + ResetEvent( m_hEvtThrdReady ); + + // force the destruction of the sta thread request window + // and the end of the thread + // remeber: DestroyWindow may only be called from within + // the thread that created the window + if ( IsWindow( m_hwndStaRequestWnd ) ) + { + SendMessageA( m_hwndStaRequestWnd, MSG_SHUTDOWN, 0, 0 ); + + // we place unregister class here because + // if we have a valid window we must have + // sucessfully registered a window class + // if the creation of the window itself + // failed after registering the window + // class we have unregistered it immediately + // in createStaRequestWindow below + UnregisterStaRequestWindowClass( ); + } + + if ( m_hStaThread ) + { + // wait for thread shutdown + sal_uInt32 dwResult = WaitForSingleObject( m_hStaThread, MAX_WAITTIME ); + OSL_ENSURE( dwResult == WAIT_OBJECT_0, "sta thread could not terminate" ); + + // terminate the thread if it + // doesn't shutdown itself + if ( WAIT_OBJECT_0 != dwResult ) + TerminateThread( + m_hStaThread, sal::static_int_cast< DWORD >(-1) ); + + CloseHandle( m_hStaThread ); + } + + CloseHandle( m_hEvtThrdReady ); + } +} + +//-------------------------------------------------------------------- +// +//-------------------------------------------------------------------- + +sal_Bool CMtaFolderPicker::browseForFolder( ) +{ + sal_Bool bRet = sal_False; + + if (IsMTA()) + { + + OSL_ASSERT( m_hEvtThrdReady ); + + if ( WaitForSingleObject( m_hEvtThrdReady, MAX_WAITTIME ) != WAIT_OBJECT_0 ) + { + OSL_ENSURE( sal_False, "sta thread not ready" ); + return sal_False; + } + + RequestContext aReqCtx; + + if ( !InitializeRequestContext( &aReqCtx ) ) + { + OSL_ASSERT( sal_False ); + return sal_False; + } + + // marshall request into the sta thread + PostMessageA( + m_hwndStaRequestWnd, + MSG_BROWSEFORFOLDER, + 0, + reinterpret_cast< LPARAM >( &aReqCtx ) ); + + // waiting for the event to be signaled or + // window messages so that we don't block + // our parent window + + sal_Bool bContinue = sal_True; + + while ( bContinue ) + { + DWORD dwResult = MsgWaitForMultipleObjects( + 1, &aReqCtx.hEvent, FALSE, INFINITE, QS_ALLEVENTS ); + + switch ( dwResult ) + { + // the request context event is signaled + case WAIT_OBJECT_0: + bContinue = sal_False; + break; + + // a window message has arrived + case WAIT_OBJECT_0 + 1: + { + // dispatching all messages but we expect to + // receive only paint or timer messages that's + // why we don't need to call TranslateMessage or + // TranslateAccelerator, because keybord or + // mouse messages are for the FolderPicker which + // is in the foreground and should not arrive here + MSG msg; + while ( PeekMessageA( &msg, NULL, 0, 0, PM_REMOVE ) ) + DispatchMessageA(&msg); + } + break; + + // should not happen + default: + OSL_ASSERT( sal_False ); + } + } + + /*sal_Bool*/ bRet = aReqCtx.bRet; + DeinitializeRequestContext( &aReqCtx ); + } + else + { + bRet = onBrowseForFolder(); + } + + return bRet; +} + +//-------------------------------------------------------------------- +// +//-------------------------------------------------------------------- + +void SAL_CALL CMtaFolderPicker::setDisplayDirectory( const OUString& aDirectory ) +{ + m_displayDir = aDirectory; +} + +//-------------------------------------------------------------------- +// +//-------------------------------------------------------------------- + +OUString SAL_CALL CMtaFolderPicker::getDisplayDirectory( ) +{ + return m_displayDir; +} + +//-------------------------------------------------------------------- +// +//-------------------------------------------------------------------- + +OUString SAL_CALL CMtaFolderPicker::getDirectory( ) +{ + return m_SelectedDir; +} + +//-------------------------------------------------------------------- +// +//-------------------------------------------------------------------- + +void SAL_CALL CMtaFolderPicker::setDescription( const rtl::OUString& aDescription ) +{ + m_Description = aDescription; +} + +//-------------------------------------------------------------------- +// +//-------------------------------------------------------------------- + +void SAL_CALL CMtaFolderPicker::setTitle( const OUString& aTitle ) +{ + m_dialogTitle = aTitle; +} + +//-------------------------------------------------------------------- +// +//-------------------------------------------------------------------- + +OUString SAL_CALL CMtaFolderPicker::getTitle( ) +{ + return m_dialogTitle; +} + +//----------------------------------------------------- +// XCancellable +//----------------------------------------------------- + +void SAL_CALL CMtaFolderPicker::cancel( ) +{ + if ( IsWindow( m_hwnd ) ) + { + // simulate a mouse click to the + // cancel button + PostMessageA( + m_hwnd, + WM_COMMAND, + MAKEWPARAM( IDCANCEL, BN_CLICKED ), + (LPARAM)GetDlgItem( m_hwnd, IDCANCEL ) ); + } +} + +//-------------------------------------------------------------------- +// +//-------------------------------------------------------------------- + +sal_Bool SAL_CALL CMtaFolderPicker::onBrowseForFolder( ) +{ + sal_Bool bRet; + LPITEMIDLIST lpiid; + + // pre SHBrowseFroFolder + + m_bi.pidlRoot = 0; + m_bi.pszDisplayName = reinterpret_cast<LPWSTR>(m_pathBuff.get()); + + if ( m_Description.getLength( ) ) + m_bi.lpszTitle = reinterpret_cast<LPCWSTR>(m_Description.getStr( )); + + lpiid = SHBrowseForFolderW( &m_bi ); + bRet = ( NULL != lpiid ); + + // post SHBrowseForFolder + + m_SelectedDir = getPathFromItemIdList( lpiid ); + releaseItemIdList( lpiid ); + + return bRet; +} + +//-------------------------------------------------------------------- +// +//-------------------------------------------------------------------- + +void SAL_CALL CMtaFolderPicker::releaseItemIdList( LPITEMIDLIST lpItemIdList ) +{ + IMallocPtr pIMalloc; + SHGetMalloc(&pIMalloc); + if (pIMalloc.is()) + { + pIMalloc->Free(lpItemIdList); + lpItemIdList = NULL; + } +} + +//-------------------------------------------------------------------- +// +//-------------------------------------------------------------------- + +LPITEMIDLIST SAL_CALL CMtaFolderPicker::getItemIdListFromPath( const rtl::OUString& aDirectory ) +{ + // parameter checking + if ( !aDirectory.getLength( ) ) + return NULL; + + LPITEMIDLIST lpItemIdList(NULL); + + IShellFolderPtr pIShellFolder; + SHGetDesktopFolder(&pIShellFolder); + + if (pIShellFolder.is()) + { + pIShellFolder->ParseDisplayName( + NULL, + NULL, + reinterpret_cast<LPWSTR>(const_cast< sal_Unicode* >( aDirectory.getStr( ) )), + NULL, + &lpItemIdList, + NULL ); + } + + return lpItemIdList; +} + +//-------------------------------------------------------------------- +// +//-------------------------------------------------------------------- + +OUString SAL_CALL CMtaFolderPicker::getPathFromItemIdList( LPCITEMIDLIST lpItemIdList ) +{ + OUString path; + + if ( lpItemIdList ) + { + bool bRet = SHGetPathFromIDListW( lpItemIdList, reinterpret_cast<LPWSTR>(m_pathBuff.get()) ); + if ( bRet ) + path = m_pathBuff.get( ); + } + + return path; +} + +//-------------------------------------------------------------------- +// +//-------------------------------------------------------------------- + +void SAL_CALL CMtaFolderPicker::enableOk( sal_Bool bEnable ) +{ + OSL_ASSERT( IsWindow( m_hwnd ) ); + + SendMessageW( + m_hwnd, + BFFM_ENABLEOK, + static_cast< WPARAM >( 0 ), + static_cast< LPARAM >( bEnable ) ); +} + +//-------------------------------------------------------------------- +// +//-------------------------------------------------------------------- + +void SAL_CALL CMtaFolderPicker::setSelection( const rtl::OUString& aDirectory ) +{ + OSL_ASSERT( IsWindow( m_hwnd ) ); + +#ifdef _MSC_VER +#pragma message( "#######################################" ) +#pragma message( "SendMessageW wrapper has to be extended" ) +#pragma message( "#######################################" ) +#endif + + SendMessageW( + m_hwnd, + BFFM_SETSELECTIONW, + static_cast< WPARAM >( sal_True ), + reinterpret_cast< LPARAM >( aDirectory.getStr( ) ) ); +} + +//-------------------------------------------------------------------- +// +//-------------------------------------------------------------------- + +void SAL_CALL CMtaFolderPicker::setStatusText( const rtl::OUString& aStatusText ) +{ + OSL_ASSERT( IsWindow( m_hwnd ) ); + + SendMessageW( + m_hwnd, + BFFM_SETSTATUSTEXTW, + static_cast< WPARAM >( 0 ), + reinterpret_cast< LPARAM >( aStatusText.getStr( ) ) ); +} + +//-------------------------------------------------------------------- +// +//-------------------------------------------------------------------- + +void SAL_CALL CMtaFolderPicker::onInitialized( ) +{ + LPITEMIDLIST lpiidDisplayDir = getItemIdListFromPath( m_displayDir ); + + if ( lpiidDisplayDir ) + { + SendMessageA( + m_hwnd, + BFFM_SETSELECTION, + (WPARAM)FALSE, + (LPARAM) lpiidDisplayDir ); + + releaseItemIdList( lpiidDisplayDir ); + } +} + +//-------------------------------------------------------------------- +// +//-------------------------------------------------------------------- + +sal_uInt32 CMtaFolderPicker::onValidateFailed() +{ + // to be overwritten by subclasses + return 1; +} + +//-------------------------------------------------------------------- +// +//-------------------------------------------------------------------- + +int CALLBACK CMtaFolderPicker::FolderPickerCallback( HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData ) +{ + CMtaFolderPicker* pImpl = reinterpret_cast< CMtaFolderPicker* >( lpData ); + OSL_ASSERT( pImpl ); + + int nRC = 0; + + switch( uMsg ) + { + case BFFM_INITIALIZED: + pImpl->m_hwnd = hwnd; + pImpl->onInitialized( ); + SetWindowTextW( hwnd, reinterpret_cast<LPCWSTR>(pImpl->m_dialogTitle.getStr()) ); + break; + + case BFFM_SELCHANGED: + pImpl->m_hwnd = hwnd; + pImpl->onSelChanged( + pImpl->getPathFromItemIdList( + reinterpret_cast< LPITEMIDLIST >( lParam ) ) ); + break; + + case BFFM_VALIDATEFAILEDW: + nRC = pImpl->onValidateFailed(); + break; + + default: + OSL_ASSERT( sal_False ); + } + + return nRC; +} + +//-------------------------------------------------------------------- +// the window proc +//-------------------------------------------------------------------- + +LRESULT CALLBACK CMtaFolderPicker::StaWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + LRESULT lResult = 0; + CMtaFolderPicker* pImpl = NULL; + + /* + we connect to the belonging class instance of this + window using SetProp, GetProp etc. + this may fail if somehow the class instance destroyed + before the window + */ + + switch( uMsg ) + { + case WM_CREATE: + { + LPCREATESTRUCT lpcs = + reinterpret_cast< LPCREATESTRUCT >( lParam ); + + OSL_ASSERT( lpcs->lpCreateParams ); + + // connect the instance handle to the window + SetPropA( hWnd, CURRENT_INSTANCE, lpcs->lpCreateParams ); + } + break; + + case WM_NCDESTROY: + // RemoveProp returns the saved value on success + pImpl = reinterpret_cast< CMtaFolderPicker* >( + RemovePropA( hWnd, CURRENT_INSTANCE ) ); + + OSL_ASSERT( pImpl && !IsBadReadPtr( pImpl, sizeof( CMtaFolderPicker ) ) ); + break; + + case MSG_BROWSEFORFOLDER: + { + RequestContext* aReqCtx = reinterpret_cast< RequestContext* >( lParam ); + OSL_ASSERT( aReqCtx ); + + pImpl = reinterpret_cast< CMtaFolderPicker* >( + GetPropA( hWnd, CURRENT_INSTANCE ) ); + + OSL_ASSERT( pImpl && !IsBadReadPtr( pImpl, sizeof( CMtaFolderPicker ) ) ); + + aReqCtx->bRet = pImpl->onBrowseForFolder( ); + SetEvent( aReqCtx->hEvent ); + } + break; + + case MSG_SHUTDOWN: + pImpl = reinterpret_cast< CMtaFolderPicker* >( + GetPropA( hWnd, CURRENT_INSTANCE ) ); + + OSL_ASSERT( pImpl && !IsBadReadPtr( pImpl, sizeof( CMtaFolderPicker ) ) ); + + DestroyWindow( pImpl->m_hwndStaRequestWnd ); + break; + + case WM_DESTROY: + PostQuitMessage( 0 ); + break; + + default: + lResult = DefWindowProcA( hWnd, uMsg, wParam, lParam ); + break; + } + + return lResult; +} + +//-------------------------------------------------------------------- +// +//-------------------------------------------------------------------- + +sal_Bool SAL_CALL CMtaFolderPicker::createStaRequestWindow( ) +{ + bool bIsWnd = false; + + if ( RegisterStaRequestWindowClass( ) ) + { + m_hwndStaRequestWnd = CreateWindowA( + g_szWndClsName, NULL, + 0, 0, 0, 0, 0, + NULL, NULL, m_hInstance, + (LPVOID)this // provide the instance of the class + ); + + bIsWnd = IsWindow( m_hwndStaRequestWnd ); + + // we do immediately unregister the window class + // if the creation of the window fails because we + // don't want to spoil the register class counter + if ( !bIsWnd ) + UnregisterStaRequestWindowClass( ); + + OSL_ENSURE( bIsWnd, "sta request window creation failed" ); + } + + return bIsWnd; +} + +//-------------------------------------------------------------------- +// +//-------------------------------------------------------------------- + +unsigned int CMtaFolderPicker::run( ) +{ + OSL_ASSERT( m_hEvtThrdReady ); + + // setup an sta environment + HRESULT hr = CoInitialize( NULL ); + + // if we can't setup an sta environment + // we stop here and return + if ( FAILED( hr ) ) + { + OSL_ENSURE( sal_False, "CoInitialize failed" ); + return sal::static_int_cast< unsigned int >(-1); + } + + unsigned int nRet; + + if ( createStaRequestWindow( ) ) + { + SetEvent( m_hEvtThrdReady ); + + // pumping messages + MSG msg; + while( GetMessageA( &msg, NULL, 0, 0 ) ) + DispatchMessageA( &msg ); + + nRet = 0; + } + else + { + OSL_ENSURE( sal_False, "failed to create sta thread" ); + nRet = sal::static_int_cast< unsigned int >(-1); + } + + // shutdown sta environment + CoUninitialize( ); + + return nRet; +} + +//-------------------------------------------------------------------- +// +//-------------------------------------------------------------------- + +unsigned int WINAPI CMtaFolderPicker::StaThreadProc( LPVOID pParam ) +{ + CMtaFolderPicker* pInst = + reinterpret_cast<CMtaFolderPicker*>( pParam ); + + OSL_ASSERT( pInst ); + + HRESULT hr = OleInitialize( NULL ); + + unsigned int result = pInst->run( ); + + if ( SUCCEEDED( hr ) ) + OleUninitialize(); + + return result; +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +ATOM SAL_CALL CMtaFolderPicker::RegisterStaRequestWindowClass( ) +{ + osl::MutexGuard aGuard( s_Mutex ); + + if ( 0 == s_ClassAtom ) + { + WNDCLASSEXA wcex; + + ZeroMemory( &wcex, sizeof( WNDCLASSEXA ) ); + + wcex.cbSize = sizeof(WNDCLASSEXA); + wcex.style = 0; + wcex.lpfnWndProc = static_cast< WNDPROC >( CMtaFolderPicker::StaWndProc ); + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = m_hInstance; + wcex.hIcon = NULL; + wcex.hCursor = NULL; + wcex.hbrBackground = NULL; + wcex.lpszMenuName = NULL; + wcex.lpszClassName = g_szWndClsName; + wcex.hIconSm = NULL; + + s_ClassAtom = RegisterClassExA( &wcex ); + OSL_ASSERT( s_ClassAtom ); + } + + // increment the register class counter + // so that we keep track of the number + // of class registrations + if ( 0 != s_ClassAtom ) + s_StaRequestWndRegisterCount++; + + return s_ClassAtom; +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +void SAL_CALL CMtaFolderPicker::UnregisterStaRequestWindowClass( ) +{ + osl::MutexGuard aGuard( s_Mutex ); + + OSL_ASSERT( 0 != s_ClassAtom ); + + // update the register class counter + // and unregister the window class if + // counter drops to zero + if ( 0 != s_ClassAtom ) + { + s_StaRequestWndRegisterCount--; + OSL_ASSERT( s_StaRequestWndRegisterCount >= 0 ); + } + + if ( 0 == s_StaRequestWndRegisterCount ) + { + UnregisterClass( + (LPCTSTR)MAKELONG( s_ClassAtom, 0 ), m_hInstance ); + + s_ClassAtom = 0; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/folderpicker/MtaFop.hxx b/fpicker/source/win32/folderpicker/MtaFop.hxx new file mode 100644 index 000000000000..36e4648b05bd --- /dev/null +++ b/fpicker/source/win32/folderpicker/MtaFop.hxx @@ -0,0 +1,194 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _MTAFOP_HXX_ +#define _MTAFOP_HXX_ + +#include <sal/types.h> +#include <rtl/ustring.hxx> +#include <osl/mutex.hxx> + +#include <utility> +#ifdef __MINGW32__ +#include <windows.h> +#endif +#if defined _MSC_VER +#pragma warning(push, 1) +#pragma warning(disable: 4917) +#endif +#include <objidl.h> +#include <shlobj.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif +#include "..\misc\WinImplHelper.hxx" + +//---------------------------------------------------------------- +// a simple helper class used to provide a buffer for different +// Win32 file and directory functions +//---------------------------------------------------------------- + +class CAutoPathBuff +{ +public: + CAutoPathBuff( size_t size = 0 ) + { + if (0 == size) + size = 32000; // max path length under Win2000 + + pBuff = new sal_Unicode[size]; + + OSL_POSTCOND(pBuff,"Could not allocate path buffer"); + } + + ~CAutoPathBuff( ) + { + delete [] pBuff; + } + + operator sal_Unicode*( ) + { + OSL_PRECOND( pBuff, \ + "No path buffer allocated" ); + return pBuff; + } + + sal_Unicode* get( ) + { + OSL_PRECOND( pBuff, \ + "No path buffer allocated" ); + return pBuff; + } + +private: + sal_Unicode* pBuff; +}; + +//-------------------------------------------------------- +// the Mta-Ole clipboard class is for internal use only! +// only one instance of this class should be created, the +// user has to ensure this! +// the class is not thread-safe because it will be used +// only from within the clipboard service and the methods +// of the clipboard service are already synchronized +//-------------------------------------------------------- + +class CMtaFolderPicker +{ +public: + CMtaFolderPicker( sal_uInt32 Flags ); + virtual ~CMtaFolderPicker( ); + + // shell functions + sal_Bool SAL_CALL browseForFolder( ); + + virtual void SAL_CALL setDisplayDirectory( const rtl::OUString& aDirectory ); + virtual rtl::OUString SAL_CALL getDisplayDirectory( ); + virtual rtl::OUString SAL_CALL getDirectory( ); + + virtual void SAL_CALL setDescription( const rtl::OUString& aDescription ); + + virtual void SAL_CALL setTitle( const rtl::OUString& aTitle ); + rtl::OUString SAL_CALL getTitle( ); + + //----------------------------------------------------- + // XCancellable + //----------------------------------------------------- + + virtual void SAL_CALL cancel( ); + +protected: + void SAL_CALL enableOk( sal_Bool bEnable ); + void SAL_CALL setSelection( const rtl::OUString& aDirectory ); + void SAL_CALL setStatusText( const rtl::OUString& aStatusText ); + + virtual void SAL_CALL onInitialized( ); + virtual void SAL_CALL onSelChanged( const rtl::OUString& aNewPath ) = 0; + +private: + sal_uInt32 onValidateFailed(); + + // helper functions + LPITEMIDLIST SAL_CALL getItemIdListFromPath( const rtl::OUString& aDirectory ); + rtl::OUString SAL_CALL getPathFromItemIdList( LPCITEMIDLIST lpItemIdList ); + void SAL_CALL releaseItemIdList( LPITEMIDLIST lpItemIdList ); + + unsigned int run( ); + + // create a hidden windows which serves as an request + // target; so we guarantee synchronization + sal_Bool SAL_CALL createStaRequestWindow( ); + + //--------------------------------------------------------------- + // message handler functions; remeber these functions are called + // from a different thread context! + //--------------------------------------------------------------- + + sal_Bool SAL_CALL onBrowseForFolder( ); + + static LRESULT CALLBACK StaWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); + static unsigned int WINAPI StaThreadProc( LPVOID pParam ); + + static int CALLBACK FolderPickerCallback( HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData ); + +protected: + HWND m_hwnd; + +private: + ATOM SAL_CALL RegisterStaRequestWindowClass( ); + void SAL_CALL UnregisterStaRequestWindowClass( ); + +private: + HANDLE m_hStaThread; + unsigned m_uStaThreadId; + HANDLE m_hEvtThrdReady; + HWND m_hwndStaRequestWnd; + rtl::OUString m_dialogTitle; + rtl::OUString m_Description; + rtl::OUString m_displayDir; + rtl::OUString m_SelectedDir; + BROWSEINFOW m_bi; + CAutoPathBuff m_pathBuff; + HINSTANCE m_hInstance; + + // the request window class has to be registered only + // once per process, so multiple instance of this class + // share the registered window class + static ATOM s_ClassAtom; + static osl::Mutex s_Mutex; + static sal_Int32 s_StaRequestWndRegisterCount; + +// prevent copy and assignment +private: + CMtaFolderPicker( const CMtaFolderPicker& ); + CMtaFolderPicker& operator=( const CMtaFolderPicker& ); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/folderpicker/WinFOPImpl.cxx b/fpicker/source/win32/folderpicker/WinFOPImpl.cxx new file mode 100644 index 000000000000..fdf191f07318 --- /dev/null +++ b/fpicker/source/win32/folderpicker/WinFOPImpl.cxx @@ -0,0 +1,167 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include "WinFOPImpl.hxx" +#include <osl/diagnose.h> +#include <com/sun/star/lang/EventObject.hpp> + +#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> +#include "FopEvtDisp.hxx" +#include <osl/file.hxx> +#include "FolderPicker.hxx" + +//------------------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------------------ + +using com::sun::star::uno::RuntimeException; +using com::sun::star::lang::IllegalArgumentException; +using com::sun::star::lang::EventObject; +using rtl::OUString; + +using namespace com::sun::star::ui::dialogs; +using osl::FileBase; + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +const OUString BACKSLASH(RTL_CONSTASCII_USTRINGPARAM( "\\" )); + +//------------------------------------------------------------------------ +// ctor +//------------------------------------------------------------------------ + +CWinFolderPickerImpl::CWinFolderPickerImpl( CFolderPicker* aFolderPicker ) : + CMtaFolderPicker( BIF_RETURNONLYFSDIRS | BIF_RETURNFSANCESTORS | BIF_EDITBOX | BIF_VALIDATE ), + m_pFolderPicker( aFolderPicker ), + m_nLastDlgResult( ::com::sun::star::ui::dialogs::ExecutableDialogResults::CANCEL ) +{ +} + +//------------------------------------------------------------------------ +// get directory in URL format, convert it to system format and set the +// member variable +// If the given URL for the directory is invalid the function throws an +// IllegalArgumentException +// If the specified path is well formed but invalid for the underlying +// OS the FolderPicker starts in the root of the file system hierarchie +//------------------------------------------------------------------------ + +void SAL_CALL CWinFolderPickerImpl::setDisplayDirectory( const OUString& aDirectory ) + throw( IllegalArgumentException, RuntimeException ) +{ + OUString sysDir; + + if( aDirectory.getLength( ) ) + { + // assuming that this function succeeds after successful execution + // of getAbsolutePath + ::osl::FileBase::RC rc = + ::osl::FileBase::getSystemPathFromFileURL( aDirectory, sysDir ); + + if ( ::osl::FileBase::E_None != rc ) + throw IllegalArgumentException( + OUString(RTL_CONSTASCII_USTRINGPARAM( "directory is not a valid file url" )), + static_cast< XFolderPicker* >( m_pFolderPicker ), + 1 ); + + // we ensure that there is a trailing '/' at the end of + // he given file url, because the windows functions only + // works correctly when providing "c:\" or an environment + // variable like "=c:=c:\.." etc. is set, else the + // FolderPicker would stand in the root of the shell + // hierarchie which is the desktop folder + if ( sysDir.lastIndexOf( BACKSLASH ) != (sysDir.getLength( ) - 1) ) + sysDir += BACKSLASH; + } + + // call base class method + CMtaFolderPicker::setDisplayDirectory( sysDir ); +} + +//------------------------------------------------------------------------ +// we return the directory in URL format +//------------------------------------------------------------------------ + +OUString CWinFolderPickerImpl::getDisplayDirectory( ) + throw( RuntimeException ) +{ + // call base class method to get the directory in system format + OUString displayDirectory = CMtaFolderPicker::getDisplayDirectory( ); + + OUString displayDirectoryURL; + if ( displayDirectory.getLength( ) ) + ::osl::FileBase::getFileURLFromSystemPath( displayDirectory, displayDirectoryURL ); + + return displayDirectoryURL; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +OUString SAL_CALL CWinFolderPickerImpl::getDirectory( ) throw( RuntimeException ) +{ + OUString sysDir = CMtaFolderPicker::getDirectory( ); + OUString dirURL; + + if ( sysDir.getLength( ) ) + ::osl::FileBase::getFileURLFromSystemPath( sysDir, dirURL ); + + return dirURL; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_Int16 SAL_CALL CWinFolderPickerImpl::execute( ) throw( RuntimeException ) +{ + return m_nLastDlgResult = CMtaFolderPicker::browseForFolder( ) ? + ::com::sun::star::ui::dialogs::ExecutableDialogResults::OK : + ::com::sun::star::ui::dialogs::ExecutableDialogResults::CANCEL; +} + +//--------------------------------------------------------------------- +// +//--------------------------------------------------------------------- + +void CWinFolderPickerImpl::onSelChanged( const OUString& aNewPath ) +{ + setStatusText( aNewPath ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/folderpicker/WinFOPImpl.hxx b/fpicker/source/win32/folderpicker/WinFOPImpl.hxx new file mode 100644 index 000000000000..d88531629d03 --- /dev/null +++ b/fpicker/source/win32/folderpicker/WinFOPImpl.hxx @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _WINFOPIMPL_HXX_ +#define _WINFOPIMPL_HXX_ + + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include "MtaFop.hxx" + +//------------------------------------------------------------------------ +// forward +//------------------------------------------------------------------------ + +class CFolderPicker; + +//------------------------------------------------------------------------ +// deklarations +//------------------------------------------------------------------------ + +class CWinFolderPickerImpl : public CMtaFolderPicker +{ +public: + CWinFolderPickerImpl( CFolderPicker* aFolderPicker ); + + //----------------------------------------------------------------------------------------- + // XExecutableDialog + //----------------------------------------------------------------------------------------- + + virtual sal_Int16 SAL_CALL execute( ) + throw( com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------- + // XFolderPicker + //----------------------------------------------------- + + virtual void SAL_CALL setDisplayDirectory( const rtl::OUString& aDirectory ) + throw( com::sun::star::lang::IllegalArgumentException, com::sun::star::uno::RuntimeException ); + + virtual rtl::OUString SAL_CALL getDisplayDirectory( ) + throw( com::sun::star::uno::RuntimeException ); + + virtual rtl::OUString SAL_CALL getDirectory( ) + throw( com::sun::star::uno::RuntimeException ); + +protected: + virtual void SAL_CALL onSelChanged( const rtl::OUString& aNewPath ); + +private: + CFolderPicker* m_pFolderPicker; + sal_Int16 m_nLastDlgResult; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/folderpicker/fop.xml b/fpicker/source/win32/folderpicker/fop.xml new file mode 100644 index 000000000000..7c6835a88cb9 --- /dev/null +++ b/fpicker/source/win32/folderpicker/fop.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + <module-name>fop</module-name> + <component-description> + <author> Tino Rachui </author> + <name>com.sun.star.comp.ui.dialogs.FolderPicker</name> + <description> + The win32 implementation of the FolderPicker service. +</description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language> c++ </language> + <status value="beta"/> + <supported-service> com.sun.star.ui.dialogs.FolderPicker </supported-service> + <service-dependency>...</service-dependency> + <type> com.sun.star.ui.dialogs.XExecutableDialog </type> + <type> com.sun.star.ui.dialogs.XFolderPicker </type> + <type> com.sun.star.ui.dialogs.ExecutableDialogException </type> + <type> com.sun.star.ui.dialogs.ExecutableDialogResults </type> + <type> com.sun.star.ui.dialogs.ExtendedFilePickerElementIds </type> + <type> com.sun.star.ui.dialogs.CommonFilePickerElementIds </type> + <type> com.sun.star.util.XCancellable </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.lang.IllegalArgumentException </type> + <type> com.sun.star.uno.TypeClass </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.uno.XAggregation </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.container.XSet </type> + </component-description> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> sal </project-build-dependency> + <runtime-module-dependency> cppuhelper </runtime-module-dependency> + <runtime-module-dependency> cppu2 </runtime-module-dependency> + <runtime-module-dependency> sal2 </runtime-module-dependency> +</module-description> diff --git a/fpicker/source/win32/folderpicker/makefile.mk b/fpicker/source/win32/folderpicker/makefile.mk new file mode 100644 index 000000000000..7f0556d7cecb --- /dev/null +++ b/fpicker/source/win32/folderpicker/makefile.mk @@ -0,0 +1,51 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. +PRJNAME=fpicker +TARGET=fop +#LIBTARGET=NO +ENABLE_EXCEPTIONS=TRUE +COMP1TYPELIST=$(TARGET) + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +# enable rtti +CFLAGS+=-GR + +SLOFILES=$(SLO)$/fopentry.obj\ + $(SLO)$/folderpicker.obj\ + $(SLO)$/WinFopImpl.obj\ + $(SLO)$/MtaFop.obj + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/fpicker/source/win32/folderpicker/workbench/Test_fops.cxx b/fpicker/source/win32/folderpicker/workbench/Test_fops.cxx new file mode 100644 index 000000000000..d4b2aa279697 --- /dev/null +++ b/fpicker/source/win32/folderpicker/workbench/Test_fops.cxx @@ -0,0 +1,200 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + + +//----------------------------------------------------------- +// interface includes +//----------------------------------------------------------- +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/registry/XSimpleRegistry.hpp> +#include <osl/file.hxx> + +//-------------------------------------------------------------- +// other includes +//-------------------------------------------------------------- +#include <cppuhelper/servicefactory.hxx> + +#ifndef _RTL_USTRING_ +#include <rtl/ustring.hxx> +#endif +#include <sal/types.h> +#include <osl/diagnose.h> + +#include <com/sun/star/ui/dialogs/XFolderPicker.hpp> + +#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> +#include <cppuhelper/implbase1.hxx> + +#include <stdio.h> + +#include "..\FOPServiceInfo.hxx" + +#include <osl/file.hxx> + +#define _WIN32_DCOM + +#include <windows.h> + +//-------------------------------------------------------------- +// namesapces +//-------------------------------------------------------------- + +using namespace ::rtl ; +using namespace ::cppu ; +using namespace ::com::sun::star::uno ; +using namespace ::com::sun::star::lang ; +using namespace ::com::sun::star::ui::dialogs; +using namespace std ; + +//-------------------------------------------------------------- +// defines +//-------------------------------------------------------------- + +#define RDB_SYSPATH "D:\\Projects\\gsl\\sysui\\wntmsci7\\bin\\applicat.rdb" + +//-------------------------------------------------------------- +// global variables +//-------------------------------------------------------------- + +Reference< XMultiServiceFactory > g_xFactory; + +/* +void CreateDeepDirectory( ) +{ + // create a deep directory + + OUString aPathURL( L"file:///d|/Deep" ); + OUString normalizedPath; + + OSL_ASSERT( ::osl::FileBase::E_None == \ + ::osl::FileBase::getNormalizedPathFromFileURL( aPathURL, normalizedPath ) ); + + while( ::osl::FileBase::E_None == osl::Directory::create( normalizedPath ) ) + { + aPathURL += L"/Deep"; + OSL_ASSERT( ::osl::FileBase::E_None == \ + ::osl::FileBase::getNormalizedPathFromFileURL( aPathURL, normalizedPath ) ); + } + +} +*/ + +//-------------------------------------------------------------- +// main +//-------------------------------------------------------------- + + +int SAL_CALL main(int /*nArgc*/, char* /*Argv[]*/, char* /*Env[]*/ ) +{ + CoInitializeEx( NULL, COINIT_MULTITHREADED ); + + printf("Starting test of FolderPicker Service\n"); + + //CreateDeepDirectory( ); + + //------------------------------------------------- + // get the global service-manager + //------------------------------------------------- + + // Get global factory for uno services. + OUString rdbName = OUString( RTL_CONSTASCII_USTRINGPARAM( RDB_SYSPATH ) ); + Reference< XMultiServiceFactory > g_xFactory( createRegistryServiceFactory( rdbName ) ); + + // Print a message if an error occured. + if ( g_xFactory.is() == sal_False ) + { + OSL_ENSURE(sal_False, "Can't create RegistryServiceFactory"); + return(-1); + } + + printf("Creating RegistryServiceFactory successful\n"); + + //------------------------------------------------- + // try to get an Interface to a XFilePicker Service + //------------------------------------------------- + + Reference< XFolderPicker > xFolderPicker; + + xFolderPicker = Reference< XFolderPicker >( + g_xFactory->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM ( FOLDER_PICKER_SERVICE_NAME ) ) ), UNO_QUERY ); + + if ( xFolderPicker.is() == sal_False ) + { + OSL_ENSURE( sal_False, "Error creating FolderPicker Service" ); + return(-1); + } + + try + { + xFolderPicker->setDisplayDirectory( L"file:///C|" ); + xFolderPicker->setTitle( L"FolderBrowse Dialog" ); + xFolderPicker->execute( ); + + OUString rootDir = xFolderPicker->getDisplayDirectory( ); + OUString selectedDir = xFolderPicker->getDirectory( ); + + xFolderPicker->setDisplayDirectory( selectedDir ); + xFolderPicker->execute( ); + + rootDir = xFolderPicker->getDisplayDirectory( ); + selectedDir = xFolderPicker->getDirectory( ); + } + catch( ::com::sun::star::uno::Exception& ) + { + MessageBox( NULL, "Exception caught!", "Error", MB_OK ); + } + + //-------------------------------------------------- + // shutdown + //-------------------------------------------------- + + // Cast factory to XComponent + Reference< XComponent > xComponent( g_xFactory, UNO_QUERY ); + + // Print a message if an error occured. + if ( xComponent.is() == sal_False ) + { + OSL_ENSURE(sal_False, "Error shuting down"); + } + + // Dispose and clear factory + xComponent->dispose(); + g_xFactory.clear(); + g_xFactory = Reference< XMultiServiceFactory >(); + + printf("Test successful\n"); + + CoUninitialize( ); + + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/folderpicker/workbench/makefile.mk b/fpicker/source/win32/folderpicker/workbench/makefile.mk new file mode 100644 index 000000000000..bfdf840989f8 --- /dev/null +++ b/fpicker/source/win32/folderpicker/workbench/makefile.mk @@ -0,0 +1,62 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/..$/.. + +PRJNAME= sysui +TARGET= testfops +LIBTARGET= NO +TARGETTYPE= CUI + + +# --- Settings ----------------------------------------------------- +#.INCLUDE : $(PRJ)$/util$/makefile.pmk + +.INCLUDE : settings.mk + +CFLAGS+=-GR -EHa + +# --- Files -------------------------------------------------------- + + +OBJFILES= $(OBJ)$/test_fops.obj + +APP1TARGET= test_fops + +APP1OBJS= $(OBJ)$/test_fops.obj + +APP1STDLIBS+= $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALLIB) \ + $(USER32LIB)\ + $(OLE32LIB) + +APP1DEF= $(MISC)$/$(APP1TARGET).def + +# --- Targets ------------------------------------------------------ +.INCLUDE : target.mk + diff --git a/fpicker/source/win32/misc/AutoBuffer.cxx b/fpicker/source/win32/misc/AutoBuffer.cxx new file mode 100644 index 000000000000..00c0f91fbf42 --- /dev/null +++ b/fpicker/source/win32/misc/AutoBuffer.cxx @@ -0,0 +1,172 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ +#include "AutoBuffer.hxx" +#include <osl/diagnose.h> + +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +//------------------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------------------ + +using rtl::OUString; + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +CAutoUnicodeBuffer::CAutoUnicodeBuffer( size_t size, sal_Bool bLazyCreation ) : + m_buffSize( size ), + m_pBuff( NULL ) +{ + if ( !bLazyCreation ) + init( ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +CAutoUnicodeBuffer::~CAutoUnicodeBuffer( ) +{ + delete [] m_pBuff; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_Bool SAL_CALL CAutoUnicodeBuffer::resize( size_t new_size ) +{ + if ( new_size != m_buffSize ) + { + if ( new_size > m_buffSize ) + { + delete [] m_pBuff; + m_pBuff = NULL; + } + + m_buffSize = new_size; + } + + return sal_True; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void SAL_CALL CAutoUnicodeBuffer::empty( ) +{ + if ( m_pBuff ) + ZeroMemory( m_pBuff, m_buffSize * sizeof( sal_Unicode ) ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_Bool SAL_CALL CAutoUnicodeBuffer::fill( const sal_Unicode* pContent, size_t nLen ) +{ + OSL_ASSERT( pContent && m_buffSize && (m_buffSize >= nLen) ); + + init( ); + + sal_Bool bRet = sal_False; + + if ( m_pBuff && pContent && nLen ) + { + CopyMemory( m_pBuff, pContent, nLen * sizeof( sal_Unicode ) ); + bRet = sal_True; + } + + return bRet; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +size_t SAL_CALL CAutoUnicodeBuffer::size( ) const +{ + return m_buffSize; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +CAutoUnicodeBuffer::operator sal_Unicode*( ) +{ + return m_pBuff; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_Unicode* CAutoUnicodeBuffer::operator&( ) +{ + return m_pBuff; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +const sal_Unicode* CAutoUnicodeBuffer::operator&( ) const +{ + return m_pBuff; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void SAL_CALL CAutoUnicodeBuffer::init( ) +{ + if ( !m_pBuff && (m_buffSize > 0) ) + m_pBuff = new sal_Unicode[ m_buffSize ]; + + empty( ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/misc/AutoBuffer.hxx b/fpicker/source/win32/misc/AutoBuffer.hxx new file mode 100644 index 000000000000..6b287d2556b0 --- /dev/null +++ b/fpicker/source/win32/misc/AutoBuffer.hxx @@ -0,0 +1,85 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _AUTO_BUFFER_HXX_ +#define _AUTO_BUFFER_HXX_ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <sal/types.h> +#include <rtl/ustring.hxx> + +//------------------------------------------------------------- +// A simple unicode buffer management class, the class itself +// is responsible for the allocated unicode buffer, any +// modification of the buffer size outside the class may lead +// to undefined behaviour +//------------------------------------------------------------- + +class CAutoUnicodeBuffer +{ +public: + + // if bLazyCreation is true the buffer will be created + // when someone wants to fill the buffer + CAutoUnicodeBuffer( size_t size, sal_Bool bLazyCreation = sal_False ); + ~CAutoUnicodeBuffer( ); + + // resizes the buffer + sal_Bool SAL_CALL resize( size_t new_size ); + + // zeros the buffer + void SAL_CALL empty( ); + + // fills the buffer with a given content + sal_Bool SAL_CALL fill( const sal_Unicode* pContent, size_t nLen ); + + // returns the size of the buffer + size_t SAL_CALL size( ) const; + + // conversion operator + operator sal_Unicode*( ); + + // address operator + sal_Unicode* operator&( ); + + const sal_Unicode* operator&( ) const; + +private: + void SAL_CALL init( ); + +private: + size_t m_buffSize; // the number of unicode chars + sal_Unicode* m_pBuff; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/misc/WinImplHelper.cxx b/fpicker/source/win32/misc/WinImplHelper.cxx new file mode 100644 index 000000000000..301a5bc9e6bc --- /dev/null +++ b/fpicker/source/win32/misc/WinImplHelper.cxx @@ -0,0 +1,612 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ +#include <osl/diagnose.h> +#include <rtl/ustrbuf.hxx> +#include "AutoBuffer.hxx" +#include "WinImplHelper.hxx" +#include <com/sun/star/uno/Sequence.hxx> + +//------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------ + +using rtl::OUString; +using rtl::OUStringBuffer; +using ::com::sun::star::lang::IllegalArgumentException; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::XInterface; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Sequence; + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +const rtl::OUString TILDE(RTL_CONSTASCII_USTRINGPARAM( "~" )); +const sal_Unicode TILDE_SIGN = L'~'; +const rtl::OUString AMPERSAND(RTL_CONSTASCII_USTRINGPARAM( "&" )); +const sal_Unicode AMPERSAND_SIGN = L'&'; + +//------------------------------------------------------------ +// OS NAME Platform Major Minor +// +// Windows NT 3.51 VER_PLATFORM_WIN32_NT 3 51 +// Windows NT 4.0 VER_PLATFORM_WIN32_NT 4 0 +// Windows 2000 VER_PLATFORM_WIN32_NT 5 0 +// Windows XP VER_PLATFORM_WIN32_NT 5 1 +// Windows Vista VER_PLATFORM_WIN32_NT 6 0 +// Windows 7 VER_PLATFORM_WIN32_NT 6 1 +// Windows 95 VER_PLATFORM_WIN32_WINDOWS 4 0 +// Windows 98 VER_PLATFORM_WIN32_WINDOWS 4 10 +// Windows ME VER_PLATFORM_WIN32_WINDOWS 4 90 +//------------------------------------------------------------ + +bool SAL_CALL IsWindowsVersion(unsigned int PlatformId, unsigned int MajorVersion, int MinorVersion = -1) +{ + OSVERSIONINFO osvi; + osvi.dwOSVersionInfoSize = sizeof(osvi); + + if(!GetVersionEx(&osvi)) + return false; + + bool bRet = (PlatformId == osvi.dwPlatformId) && + (MajorVersion == osvi.dwMajorVersion); + + if (MinorVersion > -1) + bRet = bRet && + (sal::static_int_cast< unsigned int >(MinorVersion) == + osvi.dwMinorVersion); + + return bRet; +} + +//------------------------------------------------------------ +// determine if we are running under Vista or newer OS +//------------------------------------------------------------ + +bool SAL_CALL IsWindowsVistaOrNewer() +{ + OSVERSIONINFO osvi; + osvi.dwOSVersionInfoSize = sizeof(osvi); + + if(!GetVersionEx(&osvi)) + return false; + + bool bRet = (VER_PLATFORM_WIN32_NT == osvi.dwPlatformId) && + (osvi.dwMajorVersion >= 6); + + bRet = bRet && + (osvi.dwMinorVersion >= + sal::static_int_cast< unsigned int >(0)); + + return bRet; +} + +//------------------------------------------------------------ +// determine if we are running under Windows 7 +//------------------------------------------------------------ + +bool SAL_CALL IsWindows7() +{ + return IsWindowsVersion(VER_PLATFORM_WIN32_NT, 6, 1); +} + +//------------------------------------------------------------ +// determine if we are running under Windows Vista +//------------------------------------------------------------ + +bool SAL_CALL IsWindowsVista() +{ + return IsWindowsVersion(VER_PLATFORM_WIN32_NT, 6, 0); +} + +//------------------------------------------------------------ +// determine if we are running under Windows XP +//------------------------------------------------------------ + +bool SAL_CALL IsWindowsXP() +{ + return IsWindowsVersion(VER_PLATFORM_WIN32_NT, 5, 1); +} + +//------------------------------------------------------------ +// determine if we are running under Windows 2000 +//------------------------------------------------------------ + +bool SAL_CALL IsWindows2000() +{ + return IsWindowsVersion(VER_PLATFORM_WIN32_NT, 5, 0); +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +bool SAL_CALL IsWindows98() +{ + return IsWindowsVersion(VER_PLATFORM_WIN32_WINDOWS, 4, 10); +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +bool SAL_CALL IsWindowsME() +{ + return IsWindowsVersion(VER_PLATFORM_WIN32_WINDOWS, 4, 90); +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +bool SAL_CALL IsWindows2000Platform() +{ + // POST: return true if we are at least on Windows 2000 + + // WRONG!: return IsWindowsVersion(VER_PLATFORM_WIN32_NT, 5); + + OSVERSIONINFO osvi; + ZeroMemory(&osvi, sizeof(osvi)); + osvi.dwOSVersionInfoSize = sizeof(osvi); + GetVersionEx(&osvi); + if ( osvi.dwMajorVersion >= 5 ) + { + return true; + } + return false; +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +void SAL_CALL ListboxAddString( HWND hwnd, const OUString& aString ) +{ + LRESULT rc = SendMessageW( + hwnd, CB_ADDSTRING, 0, reinterpret_cast< LPARAM >(aString.getStr( )) ); + (void) rc; // avoid warning + OSL_ASSERT( (CB_ERR != rc) && (CB_ERRSPACE != rc) ); +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +OUString SAL_CALL ListboxGetString( HWND hwnd, sal_Int32 aPosition ) +{ + OSL_ASSERT( IsWindow( hwnd ) ); + + OUString aString; + + LRESULT lItem = + SendMessageW( hwnd, CB_GETLBTEXTLEN, aPosition, 0 ); + + if ( (CB_ERR != lItem) && (lItem > 0) ) + { + // message returns the len of a combobox item + // without trailing '\0' that's why += 1 + lItem++; + + CAutoUnicodeBuffer aBuff( lItem ); + + LRESULT lRet = + SendMessageW( + hwnd, CB_GETLBTEXT, aPosition, + reinterpret_cast<LPARAM>(&aBuff) ); + + OSL_ASSERT( lRet != CB_ERR ); + + if ( CB_ERR != lRet ) + aString = OUString( aBuff, lRet ); + } + + return aString; +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +void SAL_CALL ListboxAddItem( HWND hwnd, const Any& aItem, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos ) + throw( IllegalArgumentException ) +{ + OSL_ASSERT( IsWindow( hwnd ) ); + + if ( !aItem.hasValue( ) || + aItem.getValueType( ) != getCppuType((OUString*)0) ) + throw IllegalArgumentException( + OUString(RTL_CONSTASCII_USTRINGPARAM( "invalid value type or any has no value" )), + rXInterface, + aArgPos ); + + OUString cbItem; + aItem >>= cbItem; + + ListboxAddString( hwnd, cbItem ); +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +void SAL_CALL ListboxAddItems( HWND hwnd, const Any& aItemList, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos ) + throw( IllegalArgumentException ) +{ + OSL_ASSERT( IsWindow( hwnd ) ); + + if ( !aItemList.hasValue( ) || + aItemList.getValueType( ) != getCppuType((Sequence<OUString>*)0) ) + throw IllegalArgumentException( + OUString(RTL_CONSTASCII_USTRINGPARAM( "invalid value type or any has no value" )), + rXInterface, + aArgPos ); + + Sequence< OUString > aStringList; + aItemList >>= aStringList; + + sal_Int32 nItemCount = aStringList.getLength( ); + for( sal_Int32 i = 0; i < nItemCount; i++ ) + { + ListboxAddString( hwnd, aStringList[i] ); + } +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +void SAL_CALL ListboxDeleteItem( HWND hwnd, const Any& aPosition, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos ) + throw( IllegalArgumentException ) +{ + OSL_ASSERT( IsWindow( hwnd ) ); + + if ( !aPosition.hasValue( ) || + ( (aPosition.getValueType( ) != getCppuType((sal_Int32*)0)) && + (aPosition.getValueType( ) != getCppuType((sal_Int16*)0)) && + (aPosition.getValueType( ) != getCppuType((sal_Int8*)0)) ) ) + throw IllegalArgumentException( + OUString(RTL_CONSTASCII_USTRINGPARAM( "invalid value type or any has no value" )), + rXInterface, + aArgPos ); + + sal_Int32 nPos; + aPosition >>= nPos; + + LRESULT lRet = SendMessage( hwnd, CB_DELETESTRING, nPos, 0 ); + + // if the return value is CB_ERR the given + // index was not correct + if ( CB_ERR == lRet ) + throw IllegalArgumentException( + OUString(RTL_CONSTASCII_USTRINGPARAM( "invalid item position" )), + rXInterface, + aArgPos ); +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +void SAL_CALL ListboxDeleteItems( HWND hwnd, const Any&, const Reference< XInterface >&, sal_Int16 ) + throw( IllegalArgumentException ) +{ + OSL_ASSERT( IsWindow( hwnd ) ); + + LRESULT lRet = 0; + + do + { + // the return value on success is the number + // of remaining elements in the listbox + lRet = SendMessageW( hwnd, CB_DELETESTRING, 0, 0 ); + } + while ( (lRet != CB_ERR) && (lRet > 0) ); +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +void SAL_CALL ListboxSetSelectedItem( HWND hwnd, const Any& aPosition, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos ) + throw( IllegalArgumentException ) +{ + OSL_ASSERT( IsWindow( hwnd ) ); + + if ( !aPosition.hasValue( ) || + ( (aPosition.getValueType( ) != getCppuType((sal_Int32*)0)) && + (aPosition.getValueType( ) != getCppuType((sal_Int16*)0)) && + (aPosition.getValueType( ) != getCppuType((sal_Int8*)0)) ) ) + throw IllegalArgumentException( + OUString(RTL_CONSTASCII_USTRINGPARAM( "invalid value type or any has no value" )), + rXInterface, + aArgPos ); + + sal_Int32 nPos; + aPosition >>= nPos; + + if ( nPos < -1 ) + throw IllegalArgumentException( + OUString(RTL_CONSTASCII_USTRINGPARAM("invalid index")), + rXInterface, + aArgPos ); + + LRESULT lRet = SendMessageW( hwnd, CB_SETCURSEL, nPos, 0 ); + + if ( (CB_ERR == lRet) && (-1 != nPos) ) + throw IllegalArgumentException( + OUString(RTL_CONSTASCII_USTRINGPARAM("invalid index")), + rXInterface, + aArgPos ); +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +Any SAL_CALL ListboxGetItems( HWND hwnd ) +{ + OSL_ASSERT( IsWindow( hwnd ) ); + + LRESULT nItemCount = SendMessageW( hwnd, CB_GETCOUNT, 0, 0 ); + + Sequence< OUString > aItemList; + + if ( CB_ERR != nItemCount ) + { + aItemList.realloc( nItemCount ); + + for ( sal_Int32 i = 0; i < nItemCount; i++ ) + { + aItemList[i] = ListboxGetString( hwnd, i ); + } + } + + Any aAny; + aAny <<= aItemList; + + return aAny; +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +Any SAL_CALL ListboxGetSelectedItem( HWND hwnd ) +{ + OSL_ASSERT( IsWindow( hwnd ) ); + + LRESULT idxItem = SendMessageW( hwnd, CB_GETCURSEL, 0, 0 ); + + Any aAny; + aAny <<= ListboxGetString( hwnd, idxItem ); + + return aAny; +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +Any SAL_CALL ListboxGetSelectedItemIndex( HWND hwnd ) +{ + OSL_ASSERT( IsWindow( hwnd ) ); + + LRESULT idxItem = SendMessageW( hwnd, CB_GETCURSEL, 0, 0 ); + + Any aAny; + aAny <<= static_cast< sal_Int32 >( idxItem ); + + return aAny; +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +Any SAL_CALL CheckboxGetState( HWND hwnd ) +{ + OSL_ASSERT( IsWindow( hwnd ) ); + + LRESULT lChkState = SendMessageW( hwnd, BM_GETCHECK, 0, 0 ); + sal_Bool bChkState = (lChkState == BST_CHECKED) ? sal_True : sal_False; + Any aAny; + aAny.setValue( &bChkState, getCppuType((sal_Bool*)0) ); + return aAny; +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +void SAL_CALL CheckboxSetState( + HWND hwnd, const ::com::sun::star::uno::Any& aState, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos ) + throw( IllegalArgumentException ) +{ + OSL_ASSERT( IsWindow( hwnd ) ); + + if ( !aState.hasValue( ) || + aState.getValueType( ) != getCppuType((sal_Bool*)0) ) + throw IllegalArgumentException( + OUString(RTL_CONSTASCII_USTRINGPARAM( "invalid value type or any has no value" )), + rXInterface, + aArgPos ); + + sal_Bool bCheckState = *reinterpret_cast< const sal_Bool* >( aState.getValue( ) ); + WPARAM wParam = bCheckState ? BST_CHECKED : BST_UNCHECKED; + SendMessageW( hwnd, BM_SETCHECK, wParam, 0 ); +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +sal_uInt32 SAL_CALL _wcslenex( const sal_Unicode* pStr ) +{ + if ( !pStr ) + return 0; + + const sal_Unicode* pTemp = pStr; + sal_uInt32 strLen = 0; + while( *pTemp || *(pTemp + 1) ) + { + pTemp++; + strLen++; + } + + return strLen; +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +void Replace( const OUString& aLabel, sal_Unicode OldChar, sal_Unicode NewChar, OUStringBuffer& aBuffer ) +{ + OSL_ASSERT( aLabel.getLength( ) ); + OSL_ASSERT( aBuffer.getCapacity( ) >= (aLabel.getLength( )) ); + + sal_Int32 i = 0; + const sal_Unicode* pCurrent = aLabel.getStr( ); + const sal_Unicode* pNext = aLabel.getStr( ) + 1; + const sal_Unicode* pEnd = aLabel.getStr( ) + aLabel.getLength( ); + + while( pCurrent < pEnd ) + { + OSL_ASSERT( pNext <= pEnd ); + OSL_ASSERT( (i >= 0) && (i < aBuffer.getCapacity( )) ); + + if ( OldChar == *pCurrent ) + { + if ( OldChar == *pNext ) + { + // two OldChars in line will + // be replaced by one + // e.g. ~~ -> ~ + aBuffer.insert( i, *pCurrent ); + + // skip the next one + pCurrent++; + pNext++; + } + else + { + // one OldChar will be replace + // by NexChar + aBuffer.insert( i, NewChar ); + } + } + else if ( *pCurrent == NewChar ) + { + // a NewChar will be replaced by + // two NewChars + // e.g. & -> && + aBuffer.insert( i++, *pCurrent ); + aBuffer.insert( i, *pCurrent ); + } + else + { + aBuffer.insert( i, *pCurrent ); + } + + pCurrent++; + pNext++; + i++; + } +} + +//------------------------------------------------------------ +// converts a soffice label to a windows label +// the following rules for character replacements +// will be done: +// '~' -> '&' +// '~~' -> '~' +// '&' -> '&&' +//------------------------------------------------------------ + +OUString SOfficeToWindowsLabel( const rtl::OUString& aSOLabel ) +{ + OUString aWinLabel = aSOLabel; + + if ( (aWinLabel.indexOf( TILDE ) > -1) || (aWinLabel.indexOf( AMPERSAND ) > -1) ) + { + sal_Int32 nStrLen = aWinLabel.getLength( ); + + // in the worst case the new string is + // doubled in length, maybe some waste + // of memory but how long is a label + // normaly(?) + rtl::OUStringBuffer aBuffer( nStrLen * 2 ); + + Replace( aWinLabel, TILDE_SIGN, AMPERSAND_SIGN, aBuffer ); + + aWinLabel = aBuffer.makeStringAndClear( ); + } + + return aWinLabel; +} + +//------------------------------------------------------------ +// converts a windows label to a soffice label +// the following rules for character replacements +// will be done: +// '&' -> '~' +// '&&' -> '&' +// '~' -> '~~' +//------------------------------------------------------------ + +OUString WindowsToSOfficeLabel( const rtl::OUString& aWinLabel ) +{ + OUString aSOLabel = aWinLabel; + + if ( (aSOLabel.indexOf( TILDE ) > -1) || (aSOLabel.indexOf( AMPERSAND ) > -1) ) + { + sal_Int32 nStrLen = aSOLabel.getLength( ); + + // in the worst case the new string is + // doubled in length, maybe some waste + // of memory but how long is a label + // normaly(?) + rtl::OUStringBuffer aBuffer( nStrLen * 2 ); + + Replace( aSOLabel, AMPERSAND_SIGN, TILDE_SIGN, aBuffer ); + + aSOLabel = aBuffer.makeStringAndClear( ); + } + + return aSOLabel; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/misc/WinImplHelper.hxx b/fpicker/source/win32/misc/WinImplHelper.hxx new file mode 100644 index 000000000000..03cefe901124 --- /dev/null +++ b/fpicker/source/win32/misc/WinImplHelper.hxx @@ -0,0 +1,126 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _WINIMPLHELPER_HXX_ +#define _WINIMPLHELPER_HXX_ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <sal/types.h> +#include <rtl/ustring.hxx> + +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +//------------------------------------------------------------------------ +// deklarations +//------------------------------------------------------------------------ + +bool SAL_CALL IsWindowsVistaOrNewer(); +bool SAL_CALL IsWindows7(); +bool SAL_CALL IsWindowsVista(); +bool SAL_CALL IsWindows2000(); +bool SAL_CALL IsWindowsXP(); +bool SAL_CALL IsWindows98(); +bool SAL_CALL IsWindowsME(); + +// returns true if the platform is +// Windows 2000 or above +bool SAL_CALL IsWindows2000Platform(); + +#define IsWin2000 IsWindows2000 + +// set actions +void SAL_CALL ListboxAddItem( + HWND hwnd, const ::com::sun::star::uno::Any& aItem, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rXInterface, sal_Int16 aArgPos ) + throw( ::com::sun::star::lang::IllegalArgumentException ); + +void SAL_CALL ListboxAddItems( + HWND hwnd, const ::com::sun::star::uno::Any& aItemList, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rXInterface, sal_Int16 aArgPos ) + throw( ::com::sun::star::lang:: IllegalArgumentException ); + +void SAL_CALL ListboxDeleteItem( + HWND hwnd, const ::com::sun::star::uno::Any& aPosition, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rXInterface, sal_Int16 aArgPos ) + throw( ::com::sun::star::lang::IllegalArgumentException ); + +void SAL_CALL ListboxDeleteItems( + HWND hwnd, const ::com::sun::star::uno::Any& aUnused, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rXInterface, sal_Int16 aArgPos ) + throw( ::com::sun::star::lang::IllegalArgumentException ); + +void SAL_CALL ListboxSetSelectedItem( + HWND hwnd, const ::com::sun::star::uno::Any& aPosition, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rXInterface, sal_Int16 aArgPos ) + throw( ::com::sun::star::lang::IllegalArgumentException ); + +// get actions +::com::sun::star::uno::Any SAL_CALL ListboxGetItems( HWND hwnd ); +::com::sun::star::uno::Any SAL_CALL ListboxGetSelectedItem( HWND hwnd ); +::com::sun::star::uno::Any SAL_CALL ListboxGetSelectedItemIndex( HWND hwnd ); + +// checkbox helper functions +::com::sun::star::uno::Any SAL_CALL CheckboxGetState( HWND hwnd ); + +void SAL_CALL CheckboxSetState( + HWND hwnd, const ::com::sun::star::uno::Any& aState, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rXInterface, sal_Int16 aArgPos ) + throw( ::com::sun::star::lang::IllegalArgumentException ); + +// calculates the length of '\0' separated and '\0\0' +// ending strings used in some Win32 functions +// e.g. Filter\0*.txt\0\0 +// the returned length excludes the last '\0' +sal_uInt32 SAL_CALL _wcslenex( const sal_Unicode* pStr ); + + +// converts a soffice label to a windows label +// the following rules for character replacements +// will be done: +// '~' -> '&' +// '~~' -> '~' +// '&' -> '&&' +rtl::OUString SOfficeToWindowsLabel( const rtl::OUString& aSOLabel ); + +// converts a windows label to a soffice label +// the following rules for character replacements +// will be done: +// '&' -> '~' +// '&&' -> '&' +// '~' -> '~~' +rtl::OUString WindowsToSOfficeLabel( const rtl::OUString& aWinLabel ); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/misc/makefile.mk b/fpicker/source/win32/misc/makefile.mk new file mode 100644 index 000000000000..70faefdeaef4 --- /dev/null +++ b/fpicker/source/win32/misc/makefile.mk @@ -0,0 +1,57 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. +PRJNAME=fpicker +TARGET=utils +LIBTARGET=NO +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk + +.IF "$(COM)"=="GCC" +CFLAGSAPPEND+=-fexceptions -fno-enforce-eh-specs -DUNICODE -D_UNICODE +.ELSE +CFLAGS+=-EHa -DUNICODE -D_UNICODE +.ENDIF + +# --- Files ------------------------------------- + +SLOFILES=$(SLO)$/WinImplHelper.obj\ + $(SLO)$/AutoBuffer.obj\ + $(SLO)$/resourceprovider.obj + +LIB1TARGET=$(SLB)$/$(TARGET).lib +LIB1OBJFILES=$(SLOFILES) + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + + diff --git a/fpicker/source/win32/misc/resourceprovider.cxx b/fpicker/source/win32/misc/resourceprovider.cxx new file mode 100644 index 000000000000..d0ee330cc170 --- /dev/null +++ b/fpicker/source/win32/misc/resourceprovider.cxx @@ -0,0 +1,195 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ +#include <osl/diagnose.h> +#include <rtl/ustrbuf.hxx> +#include "resourceprovider.hxx" +#include <osl/mutex.hxx> +#include <vcl/svapp.hxx> + +#include <tools/simplerm.hxx> +#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> + +#include <svtools/svtools.hrc> + +//------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------ + +using rtl::OUString; +using namespace ::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds; +using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds; + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +#define FOLDERPICKER_TITLE 500 +#define FOLDER_PICKER_DEF_DESCRIPTION 501 + +//------------------------------------------------------------ +// we have to translate control ids to resource ids +//------------------------------------------------------------ + +struct _Entry +{ + sal_Int32 ctrlId; + sal_Int16 resId; +}; + +_Entry CtrlIdToResIdTable[] = { + { CHECKBOX_AUTOEXTENSION, STR_SVT_FILEPICKER_AUTO_EXTENSION }, + { CHECKBOX_PASSWORD, STR_SVT_FILEPICKER_PASSWORD }, + { CHECKBOX_FILTEROPTIONS, STR_SVT_FILEPICKER_FILTER_OPTIONS }, + { CHECKBOX_READONLY, STR_SVT_FILEPICKER_READONLY }, + { CHECKBOX_LINK, STR_SVT_FILEPICKER_INSERT_AS_LINK }, + { CHECKBOX_PREVIEW, STR_SVT_FILEPICKER_SHOW_PREVIEW }, + { PUSHBUTTON_PLAY, STR_SVT_FILEPICKER_PLAY }, + { LISTBOX_VERSION_LABEL, STR_SVT_FILEPICKER_VERSION }, + { LISTBOX_TEMPLATE_LABEL, STR_SVT_FILEPICKER_TEMPLATES }, + { LISTBOX_IMAGE_TEMPLATE_LABEL, STR_SVT_FILEPICKER_IMAGE_TEMPLATE }, + { CHECKBOX_SELECTION, STR_SVT_FILEPICKER_SELECTION }, + { FOLDERPICKER_TITLE, STR_SVT_FOLDERPICKER_DEFAULT_TITLE }, + { FOLDER_PICKER_DEF_DESCRIPTION, STR_SVT_FOLDERPICKER_DEFAULT_DESCRIPTION } +}; + +const sal_Int32 SIZE_TABLE = sizeof( CtrlIdToResIdTable ) / sizeof( _Entry ); + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +sal_Int16 CtrlIdToResId( sal_Int32 aControlId ) +{ + sal_Int16 aResId = -1; + + for ( sal_Int32 i = 0; i < SIZE_TABLE; i++ ) + { + if ( CtrlIdToResIdTable[i].ctrlId == aControlId ) + { + aResId = CtrlIdToResIdTable[i].resId; + break; + } + } + + return aResId; +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +class CResourceProvider_Impl +{ +public: + + //------------------------------------- + // + //------------------------------------- + + CResourceProvider_Impl( ) + { + const SolarMutexGuard aGuard; + + com::sun::star::lang::Locale aLoc( Application::GetSettings().GetUILocale() ); + m_ResMgr = new SimpleResMgr( CREATEVERSIONRESMGR_NAME( fps_office ), aLoc ); + } + + //------------------------------------- + // + //------------------------------------- + + ~CResourceProvider_Impl( ) + { + delete m_ResMgr; + } + + //------------------------------------- + // + //------------------------------------- + + OUString getResString( sal_Int16 aId ) + { + OUString aResOUString; + + try + { + OSL_ASSERT( m_ResMgr ); + + // translate the control id to a resource id + sal_Int16 aResId = CtrlIdToResId( aId ); + + if ( aResId > -1 ) + aResOUString = m_ResMgr->ReadString( aResId ); + } + catch(...) + { + } + + return aResOUString; + } + +public: + SimpleResMgr* m_ResMgr; +}; + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +CResourceProvider::CResourceProvider( ) : + m_pImpl( new CResourceProvider_Impl() ) +{ +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +CResourceProvider::~CResourceProvider( ) +{ + delete m_pImpl; +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +OUString CResourceProvider::getResString( sal_Int16 aId ) +{ + return m_pImpl->getResString( aId ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fpicker/source/win32/misc/resourceprovider.hxx b/fpicker/source/win32/misc/resourceprovider.hxx new file mode 100644 index 000000000000..3b887e602a48 --- /dev/null +++ b/fpicker/source/win32/misc/resourceprovider.hxx @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _RESOURCEPROVIDER_HXX_ +#define _RESOURCEPROVIDER_HXX_ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <sal/types.h> + +#include <rtl/ustring.hxx> + +//------------------------------------------------------------------------ +// deklarations +//------------------------------------------------------------------------ + +class CResourceProvider_Impl; + +class CResourceProvider +{ +public: + CResourceProvider( ); + ~CResourceProvider( ); + + rtl::OUString getResString( sal_Int16 aId ); + +private: + CResourceProvider_Impl* m_pImpl; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |