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>
21 #include <tools/long.hxx>
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 bounding 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
)
236 // there are non key windows which are children of key windows, e.g. autofilter configuration dialog or sidebar dropdown dialogs.
237 // To handle these windows correctly, parent frame's key window state is considered here additionally.
239 const bool bDrawActive
= mpFrame
== nullptr || [mpFrame
->getNSWindow() isKeyWindow
]
240 || mpFrame
->mpParent
== nullptr || [mpFrame
->mpParent
->getNSWindow() isKeyWindow
];
241 if (!(nState
& ControlState::ENABLED
) || !bDrawActive
)
243 return kThemeStateInactive
;
245 if (nState
& ControlState::PRESSED
)
246 return kThemeStatePressed
;
247 return kThemeStateActive
;
250 UInt32
AquaSalGraphics::getTrackState(ControlState nState
)
252 const bool bDrawActive
= mpFrame
== nullptr || [mpFrame
->getNSWindow() isKeyWindow
];
253 if (!(nState
& ControlState::ENABLED
) || !bDrawActive
)
254 return kThemeTrackInactive
;
255 return kThemeTrackActive
;
258 bool AquaSalGraphics::drawNativeControl(ControlType nType
,
260 const tools::Rectangle
&rControlRegion
,
262 const ImplControlValue
&aValue
,
269 maContextHolder
.saveState();
270 tools::Rectangle buttonRect
= rControlRegion
;
271 HIRect rc
= ImplGetHIRectFromRectangle(buttonRect
);
274 case ControlType::Toolbar
:
276 #if HAVE_FEATURE_MACOSX_SANDBOX
277 HIThemeMenuItemDrawInfo aMenuItemDrawInfo
;
278 aMenuItemDrawInfo
.version
= 0;
279 aMenuItemDrawInfo
.state
= kThemeMenuActive
;
280 aMenuItemDrawInfo
.itemType
= kThemeMenuItemHierBackground
;
281 HIThemeDrawMenuItem(&rc
, &rc
, &aMenuItemDrawInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, nullptr);
283 if (rControlRegion
.Top() == 0 && nPart
== ControlPart::DrawBackgroundHorz
)
285 const bool bDrawActive
= mpFrame
== nullptr || [mpFrame
->getNSWindow() isKeyWindow
];
286 CGFloat unifiedHeight
= rControlRegion
.GetHeight();
287 CGRect drawRect
= CGRectMake(rControlRegion
.Left(), rControlRegion
.Top(),
288 rControlRegion
.GetWidth(), rControlRegion
.GetHeight());
289 CUIDraw([NSWindow coreUIRenderer
], drawRect
, maContextHolder
.get(),
290 reinterpret_cast<CFDictionaryRef
>([NSDictionary dictionaryWithObjectsAndKeys
:
291 @
"kCUIWidgetWindowFrame",
295 (bDrawActive
? @
"normal" : @
"inactive"),
297 [NSNumber numberWithDouble
:unifiedHeight
],
298 @
"kCUIWindowFrameUnifiedTitleBarHeightKey",
299 [NSNumber numberWithBool
:NO
],
300 @
"kCUIWindowFrameDrawTitleSeparatorKey",
301 [NSNumber numberWithBool
:YES
],
308 HIThemeMenuItemDrawInfo aMenuItemDrawInfo
;
309 aMenuItemDrawInfo
.version
= 0;
310 aMenuItemDrawInfo
.state
= kThemeMenuActive
;
311 aMenuItemDrawInfo
.itemType
= kThemeMenuItemHierBackground
;
312 HIThemeDrawMenuItem(&rc
, &rc
, &aMenuItemDrawInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, nullptr);
318 case ControlType::WindowBackground
:
320 HIThemeBackgroundDrawInfo aThemeBackgroundInfo
;
321 aThemeBackgroundInfo
.version
= 0;
322 aThemeBackgroundInfo
.state
= getState(nState
);
323 aThemeBackgroundInfo
.kind
= kThemeBrushDialogBackgroundActive
;
325 // FIXME: without this magical offset there is a 2 pixel black border on the right and bottom
329 HIThemeApplyBackground( &rc
, &aThemeBackgroundInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
);
330 CGContextFillRect(maContextHolder
.get(), rc
);
334 case ControlType::Tooltip
:
336 HIThemeBackgroundDrawInfo aThemeBackgroundInfo
;
337 aThemeBackgroundInfo
.version
= 0;
338 aThemeBackgroundInfo
.state
= getState(nState
);
339 aThemeBackgroundInfo
.kind
= kThemeBrushAlertBackgroundActive
;
342 HIThemeApplyBackground(&rc
, &aThemeBackgroundInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
);
343 CGContextFillRect(maContextHolder
.get(), rc
);
347 case ControlType::Menubar
:
348 case ControlType::MenuPopup
:
349 if (nPart
== ControlPart::Entire
|| nPart
== ControlPart::MenuItem
|| nPart
== ControlPart::HasBackgroundTexture
)
352 // FIXME: without this magical offset there is a 2 pixel black border on the right
355 HIThemeMenuDrawInfo aMenuInfo
;
356 aMenuInfo
.version
= 0;
357 aMenuInfo
.menuType
= kThemeMenuTypePullDown
;
358 HIThemeMenuItemDrawInfo aMenuItemDrawInfo
;
360 // grey theme when the item is selected is drawn here.
362 aMenuItemDrawInfo
.itemType
= kThemeMenuItemPlain
;
363 if ((nPart
== ControlPart::MenuItem
) && (nState
& ControlState::SELECTED
))
365 // blue theme when the item is selected is drawn here.
367 aMenuItemDrawInfo
.state
= kThemeMenuSelected
;
370 // normal color for non selected item
372 aMenuItemDrawInfo
.state
= kThemeMenuActive
;
374 // repaints the background of the pull down menu
376 HIThemeDrawMenuBackground(&rc
, &aMenuInfo
,maContextHolder
.get(), kHIThemeOrientationNormal
);
378 // repaints the item either blue (selected) and/or grey (active only)
380 HIThemeDrawMenuItem(&rc
, &rc
, &aMenuItemDrawInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, &rc
);
383 else if (nPart
== ControlPart::MenuItemCheckMark
|| nPart
== ControlPart::MenuItemRadioMark
)
386 // checked, else it is not displayed (see vcl/source/window/menu.cxx)
388 if (nState
& ControlState::PRESSED
)
390 HIThemeTextInfo aTextInfo
;
391 aTextInfo
.version
= 0;
392 aTextInfo
.state
= (nState
& ControlState::ENABLED
) ? kThemeStateInactive
: kThemeStateActive
;
393 aTextInfo
.fontID
= kThemeMenuItemMarkFont
;
394 aTextInfo
.horizontalFlushness
= kHIThemeTextHorizontalFlushCenter
;
395 aTextInfo
.verticalFlushness
= kHIThemeTextVerticalFlushTop
;
396 aTextInfo
.options
= kHIThemeTextBoxOptionNone
;
397 aTextInfo
.truncationPosition
= kHIThemeTextTruncationNone
;
399 // aTextInfo.truncationMaxLines unused because of kHIThemeTextTruncationNone item highlighted
401 if (nState
& ControlState::SELECTED
) aTextInfo
.state
= kThemeStatePressed
;
402 UniChar mark
=(nPart
== ControlPart::MenuItemCheckMark
) ? kCheckUnicode
: kBulletUnicode
;
403 CFStringRef cfString
= CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault
, &mark
, 1, kCFAllocatorNull
);
404 HIThemeDrawTextBox(cfString
, &rc
, &aTextInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
);
411 case ControlType::Pushbutton
:
414 // FIXME: instead of use a value, VCL can retrieve correct values on the fly (to be implemented)
416 HIThemeButtonDrawInfo aPushInfo
;
417 aPushInfo
.version
= 0;
421 aPushInfo
.animation
.time
.start
= 0;
422 aPushInfo
.animation
.time
.current
= 0;
423 PushButtonValue
const *pPBVal
= aValue
.getType() == ControlType::Pushbutton
?
424 static_cast<PushButtonValue
const *>(&aValue
) : nullptr;
425 int nPaintHeight
= static_cast<int>(rc
.size
.height
);
426 if (pPBVal
&& pPBVal
->mbBevelButton
)
428 aPushInfo
.kind
= kThemeRoundedBevelButton
;
430 else if (rc
.size
.height
<= PUSH_BUTTON_NORMAL_HEIGHT
)
432 aPushInfo
.kind
= kThemePushButtonMini
;
433 nPaintHeight
= PUSH_BUTTON_SMALL_HEIGHT
;
435 else if ((pPBVal
&& pPBVal
->mbSingleLine
) || rc
.size
.height
< PUSH_BUTTON_NORMAL_HEIGHT
* 3 / 2)
437 aPushInfo
.kind
= kThemePushButtonNormal
;
438 nPaintHeight
= PUSH_BUTTON_NORMAL_HEIGHT
;
440 // avoid clipping when focused
442 rc
.origin
.x
+= FOCUS_RING_WIDTH
/ 2;
443 rc
.size
.width
-= FOCUS_RING_WIDTH
;
446 aPushInfo
.kind
= kThemeBevelButton
;
448 // translate the origin for controls with fixed paint height so content ends up somewhere sensible
450 rc
.origin
.y
+= (rc
.size
.height
- nPaintHeight
) / 2;
451 aPushInfo
.state
= getState(nState
);
452 aPushInfo
.value
= ImplGetButtonValue(aValue
.getTristateVal());
453 aPushInfo
.adornment
= (nState
& ControlState::DEFAULT
) ? kThemeAdornmentDefault
: kThemeAdornmentNone
;
454 if (nState
& ControlState::FOCUSED
)
455 aPushInfo
.adornment
|= kThemeAdornmentFocus
;
456 HIThemeDrawButton(&rc
, &aPushInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, nullptr);
460 case ControlType::Radiobutton
:
461 case ControlType::Checkbox
:
463 HIThemeButtonDrawInfo aInfo
;
467 case ControlType::Radiobutton
:
468 if (rc
.size
.width
>= RADIO_BUTTON_SMALL_SIZE
)
469 aInfo
.kind
= kThemeRadioButton
;
471 aInfo
.kind
= kThemeSmallRadioButton
;
473 case ControlType::Checkbox
:
474 if (rc
.size
.width
>= CHECKBOX_SMALL_SIZE
)
475 aInfo
.kind
= kThemeCheckBox
;
477 aInfo
.kind
= kThemeSmallCheckBox
;
482 aInfo
.state
= getState(nState
);
483 ButtonValue aButtonValue
= aValue
.getTristateVal();
484 aInfo
.value
= ImplGetButtonValue(aButtonValue
);
485 aInfo
.adornment
= (nState
& ControlState::DEFAULT
) ? kThemeAdornmentDefault
: kThemeAdornmentNone
;
486 if (nState
& ControlState::FOCUSED
)
487 aInfo
.adornment
|= kThemeAdornmentFocus
;
488 rc
.size
.width
-= 2 * FOCUS_RING_WIDTH
;
489 rc
.size
.height
= RADIO_BUTTON_SMALL_SIZE
;
490 rc
.origin
.x
+= FOCUS_RING_WIDTH
;
491 rc
.origin
.y
+= FOCUS_RING_WIDTH
;
492 HIThemeDrawButton(&rc
, &aInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, nullptr);
496 case ControlType::ListNode
:
498 ButtonValue aButtonValue
= aValue
.getTristateVal();
499 HIThemeButtonDrawInfo aInfo
;
501 aInfo
.kind
= kThemeDisclosureTriangle
;
502 aInfo
.value
= kThemeDisclosureRight
;
503 aInfo
.state
= getState(nState
);
504 aInfo
.adornment
= kThemeAdornmentNone
;
505 switch (aButtonValue
)
507 case ButtonValue::On
:
508 aInfo
.value
= kThemeDisclosureDown
;
510 case ButtonValue::Off
:
511 if (AllSettings::GetLayoutRTL())
512 aInfo
.value
= kThemeDisclosureLeft
;
514 case ButtonValue::DontKnow
:
518 HIThemeDrawButton(&rc
, &aInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, nullptr);
522 case ControlType::Progress
:
523 case ControlType::IntroProgress
:
525 tools::Long nProgressWidth
= aValue
.getNumericVal();
526 HIThemeTrackDrawInfo aTrackInfo
;
527 aTrackInfo
.version
= 0;
528 aTrackInfo
.kind
= (rc
.size
.height
> 10) ? kThemeProgressBarLarge
: kThemeProgressBarMedium
;
529 aTrackInfo
.bounds
= rc
;
531 aTrackInfo
.max
= static_cast<SInt32
>(rc
.size
.width
);
532 aTrackInfo
.value
= nProgressWidth
;
533 aTrackInfo
.reserved
= 0;
534 aTrackInfo
.attributes
= kThemeTrackHorizontal
;
535 if (AllSettings::GetLayoutRTL())
536 aTrackInfo
.attributes
|= kThemeTrackRightToLeft
;
537 aTrackInfo
.enableState
= getTrackState(nState
);
539 // the intro bitmap never gets key anyway; we want to draw that enabled
541 if (nType
== ControlType::IntroProgress
)
542 aTrackInfo
.enableState
= kThemeTrackActive
;
543 aTrackInfo
.filler1
= 0;
544 aTrackInfo
.trackInfo
.progress
.phase
= static_cast<long long>(CFAbsoluteTimeGetCurrent() * 10.0);
545 HIThemeDrawTrack(&aTrackInfo
, nullptr, maContextHolder
.get(), kHIThemeOrientationNormal
);
549 case ControlType::Slider
:
551 const SliderValue
*pSliderVal
= static_cast<SliderValue
const *>(&aValue
);
552 HIThemeTrackDrawInfo aTrackDraw
;
553 aTrackDraw
.kind
= kThemeSliderMedium
;
554 if (nPart
== ControlPart::TrackHorzArea
|| nPart
== ControlPart::TrackVertArea
)
556 aTrackDraw
.bounds
= rc
;
557 aTrackDraw
.min
= pSliderVal
->mnMin
;
558 aTrackDraw
.max
= pSliderVal
->mnMax
;
559 aTrackDraw
.value
= pSliderVal
->mnCur
;
560 aTrackDraw
.reserved
= 0;
561 aTrackDraw
.attributes
= kThemeTrackShowThumb
;
562 if (nPart
== ControlPart::TrackHorzArea
)
563 aTrackDraw
.attributes
|= kThemeTrackHorizontal
;
564 aTrackDraw
.enableState
= (nState
& ControlState::ENABLED
) ? kThemeTrackActive
: kThemeTrackInactive
;
565 SliderTrackInfo aSlideInfo
;
566 aSlideInfo
.thumbDir
= kThemeThumbUpward
;
567 aSlideInfo
.pressState
= 0;
568 aTrackDraw
.trackInfo
.slider
= aSlideInfo
;
569 HIThemeDrawTrack(&aTrackDraw
, nullptr, maContextHolder
.get(), kHIThemeOrientationNormal
);
574 case ControlType::Scrollbar
:
576 const ScrollbarValue
*pScrollbarVal
= (aValue
.getType() == ControlType::Scrollbar
)
577 ? static_cast<const ScrollbarValue
*>(&aValue
) : nullptr;
578 if (nPart
== ControlPart::DrawBackgroundVert
|| nPart
== ControlPart::DrawBackgroundHorz
)
580 HIThemeTrackDrawInfo aTrackDraw
;
581 aTrackDraw
.kind
= kThemeMediumScrollBar
;
582 aTrackDraw
.bounds
= rc
;
583 aTrackDraw
.min
= pScrollbarVal
->mnMin
;
584 aTrackDraw
.max
= pScrollbarVal
->mnMax
- pScrollbarVal
->mnVisibleSize
;
585 aTrackDraw
.value
= pScrollbarVal
->mnCur
;
586 aTrackDraw
.reserved
= 0;
587 aTrackDraw
.attributes
= kThemeTrackShowThumb
;
588 if (nPart
== ControlPart::DrawBackgroundHorz
)
589 aTrackDraw
.attributes
|= kThemeTrackHorizontal
;
590 aTrackDraw
.enableState
= getTrackState(nState
);
591 ScrollBarTrackInfo aScrollInfo
;
592 aScrollInfo
.viewsize
= pScrollbarVal
->mnVisibleSize
;
593 aScrollInfo
.pressState
= 0;
594 if (pScrollbarVal
->mnButton1State
& ControlState::ENABLED
)
595 if (pScrollbarVal
->mnButton1State
& ControlState::PRESSED
)
596 aScrollInfo
.pressState
= kThemeTopOutsideArrowPressed
;
597 if (pScrollbarVal
->mnButton2State
& ControlState::ENABLED
)
598 if (pScrollbarVal
->mnButton2State
& ControlState::PRESSED
)
599 aScrollInfo
.pressState
= kThemeBottomOutsideArrowPressed
;
600 if ( pScrollbarVal
->mnThumbState
& ControlState::ENABLED
)
601 if (pScrollbarVal
->mnThumbState
& ControlState::PRESSED
)
602 aScrollInfo
.pressState
= kThemeThumbPressed
;
603 aTrackDraw
.trackInfo
.scrollbar
= aScrollInfo
;
604 HIThemeDrawTrack(&aTrackDraw
, nullptr, maContextHolder
.get(), kHIThemeOrientationNormal
);
609 case ControlType::TabPane
:
611 HIThemeTabPaneDrawInfo aTabPaneDrawInfo
;
612 aTabPaneDrawInfo
.version
= 1;
613 aTabPaneDrawInfo
.state
= kThemeStateActive
;
614 aTabPaneDrawInfo
.direction
= kThemeTabNorth
;
615 aTabPaneDrawInfo
.size
= kHIThemeTabSizeNormal
;
616 aTabPaneDrawInfo
.kind
= kHIThemeTabKindNormal
;
618 // border is outside the rect rc for Carbon but for VCL it should be inside
621 rc
.origin
.y
-= TAB_HEIGHT
/ 2;
622 rc
.size
.height
+= TAB_HEIGHT
/ 2;
624 HIThemeDrawTabPane(&rc
, &aTabPaneDrawInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
);
628 case ControlType::TabItem
:
630 HIThemeTabDrawInfo aTabItemDrawInfo
;
631 aTabItemDrawInfo
.version
= 1;
632 aTabItemDrawInfo
.style
= kThemeTabNonFront
;
633 aTabItemDrawInfo
.direction
= kThemeTabNorth
;
634 aTabItemDrawInfo
.size
= kHIThemeTabSizeNormal
;
635 aTabItemDrawInfo
.adornment
= kHIThemeTabAdornmentTrailingSeparator
;
636 if (nState
& ControlState::SELECTED
)
637 aTabItemDrawInfo
.style
= kThemeTabFront
;
638 if(nState
& ControlState::FOCUSED
)
639 aTabItemDrawInfo
.adornment
|= kHIThemeTabAdornmentFocus
;
641 // first, last or middle tab
643 aTabItemDrawInfo
.position
= kHIThemeTabPositionMiddle
;
644 TabitemValue
const * pTabValue
= static_cast<TabitemValue
const *>(&aValue
);
645 TabitemFlags nAlignment
= pTabValue
->mnAlignment
;
647 // TabitemFlags::LeftAligned (and TabitemFlags::RightAligned) for the leftmost (or rightmost) tab
648 // when there are several lines of tabs because there is only one first tab and one
649 // last tab and TabitemFlags::FirstInGroup (and TabitemFlags::LastInGroup) because when the
650 // line width is different from window width, there may not be TabitemFlags::RightAligned
652 if (((nAlignment
& TabitemFlags::LeftAligned
) && (nAlignment
& TabitemFlags::RightAligned
))
653 || ((nAlignment
& TabitemFlags::FirstInGroup
) && (nAlignment
& TabitemFlags::LastInGroup
)))
654 aTabItemDrawInfo
.position
= kHIThemeTabPositionOnly
;
655 else if ((nAlignment
& TabitemFlags::LeftAligned
) || (nAlignment
& TabitemFlags::FirstInGroup
))
656 aTabItemDrawInfo
.position
= kHIThemeTabPositionFirst
;
657 else if ((nAlignment
& TabitemFlags::RightAligned
) || (nAlignment
& TabitemFlags::LastInGroup
))
658 aTabItemDrawInfo
.position
= kHIThemeTabPositionLast
;
660 // support for RTL (see issue 79748)
662 if (AllSettings::GetLayoutRTL()) {
663 if (aTabItemDrawInfo
.position
== kHIThemeTabPositionFirst
)
664 aTabItemDrawInfo
.position
= kHIThemeTabPositionLast
;
665 else if (aTabItemDrawInfo
.position
== kHIThemeTabPositionLast
)
666 aTabItemDrawInfo
.position
= kHIThemeTabPositionFirst
;
668 rc
.size
.width
+= VCL_TAB_TEXT_SEPARATOR
;
670 HIThemeDrawTab(&rc
, &aTabItemDrawInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, nullptr);
674 case ControlType::Editbox
:
675 case ControlType::MultilineEditbox
:
677 HIThemeFrameDrawInfo aTextDrawInfo
;
678 aTextDrawInfo
.version
= 0;
679 aTextDrawInfo
.kind
= kHIThemeFrameTextFieldSquare
;
680 aTextDrawInfo
.state
= getState(nState
);
681 aTextDrawInfo
.isFocused
= false;
682 rc
.size
.width
+= 2 * EDITBOX_INSET_MARGIN
;
683 if (nType
== ControlType::Editbox
)
684 rc
.size
.height
= EDITBOX_HEIGHT
;
686 rc
.size
.height
+= 2 * (EDITBOX_BORDER_WIDTH
+ EDITBOX_INSET_MARGIN
);
687 rc
.origin
.x
-= EDITBOX_INSET_MARGIN
;
688 rc
.origin
.y
-= EDITBOX_INSET_MARGIN
;
690 // fill a white background, because HIThemeDrawFrame only draws the border
692 CGContextFillRect(maContextHolder
.get(), CGRectMake(rc
.origin
.x
, rc
.origin
.y
, rc
.size
.width
, rc
.size
.height
));
693 HIThemeDrawFrame(&rc
, &aTextDrawInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
);
694 if (nState
& ControlState::FOCUSED
)
695 HIThemeDrawFocusRect(&rc
, true, maContextHolder
.get(), kHIThemeOrientationNormal
);
699 case ControlType::Combobox
:
700 if (nPart
== ControlPart::HasBackgroundTexture
|| nPart
== ControlPart::Entire
)
702 HIThemeButtonDrawInfo aComboInfo
;
703 aComboInfo
.version
= 0;
704 aComboInfo
.kind
= kThemeComboBox
;
705 aComboInfo
.state
= getState(nState
);
706 aComboInfo
.value
= kThemeButtonOn
;
707 aComboInfo
.adornment
= kThemeAdornmentNone
;
708 if (nState
& ControlState::FOCUSED
)
709 aComboInfo
.adornment
|= kThemeAdornmentFocus
;
710 rc
.size
.width
-= 2 * FOCUS_RING_WIDTH
;
711 rc
.size
.height
= COMBOBOX_HEIGHT
;
712 rc
.origin
.x
+= FOCUS_RING_WIDTH
;
713 rc
.origin
.y
+= FOCUS_RING_WIDTH
;
714 HIThemeDrawButton(&rc
, &aComboInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, nullptr);
718 case ControlType::Listbox
:
721 case ControlPart::Entire
:
722 case ControlPart::ButtonDown
:
723 HIThemeButtonDrawInfo aListInfo
;
724 aListInfo
.version
= 0;
725 aListInfo
.kind
= kThemePopupButton
;
726 aListInfo
.state
= getState(nState
);
727 aListInfo
.value
= kThemeButtonOn
;
728 aListInfo
.adornment
= kThemeAdornmentDefault
;
729 if (nState
& ControlState::FOCUSED
)
730 aListInfo
.adornment
|= kThemeAdornmentFocus
;
731 rc
.size
.width
-= 2 * FOCUS_RING_WIDTH
;
732 rc
.size
.height
= LISTBOX_HEIGHT
;
733 rc
.origin
.x
+= FOCUS_RING_WIDTH
;
734 rc
.origin
.y
+= FOCUS_RING_WIDTH
;
735 HIThemeDrawButton(&rc
, &aListInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, nullptr);
738 case ControlPart::ListboxWindow
:
739 HIThemeFrameDrawInfo aTextDrawInfo
;
740 aTextDrawInfo
.version
= 0;
741 aTextDrawInfo
.kind
= kHIThemeFrameTextFieldSquare
;
742 aTextDrawInfo
.state
= getState(nState
);
743 aTextDrawInfo
.isFocused
= false;
744 rc
.size
.width
-= 2 * FOCUS_RING_WIDTH
;
745 rc
.size
.height
-= 2 * FOCUS_RING_WIDTH
;
746 rc
.origin
.x
+= FOCUS_RING_WIDTH
;
747 rc
.origin
.y
+= FOCUS_RING_WIDTH
;
748 HIThemeDrawFrame(&rc
, &aTextDrawInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
);
749 if (nState
& ControlState::FOCUSED
)
750 HIThemeDrawFocusRect(&rc
, true, maContextHolder
.get(), kHIThemeOrientationNormal
);
757 case ControlType::Spinbox
:
758 if (nPart
== ControlPart::Entire
)
763 HIThemeFrameDrawInfo aTextDrawInfo
;
764 aTextDrawInfo
.version
= 0;
765 aTextDrawInfo
.kind
= kHIThemeFrameTextFieldSquare
;
766 aTextDrawInfo
.state
= getState(nState
);
767 aTextDrawInfo
.isFocused
= false;
768 rc
.size
.width
-= SPIN_BUTTON_WIDTH
+ 4 * FOCUS_RING_WIDTH
;
769 rc
.size
.height
= EDITBOX_HEIGHT
;
770 rc
.origin
.x
+= FOCUS_RING_WIDTH
;
771 rc
.origin
.y
+= FOCUS_RING_WIDTH
;
773 // fill a white background, because HIThemeDrawFrame only draws the border
775 CGContextFillRect(maContextHolder
.get(), CGRectMake(rc
.origin
.x
, rc
.origin
.y
, rc
.size
.width
, rc
.size
.height
));
776 HIThemeDrawFrame(&rc
, &aTextDrawInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
);
777 if (nState
& ControlState::FOCUSED
)
778 HIThemeDrawFocusRect(&rc
, true, maContextHolder
.get(), kHIThemeOrientationNormal
);
782 const SpinbuttonValue
*pSpinButtonVal
= (aValue
.getType() == ControlType::SpinButtons
)
783 ? static_cast <const SpinbuttonValue
*>(&aValue
) : nullptr;
784 ControlState nUpperState
= ControlState::ENABLED
;
785 ControlState nLowerState
= ControlState::ENABLED
;
788 nUpperState
= pSpinButtonVal
->mnUpperState
;
789 nLowerState
= pSpinButtonVal
->mnLowerState
;
790 HIThemeButtonDrawInfo aSpinInfo
;
791 aSpinInfo
.kind
= kThemeIncDecButton
;
792 aSpinInfo
.state
= kThemeStateActive
;
793 if (nUpperState
& ControlState::PRESSED
)
794 aSpinInfo
.state
= kThemeStatePressedUp
;
795 else if (nLowerState
& ControlState::PRESSED
)
796 aSpinInfo
.state
= kThemeStatePressedDown
;
797 else if (nUpperState
& ~ControlState::ENABLED
|| nLowerState
& ~ControlState::ENABLED
)
798 aSpinInfo
.state
= kThemeStateInactive
;
799 else if (nUpperState
& ControlState::ROLLOVER
|| nLowerState
& ControlState::ROLLOVER
)
800 aSpinInfo
.state
= kThemeStateRollover
;
801 switch (aValue
.getTristateVal())
803 case ButtonValue::On
:
804 aSpinInfo
.value
= kThemeButtonOn
;
806 case ButtonValue::Off
:
807 aSpinInfo
.value
= kThemeButtonOff
;
809 case ButtonValue::Mixed
:
810 case ButtonValue::DontKnow
:
812 aSpinInfo
.value
= kThemeButtonMixed
;
815 aSpinInfo
.adornment
= (nUpperState
& ControlState::DEFAULT
|| nLowerState
& ControlState::DEFAULT
)
816 ? kThemeAdornmentDefault
: kThemeAdornmentNone
;
817 if (nUpperState
& ControlState::FOCUSED
|| nLowerState
& ControlState::FOCUSED
)
818 aSpinInfo
.adornment
|= kThemeAdornmentFocus
;
819 rc
.origin
.x
+= rc
.size
.width
+ 2 * FOCUS_RING_WIDTH
;
820 rc
.size
.width
= SPIN_BUTTON_WIDTH
;
821 rc
.size
.height
= SPIN_LOWER_BUTTON_HEIGHT
+ SPIN_LOWER_BUTTON_HEIGHT
;
822 HIThemeDrawButton(&rc
, &aSpinInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, nullptr);
827 case ControlType::Frame
:
829 DrawFrameFlags nStyle
= static_cast<DrawFrameFlags
>(aValue
.getNumericVal());
830 if (nPart
== ControlPart::Border
)
832 if (!(nStyle
& DrawFrameFlags::Menu
) && !(nStyle
& DrawFrameFlags::WindowBorder
))
835 // strange effects start to happen when HIThemeDrawFrame meets the border of the window.
836 // These can be avoided by clipping to the boundary of the frame (see issue 84756)
838 if (rc
.origin
.y
+ rc
.size
.height
>= mpFrame
->maGeometry
.nHeight
- 3)
840 CGMutablePathRef rPath
= CGPathCreateMutable();
841 CGPathAddRect(rPath
, nullptr,
842 CGRectMake(0, 0, mpFrame
->maGeometry
.nWidth
- 1, mpFrame
->maGeometry
.nHeight
- 1));
843 CGContextBeginPath(maContextHolder
.get());
844 CGContextAddPath(maContextHolder
.get(), rPath
);
845 CGContextClip(maContextHolder
.get());
846 CGPathRelease(rPath
);
848 HIThemeFrameDrawInfo aTextDrawInfo
;
849 aTextDrawInfo
.version
= 0;
850 aTextDrawInfo
.kind
= kHIThemeFrameListBox
;
851 aTextDrawInfo
.state
= kThemeStateActive
;
852 aTextDrawInfo
.isFocused
= false;
853 HIThemeDrawFrame(&rc
, &aTextDrawInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
);
859 case ControlType::ListNet
:
861 // do nothing as there isn't net for listviews on macOS
868 maContextHolder
.restoreState();
870 // in most cases invalidating the whole control region instead of just the unclipped part of it is sufficient (and probably
871 // faster). However for the window background we should not unnecessarily enlarge the really changed rectangle since the
872 // difference is usually quite high. Background is always drawn as a whole since we don't know anything about its possible
873 // contents (see issue i90291).
875 if (nType
== ControlType::WindowBackground
)
877 CGRect aRect
= {{0, 0}, {0, 0}};
879 aRect
= CGPathGetBoundingBox(mxClipPath
);
880 if (aRect
.size
.width
!= 0 && aRect
.size
.height
!= 0)
881 buttonRect
.Intersection(tools::Rectangle(Point(static_cast<tools::Long
>(aRect
.origin
.x
),
882 static_cast<tools::Long
>(aRect
.origin
.y
)),
883 Size(static_cast<tools::Long
>(aRect
.size
.width
),
884 static_cast<tools::Long
>(aRect
.size
.height
))));
886 RefreshRect(buttonRect
.Left(), buttonRect
.Top(), buttonRect
.GetWidth(), buttonRect
.GetHeight());
890 bool AquaSalGraphics::getNativeControlRegion(ControlType nType
,
892 const tools::Rectangle
&rControlRegion
,
894 const ImplControlValue
&aValue
,
896 tools::Rectangle
&rNativeBoundingRegion
,
897 tools::Rectangle
&rNativeContentRegion
)
899 bool toReturn
= false;
900 tools::Rectangle
aCtrlBoundRect(rControlRegion
);
901 short x
= aCtrlBoundRect
.Left();
902 short y
= aCtrlBoundRect
.Top();
906 case ControlType::Pushbutton
:
907 case ControlType::Radiobutton
:
908 case ControlType::Checkbox
:
910 if (nType
== ControlType::Pushbutton
)
912 w
= aCtrlBoundRect
.GetWidth();
913 h
= aCtrlBoundRect
.GetHeight();
917 w
= RADIO_BUTTON_SMALL_SIZE
+ 2 * FOCUS_RING_WIDTH
+ RADIO_BUTTON_TEXT_SEPARATOR
;
918 h
= RADIO_BUTTON_SMALL_SIZE
+ 2 * FOCUS_RING_WIDTH
;
920 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
921 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
925 case ControlType::Progress
:
927 tools::Rectangle
aRect(aCtrlBoundRect
);
928 if (aRect
.GetHeight() < LARGE_PROGRESS_INDICATOR_HEIGHT
)
929 aRect
.SetBottom(aRect
.Top() + MEDIUM_PROGRESS_INDICATOR_HEIGHT
- 1);
931 aRect
.SetBottom(aRect
.Top() + LARGE_PROGRESS_INDICATOR_HEIGHT
- 1);
932 rNativeBoundingRegion
= aRect
;
933 rNativeContentRegion
= aRect
;
937 case ControlType::IntroProgress
:
939 tools::Rectangle
aRect(aCtrlBoundRect
);
940 aRect
.SetBottom(aRect
.Top() + MEDIUM_PROGRESS_INDICATOR_HEIGHT
- 1);
941 rNativeBoundingRegion
= aRect
;
942 rNativeContentRegion
= aRect
;
946 case ControlType::Slider
:
947 if (nPart
== ControlPart::ThumbHorz
)
950 h
= aCtrlBoundRect
.GetHeight();
951 rNativeBoundingRegion
= rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
954 else if (nPart
== ControlPart::ThumbVert
)
956 w
= aCtrlBoundRect
.GetWidth();
958 rNativeBoundingRegion
= rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
962 case ControlType::Scrollbar
:
964 tools::Rectangle aRect
;
965 if (AquaGetScrollRect(nPart
, aCtrlBoundRect
, aRect
))
968 rNativeBoundingRegion
= aRect
;
969 rNativeContentRegion
= aRect
;
973 case ControlType::TabItem
:
975 w
= aCtrlBoundRect
.GetWidth() + 2 * TAB_TEXT_MARGIN
- 2 * VCL_TAB_TEXT_SEPARATOR
;
977 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
978 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
982 case ControlType::Editbox
:
984 w
= aCtrlBoundRect
.GetWidth();
985 h
= EDITBOX_HEIGHT
+ 2 * FOCUS_RING_WIDTH
;
986 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
987 w
-= 2 * (FOCUS_RING_WIDTH
+ EDITBOX_BORDER_WIDTH
+ EDITBOX_INSET_MARGIN
);
988 h
-= 2 * (FOCUS_RING_WIDTH
+ EDITBOX_BORDER_WIDTH
+ EDITBOX_INSET_MARGIN
);
989 x
+= FOCUS_RING_WIDTH
+ EDITBOX_BORDER_WIDTH
+ EDITBOX_INSET_MARGIN
;
990 y
+= FOCUS_RING_WIDTH
+ EDITBOX_BORDER_WIDTH
+ EDITBOX_INSET_MARGIN
;
991 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
995 case ControlType::Combobox
:
996 if (nPart
== ControlPart::Entire
)
998 w
= aCtrlBoundRect
.GetWidth();
999 h
= COMBOBOX_HEIGHT
+ 2 * FOCUS_RING_WIDTH
;
1000 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1001 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1004 else if (nPart
== ControlPart::ButtonDown
)
1006 w
= COMBOBOX_BUTTON_WIDTH
+ FOCUS_RING_WIDTH
;
1007 h
= COMBOBOX_HEIGHT
+ 2 * FOCUS_RING_WIDTH
;
1008 x
+= aCtrlBoundRect
.GetWidth() - w
;
1009 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1010 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1013 else if (nPart
== ControlPart::SubEdit
)
1015 w
= aCtrlBoundRect
.GetWidth() - 2 * FOCUS_RING_WIDTH
- COMBOBOX_BUTTON_WIDTH
- COMBOBOX_BORDER_WIDTH
1016 - 2 * COMBOBOX_TEXT_MARGIN
;
1017 h
= COMBOBOX_HEIGHT
- 2 * COMBOBOX_BORDER_WIDTH
;
1018 x
+= FOCUS_RING_WIDTH
+ COMBOBOX_BORDER_WIDTH
+ COMBOBOX_TEXT_MARGIN
;
1019 y
+= FOCUS_RING_WIDTH
+ COMBOBOX_BORDER_WIDTH
;
1020 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1021 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1025 case ControlType::Listbox
:
1026 if (nPart
== ControlPart::Entire
)
1028 w
= aCtrlBoundRect
.GetWidth();
1029 h
= LISTBOX_HEIGHT
+ 2 * FOCUS_RING_WIDTH
;
1030 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1031 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1034 else if (nPart
== ControlPart::ButtonDown
)
1036 w
= LISTBOX_BUTTON_WIDTH
+ FOCUS_RING_WIDTH
;
1037 h
= LISTBOX_HEIGHT
+ 2 * FOCUS_RING_WIDTH
;
1038 x
+= aCtrlBoundRect
.GetWidth() - w
;
1039 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1040 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1043 else if (nPart
== ControlPart::SubEdit
)
1045 w
= aCtrlBoundRect
.GetWidth() - 2 * FOCUS_RING_WIDTH
- LISTBOX_BUTTON_WIDTH
- LISTBOX_BORDER_WIDTH
1046 - 2 * LISTBOX_TEXT_MARGIN
;
1047 h
= LISTBOX_HEIGHT
- 2 * LISTBOX_BORDER_WIDTH
;
1048 x
+= FOCUS_RING_WIDTH
+ LISTBOX_BORDER_WIDTH
+ LISTBOX_TEXT_MARGIN
;
1049 y
+= FOCUS_RING_WIDTH
+ LISTBOX_BORDER_WIDTH
;
1050 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1051 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1055 case ControlType::Spinbox
:
1056 if (nPart
== ControlPart::Entire
)
1058 w
= aCtrlBoundRect
.GetWidth();
1059 h
= EDITBOX_HEIGHT
+ 2 * FOCUS_RING_WIDTH
;
1060 x
+= SPINBOX_OFFSET
;
1061 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1062 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1065 else if (nPart
== ControlPart::SubEdit
)
1067 w
= aCtrlBoundRect
.GetWidth() - 4 * FOCUS_RING_WIDTH
- SPIN_BUTTON_WIDTH
- 2 * EDITBOX_BORDER_WIDTH
1068 - 2 * EDITBOX_INSET_MARGIN
;
1069 h
= EDITBOX_HEIGHT
- 2 * (EDITBOX_BORDER_WIDTH
+ EDITBOX_INSET_MARGIN
);
1070 x
+= FOCUS_RING_WIDTH
+ EDITBOX_BORDER_WIDTH
+ EDITBOX_INSET_MARGIN
+ SPINBOX_OFFSET
;
1071 y
+= FOCUS_RING_WIDTH
+ EDITBOX_BORDER_WIDTH
+ EDITBOX_INSET_MARGIN
;
1072 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1073 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1076 else if (nPart
== ControlPart::ButtonUp
)
1078 w
= SPIN_BUTTON_WIDTH
+ 2 * FOCUS_RING_WIDTH
;
1079 h
= SPIN_UPPER_BUTTON_HEIGHT
+ FOCUS_RING_WIDTH
;
1080 x
+= aCtrlBoundRect
.GetWidth() - SPIN_BUTTON_WIDTH
- 2 * FOCUS_RING_WIDTH
+ SPINBOX_OFFSET
;
1081 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1082 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1085 else if (nPart
== ControlPart::ButtonDown
)
1087 w
= SPIN_BUTTON_WIDTH
+ 2 * FOCUS_RING_WIDTH
;
1088 h
= SPIN_LOWER_BUTTON_HEIGHT
+ FOCUS_RING_WIDTH
;
1089 x
+= aCtrlBoundRect
.GetWidth() - SPIN_BUTTON_WIDTH
- 2 * FOCUS_RING_WIDTH
+ SPINBOX_OFFSET
;
1090 y
+= FOCUS_RING_WIDTH
+ SPIN_UPPER_BUTTON_HEIGHT
;
1091 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1092 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1096 case ControlType::Frame
:
1098 DrawFrameStyle nStyle
= static_cast<DrawFrameStyle
>(aValue
.getNumericVal() & 0x000f);
1099 DrawFrameFlags nFlags
= static_cast<DrawFrameFlags
>(aValue
.getNumericVal() & 0xfff0);
1100 if (nPart
== ControlPart::Border
1101 && !(nFlags
& (DrawFrameFlags::Menu
| DrawFrameFlags::WindowBorder
| DrawFrameFlags::BorderWindowBorder
)))
1103 tools::Rectangle
aRect(aCtrlBoundRect
);
1104 if (nStyle
== DrawFrameStyle::DoubleIn
)
1106 aRect
.AdjustLeft(1);
1108 // rRect.Right() -= 1;
1109 // rRect.Bottom() -= 1;
1113 aRect
.AdjustLeft(1);
1115 aRect
.AdjustRight(-1);
1116 aRect
.AdjustBottom(-1);
1118 rNativeContentRegion
= aRect
;
1119 rNativeBoundingRegion
= aRect
;
1124 case ControlType::Menubar
:
1125 case ControlType::MenuPopup
:
1126 if (nPart
== ControlPart::MenuItemCheckMark
|| nPart
== ControlPart::MenuItemRadioMark
)
1130 rNativeContentRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1131 rNativeBoundingRegion
= tools::Rectangle(Point(x
, y
), Size(w
, h
));
1141 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */