mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-07 16:00:23 +02:00
cocoa: initial implementation of TMemo control, improved WScontrols handle creation, initial CocoaScrollView implementation
git-svn-id: trunk@27274 -
This commit is contained in:
parent
3cd980b72a
commit
9343928763
@ -49,11 +49,9 @@ type
|
||||
function lclClientFrame: TRect; message 'lclClientFrame';
|
||||
end;
|
||||
|
||||
{ LCLControlExtension }
|
||||
{ LCLViewExtension }
|
||||
|
||||
LCLControlExtension = objccategory(NSControl)
|
||||
function lclIsEnabled: Boolean; message 'lclIsEnabled';
|
||||
procedure lclSetEnabled(AEnabled: Boolean); message 'lclSetEnabled:';
|
||||
LCLViewExtension = objccategory(NSView)
|
||||
function lclIsVisible: Boolean; message 'lclIsVisible';
|
||||
procedure lclInvalidateRect(const r: TRect); message 'lclInvalidateRect:';
|
||||
procedure lclInvalidate; message 'lclInvalidate';
|
||||
@ -64,6 +62,13 @@ type
|
||||
function lclClientFrame: TRect; message 'lclClientFrame';
|
||||
end;
|
||||
|
||||
{ LCLControlExtension }
|
||||
|
||||
LCLControlExtension = objccategory(NSControl)
|
||||
function lclIsEnabled: Boolean; message 'lclIsEnabled';
|
||||
procedure lclSetEnabled(AEnabled: Boolean); message 'lclSetEnabled:';
|
||||
end;
|
||||
|
||||
{ LCLWindowExtension }
|
||||
|
||||
LCLWindowExtension = objccategory(NSWindow)
|
||||
@ -102,12 +107,6 @@ type
|
||||
procedure Resize; virtual; abstract;
|
||||
end;
|
||||
|
||||
{todo: consider using common protocol for all TCocoa* derived objcclasses }
|
||||
{TCocoaTopLeftRect = objcprotocol
|
||||
procedure getTopLeftFrame(var r: TRect); message 'getTopLeftFrame:';
|
||||
procedure setTopLeftFrame(const r: TRect); message 'setTopLeftFrame:';
|
||||
end;}
|
||||
|
||||
{ TCocoaButton }
|
||||
|
||||
TCocoaButton = objcclass(NSButton)
|
||||
@ -171,6 +170,10 @@ type
|
||||
procedure drawRect(dirtyRect: NSRect); override;
|
||||
end;
|
||||
|
||||
TCocoaScrollView = objcclass(NSScrollView)
|
||||
callback : TCommonCallback;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
{ TCocoaButton }
|
||||
@ -442,32 +445,32 @@ begin
|
||||
SetEnabled(AEnabled);
|
||||
end;
|
||||
|
||||
function LCLControlExtension.lclIsVisible:Boolean;
|
||||
function LCLViewExtension.lclIsVisible:Boolean;
|
||||
begin
|
||||
Result:=not isHidden;
|
||||
end;
|
||||
|
||||
procedure LCLControlExtension.lclInvalidateRect(const r:TRect);
|
||||
procedure LCLViewExtension.lclInvalidateRect(const r:TRect);
|
||||
begin
|
||||
setNeedsDisplayInRect(RectToViewCoord(Self, r));
|
||||
end;
|
||||
|
||||
procedure LCLControlExtension.lclInvalidate;
|
||||
procedure LCLViewExtension.lclInvalidate;
|
||||
begin
|
||||
setNeedsDisplay;
|
||||
setNeedsDisplay_(True);
|
||||
end;
|
||||
|
||||
procedure LCLControlExtension.lclLocalToScreen(var X,Y:Integer);
|
||||
procedure LCLViewExtension.lclLocalToScreen(var X,Y:Integer);
|
||||
begin
|
||||
|
||||
end;
|
||||
|
||||
function LCLControlExtension.lclParent:id;
|
||||
function LCLViewExtension.lclParent:id;
|
||||
begin
|
||||
Result:=superView;
|
||||
end;
|
||||
|
||||
function LCLControlExtension.lclFrame: TRect;
|
||||
function LCLViewExtension.lclFrame: TRect;
|
||||
var
|
||||
v : NSView;
|
||||
begin
|
||||
@ -477,7 +480,7 @@ begin
|
||||
else NSToLCLRect(frame, Result);
|
||||
end;
|
||||
|
||||
procedure LCLControlExtension.lclSetFrame(const r:TRect);
|
||||
procedure LCLViewExtension.lclSetFrame(const r:TRect);
|
||||
var
|
||||
ns : NSRect;
|
||||
begin
|
||||
@ -487,7 +490,7 @@ begin
|
||||
setFrame(ns);
|
||||
end;
|
||||
|
||||
function LCLControlExtension.lclClientFrame:TRect;
|
||||
function LCLViewExtension.lclClientFrame:TRect;
|
||||
var
|
||||
r: NSRect;
|
||||
begin
|
||||
|
@ -9,6 +9,9 @@ uses
|
||||
MacOSAll, CocoaAll,
|
||||
Types, LCLType;
|
||||
|
||||
const
|
||||
NSNullRect : NSRect = (origin:(x:0; y:0); size:(width:0; height:0));
|
||||
|
||||
function GetNSPoint(x,y: single): NSPoint; inline;
|
||||
|
||||
function GetCGRect(x1, y1, x2, y2: Integer): CGRect;
|
||||
|
@ -14,6 +14,12 @@ uses
|
||||
|
||||
type
|
||||
|
||||
{ LCLWSViewExtension }
|
||||
|
||||
LCLWSViewExtension = objccategory(NSView)
|
||||
function lclInitWithCreateParams(const AParams: TCreateParams): id; message 'lclInitWithCreateParams:';
|
||||
end;
|
||||
|
||||
{ TLCLCommonCallback }
|
||||
|
||||
TLCLCommonCallback = class(TCommonCallback)
|
||||
@ -53,10 +59,12 @@ type
|
||||
const AParams: TCreateParams): TLCLIntfHandle; override;
|
||||
end;
|
||||
|
||||
|
||||
// Utility WS functions
|
||||
|
||||
function AllocCustomControl(const AWinControl: TWinControl): TCocoaCustomControl;
|
||||
procedure SetCreateParamsToControl(AControl: NSControl; const AParams: TCreateParams);
|
||||
function EmbedInScrollView(AView: NSView): TCocoaScrollView;
|
||||
procedure SetViewDefaults(AView: NSView);
|
||||
|
||||
implementation
|
||||
|
||||
@ -70,12 +78,32 @@ begin
|
||||
Result.callback:=TLCLCommonCallback.Create(Result, AWinControl);
|
||||
end;
|
||||
|
||||
procedure SetCreateParamsToControl(AControl: NSControl; const AParams: TCreateParams);
|
||||
function EmbedInScrollView(AView:NSView):TCocoaScrollView;
|
||||
var
|
||||
r : TRect;
|
||||
p : NSView;
|
||||
f : NSRect;
|
||||
begin
|
||||
if not Assigned(AControl) then Exit;
|
||||
AddViewToNSObject(AControl, NSObject(AParams.WndParent), AParams.X, AParams.Y);
|
||||
if not Assigned(AView) then begin
|
||||
Result:=nil;
|
||||
Exit;
|
||||
end;
|
||||
r:=AView.lclFrame;
|
||||
p:=AView.superview;
|
||||
Result:=TCocoaScrollView.alloc.initWithFrame(NSNullRect);
|
||||
if Assigned(p) then p.addSubView(Result);
|
||||
Result.lclSetFrame(r);
|
||||
Result.setDocumentView(AView);
|
||||
SetViewDefaults(Result);
|
||||
end;
|
||||
|
||||
procedure SetViewDefaults(AView:NSView);
|
||||
begin
|
||||
if not Assigned(AView) then Exit;
|
||||
AView.setAutoresizingMask(NSViewMinYMargin or NSViewMaxXMargin);
|
||||
end;
|
||||
|
||||
|
||||
{ TLCLCommonCallback }
|
||||
|
||||
constructor TLCLCommonCallback.Create(AOwner: NSObject; ATarget: TControl);
|
||||
@ -204,10 +232,36 @@ class function TCocoaWSCustomControl.CreateHandle(const AWinControl: TWinControl
|
||||
var
|
||||
ctrl : TCocoaCustomControl;
|
||||
begin
|
||||
ctrl:=AllocCustomControl(AWinControl);
|
||||
SetCreateParamsToControl(ctrl, AParams);
|
||||
ctrl:=TCocoaCustomControl( NSView(TCocoaCustomControl.alloc).lclInitWithCreateParams(AParams));
|
||||
ctrl.callback:=TLCLCommonCallback.Create(ctrl, AWinControl);
|
||||
Result:=TLCLIntfHandle(ctrl);
|
||||
end;
|
||||
|
||||
{ LCLWSViewExtension }
|
||||
|
||||
function LCLWSViewExtension.lclInitWithCreateParams(const AParams:TCreateParams): id;
|
||||
var
|
||||
r: TRect;
|
||||
begin
|
||||
Result:=initWithFrame(NSNullRect);
|
||||
if not Assigned(Result) then Exit;
|
||||
|
||||
if (AParams.WndParent<>0) then begin
|
||||
if (NSObject(AParams.WndParent).isKindOfClass_(NSView)) then
|
||||
NSView(AParams.WndParent).addSubview(Self)
|
||||
else if (NSObject(AParams.WndParent).isKindOfClass_(NSWindow)) then
|
||||
NSWindow(AParams.WndParent).contentView.addSubview(Self)
|
||||
end;
|
||||
with AParams do begin
|
||||
r.left:=X;
|
||||
r.Top:=Y;
|
||||
r.Right:=X+Width;
|
||||
r.Bottom:=X+Height;
|
||||
end;
|
||||
Self.lclSetFrame(r);
|
||||
|
||||
SetViewDefaults(Self);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
@ -267,7 +267,8 @@ end;
|
||||
|
||||
function RegisterCustomMemo: Boolean; alias : 'WSRegisterCustomMemo';
|
||||
begin
|
||||
Result := False;
|
||||
RegisterWSComponent(TCustomMemo, TCocoaWSCustomMemo);
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
function RegisterButtonControl: Boolean; alias : 'WSRegisterButtonControl';
|
||||
|
@ -151,14 +151,18 @@ type
|
||||
{ TCocoaWSCustomMemo }
|
||||
|
||||
TCocoaWSCustomMemo = class(TWSCustomMemo)
|
||||
{published
|
||||
published
|
||||
class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override;
|
||||
class function GetStrings(const ACustomMemo: TCustomMemo): TStrings; override;
|
||||
|
||||
class procedure AppendText(const ACustomMemo: TCustomMemo; const AText: string); override;
|
||||
class procedure SetAlignment(const ACustomMemo: TCustomMemo; const AAlignment: TAlignment); override;
|
||||
{class procedure SetAlignment(const ACustomMemo: TCustomMemo; const AAlignment: TAlignment); override;
|
||||
class procedure SetScrollbars(const ACustomMemo: TCustomMemo; const NewScrollbars: TScrollStyle); override;
|
||||
class procedure SetWordWrap(const ACustomMemo: TCustomMemo; const NewWordWrap: boolean); override;}
|
||||
class procedure SetReadOnly(const ACustomEdit: TCustomEdit; NewReadOnly: boolean); override;
|
||||
|
||||
class procedure SetText(const AWinControl: TWinControl; const AText: String); override;
|
||||
class function GetText(const AWinControl: TWinControl; var AText: String): Boolean; override;
|
||||
end;
|
||||
|
||||
{ TCocoaWSEdit }
|
||||
@ -264,21 +268,15 @@ function AllocSecureTextField(ATarget: TWinControl; const AParams: TCreateParams
|
||||
|
||||
implementation
|
||||
|
||||
procedure DefaultViewSettings(view: NSView);
|
||||
begin
|
||||
view.setAutoresizingMask(NSViewMinYMargin or NSViewMaxXMargin);
|
||||
end;
|
||||
|
||||
function AllocButton(ATarget: TWinControl; const AParams: TCreateParams; btnBezel: NSBezelStyle; btnType: NSButtonType): NSButton;
|
||||
begin
|
||||
Result:=TCocoaButton.alloc;
|
||||
Result:=TCocoaButton.alloc.lclInitWithCreateParams(AParams);
|
||||
if Assigned(Result) then begin
|
||||
TCocoaButton(Result).callback:=TLCLCommonCallback.Create(Result, ATarget);
|
||||
Result.initWithFrame(CreateParamsToNSRect(AParams));
|
||||
Result.setTitle(NSStringUTF8(AParams.Caption));
|
||||
if btnBezel<>0 then Result.setBezelStyle(btnBezel);
|
||||
Result.setButtonType(btnType);
|
||||
DefaultViewSettings(Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -288,19 +286,16 @@ begin
|
||||
if Assigned(Result) then begin
|
||||
TCocoaTextView(Result).callback:=TLCLCommonCallback.Create(Result, ATarget);
|
||||
Result.initWithFrame(CreateParamsToNSRect(AParams));
|
||||
DefaultViewSettings(Result);
|
||||
Result.setFieldEditor(fieldEditor);
|
||||
end;
|
||||
end;
|
||||
|
||||
function AllocTextField(ATarget: TWinControl; const AParams: TCreateParams): TCocoaTextField;
|
||||
begin
|
||||
Result:=TCocoaTextField(TCocoaTextField.alloc);
|
||||
Result:=TCocoaTextField(TCocoaTextField.alloc.lclInitWithCreateParams(AParams));
|
||||
if Assigned(Result) then begin
|
||||
TCocoaTextField(Result).callback:=TLCLCommonCallback.Create(Result, ATarget);
|
||||
Result.initWithFrame(CreateParamsToNSRect(AParams));
|
||||
SetNSControlValue(Result, AParams.Caption);
|
||||
DefaultViewSettings(Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -311,7 +306,6 @@ begin
|
||||
TCocoaSecureTextField(Result).callback:=TLCLCommonCallback.Create(Result, ATarget);
|
||||
Result.initWithFrame(CreateParamsToNSRect(AParams));
|
||||
SetNSText(Result.currentEditor, AParams.Caption);
|
||||
DefaultViewSettings(Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -422,7 +416,6 @@ var
|
||||
btn : NSButton;
|
||||
begin
|
||||
btn:=AllocButton(AWinControl, AParams, 0, NSRadioButton);
|
||||
SetCreateParamsToControl(btn, AParams);
|
||||
Result:=TLCLIntfHandle(btn);
|
||||
end;
|
||||
|
||||
@ -435,7 +428,6 @@ begin
|
||||
if TCustomEdit(AWinControl).PasswordChar=#0
|
||||
then field:=NSTextField(AllocTextField(AWinControl, AParams))
|
||||
else field:=NSTextField(AllocSecureTextField(AWinControl, AParams));
|
||||
SetCreateParamsToControl(field, AParams);
|
||||
Result:=TLCLIntfHandle(field);
|
||||
end;
|
||||
|
||||
@ -479,5 +471,196 @@ begin
|
||||
// NSTextField(ACustomEdit.Handle).setEditable(not NewReadOnly);
|
||||
end;
|
||||
|
||||
|
||||
type
|
||||
|
||||
{ TCocoaMemoStrings }
|
||||
|
||||
TCocoaMemoStrings = class(TStrings)
|
||||
private
|
||||
fTextView : NSTextView;
|
||||
protected
|
||||
function GetTextStr: string; override;
|
||||
procedure SetTextStr(const Value: string); override;
|
||||
function GetCount: Integer; override;
|
||||
function Get(Index: Integer): string; override;
|
||||
public
|
||||
constructor Create(AText: NSTextView);
|
||||
procedure Clear; override;
|
||||
procedure Delete(Index: Integer); override;
|
||||
procedure Insert(Index: Integer; const S: string); override;
|
||||
end;
|
||||
|
||||
{ TCocoaMemoStrings }
|
||||
|
||||
constructor TCocoaMemoStrings.Create(AText:NSTextView);
|
||||
begin
|
||||
fTextView:=AText;
|
||||
inherited Create;
|
||||
end;
|
||||
|
||||
function TCocoaMemoStrings.GetTextStr:string;
|
||||
begin
|
||||
Result:=NSStringToString(fTextView.textStorage.string_);
|
||||
end;
|
||||
|
||||
procedure TCocoaMemoStrings.SetTextStr(const Value:string);
|
||||
begin
|
||||
fTextView.textStorage.mutableString.setString(NSStringUtf8(Value));
|
||||
end;
|
||||
|
||||
procedure GetLineStart(const s: AnsiString; LineIndex: Integer; var Offset, LinesSkipped: Integer);
|
||||
var
|
||||
i : Integer;
|
||||
begin
|
||||
i:=1;
|
||||
LinesSkipped:=0;
|
||||
while (LinesSkipped<>LineIndex) and (i<=length(s)) do begin
|
||||
if s[i] in [#10, #13] then begin
|
||||
inc(i);
|
||||
inc(LinesSkipped);
|
||||
if (i<=length(s)) and (s[i] in [#10,#13]) and (s[i-1]<>s[i]) then
|
||||
inc(i);
|
||||
end else
|
||||
inc(i);
|
||||
end;
|
||||
Offset:=i;
|
||||
end;
|
||||
|
||||
function GetLinesCount(const s: AnsiString): Integer;
|
||||
var
|
||||
ofs : Integer;
|
||||
begin
|
||||
GetLineStart(s, -1, ofs, Result);
|
||||
end;
|
||||
|
||||
function TCocoaMemoStrings.GetCount:Integer;
|
||||
begin
|
||||
Result:=GetLinesCount(GetTextStr);
|
||||
inc(Result);
|
||||
end;
|
||||
|
||||
function TCocoaMemoStrings.Get(Index:Integer):string;
|
||||
var
|
||||
s : AnsiString;
|
||||
ofs : Integer;
|
||||
eofs : Integer;
|
||||
t : Integer;
|
||||
begin
|
||||
s:=GetTextStr;
|
||||
GetLineStart(s, Index, ofs, t);
|
||||
eofs:=ofs;
|
||||
while (eofs<=length(s)) and not (s[eofs] in [#10,#13]) do
|
||||
inc(eofs);
|
||||
Result:=Copy(s, ofs, eofs-ofs);
|
||||
end;
|
||||
|
||||
procedure TCocoaMemoStrings.Clear;
|
||||
begin
|
||||
SetTextStr('');
|
||||
end;
|
||||
|
||||
procedure TCocoaMemoStrings.Delete(Index:Integer);
|
||||
var
|
||||
s : AnsiString;
|
||||
ofs : Integer;
|
||||
eofs : Integer;
|
||||
t : Integer;
|
||||
begin
|
||||
s:=GetTextStr;
|
||||
GetLineStart(s, Index, ofs, t);
|
||||
eofs:=ofs;
|
||||
while (eofs<=length(s)) and not (s[eofs] in [#10,#13]) do
|
||||
inc(eofs);
|
||||
if eofs<=length(s) then begin
|
||||
inc(eofs);
|
||||
if (eofs<=length(s)) and (s[eofs] in [#10,#13]) and (s[eofs-1]<>s[eofs]) then
|
||||
inc(eofs);
|
||||
end;
|
||||
System.Delete(s, ofs, eofs-ofs);
|
||||
SetTextStr(s);
|
||||
end;
|
||||
|
||||
procedure TCocoaMemoStrings.Insert(Index:Integer;const S:string);
|
||||
var
|
||||
txt : AnsiString;
|
||||
ofs : Integer;
|
||||
t : Integer;
|
||||
begin
|
||||
txt:=GetTextStr;
|
||||
GetLineStart(txt, Index, ofs, t);
|
||||
System.Insert(s+LineEnding, txt, ofs);
|
||||
SetTextStr(txt)
|
||||
end;
|
||||
|
||||
{ TCocoaWSCustomMemo }
|
||||
|
||||
function MemoTextView(AWinControl: TWinControl): TCocoaTextView;
|
||||
begin
|
||||
if not Assigned(AWinControl) or (AWinControl.Handle=0) then
|
||||
Result:=nil
|
||||
else
|
||||
Result:=TCocoaTextView(NSScrollView(AWinControl.Handle).documentView);
|
||||
end;
|
||||
|
||||
class function TCocoaWSCustomMemo.CreateHandle(const AWinControl:TWinControl;
|
||||
const AParams:TCreateParams):TLCLIntfHandle;
|
||||
var
|
||||
txt : TCocoaTextView;
|
||||
scr : TCocoaScrollView;
|
||||
begin
|
||||
txt:=TCocoaTextView( NSView(TCocoaTextView.alloc).lclInitWithCreateParams(AParams));
|
||||
txt.textStorage.mutableString.setString(NSStringUtf8(AParams.Caption));
|
||||
scr:=EmbedInScrollView(txt);
|
||||
scr.callback:=txt.callback;
|
||||
Result:=TLCLIntfHandle(scr);
|
||||
end;
|
||||
|
||||
class function TCocoaWSCustomMemo.GetStrings(const ACustomMemo:TCustomMemo): TStrings;
|
||||
var
|
||||
txt : TCocoaTextView;
|
||||
begin
|
||||
txt:=MemoTextView(ACustomMemo);
|
||||
if Assigned(txt) then
|
||||
Result := TCocoaMemoStrings.Create(txt)
|
||||
else
|
||||
Result := nil
|
||||
end;
|
||||
|
||||
class procedure TCocoaWSCustomMemo.AppendText(const ACustomMemo:TCustomMemo;
|
||||
const AText:string);
|
||||
begin
|
||||
//todo:
|
||||
end;
|
||||
|
||||
class procedure TCocoaWSCustomMemo.SetReadOnly(const ACustomEdit:TCustomEdit;
|
||||
NewReadOnly:boolean);
|
||||
var
|
||||
txt : TCocoaTextView;
|
||||
begin
|
||||
txt:=MemoTextView(ACustomEdit);
|
||||
if not Assigned(txt) then Exit;
|
||||
txt.setEditable(not NewReadOnly);
|
||||
end;
|
||||
|
||||
class procedure TCocoaWSCustomMemo.SetText(const AWinControl:TWinControl;const AText:String);
|
||||
var
|
||||
txt : TCocoaTextView;
|
||||
begin
|
||||
txt:=MemoTextView(AWinControl);
|
||||
if not Assigned(txt) then Exit;
|
||||
txt.textStorage.mutableString.setString(NSStringUtf8(AText));
|
||||
end;
|
||||
|
||||
class function TCocoaWSCustomMemo.GetText(const AWinControl:TWinControl;var AText:String):Boolean;
|
||||
var
|
||||
txt : TCocoaTextView;
|
||||
begin
|
||||
txt:=MemoTextView(AWinControl);
|
||||
Result:=Assigned(txt);
|
||||
if Result then
|
||||
AText:=NSStringToString(txt.textStorage.string_);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user