cocoa: rework TCocoaScrollBar implementation - removed direct binding to LCL control. Initial implementation of ScrollWindowsEx. added scrolling messages for TCocoaManualScrollView

git-svn-id: trunk@56944 -
This commit is contained in:
dmitry 2018-01-04 02:54:59 +00:00
parent edee7ec8ef
commit 98712b414a
6 changed files with 170 additions and 27 deletions

View File

@ -188,6 +188,8 @@ type
var
CocoaWidgetSet: TCocoaWidgetSet;
function CocoaScrollBarSetScrollInfo(bar: TCocoaScrollBar; const ScrollInfo: TScrollInfo): Integer;
function CocoaScrollBarGetScrollInfo(bar: TCocoaScrollBar; var ScrollInfo: TScrollInfo): Boolean;
procedure NSScrollerGetScrollInfo(docSz, pageSz: CGFloat; rl: NSSCroller; Var ScrollInfo: TScrollInfo);
procedure NSScrollViewGetScrollInfo(sc: NSScrollView; BarFlag: Integer; Var ScrollInfo: TScrollInfo);
procedure NSScrollerSetScrollInfo(docSz, pageSz: CGFloat; rl: NSSCroller; const ScrollInfo: TScrollInfo);
@ -204,6 +206,66 @@ uses
CocoaCaret,
CocoaThemes;
function CocoaScrollBarSetScrollInfo(bar: TCocoaScrollBar; const ScrollInfo: TScrollInfo): Integer;
var
pg : Integer;
mn : Integer;
mx : Integer;
dl : Integer;
pos : CGFloat;
begin
if not Assigned(bar) then
begin
Result := 0;
Exit;
end;
if ScrollInfo.fMask and SIF_PAGE>0 then
begin
pg:=ScrollInfo.nPage;
if pg=0 then pg:=1; // zero page is not allowed?
end
else pg:=bar.pageInt;
if ScrollInfo.fMask and SIF_RANGE>0 then
begin
mn:=ScrollInfo.nMin;
mx:=ScrollInfo.nMax;
end
else
begin
mn:=bar.minInt;
mx:=bar.maxInt;
end;
dl:=mx-mn;
if ScrollInfo.fMask and SIF_POS > 0 then
begin
if dl<>0 then
bar.setDoubleValue( ScrollInfo.nPos / dl )
else
bar.setDoubleValue( 0 )
end;
bar.setEnabled(dl<>0);
// if changed page or range, the knob changes
if ScrollInfo.fMask and (SIF_RANGE or SIF_PAGE)>0 then
begin
if dl<>0 then
//bar.setKnobProportion(pg/dl)
bar.setKnobProportion(0.5)
else
bar.setKnobProportion(1);
bar.pageInt:=pg;
bar.minInt:=mn;
bar.maxInt:=mx;
end;
end;
function CocoaScrollBarGetScrollInfo(bar: TCocoaScrollBar; var ScrollInfo: TScrollInfo): Boolean;
begin
end;
procedure NSScrollerGetScrollInfo(docSz, pageSz: CGFloat; rl: NSSCroller; Var ScrollInfo: TScrollInfo);
begin

View File

@ -65,6 +65,7 @@ type
procedure DidResignKeyNotification;
procedure SendOnChange;
procedure SendOnTextChanged;
procedure scroll(isVert: Boolean; Pos: Integer);
// non event methods
function DeliverMessage(Msg: Cardinal; WParam: WParam; LParam: LParam): LResult;
function GetPropStorage: TStringList;
@ -507,6 +508,10 @@ type
procedure setHasHorizontalScroller(doshow: Boolean); message 'setHasHorizontalScroller:';
function hasVerticalScroller: Boolean; message 'hasVerticalScroller';
function hasHorizontalScroller: Boolean; message 'hasHorizontalScroller';
function horizontalScroller: NSScroller; message 'horizontalScroller';
function verticalScroller: NSScroller; message 'verticalScroller';
end;
TStatusItemData = record
@ -605,7 +610,10 @@ type
TCocoaScrollBar = objcclass(NSScroller)
public
callback: ICommonCallback;
LCLScrollBar: TCustomScrollBar;
// minInt,maxInt are used to calculate POS on callback event
minInt : Integer;
maxInt : Integer;
pageInt : Integer;
procedure actionScrolling(sender: NSObject); message 'actionScrolling:';
function IsHorizontal: Boolean; message 'IsHorizontal';
function acceptsFirstResponder: Boolean; override;
@ -1040,11 +1048,15 @@ begin
Result:=fdocumentView;
end;
procedure allocScroller(parent: NSView; var sc: NSScroller; dst: NSRect);
procedure allocScroller(parent: TCocoaManualScrollView; var sc: NSScroller; dst: NSRect);
begin
if Assigned(sc) then Exit;
sc:=NSScroller(NSScroller.alloc).initWithFrame(dst);
sc:=TCocoaScrollBar(TCocoaScrollBar.alloc).initWithFrame(dst);
parent.addSubview(sc);
TCocoaScrollBar(sc).callback:=parent.callback;
sc.setTarget(sc);
sc.setAction(objcselector('actionScrolling:'));
end;
procedure updateDocSize(parent: NSView; doc: NSView; hrz, vrt: NSScroller);
@ -1145,6 +1157,16 @@ begin
Result:=Assigned(fhscroll) and (not fhscroll.isHidden);
end;
function TCocoaManualScrollView.horizontalScroller: NSScroller;
begin
Result:=fhscroll;
end;
function TCocoaManualScrollView.verticalScroller: NSScroller;
begin
Result:=fvscroll;
end;
{ TCocoaWindowContent }
function TCocoaWindowContent.lclIsHandle: Boolean;
@ -1840,22 +1862,9 @@ end;
{ TCocoaScrollBar }
procedure TCocoaScrollBar.actionScrolling(sender: NSObject);
var
LMScroll: TLMScroll;
b: Boolean;
begin
FillChar(LMScroll{%H-}, SizeOf(LMScroll), #0);
LMScroll.ScrollBar := PtrUInt(Self);
if IsHorizontal() then
LMScroll.Msg := LM_HSCROLL
else
LMScroll.Msg := LM_VSCROLL;
LMScroll.Pos := Round(floatValue * LCLScrollBar.Max);
LMScroll.ScrollCode := SIF_POS;
LCLMessageGlue.DeliverMessage(LCLScrollBar, LMScroll);
if Assigned(callback) then
callback.scroll( not IsHorizontal(), Round(floatValue * (maxInt-minInt)));
end;
function TCocoaScrollBar.IsHorizontal: Boolean;

View File

@ -1752,19 +1752,47 @@ var
si : TScrollInfo;
obj : NSObject;
sc : TCocoaScrollView;
bar : TCocoaScrollBar;
begin
obj := HandleToNSObject(Handle);
Result := 0;
if not Assigned(obj) then Exit;
if not obj.isKindOfClass(TCocoaScrollView) then Exit;
if obj.isKindOfClass(TCocoaScrollView) then
begin
sc:=TCocoaScrollView(obj);
NSScrollViewSetScrollInfo(NSScrollView(obj), SBStyle, ScrollInfo);
FillChar(si, sizeof(si), 0);
si.cbSize:=sizeof(si);
NSScrollViewGetScrollInfo(NSScrollView(obj), SBStyle, si);
Result:=si.nPos;
end else if obj.isKindOfClass(TCocoaManualScrollView) then
begin
bar:=nil;
if SBStyle=SB_Vert then
begin
// Win32 forced the scrollbar to show up on SetScrollInfo
// TCocoaManualScrollView - also allocates on setting visible
TCocoaManualScrollView(obj).setHasVerticalScroller(true);
bar:=TCocoaScrollBar(TCocoaManualScrollView(obj).verticalScroller);
end
else if SBStyle=SB_Horz then
begin
TCocoaManualScrollView(obj).setHasHorizontalScroller(true);
bar := TCocoaScrollBar(TCocoaManualScrollView(obj).horizontalScroller);
end;
sc:=TCocoaScrollView(obj);
NSScrollViewSetScrollInfo(NSScrollView(obj), SBStyle, ScrollInfo);
FillChar(si, sizeof(si), 0);
si.cbSize:=sizeof(si);
NSScrollViewGetScrollInfo(NSScrollView(obj), SBStyle, si);
Result:=si.nPos;
if Assigned(bar) then
Result := CocoaScrollBarSetScrollInfo(bar, ScrollInfo)
else
Result := 0;
end else if obj.isKindOfClass(TCocoaScrollBar) then
begin
Result := CocoaScrollBarSetScrollInfo(TCocoaScrollBar(obj), ScrollInfo);
end
else
Result := 0;
end;
function TCocoaWidgetSet.ShowScrollBar(Handle: HWND; wBar: Integer; bShow: Boolean): Boolean;
@ -2583,6 +2611,26 @@ begin
NSObject(Handle).lclScreenToLocal(P.X, P.Y);
end;
function TCocoaWidgetSet.ScrollWindowEx(hWnd: HWND; dx, dy: Integer; prcScroll, prcClip: PRect; hrgnUpdate: HRGN; prcUpdate: PRect; flags: UINT): Boolean;
var
obj: NSOBject;
b: NSRect;
v : NSView;
begin
obj:=NSObject(HandleToNSObject(hWnd));
Result:=Assigned(obj) and (obj.isKindOfClass(NSView));
if not Result then Exit;
v:=NSView(obj).lclContentView;
b:=v.bounds;
b.origin.x:=b.origin.x-dx;
b.origin.y:=b.origin.y+dy; // reversed
v.setBounds(b);
// ignore all updates
v.setNeedsDisplay_(true);
end;
function TCocoaWidgetSet.SelectClipRGN(DC: hDC; RGN: HRGN): Longint;
begin
Result := ExtSelectClipRgn(DC, RGN, RGN_COPY);

View File

@ -155,6 +155,7 @@ function RoundRect(DC: HDC; X1, Y1, X2, Y2: Integer; RX, RY : Integer): Boolean;
function SaveDC(DC: HDC): Integer; override;
function ScreenToClient(Handle: HWND; var P: TPoint): Integer; override;
function ScrollWindowEx(hWnd: HWND; dx, dy: Integer; prcScroll, prcClip: PRect; hrgnUpdate: HRGN; prcUpdate: PRect; flags: UINT): Boolean; override;
function SelectClipRGN(DC : hDC; RGN : HRGN) : Longint; override;
function SelectObject(ADC: HDC; GDIObj: HGDIOBJ): HGDIOBJ; override;
function SendMessage(Handle: HWND; Msg: Cardinal; WParam: WParam; LParam: LParam): LResult; override;

View File

@ -63,7 +63,7 @@ type
procedure DidResignKeyNotification; virtual;
procedure SendOnChange; virtual;
procedure SendOnTextChanged; virtual; // text controls (like spin) respond to OnChange for this event, but not for SendOnChange
procedure scroll(isVert: Boolean; Pos: Integer); virtual;
function DeliverMessage(var Msg): LRESULT; virtual; overload;
function DeliverMessage(Msg: Cardinal; WParam: WParam; LParam: LParam): LResult; virtual; overload;
procedure Draw(ControlContext: NSGraphicsContext; const bounds, dirty: NSRect); virtual;
@ -1042,6 +1042,26 @@ begin
SendSimpleMessage(Target, CM_TEXTCHANGED);
end;
procedure TLCLCommonCallback.scroll(isVert: Boolean; Pos: Integer);
var
LMScroll: TLMScroll;
b: Boolean;
begin
FillChar(LMScroll{%H-}, SizeOf(LMScroll), #0);
//todo: this should be a part of a parameter
//LMScroll.ScrollBar := Target.Handle;
if IsVert then
LMScroll.Msg := LM_VSCROLL
else
LMScroll.Msg := LM_HSCROLL;
LMScroll.Pos := Pos;
LMScroll.ScrollCode := SB_THUMBPOSITION; //SIF_POS;
LCLMessageGlue.DeliverMessage(Target, LMScroll);
end;
function TLCLCommonCallback.DeliverMessage(var Msg): LRESULT;
begin
Result := LCLMessageGlue.DeliverMessage(Target, Msg);

View File

@ -1387,10 +1387,13 @@ begin
scr.callback:=TLCLCommonCallback.Create(scr, AWinControl);
// OnChange (scrolling) event handling
scr.LCLScrollBar := TCustomScrollBar(AWinControl);
scr.setTarget(scr);
scr.setAction(objcselector('actionScrolling:'));
scr.minInt:=TCustomScrollBar(AWinControl).Min;
scr.maxInt:=TCustomScrollBar(AWinControl).Max;
scr.pageInt:=TCustomScrollBar(AWinControl).PageSize;
Result:=TLCLIntfHandle(scr);
end;