1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
22 #include <vcl/salnativewidgets.hxx>
23 #include <vcl/decoview.hxx>
24 #include <vcl/svapp.hxx>
25 #include <vcl/timer.hxx>
26 #include <vcl/settings.hxx>
28 #include <quartz/salgdi.h>
29 #include <osx/salnativewidgets.h>
30 #include <osx/saldata.hxx>
31 #include <osx/salframe.h>
34 #include <Carbon/Carbon.h>
37 #include "cuidraw.hxx"
39 // presentation of native widgets consists of two important methods:
41 // AquaSalGraphics::getNativeControlRegion to determine native rectangle in pixels to draw the widget
42 // AquaSalGraphics::drawNativeControl to do the drawing operation itself
44 // getNativeControlRegion has to calculate a content rectangle within it is safe to draw the widget. Furthermore a boundig rectangle
45 // has to be calculated by getNativeControlRegion to consider adornments like a focus rectangle. As drawNativeControl uses Carbon
46 // API calls, all widgets are drawn without text. Drawing of text is done separately by VCL on top of graphical Carbon widget
47 // representation. drawNativeControl is called by VCL using content rectangle determined by getNativeControlRegion.
49 // FIXME: when calculation bounding rectangle larger then content rectangle, text displayed by VCL will become misaligned. To avoid
50 // misalignment bounding rectangle and content rectangle are calculated equally including adornments. Reduction of size for content
51 // is done by drawNativeControl subsequently. Only exception is editbox: As other widgets have distinct ControlPart::SubEdit control
52 // parts, editbox bounding rectangle and content rectangle are both calculated to reflect content area. Extending size for
53 // adornments is done by drawNativeControl subsequently.
55 #if !HAVE_FEATURE_MACOSX_SANDBOX
57 @interface
NSWindow(CoreUIRendererPrivate
)
58 + (CUIRendererRef
)coreUIRenderer
;
63 static HIRect
ImplGetHIRectFromRectangle(tools::Rectangle aRect
)
66 aHIRect
.origin
.x
= static_cast<float>(aRect
.Left());
67 aHIRect
.origin
.y
= static_cast<float>(aRect
.Top());
68 aHIRect
.size
.width
= static_cast<float>(aRect
.GetWidth());
69 aHIRect
.size
.height
= static_cast<float>(aRect
.GetHeight());
73 static ThemeButtonValue
ImplGetButtonValue(ButtonValue aButtonValue
)
78 return kThemeButtonOn
;
80 case ButtonValue::Off
:
81 case ButtonValue::DontKnow
:
82 return kThemeButtonOff
;
84 case ButtonValue::Mixed
:
86 return kThemeButtonMixed
;
91 static bool AquaGetScrollRect(/* TODO: int nScreen, */
92 ControlPart nPart
, const tools::Rectangle
&rControlRect
, tools::Rectangle
&rResultRect
)
95 rResultRect
= rControlRect
;
98 case ControlPart::ButtonUp
:
99 rResultRect
.SetBottom(rResultRect
.Top());
101 case ControlPart::ButtonDown
:
102 rResultRect
.SetTop(rResultRect
.Bottom());
104 case ControlPart::ButtonLeft
:
105 rResultRect
.SetRight(rResultRect
.Left());
107 case ControlPart::ButtonRight
:
108 rResultRect
.SetLeft(rResultRect
.Right());
110 case ControlPart::TrackHorzArea
:
111 case ControlPart::TrackVertArea
:
112 case ControlPart::ThumbHorz
:
113 case ControlPart::ThumbVert
:
114 case ControlPart::TrackHorzLeft
:
115 case ControlPart::TrackHorzRight
:
116 case ControlPart::TrackVertUpper
:
117 case ControlPart::TrackVertLower
:
125 bool AquaSalGraphics::isNativeControlSupported(ControlType nType
, ControlPart nPart
)
127 // native controls are now defaults. If you want to disable native controls, set the environment variable SAL_NO_NWF to
128 // something and VCL controls will be used as default again.
132 case ControlType::Pushbutton
:
133 case ControlType::Radiobutton
:
134 case ControlType::Checkbox
:
135 case ControlType::ListNode
:
136 if (nPart
== ControlPart::Entire
)
139 case ControlType::Scrollbar
:
140 if (nPart
== ControlPart::DrawBackgroundHorz
|| nPart
== ControlPart::DrawBackgroundVert
141 || nPart
== ControlPart::Entire
|| nPart
== ControlPart::HasThreeButtons
)
144 case ControlType::Slider
:
145 if (nPart
== ControlPart::TrackHorzArea
|| nPart
== ControlPart::TrackVertArea
)
148 case ControlType::Editbox
:
149 if (nPart
== ControlPart::Entire
|| nPart
== ControlPart::HasBackgroundTexture
)
152 case ControlType::MultilineEditbox
:
153 if (nPart
== ControlPart::Entire
|| nPart
== ControlPart::HasBackgroundTexture
)
156 case ControlType::Spinbox
:
157 if (nPart
== ControlPart::Entire
|| nPart
== ControlPart::AllButtons
|| nPart
== ControlPart::HasBackgroundTexture
)
160 case ControlType::SpinButtons
:
163 case ControlType::Combobox
:
164 if (nPart
== ControlPart::Entire
|| nPart
== ControlPart::HasBackgroundTexture
)
167 case ControlType::Listbox
:
168 if (nPart
== ControlPart::Entire
|| nPart
== ControlPart::ListboxWindow
|| nPart
== ControlPart::HasBackgroundTexture
169 || nPart
== ControlPart::SubEdit
)
172 case ControlType::TabItem
:
173 case ControlType::TabPane
:
174 case ControlType::TabBody
:
175 if (nPart
== ControlPart::Entire
|| nPart
== ControlPart::TabsDrawRtl
|| nPart
== ControlPart::HasBackgroundTexture
)
178 case ControlType::Toolbar
:
179 if (nPart
== ControlPart::Entire
|| nPart
== ControlPart::DrawBackgroundHorz
180 || nPart
== ControlPart::DrawBackgroundVert
)
183 case ControlType::WindowBackground
:
184 if (nPart
== ControlPart::BackgroundWindow
|| nPart
== ControlPart::BackgroundDialog
)
187 case ControlType::Menubar
:
188 if (nPart
== ControlPart::Entire
)
191 case ControlType::Tooltip
:
192 if (nPart
== ControlPart::Entire
)
195 case ControlType::MenuPopup
:
196 if (nPart
== ControlPart::Entire
|| nPart
== ControlPart::MenuItem
|| nPart
== ControlPart::MenuItemCheckMark
197 || nPart
== ControlPart::MenuItemRadioMark
)
200 case ControlType::Progress
:
201 case ControlType::IntroProgress
:
202 if (nPart
== ControlPart::Entire
)
205 case ControlType::Frame
:
206 if (nPart
== ControlPart::Border
)
209 case ControlType::ListNet
:
210 if (nPart
== ControlPart::Entire
)
219 bool AquaSalGraphics::hitTestNativeControl(ControlType nType
, ControlPart nPart
, const tools::Rectangle
&rControlRegion
,
220 const Point
&rPos
, bool& rIsInside
)
222 if (nType
== ControlType::Scrollbar
)
224 tools::Rectangle aRect
;
225 bool bValid
= AquaGetScrollRect(/* TODO: int nScreen, */
226 nPart
, rControlRegion
, aRect
);
227 rIsInside
= bValid
&& aRect
.IsInside(rPos
);
233 UInt32
AquaSalGraphics::getState(ControlState nState
)
235 const bool bDrawActive
= mpFrame
== nullptr || [mpFrame
->getNSWindow() isKeyWindow
];
236 if (!(nState
& ControlState::ENABLED
) || !bDrawActive
)
238 return kThemeStateInactive
;
240 if (nState
& ControlState::PRESSED
)
241 return kThemeStatePressed
;
242 return kThemeStateActive
;
245 UInt32
AquaSalGraphics::getTrackState(ControlState nState
)
247 const bool bDrawActive
= mpFrame
== nullptr || [mpFrame
->getNSWindow() isKeyWindow
];
248 if (!(nState
& ControlState::ENABLED
) || !bDrawActive
)
249 return kThemeTrackInactive
;
250 return kThemeTrackActive
;
253 bool AquaSalGraphics::drawNativeControl(ControlType nType
,
255 const tools::Rectangle
&rControlRegion
,
257 const ImplControlValue
&aValue
,
263 maContextHolder
.saveState();
264 tools::Rectangle buttonRect
= rControlRegion
;
265 HIRect rc
= ImplGetHIRectFromRectangle(buttonRect
);
268 case ControlType::Toolbar
:
270 #if HAVE_FEATURE_MACOSX_SANDBOX
271 HIThemeMenuItemDrawInfo aMenuItemDrawInfo
;
272 aMenuItemDrawInfo
.version
= 0;
273 aMenuItemDrawInfo
.state
= kThemeMenuActive
;
274 aMenuItemDrawInfo
.itemType
= kThemeMenuItemHierBackground
;
275 HIThemeDrawMenuItem(&rc
, &rc
, &aMenuItemDrawInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, nullptr);
277 if (rControlRegion
.Top() == 0 && nPart
== ControlPart::DrawBackgroundHorz
)
279 const bool bDrawActive
= mpFrame
== nullptr || [mpFrame
->getNSWindow() isKeyWindow
];
280 CGFloat unifiedHeight
= rControlRegion
.GetHeight();
281 CGRect drawRect
= CGRectMake(rControlRegion
.Left(), rControlRegion
.Top(),
282 rControlRegion
.GetWidth(), rControlRegion
.GetHeight());
283 CUIDraw([NSWindow coreUIRenderer
], drawRect
, maContextHolder
.get(),
284 reinterpret_cast<CFDictionaryRef
>([NSDictionary dictionaryWithObjectsAndKeys
:
285 @
"kCUIWidgetWindowFrame",
289 (bDrawActive
? @
"normal" : @
"inactive"),
291 [NSNumber numberWithDouble
:unifiedHeight
],
292 @
"kCUIWindowFrameUnifiedTitleBarHeightKey",
293 [NSNumber numberWithBool
:NO
],
294 @
"kCUIWindowFrameDrawTitleSeparatorKey",
295 [NSNumber numberWithBool
:YES
],
302 HIThemeMenuItemDrawInfo aMenuItemDrawInfo
;
303 aMenuItemDrawInfo
.version
= 0;
304 aMenuItemDrawInfo
.state
= kThemeMenuActive
;
305 aMenuItemDrawInfo
.itemType
= kThemeMenuItemHierBackground
;
306 HIThemeDrawMenuItem(&rc
, &rc
, &aMenuItemDrawInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, nullptr);
312 case ControlType::WindowBackground
:
314 HIThemeBackgroundDrawInfo aThemeBackgroundInfo
;
315 aThemeBackgroundInfo
.version
= 0;
316 aThemeBackgroundInfo
.state
= getState(nState
);
317 aThemeBackgroundInfo
.kind
= kThemeBrushDialogBackgroundActive
;
319 // FIXME: without this magical offset there is a 2 pixel black border on the right and bottom
323 HIThemeApplyBackground( &rc
, &aThemeBackgroundInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
);
324 CGContextFillRect(maContextHolder
.get(), rc
);
328 case ControlType::Tooltip
:
330 HIThemeBackgroundDrawInfo aThemeBackgroundInfo
;
331 aThemeBackgroundInfo
.version
= 0;
332 aThemeBackgroundInfo
.state
= getState(nState
);
333 aThemeBackgroundInfo
.kind
= kThemeBrushAlertBackgroundActive
;
336 HIThemeApplyBackground(&rc
, &aThemeBackgroundInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
);
337 CGContextFillRect(maContextHolder
.get(), rc
);
341 case ControlType::Menubar
:
342 case ControlType::MenuPopup
:
343 if (nPart
== ControlPart::Entire
|| nPart
== ControlPart::MenuItem
|| nPart
== ControlPart::HasBackgroundTexture
)
346 // FIXME: without this magical offset there is a 2 pixel black border on the right
349 HIThemeMenuDrawInfo aMenuInfo
;
350 aMenuInfo
.version
= 0;
351 aMenuInfo
.menuType
= kThemeMenuTypePullDown
;
352 HIThemeMenuItemDrawInfo aMenuItemDrawInfo
;
354 // grey theme when the item is selected is drawn here.
356 aMenuItemDrawInfo
.itemType
= kThemeMenuItemPlain
;
357 if ((nPart
== ControlPart::MenuItem
) && (nState
& ControlState::SELECTED
))
359 // blue theme when the item is selected is drawn here.
361 aMenuItemDrawInfo
.state
= kThemeMenuSelected
;
364 // normal color for non selected item
366 aMenuItemDrawInfo
.state
= kThemeMenuActive
;
368 // repaints the background of the pull down menu
370 HIThemeDrawMenuBackground(&rc
, &aMenuInfo
,maContextHolder
.get(), kHIThemeOrientationNormal
);
372 // repaints the item either blue (selected) and/or grey (active only)
374 HIThemeDrawMenuItem(&rc
, &rc
, &aMenuItemDrawInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, &rc
);
377 else if (nPart
== ControlPart::MenuItemCheckMark
|| nPart
== ControlPart::MenuItemRadioMark
)
380 // checked, else it is not displayed (see vcl/source/window/menu.cxx)
382 if (nState
& ControlState::PRESSED
)
384 HIThemeTextInfo aTextInfo
;
385 aTextInfo
.version
= 0;
386 aTextInfo
.state
= (nState
& ControlState::ENABLED
) ? kThemeStateInactive
: kThemeStateActive
;
387 aTextInfo
.fontID
= kThemeMenuItemMarkFont
;
388 aTextInfo
.horizontalFlushness
= kHIThemeTextHorizontalFlushCenter
;
389 aTextInfo
.verticalFlushness
= kHIThemeTextVerticalFlushTop
;
390 aTextInfo
.options
= kHIThemeTextBoxOptionNone
;
391 aTextInfo
.truncationPosition
= kHIThemeTextTruncationNone
;
393 // aTextInfo.truncationMaxLines unused because of kHIThemeTextTruncationNone item highlighted
395 if (nState
& ControlState::SELECTED
) aTextInfo
.state
= kThemeStatePressed
;
396 UniChar mark
=(nPart
== ControlPart::MenuItemCheckMark
) ? kCheckUnicode
: kBulletUnicode
;
397 CFStringRef cfString
= CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault
, &mark
, 1, kCFAllocatorNull
);
398 HIThemeDrawTextBox(cfString
, &rc
, &aTextInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
);
405 case ControlType::Pushbutton
:
408 // FIXME: instead of use a value, VCL can retrieve correct values on the fly (to be implemented)
410 HIThemeButtonDrawInfo aPushInfo
;
411 aPushInfo
.version
= 0;
415 aPushInfo
.animation
.time
.start
= 0;
416 aPushInfo
.animation
.time
.current
= 0;
417 PushButtonValue
const *pPBVal
= aValue
.getType() == ControlType::Pushbutton
?
418 static_cast<PushButtonValue
const *>(&aValue
) : nullptr;
419 int nPaintHeight
= static_cast<int>(rc
.size
.height
);
420 if (pPBVal
&& pPBVal
->mbBevelButton
)
422 aPushInfo
.kind
= kThemeRoundedBevelButton
;
424 else if (rc
.size
.height
<= PUSH_BUTTON_NORMAL_HEIGHT
)
426 aPushInfo
.kind
= kThemePushButtonMini
;
427 nPaintHeight
= PUSH_BUTTON_SMALL_HEIGHT
;
429 else if ((pPBVal
&& pPBVal
->mbSingleLine
) || rc
.size
.height
< PUSH_BUTTON_NORMAL_HEIGHT
* 3 / 2)
431 aPushInfo
.kind
= kThemePushButtonNormal
;
432 nPaintHeight
= PUSH_BUTTON_NORMAL_HEIGHT
;
434 // avoid clipping when focused
436 rc
.origin
.x
+= FOCUS_RING_WIDTH
/ 2;
437 rc
.size
.width
-= FOCUS_RING_WIDTH
;
440 aPushInfo
.kind
= kThemeBevelButton
;
442 // translate the origin for controls with fixed paint height so content ends up somewhere sensible
444 rc
.origin
.y
+= (rc
.size
.height
- nPaintHeight
) / 2;
445 aPushInfo
.state
= getState(nState
);
446 aPushInfo
.value
= ImplGetButtonValue(aValue
.getTristateVal());
447 aPushInfo
.adornment
= (nState
& ControlState::DEFAULT
) ? kThemeAdornmentDefault
: kThemeAdornmentNone
;
448 if (nState
& ControlState::FOCUSED
)
449 aPushInfo
.adornment
|= kThemeAdornmentFocus
;
450 HIThemeDrawButton(&rc
, &aPushInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, nullptr);
454 case ControlType::Radiobutton
:
455 case ControlType::Checkbox
:
457 HIThemeButtonDrawInfo aInfo
;
461 case ControlType::Radiobutton
:
462 if (rc
.size
.width
>= RADIO_BUTTON_SMALL_SIZE
)
463 aInfo
.kind
= kThemeRadioButton
;
465 aInfo
.kind
= kThemeSmallRadioButton
;
467 case ControlType::Checkbox
:
468 if (rc
.size
.width
>= CHECKBOX_SMALL_SIZE
)
469 aInfo
.kind
= kThemeCheckBox
;
471 aInfo
.kind
= kThemeSmallCheckBox
;
476 aInfo
.state
= getState(nState
);
477 ButtonValue aButtonValue
= aValue
.getTristateVal();
478 aInfo
.value
= ImplGetButtonValue(aButtonValue
);
479 aInfo
.adornment
= (nState
& ControlState::DEFAULT
) ? kThemeAdornmentDefault
: kThemeAdornmentNone
;
480 if (nState
& ControlState::FOCUSED
)
481 aInfo
.adornment
|= kThemeAdornmentFocus
;
482 rc
.size
.width
-= 2 * FOCUS_RING_WIDTH
;
483 rc
.size
.height
= RADIO_BUTTON_SMALL_SIZE
;
484 rc
.origin
.x
+= FOCUS_RING_WIDTH
;
485 rc
.origin
.y
+= FOCUS_RING_WIDTH
;
486 HIThemeDrawButton(&rc
, &aInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, nullptr);
490 case ControlType::ListNode
:
492 ButtonValue aButtonValue
= aValue
.getTristateVal();
493 HIThemeButtonDrawInfo aInfo
;
495 aInfo
.kind
= kThemeDisclosureTriangle
;
496 aInfo
.value
= kThemeDisclosureRight
;
497 aInfo
.state
= getState(nState
);
498 aInfo
.adornment
= kThemeAdornmentNone
;
499 switch (aButtonValue
)
501 case ButtonValue::On
:
502 aInfo
.value
= kThemeDisclosureDown
;
504 case ButtonValue::Off
:
505 if (AllSettings::GetLayoutRTL())
506 aInfo
.value
= kThemeDisclosureLeft
;
508 case ButtonValue::DontKnow
:
512 HIThemeDrawButton(&rc
, &aInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, nullptr);
516 case ControlType::Progress
:
517 case ControlType::IntroProgress
:
519 long nProgressWidth
= aValue
.getNumericVal();
520 HIThemeTrackDrawInfo aTrackInfo
;
521 aTrackInfo
.version
= 0;
522 aTrackInfo
.kind
= (rc
.size
.height
> 10) ? kThemeProgressBarLarge
: kThemeProgressBarMedium
;
523 aTrackInfo
.bounds
= rc
;
525 aTrackInfo
.max
= static_cast<SInt32
>(rc
.size
.width
);
526 aTrackInfo
.value
= nProgressWidth
;
527 aTrackInfo
.reserved
= 0;
528 aTrackInfo
.attributes
= kThemeTrackHorizontal
;
529 if (AllSettings::GetLayoutRTL())
530 aTrackInfo
.attributes
|= kThemeTrackRightToLeft
;
531 aTrackInfo
.enableState
= getTrackState(nState
);
533 // the intro bitmap never gets key anyway; we want to draw that enabled
535 if (nType
== ControlType::IntroProgress
)
536 aTrackInfo
.enableState
= kThemeTrackActive
;
537 aTrackInfo
.filler1
= 0;
538 aTrackInfo
.trackInfo
.progress
.phase
= static_cast<long long>(CFAbsoluteTimeGetCurrent() * 10.0);
539 HIThemeDrawTrack(&aTrackInfo
, nullptr, maContextHolder
.get(), kHIThemeOrientationNormal
);
543 case ControlType::Slider
:
545 const SliderValue
*pSliderVal
= static_cast<SliderValue
const *>(&aValue
);
546 HIThemeTrackDrawInfo aTrackDraw
;
547 aTrackDraw
.kind
= kThemeSliderMedium
;
548 if (nPart
== ControlPart::TrackHorzArea
|| nPart
== ControlPart::TrackVertArea
)
550 aTrackDraw
.bounds
= rc
;
551 aTrackDraw
.min
= pSliderVal
->mnMin
;
552 aTrackDraw
.max
= pSliderVal
->mnMax
;
553 aTrackDraw
.value
= pSliderVal
->mnCur
;
554 aTrackDraw
.reserved
= 0;
555 aTrackDraw
.attributes
= kThemeTrackShowThumb
;
556 if (nPart
== ControlPart::TrackHorzArea
)
557 aTrackDraw
.attributes
|= kThemeTrackHorizontal
;
558 aTrackDraw
.enableState
= (nState
& ControlState::ENABLED
) ? kThemeTrackActive
: kThemeTrackInactive
;
559 SliderTrackInfo aSlideInfo
;
560 aSlideInfo
.thumbDir
= kThemeThumbUpward
;
561 aSlideInfo
.pressState
= 0;
562 aTrackDraw
.trackInfo
.slider
= aSlideInfo
;
563 HIThemeDrawTrack(&aTrackDraw
, nullptr, maContextHolder
.get(), kHIThemeOrientationNormal
);
568 case ControlType::Scrollbar
:
570 const ScrollbarValue
*pScrollbarVal
= (aValue
.getType() == ControlType::Scrollbar
)
571 ? static_cast<const ScrollbarValue
*>(&aValue
) : nullptr;
572 if (nPart
== ControlPart::DrawBackgroundVert
|| nPart
== ControlPart::DrawBackgroundHorz
)
574 HIThemeTrackDrawInfo aTrackDraw
;
575 aTrackDraw
.kind
= kThemeMediumScrollBar
;
576 aTrackDraw
.bounds
= rc
;
577 aTrackDraw
.min
= pScrollbarVal
->mnMin
;
578 aTrackDraw
.max
= pScrollbarVal
->mnMax
- pScrollbarVal
->mnVisibleSize
;
579 aTrackDraw
.value
= pScrollbarVal
->mnCur
;
580 aTrackDraw
.reserved
= 0;
581 aTrackDraw
.attributes
= kThemeTrackShowThumb
;
582 if (nPart
== ControlPart::DrawBackgroundHorz
)
583 aTrackDraw
.attributes
|= kThemeTrackHorizontal
;
584 aTrackDraw
.enableState
= getTrackState(nState
);
585 ScrollBarTrackInfo aScrollInfo
;
586 aScrollInfo
.viewsize
= pScrollbarVal
->mnVisibleSize
;
587 aScrollInfo
.pressState
= 0;
588 if (pScrollbarVal
->mnButton1State
& ControlState::ENABLED
)
589 if (pScrollbarVal
->mnButton1State
& ControlState::PRESSED
)
590 aScrollInfo
.pressState
= kThemeTopOutsideArrowPressed
;
591 if (pScrollbarVal
->mnButton2State
& ControlState::ENABLED
)
592 if (pScrollbarVal
->mnButton2State
& ControlState::PRESSED
)
593 aScrollInfo
.pressState
= kThemeBottomOutsideArrowPressed
;
594 if ( pScrollbarVal
->mnThumbState
& ControlState::ENABLED
)
595 if (pScrollbarVal
->mnThumbState
& ControlState::PRESSED
)
596 aScrollInfo
.pressState
= kThemeThumbPressed
;
597 aTrackDraw
.trackInfo
.scrollbar
= aScrollInfo
;
598 HIThemeDrawTrack(&aTrackDraw
, nullptr, maContextHolder
.get(), kHIThemeOrientationNormal
);
603 case ControlType::TabPane
:
605 HIThemeTabPaneDrawInfo aTabPaneDrawInfo
;
606 aTabPaneDrawInfo
.version
= 1;
607 aTabPaneDrawInfo
.state
= kThemeStateActive
;
608 aTabPaneDrawInfo
.direction
= kThemeTabNorth
;
609 aTabPaneDrawInfo
.size
= kHIThemeTabSizeNormal
;
610 aTabPaneDrawInfo
.kind
= kHIThemeTabKindNormal
;
612 // border is outside the rect rc for Carbon but for VCL it should be inside
615 rc
.origin
.y
-= TAB_HEIGHT
/ 2;
616 rc
.size
.height
+= TAB_HEIGHT
/ 2;
618 HIThemeDrawTabPane(&rc
, &aTabPaneDrawInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
);
622 case ControlType::TabItem
:
624 HIThemeTabDrawInfo aTabItemDrawInfo
;
625 aTabItemDrawInfo
.version
= 1;
626 aTabItemDrawInfo
.style
= kThemeTabNonFront
;
627 aTabItemDrawInfo
.direction
= kThemeTabNorth
;
628 aTabItemDrawInfo
.size
= kHIThemeTabSizeNormal
;
629 aTabItemDrawInfo
.adornment
= kHIThemeTabAdornmentTrailingSeparator
;
630 if (nState
& ControlState::SELECTED
)
631 aTabItemDrawInfo
.style
= kThemeTabFront
;
632 if(nState
& ControlState::FOCUSED
)
633 aTabItemDrawInfo
.adornment
|= kHIThemeTabAdornmentFocus
;
635 // first, last or middle tab
637 aTabItemDrawInfo
.position
= kHIThemeTabPositionMiddle
;
638 TabitemValue
const * pTabValue
= static_cast<TabitemValue
const *>(&aValue
);
639 TabitemFlags nAlignment
= pTabValue
->mnAlignment
;
641 // TabitemFlags::LeftAligned (and TabitemFlags::RightAligned) for the leftmost (or rightmost) tab
642 // when there are several lines of tabs because there is only one first tab and one
643 // last tab and TabitemFlags::FirstInGroup (and TabitemFlags::LastInGroup) because when the
644 // line width is different from window width, there may not be TabitemFlags::RightAligned
646 if (((nAlignment
& TabitemFlags::LeftAligned
) && (nAlignment
& TabitemFlags::RightAligned
))
647 || ((nAlignment
& TabitemFlags::FirstInGroup
) && (nAlignment
& TabitemFlags::LastInGroup
)))
648 aTabItemDrawInfo
.position
= kHIThemeTabPositionOnly
;
649 else if ((nAlignment
& TabitemFlags::LeftAligned
) || (nAlignment
& TabitemFlags::FirstInGroup
))
650 aTabItemDrawInfo
.position
= kHIThemeTabPositionFirst
;
651 else if ((nAlignment
& TabitemFlags::RightAligned
) || (nAlignment
& TabitemFlags::LastInGroup
))
652 aTabItemDrawInfo
.position
= kHIThemeTabPositionLast
;
654 // support for RTL (see issue 79748)
656 if (AllSettings::GetLayoutRTL()) {
657 if (aTabItemDrawInfo
.position
== kHIThemeTabPositionFirst
)
658 aTabItemDrawInfo
.position
= kHIThemeTabPositionLast
;
659 else if (aTabItemDrawInfo
.position
== kHIThemeTabPositionLast
)
660 aTabItemDrawInfo
.position
= kHIThemeTabPositionFirst
;
662 rc
.size
.width
+= VCL_TAB_TEXT_SEPARATOR
;
664 HIThemeDrawTab(&rc
, &aTabItemDrawInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, nullptr);
668 case ControlType::Editbox
:
669 case ControlType::MultilineEditbox
:
671 HIThemeFrameDrawInfo aTextDrawInfo
;
672 aTextDrawInfo
.version
= 0;
673 aTextDrawInfo
.kind
= kHIThemeFrameTextFieldSquare
;
674 aTextDrawInfo
.state
= getState(nState
);
675 aTextDrawInfo
.isFocused
= false;
676 rc
.size
.width
+= 2 * EDITBOX_INSET_MARGIN
;
677 if (nType
== ControlType::Editbox
)
678 rc
.size
.height
= EDITBOX_HEIGHT
;
680 rc
.size
.height
+= 2 * (EDITBOX_BORDER_WIDTH
+ EDITBOX_INSET_MARGIN
);
681 rc
.origin
.x
-= EDITBOX_INSET_MARGIN
;
682 rc
.origin
.y
-= EDITBOX_INSET_MARGIN
;
684 // fill a white background, because HIThemeDrawFrame only draws the border
686 CGContextFillRect(maContextHolder
.get(), CGRectMake(rc
.origin
.x
, rc
.origin
.y
, rc
.size
.width
, rc
.size
.height
));
687 HIThemeDrawFrame(&rc
, &aTextDrawInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
);
688 if (nState
& ControlState::FOCUSED
)
689 HIThemeDrawFocusRect(&rc
, true, maContextHolder
.get(), kHIThemeOrientationNormal
);
693 case ControlType::Combobox
:
694 if (nPart
== ControlPart::HasBackgroundTexture
|| nPart
== ControlPart::Entire
)
696 HIThemeButtonDrawInfo aComboInfo
;
697 aComboInfo
.version
= 0;
698 aComboInfo
.kind
= kThemeComboBox
;
699 aComboInfo
.state
= getState(nState
);
700 aComboInfo
.value
= kThemeButtonOn
;
701 aComboInfo
.adornment
= kThemeAdornmentNone
;
702 if (nState
& ControlState::FOCUSED
)
703 aComboInfo
.adornment
|= kThemeAdornmentFocus
;
704 rc
.size
.width
-= 2 * FOCUS_RING_WIDTH
;
705 rc
.size
.height
= COMBOBOX_HEIGHT
;
706 rc
.origin
.x
+= FOCUS_RING_WIDTH
;
707 rc
.origin
.y
+= FOCUS_RING_WIDTH
;
708 HIThemeDrawButton(&rc
, &aComboInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, nullptr);
712 case ControlType::Listbox
:
715 case ControlPart::Entire
:
716 case ControlPart::ButtonDown
:
717 HIThemeButtonDrawInfo aListInfo
;
718 aListInfo
.version
= 0;
719 aListInfo
.kind
= kThemePopupButton
;
720 aListInfo
.state
= getState(nState
);
721 aListInfo
.value
= kThemeButtonOn
;
722 aListInfo
.adornment
= kThemeAdornmentDefault
;
723 if (nState
& ControlState::FOCUSED
)
724 aListInfo
.adornment
|= kThemeAdornmentFocus
;
725 rc
.size
.width
-= 2 * FOCUS_RING_WIDTH
;
726 rc
.size
.height
= LISTBOX_HEIGHT
;
727 rc
.origin
.x
+= FOCUS_RING_WIDTH
;
728 rc
.origin
.y
+= FOCUS_RING_WIDTH
;
729 HIThemeDrawButton(&rc
, &aListInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, nullptr);
732 case ControlPart::ListboxWindow
:
733 HIThemeFrameDrawInfo aTextDrawInfo
;
734 aTextDrawInfo
.version
= 0;
735 aTextDrawInfo
.kind
= kHIThemeFrameTextFieldSquare
;
736 aTextDrawInfo
.state
= getState(nState
);
737 aTextDrawInfo
.isFocused
= false;
738 rc
.size
.width
-= 2 * FOCUS_RING_WIDTH
;
739 rc
.size
.height
-= 2 * FOCUS_RING_WIDTH
;
740 rc
.origin
.x
+= FOCUS_RING_WIDTH
;
741 rc
.origin
.y
+= FOCUS_RING_WIDTH
;
742 HIThemeDrawFrame(&rc
, &aTextDrawInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
);
743 if (nState
& ControlState::FOCUSED
)
744 HIThemeDrawFocusRect(&rc
, true, maContextHolder
.get(), kHIThemeOrientationNormal
);
751 case ControlType::Spinbox
:
752 if (nPart
== ControlPart::Entire
)
757 HIThemeFrameDrawInfo aTextDrawInfo
;
758 aTextDrawInfo
.version
= 0;
759 aTextDrawInfo
.kind
= kHIThemeFrameTextFieldSquare
;
760 aTextDrawInfo
.state
= getState(nState
);
761 aTextDrawInfo
.isFocused
= false;
762 rc
.size
.width
-= SPIN_BUTTON_WIDTH
+ 4 * FOCUS_RING_WIDTH
;
763 rc
.size
.height
= EDITBOX_HEIGHT
;
764 rc
.origin
.x
+= FOCUS_RING_WIDTH
;
765 rc
.origin
.y
+= FOCUS_RING_WIDTH
;
767 // fill a white background, because HIThemeDrawFrame only draws the border
769 CGContextFillRect(maContextHolder
.get(), CGRectMake(rc
.origin
.x
, rc
.origin
.y
, rc
.size
.width
, rc
.size
.height
));
770 HIThemeDrawFrame(&rc
, &aTextDrawInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
);
771 if (nState
& ControlState::FOCUSED
)
772 HIThemeDrawFocusRect(&rc
, true, maContextHolder
.get(), kHIThemeOrientationNormal
);
776 const SpinbuttonValue
*pSpinButtonVal
= (aValue
.getType() == ControlType::SpinButtons
)
777 ? static_cast <const SpinbuttonValue
*>(&aValue
) : nullptr;
778 ControlState nUpperState
= ControlState::ENABLED
;
779 ControlState nLowerState
= ControlState::ENABLED
;
782 nUpperState
= pSpinButtonVal
->mnUpperState
;
783 nLowerState
= pSpinButtonVal
->mnLowerState
;
784 HIThemeButtonDrawInfo aSpinInfo
;
785 aSpinInfo
.kind
= kThemeIncDecButton
;
786 aSpinInfo
.state
= kThemeStateActive
;
787 if (nUpperState
& ControlState::PRESSED
)
788 aSpinInfo
.state
= kThemeStatePressedUp
;
789 else if (nLowerState
& ControlState::PRESSED
)
790 aSpinInfo
.state
= kThemeStatePressedDown
;
791 else if (nUpperState
& ~ControlState::ENABLED
|| nLowerState
& ~ControlState::ENABLED
)
792 aSpinInfo
.state
= kThemeStateInactive
;
793 else if (nUpperState
& ControlState::ROLLOVER
|| nLowerState
& ControlState::ROLLOVER
)
794 aSpinInfo
.state
= kThemeStateRollover
;
795 switch (aValue
.getTristateVal())
797 case ButtonValue::On
:
798 aSpinInfo
.value
= kThemeButtonOn
;
800 case ButtonValue::Off
:
801 aSpinInfo
.value
= kThemeButtonOff
;
803 case ButtonValue::Mixed
:
804 case ButtonValue::DontKnow
:
806 aSpinInfo
.value
= kThemeButtonMixed
;
809 aSpinInfo
.adornment
= (nUpperState
& ControlState::DEFAULT
|| nLowerState
& ControlState::DEFAULT
)
810 ? kThemeAdornmentDefault
: kThemeAdornmentNone
;
811 if (nUpperState
& ControlState::FOCUSED
|| nLowerState
& ControlState::FOCUSED
)
812 aSpinInfo
.adornment
|= kThemeAdornmentFocus
;
813 rc
.origin
.x
+= rc
.size
.width
+ 2 * FOCUS_RING_WIDTH
;
814 rc
.size
.width
= SPIN_BUTTON_WIDTH
;
815 rc
.size
.height
= SPIN_LOWER_BUTTON_HEIGHT
+ SPIN_LOWER_BUTTON_HEIGHT
;
816 HIThemeDrawButton(&rc
, &aSpinInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, nullptr);
821 case ControlType::Frame
:
823 DrawFrameFlags nStyle
= static_cast<DrawFrameFlags
>(aValue
.getNumericVal());
824 if (nPart
== ControlPart::Border
)
826 if (!(nStyle
& DrawFrameFlags::Menu
) && !(nStyle
& DrawFrameFlags::WindowBorder
))
829 // strange effects start to happen when HIThemeDrawFrame meets the border of the window.
830 // These can be avoided by clipping to the boundary of the frame (see issue 84756)
832 if (rc
.origin
.y
+ rc
.size
.height
>= mpFrame
->maGeometry
.nHeight
- 3)
834 CGMutablePathRef rPath
= CGPathCreateMutable();
835 CGPathAddRect(rPath
, nullptr,
836 CGRectMake(0, 0, mpFrame
->maGeometry
.nWidth
- 1, mpFrame
->maGeometry
.nHeight
- 1));
837 CGContextBeginPath(maContextHolder
.get());
838 CGContextAddPath(maContextHolder
.get(), rPath
);
839 CGContextClip(maContextHolder
.get());
840 CGPathRelease(rPath
);
842 HIThemeFrameDrawInfo aTextDrawInfo
;
843 aTextDrawInfo
.version
= 0;
844 aTextDrawInfo
.kind
= kHIThemeFrameListBox
;
845 aTextDrawInfo
.state
= kThemeStateActive
;
846 aTextDrawInfo
.isFocused
= false;
847 HIThemeDrawFrame(&rc
, &aTextDrawInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
);
853 case ControlType::ListNet
:
855 // do nothing as there isn't net for listviews on macOS
862 maContextHolder
.restoreState();
864 // in most cases invalidating the whole control region instead of just the unclipped part of it is sufficient (and probably
865 // faster). However for the window background we should not unnecessarily enlarge the really changed rectangle since the
866 // difference is usually quite high. Background is always drawn as a whole since we don't know anything about its possible
867 // contents (see issue i90291).
869 if (nType
== ControlType::WindowBackground
)
871 CGRect aRect
= {{0, 0}, {0, 0}};
873 aRect
= CGPathGetBoundingBox(mxClipPath
);
874 if (aRect
.size
.width
!= 0 && aRect
.size
.height
!= 0)
875 buttonRect
.Intersection(tools::Rectangle(Point(static_cast<long int>(aRect
.origin
.x
),
876 static_cast<long int>(aRect
.origin
.y
)),
877 Size(static_cast<long int>(aRect
.size
.width
),
878 static_cast<long int>(aRect
.size
.height
))));
880 RefreshRect(buttonRect
.Left(), buttonRect
.Top(), buttonRect
.GetWidth(), buttonRect
.GetHeight());
884 bool AquaSalGraphics::getNativeControlRegion(ControlType nType
,
886 const tools::Rectangle
&rControlRegion
,
888 const ImplControlValue
&aValue
,
890 tools::Rectangle
&rNativeBoundingRegion
,
891 tools::Rectangle
&rNativeContentRegion
)
893 bool toReturn
= false;
894 tools::Rectangle
aCtrlBoundRect(rControlRegion
);
895 short x
= aCtrlBoundRect
.Left();
896 short y
= aCtrlBoundRect
.Top();
900 case ControlType::Pushbutton
:
901 case ControlType::Radiobutton
:
902 case ControlType::Checkbox
:
904 if (nType
== ControlType::Pushbutton
)
906 w
= aCtrlBoundRect
.GetWidth();
907 h
= aCtrlBoundRect
.GetHeight();
911 w
= RADIO_BUTTON_SMALL_SIZE
+ 2 * FOCUS_RING_WIDTH
+ RADIO_BUTTON_TEXT_SEPARATOR
;
912 h
= RADIO_BUTTON_SMALL_SIZE
+ 2 * FOCUS_RING_WIDTH
;
914 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
915 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
919 case ControlType::Progress
:
921 tools::Rectangle
aRect(aCtrlBoundRect
);
922 if (aRect
.GetHeight() < LARGE_PROGRESS_INDICATOR_HEIGHT
)
923 aRect
.SetBottom(aRect
.Top() + MEDIUM_PROGRESS_INDICATOR_HEIGHT
- 1);
925 aRect
.SetBottom(aRect
.Top() + LARGE_PROGRESS_INDICATOR_HEIGHT
- 1);
926 rNativeBoundingRegion
= aRect
;
927 rNativeContentRegion
= aRect
;
931 case ControlType::IntroProgress
:
933 tools::Rectangle
aRect(aCtrlBoundRect
);
934 aRect
.SetBottom(aRect
.Top() + MEDIUM_PROGRESS_INDICATOR_HEIGHT
- 1);
935 rNativeBoundingRegion
= aRect
;
936 rNativeContentRegion
= aRect
;
940 case ControlType::Slider
:
941 if (nPart
== ControlPart::ThumbHorz
)
944 h
= aCtrlBoundRect
.GetHeight();
945 rNativeBoundingRegion
= rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
948 else if (nPart
== ControlPart::ThumbVert
)
950 w
= aCtrlBoundRect
.GetWidth();
952 rNativeBoundingRegion
= rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
956 case ControlType::Scrollbar
:
958 tools::Rectangle aRect
;
959 if (AquaGetScrollRect(nPart
, aCtrlBoundRect
, aRect
))
962 rNativeBoundingRegion
= aRect
;
963 rNativeContentRegion
= aRect
;
967 case ControlType::TabItem
:
969 w
= aCtrlBoundRect
.GetWidth() + 2 * TAB_TEXT_MARGIN
- 2 * VCL_TAB_TEXT_SEPARATOR
;
971 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
972 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
976 case ControlType::Editbox
:
978 w
= aCtrlBoundRect
.GetWidth();
979 h
= EDITBOX_HEIGHT
+ 2 * FOCUS_RING_WIDTH
;
980 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
981 w
-= 2 * (FOCUS_RING_WIDTH
+ EDITBOX_BORDER_WIDTH
+ EDITBOX_INSET_MARGIN
);
982 h
-= 2 * (FOCUS_RING_WIDTH
+ EDITBOX_BORDER_WIDTH
+ EDITBOX_INSET_MARGIN
);
983 x
+= FOCUS_RING_WIDTH
+ EDITBOX_BORDER_WIDTH
+ EDITBOX_INSET_MARGIN
;
984 y
+= FOCUS_RING_WIDTH
+ EDITBOX_BORDER_WIDTH
+ EDITBOX_INSET_MARGIN
;
985 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
989 case ControlType::Combobox
:
990 if (nPart
== ControlPart::Entire
)
992 w
= aCtrlBoundRect
.GetWidth();
993 h
= COMBOBOX_HEIGHT
+ 2 * FOCUS_RING_WIDTH
;
994 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
995 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
998 else if (nPart
== ControlPart::ButtonDown
)
1000 w
= COMBOBOX_BUTTON_WIDTH
+ FOCUS_RING_WIDTH
;
1001 h
= COMBOBOX_HEIGHT
+ 2 * FOCUS_RING_WIDTH
;
1002 x
+= aCtrlBoundRect
.GetWidth() - w
;
1003 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1004 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1007 else if (nPart
== ControlPart::SubEdit
)
1009 w
= aCtrlBoundRect
.GetWidth() - 2 * FOCUS_RING_WIDTH
- COMBOBOX_BUTTON_WIDTH
- COMBOBOX_BORDER_WIDTH
1010 - 2 * COMBOBOX_TEXT_MARGIN
;
1011 h
= COMBOBOX_HEIGHT
- 2 * COMBOBOX_BORDER_WIDTH
;
1012 x
+= FOCUS_RING_WIDTH
+ COMBOBOX_BORDER_WIDTH
+ COMBOBOX_TEXT_MARGIN
;
1013 y
+= FOCUS_RING_WIDTH
+ COMBOBOX_BORDER_WIDTH
;
1014 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1015 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1019 case ControlType::Listbox
:
1020 if (nPart
== ControlPart::Entire
)
1022 w
= aCtrlBoundRect
.GetWidth();
1023 h
= LISTBOX_HEIGHT
+ 2 * FOCUS_RING_WIDTH
;
1024 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1025 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1028 else if (nPart
== ControlPart::ButtonDown
)
1030 w
= LISTBOX_BUTTON_WIDTH
+ FOCUS_RING_WIDTH
;
1031 h
= LISTBOX_HEIGHT
+ 2 * FOCUS_RING_WIDTH
;
1032 x
+= aCtrlBoundRect
.GetWidth() - w
;
1033 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1034 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1037 else if (nPart
== ControlPart::SubEdit
)
1039 w
= aCtrlBoundRect
.GetWidth() - 2 * FOCUS_RING_WIDTH
- LISTBOX_BUTTON_WIDTH
- LISTBOX_BORDER_WIDTH
1040 - 2 * LISTBOX_TEXT_MARGIN
;
1041 h
= LISTBOX_HEIGHT
- 2 * LISTBOX_BORDER_WIDTH
;
1042 x
+= FOCUS_RING_WIDTH
+ LISTBOX_BORDER_WIDTH
+ LISTBOX_TEXT_MARGIN
;
1043 y
+= FOCUS_RING_WIDTH
+ LISTBOX_BORDER_WIDTH
;
1044 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1045 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1049 case ControlType::Spinbox
:
1050 if (nPart
== ControlPart::Entire
)
1052 w
= aCtrlBoundRect
.GetWidth();
1053 h
= EDITBOX_HEIGHT
+ 2 * FOCUS_RING_WIDTH
;
1054 x
+= SPINBOX_OFFSET
;
1055 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1056 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1059 else if (nPart
== ControlPart::SubEdit
)
1061 w
= aCtrlBoundRect
.GetWidth() - 4 * FOCUS_RING_WIDTH
- SPIN_BUTTON_WIDTH
- 2 * EDITBOX_BORDER_WIDTH
1062 - 2 * EDITBOX_INSET_MARGIN
;
1063 h
= EDITBOX_HEIGHT
- 2 * (EDITBOX_BORDER_WIDTH
+ EDITBOX_INSET_MARGIN
);
1064 x
+= FOCUS_RING_WIDTH
+ EDITBOX_BORDER_WIDTH
+ EDITBOX_INSET_MARGIN
+ SPINBOX_OFFSET
;
1065 y
+= FOCUS_RING_WIDTH
+ EDITBOX_BORDER_WIDTH
+ EDITBOX_INSET_MARGIN
;
1066 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1067 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1070 else if (nPart
== ControlPart::ButtonUp
)
1072 w
= SPIN_BUTTON_WIDTH
+ 2 * FOCUS_RING_WIDTH
;
1073 h
= SPIN_UPPER_BUTTON_HEIGHT
+ FOCUS_RING_WIDTH
;
1074 x
+= aCtrlBoundRect
.GetWidth() - SPIN_BUTTON_WIDTH
- 2 * FOCUS_RING_WIDTH
+ SPINBOX_OFFSET
;
1075 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1076 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1079 else if (nPart
== ControlPart::ButtonDown
)
1081 w
= SPIN_BUTTON_WIDTH
+ 2 * FOCUS_RING_WIDTH
;
1082 h
= SPIN_LOWER_BUTTON_HEIGHT
+ FOCUS_RING_WIDTH
;
1083 x
+= aCtrlBoundRect
.GetWidth() - SPIN_BUTTON_WIDTH
- 2 * FOCUS_RING_WIDTH
+ SPINBOX_OFFSET
;
1084 y
+= FOCUS_RING_WIDTH
+ SPIN_UPPER_BUTTON_HEIGHT
;
1085 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1086 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1090 case ControlType::Frame
:
1092 DrawFrameStyle nStyle
= static_cast<DrawFrameStyle
>(aValue
.getNumericVal() & 0x000f);
1093 DrawFrameFlags nFlags
= static_cast<DrawFrameFlags
>(aValue
.getNumericVal() & 0xfff0);
1094 if (nPart
== ControlPart::Border
1095 && !(nFlags
& (DrawFrameFlags::Menu
| DrawFrameFlags::WindowBorder
| DrawFrameFlags::BorderWindowBorder
)))
1097 tools::Rectangle
aRect(aCtrlBoundRect
);
1098 if (nStyle
== DrawFrameStyle::DoubleIn
)
1100 aRect
.AdjustLeft(1);
1102 // rRect.Right() -= 1;
1103 // rRect.Bottom() -= 1;
1107 aRect
.AdjustLeft(1);
1109 aRect
.AdjustRight(-1);
1110 aRect
.AdjustBottom(-1);
1112 rNativeContentRegion
= aRect
;
1113 rNativeBoundingRegion
= aRect
;
1118 case ControlType::Menubar
:
1119 case ControlType::MenuPopup
:
1120 if (nPart
== ControlPart::MenuItemCheckMark
|| nPart
== ControlPart::MenuItemRadioMark
)
1124 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1125 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1135 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */