From 63722e3998681e9e901d97012f8116578820b556 Mon Sep 17 00:00:00 2001 From: skalogryz Date: Mon, 17 Nov 2014 06:15:03 +0000 Subject: [PATCH] richmemo: improve gtk2 support. + InDel operation, + paragraph alignment, * improved getting / setting text attributes git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3734 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- components/richmemo/gtk2/gtk2richmemo.pas | 188 ++++++++++++++++------ 1 file changed, 142 insertions(+), 46 deletions(-) diff --git a/components/richmemo/gtk2/gtk2richmemo.pas b/components/richmemo/gtk2/gtk2richmemo.pas index 8ae2d827b..b94fbcfaf 100644 --- a/components/richmemo/gtk2/gtk2richmemo.pas +++ b/components/richmemo/gtk2/gtk2richmemo.pas @@ -42,10 +42,21 @@ type TGtk2WSCustomRichMemo = class(TWSCustomRichMemo) protected class procedure SetCallbacks(const AGtkWidget: PGtkWidget; const AWidgetInfo: PWidgetInfo); + class procedure GetWidgetBuffer(const AWinControl: TWinControl; var TextWidget: PGtkWidget; var Buffer: PGtkTextBuffer); + class function GetAttrAtPos(const AWinControl: TWinControl; TextStart: Integer): PGtkTextAttributes; + class procedure ApplyTag(abuffer: PGtkTextBuffer; tag: PGtkTextTag; TextStart, TextLen: Integer; ToParagraphs: Boolean = False); published class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override; - class procedure SetTextAttributes(const AWinControl: TWinControl; TextStart, TextLen: Integer; const Params: TIntFontParams); 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 GetParaAlignment(const AWinControl: TWinControl; TextStart: Integer; + var AAlign: Integer): Boolean; override; + class procedure SetParaAlignment(const AWinControl: TWinControl; TextStart, TextLen: Integer; + const AAlign: Integer); override; + + class procedure InDelText(const AWinControl: TWinControl; const TextUTF8: String; DstStart, DstLen: Integer); override; end; implementation @@ -66,6 +77,10 @@ var w : integer; st : TPangoStyle; pf : PPangoFontDescription; + sz : double; +const + ScreenDPI = 96; // todo: might change, should be received dynamically + PageDPI = 72; // not expected to be changed begin FontParams.Style := []; FontParams.Name := ''; @@ -79,9 +94,10 @@ begin if Assigned(pf) then begin FontParams.Name := pango_font_description_get_family(pf); FontParams.Size := pango_font_description_get_size(pf); - if not pango_font_description_get_size_is_absolute(pf) then - FontParams.Size := Round(FontParams.Size / PANGO_SCALE); - + sz:=FontParams.Size / PANGO_SCALE; + if pango_font_description_get_size_is_absolute(pf) then + sz:=sz/(ScreenDPI/PageDPI); + FontParams.Size:=round(sz); w := pango_font_description_get_weight(pf); if w > PANGO_WEIGHT_NORMAL then Include(FontParams.Style, fsBold); @@ -101,6 +117,60 @@ begin TGtk2WSWinControl.SetCallbacks(PGtkObject(AGtkWidget), TComponent(AWidgetInfo^.LCLObject)); end; +class procedure TGtk2WSCustomRichMemo.GetWidgetBuffer(const AWinControl: TWinControl; + var TextWidget: PGtkWidget; var Buffer: PGtkTextBuffer); +var + Widget : PGtkWidget; + list : PGList; +begin + TextWidget:=nil; + Buffer:=nil; + // todo: cache values? + Widget := PGtkWidget(PtrUInt(AWinControl.Handle)); + + list := gtk_container_get_children(PGtkContainer(Widget)); + if not Assigned(list) then Exit; + + TextWidget := PGtkWidget(list^.data); + if not Assigned(TextWidget) then Exit; + + buffer := gtk_text_view_get_buffer (PGtkTextView(TextWidget)); +end; + +class function TGtk2WSCustomRichMemo.GetAttrAtPos( + const AWinControl: TWinControl; TextStart: Integer): PGtkTextAttributes; +var + TextWidget : PGtkWidget; + buffer : PGtkTextBuffer; + iter : TGtkTextIter; + attr : PGtkTextAttributes; +begin + Result:=nil; + GetWidgetBuffer(AWinControl, TextWidget, buffer); + + attr := gtk_text_view_get_default_attributes(PGtkTextView(TextWidget)); + if not Assigned(attr) then Exit; + + gtk_text_buffer_get_iter_at_offset(buffer, @iter, TextStart); + gtk_text_iter_get_attributes(@iter, attr); + Result:=attr; +end; + +class procedure TGtk2WSCustomRichMemo.ApplyTag(abuffer: PGtkTextBuffer; + tag: PGtkTextTag; TextStart, TextLen: Integer; ToParagraphs: Boolean = False); +var + istart : TGtkTextIter; + iend : TGtkTextIter; +begin + gtk_text_buffer_get_iter_at_offset (abuffer, @istart, TextStart); + gtk_text_buffer_get_iter_at_offset (abuffer, @iend, TextStart+TextLen); + if ToParagraphs then begin + gtk_text_iter_set_line_offset(@istart, 0); + gtk_text_iter_forward_to_line_end(@iend); + end; + gtk_text_buffer_apply_tag(abuffer, tag, @istart, @iend); +end; + class function TGtk2WSCustomRichMemo.CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; var Widget, @@ -152,12 +222,9 @@ end; class procedure TGtk2WSCustomRichMemo.SetTextAttributes(const AWinControl: TWinControl; TextStart, TextLen: Integer; const Params: TIntFontParams); var - Widget, TextWidget: PGtkWidget; - list : PGList; + TextWidget: PGtkWidget; buffer : PGtkTextBuffer; tag : Pointer; - istart : TGtkTextIter; - iend : TGtkTextIter; gcolor : TGdkColor; nm : string; const @@ -165,21 +232,12 @@ const PangoBold : array [Boolean] of Integer = (PANGO_WEIGHT_NORMAL, PANGO_WEIGHT_BOLD); PangoItalic : array [Boolean] of Integer = (PANGO_STYLE_NORMAL, PANGO_STYLE_ITALIC); begin - Widget := PGtkWidget(PtrUInt(AWinControl.Handle)); - - list := gtk_container_get_children(PGtkContainer(Widget)); - if not Assigned(list) then Exit; - - TextWidget := PGtkWidget(list^.data); - if not Assigned(TextWidget) then Exit; - - buffer := gtk_text_view_get_buffer (PGtkTextView(TextWidget)); + GetWidgetBuffer(AWinControl, TextWidget, buffer); if not Assigned(buffer) then Exit; gcolor := TColortoTGDKColor(Params.Color); nm := Params.Name; if nm = '' then nm := #0; - tag := gtk_text_buffer_create_tag (buffer, nil, 'family-set', [gboolean(gTRUE), 'family', @nm[1], @@ -195,44 +253,82 @@ begin 'strikethrough-set', gboolean(gTRUE), 'strikethrough', gboolean(fsStrikeOut in Params.Style), nil]); + ApplyTag(buffer, tag, TextStart, TextLen); - gtk_text_buffer_get_iter_at_offset (buffer, @istart, TextStart); - gtk_text_buffer_get_iter_at_offset (buffer, @iend, TextStart+TextLen); - gtk_text_buffer_apply_tag(buffer, tag, @istart, @iend); +end; + +class function TGtk2WSCustomRichMemo.GetParaAlignment( + const AWinControl: TWinControl; TextStart: Integer; var AAlign: Integer + ): Boolean; +var + attr : PGtkTextAttributes; +begin + attr:=GetAttrAtPos(AWinControl, TextStart); + Result := Assigned(attr); + if Result then begin + case attr^.justification of + GTK_JUSTIFY_LEFT: AAlign:=AL_LEFT; + GTK_JUSTIFY_RIGHT: AAlign:=AL_RIGHT; + GTK_JUSTIFY_CENTER: AAlign:=AL_CENTER; + GTK_JUSTIFY_FILL: AAlign:=AL_JUSTIFY; + else + AAlign:=AL_LEFT; + end; + gtk_text_attributes_unref(attr); + end; +end; + +class procedure TGtk2WSCustomRichMemo.SetParaAlignment( + const AWinControl: TWinControl; TextStart, TextLen: Integer; + const AAlign: Integer); +var + w : PGtkWidget; + buffer : PGtkTextBuffer; + tag : PGtkTextTag; + val : Integer; +begin + val := GTK_JUSTIFY_LEFT; + case AAlign of + AL_RIGHT: val:=GTK_JUSTIFY_RIGHT; + AL_CENTER: val:=GTK_JUSTIFY_CENTER; + AL_JUSTIFY: val:=GTK_JUSTIFY_FILL; + end; + GetWidgetBuffer(AWinControl, w, buffer); + tag := gtk_text_buffer_create_tag (buffer, nil, + 'justification', [ val, + 'justification-set', gboolean(gTRUE), + nil]); + ApplyTag(buffer, tag, TextStart, TextLen, true); +end; + +class procedure TGtk2WSCustomRichMemo.InDelText(const AWinControl: TWinControl; + const TextUTF8: String; DstStart, DstLen: Integer); +var + w : PGtkWidget; + b : PGtkTextBuffer; + istart : TGtkTextIter; + iend : TGtkTextIter; +begin + GetWidgetBuffer(AWinControl, w, b); + if not Assigned(b) then Exit; + gtk_text_buffer_get_iter_at_offset (b, @istart, DstStart); + gtk_text_buffer_get_iter_at_offset (b, @iend, DstStart+DstLen); + gtk_text_buffer_delete(b, @istart, @iend); + if length(TextUTF8)>0 then + gtk_text_buffer_insert(b, @istart, @textUTF8[1], length(TextUTF8)); end; class function TGtk2WSCustomRichMemo.GetTextAttributes(const AWinControl: TWinControl; TextStart: Integer; var Params: TIntFontParams): Boolean; var - Widget : PGtkWidget; - TextWidget : PGtkWidget; - list : PGList; - buffer : PGtkTextBuffer; - iter : TGtkTextIter; attr : PGtkTextAttributes; begin - Widget := PGtkWidget(PtrUInt(AWinControl.Handle)); - - list := gtk_container_get_children(PGtkContainer(Widget)); - if not Assigned(list) then Exit; - - TextWidget := PGtkWidget(list^.data); - if not Assigned(TextWidget) then Exit; - - buffer := gtk_text_view_get_buffer (PGtkTextView(TextWidget)); - if not Assigned(buffer) then Exit; - - attr := gtk_text_view_get_default_attributes(PGtkTextView(TextWidget)); + attr:=GetAttrAtPos(AWinControl, TextStart); Result := Assigned(attr); - if not Assigned(attr) then Exit; - - gtk_text_buffer_get_iter_at_offset(buffer, @iter, TextStart); - Result := gtk_text_iter_get_attributes(@iter, attr); - //if Result then - {Result := } - Result := true; + if Result then begin GtkTextAttrToFontParams(attr^, Params); - gtk_text_attributes_unref(attr); + gtk_text_attributes_unref(attr); + end; end; end.