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 #if !HAVE_FEATURE_MACOSX_SANDBOX
41 @interface
NSWindow(CoreUIRendererPrivate
)
42 + (CUIRendererRef
)coreUIRenderer
;
47 // Helper returns an HIRect
49 static HIRect
ImplGetHIRectFromRectangle(tools::Rectangle aRect
)
52 aHIRect
.origin
.x
= static_cast<float>(aRect
.Left());
53 aHIRect
.origin
.y
= static_cast<float>(aRect
.Top());
54 aHIRect
.size
.width
= static_cast<float>(aRect
.GetWidth());
55 aHIRect
.size
.height
= static_cast<float>(aRect
.GetHeight());
59 static ThemeButtonValue
ImplGetButtonValue( ButtonValue aButtonValue
)
61 switch( aButtonValue
)
64 return kThemeButtonOn
;
67 case ButtonValue::Off
:
68 case ButtonValue::DontKnow
:
69 return kThemeButtonOff
;
72 case ButtonValue::Mixed
:
74 return kThemeButtonMixed
;
79 static bool AquaGetScrollRect( /* TODO: int nScreen, */ ControlPart nPart
,
80 const tools::Rectangle
& rControlRect
, tools::Rectangle
& rResultRect
)
83 rResultRect
= rControlRect
;
87 case ControlPart::ButtonUp
:
88 rResultRect
.SetBottom( rResultRect
.Top() );
91 case ControlPart::ButtonDown
:
92 rResultRect
.SetTop( rResultRect
.Bottom() );
95 case ControlPart::ButtonLeft
:
96 rResultRect
.SetRight( rResultRect
.Left() );
99 case ControlPart::ButtonRight
:
100 rResultRect
.SetLeft( rResultRect
.Right() );
103 case ControlPart::TrackHorzArea
:
104 case ControlPart::TrackVertArea
:
105 case ControlPart::ThumbHorz
:
106 case ControlPart::ThumbVert
:
107 case ControlPart::TrackHorzLeft
:
108 case ControlPart::TrackHorzRight
:
109 case ControlPart::TrackVertUpper
:
110 case ControlPart::TrackVertLower
:
119 bool AquaSalGraphics::isNativeControlSupported( ControlType nType
, ControlPart nPart
)
121 // Native controls are now defaults
122 // If you want to disable experimental native controls code,
123 // just set the environment variable SAL_NO_NWF to something
124 // and vcl controls will be used as default again.
128 case ControlType::Pushbutton
:
129 case ControlType::Radiobutton
:
130 case ControlType::Checkbox
:
131 case ControlType::ListNode
:
132 if( nPart
== ControlPart::Entire
)
136 case ControlType::Scrollbar
:
137 if( nPart
== ControlPart::DrawBackgroundHorz
||
138 nPart
== ControlPart::DrawBackgroundVert
||
139 nPart
== ControlPart::Entire
||
140 nPart
== ControlPart::HasThreeButtons
)
144 case ControlType::Slider
:
145 if( nPart
== ControlPart::TrackHorzArea
|| nPart
== ControlPart::TrackVertArea
)
149 case ControlType::Editbox
:
150 if( nPart
== ControlPart::Entire
||
151 nPart
== ControlPart::HasBackgroundTexture
)
155 case ControlType::MultilineEditbox
:
156 if( nPart
== ControlPart::Entire
||
157 nPart
== ControlPart::HasBackgroundTexture
)
161 case ControlType::Spinbox
:
162 if( nPart
== ControlPart::Entire
||
163 nPart
== ControlPart::AllButtons
||
164 nPart
== ControlPart::HasBackgroundTexture
)
168 case ControlType::SpinButtons
:
172 case ControlType::Combobox
:
173 if( nPart
== ControlPart::Entire
||
174 nPart
== ControlPart::HasBackgroundTexture
)
178 case ControlType::Listbox
:
179 if( nPart
== ControlPart::Entire
||
180 nPart
== ControlPart::ListboxWindow
||
181 nPart
== ControlPart::HasBackgroundTexture
||
182 nPart
== ControlPart::SubEdit
187 case ControlType::TabItem
:
188 case ControlType::TabPane
:
189 case ControlType::TabBody
: // see vcl/source/window/tabpage.cxx
190 if( nPart
== ControlPart::Entire
||
191 nPart
== ControlPart::TabsDrawRtl
||
192 nPart
== ControlPart::HasBackgroundTexture
)
196 // when ControlPart::Button is used, toolbar icons are not highlighted when mouse rolls over.
197 // More Aqua compliant
198 case ControlType::Toolbar
:
199 if( nPart
== ControlPart::Entire
||
200 nPart
== ControlPart::DrawBackgroundHorz
||
201 nPart
== ControlPart::DrawBackgroundVert
)
205 case ControlType::WindowBackground
:
206 if ( nPart
== ControlPart::BackgroundWindow
||
207 nPart
== ControlPart::BackgroundDialog
)
211 case ControlType::Menubar
:
212 if( nPart
== ControlPart::Entire
)
216 case ControlType::Tooltip
: // ** TO DO
217 if (nPart
== ControlPart::Entire
)
221 case ControlType::MenuPopup
:
222 if( nPart
== ControlPart::Entire
||
223 nPart
== ControlPart::MenuItem
||
224 nPart
== ControlPart::MenuItemCheckMark
||
225 nPart
== ControlPart::MenuItemRadioMark
)
228 case ControlType::Progress
:
229 case ControlType::IntroProgress
:
230 if( nPart
== ControlPart::Entire
)
233 case ControlType::Frame
:
234 if( nPart
== ControlPart::Border
)
237 case ControlType::ListNet
:
238 if( nPart
== ControlPart::Entire
)
247 bool AquaSalGraphics::hitTestNativeControl( ControlType nType
, ControlPart nPart
, const tools::Rectangle
& rControlRegion
,
248 const Point
& rPos
, bool& rIsInside
)
250 if ( nType
== ControlType::Scrollbar
)
252 tools::Rectangle aRect
;
253 bool bValid
= AquaGetScrollRect( /* TODO: m_nScreen */ nPart
, rControlRegion
, aRect
);
254 rIsInside
= bValid
&& aRect
.IsInside( rPos
);
256 } // ControlType::Scrollbar
262 kThemeStateInactive = 0,
263 kThemeStateActive = 1,
264 kThemeStatePressed = 2,
265 kThemeStateRollover = 6,
266 kThemeStateUnavailable = 7,
267 kThemeStateUnavailableInactive = 8
268 kThemeStatePressedUp = 2,
269 kThemeStatePressedDown = 3
271 UInt32
AquaSalGraphics::getState( ControlState nState
)
273 const bool bDrawActive
= mpFrame
== nullptr || [mpFrame
->getNSWindow() isKeyWindow
];
274 if( !(nState
& ControlState::ENABLED
) || ! bDrawActive
)
276 return kThemeStateInactive
;
279 if( nState
& ControlState::PRESSED
)
280 return kThemeStatePressed
;
282 return kThemeStateActive
;
285 UInt32
AquaSalGraphics::getTrackState( ControlState nState
)
287 const bool bDrawActive
= mpFrame
== nullptr || [mpFrame
->getNSWindow() isKeyWindow
];
288 if( ! (nState
& ControlState::ENABLED
) || ! bDrawActive
)
289 return kThemeTrackInactive
;
291 return kThemeTrackActive
;
294 bool AquaSalGraphics::drawNativeControl(ControlType nType
,
296 const tools::Rectangle
& rControlRegion
,
298 const ImplControlValue
& aValue
,
303 if( ! CheckContext() )
306 maContextHolder
.saveState();
308 tools::Rectangle buttonRect
= rControlRegion
;
309 HIRect rc
= ImplGetHIRectFromRectangle(buttonRect
);
314 case ControlType::Combobox
:
315 if ( nPart
== ControlPart::HasBackgroundTexture
||
316 nPart
== ControlPart::Entire
)
318 HIThemeButtonDrawInfo aComboInfo
;
319 aComboInfo
.version
= 0;
320 aComboInfo
.kind
= kThemeComboBox
;
321 aComboInfo
.state
= getState( nState
);
322 aComboInfo
.value
= kThemeButtonOn
;
323 aComboInfo
.adornment
= kThemeAdornmentNone
;
325 if( nState
& ControlState::FOCUSED
)
326 aComboInfo
.adornment
|= kThemeAdornmentFocus
;
328 HIThemeDrawButton(&rc
, &aComboInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
,&rc
);
333 case ControlType::Toolbar
:
335 #if HAVE_FEATURE_MACOSX_SANDBOX
336 HIThemeMenuItemDrawInfo aMenuItemDrawInfo
;
337 aMenuItemDrawInfo
.version
= 0;
338 aMenuItemDrawInfo
.state
= kThemeMenuActive
;
339 aMenuItemDrawInfo
.itemType
= kThemeMenuItemHierBackground
;
340 HIThemeDrawMenuItem(&rc
,&rc
,&aMenuItemDrawInfo
,maContextHolder
.get(),kHIThemeOrientationNormal
,NULL
);
342 if (rControlRegion
.Top() == 0 && nPart
== ControlPart::DrawBackgroundHorz
)
344 const bool bDrawActive
= mpFrame
== nullptr || [mpFrame
->getNSWindow() isKeyWindow
];
345 CGFloat unifiedHeight
= rControlRegion
.GetHeight();
346 CGRect drawRect
= CGRectMake(rControlRegion
.Left(), rControlRegion
.Top(), rControlRegion
.GetWidth(), rControlRegion
.GetHeight());
347 CUIDraw([NSWindow coreUIRenderer
], drawRect
, maContextHolder
.get(),
348 reinterpret_cast<CFDictionaryRef
>([NSDictionary dictionaryWithObjectsAndKeys
:
349 @
"kCUIWidgetWindowFrame", @
"widget",
350 @
"regularwin", @
"windowtype",
351 (bDrawActive
? @
"normal" : @
"inactive"), @
"state",
352 [NSNumber numberWithDouble
:unifiedHeight
], @
"kCUIWindowFrameUnifiedTitleBarHeightKey",
353 [NSNumber numberWithBool
:NO
], @
"kCUIWindowFrameDrawTitleSeparatorKey",
354 [NSNumber numberWithBool
:YES
], @
"is.flipped",
360 HIThemeMenuItemDrawInfo aMenuItemDrawInfo
;
361 aMenuItemDrawInfo
.version
= 0;
362 aMenuItemDrawInfo
.state
= kThemeMenuActive
;
363 aMenuItemDrawInfo
.itemType
= kThemeMenuItemHierBackground
;
364 HIThemeDrawMenuItem(&rc
, &rc
, &aMenuItemDrawInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, nullptr);
371 case ControlType::WindowBackground
:
373 HIThemeBackgroundDrawInfo aThemeBackgroundInfo
;
374 aThemeBackgroundInfo
.version
= 0;
375 aThemeBackgroundInfo
.state
= getState( nState
);
376 aThemeBackgroundInfo
.kind
= kThemeBrushDialogBackgroundActive
;
377 // FIXME: without this magical offset there is a 2 pixel black border on the right and bottom
381 HIThemeApplyBackground( &rc
, &aThemeBackgroundInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
);
382 CGContextFillRect( maContextHolder
.get(), rc
);
387 case ControlType::Tooltip
:
389 HIThemeBackgroundDrawInfo aThemeBackgroundInfo
;
390 aThemeBackgroundInfo
.version
= 0;
391 aThemeBackgroundInfo
.state
= getState( nState
);
392 aThemeBackgroundInfo
.kind
= kThemeBrushAlertBackgroundActive
;
396 HIThemeApplyBackground( &rc
, &aThemeBackgroundInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
);
397 CGContextFillRect( maContextHolder
.get(), rc
);
402 case ControlType::Menubar
:
403 case ControlType::MenuPopup
:
405 if ((nPart
== ControlPart::Entire
) || (nPart
== ControlPart::MenuItem
)|| (nPart
== ControlPart::HasBackgroundTexture
))
407 // FIXME: without this magical offset there is a 2 pixel black border on the right
410 HIThemeMenuDrawInfo aMenuInfo
;
411 aMenuInfo
.version
= 0;
412 aMenuInfo
.menuType
= kThemeMenuTypePullDown
;
414 HIThemeMenuItemDrawInfo aMenuItemDrawInfo
;
415 // the Aqua grey theme when the item is selected is drawn here.
416 aMenuItemDrawInfo
.itemType
= kThemeMenuItemPlain
;
418 if ((nPart
== ControlPart::MenuItem
) && (nState
& ControlState::SELECTED
))
420 // the blue theme when the item is selected is drawn here.
421 aMenuItemDrawInfo
.state
= kThemeMenuSelected
;
425 // normal color for non selected item
426 aMenuItemDrawInfo
.state
= kThemeMenuActive
;
429 // repaints the background of the pull down menu
430 HIThemeDrawMenuBackground(&rc
,&aMenuInfo
,maContextHolder
.get(),kHIThemeOrientationNormal
);
432 // repaints the item either blue (selected) and/or Aqua grey (active only)
433 HIThemeDrawMenuItem(&rc
,&rc
,&aMenuItemDrawInfo
,maContextHolder
.get(),kHIThemeOrientationNormal
,&rc
);
437 else if(( nPart
== ControlPart::MenuItemCheckMark
)||( nPart
== ControlPart::MenuItemRadioMark
)) {
438 if( nState
& ControlState::PRESSED
) {//checked, else it is not displayed (see vcl/source/window/menu.cxx)
439 HIThemeTextInfo aTextInfo
;
440 aTextInfo
.version
= 0;
441 aTextInfo
.state
= (nState
& ControlState::ENABLED
) ? kThemeStateInactive
: kThemeStateActive
;
442 aTextInfo
.fontID
= kThemeMenuItemMarkFont
;
443 aTextInfo
.horizontalFlushness
=kHIThemeTextHorizontalFlushCenter
;
444 aTextInfo
.verticalFlushness
=kHIThemeTextVerticalFlushTop
;
445 aTextInfo
.options
=kHIThemeTextBoxOptionNone
;
446 aTextInfo
.truncationPosition
=kHIThemeTextTruncationNone
;
447 //aTextInfo.truncationMaxLines unused because of kHIThemeTextTruncationNone
449 if( nState
& ControlState::SELECTED
) aTextInfo
.state
= kThemeStatePressed
; //item highlighted
451 UniChar mark
=( nPart
== ControlPart::MenuItemCheckMark
) ? kCheckUnicode
: kBulletUnicode
;//0x2713;
452 CFStringRef cfString
= CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault
, &mark
, 1, kCFAllocatorNull
);
453 HIThemeDrawTextBox(cfString
, &rc
, &aTextInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
);
463 case ControlType::Pushbutton
:
465 // [ FIXME] : instead of use a value, vcl can retrieve correct values on the fly (to be implemented)
466 const int PB_Mini_Height
= 15;
467 const int PB_Norm_Height
= 21;
469 HIThemeButtonDrawInfo aPushInfo
;
470 aPushInfo
.version
= 0;
473 aPushInfo
.animation
.time
.start
= 0;
474 aPushInfo
.animation
.time
.current
= 0;
475 PushButtonValue
const * pPBVal
= aValue
.getType() == ControlType::Pushbutton
? static_cast<PushButtonValue
const *>(&aValue
) : nullptr;
476 int nPaintHeight
= static_cast<int>(rc
.size
.height
);
478 if( pPBVal
&& pPBVal
->mbBevelButton
)
480 aPushInfo
.kind
= kThemeRoundedBevelButton
;
482 else if( rc
.size
.height
<= PB_Norm_Height
)
484 aPushInfo
.kind
= kThemePushButtonMini
;
485 nPaintHeight
= PB_Mini_Height
;
487 else if( (pPBVal
&& pPBVal
->mbSingleLine
) || rc
.size
.height
< (PB_Norm_Height
+ PB_Norm_Height
/2) )
489 aPushInfo
.kind
= kThemePushButtonNormal
;
490 nPaintHeight
= PB_Norm_Height
;
492 // avoid clipping when focused
493 rc
.origin
.x
+= FOCUS_RING_WIDTH
/2;
494 rc
.size
.width
-= FOCUS_RING_WIDTH
;
497 aPushInfo
.kind
= kThemeBevelButton
;
499 // translate the origin for controls with fixed paint height
500 // so content ends up somewhere sensible
501 int delta_y
= static_cast<int>(rc
.size
.height
) - nPaintHeight
;
502 rc
.origin
.y
+= delta_y
/2;
504 aPushInfo
.state
= getState( nState
);
505 aPushInfo
.value
= ImplGetButtonValue( aValue
.getTristateVal() );
507 aPushInfo
.adornment
= ( nState
& ControlState::DEFAULT
) ?
508 kThemeAdornmentDefault
:
510 if( nState
& ControlState::FOCUSED
)
511 aPushInfo
.adornment
|= kThemeAdornmentFocus
;
513 HIThemeDrawButton( &rc
, &aPushInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, nullptr );
518 case ControlType::Radiobutton
:
519 case ControlType::Checkbox
:
521 HIThemeButtonDrawInfo aInfo
;
525 case ControlType::Radiobutton
: if(rc
.size
.width
>= BUTTON_HEIGHT
) aInfo
.kind
= kThemeRadioButton
;
526 else aInfo
.kind
= kThemeSmallRadioButton
;
528 case ControlType::Checkbox
: if(rc
.size
.width
>= BUTTON_HEIGHT
) aInfo
.kind
= kThemeCheckBox
;
529 else aInfo
.kind
= kThemeSmallCheckBox
;
534 aInfo
.state
= getState( nState
);
536 ButtonValue aButtonValue
= aValue
.getTristateVal();
537 aInfo
.value
= ImplGetButtonValue( aButtonValue
);
539 aInfo
.adornment
= ( nState
& ControlState::DEFAULT
) ?
540 kThemeAdornmentDefault
:
542 if( nState
& ControlState::FOCUSED
)
543 aInfo
.adornment
|= kThemeAdornmentFocus
;
544 HIThemeDrawButton( &rc
, &aInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, nullptr );
549 case ControlType::ListNode
:
551 ButtonValue aButtonValue
= aValue
.getTristateVal();
553 if( AllSettings::GetLayoutRTL() && aButtonValue
== ButtonValue::Off
)
555 // FIXME: a value of kThemeDisclosureLeft
556 // should draw a theme compliant left disclosure triangle
557 // sadly this does not seem to work, so we'll draw a left
558 // grey equilateral triangle here ourselves.
559 // Perhaps some other HIThemeButtonDrawInfo setting would do the trick ?
561 CGContextSetShouldAntialias( maContextHolder
.get(), true );
562 CGFloat
const aGrey
[] = { 0.45, 0.45, 0.45, 1.0 };
563 CGContextSetFillColor( maContextHolder
.get(), aGrey
);
564 CGContextBeginPath( maContextHolder
.get() );
565 float x
= rc
.origin
.x
+ rc
.size
.width
;
566 float y
= rc
.origin
.y
;
567 CGContextMoveToPoint( maContextHolder
.get(), x
, y
);
569 CGContextAddLineToPoint( maContextHolder
.get(), x
, y
);
570 x
-= rc
.size
.height
* 0.866; // cos( 30 degree ) is approx. 0.866
571 y
-= rc
.size
.height
/2;
572 CGContextAddLineToPoint( maContextHolder
.get(), x
, y
);
573 CGContextDrawPath( maContextHolder
.get(), kCGPathEOFill
);
577 HIThemeButtonDrawInfo aInfo
;
579 aInfo
.kind
= kThemeDisclosureTriangle
;
580 aInfo
.value
= kThemeDisclosureRight
;
581 aInfo
.state
= getState( nState
);
583 aInfo
.adornment
= kThemeAdornmentNone
;
585 switch( aButtonValue
) {
586 case ButtonValue::On
: aInfo
.value
= kThemeDisclosureDown
;//expanded
588 case ButtonValue::Off
:
589 // FIXME: this should have drawn a theme compliant disclosure triangle
591 if( AllSettings::GetLayoutRTL() )
593 aInfo
.value
= kThemeDisclosureLeft
;//collapsed, RTL
596 case ButtonValue::DontKnow
: //what to do?
601 HIThemeDrawButton( &rc
, &aInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, nullptr );
607 case ControlType::Progress
:
608 case ControlType::IntroProgress
:
610 long nProgressWidth
= aValue
.getNumericVal();
611 HIThemeTrackDrawInfo aTrackInfo
;
612 aTrackInfo
.version
= 0;
613 aTrackInfo
.kind
= (rc
.size
.height
> 10) ? kThemeProgressBarLarge
: kThemeProgressBarMedium
;
614 aTrackInfo
.bounds
= rc
;
616 aTrackInfo
.max
= static_cast<SInt32
>(rc
.size
.width
);
617 aTrackInfo
.value
= nProgressWidth
;
618 aTrackInfo
.reserved
= 0;
619 aTrackInfo
.bounds
.origin
.y
-= 2; // FIXME: magic for shadow
620 aTrackInfo
.bounds
.size
.width
-= 2; // FIXME: magic for shadow
621 aTrackInfo
.attributes
= kThemeTrackHorizontal
;
622 if( AllSettings::GetLayoutRTL() )
623 aTrackInfo
.attributes
|= kThemeTrackRightToLeft
;
624 aTrackInfo
.enableState
= getTrackState( nState
);
625 // the intro bitmap never gets key anyway; we want to draw that enabled
626 if( nType
== ControlType::IntroProgress
)
627 aTrackInfo
.enableState
= kThemeTrackActive
;
628 aTrackInfo
.filler1
= 0;
629 aTrackInfo
.trackInfo
.progress
.phase
= static_cast<long long>(CFAbsoluteTimeGetCurrent()*10.0);
631 HIThemeDrawTrack( &aTrackInfo
, nullptr, maContextHolder
.get(), kHIThemeOrientationNormal
);
636 case ControlType::Slider
:
638 SliderValue
const * pSLVal
= static_cast<SliderValue
const *>(&aValue
);
640 HIThemeTrackDrawInfo aTrackDraw
;
641 aTrackDraw
.kind
= kThemeSliderMedium
;
642 if( nPart
== ControlPart::TrackHorzArea
|| nPart
== ControlPart::TrackVertArea
)
644 aTrackDraw
.bounds
= rc
;
645 aTrackDraw
.min
= pSLVal
->mnMin
;
646 aTrackDraw
.max
= pSLVal
->mnMax
;
647 aTrackDraw
.value
= pSLVal
->mnCur
;
648 aTrackDraw
.reserved
= 0;
649 aTrackDraw
.attributes
= kThemeTrackShowThumb
;
650 if( nPart
== ControlPart::TrackHorzArea
)
651 aTrackDraw
.attributes
|= kThemeTrackHorizontal
;
652 aTrackDraw
.enableState
= (nState
& ControlState::ENABLED
)
653 ? kThemeTrackActive
: kThemeTrackInactive
;
655 SliderTrackInfo aSlideInfo
;
656 aSlideInfo
.thumbDir
= kThemeThumbUpward
;
657 aSlideInfo
.pressState
= 0;
658 aTrackDraw
.trackInfo
.slider
= aSlideInfo
;
660 HIThemeDrawTrack( &aTrackDraw
, nullptr, maContextHolder
.get(), kHIThemeOrientationNormal
);
666 case ControlType::Scrollbar
:
668 const ScrollbarValue
* pScrollbarVal
= (aValue
.getType() == ControlType::Scrollbar
) ? static_cast<const ScrollbarValue
*>(&aValue
) : nullptr;
670 if( nPart
== ControlPart::DrawBackgroundVert
||
671 nPart
== ControlPart::DrawBackgroundHorz
)
673 HIThemeTrackDrawInfo aTrackDraw
;
674 aTrackDraw
.kind
= kThemeMediumScrollBar
;
675 // FIXME: the scrollbar length must be adjusted
676 if (nPart
== ControlPart::DrawBackgroundVert
)
681 aTrackDraw
.bounds
= rc
;
682 aTrackDraw
.min
= pScrollbarVal
->mnMin
;
683 aTrackDraw
.max
= pScrollbarVal
->mnMax
- pScrollbarVal
->mnVisibleSize
;
684 aTrackDraw
.value
= pScrollbarVal
->mnCur
;
685 aTrackDraw
.reserved
= 0;
686 aTrackDraw
.attributes
= kThemeTrackShowThumb
;
687 if( nPart
== ControlPart::DrawBackgroundHorz
)
688 aTrackDraw
.attributes
|= kThemeTrackHorizontal
;
689 aTrackDraw
.enableState
= getTrackState( nState
);
691 ScrollBarTrackInfo aScrollInfo
;
692 aScrollInfo
.viewsize
= pScrollbarVal
->mnVisibleSize
;
693 aScrollInfo
.pressState
= 0;
695 if ( pScrollbarVal
->mnButton1State
& ControlState::ENABLED
)
697 if ( pScrollbarVal
->mnButton1State
& ControlState::PRESSED
)
698 aScrollInfo
.pressState
= kThemeTopOutsideArrowPressed
;
701 if ( pScrollbarVal
->mnButton2State
& ControlState::ENABLED
)
703 if ( pScrollbarVal
->mnButton2State
& ControlState::PRESSED
)
704 aScrollInfo
.pressState
= kThemeBottomOutsideArrowPressed
;
707 if ( pScrollbarVal
->mnThumbState
& ControlState::ENABLED
)
709 if ( pScrollbarVal
->mnThumbState
& ControlState::PRESSED
)
710 aScrollInfo
.pressState
= kThemeThumbPressed
;
713 aTrackDraw
.trackInfo
.scrollbar
= aScrollInfo
;
715 HIThemeDrawTrack( &aTrackDraw
, nullptr, maContextHolder
.get(), kHIThemeOrientationNormal
);
721 case ControlType::TabPane
:
723 HIThemeTabPaneDrawInfo aTabPaneDrawInfo
;
724 aTabPaneDrawInfo
.version
= 1;
725 aTabPaneDrawInfo
.state
= kThemeStateActive
;
726 aTabPaneDrawInfo
.direction
=kThemeTabNorth
;
727 aTabPaneDrawInfo
.size
=kHIThemeTabSizeNormal
;
728 aTabPaneDrawInfo
.kind
=kHIThemeTabKindNormal
;
730 //the border is outside the rect rc for Carbon
731 //but for VCL it should be inside
733 rc
.origin
.y
-=TAB_HEIGHT_NORMAL
/2;
734 rc
.size
.height
+=TAB_HEIGHT_NORMAL
/2;
737 HIThemeDrawTabPane(&rc
, &aTabPaneDrawInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
);
743 case ControlType::TabItem
:
745 HIThemeTabDrawInfo aTabItemDrawInfo
;
746 aTabItemDrawInfo
.version
=1;
747 aTabItemDrawInfo
.style
=kThemeTabNonFront
;
748 aTabItemDrawInfo
.direction
=kThemeTabNorth
;
749 aTabItemDrawInfo
.size
=kHIThemeTabSizeNormal
;
750 aTabItemDrawInfo
.adornment
=kHIThemeTabAdornmentTrailingSeparator
;
752 if(nState
& ControlState::SELECTED
) {
753 aTabItemDrawInfo
.style
=kThemeTabFront
;
755 if(nState
& ControlState::FOCUSED
) {
756 aTabItemDrawInfo
.adornment
|=kHIThemeTabAdornmentFocus
;
759 //first, last or middle tab
760 aTabItemDrawInfo
.position
=kHIThemeTabPositionMiddle
;
762 TabitemValue
const * pTabValue
= static_cast<TabitemValue
const *>(&aValue
);
763 TabitemFlags nAlignment
= pTabValue
->mnAlignment
;
764 //TabitemFlags::LeftAligned (and TabitemFlags::RightAligned) for the leftmost (or rightmost) tab
765 //when there are several lines of tabs because there is only one first tab and one
766 //last tab and TabitemFlags::FirstInGroup (and TabitemFlags::LastInGroup) because when the
767 //line width is different from window width, there may not be TabitemFlags::RightAligned
768 if( ( (nAlignment
& TabitemFlags::LeftAligned
)&&(nAlignment
& TabitemFlags::RightAligned
) ) ||
769 ( (nAlignment
& TabitemFlags::FirstInGroup
)&&(nAlignment
& TabitemFlags::LastInGroup
) )
771 aTabItemDrawInfo
.position
=kHIThemeTabPositionOnly
;
772 else if((nAlignment
& TabitemFlags::LeftAligned
)||(nAlignment
& TabitemFlags::FirstInGroup
))
773 aTabItemDrawInfo
.position
=kHIThemeTabPositionFirst
;
774 else if((nAlignment
& TabitemFlags::RightAligned
)||(nAlignment
& TabitemFlags::LastInGroup
))
775 aTabItemDrawInfo
.position
=kHIThemeTabPositionLast
;
779 if( AllSettings::GetLayoutRTL() ) {
780 if( aTabItemDrawInfo
.position
== kHIThemeTabPositionFirst
)
781 aTabItemDrawInfo
.position
= kHIThemeTabPositionLast
;
782 else if( aTabItemDrawInfo
.position
== kHIThemeTabPositionLast
)
783 aTabItemDrawInfo
.position
= kHIThemeTabPositionFirst
;
786 rc
.size
.width
+=2;//because VCL has 2 empty pixels between 2 tabs
789 HIThemeDrawTab(&rc
, &aTabItemDrawInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, &rc
);
795 case ControlType::Listbox
:
798 case ControlPart::Entire
:
799 case ControlPart::ButtonDown
:
801 HIThemeButtonDrawInfo aListInfo
;
802 aListInfo
.version
= 0;
803 aListInfo
.kind
= kThemePopupButton
;
804 aListInfo
.state
= getState( nState
);//kThemeStateInactive -> greyed
805 aListInfo
.value
= kThemeButtonOn
;
807 aListInfo
.adornment
= kThemeAdornmentDefault
;
808 if( nState
& ControlState::FOCUSED
)
809 aListInfo
.adornment
|= kThemeAdornmentFocus
;
811 HIThemeDrawButton(&rc
, &aListInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
,&rc
);
815 case ControlPart::ListboxWindow
:
817 HIThemeFrameDrawInfo aTextDrawInfo
;
818 aTextDrawInfo
.version
=0;
819 aTextDrawInfo
.kind
=kHIThemeFrameTextFieldSquare
;
820 aTextDrawInfo
.state
=getState( nState
);
821 aTextDrawInfo
.isFocused
=false;
823 rc
.size
.width
+=1; // else there's a white space because a macOS theme has no 3D border
825 HIThemeDrawFrame(&rc
, &aTextDrawInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
);
827 if(nState
& ControlState::FOCUSED
) HIThemeDrawFocusRect(&rc
, true, maContextHolder
.get(), kHIThemeOrientationNormal
);
836 case ControlType::Editbox
:
837 case ControlType::MultilineEditbox
:
839 HIThemeFrameDrawInfo aTextDrawInfo
;
840 aTextDrawInfo
.version
=0;
841 aTextDrawInfo
.kind
=kHIThemeFrameTextFieldSquare
;
842 aTextDrawInfo
.state
=getState( nState
);
843 aTextDrawInfo
.isFocused
=false;
845 rc
.size
.width
+= 1; // else there may be a white space because a macOS theme has no 3D border
846 // change rc so that the frame will encompass only the content region
847 // see counterpart in GetNativeControlRegion
851 //CGContextSetFillColorWithColor
852 CGContextFillRect (maContextHolder
.get(), CGRectMake(rc
.origin
.x
, rc
.origin
.y
, rc
.size
.width
, rc
.size
.height
));
853 //fill a white background, because drawFrame only draws the border
855 HIThemeDrawFrame(&rc
, &aTextDrawInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
);
857 if(nState
& ControlState::FOCUSED
) HIThemeDrawFocusRect(&rc
, true, maContextHolder
.get(), kHIThemeOrientationNormal
);
863 case ControlType::Spinbox
:
865 if(nPart
== ControlPart::Entire
)
868 HIThemeFrameDrawInfo aTextDrawInfo
;
869 aTextDrawInfo
.version
=0;
870 aTextDrawInfo
.kind
=kHIThemeFrameTextFieldSquare
;
871 aTextDrawInfo
.state
=getState( nState
);
872 aTextDrawInfo
.isFocused
=false;
874 //rc.size.width contains the full size of the spinbox ie textfield + button
875 //so we remove the button width and the space between the button and the textfield
876 rc
.size
.width
-= SPIN_BUTTON_SPACE
+ SPIN_BUTTON_WIDTH
+ 2*FOCUS_RING_WIDTH
;
877 rc
.origin
.x
+= FOCUS_RING_WIDTH
;
878 rc
.origin
.y
+= FOCUS_RING_WIDTH
;
880 //CGContextSetFillColorWithColor
881 CGContextFillRect (maContextHolder
.get(), CGRectMake(rc
.origin
.x
, rc
.origin
.y
, rc
.size
.width
, rc
.size
.height
));
882 //fill a white background, because drawFrame only draws the border
884 HIThemeDrawFrame(&rc
, &aTextDrawInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
);
886 if(nState
& ControlState::FOCUSED
) HIThemeDrawFocusRect(&rc
, true, maContextHolder
.get(), kHIThemeOrientationNormal
);
889 const SpinbuttonValue
* pSpinButtonVal
= (aValue
.getType() == ControlType::SpinButtons
) ? static_cast<const SpinbuttonValue
*>(&aValue
) : nullptr;
890 ControlState nUpperState
= ControlState::ENABLED
;//state of the upper button
891 ControlState nLowerState
= ControlState::ENABLED
;//and of the lower button
892 if(pSpinButtonVal
) {//pSpinButtonVal is sometimes null
893 nUpperState
= pSpinButtonVal
->mnUpperState
;
894 nLowerState
= pSpinButtonVal
->mnLowerState
;
896 HIThemeButtonDrawInfo aSpinInfo
;
897 aSpinInfo
.kind
= kThemeIncDecButton
;
898 aSpinInfo
.state
= kThemeStateActive
;
899 if(nUpperState
& ControlState::PRESSED
)
900 aSpinInfo
.state
= kThemeStatePressedUp
;
901 else if(nLowerState
& ControlState::PRESSED
)
902 aSpinInfo
.state
= kThemeStatePressedDown
;
903 else if((nUpperState
& ~ControlState::ENABLED
)||(nLowerState
& ~ControlState::ENABLED
))
904 aSpinInfo
.state
= kThemeStateInactive
;
905 else if((nUpperState
& ControlState::ROLLOVER
)||(nLowerState
& ControlState::ROLLOVER
))
906 aSpinInfo
.state
= kThemeStateRollover
;
908 tools::Rectangle
aSpinRect( pSpinButtonVal
->maUpperRect
);
909 aSpinRect
.Union( pSpinButtonVal
->maLowerRect
);
910 HIRect buttonRc
= ImplGetHIRectFromRectangle(aSpinRect
);
912 // FIXME: without this fuzz factor there is some unwanted clipping
913 if( AllSettings::GetLayoutRTL() )
914 buttonRc
.origin
.x
-= FOCUS_RING_WIDTH
- CLIP_FUZZ
;
916 buttonRc
.origin
.x
+= FOCUS_RING_WIDTH
+ CLIP_FUZZ
;
918 switch( aValue
.getTristateVal() )
920 case ButtonValue::On
: aSpinInfo
.value
= kThemeButtonOn
;
922 case ButtonValue::Off
: aSpinInfo
.value
= kThemeButtonOff
;
924 case ButtonValue::Mixed
:
925 case ButtonValue::DontKnow
:
926 default: aSpinInfo
.value
= kThemeButtonMixed
;
930 aSpinInfo
.adornment
= ( (nUpperState
& ControlState::DEFAULT
) ||
931 (nLowerState
& ControlState::DEFAULT
) ) ?
932 kThemeAdornmentDefault
:
934 if( (nUpperState
& ControlState::FOCUSED
) || (nLowerState
& ControlState::FOCUSED
))
935 aSpinInfo
.adornment
|= kThemeAdornmentFocus
;
937 HIThemeDrawButton( &buttonRc
, &aSpinInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
, nullptr );
946 case ControlType::Frame
:
948 DrawFrameFlags nStyle
= static_cast<DrawFrameFlags
>(aValue
.getNumericVal());
949 if( nPart
== ControlPart::Border
) {
950 if(!( nStyle
& DrawFrameFlags::Menu
) && !(nStyle
& DrawFrameFlags::WindowBorder
) )
952 // #i84756# strange effects start to happen when HIThemeDrawFrame
953 // meets the border of the window. These can be avoided by clipping
954 // to the boundary of the frame
955 if( rc
.origin
.y
+ rc
.size
.height
>= mpFrame
->maGeometry
.nHeight
-3 )
957 CGMutablePathRef rPath
= CGPathCreateMutable();
958 CGPathAddRect( rPath
, nullptr, CGRectMake( 0, 0, mpFrame
->maGeometry
.nWidth
-1, mpFrame
->maGeometry
.nHeight
-1 ) );
960 CGContextBeginPath( maContextHolder
.get() );
961 CGContextAddPath( maContextHolder
.get(), rPath
);
962 CGContextClip( maContextHolder
.get() );
963 CGPathRelease( rPath
);
966 HIThemeFrameDrawInfo aTextDrawInfo
;
967 aTextDrawInfo
.version
=0;
968 aTextDrawInfo
.kind
=kHIThemeFrameListBox
;
969 aTextDrawInfo
.state
=kThemeStateActive
;
970 aTextDrawInfo
.isFocused
=false;
972 HIThemeDrawFrame(&rc
, &aTextDrawInfo
, maContextHolder
.get(), kHIThemeOrientationNormal
);
980 case ControlType::ListNet
:
982 //do nothing as there isn't net for listviews on macos
989 maContextHolder
.restoreState();
991 /* #i90291# in most cases invalidating the whole control region instead
992 of just the unclipped part of it is sufficient (and probably faster).
993 However for the window background we should not unnecessarily enlarge
994 the really changed rectangle since the difference is usually quite high
995 (the background is always drawn as a whole since we don't know anything
996 about its possible contents)
998 if( nType
== ControlType::WindowBackground
)
1000 CGRect aRect
= { { 0, 0 }, { 0, 0 } };
1002 aRect
= CGPathGetBoundingBox( mxClipPath
);
1003 if( aRect
.size
.width
!= 0 && aRect
.size
.height
!= 0 )
1004 buttonRect
.Intersection( tools::Rectangle( Point( static_cast<long int>(aRect
.origin
.x
),
1005 static_cast<long int>(aRect
.origin
.y
) ),
1006 Size( static_cast<long int>(aRect
.size
.width
),
1007 static_cast<long int>(aRect
.size
.height
) ) ) );
1010 RefreshRect( buttonRect
.Left(), buttonRect
.Top(), buttonRect
.GetWidth(), buttonRect
.GetHeight() );
1015 bool AquaSalGraphics::getNativeControlRegion( ControlType nType
, ControlPart nPart
, const tools::Rectangle
& rControlRegion
, ControlState
/*nState*/,
1016 const ImplControlValue
& aValue
, const OUString
&,
1017 tools::Rectangle
&rNativeBoundingRegion
, tools::Rectangle
&rNativeContentRegion
)
1020 bool toReturn
= false;
1022 tools::Rectangle
aCtrlBoundRect( rControlRegion
);
1023 short x
= aCtrlBoundRect
.Left();
1024 short y
= aCtrlBoundRect
.Top();
1027 sal_uInt8 nBorderCleanup
= 0;
1031 case ControlType::Slider
:
1033 if( nPart
== ControlPart::ThumbHorz
)
1035 w
= 19; // taken from HIG
1036 h
= aCtrlBoundRect
.GetHeight();
1037 rNativeBoundingRegion
= rNativeContentRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1040 else if( nPart
== ControlPart::ThumbVert
)
1042 w
= aCtrlBoundRect
.GetWidth();
1043 h
= 18; // taken from HIG
1044 rNativeBoundingRegion
= rNativeContentRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1050 case ControlType::Scrollbar
:
1052 tools::Rectangle aRect
;
1053 if( AquaGetScrollRect( /* m_nScreen */ nPart
, aCtrlBoundRect
, aRect
) )
1056 rNativeBoundingRegion
= aRect
;
1057 rNativeContentRegion
= aRect
;
1062 case ControlType::Pushbutton
:
1063 case ControlType::Radiobutton
:
1064 case ControlType::Checkbox
:
1066 if ( nType
== ControlType::Pushbutton
)
1068 w
= aCtrlBoundRect
.GetWidth();
1069 h
= aCtrlBoundRect
.GetHeight();
1073 // checkbox and radio borders need cleanup after unchecking them
1076 // TEXT_SEPARATOR to respect Aqua HIG
1077 w
= BUTTON_WIDTH
+ TEXT_SEPARATOR
;
1082 rNativeContentRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
+ nBorderCleanup
) );
1083 rNativeBoundingRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1088 case ControlType::Progress
:
1090 tools::Rectangle
aRect( aCtrlBoundRect
);
1091 if( aRect
.GetHeight() < 16 )
1092 aRect
.SetBottom( aRect
.Top() + 9 ); // values taken from HIG for medium progress
1094 aRect
.SetBottom( aRect
.Top() + 15 ); // values taken from HIG for large progress
1095 rNativeBoundingRegion
= aRect
;
1096 rNativeContentRegion
= aRect
;
1101 case ControlType::IntroProgress
:
1103 tools::Rectangle
aRect( aCtrlBoundRect
);
1104 aRect
.SetBottom( aRect
.Top() + INTRO_PROGRESS_HEIGHT
); // values taken from HIG for medium progress
1105 rNativeBoundingRegion
= aRect
;
1106 rNativeContentRegion
= aRect
;
1111 case ControlType::TabItem
:
1113 w
= aCtrlBoundRect
.GetWidth() + 2*TAB_TEXT_OFFSET
- 2*VCL_TAB_TEXT_OFFSET
;
1114 h
= TAB_HEIGHT_NORMAL
+2;
1116 rNativeContentRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1117 rNativeBoundingRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1123 case ControlType::Editbox
:
1125 w
= aCtrlBoundRect
.GetWidth();
1126 if( w
< 3+2*FOCUS_RING_WIDTH
)
1127 w
= 3+2*FOCUS_RING_WIDTH
;
1128 h
= TEXT_EDIT_HEIGHT_NORMAL
+2*FOCUS_RING_WIDTH
;
1129 if( h
< aCtrlBoundRect
.GetHeight() )
1130 h
= aCtrlBoundRect
.GetHeight();
1132 rNativeContentRegion
= tools::Rectangle( Point( x
+FOCUS_RING_WIDTH
, y
+FOCUS_RING_WIDTH
), Size( w
-2*(FOCUS_RING_WIDTH
+1), h
-2*(FOCUS_RING_WIDTH
+1) ) );
1133 rNativeBoundingRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1138 case ControlType::Listbox
:
1139 case ControlType::Combobox
:
1141 if( nPart
== ControlPart::Entire
)
1143 w
= aCtrlBoundRect
.GetWidth();
1144 h
= COMBOBOX_HEIGHT_NORMAL
;//listboxes and comboxes have the same height
1146 rNativeContentRegion
= tools::Rectangle( Point( x
+FOCUS_RING_WIDTH
, y
+FOCUS_RING_WIDTH
), Size( w
-2*FOCUS_RING_WIDTH
, h
) );
1147 rNativeBoundingRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
+2*FOCUS_RING_WIDTH
) );
1151 else if( nPart
== ControlPart::ButtonDown
)
1153 w
= aCtrlBoundRect
.GetWidth();
1154 if( w
< 3+2*FOCUS_RING_WIDTH
)
1155 w
= 3+2*FOCUS_RING_WIDTH
;
1156 h
= COMBOBOX_HEIGHT_NORMAL
;//listboxes and comboxes have the same height
1158 x
+= w
-DROPDOWN_BUTTON_WIDTH
- FOCUS_RING_WIDTH
;
1159 y
+= FOCUS_RING_WIDTH
;
1160 w
= DROPDOWN_BUTTON_WIDTH
;
1162 rNativeContentRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1163 rNativeBoundingRegion
= tools::Rectangle( Point( x
, y
), Size( w
+FOCUS_RING_WIDTH
, h
+2*FOCUS_RING_WIDTH
) );
1167 else if( nPart
== ControlPart::SubEdit
)
1169 w
= aCtrlBoundRect
.GetWidth();
1170 h
= COMBOBOX_HEIGHT_NORMAL
;//listboxes and comboxes have the same height
1172 x
+= FOCUS_RING_WIDTH
;
1173 x
+= 3; // add an offset for rounded borders
1174 y
+= 2; // don't draw into upper border
1175 y
+= FOCUS_RING_WIDTH
;
1176 w
-= 3 + DROPDOWN_BUTTON_WIDTH
+ 2*FOCUS_RING_WIDTH
;
1177 if( nType
== ControlType::Listbox
)
1178 w
-= 9; // HIG specifies 9 units distance between dropdown button area and content
1179 h
-= 4; // don't draw into lower border
1181 rNativeContentRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1182 rNativeBoundingRegion
= tools::Rectangle( Point( x
, y
), Size( w
+FOCUS_RING_WIDTH
, h
+2*FOCUS_RING_WIDTH
) );
1188 case ControlType::Spinbox
:
1189 if( nPart
== ControlPart::Entire
) {
1190 w
= aCtrlBoundRect
.GetWidth();
1191 if( w
< 3+2*FOCUS_RING_WIDTH
+SPIN_BUTTON_SPACE
+SPIN_BUTTON_WIDTH
)
1192 w
= 3+2*FOCUS_RING_WIDTH
+SPIN_BUTTON_SPACE
+SPIN_BUTTON_WIDTH
;
1193 h
= TEXT_EDIT_HEIGHT_NORMAL
;
1195 rNativeContentRegion
= tools::Rectangle( Point( x
+FOCUS_RING_WIDTH
, y
), Size( w
-2*FOCUS_RING_WIDTH
, h
) );
1196 rNativeBoundingRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
+2*FOCUS_RING_WIDTH
) );
1200 else if( nPart
== ControlPart::SubEdit
) {
1201 w
= aCtrlBoundRect
.GetWidth() - SPIN_BUTTON_SPACE
- SPIN_BUTTON_WIDTH
;
1202 h
= TEXT_EDIT_HEIGHT_NORMAL
;
1203 x
+= 4; // add an offset for rounded borders
1204 y
+= 2; // don't draw into upper border
1205 w
-= 8; // offset for left and right rounded border
1206 h
-= 4; // don't draw into upper or lower border
1208 rNativeContentRegion
= tools::Rectangle( Point( x
+ FOCUS_RING_WIDTH
, y
+ FOCUS_RING_WIDTH
), Size( w
- 2* FOCUS_RING_WIDTH
, h
) );
1209 rNativeBoundingRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
+2*FOCUS_RING_WIDTH
) );
1213 else if( nPart
== ControlPart::ButtonUp
) {
1214 //aCtrlBoundRect.GetWidth() contains the width of the full control
1215 //ie the width of the textfield + button
1216 //x is the position of the left corner of the full control
1217 x
+= aCtrlBoundRect
.GetWidth() - SPIN_BUTTON_WIDTH
- SPIN_BUTTON_SPACE
- CLIP_FUZZ
;
1218 y
+= FOCUS_RING_WIDTH
- CLIP_FUZZ
;
1219 w
= SPIN_BUTTON_WIDTH
+ 2*CLIP_FUZZ
;
1220 h
= SPIN_UPPER_BUTTON_HEIGHT
+ 2*CLIP_FUZZ
;
1222 rNativeContentRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1223 rNativeBoundingRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1227 else if( nPart
== ControlPart::ButtonDown
) {
1228 x
+= aCtrlBoundRect
.GetWidth() - SPIN_BUTTON_WIDTH
- SPIN_BUTTON_SPACE
- CLIP_FUZZ
;
1229 y
+= SPIN_UPPER_BUTTON_HEIGHT
+ FOCUS_RING_WIDTH
- CLIP_FUZZ
;
1230 w
= SPIN_BUTTON_WIDTH
+ 2*CLIP_FUZZ
;
1231 h
= SPIN_LOWER_BUTTON_HEIGHT
+ 2*CLIP_FUZZ
;
1233 rNativeContentRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1234 rNativeBoundingRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1239 case ControlType::Frame
:
1241 DrawFrameStyle nStyle
= static_cast<DrawFrameStyle
>(aValue
.getNumericVal() & 0x000f);
1242 DrawFrameFlags nFlags
= static_cast<DrawFrameFlags
>(aValue
.getNumericVal() & 0xfff0);
1243 if( ( nPart
== ControlPart::Border
) &&
1244 !( nFlags
& (DrawFrameFlags::Menu
| DrawFrameFlags::WindowBorder
| DrawFrameFlags::BorderWindowBorder
) ) )
1246 tools::Rectangle
aRect(aCtrlBoundRect
);
1247 if( nStyle
== DrawFrameStyle::DoubleIn
)
1249 aRect
.AdjustLeft(1);
1251 //rRect.Right() -= 1;
1252 //rRect.Bottom() -= 1;
1256 aRect
.AdjustLeft(1);
1258 aRect
.AdjustRight(-1);
1259 aRect
.AdjustBottom(-1);
1262 rNativeContentRegion
= aRect
;
1263 rNativeBoundingRegion
= aRect
;
1270 case ControlType::Menubar
:
1271 case ControlType::MenuPopup
:
1273 if(( nPart
== ControlPart::MenuItemCheckMark
)||( nPart
== ControlPart::MenuItemRadioMark
)) {
1276 h
=10;//dimensions of the mark (10px font)
1278 rNativeContentRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1279 rNativeBoundingRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1292 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */