/
macosformprop.pas
140 lines (114 loc) · 3.65 KB
/
macosformprop.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
unit MacOSFormProp;
{$mode delphi}{$H+}
{$ifdef LCLCocoa}
{$modeswitch objectivec1}
{$endif}
interface
uses
{$ifdef LCLCocoa}CocoaAll,{$endif}
Classes, SysUtils, Controls, LCLClasses;
const
macOSNSAppearanceNameAqua = 'NSAppearanceNameAqua';
DefaultAppearance = macOSNSAppearanceNameAqua;
macOSNSAppearanceNameVibrantDark = 'NSAppearanceNameVibrantDark';
macOSNSAppearanceNameVibrantLight = 'NSAppearanceNameVibrantLight';
macOSNSAppearanceNameDarkAqua = 'NSAppearanceNameDarkAqua';
type
{ TMacOSFormProp }
TMacOSFormProp = class(TLCLComponent)
private
fAppearance : String;
fDocEdited: Boolean;
protected
procedure SetApparance(const AAppearance: String);
procedure SetDocEdited(ADocEdited: Boolean);
public
constructor Create(AOwner: TComponent); override;
published
property Appearance: string read fAppearance write SetApparance;
property DocEdited: Boolean read fDocEdited write SetDocEdited;
end;
implementation
{ TMacOSFormProp }
{$ifdef LCLCocoa}
// https://developer.apple.com/documentation/appkit/nsappearance?language=objc
// NSAppearanceNameAqua
// NSAppearanceNameLightContent (deprecated)
// NSAppearanceNameVibrantDark
// NSAppearanceNameVibrantLight
function ComponentToNSWindow(Owner: TComponent): NSWindow;
var
obj : NSObject;
begin
Result := nil;
if not Assigned(Owner) or not (Owner is TWinControl) then Exit;
obj := NSObject(TWinControl(Owner).Handle);
if not Assigned(obj) then Exit;
if obj.isKindOfClass(NSView) then
Result := NSView(obj).window;
end;
type
NSAppearanceInt = NSObject; // declare as alias, rather than a subclass
NSAppearanceWin = objccategory external (NSResponder)
procedure setAppearance(app: NSAppearanceInt); message 'setAppearance:';
end;
NSAppearanceCat = objccategory external (NSAppearanceInt)
class function appearanceNamed(app: NSObject): NSAppearanceInt; message 'appearanceNamed:';
end;
type
NSAppearanceClass = class of NSAppearanceInt;
function UpdateAppearance(Owner: TComponent; const AAppearance: String): Boolean;
var
cls : NSAppearanceClass;
apr : id;
win : NSWindow;
nm : NSString;
begin
Result := false;
win := ComponentToNSWindow(Owner);
if not Assigned(win) then Exit;
if AAppearance = ''
then nm := NSSTR(DefaultAppearance) // it's constant
else nm := NSString.stringWithUTF8String(@AAppearance[1]);
cls := NSAppearanceClass(NSClassFromString(NSSTR('NSAppearance')));
if not Assigned(cls) then Exit; // not suppored in OSX version
// respondesToSelector returns if a class can respond to class methods!
// BUT, "respondesToSelector" is actually an instance method.
// in order to get "class instance object" (rather than "instance of a class")
// once should get cls.classClass object, cast it NSObject and call respondsToSelector
// from it
if NSObject(cls.classClass).respondsToSelector(ObjCSelector('appearanceNamed:')) then
apr := cls.appearanceNamed(nm)
else
apr := nil;
if not Assigned(apr) then Exit;
win.setAppearance(apr);
Result := true;
end;
{$endif}
procedure TMacOSFormProp.SetApparance(const AAppearance: String);
begin
if fAppearance = AAppearance then Exit;
fAppearance := AAppearance;
{$ifdef LCLCocoa}
UpdateAppearance(Owner, AAppearance);
{$endif}
end;
procedure TMacOSFormProp.SetDocEdited(ADocEdited: Boolean);
{$ifdef LCLCocoa}
var
win : NSWindow;
{$endif}
begin
fDocEdited := ADocEdited;
{$ifdef LCLCocoa}
win := ComponentToNSWindow(Owner);
if Assigned(win) then win.setDocumentEdited(ADocEdited);
{$endif}
end;
constructor TMacOSFormProp.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
fAppearance := 'NSAppearanceNameAqua';
end;
end.