cocoa: initial implementation of TMemo control, improved WScontrols handle creation, initial CocoaScrollView implementation

git-svn-id: trunk@27274 -
This commit is contained in:
dmitry 2010-09-05 13:47:24 +00:00
parent 3cd980b72a
commit 9343928763
5 changed files with 286 additions and 42 deletions

View File

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

View File

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

View File

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

View File

@ -267,7 +267,8 @@ end;
function RegisterCustomMemo: Boolean; alias : 'WSRegisterCustomMemo';
begin
Result := False;
RegisterWSComponent(TCustomMemo, TCocoaWSCustomMemo);
Result := True;
end;
function RegisterButtonControl: Boolean; alias : 'WSRegisterButtonControl';

View File

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