20#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
21#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
22#include <com/sun/star/ui/dialogs/ControlActions.hpp>
23#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
24#include <osl/mutex.hxx>
33#define POPUP_WIDTH_MIN 200
34#define POPUP_WIDTH_MAX 350
37using namespace ::com::sun::star::ui::dialogs::TemplateDescription;
38using namespace ::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds;
39using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds;
43uno::Any HandleGetListValue(
const NSControl* pControl,
const sal_Int16 nControlAction)
47 if ([pControl
class] != [NSPopUpButton
class]) {
48 SAL_INFO(
"fpicker.aqua",
"not a popup button");
52 NSPopUpButton *pButton =
static_cast<NSPopUpButton*
>(pControl);
53 NSMenu *rMenu = [pButton menu];
55 SAL_INFO(
"fpicker.aqua",
"button has no menu");
59 switch (nControlAction)
61 case ControlActions::GET_ITEMS:
63 SAL_INFO(
"fpicker.aqua",
"GET_ITEMS");
64 uno::Sequence< OUString > aItemList;
66 int nItems = [rMenu numberOfItems];
68 aItemList.realloc(nItems);
69 OUString* pItemList = aItemList.getArray();
70 for (
int i = 0;
i < nItems;
i++) {
71 NSString* sCFItem = [pButton itemTitleAtIndex:
i];
73 pItemList[
i] = [sCFItem OUString];
74 SAL_INFO(
"fpicker.aqua",
"Return value[" << (
i - 1) <<
"]: " << aItemList[
i - 1]);
82 case ControlActions::GET_SELECTED_ITEM:
84 SAL_INFO(
"fpicker.aqua",
"GET_SELECTED_ITEM");
85 NSString* sCFItem = [pButton titleOfSelectedItem];
87 OUString sString = [sCFItem OUString];
88 SAL_INFO(
"fpicker.aqua",
"Return value: " << sString);
93 case ControlActions::GET_SELECTED_ITEM_INDEX:
95 SAL_INFO(
"fpicker.aqua",
"GET_SELECTED_ITEM_INDEX");
96 sal_Int32 nActive = [pButton indexOfSelectedItem];
97 SAL_INFO(
"fpicker.aqua",
"Return value: " << nActive);
102 SAL_INFO(
"fpicker.aqua",
"undocumented/unimplemented ControlAction for a list");
109NSTextField* createLabelWithString(NSString* labelString)
111 NSTextField *textField = [NSTextField
new];
112 [textField setEditable:
NO];
113 [textField setSelectable:
NO];
114 [textField setDrawsBackground:
NO];
115 [textField setBordered:
NO];
116 [[textField cell] setTitle:labelString];
123#pragma mark Constructor / Destructor
128: m_pUserPane(nullptr)
129, m_pFilterControl(nil)
130, m_bUserPaneNeeded( false )
131, m_bIsUserPaneLaidOut(false)
132, m_bIsFilterControlNeeded(false)
133, m_pFilterHelper(nullptr)
148 NSAutoreleasePool *pool = [NSAutoreleasePool
new];
161 if (sLabelName != nil) {
162 [sLabelName release];
164 if ([activeControl
class] == [NSPopUpButton
class]) {
170 [activeControl release];
176#pragma mark XInitialization delegate
182 switch( nTemplateId )
184 case FILESAVE_AUTOEXTENSION_PASSWORD:
189 case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS:
195 case FILESAVE_AUTOEXTENSION_SELECTION:
199 case FILESAVE_AUTOEXTENSION_TEMPLATE:
203 case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE:
208 case FILEOPEN_LINK_PREVIEW_IMAGE_ANCHOR:
213 case FILEOPEN_READONLY_VERSION:
217 case FILEOPEN_LINK_PREVIEW:
221 case FILESAVE_AUTOEXTENSION:
224 case FILEOPEN_PREVIEW:
227 case FILEOPEN_LINK_PLAY:
234#pragma mark XFilePickerControlAccess delegates
243 if (
nControlId == ExtendedFilePickerElementIds::CHECKBOX_PREVIEW) {
244 SAL_INFO(
"fpicker.aqua",
" preview checkbox cannot be changed");
250 if( pControl != nil ) {
252 SAL_INFO(
"fpicker.aqua",
"enable" );
254 SAL_INFO(
"fpicker.aqua",
"disable" );
256 [pControl setEnabled:bEnable];
268 if( pControl == nil ) {
274 if ([pControl
class] == [NSPopUpButton
class]) {
277 retVal = [temp OUString];
280 NSString* sLabel = [[pControl cell] title];
281 retVal = [sLabel OUString];
291 NSAutoreleasePool *pool = [NSAutoreleasePool
new];
295 if (nil != pControl) {
296 if ([pControl
class] == [NSPopUpButton
class]) {
298 if (sOldName !=
nullptr && sOldName !=
aLabel) {
303 }
else if ([pControl
class] == [NSButton
class]) {
304 [[pControl cell] setTitle:
aLabel];
307 SAL_INFO(
"fpicker.aqua",
"Control not found to set label for");
319 if (
nControlId == ExtendedFilePickerElementIds::CHECKBOX_PREVIEW) {
320 SAL_INFO(
"fpicker.aqua",
" value for preview is unchangeable");
325 if( pControl == nil ) {
328 if( [pControl
class] == [NSPopUpButton
class] ) {
330 }
else if( [pControl
class] == [NSButton
class] ) {
331 bool bChecked =
false;
333 SAL_INFO(
"fpicker.aqua",
" value is a bool: " << bChecked);
334 [
static_cast<NSButton*
>(pControl) setState:(bChecked ? NSControlStateValueOn : NSControlStateValueOff)];
337 SAL_INFO(
"fpicker.aqua",
"Can't set value on button / list " <<
nControlId <<
" " << nControlAction);
350 if( pControl == nil ) {
353 if( [pControl
class] == [NSPopUpButton
class] ) {
354 aRetval = HandleGetListValue(pControl, nControlAction);
355 }
else if( [pControl
class] == [NSButton
class] ) {
357 bool bValue = [
static_cast<NSButton*
>(pControl) state] == NSControlStateValueOn;
359 SAL_INFO(
"fpicker.aqua",
"value is a bool (checkbox): " << bValue);
369 SAL_INFO(
"fpicker.aqua",
"no user pane needed");
374 SAL_INFO(
"fpicker.aqua",
"user pane already exists");
382 NSRect minRect = NSMakeRect(0,0,300,33);
383 m_pUserPane = [[NSView alloc] initWithFrame:minRect];
386 int currentWidth = 300;
388 bool bPopupControlPresent =
false;
389 bool bButtonControlPresent =
false;
391 int nCheckboxMaxWidth = 0;
392 int nPopupMaxWidth = 0;
393 int nPopupLabelMaxWidth = 0;
398 SAL_INFO(
"fpicker.aqua",
"currentHeight: " << currentHeight);
401 [activeControl sizeToFit];
403 NSRect frame = [activeControl frame];
404 SAL_INFO(
"fpicker.aqua",
"frame for control " << [[activeControl description] UTF8String] <<
" is {" << frame.origin.x <<
", " << frame.origin.y <<
", " << frame.size.width <<
", " << frame.size.height <<
"}");
406 int nControlHeight = frame.size.height;
407 int nControlWidth = frame.size.width;
410 if ([activeControl
class] == [NSPopUpButton
class]) {
411 if (bPopupControlPresent) {
420 bPopupControlPresent =
true;
425 NSTextField *textField = createLabelWithString(
label);
426 [textField sizeToFit];
430 NSRect tfRect = [textField frame];
431 SAL_INFO(
"fpicker.aqua",
"frame for textfield " << [[textField description] UTF8String] <<
" is {" << tfRect.origin.x <<
", " << tfRect.origin.y <<
", " << tfRect.size.width <<
", " << tfRect.size.height <<
"}");
433 int tfWidth = tfRect.size.width;
435 if (nPopupLabelMaxWidth < tfWidth) {
436 nPopupLabelMaxWidth = tfWidth;
443 frame.size.width = nControlWidth;
444 [activeControl setFrame:frame];
449 frame.size.width = nControlWidth;
450 [activeControl setFrame:frame];
454 if (nPopupMaxWidth < nControlWidth) {
455 nPopupMaxWidth = nControlWidth;
466 else if ([activeControl
class] == [NSButton
class]) {
472 if (nCheckboxMaxWidth < nControlWidth) {
473 nCheckboxMaxWidth = nControlWidth;
476 bButtonControlPresent =
true;
485 currentHeight += nControlHeight;
491 SAL_INFO(
"fpicker.aqua",
"height after adding all controls: " << currentHeight);
493 if (bPopupControlPresent && bButtonControlPresent)
498 SAL_INFO(
"fpicker.aqua",
"popup extra space added, currentHeight: " << currentHeight);
503 currentWidth = nLongestPopupWidth > nCheckboxMaxWidth ? nLongestPopupWidth : nCheckboxMaxWidth;
504 SAL_INFO(
"fpicker.aqua",
"longest control width: " << currentWidth);
508 if (currentWidth < minRect.size.width)
509 currentWidth = minRect.size.width;
511 if (currentHeight < minRect.size.height)
512 currentHeight = minRect.size.height;
514 NSRect upRect = NSMakeRect(0, 0, currentWidth, currentHeight );
515 SAL_INFO(
"fpicker.aqua",
"setting user pane rect to {" << upRect.origin.x <<
", " << upRect.origin.y <<
", " << upRect.size.width <<
", " << upRect.size.height <<
"}");
522#pragma mark Private / Misc
537#define MAP_LIST_( elem ) \
539 setLabel(ExtendedFilePickerElementIds::LISTBOX_##elem, sLabel); \
562 NSButton *button = [NSButton
new];
563 [button setTitle:sLabel];
565 [button setButtonType:NSButtonTypeSwitch];
567 [button setState:NSControlStateValueOff];
571 [button setAction:
@selector(autoextensionChanged:)];
584 if (pPreviewBox != nil) {
585 [pPreviewBox setEnabled:
NO];
586 [
static_cast<NSButton*
>(pPreviewBox) setState:NSControlStateValueOn];
590#define TOGGLE_ELEMENT( elem ) \
592 nReturn = CHECKBOX_##elem; \
594#define LIST_ELEMENT( elem ) \
596 nReturn = LISTBOX_##elem##_LABEL; \
602 if (aClazz == [NSButton
class])
615 else if (aClazz == [NSPopUpButton
class])
630 if ([pControl
class] != [NSPopUpButton
class]) {
631 SAL_INFO(
"fpicker.aqua",
"not a popup menu");
635 NSPopUpButton *pButton =
static_cast<NSPopUpButton*
>(pControl);
636 NSMenu *rMenu = [pButton menu];
638 SAL_INFO(
"fpicker.aqua",
"button has no menu");
642 switch (nControlAction)
644 case ControlActions::ADD_ITEM:
646 SAL_INFO(
"fpicker.aqua",
"ADD_ITEMS");
650 NSString* sCFItem = [NSString stringWithOUString:sItem];
651 SAL_INFO(
"fpicker.aqua",
"Adding menu item: " << sItem);
652 [pButton addItemWithTitle:sCFItem];
655 case ControlActions::ADD_ITEMS:
657 SAL_INFO(
"fpicker.aqua",
"ADD_ITEMS");
661 for (sal_Int32
i = 0;
i < nItemCount; ++
i)
663 NSString* sCFItem = [NSString stringWithOUString:
aStringList[
i]];
665 [pButton addItemWithTitle:sCFItem];
669 case ControlActions::DELETE_ITEM:
671 SAL_INFO(
"fpicker.aqua",
"DELETE_ITEM");
674 SAL_INFO(
"fpicker.aqua",
"Deleting item at position " << (
nPos));
675 [rMenu removeItemAtIndex:
nPos];
678 case ControlActions::DELETE_ITEMS:
680 SAL_INFO(
"fpicker.aqua",
"DELETE_ITEMS");
681 int nItems = [rMenu numberOfItems];
683 SAL_INFO(
"fpicker.aqua",
"no menu items to delete");
686 for(sal_Int32
i = 0;
i < nItems;
i++) {
687 [rMenu removeItemAtIndex:
i];
691 case ControlActions::SET_SELECT_ITEM:
695 SAL_INFO(
"fpicker.aqua",
"Selecting item at position " <<
nPos);
696 [pButton selectItemAtIndex:
nPos];
700 SAL_INFO(
"fpicker.aqua",
"undocumented/unimplemented ControlAction for a list");
710 NSControl* pWidget = nil;
712#define MAP_TOGGLE( elem ) \
713case ExtendedFilePickerElementIds::CHECKBOX_##elem: \
714 pWidget = m_pToggles[elem]; \
717#define MAP_LIST( elem ) \
718case ExtendedFilePickerElementIds::LISTBOX_##elem: \
719 pWidget = m_pListControls[elem]; \
722#define MAP_LIST_LABEL( elem ) \
723case ExtendedFilePickerElementIds::LISTBOX_##elem##_LABEL: \
724 pWidget = m_pListControls[elem]; \
760 SAL_INFO(
"fpicker.aqua",
"no user pane to layout");
765 SAL_INFO(
"fpicker.aqua",
"user pane already laid out");
770 SAL_INFO(
"fpicker.aqua",
"userPane frame: {" << userPaneRect.origin.x <<
", " << userPaneRect.origin.y <<
", " << userPaneRect.size.width <<
", " << userPaneRect.size.height <<
"}");
772 int nUsableWidth = userPaneRect.size.width;
776 int currenttop = userPaneRect.size.height;
777 int nCheckboxMaxWidth = 0;
778 int nPopupMaxWidth = 0;
779 int nPopupLabelMaxWidth = 0;
785 NSRect controlRect = [activeControl frame];
786 int nControlWidth = controlRect.size.width;
788 Class aSubType = [activeControl
class];
789 if (aSubType == [NSPopUpButton
class]) {
790 if (nPopupMaxWidth < nControlWidth) {
791 nPopupMaxWidth = nControlWidth;
794 NSRect labelFrame = [
label frame];
795 int nLabelWidth = labelFrame.size.width;
796 if (nPopupLabelMaxWidth < nLabelWidth) {
797 nPopupLabelMaxWidth = nLabelWidth;
800 if (nCheckboxMaxWidth < nControlWidth) {
801 nCheckboxMaxWidth = nControlWidth;
807 SAL_INFO(
"fpicker.aqua",
"longest popup width: " << nLongestPopupWidth);
809 NSControl* previousControl = nil;
811 int nDistBetweenControls = 0;
816 NSRect controlRect = [activeControl frame];
817 int nControlHeight = controlRect.size.height;
820 currenttop -= nControlHeight;
822 Class aSubType = [activeControl
class];
826 SAL_INFO(
"fpicker.aqua",
"vertical distance: " << nDistBetweenControls);
827 currenttop -= nDistBetweenControls;
829 previousControl = activeControl;
831 if (aSubType == [NSPopUpButton
class]) {
837 NSRect labelFrame = [
label frame];
839 SAL_INFO(
"fpicker.aqua",
"totalWidth: " << totalWidth);
841 int left = (nUsableWidth + nLongestPopupWidth) / 2 - totalWidth;
843 labelFrame.origin.x =
left;
845 SAL_INFO(
"fpicker.aqua",
"setting label at: {" << labelFrame.origin.x <<
", " << labelFrame.origin.y <<
", " << labelFrame.size.width <<
", " << labelFrame.size.height <<
"}");
846 [
label setFrame:labelFrame];
849 controlRect.origin.y = currenttop;
850 controlRect.size.width = nPopupMaxWidth;
851 SAL_INFO(
"fpicker.aqua",
"setting popup at: {" << controlRect.origin.x <<
", " << controlRect.origin.y <<
", " << controlRect.size.width <<
", " << controlRect.size.height <<
"}");
852 [activeControl setFrame:controlRect];
859 int left = (nUsableWidth - nCheckboxMaxWidth) / 2;
860 controlRect.origin.x =
left;
861 controlRect.origin.y = currenttop;
862 controlRect.size.width = nPopupMaxWidth;
863 [activeControl setFrame:controlRect];
864 SAL_INFO(
"fpicker.aqua",
"setting checkbox at: {" << controlRect.origin.x <<
", " << controlRect.origin.y <<
", " << controlRect.size.width <<
", " << controlRect.size.height <<
"}");
886 SAL_INFO(
"fpicker.aqua",
"adding filter name: " << [filterName UTF8String]);
887 if ([filterName isEqualToString:
@"-"]) {
888 [menu addItem:[NSMenuItem separatorItem]];
905 else if (second == nil) {
910 Class secondClass = [second
class];
912 if (firstClass == [NSPopUpButton
class]) {
913 if (secondClass == [NSPopUpButton
class]) {
928 SAL_INFO(
"fpicker.aqua",
"no filter control needed or no filter helper present");
#define LIST_ELEMENT(elem)
#define MAP_LIST_LABEL(elem)
#define TOGGLE_ELEMENT(elem)
#define kAquaSpaceSwitchButtonFrameBoundsDiff
#define kAquaSpacePopupMenuFrameBoundsDiffTop
#define kAquaSpacePopupMenuFrameBoundsDiffBottom
#define kAquaSpaceBetweenPopupMenus
#define kAquaSpacePopupMenuFrameBoundsDiffLeft
#define kAquaSpaceInsideGroupH
#define kAquaPopupButtonDefaultHeight
#define kAquaSpaceAfterPopupButtonsV
#define kAquaSpaceBoxFrameViewDiffBottom
#define kAquaSpaceLabelFrameBoundsDiffH
#define kAquaSpaceBoxFrameViewDiffTop
#define kAquaSpaceBetweenControls
#define kAquaSpacePopupMenuFrameBoundsDiffV
#define kAquaSpaceLabelPopupDiffV
FilterHelper * m_pFilterHelper
the filter helper
uno::Any getValue(sal_Int16 nControlId, sal_Int16 nControlAction) const
NSView * m_pUserPane
the native view object
::std::list< NSControl * > m_aActiveControls
a list with all actively used controls
bool m_bToggleVisibility[TOGGLE_LAST]
the visibility flags for the checkboxes
NSControl * m_pListControls[LIST_LAST]
the popup menu controls (except for the filter control)
bool m_bUserPaneNeeded
indicates if a user pane is needed
void createFilterControl()
bool m_bIsUserPaneLaidOut
indicates if the user pane was laid out already
void initialize(sal_Int16 templateId)
NSControl * getControl(const sal_Int16 nControlId) const
void setLabel(sal_Int16 nControlId, NSString *aLabel)
OUString getLabel(sal_Int16 nControlId)
AquaFilePickerDelegate * m_pDelegate
the save or open panel's delegate
static int getControlElementName(const Class clazz, const int nControlId)
NSControl * m_pToggles[TOGGLE_LAST]
the checkbox controls
static int getVerticalDistance(const NSControl *first, const NSControl *second)
void enableControl(sal_Int16 nControlId, bool bEnable) const
void HandleSetListValue(const NSControl *pControl, const sal_Int16 nControlAction, const uno::Any &rValue)
NSPopUpButton * m_pFilterControl
the special filter control
::std::map< NSPopUpButton *, NSTextField * > m_aMapListLabelFields
a map to store a popup menu's label text field
bool m_bListVisibility[LIST_LAST]
the visibility flags for the popup menus
bool m_bIsFilterControlNeeded
indicates if a filter control is needed
void setValue(sal_Int16 nControlId, sal_Int16 nControlAction, const uno::Any &rValue)
::std::map< NSControl *, NSString * > m_aMapListLabels
a map to store a control's label text
int getCurrentFilterIndex()
NSStringList * getFilterNames()
#define SAL_INFO(area, stream)
NSString * getResString(sal_Int32 aId)
constexpr OUStringLiteral first
const std::u16string_view aStringList[]