1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ControlHelper.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
32 #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
33 #include <com/sun/star/ui/dialogs/ControlActions.hpp>
34 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
35 #include <vos/mutex.hxx>
36 #include <vcl/svapp.hxx>
37 #include "CFStringUtilities.hxx"
38 #include "resourceprovider.hxx"
39 #include "NSString_OOoAdditions.hxx"
41 #include "ControlHelper.hxx"
44 #define CLASS_NAME "ControlHelper"
45 #define POPUP_WIDTH_MIN 200
46 #define POPUP_WIDTH_MAX 350
48 using namespace ::com::sun::star::ui::dialogs
;
49 using namespace ::com::sun::star::ui::dialogs::TemplateDescription
;
50 using namespace ::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds
;
51 using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds
;
52 using namespace ::rtl
;
54 #pragma mark Constructor / Destructor
55 //------------------------------------------------------------------------------------
56 // Constructor / Destructor
57 //------------------------------------------------------------------------------------
58 ControlHelper::ControlHelper()
60 , m_pFilterControl(nil
)
61 , m_bUserPaneNeeded( false )
62 , m_bIsUserPaneLaidOut(false)
63 , m_bIsFilterControlNeeded(false)
64 , m_pFilterHelper(NULL
)
66 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
);
70 for( i
= 0; i
< TOGGLE_LAST
; i
++ ) {
71 m_bToggleVisibility
[i
] = false;
74 for( i
= 0; i
< LIST_LAST
; i
++ ) {
75 m_bListVisibility
[i
] = false;
78 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
81 ControlHelper::~ControlHelper()
83 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
);
85 NSAutoreleasePool
*pool
= [NSAutoreleasePool
new];
87 if (NULL
!= m_pUserPane
) {
88 [m_pUserPane release
];
91 for(std::list
<NSControl
*>::iterator control
= m_aActiveControls
.begin(); control
!= m_aActiveControls
.end(); control
++) {
92 NSControl
* pControl
= (*control
);
93 NSString
* sLabelName
= m_aMapListLabels
[pControl
];
94 if (sLabelName
!= nil
) {
97 if ([pControl
class] == [NSPopUpButton
class]) {
98 NSTextField
* pField
= m_aMapListLabelFields
[(NSPopUpButton
*)pControl
];
106 if (m_pFilterControl
!= NULL
) {
107 [m_pFilterControl setTarget
:nil
];
112 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
115 #pragma mark XInitialization delegate
116 //------------------------------------------------
117 // XInitialization delegate
118 //------------------------------------------------
119 void ControlHelper::initialize( sal_Int16 nTemplateId
)
121 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
, "templateId", nTemplateId
);
123 switch( nTemplateId
)
125 case FILESAVE_AUTOEXTENSION_PASSWORD
:
126 m_bToggleVisibility
[AUTOEXTENSION
] = true;
127 m_bToggleVisibility
[PASSWORD
] = true;
129 case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS
:
130 m_bToggleVisibility
[AUTOEXTENSION
] = true;
131 m_bToggleVisibility
[PASSWORD
] = true;
132 m_bToggleVisibility
[FILTEROPTIONS
] = true;
134 case FILESAVE_AUTOEXTENSION_SELECTION
:
135 m_bToggleVisibility
[AUTOEXTENSION
] = true;
136 m_bToggleVisibility
[SELECTION
] = true;
138 case FILESAVE_AUTOEXTENSION_TEMPLATE
:
139 m_bToggleVisibility
[AUTOEXTENSION
] = true;
140 m_bListVisibility
[TEMPLATE
] = true;
142 case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE
:
143 m_bToggleVisibility
[LINK
] = true;
144 m_bToggleVisibility
[PREVIEW
] = true;
145 m_bListVisibility
[IMAGE_TEMPLATE
] = true;
147 case FILEOPEN_READONLY_VERSION
:
148 m_bToggleVisibility
[READONLY
] = true;
149 m_bListVisibility
[VERSION
] = true;
151 case FILEOPEN_LINK_PREVIEW
:
152 m_bToggleVisibility
[LINK
] = true;
153 m_bToggleVisibility
[PREVIEW
] = true;
155 case FILESAVE_AUTOEXTENSION
:
156 m_bToggleVisibility
[AUTOEXTENSION
] = true;
162 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
165 #pragma mark XFilePickerControlAccess delegates
166 //------------------------------------------------------------------------------------
167 // XFilePickerControlAccess functions
168 //------------------------------------------------------------------------------------
170 void ControlHelper::enableControl( const sal_Int16 nControlId
, const sal_Bool bEnable
) const
172 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
, "controlId", nControlId
, "enable", bEnable
);
174 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
176 if (nControlId
== ExtendedFilePickerElementIds::CHECKBOX_PREVIEW
) {
177 OSL_TRACE(" preview checkbox cannot be changed");
178 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
182 NSControl
* pControl
= getControl(nControlId
);
184 if( pControl
!= nil
) {
186 OSL_TRACE( "enable" );
188 OSL_TRACE( "disable" );
190 [pControl setEnabled
:bEnable
];
192 OSL_TRACE("enable unknown control %d", nControlId
);
195 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
198 OUString
ControlHelper::getLabel( sal_Int16 nControlId
)
200 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
, "controlId", nControlId
);
202 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
204 NSControl
* pControl
= getControl( nControlId
);
206 if( pControl
== nil
) {
207 OSL_TRACE("Get label for unknown control %d", nControlId
);
211 rtl::OUString retVal
;
212 if ([pControl
class] == [NSPopUpButton
class]) {
213 NSString
*temp
= m_aMapListLabels
[pControl
];
215 retVal
= [temp OUString
];
218 NSString
* sLabel
= [[pControl cell
] title
];
219 retVal
= [sLabel OUString
];
222 DBG_PRINT_EXIT(CLASS_NAME
, __func__
, retVal
);
227 void ControlHelper::setLabel( sal_Int16 nControlId
, const NSString
* aLabel
)
229 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
, "controlId", nControlId
, "label", aLabel
);
231 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
233 NSAutoreleasePool
*pool
= [NSAutoreleasePool
new];
235 NSControl
* pControl
= getControl(nControlId
);
237 if (nil
!= pControl
) {
238 if ([pControl
class] == [NSPopUpButton
class]) {
239 NSString
*sOldName
= m_aMapListLabels
[pControl
];
240 if (sOldName
!= NULL
&& sOldName
!= aLabel
) {
244 m_aMapListLabels
[pControl
] = [aLabel retain
];
245 } else if ([pControl
class] == [NSButton
class]) {
246 [[pControl cell
] setTitle
:aLabel
];
249 OSL_TRACE("Control not found to set label for");
256 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
259 void ControlHelper::setValue( sal_Int16 nControlId
, sal_Int16 nControlAction
, const uno::Any
& rValue
)
261 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
, "controlId", nControlId
, "controlAction", nControlAction
);
263 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
265 if (nControlId
== ExtendedFilePickerElementIds::CHECKBOX_PREVIEW
) {
266 OSL_TRACE(" value for preview is unchangeable");
269 NSControl
* pControl
= getControl( nControlId
);
271 if( pControl
== nil
) {
272 OSL_TRACE("enable unknown control %d", nControlId
);
274 if( [pControl
class] == [NSPopUpButton
class] ) {
275 HandleSetListValue(pControl
, nControlAction
, rValue
);
276 } else if( [pControl
class] == [NSButton
class] ) {
277 sal_Bool bChecked
= false;
279 OSL_TRACE(" value is a bool: %d", bChecked
);
280 [(NSButton
*)pControl setState
:(bChecked
? NSOnState
: NSOffState
)];
283 OSL_TRACE("Can't set value on button / list %d %d",
284 nControlId
, nControlAction
);
289 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
292 uno::Any
ControlHelper::getValue( sal_Int16 nControlId
, sal_Int16 nControlAction
) const
294 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
, "controlId", nControlId
, "controlAction", nControlAction
);
296 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
299 NSControl
* pControl
= getControl( nControlId
);
301 if( pControl
== nil
) {
302 OSL_TRACE("get value for unknown control %d", nControlId
);
303 aRetval
<<= sal_True
;
305 if( [pControl
class] == [NSPopUpButton
class] ) {
306 aRetval
= HandleGetListValue(pControl
, nControlAction
);
307 } else if( [pControl
class] == [NSButton
class] ) {
308 //NSLog(@"control: %@", [[pControl cell] title]);
309 sal_Bool bValue
= [(NSButton
*)pControl state
] == NSOnState
? sal_True
: sal_False
;
311 OSL_TRACE("value is a bool (checkbox): %d", bValue
);
315 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
320 void ControlHelper::createUserPane()
322 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
);
324 if (m_bUserPaneNeeded
== false) {
325 OSL_TRACE("no user pane needed");
326 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
330 if (nil
!= m_pUserPane
) {
331 OSL_TRACE("user pane already exists");
332 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
336 if (m_bIsFilterControlNeeded
== true && m_pFilterControl
== nil
) {
337 createFilterControl();
340 NSRect minRect
= NSMakeRect(0,0,300,33);
341 m_pUserPane
= [[NSView alloc
] initWithFrame
:minRect
];
343 int currentHeight
= kAquaSpaceBoxFrameViewDiffTop
+ kAquaSpaceBoxFrameViewDiffBottom
;
344 int currentWidth
= 300;
346 BOOL bPopupControlPresent
= NO
;
347 BOOL bButtonControlPresent
= NO
;
349 int nCheckboxMaxWidth
= 0;
350 int nPopupMaxWidth
= 0;
351 int nPopupLabelMaxWidth
= 0;
353 for (::std::list
<NSControl
*>::iterator child
= m_aActiveControls
.begin(); child
!= m_aActiveControls
.end(); child
++) {
354 OSL_TRACE("currentHeight: %d", currentHeight
);
356 NSControl
* pControl
= *child
;
358 //let the control calculate its size
359 [pControl sizeToFit
];
361 NSRect frame
= [pControl frame
];
362 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
);
364 int nControlHeight
= frame
.size
.height
;
365 int nControlWidth
= frame
.size
.width
;
367 // Note: controls are grouped by kind, first all popup menus, then checkboxes
368 if ([pControl
class] == [NSPopUpButton
class]) {
369 if (bPopupControlPresent
== YES
) {
370 //this is not the first popup
371 currentHeight
+= kAquaSpaceBetweenPopupMenus
;
373 else if (child
!= m_aActiveControls
.begin()){
374 currentHeight
+= kAquaSpaceBetweenControls
;
377 bPopupControlPresent
= YES
;
379 // we have to add the label text width
380 NSString
*label
= m_aMapListLabels
[pControl
];
382 NSTextField
*textField
= createLabelWithString(label
);
383 [textField sizeToFit
];
384 m_aMapListLabelFields
[(NSPopUpButton
*)pControl
] = textField
;
385 [m_pUserPane addSubview
:textField
];
387 NSRect tfRect
= [textField frame
];
388 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
);
390 int tfWidth
= tfRect
.size
.width
;
392 if (nPopupLabelMaxWidth
< tfWidth
) {
393 nPopupLabelMaxWidth
= tfWidth
;
396 frame
.origin
.x
+= (kAquaSpaceBetweenControls
- kAquaSpaceLabelFrameBoundsDiffH
- kAquaSpacePopupMenuFrameBoundsDiffLeft
) + tfWidth
;
398 if (nControlWidth
< POPUP_WIDTH_MIN
) {
399 nControlWidth
= POPUP_WIDTH_MIN
;
400 frame
.size
.width
= nControlWidth
;
401 [pControl setFrame
:frame
];
404 if (nControlWidth
> POPUP_WIDTH_MAX
) {
405 nControlWidth
= POPUP_WIDTH_MAX
;
406 frame
.size
.width
= nControlWidth
;
407 [pControl setFrame
:frame
];
411 if (nPopupMaxWidth
< nControlWidth
) {
412 nPopupMaxWidth
= nControlWidth
;
415 nControlWidth
+= tfWidth
+ kAquaSpaceBetweenControls
- kAquaSpaceLabelFrameBoundsDiffH
- kAquaSpacePopupMenuFrameBoundsDiffLeft
;
416 if (nControlHeight
< kAquaPopupButtonDefaultHeight
) {
417 //maybe the popup has no menu item yet, so set a default height
418 nControlHeight
= kAquaPopupButtonDefaultHeight
;
421 nControlHeight
-= kAquaSpacePopupMenuFrameBoundsDiffV
;
423 else if ([pControl
class] == [NSButton
class]) {
424 if (child
!= m_aActiveControls
.begin()){
425 currentHeight
+= kAquaSpaceBetweenControls
;
428 if (nCheckboxMaxWidth
< nControlWidth
) {
429 nCheckboxMaxWidth
= nControlWidth
;
432 bButtonControlPresent
= YES
;
433 nControlWidth
-= 2 * kAquaSpaceSwitchButtonFrameBoundsDiff
;
434 nControlHeight
-= 2 * kAquaSpaceSwitchButtonFrameBoundsDiff
;
437 // if ((nControlWidth + 2 * kAquaSpaceInsideGroupH) > currentWidth) {
438 // currentWidth = nControlWidth + 2 * kAquaSpaceInsideGroupH;
441 currentHeight
+= nControlHeight
;
443 [m_pUserPane addSubview
:pControl
];
446 OSL_TRACE("height after adding all controls: %d", currentHeight
);
448 if (bPopupControlPresent
&& bButtonControlPresent
)
450 //after a popup button (array) and before a different kind of control we need some extra space instead of the standard
451 currentHeight
-= kAquaSpaceBetweenControls
;
452 currentHeight
+= kAquaSpaceAfterPopupButtonsV
;
453 OSL_TRACE("popup extra space added, currentHeight: %d", currentHeight
);
456 int nLongestPopupWidth
= nPopupMaxWidth
+ nPopupLabelMaxWidth
+ kAquaSpaceBetweenControls
- kAquaSpacePopupMenuFrameBoundsDiffLeft
- kAquaSpaceLabelFrameBoundsDiffH
;
458 currentWidth
= nLongestPopupWidth
> nCheckboxMaxWidth
? nLongestPopupWidth
: nCheckboxMaxWidth
;
459 OSL_TRACE("longest control width: %d", currentWidth
);
461 currentWidth
+= 2* kAquaSpaceInsideGroupH
;
463 if (currentWidth
< minRect
.size
.width
)
464 currentWidth
= minRect
.size
.width
;
466 if (currentHeight
< minRect
.size
.height
)
467 currentHeight
= minRect
.size
.height
;
469 NSRect upRect
= NSMakeRect(0, 0, currentWidth
, currentHeight
);
470 OSL_TRACE("setting user pane rect to {%f, %f, %f, %f}",upRect
.origin
.x
, upRect
.origin
.y
, upRect
.size
.width
, upRect
.size
.height
);
472 [m_pUserPane setFrame
:upRect
];
476 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
479 #pragma mark Private / Misc
480 //------------------------------------------------------------------------------------
482 //------------------------------------------------------------------------------------
483 void ControlHelper::createControls()
485 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
);
487 CResourceProvider aResProvider
;
488 for (int i
= 0; i
< LIST_LAST
; i
++) {
489 if (true == m_bListVisibility
[i
]) {
490 m_bUserPaneNeeded
= true;
492 int elementName
= getControlElementName([NSPopUpButton
class], i
);
493 NSString
* sLabel
= aResProvider
.getResString(elementName
);
495 m_pListControls
[i
] = [NSPopUpButton
new];
497 #define MAP_LIST_( elem ) \
499 setLabel(ExtendedFilePickerElementIds::LISTBOX_##elem, sLabel); \
505 MAP_LIST_(IMAGE_TEMPLATE
);
508 m_aActiveControls
.push_back(m_pListControls
[i
]);
510 m_pListControls
[i
] = nil
;
514 for (int i
= 0/*#i102102*/; i
< TOGGLE_LAST
; i
++) {
515 if (true == m_bToggleVisibility
[i
]) {
516 m_bUserPaneNeeded
= true;
518 int elementName
= getControlElementName([NSButton
class], i
);
519 NSString
* sLabel
= aResProvider
.getResString(elementName
);
521 NSButton
*button
= [NSButton
new];
522 [button setTitle
:sLabel
];
524 [button setButtonType
:NSSwitchButton
];
526 [button setState
:NSOffState
];
528 if (i
== AUTOEXTENSION
) {
529 [button setTarget
:m_pDelegate
];
530 [button setAction
:@
selector(autoextensionChanged
:)];
533 m_pToggles
[i
] = button
;
535 m_aActiveControls
.push_back(m_pToggles
[i
]);
541 //preview is always on with Mac OS X
542 NSControl
*pPreviewBox
= m_pToggles
[PREVIEW
];
543 if (pPreviewBox
!= nil
) {
544 [pPreviewBox setEnabled
:NO
];
545 [(NSButton
*)pPreviewBox setState
:NSOnState
];
548 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
551 #define TOGGLE_ELEMENT( elem ) \
553 nReturn = CHECKBOX_##elem; \
554 DBG_PRINT_EXIT(CLASS_NAME, __func__, nReturn); \
556 #define LIST_ELEMENT( elem ) \
558 nReturn = LISTBOX_##elem##_LABEL; \
559 DBG_PRINT_EXIT(CLASS_NAME, __func__, nReturn); \
562 int ControlHelper::getControlElementName(const Class aClazz
, const int nControlId
) const
564 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
, "aClazz", [[aClazz description
] UTF8String
], "controlId", nControlId
);
567 if (aClazz
== [NSButton
class])
569 switch (nControlId
) {
570 TOGGLE_ELEMENT( AUTOEXTENSION
);
571 TOGGLE_ELEMENT( PASSWORD
);
572 TOGGLE_ELEMENT( FILTEROPTIONS
);
573 TOGGLE_ELEMENT( READONLY
);
574 TOGGLE_ELEMENT( LINK
);
575 TOGGLE_ELEMENT( PREVIEW
);
576 TOGGLE_ELEMENT( SELECTION
);
579 else if (aClazz
== [NSPopUpButton
class])
581 switch (nControlId
) {
582 LIST_ELEMENT( VERSION
);
583 LIST_ELEMENT( TEMPLATE
);
584 LIST_ELEMENT( IMAGE_TEMPLATE
);
588 DBG_PRINT_EXIT(CLASS_NAME
, __func__
, nReturn
);
593 void ControlHelper::HandleSetListValue(const NSControl
* pControl
, const sal_Int16 nControlAction
, const uno::Any
& rValue
)
595 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
, "controlAction", nControlAction
);
597 if ([pControl
class] != [NSPopUpButton
class]) {
598 OSL_TRACE("not a popup menu");
599 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
603 NSPopUpButton
*pButton
= (NSPopUpButton
*)pControl
;
604 NSMenu
*rMenu
= [pButton menu
];
606 OSL_TRACE("button has no menu");
607 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
611 switch (nControlAction
)
613 case ControlActions::ADD_ITEM
:
615 OSL_TRACE("ADD_ITEMS");
619 NSString
* sCFItem
= [NSString stringWithOUString
:sItem
];
620 OSL_TRACE("Adding menu item: %s", OUStringToOString(sItem
, RTL_TEXTENCODING_UTF8
).getStr());
621 [pButton addItemWithTitle
:sCFItem
];
624 case ControlActions::ADD_ITEMS
:
626 OSL_TRACE("ADD_ITEMS");
627 uno::Sequence
< OUString
> aStringList
;
628 rValue
>>= aStringList
;
629 sal_Int32 nItemCount
= aStringList
.getLength();
630 for (sal_Int32 i
= 0; i
< nItemCount
; ++i
)
632 NSString
* sCFItem
= [NSString stringWithOUString
:aStringList
[i
]];
633 OSL_TRACE("Adding menu item: %s", OUStringToOString(aStringList
[i
], RTL_TEXTENCODING_UTF8
).getStr());
634 [pButton addItemWithTitle
:sCFItem
];
638 case ControlActions::DELETE_ITEM
:
640 OSL_TRACE("DELETE_ITEM");
643 OSL_TRACE("Deleting item at position %d", (nPos
));
644 [rMenu removeItemAtIndex
:nPos
];
647 case ControlActions::DELETE_ITEMS
:
649 OSL_TRACE("DELETE_ITEMS");
650 int nItems
= [rMenu numberOfItems
];
652 OSL_TRACE("no menu items to delete");
653 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
656 for(sal_Int32 i
= 0; i
< nItems
; i
++) {
657 [rMenu removeItemAtIndex
:i
];
661 case ControlActions::SET_SELECT_ITEM
:
665 OSL_TRACE("Selecting item at position %d", nPos
);
666 [pButton selectItemAtIndex
:nPos
];
670 OSL_TRACE("undocumented/unimplemented ControlAction for a list");
676 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
680 uno::Any
ControlHelper::HandleGetListValue(const NSControl
* pControl
, const sal_Int16 nControlAction
) const
682 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
, "controlAction", nControlAction
);
686 if ([pControl
class] != [NSPopUpButton
class]) {
687 OSL_TRACE("not a popup button");
688 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
692 NSPopUpButton
*pButton
= (NSPopUpButton
*)pControl
;
693 NSMenu
*rMenu
= [pButton menu
];
695 OSL_TRACE("button has no menu");
696 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
700 switch (nControlAction
)
702 case ControlActions::GET_ITEMS
:
704 OSL_TRACE("GET_ITEMS");
705 uno::Sequence
< OUString
> aItemList
;
707 int nItems
= [rMenu numberOfItems
];
709 aItemList
.realloc(nItems
);
711 for (int i
= 0; i
< nItems
; i
++) {
712 NSString
* sCFItem
= [pButton itemTitleAtIndex
:i
];
713 if (nil
!= sCFItem
) {
714 aItemList
[i
] = [sCFItem OUString
];
715 OSL_TRACE("Return value[%d]: %s", (i
- 1), OUStringToOString(aItemList
[i
- 1], RTL_TEXTENCODING_UTF8
).getStr());
722 case ControlActions::GET_SELECTED_ITEM
:
724 OSL_TRACE("GET_SELECTED_ITEM");
725 NSString
* sCFItem
= [pButton titleOfSelectedItem
];
726 if (nil
!= sCFItem
) {
727 OUString sString
= [sCFItem OUString
];
728 OSL_TRACE("Return value: %s", OUStringToOString(sString
, RTL_TEXTENCODING_UTF8
).getStr());
733 case ControlActions::GET_SELECTED_ITEM_INDEX
:
735 OSL_TRACE("GET_SELECTED_ITEM_INDEX");
736 sal_Int32 nActive
= [pButton indexOfSelectedItem
];
737 OSL_TRACE("Return value: %d", nActive
);
742 OSL_TRACE("undocumented/unimplemented ControlAction for a list");
746 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
752 // cf. offapi/com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.idl
753 NSControl
* ControlHelper::getControl( const sal_Int16 nControlId
) const
755 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
, "controlId", nControlId
);
757 NSControl
* pWidget
= nil
;
759 #define MAP_TOGGLE( elem ) \
760 case ExtendedFilePickerElementIds::CHECKBOX_##elem: \
761 pWidget = m_pToggles[elem]; \
764 #define MAP_BUTTON( elem ) \
765 case ExtendedFilePickerElementIds::PUSHBUTTON_##elem: \
766 pWidget = m_pButtons[elem]; \
769 #define MAP_LIST( elem ) \
770 case ExtendedFilePickerElementIds::LISTBOX_##elem: \
771 pWidget = m_pListControls[elem]; \
774 #define MAP_LIST_LABEL( elem ) \
775 case ExtendedFilePickerElementIds::LISTBOX_##elem##_LABEL: \
776 pWidget = m_pListControls[elem]; \
781 MAP_TOGGLE( AUTOEXTENSION
);
782 MAP_TOGGLE( PASSWORD
);
783 MAP_TOGGLE( FILTEROPTIONS
);
784 MAP_TOGGLE( READONLY
);
786 MAP_TOGGLE( PREVIEW
);
787 MAP_TOGGLE( SELECTION
);
788 //MAP_BUTTON( PLAY );
790 MAP_LIST( TEMPLATE
);
791 MAP_LIST( IMAGE_TEMPLATE
);
792 MAP_LIST_LABEL( VERSION
);
793 MAP_LIST_LABEL( TEMPLATE
);
794 MAP_LIST_LABEL( IMAGE_TEMPLATE
);
796 OSL_TRACE("Handle unknown control %d", nControlId
);
801 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
806 void ControlHelper::layoutControls()
808 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
);
810 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
812 if (nil
== m_pUserPane
) {
813 OSL_TRACE("no user pane to layout");
814 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
818 if (m_bIsUserPaneLaidOut
== true) {
819 OSL_TRACE("user pane already laid out");
820 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
824 NSRect userPaneRect
= [m_pUserPane frame
];
825 OSL_TRACE("userPane frame: {%f, %f, %f, %f}",userPaneRect
.origin
.x
, userPaneRect
.origin
.y
, userPaneRect
.size
.width
, userPaneRect
.size
.height
);
827 int nUsableWidth
= userPaneRect
.size
.width
;
829 //NOTE: NSView's coordinate system starts in the lower left hand corner but we start adding controls from the top,
830 // so we subtract from the vertical position as we make our way down the pane.
831 int currenttop
= userPaneRect
.size
.height
;
832 int nCheckboxMaxWidth
= 0;
833 int nPopupMaxWidth
= 0;
834 int nPopupLabelMaxWidth
= 0;
836 //first loop to determine max sizes
837 for (::std::list
<NSControl
*>::iterator child
= m_aActiveControls
.begin(); child
!= m_aActiveControls
.end(); child
++) {
838 NSControl
* pControl
= *child
;
840 NSRect controlRect
= [pControl frame
];
841 int nControlWidth
= controlRect
.size
.width
;
843 Class aSubType
= [pControl
class];
844 if (aSubType
== [NSPopUpButton
class]) {
845 if (nPopupMaxWidth
< nControlWidth
) {
846 nPopupMaxWidth
= nControlWidth
;
848 NSTextField
*label
= m_aMapListLabelFields
[(NSPopUpButton
*)pControl
];
849 NSRect labelFrame
= [label frame
];
850 int nLabelWidth
= labelFrame
.size
.width
;
851 if (nPopupLabelMaxWidth
< nLabelWidth
) {
852 nPopupLabelMaxWidth
= nLabelWidth
;
855 if (nCheckboxMaxWidth
< nControlWidth
) {
856 nCheckboxMaxWidth
= nControlWidth
;
861 int nLongestPopupWidth
= nPopupMaxWidth
+ nPopupLabelMaxWidth
+ kAquaSpaceBetweenControls
- kAquaSpacePopupMenuFrameBoundsDiffLeft
- kAquaSpaceLabelFrameBoundsDiffH
;
862 OSL_TRACE("longest popup width: %d", nLongestPopupWidth
);
864 NSControl
* previousControl
= nil
;
866 int nDistBetweenControls
= 0;
868 for (::std::list
<NSControl
*>::iterator child
= m_aActiveControls
.begin(); child
!= m_aActiveControls
.end(); child
++) {
869 NSControl
* pControl
= *child
;
871 //get the control's bounds
872 NSRect controlRect
= [pControl frame
];
873 int nControlHeight
= controlRect
.size
.height
;
874 int nControlWidth
= controlRect
.size
.width
;
876 //subtract the height from the current vertical position, because the control's bounds origin rect will be its lower left hand corner
877 currenttop
-= nControlHeight
;
879 Class aSubType
= [pControl
class];
881 //add space between the previous control and this control according to Apple's HIG
882 nDistBetweenControls
= getVerticalDistance(previousControl
, pControl
);
883 OSL_TRACE("vertical distance: %d", nDistBetweenControls
);
884 currenttop
-= nDistBetweenControls
;
886 previousControl
= pControl
;
888 if (aSubType
== [NSPopUpButton
class]) {
889 //move vertically up some pixels to space the controls between their real (visual) bounds
890 currenttop
+= kAquaSpacePopupMenuFrameBoundsDiffTop
;//from top
892 //get the corresponding popup label
893 NSTextField
*label
= m_aMapListLabelFields
[(NSPopUpButton
*)pControl
];
894 NSRect labelFrame
= [label frame
];
895 int totalWidth
= nPopupMaxWidth
+ labelFrame
.size
.width
+ kAquaSpaceBetweenControls
- kAquaSpacePopupMenuFrameBoundsDiffLeft
- kAquaSpaceLabelFrameBoundsDiffH
;
896 OSL_TRACE("totalWidth: %d", totalWidth
);
897 //let's center popups
898 int left
= (nUsableWidth
+ nLongestPopupWidth
) / 2 - totalWidth
;
899 OSL_TRACE("left: %d", left
);
900 labelFrame
.origin
.x
= left
;
901 labelFrame
.origin
.y
= currenttop
+ kAquaSpaceLabelPopupDiffV
;
902 OSL_TRACE("setting label at: {%f, %f, %f, %f}",labelFrame
.origin
.x
, labelFrame
.origin
.y
, labelFrame
.size
.width
, labelFrame
.size
.height
);
903 [label setFrame
:labelFrame
];
905 controlRect
.origin
.x
= left
+ labelFrame
.size
.width
+ kAquaSpaceBetweenControls
- kAquaSpaceLabelFrameBoundsDiffH
- kAquaSpacePopupMenuFrameBoundsDiffLeft
;
906 controlRect
.origin
.y
= currenttop
;
907 controlRect
.size
.width
= nPopupMaxWidth
;
908 OSL_TRACE("setting popup at: {%f, %f, %f, %f}",controlRect
.origin
.x
, controlRect
.origin
.y
, controlRect
.size
.width
, controlRect
.size
.height
);
909 [pControl setFrame
:controlRect
];
911 //add some space to place the vertical position right below the popup's visual bounds
912 currenttop
+= kAquaSpacePopupMenuFrameBoundsDiffBottom
;
914 currenttop
+= kAquaSpaceSwitchButtonFrameBoundsDiff
;//from top
916 nControlWidth
= nCheckboxMaxWidth
;
917 int left
= (nUsableWidth
- nCheckboxMaxWidth
) / 2;
918 controlRect
.origin
.x
= left
;
919 controlRect
.origin
.y
= currenttop
;
920 controlRect
.size
.width
= nPopupMaxWidth
;
921 [pControl setFrame
:controlRect
];
922 OSL_TRACE("setting checkbox at: {%f, %f, %f, %f}",controlRect
.origin
.x
, controlRect
.origin
.y
, controlRect
.size
.width
, controlRect
.size
.height
);
924 currenttop
+= kAquaSpaceSwitchButtonFrameBoundsDiff
;
928 m_bIsUserPaneLaidOut
= true;
930 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
933 void ControlHelper::createFilterControl() {
934 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
);
936 CResourceProvider aResProvider
;
937 NSString
* sLabel
= aResProvider
.getResString(CommonFilePickerElementIds::LISTBOX_FILTER_LABEL
);
939 m_pFilterControl
= [NSPopUpButton
new];
941 [m_pFilterControl setAction
:@
selector(filterSelectedAtIndex
:)];
942 [m_pFilterControl setTarget
:m_pDelegate
];
944 NSMenu
*menu
= [m_pFilterControl menu
];
946 for (NSStringList::iterator iter
= m_pFilterHelper
->getFilterNames()->begin(); iter
!= m_pFilterHelper
->getFilterNames()->end(); iter
++) {
947 NSString
*filterName
= *iter
;
948 OSL_TRACE("adding filter name: %s", [filterName UTF8String
]);
949 if ([filterName isEqualToString
:@
"-"]) {
950 [menu addItem
:[NSMenuItem separatorItem
]];
953 [m_pFilterControl addItemWithTitle
:filterName
];
957 // always add the filter as first item
958 m_aActiveControls
.push_front(m_pFilterControl
);
959 m_aMapListLabels
[m_pFilterControl
] = [sLabel retain
];
961 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
964 NSTextField
* ControlHelper::createLabelWithString(const NSString
* labelString
) {
965 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
, "label", labelString
);
967 NSTextField
*textField
= [NSTextField
new];
968 [textField setEditable
:NO
];
969 [textField setSelectable
:NO
];
970 [textField setDrawsBackground
:NO
];
971 [textField setBordered
:NO
];
972 [[textField cell
] setTitle
:labelString
];
974 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
978 int ControlHelper::getVerticalDistance(const NSControl
* first
, const NSControl
* second
)
981 return kAquaSpaceBoxFrameViewDiffTop
;
983 else if (second
== nil
) {
984 return kAquaSpaceBoxFrameViewDiffBottom
;
987 Class firstClass
= [first
class];
988 Class secondClass
= [second
class];
990 if (firstClass
== [NSPopUpButton
class]) {
991 if (secondClass
== [NSPopUpButton
class]) {
992 return kAquaSpaceBetweenPopupMenus
;
995 return kAquaSpaceAfterPopupButtonsV
;
999 return kAquaSpaceBetweenControls
;
1003 void ControlHelper::updateFilterUI()
1005 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
);
1007 if (m_bIsFilterControlNeeded
== false || m_pFilterHelper
== NULL
) {
1008 OSL_TRACE("no filter control needed or no filter helper present");
1009 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
1013 int index
= m_pFilterHelper
->getCurrentFilterIndex();
1015 if (m_pFilterControl
== nil
) {
1016 createFilterControl();
1019 [m_pFilterControl selectItemAtIndex
:index
];
1021 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);