1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salnativewidgets.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
33 #include "salnativewidgets.h"
34 #include "saldata.hxx"
37 #include "vcl/salnativewidgets.hxx"
38 #include "vcl/decoview.hxx"
39 #include "vcl/svapp.hxx"
40 #include "vcl/timer.hxx"
43 #include <Carbon/Carbon.h>
46 class AquaBlinker
: public Timer
48 AquaSalFrame
* mpFrame
;
49 Rectangle maInvalidateRect
;
51 AquaBlinker( AquaSalFrame
* pFrame
, const Rectangle
& rRect
)
52 : mpFrame( pFrame
), maInvalidateRect( rRect
)
54 mpFrame
->maBlinkers
.push_back( this );
59 static void Blink( AquaSalFrame
*, const Rectangle
&, int nTimeout
= 80 );
61 virtual void Timeout()
64 if( AquaSalFrame::isAlive( mpFrame
) && mpFrame
->mbShown
)
66 mpFrame
->maBlinkers
.remove( this );
67 mpFrame
->SendPaintEvent( &maInvalidateRect
);
73 void AquaBlinker::Blink( AquaSalFrame
* pFrame
, const Rectangle
& rRect
, int nTimeout
)
75 // prevent repeated paints from triggering themselves all the time
76 for( std::list
< AquaBlinker
* >::const_iterator it
= pFrame
->maBlinkers
.begin();
77 it
!= pFrame
->maBlinkers
.end(); ++it
)
79 if( (*it
)->maInvalidateRect
== rRect
)
82 AquaBlinker
* pNew
= new AquaBlinker( pFrame
, rRect
);
83 pNew
->SetTimeout( nTimeout
);
87 ControlPart
ImplgetCounterPart( ControlPart nPart
)
89 ControlPart nCounterPart
= 0;
93 nCounterPart
= PART_BUTTON_DOWN
;
95 case PART_BUTTON_DOWN
:
96 nCounterPart
= PART_BUTTON_UP
;
98 case PART_BUTTON_LEFT
:
99 nCounterPart
= PART_BUTTON_RIGHT
;
101 case PART_BUTTON_RIGHT
:
102 nCounterPart
= PART_BUTTON_LEFT
;
109 // Helper returns an HIRect
111 static HIRect
ImplGetHIRectFromRectangle(Rectangle aRect
)
114 aHIRect
.origin
.x
= static_cast<float>(aRect
.Left());
115 aHIRect
.origin
.y
= static_cast<float>(aRect
.Top());
116 aHIRect
.size
.width
= static_cast<float>(aRect
.GetWidth());
117 aHIRect
.size
.height
= static_cast<float>(aRect
.GetHeight());
121 static ThemeButtonValue
ImplGetButtonValue( ButtonValue aButtonValue
)
123 switch( aButtonValue
)
126 return kThemeButtonOn
;
129 case BUTTONVALUE_OFF
:
130 return kThemeButtonOff
;
133 case BUTTONVALUE_MIXED
:
134 case BUTTONVALUE_DONTKNOW
:
136 return kThemeButtonMixed
;
141 static bool AquaGetScrollRect( /* TODO: int nScreen, */ ControlPart nPart
,
142 const Rectangle
& rControlRect
, Rectangle
& rResultRect
)
145 rResultRect
= rControlRect
;
150 if( GetSalData()->mbIsScrollbarDoubleMax
)
151 rResultRect
.Top() = rControlRect
.Bottom() - 2*BUTTON_HEIGHT
;
152 rResultRect
.Bottom() = rResultRect
.Top() + BUTTON_HEIGHT
;
155 case PART_BUTTON_DOWN
:
156 rResultRect
.Top() = rControlRect
.Bottom() - BUTTON_HEIGHT
;
159 case PART_BUTTON_LEFT
:
160 if( GetSalData()->mbIsScrollbarDoubleMax
)
161 rResultRect
.Left() = rControlRect
.Right() - 2*BUTTON_WIDTH
;
162 rResultRect
.Right() = rResultRect
.Left() + BUTTON_WIDTH
;
165 case PART_BUTTON_RIGHT
:
166 rResultRect
.Left() = rControlRect
.Right() - BUTTON_WIDTH
;
169 case PART_TRACK_HORZ_AREA
:
170 rResultRect
.Right() -= BUTTON_WIDTH
+ 1;
171 if( GetSalData()->mbIsScrollbarDoubleMax
)
172 rResultRect
.Right() -= BUTTON_WIDTH
;
174 rResultRect
.Left() += BUTTON_WIDTH
+ 1;
177 case PART_TRACK_VERT_AREA
:
178 rResultRect
.Bottom() -= BUTTON_HEIGHT
+ 1;
179 if( GetSalData()->mbIsScrollbarDoubleMax
)
180 rResultRect
.Bottom() -= BUTTON_HEIGHT
;
182 rResultRect
.Top() += BUTTON_HEIGHT
+ 1;
184 case PART_THUMB_HORZ
:
185 if( GetSalData()->mbIsScrollbarDoubleMax
)
187 rResultRect
.Left() += 8;
188 rResultRect
.Right() += 6;
192 rResultRect
.Left() += 4;
193 rResultRect
.Right() += 4;
196 case PART_THUMB_VERT
:
197 if( GetSalData()->mbIsScrollbarDoubleMax
)
199 rResultRect
.Top() += 8;
200 rResultRect
.Bottom() += 8;
204 rResultRect
.Top() += 4;
205 rResultRect
.Bottom() += 4;
208 case PART_TRACK_HORZ_LEFT
:
209 if( GetSalData()->mbIsScrollbarDoubleMax
)
210 rResultRect
.Right() += 8;
212 rResultRect
.Right() += 4;
214 case PART_TRACK_HORZ_RIGHT
:
215 if( GetSalData()->mbIsScrollbarDoubleMax
)
216 rResultRect
.Left() += 6;
218 rResultRect
.Left() += 4;
220 case PART_TRACK_VERT_UPPER
:
221 if( GetSalData()->mbIsScrollbarDoubleMax
)
222 rResultRect
.Bottom() += 8;
224 rResultRect
.Bottom() += 4;
226 case PART_TRACK_VERT_LOWER
:
227 if( GetSalData()->mbIsScrollbarDoubleMax
)
228 rResultRect
.Top() += 8;
230 rResultRect
.Top() += 4;
240 * IsNativeControlSupported()
241 * --------------------------
242 * Returns TRUE if the platform supports native
243 * drawing of the control defined by nPart.
246 BOOL
AquaSalGraphics::IsNativeControlSupported( ControlType nType
, ControlPart nPart
)
250 // Native controls are now defaults
251 // If you want to disable experimental native controls code,
252 // just set the environment variable SAL_NO_NWF to something
253 // and vcl controls will be used as default again.
257 case CTRL_PUSHBUTTON
:
258 case CTRL_RADIOBUTTON
:
261 if( nPart
== PART_ENTIRE_CONTROL
)
266 if( nPart
== PART_DRAW_BACKGROUND_HORZ
||
267 nPart
== PART_DRAW_BACKGROUND_VERT
||
268 nPart
== PART_ENTIRE_CONTROL
||
269 nPart
== HAS_THREE_BUTTONS
)
274 if( nPart
== PART_ENTIRE_CONTROL
||
275 nPart
== HAS_BACKGROUND_TEXTURE
)
279 case CTRL_MULTILINE_EDITBOX
:
280 if( nPart
== PART_ENTIRE_CONTROL
||
281 nPart
== HAS_BACKGROUND_TEXTURE
)
286 if( nPart
== PART_ENTIRE_CONTROL
||
287 nPart
== PART_ALL_BUTTONS
||
288 nPart
== HAS_BACKGROUND_TEXTURE
)
292 case CTRL_SPINBUTTONS
:
297 if( nPart
== PART_ENTIRE_CONTROL
||
298 nPart
== HAS_BACKGROUND_TEXTURE
)
303 if( nPart
== PART_ENTIRE_CONTROL
||
304 nPart
== PART_WINDOW
||
305 nPart
== HAS_BACKGROUND_TEXTURE
||
306 nPart
== PART_SUB_EDIT
313 case CTRL_TAB_BODY
: // see vcl/source/window/tabpage.cxx
314 case CTRL_FIXEDBORDER
:
315 if( nPart
== PART_ENTIRE_CONTROL
||
316 nPart
== PART_TABS_DRAW_RTL
||
317 nPart
== HAS_BACKGROUND_TEXTURE
)
321 // when PART_BUTTON is used, toolbar icons are not highlighted when mouse rolls over.
322 // More Aqua compliant
324 if( nPart
== PART_ENTIRE_CONTROL
||
325 nPart
== PART_DRAW_BACKGROUND_HORZ
||
326 nPart
== PART_DRAW_BACKGROUND_VERT
)
330 case CTRL_WINDOW_BACKGROUND
:
331 if ( nPart
== PART_BACKGROUND_WINDOW
||
332 nPart
== PART_BACKGROUND_DIALOG
)
337 if( nPart
== PART_ENTIRE_CONTROL
)
341 case CTRL_TOOLTIP
: // ** TO DO
343 if( nPart
== PART_ENTIRE_CONTROL
) // we don't currently support the tooltip
348 case CTRL_MENU_POPUP
:
349 if( nPart
== PART_ENTIRE_CONTROL
||
350 nPart
== PART_MENU_ITEM
||
351 nPart
== PART_MENU_ITEM_CHECK_MARK
||
352 nPart
== PART_MENU_ITEM_RADIO_MARK
)
356 case CTRL_INTROPROGRESS
:
357 if( nPart
== PART_ENTIRE_CONTROL
)
361 if( nPart
== PART_BORDER
)
365 if( nPart
== PART_ENTIRE_CONTROL
)
374 * HitTestNativeControl()
376 * If the return value is TRUE, bIsInside contains information whether
377 * aPos was or was not inside the native widget specified by the
378 * nType/nPart combination.
380 BOOL
AquaSalGraphics::hitTestNativeControl( ControlType nType
, ControlPart nPart
, const Region
& rControlRegion
,
381 const Point
& rPos
, SalControlHandle
& rControlHandle
, BOOL
& rIsInside
)
383 if ( nType
== CTRL_SCROLLBAR
)
386 bool bValid
= AquaGetScrollRect( /* TODO: m_nScreen */ nPart
, rControlRegion
.GetBoundRect(), aRect
);
387 rIsInside
= bValid
? aRect
.IsInside( rPos
) : FALSE
;
388 if( GetSalData()->mbIsScrollbarDoubleMax
)
390 // in double max mode the actual trough is a little smaller than the track
391 // there is some visual filler that is not sensitive
392 if( bValid
&& rIsInside
)
394 if( nPart
== PART_TRACK_HORZ_AREA
)
396 // the left 4 pixels are not hit sensitive
397 if( rPos
.X() - aRect
.Left() < 4 )
400 else if( nPart
== PART_TRACK_VERT_AREA
)
402 // the top 4 pixels are not hit sensitive
403 if( rPos
.Y() - aRect
.Top() < 4 )
415 kThemeStateInactive = 0,
416 kThemeStateActive = 1,
417 kThemeStatePressed = 2,
418 kThemeStateRollover = 6,
419 kThemeStateUnavailable = 7,
420 kThemeStateUnavailableInactive = 8
421 kThemeStatePressedUp = 2,
422 kThemeStatePressedDown = 3
424 #define CTRL_STATE_ENABLED 0x0001
425 #define CTRL_STATE_FOCUSED 0x0002
426 #define CTRL_STATE_PRESSED 0x0004
427 #define CTRL_STATE_ROLLOVER 0x0008
428 #define CTRL_STATE_HIDDEN 0x0010
429 #define CTRL_STATE_DEFAULT 0x0020
430 #define CTRL_STATE_SELECTED 0x0040
431 #define CTRL_CACHING_ALLOWED 0x8000 // set when the control is completely visible (i.e. not clipped)
433 static ThemeDrawState
getState( ControlState nState
)
435 if( (nState
& CTRL_STATE_ENABLED
) == 0 )
437 if( (nState
& CTRL_STATE_HIDDEN
) == 0 )
438 return kThemeStateInactive
;
440 return kThemeStateUnavailableInactive
;
443 if( (nState
& CTRL_STATE_HIDDEN
) != 0 )
444 return kThemeStateUnavailable
;
446 if( (nState
& CTRL_STATE_PRESSED
) != 0 )
447 return kThemeStatePressed
;
449 return kThemeStateActive
;
453 * DrawNativeControl()
455 * Draws the requested control described by nPart/nState.
457 * rControlRegion: The bounding region of the complete control in VCL frame coordinates.
458 * aValue: An optional value (tristate/numerical/string)
459 * rControlHandle: Carries platform dependent data and is maintained by the AquaSalGraphics implementation.
460 * aCaption: A caption or title string (like button text etc)
462 BOOL
AquaSalGraphics::drawNativeControl(ControlType nType
,
464 const Region
& rControlRegion
,
466 const ImplControlValue
& aValue
,
467 SalControlHandle
& rControlHandle
,
468 const rtl::OUString
& aCaption
)
472 if( ! CheckContext() )
475 CGContextSaveGState( mrContext
);
477 Rectangle buttonRect
= rControlRegion
.GetBoundRect();
478 HIRect rc
= ImplGetHIRectFromRectangle(buttonRect
);
480 /** Scrollbar parts code equivalent **
484 PART_TRACK_VERT_UPPER 201
485 PART_TRACK_VERT_LOWER 203
487 PART_DRAW_BACKGROUND_HORZ 1000
488 PART_DRAW_BACKGROUND_VERT 1001
495 if ( nPart
== HAS_BACKGROUND_TEXTURE
||
496 nPart
== PART_ENTIRE_CONTROL
)
498 HIThemeButtonDrawInfo aComboInfo
;
499 aComboInfo
.version
= 0;
500 aComboInfo
.kind
= kThemeComboBox
;
501 aComboInfo
.state
= getState( nState
);
502 aComboInfo
.value
= kThemeButtonOn
;
503 aComboInfo
.adornment
= kThemeAdornmentNone
;
505 if( (nState
& CTRL_STATE_FOCUSED
) != 0 )
506 aComboInfo
.adornment
|= kThemeAdornmentFocus
;
508 HIThemeDrawButton(&rc
, &aComboInfo
, mrContext
, kHIThemeOrientationNormal
,&rc
);
513 case CTRL_FIXEDBORDER
:
516 HIThemeMenuItemDrawInfo aMenuItemDrawInfo
;
517 aMenuItemDrawInfo
.version
= 0;
518 aMenuItemDrawInfo
.state
= kThemeMenuActive
;
519 aMenuItemDrawInfo
.itemType
= kThemeMenuItemHierBackground
;
520 HIThemeDrawMenuItem(&rc
,&rc
,&aMenuItemDrawInfo
,mrContext
,kHIThemeOrientationNormal
,NULL
);
525 case CTRL_WINDOW_BACKGROUND
:
527 HIThemeBackgroundDrawInfo aThemeBackgroundInfo
;
528 aThemeBackgroundInfo
.version
= 0;
529 aThemeBackgroundInfo
.state
= getState( nState
);
530 aThemeBackgroundInfo
.kind
= kThemeBrushDialogBackgroundInactive
;
531 // FIXME: without this magical offset there is a 2 pixel black border on the right and bottom
535 HIThemeApplyBackground( &rc
, &aThemeBackgroundInfo
, mrContext
, kHIThemeOrientationNormal
);
536 CGContextFillRect( mrContext
, rc
);
542 case CTRL_MENU_POPUP
:
544 if ((nPart
== PART_ENTIRE_CONTROL
) || (nPart
== PART_MENU_ITEM
)|| (nPart
== HAS_BACKGROUND_TEXTURE
))
546 // FIXME: without this magical offset there is a 2 pixel black border on the right
549 HIThemeMenuDrawInfo aMenuInfo
;
550 aMenuInfo
.version
= 0;
551 aMenuInfo
.menuType
= kThemeMenuTypePullDown
;
553 HIThemeMenuItemDrawInfo aMenuItemDrawInfo
;
554 // the Aqua grey theme when the item is selected is drawn here.
555 aMenuItemDrawInfo
.itemType
= kThemeMenuItemPlain
;
557 if ((nPart
== PART_MENU_ITEM
))
559 // the blue theme when the item is selected is drawn here.
560 aMenuItemDrawInfo
.state
= kThemeMenuSelected
;
564 // normal color for non selected item
565 aMenuItemDrawInfo
.state
= kThemeMenuActive
;
568 // repaints the background of the pull down menu
569 HIThemeDrawMenuBackground(&rc
,&aMenuInfo
,mrContext
,kHIThemeOrientationNormal
);
571 // repaints the item either blue (selected) and/or Aqua grey (active only)
572 HIThemeDrawMenuItem(&rc
,&rc
,&aMenuItemDrawInfo
,mrContext
,kHIThemeOrientationNormal
,&rc
);
576 else if(( nPart
== PART_MENU_ITEM_CHECK_MARK
)||( nPart
== PART_MENU_ITEM_RADIO_MARK
)) {
577 if( nState
& CTRL_STATE_PRESSED
) {//checked, else it is not displayed (see vcl/source/window/menu.cxx)
578 HIThemeTextInfo aTextInfo
;
579 aTextInfo
.version
= 0;
580 aTextInfo
.state
= ((nState
& CTRL_STATE_ENABLED
)==0) ? kThemeStateInactive
: kThemeStateActive
;
581 aTextInfo
.fontID
= kThemeMenuItemMarkFont
;
582 aTextInfo
.horizontalFlushness
=kHIThemeTextHorizontalFlushCenter
;
583 aTextInfo
.verticalFlushness
=kHIThemeTextVerticalFlushTop
;
584 aTextInfo
.options
=kHIThemeTextBoxOptionNone
;
585 aTextInfo
.truncationPosition
=kHIThemeTextTruncationNone
;
586 //aTextInfo.truncationMaxLines unused because of kHIThemeTextTruncationNone
588 if( nState
& CTRL_STATE_SELECTED
) aTextInfo
.state
= kThemeStatePressed
; //item highlighted
590 UniChar mark
=( nPart
== PART_MENU_ITEM_CHECK_MARK
) ? kCheckUnicode
: kBulletUnicode
;//0x2713;
591 CFStringRef cfString
= CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault
, &mark
, 1, kCFAllocatorNull
);
592 HIThemeDrawTextBox(cfString
, &rc
, &aTextInfo
, mrContext
, kHIThemeOrientationNormal
);
602 case CTRL_PUSHBUTTON
:
604 // [ FIXME] : instead of use a value, vcl can retrieve corect values on the fly (to be implemented)
605 const int PB_Mini_Height
= 15;
606 const int PB_Norm_Height
= 21;
608 HIThemeButtonDrawInfo aPushInfo
;
609 aPushInfo
.version
= 0;
612 aPushInfo
.animation
.time
.start
= 0;
613 aPushInfo
.animation
.time
.current
= 0;
614 PushButtonValue
* pPBVal
= (PushButtonValue
*)aValue
.getOptionalVal();
615 int nPaintHeight
= static_cast<int>(rc
.size
.height
);
617 if( pPBVal
&& pPBVal
->mbBevelButton
)
619 aPushInfo
.kind
= kThemeRoundedBevelButton
;
621 else if( rc
.size
.height
<= PB_Norm_Height
)
623 aPushInfo
.kind
= kThemePushButtonMini
;
624 nPaintHeight
= PB_Mini_Height
;
626 else if( pPBVal
->mbSingleLine
|| rc
.size
.height
< (PB_Norm_Height
+ PB_Norm_Height
/2) )
628 aPushInfo
.kind
= kThemePushButtonNormal
;
629 nPaintHeight
= PB_Norm_Height
;
631 // avoid clipping when focused
632 rc
.origin
.x
+= FOCUS_RING_WIDTH
/2;
633 rc
.size
.width
-= FOCUS_RING_WIDTH
;
635 if( (nState
& CTRL_STATE_DEFAULT
) != 0 )
637 AquaBlinker::Blink( mpFrame
, buttonRect
);
638 // show correct animation phase
639 aPushInfo
.animation
.time
.current
= CFAbsoluteTimeGetCurrent();
643 aPushInfo
.kind
= kThemeBevelButton
;
645 // translate the origin for controls with fixed paint height
646 // so content ends up somewhere sensible
647 int delta_y
= static_cast<int>(rc
.size
.height
) - nPaintHeight
;
648 rc
.origin
.y
+= delta_y
/2;
650 aPushInfo
.state
= getState( nState
);
651 aPushInfo
.value
= ImplGetButtonValue( aValue
.getTristateVal() );
653 aPushInfo
.adornment
= (( nState
& CTRL_STATE_DEFAULT
) != 0) ?
654 kThemeAdornmentDefault
:
656 if( (nState
& CTRL_STATE_FOCUSED
) != 0 )
657 aPushInfo
.adornment
|= kThemeAdornmentFocus
;
659 HIThemeDrawButton( &rc
, &aPushInfo
, mrContext
, kHIThemeOrientationNormal
, NULL
);
664 case CTRL_RADIOBUTTON
:
667 HIThemeButtonDrawInfo aInfo
;
671 case CTRL_RADIOBUTTON
: if(rc
.size
.width
>= BUTTON_HEIGHT
) aInfo
.kind
= kThemeRadioButton
;
672 else aInfo
.kind
= kThemeSmallRadioButton
;
674 case CTRL_CHECKBOX
: if(rc
.size
.width
>= BUTTON_HEIGHT
) aInfo
.kind
= kThemeCheckBox
;
675 else aInfo
.kind
= kThemeSmallCheckBox
;
679 aInfo
.state
= getState( nState
);
681 ButtonValue aButtonValue
= aValue
.getTristateVal();
682 aInfo
.value
= ImplGetButtonValue( aButtonValue
);
684 aInfo
.adornment
= (( nState
& CTRL_STATE_DEFAULT
) != 0) ?
685 kThemeAdornmentDefault
:
687 if( (nState
& CTRL_STATE_FOCUSED
) != 0 )
688 aInfo
.adornment
|= kThemeAdornmentFocus
;
689 HIThemeDrawButton( &rc
, &aInfo
, mrContext
, kHIThemeOrientationNormal
, NULL
);
696 ButtonValue aButtonValue
= aValue
.getTristateVal();
698 if( Application::GetSettings().GetLayoutRTL() && aButtonValue
== BUTTONVALUE_OFF
)
700 // FIXME: a value of kThemeDisclosureLeft
701 // should draw a theme compliant left disclosure triangle
702 // sadly this does not seem to work, so we'll draw a left
703 // grey equilateral triangle here ourselves.
704 // Perhaps some other HIThemeButtonDrawInfo setting would do the trick ?
706 CGContextSetShouldAntialias( mrContext
, true );
707 float aGrey
[] = { 0.45, 0.45, 0.45, 1.0 };
708 CGContextSetFillColor( mrContext
, aGrey
);
709 CGContextBeginPath( mrContext
);
710 float x
= rc
.origin
.x
+ rc
.size
.width
;
711 float y
= rc
.origin
.y
;
712 CGContextMoveToPoint( mrContext
, x
, y
);
714 CGContextAddLineToPoint( mrContext
, x
, y
);
715 x
-= rc
.size
.height
* 0.866; // cos( 30 degree ) is approx. 0.866
716 y
-= rc
.size
.height
/2;
717 CGContextAddLineToPoint( mrContext
, x
, y
);
718 CGContextDrawPath( mrContext
, kCGPathEOFill
);
722 HIThemeButtonDrawInfo aInfo
;
724 aInfo
.kind
= kThemeDisclosureTriangle
;
725 aInfo
.value
= kThemeDisclosureRight
;
726 aInfo
.state
= getState( nState
);
728 aInfo
.adornment
= kThemeAdornmentNone
;
730 switch( aButtonValue
) {
731 case BUTTONVALUE_ON
: aInfo
.value
= kThemeDisclosureDown
;//expanded
733 case BUTTONVALUE_OFF
:
734 // FIXME: this should have drawn a theme compliant disclosure triangle
736 if( Application::GetSettings().GetLayoutRTL() )
738 aInfo
.value
= kThemeDisclosureLeft
;//collapsed, RTL
741 case BUTTONVALUE_DONTKNOW
: //what to do?
746 HIThemeDrawButton( &rc
, &aInfo
, mrContext
, kHIThemeOrientationNormal
, NULL
);
753 case CTRL_INTROPROGRESS
:
755 long nProgressWidth
= aValue
.getNumericVal();
756 HIThemeTrackDrawInfo aTrackInfo
;
757 aTrackInfo
.version
= 0;
758 aTrackInfo
.kind
= (rc
.size
.height
> 10) ? kThemeProgressBarLarge
: kThemeProgressBarMedium
;
759 aTrackInfo
.bounds
= rc
;
761 aTrackInfo
.max
= static_cast<SInt32
>(rc
.size
.width
);
762 aTrackInfo
.value
= nProgressWidth
;
763 aTrackInfo
.reserved
= 0;
764 aTrackInfo
.bounds
.origin
.y
-= 2; // FIXME: magic for shadow
765 aTrackInfo
.bounds
.size
.width
-= 2; // FIXME: magic for shadow
766 aTrackInfo
.attributes
= kThemeTrackHorizontal
;
767 if( Application::GetSettings().GetLayoutRTL() )
768 aTrackInfo
.attributes
|= kThemeTrackRightToLeft
;
769 aTrackInfo
.enableState
= (nState
& CTRL_STATE_ENABLED
) ? kThemeTrackActive
: kThemeTrackInactive
;
770 aTrackInfo
.filler1
= 0;
771 aTrackInfo
.trackInfo
.progress
.phase
= static_cast<UInt8
>(CFAbsoluteTimeGetCurrent()*10.0);
773 HIThemeDrawTrack( &aTrackInfo
, NULL
, mrContext
, kHIThemeOrientationNormal
);
780 ScrollbarValue
* pScrollbarVal
= (ScrollbarValue
*)(aValue
.getOptionalVal());
782 if( nPart
== PART_DRAW_BACKGROUND_VERT
||
783 nPart
== PART_DRAW_BACKGROUND_HORZ
)
785 HIThemeTrackDrawInfo aTrackDraw
;
786 aTrackDraw
.kind
= kThemeMediumScrollBar
;
787 // FIXME: the scrollbar length must be adjusted
788 if (nPart
== PART_DRAW_BACKGROUND_VERT
)
793 aTrackDraw
.bounds
= rc
;
794 aTrackDraw
.min
= pScrollbarVal
->mnMin
;
795 aTrackDraw
.max
= pScrollbarVal
->mnMax
- pScrollbarVal
->mnVisibleSize
;
796 aTrackDraw
.value
= pScrollbarVal
->mnCur
;
797 aTrackDraw
.reserved
= 0;
798 aTrackDraw
.attributes
= kThemeTrackShowThumb
;
799 if( nPart
== PART_DRAW_BACKGROUND_HORZ
)
800 aTrackDraw
.attributes
|= kThemeTrackHorizontal
;
801 aTrackDraw
.enableState
= kThemeTrackActive
;
803 ScrollBarTrackInfo aScrollInfo
;
804 aScrollInfo
.viewsize
= pScrollbarVal
->mnVisibleSize
;
805 aScrollInfo
.pressState
= 0;
807 if ( pScrollbarVal
->mnButton1State
& CTRL_STATE_ENABLED
)
809 if ( pScrollbarVal
->mnButton1State
& CTRL_STATE_PRESSED
)
810 aScrollInfo
.pressState
= kThemeTopOutsideArrowPressed
;
813 if ( pScrollbarVal
->mnButton2State
& CTRL_STATE_ENABLED
)
815 if ( pScrollbarVal
->mnButton2State
& CTRL_STATE_PRESSED
)
816 aScrollInfo
.pressState
= kThemeBottomOutsideArrowPressed
;
819 if ( pScrollbarVal
->mnThumbState
& CTRL_STATE_ENABLED
)
821 if ( pScrollbarVal
->mnThumbState
& CTRL_STATE_PRESSED
)
822 aScrollInfo
.pressState
= kThemeThumbPressed
;
825 aTrackDraw
.trackInfo
.scrollbar
= aScrollInfo
;
827 HIThemeDrawTrack( &aTrackDraw
, NULL
, mrContext
, kHIThemeOrientationNormal
);
833 //#define OLD_TAB_STYLE
837 HIThemeTabPaneDrawInfo aTabPaneDrawInfo
;
838 aTabPaneDrawInfo
.version
= 0;
839 aTabPaneDrawInfo
.state
= kThemeStateActive
;
840 aTabPaneDrawInfo
.direction
=kThemeTabNorth
;
841 aTabPaneDrawInfo
.size
=kHIThemeTabSizeNormal
;
843 //the border is outside the rect rc for Carbon
844 //but for VCL it should be inside
848 HIThemeDrawTabPane(&rc
, &aTabPaneDrawInfo
, mrContext
, kHIThemeOrientationNormal
);
855 HIThemeTabDrawInfo aTabItemDrawInfo
;
856 aTabItemDrawInfo
.version
=0;
857 aTabItemDrawInfo
.style
=kThemeTabNonFront
;
858 aTabItemDrawInfo
.direction
=kThemeTabNorth
;
859 aTabItemDrawInfo
.size
=kHIThemeTabSizeNormal
;
860 aTabItemDrawInfo
.adornment
=kHIThemeTabAdornmentNone
;
862 if(nState
& CTRL_STATE_SELECTED
) {
863 aTabItemDrawInfo
.style
=kThemeTabFront
;
865 if(nState
& CTRL_STATE_FOCUSED
) {
866 aTabItemDrawInfo
.adornment
=kHIThemeTabAdornmentFocus
;
869 /*if(rc.size.height>=TAB_HEIGHT_NORMAL) rc.size.height=TAB_HEIGHT_NORMAL;
870 else if(rc.size.height>=TAB_HEIGHT_SMALL) rc.size.height=TAB_HEIGHT_SMALL;
871 else rc.size.height=TAB_HEIGHT_MINI;*/
872 //now we only use the default size
873 rc
.size
.height
=TAB_HEIGHT_NORMAL
;
875 HIThemeDrawTab(&rc
, &aTabItemDrawInfo
, mrContext
, kHIThemeOrientationNormal
, &rc
);
883 HIThemeTabPaneDrawInfo aTabPaneDrawInfo
;
884 aTabPaneDrawInfo
.version
= 1;
885 aTabPaneDrawInfo
.state
= kThemeStateActive
;
886 aTabPaneDrawInfo
.direction
=kThemeTabNorth
;
887 aTabPaneDrawInfo
.size
=kHIThemeTabSizeNormal
;
888 aTabPaneDrawInfo
.kind
=kHIThemeTabKindNormal
;
890 //the border is outside the rect rc for Carbon
891 //but for VCL it should be inside
893 rc
.origin
.y
-=TAB_HEIGHT_NORMAL
/2;
894 rc
.size
.height
+=TAB_HEIGHT_NORMAL
/2;
897 HIThemeDrawTabPane(&rc
, &aTabPaneDrawInfo
, mrContext
, kHIThemeOrientationNormal
);
905 HIThemeTabDrawInfo aTabItemDrawInfo
;
906 aTabItemDrawInfo
.version
=1;
907 aTabItemDrawInfo
.style
=kThemeTabNonFront
;
908 aTabItemDrawInfo
.direction
=kThemeTabNorth
;
909 aTabItemDrawInfo
.size
=kHIThemeTabSizeNormal
;
910 aTabItemDrawInfo
.adornment
=kHIThemeTabAdornmentTrailingSeparator
;
912 if(nState
& CTRL_STATE_SELECTED
) {
913 aTabItemDrawInfo
.style
=kThemeTabFront
;
915 if(nState
& CTRL_STATE_FOCUSED
) {
916 aTabItemDrawInfo
.adornment
|=kHIThemeTabAdornmentFocus
;
919 //first, last or middle tab
920 aTabItemDrawInfo
.position
=kHIThemeTabPositionMiddle
;
922 TabitemValue
*aTabValue
=(TabitemValue
*) aValue
.getOptionalVal();
923 unsigned int nAlignement
=aTabValue
->mnAlignment
;
924 //TABITEM_LEFTALIGNED (and TABITEM_RIGHTALIGNED) for the leftmost (or rightmost) tab
925 //when there are several lines of tabs because there is only one first tab and one
926 //last tab and TABITEM_FIRST_IN_GROUP (and TABITEM_LAST_IN_GROUP) because when the
927 //line width is different from window width, there may not be TABITEM_RIGHTALIGNED
928 if((nAlignement
& TABITEM_LEFTALIGNED
)&&(nAlignement
& TABITEM_RIGHTALIGNED
)) //tab alone
929 aTabItemDrawInfo
.position
=kHIThemeTabPositionOnly
;
930 else if((nAlignement
& TABITEM_LEFTALIGNED
)||(nAlignement
& TABITEM_FIRST_IN_GROUP
))
931 aTabItemDrawInfo
.position
=kHIThemeTabPositionFirst
;
932 else if((nAlignement
& TABITEM_RIGHTALIGNED
)||(nAlignement
& TABITEM_LAST_IN_GROUP
))
933 aTabItemDrawInfo
.position
=kHIThemeTabPositionLast
;
937 if( Application::GetSettings().GetLayoutRTL() ) {
938 if( aTabItemDrawInfo
.position
== kHIThemeTabPositionFirst
)
939 aTabItemDrawInfo
.position
= kHIThemeTabPositionLast
;
940 else if( aTabItemDrawInfo
.position
== kHIThemeTabPositionLast
)
941 aTabItemDrawInfo
.position
= kHIThemeTabPositionFirst
;
944 rc
.size
.width
+=2;//because VCL has 2 empty pixels between 2 tabs
947 HIThemeDrawTab(&rc
, &aTabItemDrawInfo
, mrContext
, kHIThemeOrientationNormal
, &rc
);
957 case PART_ENTIRE_CONTROL
:
958 case PART_BUTTON_DOWN
:
960 HIThemeButtonDrawInfo aListInfo
;
961 aListInfo
.version
= 0;
962 aListInfo
.kind
= kThemePopupButton
;
963 aListInfo
.state
= getState( nState
);//kThemeStateInactive -> greyed
964 aListInfo
.value
= kThemeButtonOn
;
966 aListInfo
.adornment
= kThemeAdornmentDefault
;
967 if( (nState
& CTRL_STATE_FOCUSED
) != 0 )
968 aListInfo
.adornment
|= kThemeAdornmentFocus
;
970 HIThemeDrawButton(&rc
, &aListInfo
, mrContext
, kHIThemeOrientationNormal
,&rc
);
976 HIThemeFrameDrawInfo aTextDrawInfo
;
977 aTextDrawInfo
.version
=0;
978 aTextDrawInfo
.kind
=kHIThemeFrameTextFieldSquare
;
979 aTextDrawInfo
.state
=getState( nState
);
980 aTextDrawInfo
.isFocused
=false;
982 rc
.size
.width
+=1;//else there's a white space because aqua theme hasn't a 3D border
984 HIThemeDrawFrame(&rc
, &aTextDrawInfo
, mrContext
, kHIThemeOrientationNormal
);
986 if(nState
& CTRL_STATE_FOCUSED
) HIThemeDrawFocusRect(&rc
, true, mrContext
, kHIThemeOrientationNormal
);
995 case CTRL_MULTILINE_EDITBOX
:
997 HIThemeFrameDrawInfo aTextDrawInfo
;
998 aTextDrawInfo
.version
=0;
999 aTextDrawInfo
.kind
=kHIThemeFrameTextFieldSquare
;
1000 aTextDrawInfo
.state
=getState( nState
);
1001 aTextDrawInfo
.isFocused
=false;
1003 rc
.size
.width
+= 1; // else there may be a white space because aqua theme hasn't a 3D border
1004 // change rc so that the frame will encompass only the content region
1005 // see counterpart in GetNativeControlRegion
1007 rc
.size
.height
+= 2;
1009 //CGContextSetFillColorWithColor
1010 CGContextFillRect (mrContext
, CGRectMake(rc
.origin
.x
, rc
.origin
.y
, rc
.size
.width
, rc
.size
.height
));
1011 //fill a white background, because drawFrame only draws the border
1013 HIThemeDrawFrame(&rc
, &aTextDrawInfo
, mrContext
, kHIThemeOrientationNormal
);
1015 if(nState
& CTRL_STATE_FOCUSED
) HIThemeDrawFocusRect(&rc
, true, mrContext
, kHIThemeOrientationNormal
);
1023 if(nPart
== PART_ENTIRE_CONTROL
)
1026 HIThemeFrameDrawInfo aTextDrawInfo
;
1027 aTextDrawInfo
.version
=0;
1028 aTextDrawInfo
.kind
=kHIThemeFrameTextFieldSquare
;
1029 aTextDrawInfo
.state
=getState( nState
);
1030 aTextDrawInfo
.isFocused
=false;
1032 //rc.size.width contains the full size of the spinbox ie textfield + button
1033 //so we remove the button width and the space between the button and the textfield
1034 rc
.size
.width
-= SPIN_BUTTON_SPACE
+ SPIN_BUTTON_WIDTH
+ 2*FOCUS_RING_WIDTH
;
1035 rc
.origin
.x
+= FOCUS_RING_WIDTH
;
1036 rc
.origin
.y
+= FOCUS_RING_WIDTH
;
1038 //CGContextSetFillColorWithColor
1039 CGContextFillRect (mrContext
, CGRectMake(rc
.origin
.x
, rc
.origin
.y
, rc
.size
.width
, rc
.size
.height
));
1040 //fill a white background, because drawFrame only draws the border
1042 HIThemeDrawFrame(&rc
, &aTextDrawInfo
, mrContext
, kHIThemeOrientationNormal
);
1044 if(nState
& CTRL_STATE_FOCUSED
) HIThemeDrawFocusRect(&rc
, true, mrContext
, kHIThemeOrientationNormal
);
1047 SpinbuttonValue
* pSpinButtonVal
= (SpinbuttonValue
*)(aValue
.getOptionalVal());
1048 ControlState nUpperState
= CTRL_STATE_ENABLED
;//state of the upper button
1049 ControlState nLowerState
= CTRL_STATE_ENABLED
;//and of the lower button
1050 if(pSpinButtonVal
) {//pSpinButtonVal is sometimes null
1051 nUpperState
= (ControlState
) pSpinButtonVal
->mnUpperState
;
1052 nLowerState
= (ControlState
) pSpinButtonVal
->mnLowerState
;
1055 if( pSpinButtonVal
)
1057 HIThemeButtonDrawInfo aSpinInfo
;
1058 aSpinInfo
.kind
= kThemeIncDecButton
;
1059 aSpinInfo
.state
= kThemeStateActive
;
1060 if(nUpperState
& CTRL_STATE_PRESSED
)
1061 aSpinInfo
.state
= kThemeStatePressedUp
;
1062 else if(nLowerState
& CTRL_STATE_PRESSED
)
1063 aSpinInfo
.state
= kThemeStatePressedDown
;
1064 else if((nUpperState
& ~CTRL_STATE_ENABLED
)||(nLowerState
& ~CTRL_STATE_ENABLED
))
1065 aSpinInfo
.state
= kThemeStateInactive
;
1066 else if((nUpperState
& CTRL_STATE_ROLLOVER
)||(nLowerState
& CTRL_STATE_ROLLOVER
))
1067 aSpinInfo
.state
= kThemeStateRollover
;
1069 Rectangle
aSpinRect( pSpinButtonVal
->maUpperRect
);
1070 aSpinRect
.Union( pSpinButtonVal
->maLowerRect
);
1071 HIRect buttonRc
= ImplGetHIRectFromRectangle(aSpinRect
);
1073 // FIXME: without this fuzz factor there is some unwanted clipping
1074 if( Application::GetSettings().GetLayoutRTL() )
1075 buttonRc
.origin
.x
-= FOCUS_RING_WIDTH
- CLIP_FUZZ
;
1077 buttonRc
.origin
.x
+= FOCUS_RING_WIDTH
+ CLIP_FUZZ
;
1079 switch( aValue
.getTristateVal() )
1081 case BUTTONVALUE_ON
: aSpinInfo
.value
= kThemeButtonOn
;
1083 case BUTTONVALUE_OFF
: aSpinInfo
.value
= kThemeButtonOff
;
1085 case BUTTONVALUE_MIXED
:
1086 case BUTTONVALUE_DONTKNOW
:
1087 default: aSpinInfo
.value
= kThemeButtonMixed
;
1091 aSpinInfo
.adornment
= ( ((nUpperState
& CTRL_STATE_DEFAULT
) != 0 ) ||
1092 ((nLowerState
& CTRL_STATE_DEFAULT
) != 0 )) ?
1093 kThemeAdornmentDefault
:
1094 kThemeAdornmentNone
;
1095 if( ((nUpperState
& CTRL_STATE_FOCUSED
) != 0 ) || ((nLowerState
& CTRL_STATE_FOCUSED
) != 0 ))
1096 aSpinInfo
.adornment
|= kThemeAdornmentFocus
;
1098 HIThemeDrawButton( &buttonRc
, &aSpinInfo
, mrContext
, kHIThemeOrientationNormal
, NULL
);
1109 USHORT nStyle
= aValue
.getNumericVal();
1110 if( nPart
== PART_BORDER
) {
1111 if(!( nStyle
& FRAME_DRAW_MENU
) && !(nStyle
& FRAME_DRAW_WINDOWBORDER
) )
1113 // #i84756# strange effects start to happen when HIThemeDrawFrame
1114 // meets the border of the window. These can be avoided by clipping
1115 // to the boundary of the frame
1116 if( rc
.origin
.y
+ rc
.size
.height
>= mpFrame
->maGeometry
.nHeight
-3 )
1118 CGMutablePathRef rPath
= CGPathCreateMutable();
1119 CGPathAddRect( rPath
, NULL
, CGRectMake( 0, 0, mpFrame
->maGeometry
.nWidth
-1, mpFrame
->maGeometry
.nHeight
-1 ) );
1121 CGContextBeginPath( mrContext
);
1122 CGContextAddPath( mrContext
, rPath
);
1123 CGContextClip( mrContext
);
1124 CGPathRelease( rPath
);
1127 HIThemeFrameDrawInfo aTextDrawInfo
;
1128 aTextDrawInfo
.version
=0;
1129 aTextDrawInfo
.kind
=kHIThemeFrameListBox
;
1130 aTextDrawInfo
.state
=kThemeStateActive
;
1131 aTextDrawInfo
.isFocused
=false;
1133 HIThemeDrawFrame(&rc
, &aTextDrawInfo
, mrContext
, kHIThemeOrientationNormal
);
1143 //do nothing as there isn't net for listviews on macos
1150 CGContextRestoreGState( mrContext
);
1152 /* #i90291# in most cases invalidating the whole control region instead
1153 of just the unclipped part of it is sufficient (and probably faster).
1154 However for the window background we should not unnecessarily enlarge
1155 the really changed rectangle since the difference is usually quite high
1156 (the background is always drawn as a whole since we don't know anything
1157 about its possible contents)
1159 if( nType
== CTRL_WINDOW_BACKGROUND
)
1161 CGRect aRect
= { { 0, 0 }, { 0, 0 } };
1163 aRect
= CGPathGetBoundingBox( mxClipPath
);
1164 if( aRect
.size
.width
!= 0 && aRect
.size
.height
!= 0 )
1165 buttonRect
.Intersection( Rectangle( Point( static_cast<long int>(aRect
.origin
.x
),
1166 static_cast<long int>(aRect
.origin
.y
) ),
1167 Size( static_cast<long int>(aRect
.size
.width
),
1168 static_cast<long int>(aRect
.size
.height
) ) ) );
1171 RefreshRect( buttonRect
.Left(), buttonRect
.Top(), buttonRect
.GetWidth(), buttonRect
.GetHeight() );
1177 * DrawNativeControlText()
1179 * OPTIONAL. Draws the requested text for the control described by nPart/nState.
1180 * Used if text not drawn by DrawNativeControl().
1182 * rControlRegion: The bounding region of the complete control in VCL frame coordinates.
1183 * aValue: An optional value (tristate/numerical/string)
1184 * rControlHandle: Carries platform dependent data and is maintained by the AquaSalGraphics implementation.
1185 * aCaption: A caption or title string (like button text etc)
1187 BOOL
AquaSalGraphics::drawNativeControlText( ControlType nType
, ControlPart nPart
, const Region
& rControlRegion
,
1188 ControlState nState
, const ImplControlValue
& aValue
,
1189 SalControlHandle
& rControlHandle
, const rtl::OUString
& aCaption
)
1196 * GetNativeControlRegion()
1198 * If the return value is TRUE, rNativeBoundingRegion
1199 * contains the true bounding region covered by the control
1200 * including any adornment, while rNativeContentRegion contains the area
1201 * within the control that can be safely drawn into without drawing over
1202 * the borders of the control.
1204 * rControlRegion: The bounding region of the control in VCL frame coordinates.
1205 * aValue: An optional value (tristate/numerical/string)
1206 * rControlHandle: Carries platform dependent data and is maintained by the AquaSalGraphics implementation.
1207 * aCaption: A caption or title string (like button text etc)
1209 BOOL
AquaSalGraphics::getNativeControlRegion( ControlType nType
, ControlPart nPart
, const Region
& rControlRegion
, ControlState nState
,
1210 const ImplControlValue
& aValue
, SalControlHandle
& rControlHandle
, const rtl::OUString
& aCaption
,
1211 Region
&rNativeBoundingRegion
, Region
&rNativeContentRegion
)
1214 BOOL toReturn
= FALSE
;
1216 short x
= rControlRegion
.GetBoundRect().Left();
1217 short y
= rControlRegion
.GetBoundRect().Top();
1220 sal_uInt8 nBorderCleanup
= 0;
1224 case CTRL_SCROLLBAR
:
1227 if( AquaGetScrollRect( /* m_nScreen */ nPart
, rControlRegion
.GetBoundRect(), aRect
) )
1230 rNativeBoundingRegion
= aRect
;
1231 rNativeContentRegion
= aRect
;
1236 case CTRL_PUSHBUTTON
:
1237 case CTRL_RADIOBUTTON
:
1240 if ( nType
== CTRL_PUSHBUTTON
)
1242 w
= rControlRegion
.GetBoundRect().GetWidth();
1243 h
= rControlRegion
.GetBoundRect().GetHeight();
1247 // checkbox and radio borders need cleanup after unchecking them
1250 // TEXT_SEPARATOR to respect Aqua HIG
1251 w
= BUTTON_WIDTH
+ TEXT_SEPARATOR
;
1256 rNativeContentRegion
= Rectangle( Point( x
, y
), Size( w
, h
+ nBorderCleanup
) );
1257 rNativeBoundingRegion
= Rectangle( Point( x
, y
), Size( w
, h
) );
1264 Rectangle
aRect( rControlRegion
.GetBoundRect() );
1265 if( aRect
.GetHeight() < 16 )
1266 aRect
.Bottom() = aRect
.Top() + 9; // values taken from HIG for medium progress
1268 aRect
.Bottom() = aRect
.Top() + 15; // values taken from HIG for large progress
1269 rNativeBoundingRegion
= aRect
;
1270 rNativeContentRegion
= aRect
;
1275 case CTRL_INTROPROGRESS
:
1277 Rectangle
aRect( rControlRegion
.GetBoundRect() );
1278 aRect
.Bottom() = aRect
.Top() + INTRO_PROGRESS_HEIGHT
; // values taken from HIG for medium progress
1279 rNativeBoundingRegion
= aRect
;
1280 rNativeContentRegion
= aRect
;
1287 w
= rControlRegion
.GetBoundRect().GetWidth() + 2*TAB_TEXT_OFFSET
- 2*VCL_TAB_TEXT_OFFSET
;
1289 #ifdef OLD_TAB_STYLE
1290 h
= TAB_HEIGHT_NORMAL
;
1292 h
= TAB_HEIGHT_NORMAL
+2;
1294 rNativeContentRegion
= Rectangle( Point( x
, y
), Size( w
, h
) );
1295 rNativeBoundingRegion
= Rectangle( Point( x
, y
), Size( w
, h
) );
1303 w
= rControlRegion
.GetBoundRect().GetWidth();
1304 if( w
< 3+2*FOCUS_RING_WIDTH
)
1305 w
= 3+2*FOCUS_RING_WIDTH
;
1306 h
= TEXT_EDIT_HEIGHT_NORMAL
;
1308 rNativeContentRegion
= Rectangle( Point( x
+FOCUS_RING_WIDTH
, y
+FOCUS_RING_WIDTH
), Size( w
-2*FOCUS_RING_WIDTH
-2, h
-2 ) );
1309 rNativeBoundingRegion
= Rectangle( Point( x
, y
), Size( w
, h
+2*FOCUS_RING_WIDTH
) );
1317 if( nPart
== PART_ENTIRE_CONTROL
)
1319 w
= rControlRegion
.GetBoundRect().GetWidth();
1320 h
= COMBOBOX_HEIGHT_NORMAL
;//listboxes and comboxes have the same height
1322 rNativeContentRegion
= Rectangle( Point( x
+FOCUS_RING_WIDTH
, y
+FOCUS_RING_WIDTH
), Size( w
-2*FOCUS_RING_WIDTH
, h
) );
1323 rNativeBoundingRegion
= Rectangle( Point( x
, y
), Size( w
, h
+2*FOCUS_RING_WIDTH
) );
1327 else if( nPart
== PART_BUTTON_DOWN
)
1329 w
= rControlRegion
.GetBoundRect().GetWidth();
1330 if( w
< 3+2*FOCUS_RING_WIDTH
)
1331 w
= 3+2*FOCUS_RING_WIDTH
;
1332 h
= COMBOBOX_HEIGHT_NORMAL
;//listboxes and comboxes have the same height
1334 x
+= w
-DROPDOWN_BUTTON_WIDTH
- FOCUS_RING_WIDTH
;
1335 y
+= FOCUS_RING_WIDTH
;
1336 w
= DROPDOWN_BUTTON_WIDTH
;
1338 rNativeContentRegion
= Rectangle( Point( x
, y
), Size( w
, h
) );
1339 rNativeBoundingRegion
= Rectangle( Point( x
, y
), Size( w
+FOCUS_RING_WIDTH
, h
+2*FOCUS_RING_WIDTH
) );
1343 else if( nPart
== PART_SUB_EDIT
)
1345 w
= rControlRegion
.GetBoundRect().GetWidth();
1346 h
= COMBOBOX_HEIGHT_NORMAL
;//listboxes and comboxes have the same height
1348 x
+= FOCUS_RING_WIDTH
;
1349 x
+= 3; // add an offset for rounded borders
1350 y
+= 2; // don't draw into upper border
1351 y
+= FOCUS_RING_WIDTH
;
1352 w
-= 3 + DROPDOWN_BUTTON_WIDTH
+ 2*FOCUS_RING_WIDTH
;
1353 if( nType
== CTRL_LISTBOX
)
1354 w
-= 9; // HIG specifies 9 units distance between dropdown button area and content
1355 h
-= 4; // don't draw into lower border
1357 rNativeContentRegion
= Rectangle( Point( x
, y
), Size( w
, h
) );
1358 rNativeBoundingRegion
= Rectangle( Point( x
, y
), Size( w
+FOCUS_RING_WIDTH
, h
+2*FOCUS_RING_WIDTH
) );
1365 if( nPart
== PART_ENTIRE_CONTROL
) {
1366 w
= rControlRegion
.GetBoundRect().GetWidth();
1367 if( w
< 3+2*FOCUS_RING_WIDTH
+SPIN_BUTTON_SPACE
+SPIN_BUTTON_WIDTH
)
1368 w
= 3+2*FOCUS_RING_WIDTH
+SPIN_BUTTON_SPACE
+SPIN_BUTTON_WIDTH
;
1369 h
= TEXT_EDIT_HEIGHT_NORMAL
;
1371 rNativeContentRegion
= Rectangle( Point( x
+FOCUS_RING_WIDTH
, y
), Size( w
-2*FOCUS_RING_WIDTH
, h
) );
1372 rNativeBoundingRegion
= Rectangle( Point( x
, y
), Size( w
, h
+2*FOCUS_RING_WIDTH
) );
1376 else if( nPart
== PART_SUB_EDIT
) {
1377 w
= rControlRegion
.GetBoundRect().GetWidth() - SPIN_BUTTON_SPACE
- SPIN_BUTTON_WIDTH
;
1378 h
= TEXT_EDIT_HEIGHT_NORMAL
;
1379 x
+= 4; // add an offset for rounded borders
1380 y
+= 2; // don't draw into upper border
1381 w
-= 8; // offset for left and right rounded border
1382 h
-= 4; // don't draw into upper or ower border
1384 rNativeContentRegion
= Rectangle( Point( x
+ FOCUS_RING_WIDTH
, y
+ FOCUS_RING_WIDTH
), Size( w
- 2* FOCUS_RING_WIDTH
, h
) );
1385 rNativeBoundingRegion
= Rectangle( Point( x
, y
), Size( w
, h
+2*FOCUS_RING_WIDTH
) );
1389 else if( nPart
== PART_BUTTON_UP
) {
1390 //rControlRegion.GetBoundRect().GetWidth() contains the width of the full control
1391 //ie the width of the textfield + button
1392 //x is the position of the left corner of the full control
1393 x
+= rControlRegion
.GetBoundRect().GetWidth() - SPIN_BUTTON_WIDTH
- SPIN_BUTTON_SPACE
- CLIP_FUZZ
;
1394 y
+= FOCUS_RING_WIDTH
- CLIP_FUZZ
;
1395 w
= SPIN_BUTTON_WIDTH
+ 2*CLIP_FUZZ
;
1396 h
= SPIN_UPPER_BUTTON_HEIGHT
+ 2*CLIP_FUZZ
;
1398 rNativeContentRegion
= Rectangle( Point( x
, y
), Size( w
, h
) );
1399 rNativeBoundingRegion
= Rectangle( Point( x
, y
), Size( w
, h
) );
1403 else if( nPart
== PART_BUTTON_DOWN
) {
1404 x
+= rControlRegion
.GetBoundRect().GetWidth() - SPIN_BUTTON_WIDTH
- SPIN_BUTTON_SPACE
- CLIP_FUZZ
;
1405 y
+= SPIN_UPPER_BUTTON_HEIGHT
+ FOCUS_RING_WIDTH
- CLIP_FUZZ
;
1406 w
= SPIN_BUTTON_WIDTH
+ 2*CLIP_FUZZ
;
1407 h
= SPIN_LOWER_BUTTON_HEIGHT
+ 2*CLIP_FUZZ
;
1409 rNativeContentRegion
= Rectangle( Point( x
, y
), Size( w
, h
) );
1410 rNativeBoundingRegion
= Rectangle( Point( x
, y
), Size( w
, h
) );
1417 USHORT nStyle
= aValue
.getNumericVal();
1418 if( ( nPart
== PART_BORDER
) &&
1419 !( nStyle
& (FRAME_DRAW_MENU
| FRAME_DRAW_WINDOWBORDER
| FRAME_DRAW_BORDERWINDOWBORDER
) ) )
1421 Rectangle aRect
= rControlRegion
.GetBoundRect();
1422 if( nStyle
& FRAME_DRAW_DOUBLEIN
)
1426 //rRect.Right() -= 1;
1427 //rRect.Bottom() -= 1;
1434 aRect
.Bottom() -= 1;
1437 rNativeContentRegion
= aRect
;
1438 rNativeBoundingRegion
= aRect
;
1446 case CTRL_MENU_POPUP
:
1448 if(( nPart
== PART_MENU_ITEM_CHECK_MARK
)||( nPart
== PART_MENU_ITEM_RADIO_MARK
)) {
1451 h
=10;//dimensions of the mark (10px font)
1453 rNativeContentRegion
= Rectangle( Point( x
, y
), Size( w
, h
) );
1454 rNativeBoundingRegion
= Rectangle( Point( x
, y
), Size( w
, h
) );