mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-12 00:37:47 +02:00
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:
parent
edee7ec8ef
commit
98712b414a
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user