mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-15 10:19:23 +02:00
Cocoa: Scroller Style can be dynamically updated at runtime according to macOS settings
This commit is contained in:
parent
fc40f7730d
commit
50cdfdfaae
@ -102,7 +102,7 @@ type
|
|||||||
{ TCocoaScrollStyleManager }
|
{ TCocoaScrollStyleManager }
|
||||||
|
|
||||||
TCocoaScrollStyleManager = class(TCocoaScrollBarStyleManager)
|
TCocoaScrollStyleManager = class(TCocoaScrollBarStyleManager)
|
||||||
protected
|
private
|
||||||
_scrollView: TCocoaManualScrollView;
|
_scrollView: TCocoaManualScrollView;
|
||||||
public
|
public
|
||||||
procedure updateLayout; virtual; abstract;
|
procedure updateLayout; virtual; abstract;
|
||||||
@ -115,9 +115,12 @@ type
|
|||||||
|
|
||||||
TCocoaScrollBar = objcclass(NSScroller)
|
TCocoaScrollBar = objcclass(NSScroller)
|
||||||
private
|
private
|
||||||
manager: TCocoaScrollBarStyleManager;
|
_scrollView: TCocoaManualScrollView;
|
||||||
effect: TCocoaScrollBarEffect;
|
_manager: TCocoaScrollBarStyleManager;
|
||||||
trackingArea: NSTrackingArea;
|
_effect: TCocoaScrollBarEffect;
|
||||||
|
_trackingArea: NSTrackingArea;
|
||||||
|
private
|
||||||
|
procedure releaseManager; message 'releaseManager';
|
||||||
public
|
public
|
||||||
callback: ICommonCallback;
|
callback: ICommonCallback;
|
||||||
preventBlock : Boolean;
|
preventBlock : Boolean;
|
||||||
@ -131,6 +134,13 @@ type
|
|||||||
|
|
||||||
procedure dealloc; override;
|
procedure dealloc; override;
|
||||||
|
|
||||||
|
function manager: TCocoaScrollBarStyleManager;
|
||||||
|
message 'manager';
|
||||||
|
function effect: TCocoaScrollBarEffect;
|
||||||
|
message 'effect';
|
||||||
|
procedure setManager( newManager:TCocoaScrollBarStyleManager );
|
||||||
|
message 'setManager:';
|
||||||
|
|
||||||
procedure drawKnob; override;
|
procedure drawKnob; override;
|
||||||
procedure drawKnobSlotInRect_highlight(slotRect: NSRect; flag: ObjCBOOL); override;
|
procedure drawKnobSlotInRect_highlight(slotRect: NSRect; flag: ObjCBOOL); override;
|
||||||
procedure setDoubleValue(newValue: double); override;
|
procedure setDoubleValue(newValue: double); override;
|
||||||
@ -165,7 +175,7 @@ type
|
|||||||
|
|
||||||
TCocoaManualScrollView = objcclass(NSView)
|
TCocoaManualScrollView = objcclass(NSView)
|
||||||
private
|
private
|
||||||
manager: TCocoaScrollStyleManager;
|
_manager: TCocoaScrollStyleManager;
|
||||||
fdocumentView: NSView;
|
fdocumentView: NSView;
|
||||||
fhscroll : TCocoaScrollBar;
|
fhscroll : TCocoaScrollBar;
|
||||||
fvscroll : TCocoaScrollBar;
|
fvscroll : TCocoaScrollBar;
|
||||||
@ -175,6 +185,9 @@ type
|
|||||||
procedure dealloc; override;
|
procedure dealloc; override;
|
||||||
procedure setFrame(newValue: NSRect); override;
|
procedure setFrame(newValue: NSRect); override;
|
||||||
|
|
||||||
|
procedure resetManager; message 'resetManager';
|
||||||
|
procedure onScrollerStyleUpdated; message 'onScrollerStyleUpdated';
|
||||||
|
|
||||||
function lclGetCallback: ICommonCallback; override;
|
function lclGetCallback: ICommonCallback; override;
|
||||||
procedure lclClearCallback; override;
|
procedure lclClearCallback; override;
|
||||||
function lclContentView: NSView; override;
|
function lclContentView: NSView; override;
|
||||||
@ -208,6 +221,8 @@ type
|
|||||||
function lclClientFrame: TRect; override;
|
function lclClientFrame: TRect; override;
|
||||||
procedure scrollWheel(theEvent: NSEvent); override;
|
procedure scrollWheel(theEvent: NSEvent); override;
|
||||||
procedure setFrame(newValue: NSRect); override;
|
procedure setFrame(newValue: NSRect); override;
|
||||||
|
|
||||||
|
procedure setScrollerStyle(newValue: NSScrollerStyle); override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function createLegacyScroller: TCocoaScrollBar;
|
function createLegacyScroller: TCocoaScrollBar;
|
||||||
@ -454,20 +469,22 @@ end;
|
|||||||
// only the Legacy Style can be used for compatibility.
|
// only the Legacy Style can be used for compatibility.
|
||||||
// it's the same logical relationship as NSScrollView and NSScroller.
|
// it's the same logical relationship as NSScrollView and NSScroller.
|
||||||
function createLegacyScroller: TCocoaScrollBar;
|
function createLegacyScroller: TCocoaScrollBar;
|
||||||
|
var
|
||||||
|
scrollBar: TCocoaScrollBar Absolute Result;
|
||||||
|
manager: TCocoaScrollStyleManager;
|
||||||
begin
|
begin
|
||||||
Result:= TCocoaScrollBar(TCocoaScrollBar.alloc);
|
scrollBar:= TCocoaScrollBar(TCocoaScrollBar.alloc);
|
||||||
Result.manager:= TCocoaScrollStyleManagerLegacy.createForScrollBar;
|
manager:= TCocoaScrollStyleManagerLegacy.createForScrollBar;
|
||||||
Result.effect:= Result.manager.createScrollBarEffect(Result);
|
scrollBar.setManager( manager );
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function allocScroller(parent: TCocoaManualScrollView; dst: NSRect; aVisible: Boolean)
|
function allocScroller(parent: TCocoaManualScrollView; dst: NSRect; aVisible: Boolean)
|
||||||
:TCocoaScrollBar;
|
:TCocoaScrollBar;
|
||||||
var
|
var
|
||||||
scrollBar: TCocoaScrollBar;
|
scrollBar: TCocoaScrollBar Absolute Result;
|
||||||
begin
|
begin
|
||||||
scrollBar:= TCocoaScrollBar(TCocoaScrollBar.alloc).initWithFrame(dst);
|
scrollBar:= TCocoaScrollBar(TCocoaScrollBar.alloc).initWithFrame(dst);
|
||||||
scrollBar.manager:= parent.manager;
|
scrollBar.setManager( parent._manager );
|
||||||
scrollBar.effect:= parent.manager.createScrollBarEffect(scrollBar);
|
|
||||||
parent.addSubview(scrollBar);
|
parent.addSubview(scrollBar);
|
||||||
{$ifdef BOOLFIX}
|
{$ifdef BOOLFIX}
|
||||||
scrollBar.setEnabled_(Ord(true));
|
scrollBar.setEnabled_(Ord(true));
|
||||||
@ -482,7 +499,6 @@ begin
|
|||||||
scrollBar.suppressLCLMouse := true;
|
scrollBar.suppressLCLMouse := true;
|
||||||
scrollBar.setTarget(scrollBar);
|
scrollBar.setTarget(scrollBar);
|
||||||
scrollBar.setAction(objcselector('actionScrolling:'));
|
scrollBar.setAction(objcselector('actionScrolling:'));
|
||||||
Result:= scrollBar;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TCocoaManualScrollHost }
|
{ TCocoaManualScrollHost }
|
||||||
@ -526,43 +542,94 @@ begin
|
|||||||
sc.setFrame( scFrame );
|
sc.setFrame( scFrame );
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TCocoaManualScrollHost.setScrollerStyle(newValue: NSScrollerStyle);
|
||||||
|
begin
|
||||||
|
inherited setScrollerStyle(newValue);
|
||||||
|
if Assigned(self.lclGetTarget) and Assigned(self.documentView) then
|
||||||
|
TCocoaManualScrollView(self.documentView).onScrollerStyleUpdated;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TCocoaManualScrollView }
|
{ TCocoaManualScrollView }
|
||||||
|
|
||||||
function TCocoaManualScrollView.initWithFrame(frameRect: NSRect): id;
|
function TCocoaManualScrollView.initWithFrame(frameRect: NSRect): id;
|
||||||
var
|
|
||||||
style: NSScrollerStyle;
|
|
||||||
begin
|
begin
|
||||||
Result:= inherited;
|
Result:= inherited;
|
||||||
|
resetManager;
|
||||||
style:= CocoaConfig.CocoaScrollerPreferredStyle;
|
|
||||||
if style < 0 then
|
|
||||||
style:= NSScroller.preferredScrollerStyle;
|
|
||||||
|
|
||||||
if style = NSScrollerStyleLegacy then
|
|
||||||
self.manager:= TCocoaScrollStyleManagerLegacy.createForScrollView(self)
|
|
||||||
else
|
|
||||||
self.manager:= TCocoaScrollStyleManagerOverlay.createForScrollView(self);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCocoaManualScrollView.dealloc;
|
procedure TCocoaManualScrollView.dealloc;
|
||||||
begin
|
begin
|
||||||
if Assigned(fhscroll) then begin
|
if Assigned(fhscroll) then begin
|
||||||
fhscroll.removeFromSuperview;
|
fhscroll.removeFromSuperview;
|
||||||
fhscroll.manager:= nil;
|
fhscroll.setManager( nil );
|
||||||
fhscroll.release;
|
fhscroll.release;
|
||||||
end;
|
end;
|
||||||
if Assigned(fvscroll) then begin
|
if Assigned(fvscroll) then begin
|
||||||
fvscroll.removeFromSuperview;
|
fvscroll.removeFromSuperview;
|
||||||
fvscroll.manager:= nil;
|
fvscroll.setManager( nil );
|
||||||
fvscroll.release;
|
fvscroll.release;
|
||||||
end;
|
end;
|
||||||
FreeAndNil(manager);
|
FreeAndNil( _manager );
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCocoaManualScrollView.setFrame(newValue: NSRect);
|
procedure TCocoaManualScrollView.setFrame(newValue: NSRect);
|
||||||
begin
|
begin
|
||||||
inherited setFrame(newValue);
|
inherited setFrame(newValue);
|
||||||
manager.updateLayout;
|
_manager.updateLayout;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCocoaManualScrollView.resetManager;
|
||||||
|
var
|
||||||
|
oldManager: TCocoaScrollStyleManager;
|
||||||
|
style: NSScrollerStyle;
|
||||||
|
begin
|
||||||
|
oldManager:= _manager;
|
||||||
|
|
||||||
|
style:= CocoaConfig.CocoaScrollerPreferredStyle;
|
||||||
|
if style < 0 then
|
||||||
|
style:= NSScroller.preferredScrollerStyle;
|
||||||
|
|
||||||
|
if style = NSScrollerStyleLegacy then
|
||||||
|
_manager:= TCocoaScrollStyleManagerLegacy.createForScrollView(self)
|
||||||
|
else
|
||||||
|
_manager:= TCocoaScrollStyleManagerOverlay.createForScrollView(self);
|
||||||
|
|
||||||
|
if Assigned(self.fhscroll) then begin
|
||||||
|
self.fhscroll.setManager( _manager );
|
||||||
|
end;
|
||||||
|
if Assigned(self.fvscroll) then begin
|
||||||
|
self.fvscroll.setManager( _manager );
|
||||||
|
end;
|
||||||
|
|
||||||
|
oldManager.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCocoaManualScrollView.onScrollerStyleUpdated;
|
||||||
|
var
|
||||||
|
horzAvailable: Boolean;
|
||||||
|
vertAvailabl: Boolean;
|
||||||
|
begin
|
||||||
|
horzAvailable:= _manager.isAvailableScrollBar( self.fhscroll );
|
||||||
|
vertAvailabl:= _manager.isAvailableScrollBar( self.fvscroll );
|
||||||
|
|
||||||
|
self.resetManager;
|
||||||
|
|
||||||
|
_manager.availScrollBar( self.fhscroll, horzAvailable );
|
||||||
|
_manager.availScrollBar( self.fvscroll, vertAvailabl );
|
||||||
|
|
||||||
|
if self.lclGetTarget is TWinControl then begin
|
||||||
|
/// TWinControl(self.lclGetTarget).InvalidateClientRectCache(True);
|
||||||
|
/// TWinControl(self.lclGetTarget).InvalidatePreferredSize;
|
||||||
|
TWinControl(self.lclGetTarget).AdjustSize;
|
||||||
|
/// TWinControl(self.lclGetTarget).Invalidate;
|
||||||
|
end;
|
||||||
|
|
||||||
|
_manager.updateLayout;
|
||||||
|
|
||||||
|
if self.hasHorizontalScroller then
|
||||||
|
_manager.showScrollBar(self.fhscroll);
|
||||||
|
if self.hasVerticalScroller then
|
||||||
|
_manager.showScrollBar(self.fvscroll);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TCocoaManualScrollView.lclGetCallback: ICommonCallback;
|
function TCocoaManualScrollView.lclGetCallback: ICommonCallback;
|
||||||
@ -638,26 +705,26 @@ procedure TCocoaManualScrollView.setHasVerticalScroller(doshow: Boolean);
|
|||||||
begin
|
begin
|
||||||
if NOT Assigned(fvscroll) and doshow then
|
if NOT Assigned(fvscroll) and doshow then
|
||||||
fvscroll:= self.allocVerticalScroller( True );
|
fvscroll:= self.allocVerticalScroller( True );
|
||||||
self.manager.availScrollBar( fvscroll, doshow );
|
_manager.availScrollBar( fvscroll, doshow );
|
||||||
self.manager.updateLayout;
|
_manager.updateLayout;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCocoaManualScrollView.setHasHorizontalScroller(doshow: Boolean);
|
procedure TCocoaManualScrollView.setHasHorizontalScroller(doshow: Boolean);
|
||||||
begin
|
begin
|
||||||
if NOT Assigned(fhscroll) and doshow then
|
if NOT Assigned(fhscroll) and doshow then
|
||||||
fhscroll:= self.allocHorizontalScroller( True );
|
fhscroll:= self.allocHorizontalScroller( True );
|
||||||
self.manager.availScrollBar( fhscroll, doshow );
|
_manager.availScrollBar( fhscroll, doshow );
|
||||||
self.manager.updateLayout;
|
_manager.updateLayout;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TCocoaManualScrollView.hasVerticalScroller: Boolean;
|
function TCocoaManualScrollView.hasVerticalScroller: Boolean;
|
||||||
begin
|
begin
|
||||||
Result:= self.manager.isAvailableScrollBar(fvscroll);
|
Result:= _manager.isAvailableScrollBar(fvscroll);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TCocoaManualScrollView.hasHorizontalScroller: Boolean;
|
function TCocoaManualScrollView.hasHorizontalScroller: Boolean;
|
||||||
begin
|
begin
|
||||||
Result:= self.manager.isAvailableScrollBar(fhscroll);
|
Result:= _manager.isAvailableScrollBar(fhscroll);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TCocoaManualScrollView.horizontalScroller: NSScroller;
|
function TCocoaManualScrollView.horizontalScroller: NSScroller;
|
||||||
@ -926,20 +993,52 @@ end;
|
|||||||
|
|
||||||
{ TCocoaScrollBar }
|
{ TCocoaScrollBar }
|
||||||
|
|
||||||
|
procedure TCocoaScrollBar.releaseManager;
|
||||||
|
begin
|
||||||
|
if NOT Assigned(_manager) then
|
||||||
|
Exit;
|
||||||
|
|
||||||
|
if NOT Assigned(_scrollView) then
|
||||||
|
FreeAndNil(_manager);
|
||||||
|
|
||||||
|
if Assigned(_effect) then begin
|
||||||
|
_effect.onDestroy;
|
||||||
|
_effect.release;
|
||||||
|
_effect:= nil;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TCocoaScrollBar.dealloc;
|
procedure TCocoaScrollBar.dealloc;
|
||||||
begin
|
begin
|
||||||
FreeAndNil(manager);
|
releaseManager;
|
||||||
effect.onDestroy;
|
|
||||||
effect.release;
|
|
||||||
inherited dealloc;
|
inherited dealloc;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCocoaScrollBar.drawKnob;
|
function TCocoaScrollBar.manager: TCocoaScrollBarStyleManager;
|
||||||
var
|
|
||||||
rect: NSRect;
|
|
||||||
path: NSBezierPath;
|
|
||||||
begin
|
begin
|
||||||
self.manager.onDrawKnob(self);
|
Result:= _manager;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TCocoaScrollBar.effect: TCocoaScrollBarEffect;
|
||||||
|
begin
|
||||||
|
Result:= _effect;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCocoaScrollBar.setManager( newManager: TCocoaScrollBarStyleManager);
|
||||||
|
begin
|
||||||
|
releaseManager;
|
||||||
|
_scrollView:= nil;
|
||||||
|
_manager:= newManager;
|
||||||
|
if Assigned(_manager) then begin
|
||||||
|
if _manager is TCocoaScrollStyleManager then
|
||||||
|
_scrollView:= TCocoaScrollStyleManager(_manager)._scrollView;
|
||||||
|
_effect:= _manager.createScrollBarEffect(self);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCocoaScrollBar.drawKnob;
|
||||||
|
begin
|
||||||
|
_manager.onDrawKnob(self);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCocoaScrollBar.drawKnobSlotInRect_highlight(slotRect: NSRect;
|
procedure TCocoaScrollBar.drawKnobSlotInRect_highlight(slotRect: NSRect;
|
||||||
@ -947,7 +1046,7 @@ procedure TCocoaScrollBar.drawKnobSlotInRect_highlight(slotRect: NSRect;
|
|||||||
var
|
var
|
||||||
drawSlot: Boolean;
|
drawSlot: Boolean;
|
||||||
begin
|
begin
|
||||||
drawSlot:= self.manager.onDrawKnobSlot(self, slotRect);
|
drawSlot:= _manager.onDrawKnobSlot(self, slotRect);
|
||||||
if drawSlot then
|
if drawSlot then
|
||||||
Inherited;
|
Inherited;
|
||||||
end;
|
end;
|
||||||
@ -957,7 +1056,7 @@ var
|
|||||||
proportion: CGFloat;
|
proportion: CGFloat;
|
||||||
begin
|
begin
|
||||||
proportion:= self.knobProportion;
|
proportion:= self.knobProportion;
|
||||||
manager.onKnobValueUpdated( self, newValue, proportion );
|
_manager.onKnobValueUpdated( self, newValue, proportion );
|
||||||
inherited;
|
inherited;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -966,7 +1065,7 @@ var
|
|||||||
position: CGFloat;
|
position: CGFloat;
|
||||||
begin
|
begin
|
||||||
position:= self.doubleValue;
|
position:= self.doubleValue;
|
||||||
manager.onKnobValueUpdated( self, position, newValue );
|
_manager.onKnobValueUpdated( self, position, newValue );
|
||||||
inherited;
|
inherited;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -977,28 +1076,28 @@ const
|
|||||||
options: NSTrackingAreaOptions = NSTrackingMouseEnteredAndExited
|
options: NSTrackingAreaOptions = NSTrackingMouseEnteredAndExited
|
||||||
or NSTrackingActiveAlways;
|
or NSTrackingActiveAlways;
|
||||||
begin
|
begin
|
||||||
if Assigned(trackingArea) then begin
|
if Assigned(_trackingArea) then begin
|
||||||
removeTrackingArea(trackingArea);
|
removeTrackingArea(_trackingArea);
|
||||||
trackingArea:= nil;
|
_trackingArea:= nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
trackingArea:= NSTrackingArea.alloc.initWithRect_options_owner_userInfo(
|
_trackingArea:= NSTrackingArea.alloc.initWithRect_options_owner_userInfo(
|
||||||
self.bounds,
|
self.bounds,
|
||||||
options,
|
options,
|
||||||
self,
|
self,
|
||||||
nil);
|
nil);
|
||||||
self.addTrackingArea( trackingArea );
|
self.addTrackingArea( _trackingArea );
|
||||||
trackingArea.release;
|
_trackingArea.release;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCocoaScrollBar.mouseEntered(theEvent: NSEvent);
|
procedure TCocoaScrollBar.mouseEntered(theEvent: NSEvent);
|
||||||
begin
|
begin
|
||||||
manager.onMouseEntered(self);
|
_manager.onMouseEntered(self);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCocoaScrollBar.mouseExited(theEvent: NSEvent);
|
procedure TCocoaScrollBar.mouseExited(theEvent: NSEvent);
|
||||||
begin
|
begin
|
||||||
manager.onMouseExited( self );
|
_manager.onMouseExited( self );
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCocoaScrollBar.actionScrolling(sender: NSObject);
|
procedure TCocoaScrollBar.actionScrolling(sender: NSObject);
|
||||||
@ -1571,6 +1670,9 @@ begin
|
|||||||
knobProportion:= 25/slotSize;
|
knobProportion:= 25/slotSize;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
effect.currentKnobPosition:= knobPosition;
|
||||||
|
effect.currentKnobProportion:= knobProportion;
|
||||||
|
|
||||||
self.showScrollBar( scroller );
|
self.showScrollBar( scroller );
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1634,7 +1736,7 @@ var
|
|||||||
begin
|
begin
|
||||||
effect:= TCocoaScrollBarEffectOverlay(scrollBar.effect);
|
effect:= TCocoaScrollBarEffectOverlay(scrollBar.effect);
|
||||||
|
|
||||||
if scroller.knobProportion=1 then begin
|
if effect.currentKnobProportion=1 then begin
|
||||||
scroller.setAlphaValue(0);
|
scroller.setAlphaValue(0);
|
||||||
scroller.setHidden(True);
|
scroller.setHidden(True);
|
||||||
Exit;
|
Exit;
|
||||||
|
Loading…
Reference in New Issue
Block a user