diff --git a/.gitattributes b/.gitattributes index 299d9ec6dc..cb5ff573b3 100644 --- a/.gitattributes +++ b/.gitattributes @@ -6350,6 +6350,7 @@ lcl/interfaces/cocoa/cocoalclintfh.inc svneol=native#text/pascal lcl/interfaces/cocoa/cocoaobject.inc svneol=native#text/pascal lcl/interfaces/cocoa/cocoaprivate.pp svneol=native#text/plain lcl/interfaces/cocoa/cocoaproc.pas svneol=native#text/pascal +lcl/interfaces/cocoa/cocoathemes.pas svneol=native#text/plain lcl/interfaces/cocoa/cocoatrayicon.inc svneol=native#text/pascal lcl/interfaces/cocoa/cocoautils.pas svneol=native#text/plain lcl/interfaces/cocoa/cocoawinapi.inc svneol=native#text/pascal diff --git a/lcl/interfaces/cocoa/cocoaint.pas b/lcl/interfaces/cocoa/cocoaint.pas index 7dc1ba7d77..78b5ca25ab 100644 --- a/lcl/interfaces/cocoa/cocoaint.pas +++ b/lcl/interfaces/cocoa/cocoaint.pas @@ -36,7 +36,7 @@ uses CocoaProc, // LCL LCLStrConsts, LMessages, LCLMessageGlue, LCLProc, LCLIntf, LCLType, - Controls, Forms, + Controls, Forms, Themes, IntfGraphics, Graphics, CocoaWSFactory; type @@ -84,6 +84,7 @@ type DialogType: longint; Buttons: PLongint; ButtonCount, DefaultIndex, EscapeResult: Longint): Longint; override; function GetAppHandle: THandle; override; + function CreateThemeServices: TThemeServices; override; public constructor Create; override; destructor Destroy; override; @@ -138,7 +139,8 @@ var implementation uses - CocoaCaret; + CocoaCaret, + CocoaThemes; // the implementation of the utility methods {$I cocoaobject.inc} diff --git a/lcl/interfaces/cocoa/cocoaobject.inc b/lcl/interfaces/cocoa/cocoaobject.inc index 073bc44dbe..6ee32948b0 100644 --- a/lcl/interfaces/cocoa/cocoaobject.inc +++ b/lcl/interfaces/cocoa/cocoaobject.inc @@ -412,6 +412,11 @@ begin Result:=THandle(NSApp); end; +function TCocoaWidgetSet.CreateThemeServices: TThemeServices; +begin + Result:=TCocoaThemeServices.Create; +end; + function TCocoaWidgetSet.DCGetPixel(CanvasHandle: HDC; X, Y: integer): TGraphicsColor; begin Result:=0; diff --git a/lcl/interfaces/cocoa/cocoathemes.pas b/lcl/interfaces/cocoa/cocoathemes.pas new file mode 100644 index 0000000000..9ec89755ff --- /dev/null +++ b/lcl/interfaces/cocoa/cocoathemes.pas @@ -0,0 +1,662 @@ +{ ----------------------------------------- + CocoaThemes.pas - Cocoa Theme support + ----------------------------------------- + + See Themes.pas for licencing and other further information. +} +unit CocoaThemes; + +{$mode objfpc}{$H+} + +interface + +uses + // rtl + Types, Classes, SysUtils, + // carbon bindings + //MacOSAll, + // lcl + LCLType, LCLProc, LCLIntf, Graphics, Themes, TmSchema; + // widgetset + //CarbonProc, CarbonCanvas, CarbonGDIObjects; + +type + { TCocoaThemeServices } + + TCocoaThemeServices = class(TThemeServices) + private + protected +(* + function InitThemes: Boolean; override; + function UseThemes: Boolean; override; + function ThemedControlsEnabled: Boolean; override; + procedure InternalDrawParentBackground({%H-}Window: HWND; {%H-}Target: HDC; {%H-}Bounds: PRect); override; + + function GetDrawState(Details: TThemedElementDetails): ThemeDrawState; + function DrawButtonElement(DC: TCarbonDeviceContext; Details: TThemedElementDetails; R: TRect; {%H-}ClipRect: PRect): TRect; + function DrawComboBoxElement(DC: TCarbonDeviceContext; Details: TThemedElementDetails; R: TRect; {%H-}ClipRect: PRect): TRect; + function DrawHeaderElement(DC: TCarbonDeviceContext; Details: TThemedElementDetails; R: TRect; {%H-}ClipRect: PRect): TRect; + function DrawRebarElement(DC: TCarbonDeviceContext; Details: TThemedElementDetails; R: TRect; {%H-}ClipRect: PRect): TRect; + function DrawToolBarElement(DC: TCarbonDeviceContext; Details: TThemedElementDetails; R: TRect; {%H-}ClipRect: PRect): TRect; + function DrawTreeviewElement(DC: TCarbonDeviceContext; Details: TThemedElementDetails; R: TRect; {%H-}ClipRect: PRect): TRect; + function DrawWindowElement(DC: TCarbonDeviceContext; Details: TThemedElementDetails; R: TRect; {%H-}ClipRect: PRect): TRect; +*) + public + procedure DrawElement(DC: HDC; Details: TThemedElementDetails; const R: TRect; ClipRect: PRect); override; +(* + procedure DrawEdge({%H-}DC: HDC; {%H-}Details: TThemedElementDetails; const {%H-}R: TRect; {%H-}Edge, {%H-}Flags: Cardinal; {%H-}AContentRect: PRect); override; + procedure DrawIcon({%H-}DC: HDC; {%H-}Details: TThemedElementDetails; const {%H-}R: TRect; {%H-}himl: HIMAGELIST; {%H-}Index: Integer); override; + procedure DrawText({%H-}DC: HDC; {%H-}Details: TThemedElementDetails; const {%H-}S: String; {%H-}R: TRect; {%H-}Flags, {%H-}Flags2: Cardinal); override; + + function ContentRect({%H-}DC: HDC; Details: TThemedElementDetails; BoundingRect: TRect): TRect; override; + function HasTransparentParts({%H-}Details: TThemedElementDetails): Boolean; override; + function GetDetailSize(Details: TThemedElementDetails): TSize; override; + function GetOption(AOption: TThemeOption): Integer; override; +*) + end; + +implementation + +{ TCocoaThemeServices } +(* +{------------------------------------------------------------------------------ + Method: TCarbonThemeServices.GetDrawState + Params: Details - Details for themed element + Returns: Draw state of the themed element passed + ------------------------------------------------------------------------------} +function TCarbonThemeServices.GetDrawState(Details: TThemedElementDetails): ThemeDrawState; +{ + kThemeStateInactive = 0; + kThemeStateActive = 1; + kThemeStatePressed = 2; + kThemeStateRollover = 6; + kThemeStateUnavailable = 7; + kThemeStateUnavailableInactive = 8; + + kThemeStatePressedUp = 2; draw with up pressed (increment/decrement buttons) + kThemeStatePressedDown = 3; draw with down pressed (increment/decrement buttons) + +} +begin + if IsDisabled(Details) then + Result := kThemeStateInactive + else + if IsPushed(Details) then + Result := kThemeStatePressed + else + if IsHot(Details) then + Result := kThemeStateRollover + else + Result := kThemeStateActive; +end; + +{------------------------------------------------------------------------------ + Method: TCarbonThemeServices.DrawComboBoxElement + Params: DC - Carbon device context + Details - Details for themed element + R - Bounding rectangle + ClipRect - Clipping rectangle + Returns: ClientRect + + Draws a ComboBox element with native Carbon look + ------------------------------------------------------------------------------} +function TCarbonThemeServices.DrawComboBoxElement(DC: TCarbonDeviceContext; + Details: TThemedElementDetails; R: TRect; ClipRect: PRect): TRect; +var + ButtonDrawInfo: HIThemeButtonDrawInfo; + BoundsRect: HIRect; + NewHeight: Integer; + BtnWidth: Integer; +begin + ButtonDrawInfo.version := 0; + ButtonDrawInfo.State := GetDrawState(Details); + ButtonDrawInfo.value := kThemeButtonOn; + ButtonDrawInfo.adornment := kThemeAdornmentNone; + + BoundsRect := RectToCGRect(R); + + NewHeight := GetCarbonThemeMetric(kThemeMetricPopupButtonHeight); + BtnWidth := GetCarbonThemeMetric(kThemeMetricComboBoxLargeDisclosureWidth); + ButtonDrawInfo.kind := kThemeComboBox; + if BoundsRect.size.height < NewHeight then begin + NewHeight := GetCarbonThemeMetric(kThemeMetricSmallPopupButtonHeight); + BtnWidth := GetCarbonThemeMetric(kThemeMetricComboBoxSmallDisclosureWidth); + ButtonDrawInfo.kind := kThemeComboBoxSmall; + end; + if BoundsRect.size.height < NewHeight then begin + NewHeight := GetCarbonThemeMetric(kThemeMetricMiniPopupButtonHeight); + BtnWidth := GetCarbonThemeMetric(kThemeMetricComboBoxMiniDisclosureWidth); + ButtonDrawInfo.kind := kThemeComboBoxMini; + end; + + OSError( + HIThemeDrawButton(BoundsRect, ButtonDrawInfo, DC.CGContext, + kHIThemeOrientationNormal, nil), + Self, 'DrawComboBoxElement', 'HIThemeDrawButton'); + + BoundsRect.size.height := NewHeight + 1; + BoundsRect.size.width := BoundsRect.size.width - BtnWidth; + Result := CGRectToRect(BoundsRect); +end; + +{------------------------------------------------------------------------------ + Method: TCarbonThemeServices.DrawButtonElement + Params: DC - Carbon device context + Details - Details for themed element + R - Bounding rectangle + ClipRect - Clipping rectangle + Returns: ClientRect + + Draws a button element with native Carbon look + ------------------------------------------------------------------------------} +function TCarbonThemeServices.DrawButtonElement(DC: TCarbonDeviceContext; + Details: TThemedElementDetails; R: TRect; ClipRect: PRect): TRect; +const + ButtonMap: array[BP_PUSHBUTTON..BP_USERBUTTON] of ThemeButtonKind = + ( +{BP_PUSHBUTTON } kThemeRoundedBevelButton, +{BP_RADIOBUTTON} kThemeRadioButton, +{BP_CHECKBOX } kThemeCheckBox, +{BP_GROUPBOX } kHIThemeGroupBoxKindPrimary, // ?? +{BP_USERBUTTON } kThemeRoundedBevelButton + ); +var + ButtonDrawInfo: HIThemeButtonDrawInfo; + // we can do so because GroupDrawIndo have common fields with ButtonDrawInfo + GroupDrawInfo: HIThemeGroupBoxDrawInfo absolute ButtonDrawInfo; + LabelRect: HIRect; +begin + ButtonDrawInfo.version := 0; + ButtonDrawInfo.State := GetDrawState(Details); + ButtonDrawInfo.kind := ButtonMap[Details.Part]; + if IsMixed(Details) then + ButtonDrawInfo.value := kThemeButtonMixed + else + if IsChecked(Details) then + ButtonDrawInfo.value := kThemeButtonOn + else + ButtonDrawInfo.value := kThemeButtonOff; + ButtonDrawInfo.adornment := kThemeAdornmentNone; + + LabelRect := RectToCGRect(R); + + if Details.Part = BP_GROUPBOX then + OSError( + HIThemeDrawGroupBox(LabelRect, GroupDrawInfo, DC.CGContext, + kHIThemeOrientationNormal), + Self, 'DrawButtonElement', 'HIThemeDrawGroupBox') + else + OSError( + HIThemeDrawButton(LabelRect, ButtonDrawInfo, DC.CGContext, + kHIThemeOrientationNormal, @LabelRect), + Self, 'DrawButtonElement', 'HIThemeDrawButton'); + + Result := CGRectToRect(LabelRect); +end; + +{------------------------------------------------------------------------------ + Method: TCarbonThemeServices.DrawHeaderElement + Params: DC - Carbon device context + Details - Details for themed element + R - Bounding rectangle + ClipRect - Clipping rectangle + Returns: ClientRect + + Draws a header (THeaderControl same as ListView header) element with native Carbon look + ------------------------------------------------------------------------------} +function TCarbonThemeServices.DrawHeaderElement(DC: TCarbonDeviceContext; + Details: TThemedElementDetails; R: TRect; ClipRect: PRect): TRect; +var + ButtonDrawInfo: HIThemeButtonDrawInfo; + PaintRect: HIRect; +begin + ButtonDrawInfo.version := 0; + ButtonDrawInfo.State := GetDrawState(Details); + ButtonDrawInfo.kind := kThemeBevelButtonSmall;//kThemeListHeaderButton; + ButtonDrawInfo.adornment := kThemeAdornmentNone; + + PaintRect := RectToCGRect(R); + + OSError( + HIThemeDrawButton(PaintRect, ButtonDrawInfo, DC.CGContext, + kHIThemeOrientationNormal, @PaintRect), + Self, 'DrawButtonElement', 'HIThemeDrawButton'); + + Result := CGRectToRect(PaintRect); +end; + +{------------------------------------------------------------------------------ + Method: TCarbonThemeServices.DrawRebarElement + Params: DC - Carbon device context + Details - Details for themed element + R - Bounding rectangle + ClipRect - Clipping rectangle + Returns: ClientRect + + Draws a rebar element (splitter) with native Carbon look + ------------------------------------------------------------------------------} +function TCarbonThemeServices.DrawRebarElement(DC: TCarbonDeviceContext; + Details: TThemedElementDetails; R: TRect; ClipRect: PRect): TRect; +var + SplitterInfo: HIThemeSplitterDrawInfo; + PlacardInfo: HIThemePlacardDrawInfo; + ARect: HIRect; +const + SName = 'DrawRebarElement'; +begin + ARect := RectToCGRect(R); + if Details.Part in [RP_GRIPPER, RP_GRIPPERVERT] then + begin + SplitterInfo.version := 0; + SplitterInfo.State := kThemeStateActive; + SplitterInfo.adornment := kHiThemeSplitterAdornmentNone; + + OSError( + HIThemeDrawPaneSplitter(ARect, SplitterInfo, DC.CGContext, kHIThemeOrientationNormal), + Self, SName, 'HIThemeDrawPaneSplitter'); + end + else + if Details.Part = RP_BAND then + begin + PlacardInfo.version := 0; + PlacardInfo.State := GetDrawState(Details); + + OSError( + HIThemeDrawPlacard(ARect, PlacardInfo, DC.CGContext, kHIThemeOrientationNormal), + Self, SName, 'HIThemeDrawPlacard'); + end; + + Result := CGRectToRect(ARect); +end; + +{------------------------------------------------------------------------------ + Method: TCarbonThemeServices.DrawToolBarElement + Params: DC - Carbon device context + Details - Details for themed element + R - Bounding rectangle + ClipRect - Clipping rectangle + Returns: ClientRect + + Draws a tool bar element with native Carbon look + ------------------------------------------------------------------------------} +function TCarbonThemeServices.DrawToolBarElement(DC: TCarbonDeviceContext; + Details: TThemedElementDetails; R: TRect; ClipRect: PRect): TRect; +var + ButtonDrawInfo: HIThemeButtonDrawInfo; + LabelRect: HIRect; +begin + if Details.Part in [TP_BUTTON, TP_DROPDOWNBUTTON, TP_SPLITBUTTON, TP_SPLITBUTTONDROPDOWN] then + begin + ButtonDrawInfo.version := 0; + ButtonDrawInfo.State := GetDrawState(Details); + case Details.Part of + TP_BUTTON, TP_SPLITBUTTON: ButtonDrawInfo.kind := kThemeBevelButtonSmall; + TP_DROPDOWNBUTTON: ButtonDrawInfo.kind := kThemePopupButtonSmall; + TP_SPLITBUTTONDROPDOWN: ButtonDrawInfo.kind := kThemeDisclosureButton; + end; + + if Details.Part = TP_SPLITBUTTONDROPDOWN then + begin + ButtonDrawInfo.value := kThemeDisclosureDown; + end + else + begin + if IsChecked(Details) then + ButtonDrawInfo.value := kThemeButtonOn + else + ButtonDrawInfo.value := kThemeButtonOff; + end; + ButtonDrawInfo.adornment := kThemeAdornmentNone; + + LabelRect := RectToCGRect(R); + + // if button is normal or disabled, draw it to dummy context, to eliminate borders + if ((ButtonDrawInfo.State = kThemeStateActive) or + (ButtonDrawInfo.State = kThemeStateInActive)) and + (ButtonDrawInfo.value = kThemeButtonOff) then + OSError( + HIThemeDrawButton(LabelRect, ButtonDrawInfo, DefaultContext.CGContext, + kHIThemeOrientationNormal, @LabelRect), + Self, 'DrawButtonElement', 'HIThemeDrawButton') + else + OSError( + HIThemeDrawButton(LabelRect, ButtonDrawInfo, DC.CGContext, + kHIThemeOrientationNormal, @LabelRect), + Self, 'DrawButtonElement', 'HIThemeDrawButton'); + + Result := CGRectToRect(LabelRect); + end; +end; + +function TCarbonThemeServices.DrawTreeviewElement(DC: TCarbonDeviceContext; + Details: TThemedElementDetails; R: TRect; ClipRect: PRect): TRect; +var + ButtonDrawInfo: HIThemeButtonDrawInfo; + LabelRect: HIRect; + b: TCarbonBrush; +begin + case Details.Part of + TVP_TREEITEM: + begin + b:=TCarbonBrush.Create(False); + case Details.State of + TREIS_NORMAL: b.SetColor( ColorToRGB(clWindow), True); + TREIS_HOT: b.SetColor( ColorToRGB(clHotLight), True); + TREIS_SELECTED: b.SetColor( ColorToRGB(clHighlight), True); + TREIS_DISABLED: b.SetColor( ColorToRGB(clWindow), True); + TREIS_SELECTEDNOTFOCUS: b.SetColor( ColorToRGB(clBtnFace), True); + TREIS_HOTSELECTED: b.SetColor( ColorToRGB(clHighlight), True); + end; + DC.FillRect(R, b); + b.Free; + end; + TVP_GLYPH, TVP_HOTGLYPH: + begin + ButtonDrawInfo.version := 0; + ButtonDrawInfo.State := GetDrawState(Details); + ButtonDrawInfo.kind := kThemeDisclosureTriangle; + if Details.State = GLPS_CLOSED then + ButtonDrawInfo.value := kThemeDisclosureRight + else + ButtonDrawInfo.value := kThemeDisclosureDown; + + ButtonDrawInfo.adornment := kThemeAdornmentNone; + LabelRect := RectToCGRect(R); + + OSError( + HIThemeDrawButton(LabelRect, ButtonDrawInfo, DC.CGContext, + kHIThemeOrientationNormal, @LabelRect), + Self, 'DrawTreeviewElement', 'HIThemeDrawButton'); + + Result := CGRectToRect(LabelRect); + end; + end; +end; + +function TCarbonThemeServices.DrawWindowElement(DC: TCarbonDeviceContext; + Details: TThemedElementDetails; R: TRect; ClipRect: PRect): TRect; +var + WindowDrawInfo: HIThemeWindowDrawInfo; + WindowWidgetDrawInfo: HIThemeWindowWidgetDrawInfo; + BtnRect: HIRect; + WindowShape: HIShapeRef; + WindowRegion: WindowRegionCode; + Offset: TPoint; +begin + WindowWidgetDrawInfo.version := 0; + WindowWidgetDrawInfo.windowState := kThemeStateActive; + WindowWidgetDrawInfo.windowType := kThemeDocumentWindow; + WindowWidgetDrawInfo.widgetState := GetDrawState(Details); + WindowWidgetDrawInfo.titleHeight := 0; + WindowWidgetDrawInfo.titleWidth := 0; + WindowWidgetDrawInfo.attributes := kThemeWindowHasFullZoom or kThemeWindowHasCloseBox or kThemeWindowHasCollapseBox; + case Details.Part of + WP_MINBUTTON, + WP_MDIMINBUTTON: + begin + WindowWidgetDrawInfo.widgetType := kThemeWidgetCollapseBox; + WindowRegion := kWindowCollapseBoxRgn; + end; + WP_MAXBUTTON: + begin + WindowWidgetDrawInfo.widgetType := kThemeWidgetZoomBox; + WindowRegion := kWindowZoomBoxRgn; + end; + WP_CLOSEBUTTON, + WP_SMALLCLOSEBUTTON, + WP_MDICLOSEBUTTON: + begin + WindowWidgetDrawInfo.widgetType := kThemeWidgetCloseBox; + WindowRegion := kWindowCloseBoxRgn; + end; + WP_RESTOREBUTTON, + WP_MDIRESTOREBUTTON: + begin + WindowWidgetDrawInfo.widgetType := kThemeWidgetZoomBox; + WindowRegion := kWindowZoomBoxRgn; + end; + else + Exit; + end; + // We have a button rectanle but carbon expects from us a titlebar rectangle, + // so we need to translate one coordinate to another + BtnRect := RectToCGRect(Types.Rect(0, 0, 100, 100)); + WindowDrawInfo.version := 0; + WindowDrawInfo.windowType := WindowWidgetDrawInfo.windowType; + WindowDrawInfo.attributes := WindowWidgetDrawInfo.attributes; + WindowDrawInfo.state := WindowWidgetDrawInfo.windowState; + WindowDrawInfo.titleHeight := WindowWidgetDrawInfo.titleHeight; + WindowDrawInfo.titleWidth := WindowWidgetDrawInfo.titleWidth; + WindowShape:=nil; + HIThemeGetWindowShape(BtnRect, WindowDrawInfo, WindowRegion, WindowShape); + HIShapeGetBounds(WindowShape, BtnRect); + Offset := CGRectToRect(BtnRect).TopLeft; + OffsetRect(R, -Offset.X, -Offset.Y); + BtnRect := RectToCGRect(R); + OSError( + HIThemeDrawTitleBarWidget(BtnRect, WindowWidgetDrawInfo, DC.CGContext, + kHIThemeOrientationNormal), + Self, 'DrawTreeviewElement', 'HIThemeDrawButton'); + + Result := CGRectToRect(BtnRect); + OffsetRect(Result, Offset.X, Offset.Y); +end; + +{------------------------------------------------------------------------------ + Method: TCarbonThemeServices.InitThemes + Returns: If the themes are initialized + ------------------------------------------------------------------------------} +function TCarbonThemeServices.InitThemes: Boolean; +begin + Result := True; +end; + +{------------------------------------------------------------------------------ + Method: TCarbonThemeServices.InitThemes + Returns: If the themes have to be used + ------------------------------------------------------------------------------} +function TCarbonThemeServices.UseThemes: Boolean; +begin + Result := True; +end; + +{------------------------------------------------------------------------------ + Method: TCarbonThemeServices.ThemedControlsEnabled + Returns: If the themed controls are enabled + ------------------------------------------------------------------------------} +function TCarbonThemeServices.ThemedControlsEnabled: Boolean; +begin + Result := True; +end; + +{------------------------------------------------------------------------------ + Method: TCarbonThemeServices.ContentRect + Params: DC - Carbon device context + Details - Details for themed element + BoundingRect - Bounding rectangle + Returns: Content rectangle of the passed themed element + ------------------------------------------------------------------------------} +function TCarbonThemeServices.ContentRect(DC: HDC; + Details: TThemedElementDetails; BoundingRect: TRect): TRect; +begin + case Details.Element of + teComboBox: Result := DrawComboBoxElement(DefaultContext, Details, BoundingRect, nil); + teHeader: Result := DrawHeaderElement(DefaultContext, Details, BoundingRect, nil); + teButton: Result := DrawButtonElement(DefaultContext, Details, BoundingRect, nil); + teRebar: Result := DrawRebarElement(DefaultContext, Details, BoundingRect, nil); + teToolBar: Result := DrawToolBarElement(DefaultContext, Details, BoundingRect, nil); + teWindow: Result := DrawWindowElement(DefaultContext, Details, BoundingRect, nil); + end; +end; + +{------------------------------------------------------------------------------ + Method: TCarbonThemeServices.DrawEdge + Params: DC - Carbon device context + Details - Details for themed element + R - Bounding rectangle + Edge - Type of edge + Flags - Type of border + + Draws an edge with native Carbon look + ------------------------------------------------------------------------------} +procedure TCarbonThemeServices.DrawEdge(DC: HDC; + Details: TThemedElementDetails; const R: TRect; Edge, Flags: Cardinal; + AContentRect: PRect); +begin + +end; +*) +{------------------------------------------------------------------------------ + Method: TCocoaThemeServices.DrawElement + Params: DC - Carbon device context + Details - Details for themed element + R - Bounding rectangle + ClipRect - Clipping rectangle + + Draws an element with native Aqua look + ------------------------------------------------------------------------------} +procedure TCocoaThemeServices.DrawElement(DC: HDC; + Details: TThemedElementDetails; const R: TRect; ClipRect: PRect); +//var +// Context: TCarbonDeviceContext absolute DC; +begin +{ if CheckDC(DC, 'TCocoaThemeServices.DrawElement') then + begin + case Details.Element of + teComboBox: DrawComboBoxElement(Context, Details, R, ClipRect); + teButton: DrawButtonElement(Context, Details, R, ClipRect); + teHeader: DrawHeaderElement(Context, Details, R, ClipRect); + teRebar: DrawRebarElement(Context, Details, R, ClipRect); + teToolBar: DrawToolBarElement(Context, Details, R, ClipRect); + teTreeview: DrawTreeviewElement(Context, Details, R, ClipRect); + teWindow: DrawWindowElement(Context, Details, R, ClipRect); + else + inherited DrawElement(DC, Details, R, ClipRect); + end; + end; } +end; +(* +{------------------------------------------------------------------------------ + Method: TCarbonThemeServices.DrawIcon + Params: DC - Carbon device context + Details - Details for themed element + R - Bounding rectangle + himl - Image list + Index - Icon index + + Draws an icon with native Carbon look + ------------------------------------------------------------------------------} +procedure TCarbonThemeServices.DrawIcon(DC: HDC; + Details: TThemedElementDetails; const R: TRect; himl: HIMAGELIST; + Index: Integer); +begin + +end; + +{------------------------------------------------------------------------------ + Method: TCarbonThemeServices.HasTransparentParts + Params: Details - Details for themed element + Returns: If the themed element has transparent parts + ------------------------------------------------------------------------------} +function TCarbonThemeServices.HasTransparentParts(Details: TThemedElementDetails): Boolean; +begin + Result := True; +end; + +function TCarbonThemeServices.GetDetailSize(Details: TThemedElementDetails): TSize; +const + DefaultPushButtonWidth = 70; +var + BtnRect: CGRect; + WindowDrawInfo: HIThemeWindowDrawInfo; + WindowShape: HIShapeRef; +begin + case Details.Element of + teTreeView: + if (Details.Part in [TVP_GLYPH, TVP_HOTGLYPH]) then + begin + Result := Types.Size( + GetCarbonThemeMetric(kThemeMetricDisclosureTriangleWidth), + GetCarbonThemeMetric(kThemeMetricDisclosureTriangleHeight) + ); + end + else + Result := inherited GetDetailSize(Details); + teButton: + if Details.Part = BP_PUSHBUTTON then + begin + Result := Types.Size( + DefaultPushButtonWidth, + GetCarbonThemeMetric(kThemeMetricPushButtonHeight) + ); + end else + Result := inherited GetDetailSize(Details); + teWindow: + if (Details.Part in [WP_MINBUTTON, WP_MDIMINBUTTON, WP_MAXBUTTON, WP_CLOSEBUTTON, WP_SMALLCLOSEBUTTON, WP_MDICLOSEBUTTON, WP_RESTOREBUTTON, WP_MDIRESTOREBUTTON]) then + begin + BtnRect := RectToCGRect(Types.Rect(0, 0, 100, 100)); + WindowDrawInfo.version := 0; + WindowDrawInfo.windowType := kThemeDocumentWindow; + WindowDrawInfo.attributes := kThemeWindowHasFullZoom or kThemeWindowHasCloseBox or kThemeWindowHasCollapseBox; + WindowDrawInfo.state := kThemeStateActive; + WindowDrawInfo.titleHeight := 0; + WindowDrawInfo.titleWidth := 0; + + WindowShape:=nil; + HIThemeGetWindowShape(BtnRect, WindowDrawInfo, kWindowCloseBoxRgn, WindowShape); + HIShapeGetBounds(WindowShape, BtnRect); + with BtnRect.size do + begin + Result.cx := Round(width); + Result.cy := Round(height); + end; + end else + Result := inherited GetDetailSize(Details); + else + Result := inherited GetDetailSize(Details); + end; +end; + +function TCarbonThemeServices.GetOption(AOption: TThemeOption): Integer; +begin + case AOption of + toShowButtonImages: Result := 0; + toShowMenuImages: Result := 0; + else + Result := inherited GetOption(AOption); + end; +end; + +{------------------------------------------------------------------------------ + Method: TCarbonThemeServices.InternalDrawParentBackground + Params: Window - Handle to window + Target - Carbon device context + Bounds - Bounding rectangle + + Draws the parent background with native Carbon look + ------------------------------------------------------------------------------} +procedure TCarbonThemeServices.InternalDrawParentBackground(Window: HWND; + Target: HDC; Bounds: PRect); +begin + // ? +end; + +{------------------------------------------------------------------------------ + Method: TCarbonThemeServices.DrawText + Params: DC - Carbon device context + Details - Details for themed element + S - Text string to darw + R - Bounding rectangle + Flags - Draw flags + Flags2 - Extra draw flags + + Draws the passed text with native Carbon look + ------------------------------------------------------------------------------} +procedure TCarbonThemeServices.DrawText(DC: HDC; Details: TThemedElementDetails; + const S: String; R: TRect; Flags, Flags2: Cardinal); +begin + // +end; +*) +end. +