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 class AquaBlinker
: public Timer
49 AquaSalFrame
* mpFrame
;
50 tools::Rectangle maInvalidateRect
;
52 AquaBlinker( AquaSalFrame
* pFrame
, const tools::Rectangle
& rRect
)
53 : mpFrame( pFrame
), maInvalidateRect( rRect
)
55 mpFrame
->maBlinkers
.push_back( this );
60 static void Blink( AquaSalFrame
*, const tools::Rectangle
&, int nTimeout
= 80 );
62 virtual void Invoke() override
65 if( AquaSalFrame::isAlive( mpFrame
) && mpFrame
->mbShown
)
67 mpFrame
->maBlinkers
.remove( this );
68 mpFrame
->SendPaintEvent( &maInvalidateRect
);
74 void AquaBlinker::Blink( AquaSalFrame
* pFrame
, const tools::Rectangle
& rRect
, int nTimeout
)
76 // prevent repeated paints from triggering themselves all the time
77 for( std::list
< AquaBlinker
* >::const_iterator it
= pFrame
->maBlinkers
.begin();
78 it
!= pFrame
->maBlinkers
.end(); ++it
)
80 if( (*it
)->maInvalidateRect
== rRect
)
83 AquaBlinker
* pNew
= new AquaBlinker( pFrame
, rRect
);
84 pNew
->SetTimeout( nTimeout
);
88 // Helper returns an HIRect
90 static HIRect
ImplGetHIRectFromRectangle(tools::Rectangle aRect
)
93 aHIRect
.origin
.x
= static_cast<float>(aRect
.Left());
94 aHIRect
.origin
.y
= static_cast<float>(aRect
.Top());
95 aHIRect
.size
.width
= static_cast<float>(aRect
.GetWidth());
96 aHIRect
.size
.height
= static_cast<float>(aRect
.GetHeight());
100 static ThemeButtonValue
ImplGetButtonValue( ButtonValue aButtonValue
)
102 switch( aButtonValue
)
104 case ButtonValue::On
:
105 return kThemeButtonOn
;
108 case ButtonValue::Off
:
109 return kThemeButtonOff
;
112 case ButtonValue::Mixed
:
113 case ButtonValue::DontKnow
:
115 return kThemeButtonMixed
;
120 static bool AquaGetScrollRect( /* TODO: int nScreen, */ ControlPart nPart
,
121 const tools::Rectangle
& rControlRect
, tools::Rectangle
& rResultRect
)
124 rResultRect
= rControlRect
;
128 case ControlPart::ButtonUp
:
129 rResultRect
.Bottom() = rResultRect
.Top();
132 case ControlPart::ButtonDown
:
133 rResultRect
.Top() = rResultRect
.Bottom();
136 case ControlPart::ButtonLeft
:
137 rResultRect
.Right() = rResultRect
.Left();
140 case ControlPart::ButtonRight
:
141 rResultRect
.Left() = rResultRect
.Right();
144 case ControlPart::TrackHorzArea
:
145 case ControlPart::TrackVertArea
:
146 case ControlPart::ThumbHorz
:
147 case ControlPart::ThumbVert
:
148 case ControlPart::TrackHorzLeft
:
149 case ControlPart::TrackHorzRight
:
150 case ControlPart::TrackVertUpper
:
151 case ControlPart::TrackVertLower
:
160 bool AquaSalGraphics::IsNativeControlSupported( ControlType nType
, ControlPart nPart
)
164 // Native controls are now defaults
165 // If you want to disable experimental native controls code,
166 // just set the environment variable SAL_NO_NWF to something
167 // and vcl controls will be used as default again.
171 case ControlType::Pushbutton
:
172 case ControlType::Radiobutton
:
173 case ControlType::Checkbox
:
174 case ControlType::ListNode
:
175 if( nPart
== ControlPart::Entire
)
179 case ControlType::Scrollbar
:
180 if( nPart
== ControlPart::DrawBackgroundHorz
||
181 nPart
== ControlPart::DrawBackgroundVert
||
182 nPart
== ControlPart::Entire
||
183 nPart
== ControlPart::HasThreeButtons
)
187 case ControlType::Slider
:
188 if( nPart
== ControlPart::TrackHorzArea
|| nPart
== ControlPart::TrackVertArea
)
192 case ControlType::Editbox
:
193 if( nPart
== ControlPart::Entire
||
194 nPart
== ControlPart::HasBackgroundTexture
)
198 case ControlType::MultilineEditbox
:
199 if( nPart
== ControlPart::Entire
||
200 nPart
== ControlPart::HasBackgroundTexture
)
204 case ControlType::Spinbox
:
205 if( nPart
== ControlPart::Entire
||
206 nPart
== ControlPart::AllButtons
||
207 nPart
== ControlPart::HasBackgroundTexture
)
211 case ControlType::SpinButtons
:
215 case ControlType::Combobox
:
216 if( nPart
== ControlPart::Entire
||
217 nPart
== ControlPart::HasBackgroundTexture
)
221 case ControlType::Listbox
:
222 if( nPart
== ControlPart::Entire
||
223 nPart
== ControlPart::ListboxWindow
||
224 nPart
== ControlPart::HasBackgroundTexture
||
225 nPart
== ControlPart::SubEdit
230 case ControlType::TabItem
:
231 case ControlType::TabPane
:
232 case ControlType::TabBody
: // see vcl/source/window/tabpage.cxx
233 if( nPart
== ControlPart::Entire
||
234 nPart
== ControlPart::TabsDrawRtl
||
235 nPart
== ControlPart::HasBackgroundTexture
)
239 // when ControlPart::Button is used, toolbar icons are not highlighted when mouse rolls over.
240 // More Aqua compliant
241 case ControlType::Toolbar
:
242 if( nPart
== ControlPart::Entire
||
243 nPart
== ControlPart::DrawBackgroundHorz
||
244 nPart
== ControlPart::DrawBackgroundVert
)
248 case ControlType::WindowBackground
:
249 if ( nPart
== ControlPart::BackgroundWindow
||
250 nPart
== ControlPart::BackgroundDialog
)
254 case ControlType::Menubar
:
255 if( nPart
== ControlPart::Entire
)
259 case ControlType::Tooltip
: // ** TO DO
262 case ControlType::MenuPopup
:
263 if( nPart
== ControlPart::Entire
||
264 nPart
== ControlPart::MenuItem
||
265 nPart
== ControlPart::MenuItemCheckMark
||
266 nPart
== ControlPart::MenuItemRadioMark
)
269 case ControlType::Progress
:
270 case ControlType::IntroProgress
:
271 if( nPart
== ControlPart::Entire
)
274 case ControlType::Frame
:
275 if( nPart
== ControlPart::Border
)
278 case ControlType::ListNet
:
279 if( nPart
== ControlPart::Entire
)
288 bool AquaSalGraphics::hitTestNativeControl( ControlType nType
, ControlPart nPart
, const tools::Rectangle
& rControlRegion
,
289 const Point
& rPos
, bool& rIsInside
)
291 if ( nType
== ControlType::Scrollbar
)
293 tools::Rectangle aRect
;
294 bool bValid
= AquaGetScrollRect( /* TODO: m_nScreen */ nPart
, rControlRegion
, aRect
);
295 rIsInside
= bValid
&& aRect
.IsInside( rPos
);
297 } // ControlType::Scrollbar
303 kThemeStateInactive = 0,
304 kThemeStateActive = 1,
305 kThemeStatePressed = 2,
306 kThemeStateRollover = 6,
307 kThemeStateUnavailable = 7,
308 kThemeStateUnavailableInactive = 8
309 kThemeStatePressedUp = 2,
310 kThemeStatePressedDown = 3
312 UInt32
AquaSalGraphics::getState( ControlState nState
)
314 const bool bDrawActive
= mpFrame
== nullptr || [mpFrame
->getNSWindow() isKeyWindow
];
315 if( !(nState
& ControlState::ENABLED
) || ! bDrawActive
)
317 return kThemeStateInactive
;
320 if( nState
& ControlState::PRESSED
)
321 return kThemeStatePressed
;
323 return kThemeStateActive
;
326 UInt32
AquaSalGraphics::getTrackState( ControlState nState
)
328 const bool bDrawActive
= mpFrame
== nullptr || [mpFrame
->getNSWindow() isKeyWindow
];
329 if( ! (nState
& ControlState::ENABLED
) || ! bDrawActive
)
330 return kThemeTrackInactive
;
332 return kThemeTrackActive
;
335 bool AquaSalGraphics::drawNativeControl(ControlType nType
,
337 const tools::Rectangle
& rControlRegion
,
339 const ImplControlValue
& aValue
,
344 if( ! CheckContext() )
347 CGContextSaveGState( mrContext
);
349 tools::Rectangle buttonRect
= rControlRegion
;
350 HIRect rc
= ImplGetHIRectFromRectangle(buttonRect
);
355 case ControlType::Combobox
:
356 if ( nPart
== ControlPart::HasBackgroundTexture
||
357 nPart
== ControlPart::Entire
)
359 HIThemeButtonDrawInfo aComboInfo
;
360 aComboInfo
.version
= 0;
361 aComboInfo
.kind
= kThemeComboBox
;
362 aComboInfo
.state
= getState( nState
);
363 aComboInfo
.value
= kThemeButtonOn
;
364 aComboInfo
.adornment
= kThemeAdornmentNone
;
366 if( nState
& ControlState::FOCUSED
)
367 aComboInfo
.adornment
|= kThemeAdornmentFocus
;
369 HIThemeDrawButton(&rc
, &aComboInfo
, mrContext
, kHIThemeOrientationNormal
,&rc
);
374 case ControlType::Toolbar
:
376 #if HAVE_FEATURE_MACOSX_SANDBOX
377 HIThemeMenuItemDrawInfo aMenuItemDrawInfo
;
378 aMenuItemDrawInfo
.version
= 0;
379 aMenuItemDrawInfo
.state
= kThemeMenuActive
;
380 aMenuItemDrawInfo
.itemType
= kThemeMenuItemHierBackground
;
381 HIThemeDrawMenuItem(&rc
,&rc
,&aMenuItemDrawInfo
,mrContext
,kHIThemeOrientationNormal
,NULL
);
383 if (rControlRegion
.Top() == 0 && nPart
== ControlPart::DrawBackgroundHorz
)
385 const bool bDrawActive
= mpFrame
== nullptr || [mpFrame
->getNSWindow() isKeyWindow
];
386 CGFloat unifiedHeight
= rControlRegion
.GetHeight();
387 CGRect drawRect
= CGRectMake(rControlRegion
.Left(), rControlRegion
.Top(), rControlRegion
.GetWidth(), rControlRegion
.GetHeight());
388 CUIDraw([NSWindow coreUIRenderer
], drawRect
, mrContext
,
389 reinterpret_cast<CFDictionaryRef
>([NSDictionary dictionaryWithObjectsAndKeys
:
390 @
"kCUIWidgetWindowFrame", @
"widget",
391 @
"regularwin", @
"windowtype",
392 (bDrawActive
? @
"normal" : @
"inactive"), @
"state",
393 [NSNumber numberWithDouble
:unifiedHeight
], @
"kCUIWindowFrameUnifiedTitleBarHeightKey",
394 [NSNumber numberWithBool
:NO
], @
"kCUIWindowFrameDrawTitleSeparatorKey",
395 [NSNumber numberWithBool
:YES
], @
"is.flipped",
401 HIThemeMenuItemDrawInfo aMenuItemDrawInfo
;
402 aMenuItemDrawInfo
.version
= 0;
403 aMenuItemDrawInfo
.state
= kThemeMenuActive
;
404 aMenuItemDrawInfo
.itemType
= kThemeMenuItemHierBackground
;
405 HIThemeDrawMenuItem(&rc
, &rc
, &aMenuItemDrawInfo
, mrContext
, kHIThemeOrientationNormal
, nullptr);
412 case ControlType::WindowBackground
:
414 HIThemeBackgroundDrawInfo aThemeBackgroundInfo
;
415 aThemeBackgroundInfo
.version
= 0;
416 aThemeBackgroundInfo
.state
= getState( nState
);
417 aThemeBackgroundInfo
.kind
= kThemeBrushDialogBackgroundActive
;
418 // FIXME: without this magical offset there is a 2 pixel black border on the right and bottom
422 HIThemeApplyBackground( &rc
, &aThemeBackgroundInfo
, mrContext
, kHIThemeOrientationNormal
);
423 CGContextFillRect( mrContext
, rc
);
428 case ControlType::Menubar
:
429 case ControlType::MenuPopup
:
431 if ((nPart
== ControlPart::Entire
) || (nPart
== ControlPart::MenuItem
)|| (nPart
== ControlPart::HasBackgroundTexture
))
433 // FIXME: without this magical offset there is a 2 pixel black border on the right
436 HIThemeMenuDrawInfo aMenuInfo
;
437 aMenuInfo
.version
= 0;
438 aMenuInfo
.menuType
= kThemeMenuTypePullDown
;
440 HIThemeMenuItemDrawInfo aMenuItemDrawInfo
;
441 // the Aqua grey theme when the item is selected is drawn here.
442 aMenuItemDrawInfo
.itemType
= kThemeMenuItemPlain
;
444 if ((nPart
== ControlPart::MenuItem
) && (nState
& ControlState::SELECTED
))
446 // the blue theme when the item is selected is drawn here.
447 aMenuItemDrawInfo
.state
= kThemeMenuSelected
;
451 // normal color for non selected item
452 aMenuItemDrawInfo
.state
= kThemeMenuActive
;
455 // repaints the background of the pull down menu
456 HIThemeDrawMenuBackground(&rc
,&aMenuInfo
,mrContext
,kHIThemeOrientationNormal
);
458 // repaints the item either blue (selected) and/or Aqua grey (active only)
459 HIThemeDrawMenuItem(&rc
,&rc
,&aMenuItemDrawInfo
,mrContext
,kHIThemeOrientationNormal
,&rc
);
463 else if(( nPart
== ControlPart::MenuItemCheckMark
)||( nPart
== ControlPart::MenuItemRadioMark
)) {
464 if( nState
& ControlState::PRESSED
) {//checked, else it is not displayed (see vcl/source/window/menu.cxx)
465 HIThemeTextInfo aTextInfo
;
466 aTextInfo
.version
= 0;
467 aTextInfo
.state
= (nState
& ControlState::ENABLED
) ? kThemeStateInactive
: kThemeStateActive
;
468 aTextInfo
.fontID
= kThemeMenuItemMarkFont
;
469 aTextInfo
.horizontalFlushness
=kHIThemeTextHorizontalFlushCenter
;
470 aTextInfo
.verticalFlushness
=kHIThemeTextVerticalFlushTop
;
471 aTextInfo
.options
=kHIThemeTextBoxOptionNone
;
472 aTextInfo
.truncationPosition
=kHIThemeTextTruncationNone
;
473 //aTextInfo.truncationMaxLines unused because of kHIThemeTextTruncationNone
475 if( nState
& ControlState::SELECTED
) aTextInfo
.state
= kThemeStatePressed
; //item highlighted
477 UniChar mark
=( nPart
== ControlPart::MenuItemCheckMark
) ? kCheckUnicode
: kBulletUnicode
;//0x2713;
478 CFStringRef cfString
= CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault
, &mark
, 1, kCFAllocatorNull
);
479 HIThemeDrawTextBox(cfString
, &rc
, &aTextInfo
, mrContext
, kHIThemeOrientationNormal
);
489 case ControlType::Pushbutton
:
491 // [ FIXME] : instead of use a value, vcl can retrieve correct values on the fly (to be implemented)
492 const int PB_Mini_Height
= 15;
493 const int PB_Norm_Height
= 21;
495 HIThemeButtonDrawInfo aPushInfo
;
496 aPushInfo
.version
= 0;
499 aPushInfo
.animation
.time
.start
= 0;
500 aPushInfo
.animation
.time
.current
= 0;
501 PushButtonValue
const * pPBVal
= aValue
.getType() == ControlType::Pushbutton
? static_cast<PushButtonValue
const *>(&aValue
) : nullptr;
502 int nPaintHeight
= static_cast<int>(rc
.size
.height
);
504 if( pPBVal
&& pPBVal
->mbBevelButton
)
506 aPushInfo
.kind
= kThemeRoundedBevelButton
;
508 else if( rc
.size
.height
<= PB_Norm_Height
)
510 aPushInfo
.kind
= kThemePushButtonMini
;
511 nPaintHeight
= PB_Mini_Height
;
513 else if( (pPBVal
&& pPBVal
->mbSingleLine
) || rc
.size
.height
< (PB_Norm_Height
+ PB_Norm_Height
/2) )
515 aPushInfo
.kind
= kThemePushButtonNormal
;
516 nPaintHeight
= PB_Norm_Height
;
518 // avoid clipping when focused
519 rc
.origin
.x
+= FOCUS_RING_WIDTH
/2;
520 rc
.size
.width
-= FOCUS_RING_WIDTH
;
522 if( nState
& ControlState::DEFAULT
)
524 AquaBlinker::Blink( mpFrame
, buttonRect
);
525 // show correct animation phase
526 aPushInfo
.animation
.time
.current
= CFAbsoluteTimeGetCurrent();
530 aPushInfo
.kind
= kThemeBevelButton
;
532 // translate the origin for controls with fixed paint height
533 // so content ends up somewhere sensible
534 int delta_y
= static_cast<int>(rc
.size
.height
) - nPaintHeight
;
535 rc
.origin
.y
+= delta_y
/2;
537 aPushInfo
.state
= getState( nState
);
538 aPushInfo
.value
= ImplGetButtonValue( aValue
.getTristateVal() );
540 aPushInfo
.adornment
= ( nState
& ControlState::DEFAULT
) ?
541 kThemeAdornmentDefault
:
543 if( nState
& ControlState::FOCUSED
)
544 aPushInfo
.adornment
|= kThemeAdornmentFocus
;
546 HIThemeDrawButton( &rc
, &aPushInfo
, mrContext
, kHIThemeOrientationNormal
, nullptr );
551 case ControlType::Radiobutton
:
552 case ControlType::Checkbox
:
554 HIThemeButtonDrawInfo aInfo
;
558 case ControlType::Radiobutton
: if(rc
.size
.width
>= BUTTON_HEIGHT
) aInfo
.kind
= kThemeRadioButton
;
559 else aInfo
.kind
= kThemeSmallRadioButton
;
561 case ControlType::Checkbox
: if(rc
.size
.width
>= BUTTON_HEIGHT
) aInfo
.kind
= kThemeCheckBox
;
562 else aInfo
.kind
= kThemeSmallCheckBox
;
567 aInfo
.state
= getState( nState
);
569 ButtonValue aButtonValue
= aValue
.getTristateVal();
570 aInfo
.value
= ImplGetButtonValue( aButtonValue
);
572 aInfo
.adornment
= ( nState
& ControlState::DEFAULT
) ?
573 kThemeAdornmentDefault
:
575 if( nState
& ControlState::FOCUSED
)
576 aInfo
.adornment
|= kThemeAdornmentFocus
;
577 HIThemeDrawButton( &rc
, &aInfo
, mrContext
, kHIThemeOrientationNormal
, nullptr );
582 case ControlType::ListNode
:
584 ButtonValue aButtonValue
= aValue
.getTristateVal();
586 if( AllSettings::GetLayoutRTL() && aButtonValue
== ButtonValue::Off
)
588 // FIXME: a value of kThemeDisclosureLeft
589 // should draw a theme compliant left disclosure triangle
590 // sadly this does not seem to work, so we'll draw a left
591 // grey equilateral triangle here ourselves.
592 // Perhaps some other HIThemeButtonDrawInfo setting would do the trick ?
594 CGContextSetShouldAntialias( mrContext
, true );
595 CGFloat aGrey
[] = { 0.45, 0.45, 0.45, 1.0 };
596 CGContextSetFillColor( mrContext
, aGrey
);
597 CGContextBeginPath( mrContext
);
598 float x
= rc
.origin
.x
+ rc
.size
.width
;
599 float y
= rc
.origin
.y
;
600 CGContextMoveToPoint( mrContext
, x
, y
);
602 CGContextAddLineToPoint( mrContext
, x
, y
);
603 x
-= rc
.size
.height
* 0.866; // cos( 30 degree ) is approx. 0.866
604 y
-= rc
.size
.height
/2;
605 CGContextAddLineToPoint( mrContext
, x
, y
);
606 CGContextDrawPath( mrContext
, kCGPathEOFill
);
610 HIThemeButtonDrawInfo aInfo
;
612 aInfo
.kind
= kThemeDisclosureTriangle
;
613 aInfo
.value
= kThemeDisclosureRight
;
614 aInfo
.state
= getState( nState
);
616 aInfo
.adornment
= kThemeAdornmentNone
;
618 switch( aButtonValue
) {
619 case ButtonValue::On
: aInfo
.value
= kThemeDisclosureDown
;//expanded
621 case ButtonValue::Off
:
622 // FIXME: this should have drawn a theme compliant disclosure triangle
624 if( AllSettings::GetLayoutRTL() )
626 aInfo
.value
= kThemeDisclosureLeft
;//collapsed, RTL
629 case ButtonValue::DontKnow
: //what to do?
634 HIThemeDrawButton( &rc
, &aInfo
, mrContext
, kHIThemeOrientationNormal
, nullptr );
640 case ControlType::Progress
:
641 case ControlType::IntroProgress
:
643 long nProgressWidth
= aValue
.getNumericVal();
644 HIThemeTrackDrawInfo aTrackInfo
;
645 aTrackInfo
.version
= 0;
646 aTrackInfo
.kind
= (rc
.size
.height
> 10) ? kThemeProgressBarLarge
: kThemeProgressBarMedium
;
647 aTrackInfo
.bounds
= rc
;
649 aTrackInfo
.max
= static_cast<SInt32
>(rc
.size
.width
);
650 aTrackInfo
.value
= nProgressWidth
;
651 aTrackInfo
.reserved
= 0;
652 aTrackInfo
.bounds
.origin
.y
-= 2; // FIXME: magic for shadow
653 aTrackInfo
.bounds
.size
.width
-= 2; // FIXME: magic for shadow
654 aTrackInfo
.attributes
= kThemeTrackHorizontal
;
655 if( AllSettings::GetLayoutRTL() )
656 aTrackInfo
.attributes
|= kThemeTrackRightToLeft
;
657 aTrackInfo
.enableState
= getTrackState( nState
);
658 // the intro bitmap never gets key anyway; we want to draw that enabled
659 if( nType
== ControlType::IntroProgress
)
660 aTrackInfo
.enableState
= kThemeTrackActive
;
661 aTrackInfo
.filler1
= 0;
662 aTrackInfo
.trackInfo
.progress
.phase
= static_cast<long long>(CFAbsoluteTimeGetCurrent()*10.0);
664 HIThemeDrawTrack( &aTrackInfo
, nullptr, mrContext
, kHIThemeOrientationNormal
);
669 case ControlType::Slider
:
671 SliderValue
const * pSLVal
= static_cast<SliderValue
const *>(&aValue
);
673 HIThemeTrackDrawInfo aTrackDraw
;
674 aTrackDraw
.kind
= kThemeSliderMedium
;
675 if( nPart
== ControlPart::TrackHorzArea
|| nPart
== ControlPart::TrackVertArea
)
677 aTrackDraw
.bounds
= rc
;
678 aTrackDraw
.min
= pSLVal
->mnMin
;
679 aTrackDraw
.max
= pSLVal
->mnMax
;
680 aTrackDraw
.value
= pSLVal
->mnCur
;
681 aTrackDraw
.reserved
= 0;
682 aTrackDraw
.attributes
= kThemeTrackShowThumb
;
683 if( nPart
== ControlPart::TrackHorzArea
)
684 aTrackDraw
.attributes
|= kThemeTrackHorizontal
;
685 aTrackDraw
.enableState
= (nState
& ControlState::ENABLED
)
686 ? kThemeTrackActive
: kThemeTrackInactive
;
688 SliderTrackInfo aSlideInfo
;
689 aSlideInfo
.thumbDir
= kThemeThumbUpward
;
690 aSlideInfo
.pressState
= 0;
691 aTrackDraw
.trackInfo
.slider
= aSlideInfo
;
693 HIThemeDrawTrack( &aTrackDraw
, nullptr, mrContext
, kHIThemeOrientationNormal
);
699 case ControlType::Scrollbar
:
701 const ScrollbarValue
* pScrollbarVal
= (aValue
.getType() == ControlType::Scrollbar
) ? static_cast<const ScrollbarValue
*>(&aValue
) : nullptr;
703 if( nPart
== ControlPart::DrawBackgroundVert
||
704 nPart
== ControlPart::DrawBackgroundHorz
)
706 HIThemeTrackDrawInfo aTrackDraw
;
707 aTrackDraw
.kind
= kThemeMediumScrollBar
;
708 // FIXME: the scrollbar length must be adjusted
709 if (nPart
== ControlPart::DrawBackgroundVert
)
714 aTrackDraw
.bounds
= rc
;
715 aTrackDraw
.min
= pScrollbarVal
->mnMin
;
716 aTrackDraw
.max
= pScrollbarVal
->mnMax
- pScrollbarVal
->mnVisibleSize
;
717 aTrackDraw
.value
= pScrollbarVal
->mnCur
;
718 aTrackDraw
.reserved
= 0;
719 aTrackDraw
.attributes
= kThemeTrackShowThumb
;
720 if( nPart
== ControlPart::DrawBackgroundHorz
)
721 aTrackDraw
.attributes
|= kThemeTrackHorizontal
;
722 aTrackDraw
.enableState
= getTrackState( nState
);
724 ScrollBarTrackInfo aScrollInfo
;
725 aScrollInfo
.viewsize
= pScrollbarVal
->mnVisibleSize
;
726 aScrollInfo
.pressState
= 0;
728 if ( pScrollbarVal
->mnButton1State
& ControlState::ENABLED
)
730 if ( pScrollbarVal
->mnButton1State
& ControlState::PRESSED
)
731 aScrollInfo
.pressState
= kThemeTopOutsideArrowPressed
;
734 if ( pScrollbarVal
->mnButton2State
& ControlState::ENABLED
)
736 if ( pScrollbarVal
->mnButton2State
& ControlState::PRESSED
)
737 aScrollInfo
.pressState
= kThemeBottomOutsideArrowPressed
;
740 if ( pScrollbarVal
->mnThumbState
& ControlState::ENABLED
)
742 if ( pScrollbarVal
->mnThumbState
& ControlState::PRESSED
)
743 aScrollInfo
.pressState
= kThemeThumbPressed
;
746 aTrackDraw
.trackInfo
.scrollbar
= aScrollInfo
;
748 HIThemeDrawTrack( &aTrackDraw
, nullptr, mrContext
, kHIThemeOrientationNormal
);
754 case ControlType::TabPane
:
756 HIThemeTabPaneDrawInfo aTabPaneDrawInfo
;
757 aTabPaneDrawInfo
.version
= 1;
758 aTabPaneDrawInfo
.state
= kThemeStateActive
;
759 aTabPaneDrawInfo
.direction
=kThemeTabNorth
;
760 aTabPaneDrawInfo
.size
=kHIThemeTabSizeNormal
;
761 aTabPaneDrawInfo
.kind
=kHIThemeTabKindNormal
;
763 //the border is outside the rect rc for Carbon
764 //but for VCL it should be inside
766 rc
.origin
.y
-=TAB_HEIGHT_NORMAL
/2;
767 rc
.size
.height
+=TAB_HEIGHT_NORMAL
/2;
770 HIThemeDrawTabPane(&rc
, &aTabPaneDrawInfo
, mrContext
, kHIThemeOrientationNormal
);
776 case ControlType::TabItem
:
778 HIThemeTabDrawInfo aTabItemDrawInfo
;
779 aTabItemDrawInfo
.version
=1;
780 aTabItemDrawInfo
.style
=kThemeTabNonFront
;
781 aTabItemDrawInfo
.direction
=kThemeTabNorth
;
782 aTabItemDrawInfo
.size
=kHIThemeTabSizeNormal
;
783 aTabItemDrawInfo
.adornment
=kHIThemeTabAdornmentTrailingSeparator
;
785 if(nState
& ControlState::SELECTED
) {
786 aTabItemDrawInfo
.style
=kThemeTabFront
;
788 if(nState
& ControlState::FOCUSED
) {
789 aTabItemDrawInfo
.adornment
|=kHIThemeTabAdornmentFocus
;
792 //first, last or middle tab
793 aTabItemDrawInfo
.position
=kHIThemeTabPositionMiddle
;
795 TabitemValue
const * pTabValue
= static_cast<TabitemValue
const *>(&aValue
);
796 TabitemFlags nAlignment
= pTabValue
->mnAlignment
;
797 //TabitemFlags::LeftAligned (and TabitemFlags::RightAligned) for the leftmost (or rightmost) tab
798 //when there are several lines of tabs because there is only one first tab and one
799 //last tab and TabitemFlags::FirstInGroup (and TabitemFlags::LastInGroup) because when the
800 //line width is different from window width, there may not be TabitemFlags::RightAligned
801 if( ( (nAlignment
& TabitemFlags::LeftAligned
)&&(nAlignment
& TabitemFlags::RightAligned
) ) ||
802 ( (nAlignment
& TabitemFlags::FirstInGroup
)&&(nAlignment
& TabitemFlags::LastInGroup
) )
804 aTabItemDrawInfo
.position
=kHIThemeTabPositionOnly
;
805 else if((nAlignment
& TabitemFlags::LeftAligned
)||(nAlignment
& TabitemFlags::FirstInGroup
))
806 aTabItemDrawInfo
.position
=kHIThemeTabPositionFirst
;
807 else if((nAlignment
& TabitemFlags::RightAligned
)||(nAlignment
& TabitemFlags::LastInGroup
))
808 aTabItemDrawInfo
.position
=kHIThemeTabPositionLast
;
812 if( AllSettings::GetLayoutRTL() ) {
813 if( aTabItemDrawInfo
.position
== kHIThemeTabPositionFirst
)
814 aTabItemDrawInfo
.position
= kHIThemeTabPositionLast
;
815 else if( aTabItemDrawInfo
.position
== kHIThemeTabPositionLast
)
816 aTabItemDrawInfo
.position
= kHIThemeTabPositionFirst
;
819 rc
.size
.width
+=2;//because VCL has 2 empty pixels between 2 tabs
822 HIThemeDrawTab(&rc
, &aTabItemDrawInfo
, mrContext
, kHIThemeOrientationNormal
, &rc
);
828 case ControlType::Listbox
:
831 case ControlPart::Entire
:
832 case ControlPart::ButtonDown
:
834 HIThemeButtonDrawInfo aListInfo
;
835 aListInfo
.version
= 0;
836 aListInfo
.kind
= kThemePopupButton
;
837 aListInfo
.state
= getState( nState
);//kThemeStateInactive -> greyed
838 aListInfo
.value
= kThemeButtonOn
;
840 aListInfo
.adornment
= kThemeAdornmentDefault
;
841 if( nState
& ControlState::FOCUSED
)
842 aListInfo
.adornment
|= kThemeAdornmentFocus
;
844 HIThemeDrawButton(&rc
, &aListInfo
, mrContext
, kHIThemeOrientationNormal
,&rc
);
848 case ControlPart::ListboxWindow
:
850 HIThemeFrameDrawInfo aTextDrawInfo
;
851 aTextDrawInfo
.version
=0;
852 aTextDrawInfo
.kind
=kHIThemeFrameTextFieldSquare
;
853 aTextDrawInfo
.state
=getState( nState
);
854 aTextDrawInfo
.isFocused
=false;
856 rc
.size
.width
+=1;//else there's a white space because an OS X theme has no 3D border
858 HIThemeDrawFrame(&rc
, &aTextDrawInfo
, mrContext
, kHIThemeOrientationNormal
);
860 if(nState
& ControlState::FOCUSED
) HIThemeDrawFocusRect(&rc
, true, mrContext
, kHIThemeOrientationNormal
);
869 case ControlType::Editbox
:
870 case ControlType::MultilineEditbox
:
872 HIThemeFrameDrawInfo aTextDrawInfo
;
873 aTextDrawInfo
.version
=0;
874 aTextDrawInfo
.kind
=kHIThemeFrameTextFieldSquare
;
875 aTextDrawInfo
.state
=getState( nState
);
876 aTextDrawInfo
.isFocused
=false;
878 rc
.size
.width
+= 1; // else there may be a white space because an OS X theme has no 3D border
879 // change rc so that the frame will encompass only the content region
880 // see counterpart in GetNativeControlRegion
884 //CGContextSetFillColorWithColor
885 CGContextFillRect (mrContext
, CGRectMake(rc
.origin
.x
, rc
.origin
.y
, rc
.size
.width
, rc
.size
.height
));
886 //fill a white background, because drawFrame only draws the border
888 HIThemeDrawFrame(&rc
, &aTextDrawInfo
, mrContext
, kHIThemeOrientationNormal
);
890 if(nState
& ControlState::FOCUSED
) HIThemeDrawFocusRect(&rc
, true, mrContext
, kHIThemeOrientationNormal
);
896 case ControlType::Spinbox
:
898 if(nPart
== ControlPart::Entire
)
901 HIThemeFrameDrawInfo aTextDrawInfo
;
902 aTextDrawInfo
.version
=0;
903 aTextDrawInfo
.kind
=kHIThemeFrameTextFieldSquare
;
904 aTextDrawInfo
.state
=getState( nState
);
905 aTextDrawInfo
.isFocused
=false;
907 //rc.size.width contains the full size of the spinbox ie textfield + button
908 //so we remove the button width and the space between the button and the textfield
909 rc
.size
.width
-= SPIN_BUTTON_SPACE
+ SPIN_BUTTON_WIDTH
+ 2*FOCUS_RING_WIDTH
;
910 rc
.origin
.x
+= FOCUS_RING_WIDTH
;
911 rc
.origin
.y
+= FOCUS_RING_WIDTH
;
913 //CGContextSetFillColorWithColor
914 CGContextFillRect (mrContext
, CGRectMake(rc
.origin
.x
, rc
.origin
.y
, rc
.size
.width
, rc
.size
.height
));
915 //fill a white background, because drawFrame only draws the border
917 HIThemeDrawFrame(&rc
, &aTextDrawInfo
, mrContext
, kHIThemeOrientationNormal
);
919 if(nState
& ControlState::FOCUSED
) HIThemeDrawFocusRect(&rc
, true, mrContext
, kHIThemeOrientationNormal
);
922 const SpinbuttonValue
* pSpinButtonVal
= (aValue
.getType() == ControlType::SpinButtons
) ? static_cast<const SpinbuttonValue
*>(&aValue
) : nullptr;
923 ControlState nUpperState
= ControlState::ENABLED
;//state of the upper button
924 ControlState nLowerState
= ControlState::ENABLED
;//and of the lower button
925 if(pSpinButtonVal
) {//pSpinButtonVal is sometimes null
926 nUpperState
= (ControlState
) pSpinButtonVal
->mnUpperState
;
927 nLowerState
= (ControlState
) pSpinButtonVal
->mnLowerState
;
929 HIThemeButtonDrawInfo aSpinInfo
;
930 aSpinInfo
.kind
= kThemeIncDecButton
;
931 aSpinInfo
.state
= kThemeStateActive
;
932 if(nUpperState
& ControlState::PRESSED
)
933 aSpinInfo
.state
= kThemeStatePressedUp
;
934 else if(nLowerState
& ControlState::PRESSED
)
935 aSpinInfo
.state
= kThemeStatePressedDown
;
936 else if((nUpperState
& ~ControlState::ENABLED
)||(nLowerState
& ~ControlState::ENABLED
))
937 aSpinInfo
.state
= kThemeStateInactive
;
938 else if((nUpperState
& ControlState::ROLLOVER
)||(nLowerState
& ControlState::ROLLOVER
))
939 aSpinInfo
.state
= kThemeStateRollover
;
941 tools::Rectangle
aSpinRect( pSpinButtonVal
->maUpperRect
);
942 aSpinRect
.Union( pSpinButtonVal
->maLowerRect
);
943 HIRect buttonRc
= ImplGetHIRectFromRectangle(aSpinRect
);
945 // FIXME: without this fuzz factor there is some unwanted clipping
946 if( AllSettings::GetLayoutRTL() )
947 buttonRc
.origin
.x
-= FOCUS_RING_WIDTH
- CLIP_FUZZ
;
949 buttonRc
.origin
.x
+= FOCUS_RING_WIDTH
+ CLIP_FUZZ
;
951 switch( aValue
.getTristateVal() )
953 case ButtonValue::On
: aSpinInfo
.value
= kThemeButtonOn
;
955 case ButtonValue::Off
: aSpinInfo
.value
= kThemeButtonOff
;
957 case ButtonValue::Mixed
:
958 case ButtonValue::DontKnow
:
959 default: aSpinInfo
.value
= kThemeButtonMixed
;
963 aSpinInfo
.adornment
= ( (nUpperState
& ControlState::DEFAULT
) ||
964 (nLowerState
& ControlState::DEFAULT
) ) ?
965 kThemeAdornmentDefault
:
967 if( (nUpperState
& ControlState::FOCUSED
) || (nLowerState
& ControlState::FOCUSED
))
968 aSpinInfo
.adornment
|= kThemeAdornmentFocus
;
970 HIThemeDrawButton( &buttonRc
, &aSpinInfo
, mrContext
, kHIThemeOrientationNormal
, nullptr );
979 case ControlType::Frame
:
981 DrawFrameFlags nStyle
= static_cast<DrawFrameFlags
>(aValue
.getNumericVal());
982 if( nPart
== ControlPart::Border
) {
983 if(!( nStyle
& DrawFrameFlags::Menu
) && !(nStyle
& DrawFrameFlags::WindowBorder
) )
985 // #i84756# strange effects start to happen when HIThemeDrawFrame
986 // meets the border of the window. These can be avoided by clipping
987 // to the boundary of the frame
988 if( rc
.origin
.y
+ rc
.size
.height
>= mpFrame
->maGeometry
.nHeight
-3 )
990 CGMutablePathRef rPath
= CGPathCreateMutable();
991 CGPathAddRect( rPath
, nullptr, CGRectMake( 0, 0, mpFrame
->maGeometry
.nWidth
-1, mpFrame
->maGeometry
.nHeight
-1 ) );
993 CGContextBeginPath( mrContext
);
994 CGContextAddPath( mrContext
, rPath
);
995 CGContextClip( mrContext
);
996 CGPathRelease( rPath
);
999 HIThemeFrameDrawInfo aTextDrawInfo
;
1000 aTextDrawInfo
.version
=0;
1001 aTextDrawInfo
.kind
=kHIThemeFrameListBox
;
1002 aTextDrawInfo
.state
=kThemeStateActive
;
1003 aTextDrawInfo
.isFocused
=false;
1005 HIThemeDrawFrame(&rc
, &aTextDrawInfo
, mrContext
, kHIThemeOrientationNormal
);
1013 case ControlType::ListNet
:
1015 //do nothing as there isn't net for listviews on macos
1022 CGContextRestoreGState( mrContext
);
1024 /* #i90291# in most cases invalidating the whole control region instead
1025 of just the unclipped part of it is sufficient (and probably faster).
1026 However for the window background we should not unnecessarily enlarge
1027 the really changed rectangle since the difference is usually quite high
1028 (the background is always drawn as a whole since we don't know anything
1029 about its possible contents)
1031 if( nType
== ControlType::WindowBackground
)
1033 CGRect aRect
= { { 0, 0 }, { 0, 0 } };
1035 aRect
= CGPathGetBoundingBox( mxClipPath
);
1036 if( aRect
.size
.width
!= 0 && aRect
.size
.height
!= 0 )
1037 buttonRect
.Intersection( tools::Rectangle( Point( static_cast<long int>(aRect
.origin
.x
),
1038 static_cast<long int>(aRect
.origin
.y
) ),
1039 Size( static_cast<long int>(aRect
.size
.width
),
1040 static_cast<long int>(aRect
.size
.height
) ) ) );
1043 RefreshRect( buttonRect
.Left(), buttonRect
.Top(), buttonRect
.GetWidth(), buttonRect
.GetHeight() );
1048 bool AquaSalGraphics::getNativeControlRegion( ControlType nType
, ControlPart nPart
, const tools::Rectangle
& rControlRegion
, ControlState
/*nState*/,
1049 const ImplControlValue
& aValue
, const OUString
&,
1050 tools::Rectangle
&rNativeBoundingRegion
, tools::Rectangle
&rNativeContentRegion
)
1053 bool toReturn
= false;
1055 tools::Rectangle
aCtrlBoundRect( rControlRegion
);
1056 short x
= aCtrlBoundRect
.Left();
1057 short y
= aCtrlBoundRect
.Top();
1060 sal_uInt8 nBorderCleanup
= 0;
1064 case ControlType::Slider
:
1066 if( nPart
== ControlPart::ThumbHorz
)
1068 w
= 19; // taken from HIG
1069 h
= aCtrlBoundRect
.GetHeight();
1070 rNativeBoundingRegion
= rNativeContentRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1073 else if( nPart
== ControlPart::ThumbVert
)
1075 w
= aCtrlBoundRect
.GetWidth();
1076 h
= 18; // taken from HIG
1077 rNativeBoundingRegion
= rNativeContentRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1083 case ControlType::Scrollbar
:
1085 tools::Rectangle aRect
;
1086 if( AquaGetScrollRect( /* m_nScreen */ nPart
, aCtrlBoundRect
, aRect
) )
1089 rNativeBoundingRegion
= aRect
;
1090 rNativeContentRegion
= aRect
;
1095 case ControlType::Pushbutton
:
1096 case ControlType::Radiobutton
:
1097 case ControlType::Checkbox
:
1099 if ( nType
== ControlType::Pushbutton
)
1101 w
= aCtrlBoundRect
.GetWidth();
1102 h
= aCtrlBoundRect
.GetHeight();
1106 // checkbox and radio borders need cleanup after unchecking them
1109 // TEXT_SEPARATOR to respect Aqua HIG
1110 w
= BUTTON_WIDTH
+ TEXT_SEPARATOR
;
1115 rNativeContentRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
+ nBorderCleanup
) );
1116 rNativeBoundingRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1121 case ControlType::Progress
:
1123 tools::Rectangle
aRect( aCtrlBoundRect
);
1124 if( aRect
.GetHeight() < 16 )
1125 aRect
.Bottom() = aRect
.Top() + 9; // values taken from HIG for medium progress
1127 aRect
.Bottom() = aRect
.Top() + 15; // values taken from HIG for large progress
1128 rNativeBoundingRegion
= aRect
;
1129 rNativeContentRegion
= aRect
;
1134 case ControlType::IntroProgress
:
1136 tools::Rectangle
aRect( aCtrlBoundRect
);
1137 aRect
.Bottom() = aRect
.Top() + INTRO_PROGRESS_HEIGHT
; // values taken from HIG for medium progress
1138 rNativeBoundingRegion
= aRect
;
1139 rNativeContentRegion
= aRect
;
1144 case ControlType::TabItem
:
1146 w
= aCtrlBoundRect
.GetWidth() + 2*TAB_TEXT_OFFSET
- 2*VCL_TAB_TEXT_OFFSET
;
1147 h
= TAB_HEIGHT_NORMAL
+2;
1149 rNativeContentRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1150 rNativeBoundingRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1156 case ControlType::Editbox
:
1158 w
= aCtrlBoundRect
.GetWidth();
1159 if( w
< 3+2*FOCUS_RING_WIDTH
)
1160 w
= 3+2*FOCUS_RING_WIDTH
;
1161 h
= TEXT_EDIT_HEIGHT_NORMAL
+2*FOCUS_RING_WIDTH
;
1162 if( h
< aCtrlBoundRect
.GetHeight() )
1163 h
= aCtrlBoundRect
.GetHeight();
1165 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) ) );
1166 rNativeBoundingRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1171 case ControlType::Listbox
:
1172 case ControlType::Combobox
:
1174 if( nPart
== ControlPart::Entire
)
1176 w
= aCtrlBoundRect
.GetWidth();
1177 h
= COMBOBOX_HEIGHT_NORMAL
;//listboxes and comboxes have the same height
1179 rNativeContentRegion
= tools::Rectangle( Point( x
+FOCUS_RING_WIDTH
, y
+FOCUS_RING_WIDTH
), Size( w
-2*FOCUS_RING_WIDTH
, h
) );
1180 rNativeBoundingRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
+2*FOCUS_RING_WIDTH
) );
1184 else if( nPart
== ControlPart::ButtonDown
)
1186 w
= aCtrlBoundRect
.GetWidth();
1187 if( w
< 3+2*FOCUS_RING_WIDTH
)
1188 w
= 3+2*FOCUS_RING_WIDTH
;
1189 h
= COMBOBOX_HEIGHT_NORMAL
;//listboxes and comboxes have the same height
1191 x
+= w
-DROPDOWN_BUTTON_WIDTH
- FOCUS_RING_WIDTH
;
1192 y
+= FOCUS_RING_WIDTH
;
1193 w
= DROPDOWN_BUTTON_WIDTH
;
1195 rNativeContentRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1196 rNativeBoundingRegion
= tools::Rectangle( Point( x
, y
), Size( w
+FOCUS_RING_WIDTH
, h
+2*FOCUS_RING_WIDTH
) );
1200 else if( nPart
== ControlPart::SubEdit
)
1202 w
= aCtrlBoundRect
.GetWidth();
1203 h
= COMBOBOX_HEIGHT_NORMAL
;//listboxes and comboxes have the same height
1205 x
+= FOCUS_RING_WIDTH
;
1206 x
+= 3; // add an offset for rounded borders
1207 y
+= 2; // don't draw into upper border
1208 y
+= FOCUS_RING_WIDTH
;
1209 w
-= 3 + DROPDOWN_BUTTON_WIDTH
+ 2*FOCUS_RING_WIDTH
;
1210 if( nType
== ControlType::Listbox
)
1211 w
-= 9; // HIG specifies 9 units distance between dropdown button area and content
1212 h
-= 4; // don't draw into lower border
1214 rNativeContentRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1215 rNativeBoundingRegion
= tools::Rectangle( Point( x
, y
), Size( w
+FOCUS_RING_WIDTH
, h
+2*FOCUS_RING_WIDTH
) );
1221 case ControlType::Spinbox
:
1222 if( nPart
== ControlPart::Entire
) {
1223 w
= aCtrlBoundRect
.GetWidth();
1224 if( w
< 3+2*FOCUS_RING_WIDTH
+SPIN_BUTTON_SPACE
+SPIN_BUTTON_WIDTH
)
1225 w
= 3+2*FOCUS_RING_WIDTH
+SPIN_BUTTON_SPACE
+SPIN_BUTTON_WIDTH
;
1226 h
= TEXT_EDIT_HEIGHT_NORMAL
;
1228 rNativeContentRegion
= tools::Rectangle( Point( x
+FOCUS_RING_WIDTH
, y
), Size( w
-2*FOCUS_RING_WIDTH
, h
) );
1229 rNativeBoundingRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
+2*FOCUS_RING_WIDTH
) );
1233 else if( nPart
== ControlPart::SubEdit
) {
1234 w
= aCtrlBoundRect
.GetWidth() - SPIN_BUTTON_SPACE
- SPIN_BUTTON_WIDTH
;
1235 h
= TEXT_EDIT_HEIGHT_NORMAL
;
1236 x
+= 4; // add an offset for rounded borders
1237 y
+= 2; // don't draw into upper border
1238 w
-= 8; // offset for left and right rounded border
1239 h
-= 4; // don't draw into upper or lower border
1241 rNativeContentRegion
= tools::Rectangle( Point( x
+ FOCUS_RING_WIDTH
, y
+ FOCUS_RING_WIDTH
), Size( w
- 2* FOCUS_RING_WIDTH
, h
) );
1242 rNativeBoundingRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
+2*FOCUS_RING_WIDTH
) );
1246 else if( nPart
== ControlPart::ButtonUp
) {
1247 //aCtrlBoundRect.GetWidth() contains the width of the full control
1248 //ie the width of the textfield + button
1249 //x is the position of the left corner of the full control
1250 x
+= aCtrlBoundRect
.GetWidth() - SPIN_BUTTON_WIDTH
- SPIN_BUTTON_SPACE
- CLIP_FUZZ
;
1251 y
+= FOCUS_RING_WIDTH
- CLIP_FUZZ
;
1252 w
= SPIN_BUTTON_WIDTH
+ 2*CLIP_FUZZ
;
1253 h
= SPIN_UPPER_BUTTON_HEIGHT
+ 2*CLIP_FUZZ
;
1255 rNativeContentRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1256 rNativeBoundingRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1260 else if( nPart
== ControlPart::ButtonDown
) {
1261 x
+= aCtrlBoundRect
.GetWidth() - SPIN_BUTTON_WIDTH
- SPIN_BUTTON_SPACE
- CLIP_FUZZ
;
1262 y
+= SPIN_UPPER_BUTTON_HEIGHT
+ FOCUS_RING_WIDTH
- CLIP_FUZZ
;
1263 w
= SPIN_BUTTON_WIDTH
+ 2*CLIP_FUZZ
;
1264 h
= SPIN_LOWER_BUTTON_HEIGHT
+ 2*CLIP_FUZZ
;
1266 rNativeContentRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1267 rNativeBoundingRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1272 case ControlType::Frame
:
1274 DrawFrameStyle nStyle
= static_cast<DrawFrameStyle
>(aValue
.getNumericVal() & 0x000f);
1275 DrawFrameFlags nFlags
= static_cast<DrawFrameFlags
>(aValue
.getNumericVal() & 0xfff0);
1276 if( ( nPart
== ControlPart::Border
) &&
1277 !( nFlags
& (DrawFrameFlags::Menu
| DrawFrameFlags::WindowBorder
| DrawFrameFlags::BorderWindowBorder
) ) )
1279 tools::Rectangle
aRect(aCtrlBoundRect
);
1280 if( nStyle
== DrawFrameStyle::DoubleIn
)
1284 //rRect.Right() -= 1;
1285 //rRect.Bottom() -= 1;
1292 aRect
.Bottom() -= 1;
1295 rNativeContentRegion
= aRect
;
1296 rNativeBoundingRegion
= aRect
;
1303 case ControlType::Menubar
:
1304 case ControlType::MenuPopup
:
1306 if(( nPart
== ControlPart::MenuItemCheckMark
)||( nPart
== ControlPart::MenuItemRadioMark
)) {
1309 h
=10;//dimensions of the mark (10px font)
1311 rNativeContentRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1312 rNativeBoundingRegion
= tools::Rectangle( Point( x
, y
), Size( w
, h
) );
1325 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */