From 611c971eaf823c743286e27faf856ec00a264a16 Mon Sep 17 00:00:00 2001 From: dmitry Date: Fri, 5 Jan 2018 05:17:04 +0000 Subject: [PATCH] cocoa: improved implementation of TCocoaScrollBar - keeping track of the actual ranges and position of as scroll bar (that's critical for all custom controls using scrollbars heavily: TreeView #32931, SynEdit #32929, Grids #32932, #32767 ). Simplified ScrollWindowEx to just a complete invalidation of control content. git-svn-id: trunk@56961 - --- lcl/interfaces/cocoa/cocoaint.pas | 27 +++++++++++++++++++-------- lcl/interfaces/cocoa/cocoaprivate.pp | 28 ++++++++++++++++++++++++++-- lcl/interfaces/cocoa/cocoawinapi.inc | 21 +++++++++++++-------- 3 files changed, 58 insertions(+), 18 deletions(-) diff --git a/lcl/interfaces/cocoa/cocoaint.pas b/lcl/interfaces/cocoa/cocoaint.pas index 346db194ce..c33b8c4f5f 100644 --- a/lcl/interfaces/cocoa/cocoaint.pas +++ b/lcl/interfaces/cocoa/cocoaint.pas @@ -239,14 +239,6 @@ begin 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 @@ -261,10 +253,29 @@ begin bar.minInt:=mn; bar.maxInt:=mx; end; + + if ScrollInfo.fMask and SIF_POS > 0 then + bar.lclSetPos( ScrollInfo.nPos ); + + Result:=bar.lclPos; end; function CocoaScrollBarGetScrollInfo(bar: TCocoaScrollBar; var ScrollInfo: TScrollInfo): Boolean; +var + l : integer; begin + Result:=Assigned(bar); + if not Result then Exit; + + FillChar(ScrollInfo, sizeof(ScrollInfo), 0); + ScrollInfo.cbSize:=sizeof(ScrollInfo); + ScrollInfo.fMask:=SIF_ALL; + ScrollInfo.nMin:=bar.minInt; + ScrollInfo.nMax:=bar.maxInt; + ScrollInfo.nPage:=bar.pageInt; + ScrollInfo.nPos:=bar.lclPos; + ScrollInfo.nTrackPos:=ScrollInfo.nPos; + Result:=true; end; procedure NSScrollerGetScrollInfo(docSz, pageSz: CGFloat; rl: NSSCroller; Var ScrollInfo: TScrollInfo); diff --git a/lcl/interfaces/cocoa/cocoaprivate.pp b/lcl/interfaces/cocoa/cocoaprivate.pp index 6d9ea24379..4b2648b112 100644 --- a/lcl/interfaces/cocoa/cocoaprivate.pp +++ b/lcl/interfaces/cocoa/cocoaprivate.pp @@ -610,7 +610,7 @@ type TCocoaScrollBar = objcclass(NSScroller) public callback: ICommonCallback; - // minInt,maxInt are used to calculate POS on callback event + // minInt,maxInt are used to calculate position for lclPos and lclSetPos minInt : Integer; maxInt : Integer; pageInt : Integer; @@ -623,6 +623,8 @@ type procedure lclClearCallback; override; procedure resetCursorRects; override; function lclIsHandle: Boolean; override; + function lclPos: Integer; message 'lclPos'; + procedure lclSetPos(aPos: integer); message 'lclSetPos:'; end; TCocoaListBox = objcclass; @@ -1864,7 +1866,9 @@ end; procedure TCocoaScrollBar.actionScrolling(sender: NSObject); begin if Assigned(callback) then - callback.scroll( not IsHorizontal(), Round(floatValue * (maxInt-minInt))); + begin + callback.scroll( not IsHorizontal(), lclPos); + end; end; function TCocoaScrollBar.IsHorizontal: Boolean; @@ -1877,6 +1881,26 @@ begin Result := True; end; +function TCocoaScrollBar.lclPos: Integer; +begin + Result:=round( floatValue * (maxint-minInt)) + minInt; +end; + +procedure TCocoaScrollBar.lclSetPos(aPos: integer); +var + d : integer; +begin + d := maxInt - minInt; + if d = 0 then + setDoubleValue(0) + else + begin + if aPos < minInt then aPos:=minInt + else if aPos > maxInt then aPos:=maxInt; + setDoubleValue( (aPos - minInt) / d ); + end; +end; + function TCocoaScrollBar.acceptsFirstResponder: Boolean; begin Result := True; diff --git a/lcl/interfaces/cocoa/cocoawinapi.inc b/lcl/interfaces/cocoa/cocoawinapi.inc index 0490f7194f..931aaa7264 100644 --- a/lcl/interfaces/cocoa/cocoawinapi.inc +++ b/lcl/interfaces/cocoa/cocoawinapi.inc @@ -1620,7 +1620,16 @@ begin Result := Assigned(obj); if not Result then Exit; - if obj.isKindOfClass(NSScrollView) then + if obj.isKindOfClass(TCocoaScrollBar) then + Result := CocoaScrollBarGetScrollInfo(TCocoaScrollBar(obj), ScrollInfo) + else + if obj.isKindOfClass(TCocoaManualScrollView) then + begin + if BarFlag = SB_Vert then + Result := CocoaScrollBarGetScrollInfo( TCocoaScrollBar(TCocoaManualScrollView(obj).verticalScroller), ScrollInfo) + else + Result := CocoaScrollBarGetScrollInfo( TCocoaScrollBar(TCocoaManualScrollView(obj).horizontalScroller), ScrollInfo); + end else if obj.isKindOfClass(NSScrollView) then NSScrollViewGetScrollInfo(NSScrollView(obj), BarFlag, ScrollInfo) else Result := False; @@ -2614,7 +2623,6 @@ 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)); @@ -2622,12 +2630,9 @@ begin 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 + // todo: parse the passed parameters. + // the content of the window could be already prepared + // thus not entire control should be invalided v.setNeedsDisplay_(true); end;