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 -
This commit is contained in:
dmitry 2018-01-05 05:17:04 +00:00
parent 9770119ed5
commit 611c971eaf
3 changed files with 58 additions and 18 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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;