
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4140 8e941d3f-bd1b-0410-a28a-d453659cc2b4
602 lines
18 KiB
ObjectPascal
602 lines
18 KiB
ObjectPascal
unit CocoaRichMemo;
|
|
|
|
interface
|
|
|
|
{$mode delphi}
|
|
{$modeswitch objectivec1}
|
|
{$modeswitch objectivec2}
|
|
|
|
uses
|
|
CocoaAll, Classes, SysUtils,
|
|
LCLType, Graphics, Controls, StdCtrls,
|
|
CocoaPrivate, CocoaUtils, CocoaWSCommon,
|
|
WSRichMemo, RichMemo;
|
|
|
|
type
|
|
TCocoaRichView = objcclass(TCocoaTextView)
|
|
public
|
|
scale : Double;
|
|
end;
|
|
|
|
{ TCocoaWSCustomRichMemo }
|
|
|
|
TCocoaWSCustomRichMemo = class(TWSCustomRichMemo)
|
|
public
|
|
class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override;
|
|
|
|
class function GetTextAttributes(const AWinControl: TWinControl; TextStart: Integer;
|
|
var Params: TIntFontParams): Boolean; override;
|
|
class procedure SetTextAttributes(const AWinControl: TWinControl; TextStart, TextLen: Integer;
|
|
const Params: TIntFontParams); override;
|
|
|
|
class procedure SetParaAlignment(const AWinControl: TWinControl; TextStart, TextLen: Integer;
|
|
const AAlign: TIntParaAlignment); override;
|
|
class function GetParaAlignment(const AWinControl: TWinControl; TextStart: Integer;
|
|
var AAlign: TIntParaAlignment): Boolean; override;
|
|
|
|
class function GetParaMetric(const AWinControl: TWinControl; TextStart: Integer;
|
|
var AMetric: TIntParaMetric): Boolean; override;
|
|
class procedure SetParaMetric(const AWinControl: TWinControl; TextStart, TextLen: Integer;
|
|
const AMetric: TIntParaMetric); override;
|
|
|
|
class procedure SetParaTabs(const AWinControl: TWinControl; TextStart, TextLen: Integer;
|
|
const AStopList: TTabStopList); override;
|
|
class function GetParaTabs(const AWinControl: TWinControl; TextStart: integer;
|
|
var AStopList: TTabStopList): Boolean; override;
|
|
|
|
class procedure SetZoomFactor(const AWinControl: TWinControl; AZoomFactor: Double); override;
|
|
|
|
class procedure InDelText(const AWinControl: TWinControl;
|
|
const TextUTF8: String; DstStart, DstLen: Integer); override;
|
|
class function LoadRichText(const AWinControl: TWinControl; Source: TStream): Boolean; override;
|
|
end;
|
|
|
|
implementation
|
|
|
|
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;
|
|
|
|
function ParaRange(txt: NSString; textOffset, TextLen: Integer): NSRange; overload;
|
|
begin
|
|
Result.location:=textOffset;
|
|
if textOffset+TextLen>txt.length then
|
|
Result.length:=txt.length-textOffset
|
|
else
|
|
Result.length:=TextLen;
|
|
Result:=txt.paragraphRangeForRange(Result);
|
|
end;
|
|
|
|
function ParaRange(txt: NSTextStorage; textOffset, TextLen: Integer): NSRange; inline; overload;
|
|
begin
|
|
Result:=ParaRange(txt.string_, textOffset, textLen);
|
|
end;
|
|
|
|
function TextRange(txt: NSTextStorage; textOffset, TextLen: Integer): NSRange; inline; overload;
|
|
begin
|
|
Result.location:=textOffset;
|
|
if textOffset+TextLen>txt.length then
|
|
Result.length:=txt.length-textOffset
|
|
else
|
|
Result.length:=TextLen;
|
|
end;
|
|
|
|
|
|
function GetDict(txt: NSTextStorage; textOffset: integer): NSDictionary;
|
|
begin
|
|
if textOffset>=txt.string_.length then
|
|
textOffset:=txt.string_.length-1;
|
|
Result := txt.attributesAtIndex_effectiveRange(textOffset, nil);
|
|
end;
|
|
|
|
function GetPara(txt: NSTextStorage; textOffset: integer; isReadOnly, useDefault: Boolean): NSParagraphStyle;
|
|
var
|
|
dict: NSDictionary;
|
|
op : NSParagraphStyle;
|
|
begin
|
|
Result:=nil;
|
|
if not Assigned(txt) then Exit;
|
|
dict:=GetDict(txt, textOffset);
|
|
op:=nil;
|
|
if Assigned(dict) then
|
|
op:=NSParagraphStyle( dict.objectForKey(NSParagraphStyleAttributeName) );
|
|
|
|
if not Assigned(op) then begin
|
|
if not useDefault then Exit;
|
|
op:=NSParagraphStyle.defaultParagraphStyle;
|
|
end;
|
|
|
|
if isReadOnly then
|
|
Result := op
|
|
else
|
|
Result := op.mutableCopyWithZone(nil)
|
|
end;
|
|
|
|
function GetWritePara(txt: NSTextStorage; textOffset: integer): NSMutableParagraphStyle;
|
|
begin
|
|
Result:=NSMutableParagraphStyle(GetPara(txt, textOffset, false, true));
|
|
end;
|
|
|
|
function GetReadPara(txt: NSTextStorage; textOffset: integer; useDefault: Boolean = false): NSParagraphStyle;
|
|
begin
|
|
Result:=GetPara(txt, textOffset, true, useDefault);
|
|
end;
|
|
|
|
type
|
|
TNSFontParams = record
|
|
font : NSFont;
|
|
fontColor : NSColor;
|
|
backColor : NSColor;
|
|
ulnStyle : NSNumber;
|
|
strStyle : NSNumber;
|
|
end;
|
|
|
|
procedure ReadNSFontParams(dict: NSDictionary; var params: TNSFontParams);
|
|
begin
|
|
if not Assigned(dict) then FillChar(params, sizeof(params),0)
|
|
else begin
|
|
params.font:=dict.objectForKey(NSFontAttributeName);
|
|
params.fontColor:=dict.objectForKey(NSForegroundColorAttributeName);
|
|
params.backColor:=dict.objectForKey(NSBackgroundColorAttributeName);
|
|
params.ulnStyle:=dict.objectForKey(NSUnderlineStyleAttributeName);
|
|
params.strStyle:=dict.objectForKey(NSStrikethroughStyleAttributeName);
|
|
end;
|
|
end;
|
|
|
|
{ TCocoaWSCustomRichMemo }
|
|
|
|
const
|
|
VerticalScrollerVisible: array[TScrollStyle] of boolean = (
|
|
{ssNone } false,
|
|
{ssHorizontal } false,
|
|
{ssVertical } true,
|
|
{ssBoth } true,
|
|
{ssAutoHorizontal} false,
|
|
{ssAutoVertical } true,
|
|
{ssAutoBoth } true
|
|
);
|
|
|
|
HorizontalScrollerVisible: array[TScrollStyle] of boolean = (
|
|
{ssNone } false,
|
|
{ssHorizontal } true,
|
|
{ssVertical } false,
|
|
{ssBoth } true,
|
|
{ssAutoHorizontal} true,
|
|
{ssAutoVertical } false,
|
|
{ssAutoBoth } true
|
|
);
|
|
|
|
ScrollerAutoHide: array[TScrollStyle] of boolean = (
|
|
{ssNone } false,
|
|
{ssHorizontal } false,
|
|
{ssVertical } false,
|
|
{ssBoth } false,
|
|
{ssAutoHorizontal} true,
|
|
{ssAutoVertical } true,
|
|
{ssAutoBoth } true
|
|
);
|
|
|
|
class function TCocoaWSCustomRichMemo.CreateHandle(
|
|
const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle;
|
|
var
|
|
txt: TCocoaRichView;
|
|
ns: NSString;
|
|
scr: TCocoaScrollView;
|
|
nr:NSRect;
|
|
r:TRect;
|
|
begin
|
|
scr := TCocoaScrollView(NSView(TCocoaScrollView.alloc).lclInitWithCreateParams(AParams));
|
|
|
|
nr.origin.x:=0;
|
|
nr.origin.x:=0;
|
|
nr.size.height:=0;
|
|
nr.size.width:=AParams.Width;
|
|
|
|
txt := TCocoaRichView.alloc.initwithframe(nr);
|
|
txt.scale := 1.0;
|
|
|
|
scr.setDocumentView(txt);
|
|
|
|
scr.setHasVerticalScroller(VerticalScrollerVisible[TMemo(AWinControl).ScrollBars]);
|
|
scr.setHasHorizontalScroller(HorizontalScrollerVisible[TMemo(AWinControl).ScrollBars]);
|
|
scr.setAutohidesScrollers(ScrollerAutoHide[TMemo(AWinControl).ScrollBars]);
|
|
|
|
if TCustomMemo(AWinControl).BorderStyle=bsSingle then
|
|
scr.setBorderType(NSBezelBorder);
|
|
|
|
nr:=scr.documentVisibleRect;
|
|
txt.setFrame(nr);
|
|
txt.textContainer.setLineFragmentPadding(0);
|
|
|
|
txt.callback := TLCLCommonCallback.Create(txt, AWinControl);
|
|
ns := NSStringUtf8(AParams.Caption);
|
|
txt.setString(ns);
|
|
ns.release;
|
|
|
|
scr.callback := txt.callback;
|
|
Result := TLCLIntfHandle(scr);
|
|
end;
|
|
|
|
class function TCocoaWSCustomRichMemo.GetTextAttributes(
|
|
const AWinControl: TWinControl; TextStart: Integer; var Params: TIntFontParams
|
|
): Boolean;
|
|
var
|
|
view : TCocoaTextView;
|
|
txt : NSTextStorage;
|
|
dict : NSDictionary;
|
|
|
|
prm : TNSFontParams;
|
|
trt : NSFontSymbolicTraits;
|
|
begin
|
|
InitFontParams(Params);
|
|
view:=MemoTextView(AWinControl);
|
|
Result:=false;
|
|
if not Assigned(view) then Exit;
|
|
|
|
txt:=view.textStorage;
|
|
dict:=GetDict(txt, textStart);
|
|
ReadNSFontParams(dict, prm);
|
|
if Assigned(prm.font) then begin
|
|
Params.Name:=NSStringToString(prm.font.familyName);
|
|
Params.Size:=round(prm.font.pointSize);
|
|
trt:=prm.font.fontDescriptor.symbolicTraits;
|
|
if (trt and NSFontItalicTrait) > 0 then Include(Params.Style, fsItalic);
|
|
if (trt and NSFontBoldTrait) > 0 then Include(Params.Style, fsBold);
|
|
end;
|
|
if Assigned(prm.ulnStyle) and (prm.ulnStyle.integerValue <> NSUnderlineStyleNone) then
|
|
Include(Params.Style, fsUnderline);
|
|
if Assigned(prm.strStyle) and (prm.strStyle.integerValue <> NSUnderlineStyleNone) then
|
|
Include(Params.Style, fsStrikeOut);
|
|
if Assigned(prm.fontColor) then
|
|
Params.Color:=NSColorToColorRef(prm.fontColor);
|
|
Params.HasBkClr:=Assigned(prm.backColor);
|
|
if Params.HasBkClr then
|
|
Params.BkColor:=NSColorToColorRef(prm.backColor);
|
|
Result:=true;
|
|
end;
|
|
|
|
function FindFont(const FamilyName: String; astyle: TFontStyles): NSFontDescriptor;
|
|
var
|
|
fd : NSFontDescriptor;
|
|
old : NSFontDescriptor;
|
|
fdd : NSFontDescriptor;
|
|
trt : NSFontSymbolicTraits;
|
|
ns : NSString;
|
|
i : Integer;
|
|
const
|
|
fallback : array [0..1] of NSFontSymbolicTraits = (NSFontItalicTrait, NSFontBoldTrait);
|
|
begin
|
|
trt:=0;
|
|
ns:=NSStringUtf8(FamilyName);
|
|
if fsItalic in aStyle then trt:=trt or NSFontItalicTrait;
|
|
if fsBold in aStyle then trt:=trt or NSFontBoldTrait;
|
|
|
|
fd:=NSFontDescriptor(NSFontDescriptor.alloc).initWithFontAttributes(nil);
|
|
fd:=fd.fontDescriptorWithFamily(ns);
|
|
fd:=fd.fontDescriptorWithSymbolicTraits(trt);
|
|
|
|
fdd:=fd.matchingFontDescriptorWithMandatoryKeys(nil);
|
|
i:=0;
|
|
while not Assigned(fdd) and (i<length(fallback)) do begin
|
|
trt:=trt and (not fallback[i]);
|
|
fd:=fd.fontDescriptorWithSymbolicTraits(trt);
|
|
fdd:=fd.matchingFontDescriptorWithMandatoryKeys(nil);
|
|
end;
|
|
Result:=fdd;
|
|
ns.release;
|
|
end;
|
|
|
|
class procedure TCocoaWSCustomRichMemo.SetTextAttributes(
|
|
const AWinControl: TWinControl; TextStart, TextLen: Integer;
|
|
const Params: TIntFontParams);
|
|
var
|
|
view : TCocoaTextView;
|
|
txt : NSTextStorage;
|
|
|
|
fd : NSFontDescriptor;
|
|
font : NSFont;
|
|
rng : NSRange;
|
|
clr : NSColor;
|
|
num : NSNumber;
|
|
arr : NSArray;
|
|
|
|
begin
|
|
view:=MemoTextView(AWinControl);
|
|
if not Assigned(view) then Exit;
|
|
|
|
txt:=view.textStorage;
|
|
|
|
rng := TextRange(txt, TextStart, textLen);
|
|
|
|
fd:=FindFont(Params.Name, Params.Style);
|
|
font:=NSFont.fontWithDescriptor_size(fd, Params.Size);
|
|
txt.addAttribute_value_range(NSFontAttributeName, font, rng);
|
|
// fd.release;
|
|
|
|
if fsUnderline in Params.Style then begin
|
|
num:=NSNumber.numberWithInt(NSUnderlineStyleSingle);
|
|
txt.addAttribute_value_range(NSUnderlineStyleAttributeName, num, rng);
|
|
num.release;
|
|
end else
|
|
txt.removeAttribute_range(NSUnderlineStyleAttributeName, rng);
|
|
|
|
if fsStrikeOut in Params.Style then begin
|
|
num:=NSNumber.numberWithInt(NSUnderlineStyleSingle);
|
|
txt.addAttribute_value_range(NSStrikethroughStyleAttributeName, num, rng);
|
|
num.release;
|
|
end else
|
|
txt.removeAttribute_range(NSStrikethroughStyleAttributeName, rng);
|
|
|
|
|
|
clr:=ColorToNSColor(Params.Color);
|
|
txt.addAttribute_value_range(NSForegroundColorAttributeName, clr, rng);
|
|
clr.release;
|
|
|
|
if Params.HasBkClr then begin
|
|
clr:=ColorToNSColor(Params.BkColor);
|
|
txt.addAttribute_value_range(NSBackgroundColorAttributeName, clr, rng);
|
|
clr.release;
|
|
end else
|
|
txt.removeAttribute_range(NSBackgroundColorAttributeName, rng);
|
|
|
|
end;
|
|
|
|
class procedure TCocoaWSCustomRichMemo.SetParaAlignment(
|
|
const AWinControl: TWinControl; TextStart, TextLen: Integer;
|
|
const AAlign: TIntParaAlignment);
|
|
var
|
|
txt : TCocoaTextView;
|
|
rng : NSRange;
|
|
const
|
|
TxtAlign : array [TIntParaAlignment] of integer = (
|
|
NSLeftTextAlignment, NSRightTextAlignment, NSCenterTextAlignment, NSJustifiedTextAlignment
|
|
);
|
|
begin
|
|
txt:=MemoTextView(AWinControl);
|
|
if not Assigned(txt) then Exit;
|
|
|
|
rng.location:=TextStart;
|
|
rng.length:=TextLen;
|
|
if TextStart+TextLen>txt.textStorage.string_.length then
|
|
rng.length:=txt.textStorage.string_.length-TextStart;
|
|
|
|
rng:=txt.textStorage.string_.paragraphRangeForRange(rng);
|
|
txt.setAlignment_range(TxtAlign[AAlign], rng);
|
|
end;
|
|
|
|
class function TCocoaWSCustomRichMemo.GetParaAlignment(
|
|
const AWinControl: TWinControl; TextStart: Integer;
|
|
var AAlign: TIntParaAlignment): Boolean;
|
|
var
|
|
txt : TCocoaTextView;
|
|
rng : NSRange;
|
|
cur : NSRange;
|
|
al : NSTextAlignment;
|
|
const
|
|
TxtAlign : array [TIntParaAlignment] of integer = (
|
|
NSLeftTextAlignment, NSRightTextAlignment, NSCenterTextAlignment, NSJustifiedTextAlignment
|
|
);
|
|
begin
|
|
txt:=MemoTextView(AWinControl);
|
|
if not Assigned(txt) then begin
|
|
Result:=false;
|
|
Exit;
|
|
end;
|
|
|
|
cur:=txt.selectedRange;
|
|
rng.location:=TextStart;
|
|
rng.length:=1;
|
|
if TextStart+1>txt.textStorage.string_.length then
|
|
rng.length:=txt.textStorage.string_.length-TextStart;
|
|
|
|
|
|
rng:=txt.textStorage.string_.paragraphRangeForRange(rng);
|
|
txt.setSelectedRange(rng);
|
|
al:=txt.alignment;
|
|
case al of
|
|
NSRightTextAlignment: AAlign:=paRight;
|
|
NSCenterTextAlignment: AAlign:=paCenter;
|
|
NSJustifiedTextAlignment: AAlign:=paJustify;
|
|
else
|
|
AAlign:=paLeft;
|
|
end;
|
|
txt.setSelectedRange(cur);
|
|
Result:=true;
|
|
end;
|
|
|
|
class function TCocoaWSCustomRichMemo.GetParaMetric(
|
|
const AWinControl: TWinControl; TextStart: Integer;
|
|
var AMetric: TIntParaMetric): Boolean;
|
|
var
|
|
view : TCocoaTextView;
|
|
txt : NSTextStorage;
|
|
par : NSParagraphStyle;
|
|
begin
|
|
InitParaMetric(AMetric);
|
|
view:=MemoTextView(AWinControl);
|
|
Result:=false;
|
|
if not Assigned(view) then Exit;
|
|
|
|
txt:=view.textStorage;
|
|
par:=GetReadPara(txt, TextStart, true);
|
|
|
|
AMetric.FirstLine := par.firstLineHeadIndent;
|
|
AMetric.HeadIndent := par.headIndent;
|
|
AMetric.TailIndent := par.tailIndent;
|
|
AMetric.LineSpacing := par.lineSpacing;
|
|
AMetric.SpaceAfter := par.paragraphSpacing;
|
|
AMetric.SpaceBefore := par.paragraphSpacingBefore;
|
|
|
|
Result:=true;
|
|
end;
|
|
|
|
class procedure TCocoaWSCustomRichMemo.SetParaMetric(
|
|
const AWinControl: TWinControl; TextStart, TextLen: Integer;
|
|
const AMetric: TIntParaMetric);
|
|
var
|
|
view : TCocoaTextView;
|
|
txt : NSTextStorage;
|
|
par : NSMutableParagraphStyle;
|
|
begin
|
|
view:=MemoTextView(AWinControl);
|
|
if not Assigned(view) then Exit;
|
|
|
|
txt:=view.textStorage;
|
|
par:=GetWritePara(txt, TextStart);
|
|
|
|
par.setFirstLineHeadIndent(AMetric.FirstLine);
|
|
par.setHeadIndent(AMetric.HeadIndent);
|
|
par.setTailIndent(AMetric.TailIndent);
|
|
par.setLineSpacing(AMetric.LineSpacing);
|
|
par.setParagraphSpacing(AMetric.SpaceAfter);
|
|
par.setParagraphSpacingBefore(AMetric.SpaceBefore);
|
|
|
|
txt.addAttribute_value_range( NSParagraphStyleAttributeName, par, ParaRange(txt, TextStart, textLen));
|
|
par.release;
|
|
end;
|
|
|
|
class procedure TCocoaWSCustomRichMemo.SetParaTabs(
|
|
const AWinControl: TWinControl; TextStart, TextLen: Integer;
|
|
const AStopList: TTabStopList);
|
|
var
|
|
view : TCocoaTextView;
|
|
txt : NSTextStorage;
|
|
par : NSMutableParagraphStyle;
|
|
tabs : NSMutableArray;
|
|
tab : NSTextTab;
|
|
i : Integer;
|
|
rng : NSRange;
|
|
const
|
|
TabAlignMap : array [TTabAlignment] of NSTextTabType = (
|
|
NSLeftTabStopType, // tabLeft,
|
|
NSCenterTabStopType, // tabCenter,
|
|
NSRightTabStopType, // tabRight,
|
|
NSDecimalTabStopType, // tabDecimal
|
|
NSLeftTabStopType // tabWordBar - not supported
|
|
);
|
|
begin
|
|
view:=MemoTextView(AWinControl);
|
|
if not Assigned(view) then Exit;
|
|
|
|
txt := view.textStorage;
|
|
par:=GetWritePara(txt, TextStart);
|
|
|
|
if AStopList.Count>0 then begin
|
|
tabs := NSMutableArray.alloc.init;
|
|
for i:=0 to AStopList.Count-1 do begin
|
|
tab := NSTextTab.alloc.initWithType_location( TabAlignMap[AStopList.Tabs[i].Align], AStopList.Tabs[i].Offset );
|
|
tabs.addObject( tab );
|
|
tab.release;
|
|
end;
|
|
end;
|
|
par.setTabStops(tabs);
|
|
txt.addAttribute_value_range( NSParagraphStyleAttributeName, par, ParaRange(txt, TextStart, textLen));
|
|
par.release;
|
|
end;
|
|
|
|
class function TCocoaWSCustomRichMemo.GetParaTabs(
|
|
const AWinControl: TWinControl; TextStart: integer;
|
|
var AStopList: TTabStopList): Boolean;
|
|
var
|
|
view : TCocoaTextView;
|
|
txt : NSTextStorage;
|
|
par : NSParagraphStyle;
|
|
tabs : NSArray;
|
|
tab : NSTextTab;
|
|
i : Integer;
|
|
begin
|
|
InitTabStopList(AStopList);
|
|
view:=MemoTextView(AWinControl);
|
|
Result:=false;
|
|
if not Assigned(view) then Exit;
|
|
|
|
txt:=view.textStorage;
|
|
par:=GetReadPara(txt, textStart, false);
|
|
if not Assigned(par) then Exit;
|
|
|
|
tabs:=par.tabStops;
|
|
if not Assigned(tabs) then Exit;
|
|
AStopList.Count:=tabs.count;
|
|
SetLength(AStopList.Tabs, AStopList.Count);
|
|
for i:=0 to tabs.count-1 do begin
|
|
tab:=NSTextTab(tabs.objectAtIndex(i));
|
|
AStopList.Tabs[i].Offset:=tab.location;
|
|
case tab.tabStopType of
|
|
NSCenterTabStopType: AStopList.Tabs[i].Align:= tabCenter;
|
|
NSRightTabStopType: AStopList.Tabs[i].Align:= tabRight;
|
|
NSDecimalTabStopType: AStopList.Tabs[i].Align:= tabDecimal;
|
|
else
|
|
AStopList.Tabs[i].Align:=taLeft;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
class procedure TCocoaWSCustomRichMemo.SetZoomFactor(
|
|
const AWinControl: TWinControl; AZoomFactor: Double);
|
|
var
|
|
view : TCocoaRichView;
|
|
sz : NSSize;
|
|
begin
|
|
view:=TCocoaRichView(MemoTextView(AWinControl));
|
|
if not Assigned(view) then Exit;
|
|
|
|
// reset Scaling
|
|
if view.scale<>1.0 then begin
|
|
sz.width:=1/view.scale;
|
|
sz.height:=1/view.scale;
|
|
view.scaleUnitSquareToSize(sz);
|
|
end;
|
|
|
|
// set new scaling
|
|
sz.width:=AZoomFactor;
|
|
sz.height:=AZoomFactor;
|
|
view.scaleUnitSquareToSize(sz);
|
|
view.layoutManager.ensureLayoutForTextContainer(view.textContainer);
|
|
|
|
view.scale:=AZoomFactor;
|
|
end;
|
|
|
|
class procedure TCocoaWSCustomRichMemo.InDelText(
|
|
const AWinControl: TWinControl; const TextUTF8: String; DstStart,
|
|
DstLen: Integer);
|
|
var
|
|
txt : TCocoaTextView;
|
|
str : NSString;
|
|
begin
|
|
txt:=MemoTextView(AWinControl);
|
|
if not Assigned(txt) then Exit;
|
|
|
|
str := NSStringUtf8(TextUtf8);
|
|
txt.textStorage.replaceCharactersInRange_withString(NSMakeRange(DstStart, DstLen), str);
|
|
str.release;
|
|
end;
|
|
|
|
class function TCocoaWSCustomRichMemo.LoadRichText(
|
|
const AWinControl: TWinControl; Source: TStream): Boolean;
|
|
var
|
|
data: NSMutableData;
|
|
rng : NSRange;
|
|
txt : TCocoaTextView;
|
|
begin
|
|
//todo: avoid copying data.
|
|
Result:=false;
|
|
if not Assigned(Source) or not Assigned(AWinControl) or (AWinControl.Handle=0) then Exit;
|
|
|
|
txt:=MemoTextView(AWinControl);
|
|
if Source.size>0 then begin
|
|
data:=NSMutableData(NSMutableData.alloc).initWithLength(Source.size);
|
|
Source.Read(data.mutableBytes^, Source.Size);
|
|
rng.length:=txt.textStorage.string_.length;
|
|
rng.location:=0;
|
|
txt.replaceCharactersInRange_withRTF(rng, data);
|
|
data.release;
|
|
end;
|
|
Result:=true;
|
|
end;
|
|
|
|
end.
|