
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7000 8e941d3f-bd1b-0410-a28a-d453659cc2b4
351 lines
9.8 KiB
ObjectPascal
351 lines
9.8 KiB
ObjectPascal
unit qt5richmemo;
|
|
|
|
interface
|
|
|
|
{$mode delphi}
|
|
|
|
{$define RMQT5_TEXTFORMATS} // the feature is available in Qt5 Trunk
|
|
// it allows to query Qt5TextEdit for character formats array
|
|
{$ifdef RMQT5_NOTEXTFORMATS}{$undef RMQT5_TEXTFORMATS}{$endif}
|
|
|
|
//
|
|
// Following class methods are need for the implementation
|
|
// QTextCharFormatH
|
|
// QTextBlockFormatH
|
|
uses
|
|
LCLType, Controls, StdCtrls, Graphics,
|
|
qt5, qtobjects, qtwidgets, qtprivate,
|
|
WSProc,
|
|
RichMemo, WSRichMemo;
|
|
|
|
type
|
|
{ TQtWSCustomRichMemo }
|
|
|
|
TQtWSCustomRichMemo = class(TWSCustomRichMemo)
|
|
published
|
|
class function CreateHandle(const AWinControl: TWinControl;
|
|
const AParams: TCreateParams): HWND; override;
|
|
class function GetParaAlignment(const AWinControl: TWinControl; TextStart: Integer;
|
|
var AAlign: TIntParaAlignment): Boolean; override;
|
|
class procedure SetParaAlignment(const AWinControl: TWinControl; TextStart, TextLen: Integer;
|
|
const AAlign: TIntParaAlignment); 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 function Search(const AWinControl: TWinControl; const ANiddle: string; const SearchOpts: TIntSearchOpt): Integer; override;
|
|
|
|
class function isInternalChange(const AWinControl: TWinControl; Params: TTextModifyMask
|
|
): Boolean; override;
|
|
class procedure SetTextAttributesInternal(const AWinControl: TWinControl; TextStart, TextLen: Integer;
|
|
const AModifyMask: TTextModifyMask; const Params: TIntFontParams); override;
|
|
|
|
class function GetStyleRange(const AWinControl: TWinControl; TextStart: Integer; var RangeStart, RangeLen: Integer): Boolean; override;
|
|
|
|
end;
|
|
|
|
type
|
|
TEditorState = record
|
|
selst : integer; // selection start
|
|
sellen : integer; // selection length
|
|
end;
|
|
|
|
// no sanity check is done in these functions
|
|
procedure MakeBackup(te: TQtTextEdit; out backup: TEditorState);
|
|
procedure ApplyBackup(te: TQtTextEdit; const backup: TEditorState);
|
|
|
|
implementation
|
|
|
|
const
|
|
WordWrapMap: array[Boolean] of QTextEditLineWrapMode =
|
|
(
|
|
QTextEditNoWrap,
|
|
QTextEditWidgetWidth
|
|
);
|
|
|
|
AlignmentMap: array[TIntParaAlignment] of QtAlignment =
|
|
(
|
|
QtAlignLeft,
|
|
QtAlignRight,
|
|
QtAlignHCenter,
|
|
QtAlignJustify
|
|
);
|
|
|
|
{ TQtWSCustomRichMemo }
|
|
|
|
class function TQtWSCustomRichMemo.CreateHandle(const AWinControl: TWinControl;
|
|
const AParams: TCreateParams): HWND;
|
|
var
|
|
QtTextEdit: TQtTextEdit;
|
|
begin
|
|
QtTextEdit := TQtTextEdit.Create(AWinControl, AParams);
|
|
QtTextEdit.AcceptRichText := True;
|
|
QtTextEdit.ClearText;
|
|
QtTextEdit.setBorder(TCustomMemo(AWinControl).BorderStyle = bsSingle);
|
|
QtTextEdit.setReadOnly(TCustomMemo(AWinControl).ReadOnly);
|
|
QtTextEdit.setLineWrapMode(WordWrapMap[TCustomMemo(AWinControl).WordWrap]);
|
|
// create our FList helper
|
|
QtTextEdit.FList := TQtMemoStrings.Create(TCustomMemo(AWinControl));
|
|
QtTextEdit.setScrollStyle(TCustomMemo(AWinControl).ScrollBars);
|
|
QtTextEdit.setTabChangesFocus(not TCustomMemo(AWinControl).WantTabs);
|
|
QtTextEdit.AttachEvents;
|
|
|
|
Result := TLCLIntfHandle(QtTextEdit);
|
|
end;
|
|
|
|
class procedure TQtWSCustomRichMemo.SetParaAlignment(
|
|
const AWinControl: TWinControl; TextStart, TextLen: Integer;
|
|
const AAlign: TIntParaAlignment);
|
|
var
|
|
w : QTextEditH;
|
|
te : TQtTextEdit;
|
|
ss, sl : Integer;
|
|
begin
|
|
if not WSCheckHandleAllocated(AWinControl, 'SetParaAlignment') then
|
|
Exit;
|
|
te:=TQtTextEdit(AWinControl.Handle);
|
|
w:=QTextEditH(te.Widget);
|
|
|
|
ss:=te.getSelectionStart;
|
|
sl:=te.getSelectionLength;
|
|
|
|
te.setSelection(TextStart, TextLen);
|
|
|
|
// alignment
|
|
QTextEdit_setAlignment(w, AlignmentMap[AAlign]);
|
|
|
|
te.setSelection(ss, sl);
|
|
end;
|
|
|
|
const
|
|
QNormal = 50;
|
|
QBold = 75;
|
|
|
|
class function TQtWSCustomRichMemo.GetTextAttributes(
|
|
const AWinControl: TWinControl; TextStart: Integer; var Params: TIntFontParams
|
|
): Boolean;
|
|
var
|
|
w : QTextEditH;
|
|
te : TQtTextEdit;
|
|
ws : WideString;
|
|
clr: TQColor;
|
|
bck : TEditorState;
|
|
begin
|
|
InitFontParams(Params);
|
|
if not WSCheckHandleAllocated(AWinControl, 'GetTextAttributes') then begin
|
|
Result:=false;
|
|
Exit;
|
|
end;
|
|
|
|
te:=TQtTextEdit(AWinControl.Handle);
|
|
w:=QTextEditH(te.Widget);
|
|
|
|
MakeBackup(te, bck);
|
|
|
|
te.setSelection(TextStart, 1);
|
|
|
|
//todo!
|
|
ws:='';
|
|
QTextEdit_fontFamily(w, @ws);
|
|
if ws<>'' then Params.Name:=UTF8Encode(ws);
|
|
|
|
Params.Size:=round(QTextEdit_fontPointSize(w));
|
|
if QTextEdit_fontWeight(w)>=QBold then Include(Params.Style, fsBold);
|
|
if QTextEdit_fontItalic(w) then Include(Params.Style, fsItalic);
|
|
if QTextEdit_fontUnderline(w) then Include(Params.Style, fsUnderline);
|
|
|
|
FillChar(clr, sizeof(clr), 0);
|
|
QTextEdit_textColor(w, @clr);
|
|
TQColorToColorRef(clr, TColorRef(params.Color));
|
|
|
|
FillChar(clr, sizeof(clr), 0);
|
|
QTextEdit_textBackgroundColor(w, @clr);
|
|
TQColorToColorRef(clr, TColorRef(params.BkColor));
|
|
//todo!
|
|
params.HasBkClr:=false;
|
|
|
|
ApplyBackup(te, bck);
|
|
|
|
Result:=true;
|
|
end;
|
|
|
|
class procedure TQtWSCustomRichMemo.SetTextAttributes(
|
|
const AWinControl: TWinControl; TextStart, TextLen: Integer;
|
|
const Params: TIntFontParams);
|
|
var
|
|
w : QTextEditH;
|
|
te : TQtTextEdit;
|
|
ss, sl : Integer;
|
|
ws : WideString;
|
|
clr: TQColor;
|
|
const
|
|
QNormal = 50;
|
|
QBold = 75;
|
|
const
|
|
QIsBold: array [Boolean] of integer = (QNormal, QBold);
|
|
begin
|
|
if not WSCheckHandleAllocated(AWinControl, 'SetTextAttributes') then
|
|
Exit;
|
|
te:=TQtTextEdit(AWinControl.Handle);
|
|
w:=QTextEditH(te.Widget);
|
|
|
|
ss:=te.getSelectionStart;
|
|
sl:=te.getSelectionLength;
|
|
|
|
te.setSelection(TextStart, TextLen);
|
|
|
|
ws:=UTF8Decode(Params.Name);
|
|
if ws<>'' then QTextEdit_setFontFamily(w, @ws);
|
|
if Params.Size>0 then QTextEdit_setFontPointSize(w, Params.Size);
|
|
QTextEdit_setFontUnderline(w, fsUnderline in Params.Style);
|
|
QTextEdit_setFontWeight(w, QisBold[fsBold in Params.Style]);
|
|
QTextEdit_setFontItalic(w, fsItalic in Params.Style);
|
|
|
|
ColorRefToTQColor(Params.Color, clr);
|
|
QTextEdit_setTextColor(w, @clr);
|
|
|
|
//todo:
|
|
{
|
|
if not Params.HasBkClr then begin
|
|
ColorRefToTQColor(Params.BkColor, clr);
|
|
clr.Alpha:=0;
|
|
end else
|
|
ColorRefToTQColor(Params.BkColor, clr);
|
|
QTextEdit_setTextBackgroundColor(w, @clr);
|
|
}
|
|
|
|
te.setSelection(ss, sl);
|
|
end;
|
|
|
|
class function TQtWSCustomRichMemo.Search(const AWinControl: TWinControl;
|
|
const ANiddle: string; const SearchOpts: TIntSearchOpt): Integer;
|
|
var
|
|
w : QTextEditH;
|
|
te : TQtTextEdit;
|
|
ws : Widestring;
|
|
fl : QTextDocumentFindFlags;
|
|
begin
|
|
if not WSCheckHandleAllocated(AWinControl, 'SetParaAlignment') then
|
|
Exit;
|
|
te:=TQtTextEdit(AWinControl.Handle);
|
|
w:=QTextEditH(te.Widget);
|
|
|
|
fl:=0;
|
|
if soMatchCase in SearchOpts.Options then fl:=fl or QTextDocumentFindCaseSensitively;
|
|
if soWholeWord in SearchOpts.Options then fl:=fl or QTextDocumentFindWholeWords;
|
|
if soBackward in SearchOpts.Options then fl:=fl or QTextDocumentFindBackward;
|
|
|
|
//todo: range filtering in Serach Opts
|
|
ws:=UTF8Decode(ANiddle);
|
|
if QTextEdit_find(w, @ws, fl) then Result:=te.getSelectionStart
|
|
else Result:=-1;
|
|
end;
|
|
|
|
class function TQtWSCustomRichMemo.isInternalChange(
|
|
const AWinControl: TWinControl; Params: TTextModifyMask): Boolean;
|
|
begin
|
|
Result := false;
|
|
|
|
//Result:=inherited isInternalChange(AWinControl, Params);
|
|
end;
|
|
|
|
class procedure TQtWSCustomRichMemo.SetTextAttributesInternal(
|
|
const AWinControl: TWinControl; TextStart, TextLen: Integer;
|
|
const AModifyMask: TTextModifyMask; const Params: TIntFontParams);
|
|
begin
|
|
SetTextAttributes(AWinControl, TextStart, TextLen, Params);
|
|
end;
|
|
|
|
class function TQtWSCustomRichMemo.GetStyleRange(
|
|
const AWinControl: TWinControl; TextStart: Integer; var RangeStart,
|
|
RangeLen: Integer): Boolean;
|
|
var
|
|
te : TQtTextEdit;
|
|
bck : TEditorState;
|
|
al : QtAlignment;
|
|
qcur : QTextCursorH;
|
|
qblck : QTextBlockH;
|
|
qbfmt : QTextBlockFormatH;
|
|
i : integer;
|
|
cnt : integer;
|
|
rng : array of TTextRange;
|
|
blckofs: integer;
|
|
begin
|
|
if not WSCheckHandleAllocated(AWinControl, 'GetStyleRange') then begin
|
|
Result:=false;
|
|
Exit;
|
|
end;
|
|
|
|
RangeStart:=TextStart;
|
|
RangeLen:=1;
|
|
Result:=true;
|
|
{$ifndef RMQT5_TEXTFORMATS}
|
|
Exit;
|
|
{$else}
|
|
te:=TQtTextEdit(AWinControl.Handle);
|
|
|
|
MakeBackup(te, bck);
|
|
qcur := QTextCursor_Create();
|
|
qblck := QTextBlock_Create();
|
|
try
|
|
te.setSelection(TextStart, 0);
|
|
QTextEdit_textCursor(QTextEditH(te.Widget), qcur);
|
|
QTextCursor_block(qcur, qblck);
|
|
|
|
cnt := QTextBlock_textFormatsCount(qblck);
|
|
SetLength(rng, cnt);
|
|
if cnt>0 then begin
|
|
blckofs := QTextBlock_position(qblck);
|
|
textStart := textStart - blckofs;
|
|
for i:=0 to cnt-1 do begin
|
|
if (textStart >= rng[i].start) and (textStart<rng[i].start+rng[i].length) then
|
|
begin
|
|
RangeStart := rng[i].start + blckofs;
|
|
RangeLen := rng[i].length;
|
|
break;
|
|
end;
|
|
end;
|
|
end;
|
|
finally
|
|
QTextBlock_Destroy(qblck);
|
|
QTextCursor_Destroy(qcur);
|
|
ApplyBackup(te, bck);
|
|
end;
|
|
{$endif}
|
|
end;
|
|
|
|
class function TQtWSCustomRichMemo.GetParaAlignment(
|
|
const AWinControl: TWinControl; TextStart: Integer;
|
|
var AAlign: TIntParaAlignment): Boolean;
|
|
var
|
|
te : TQtTextEdit;
|
|
al : QtAlignment;
|
|
begin
|
|
if not WSCheckHandleAllocated(AWinControl, 'GetParaAlignment') then begin
|
|
Result:=false;
|
|
Exit;
|
|
end;
|
|
te:=TQtTextEdit(AWinControl.Handle);
|
|
al:=QTextEdit_alignment(QTextEditH(te.Widget));
|
|
if QtAlignLeading and al > 0 then AAlign:=paLeft
|
|
else if QtAlignTrailing and al > 0 then AAlign:=paRight
|
|
else if QtAlignCenter and al > 0 then AAlign:=paCenter
|
|
else if QtAlignJustify and al > 0 then AAlign:=paJustify
|
|
else AAlign:=paLeft;
|
|
Result:=true;
|
|
end;
|
|
|
|
procedure MakeBackup(te: TQtTextEdit; out backup: TEditorState);
|
|
begin
|
|
backup.selst:=te.getSelectionStart;
|
|
backup.sellen:=te.getSelectionLength;
|
|
end;
|
|
|
|
procedure ApplyBackup(te: TQtTextEdit; const backup: TEditorState);
|
|
begin
|
|
te.setSelection(backup.selst, backup.sellen);
|
|
end;
|
|
|
|
end.
|