richmemo: gtk2 line spacing and image loading

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3766 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
skalogryz
2014-11-22 08:04:51 +00:00
parent 7cc8b875e5
commit 9dba703693

View File

@ -26,16 +26,16 @@ interface
uses uses
// Bindings // Bindings
gtk2, glib2, gdk2, pango, gtk2, glib2, gdk2, pango,
// FCL // RTL/FCL
Classes, SysUtils, Types, Classes, SysUtils,
// LCL // LCL
LCLType, Controls, Graphics, LCLType, Controls, Graphics,
// Gtk2 widget // Gtk2 widget
Gtk2Def, Gtk2Def,
GTK2WinApiWindow, Gtk2Globals, Gtk2Proc, InterfaceBase, GTK2WinApiWindow, Gtk2Globals, Gtk2Proc, InterfaceBase,
Gtk2WSControls, Gtk2WSControls, gdk2pixbuf,
// RichMemo // RichMemo
RichMemo, WSRichMemo; RichMemo, WSRichMemo, RichMemoUtils;
{ TGtk2WSCustomRichMemo } { TGtk2WSCustomRichMemo }
type type
@ -45,6 +45,7 @@ type
class procedure GetWidgetBuffer(const AWinControl: TWinControl; var TextWidget: PGtkWidget; var Buffer: PGtkTextBuffer); class procedure GetWidgetBuffer(const AWinControl: TWinControl; var TextWidget: PGtkWidget; var Buffer: PGtkTextBuffer);
class function GetAttrAtPos(const AWinControl: TWinControl; TextStart: Integer): PGtkTextAttributes; class function GetAttrAtPos(const AWinControl: TWinControl; TextStart: Integer): PGtkTextAttributes;
class procedure ApplyTag(abuffer: PGtkTextBuffer; tag: PGtkTextTag; TextStart, TextLen: Integer; ToParagraphs: Boolean = False); class procedure ApplyTag(abuffer: PGtkTextBuffer; tag: PGtkTextTag; TextStart, TextLen: Integer; ToParagraphs: Boolean = False);
published published
class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override; class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override;
@ -56,10 +57,17 @@ type
class procedure SetParaAlignment(const AWinControl: TWinControl; TextStart, TextLen: Integer; class procedure SetParaAlignment(const AWinControl: TWinControl; TextStart, TextLen: Integer;
const AAlign: TIntParaAlignment); override; const AAlign: TIntParaAlignment); override;
class function GetParaMetric(const AWinControl: TWinControl; TextStart: Integer;
var AMetric: TIntParaMetric): Boolean; override;
class procedure SetParaMetric(const AWinControl: TWinControl; TextStart, TextLen: Integer; class procedure SetParaMetric(const AWinControl: TWinControl; TextStart, TextLen: Integer;
const AMetric: TIntParaMetric); override; const AMetric: TIntParaMetric); override;
class procedure InDelText(const AWinControl: TWinControl; const TextUTF8: String; DstStart, DstLen: Integer); override; class procedure InDelText(const AWinControl: TWinControl; const TextUTF8: String; DstStart, DstLen: Integer); override;
class function ImageFromFile(const ARichMemo: TCustomRichMemo; APos: Integer;
const FileNameUTF8: string;
const AImgSize: TSize
): Boolean;
end; end;
implementation implementation
@ -305,6 +313,31 @@ begin
ApplyTag(buffer, tag, TextStart, TextLen, true); ApplyTag(buffer, tag, TextStart, TextLen, true);
end; end;
class function TGtk2WSCustomRichMemo.GetParaMetric(
const AWinControl: TWinControl; TextStart: Integer;
var AMetric: TIntParaMetric): Boolean;
var
attr : PGtkTextAttributes;
fp : TFontParams;
const
ScreenDPI = 96; // todo: might change, should be received dynamically
PageDPI = 72; // not expected to be changed
PixToPt = PageDPI / ScreenDPI;
begin
attr:=GetAttrAtPos(AWinControl, TextStart);
GtkTextAttrToFontParams(attr^, fp);
Result := Assigned(attr);
if Result then begin
AMetric.SpaceAfter:=attr^.pixels_above_lines*PixToPt;
AMetric.SpaceBefore:=attr^.pixels_below_lines*PixToPt;
AMetric.FirstLine:=attr^.indent*PixToPt;
AMetric.HeadIndent:=attr^.left_margin*PixToPt;
AMetric.TailIndent:=attr^.right_margin*PixToPt;
AMetric.LineSpacing:=(attr^.pixels_inside_wrap*PixToPt+fp.Size*1.2)/(fp.Size*1.2);
gtk_text_attributes_unref(attr);
end;
end;
class procedure TGtk2WSCustomRichMemo.SetParaMetric( class procedure TGtk2WSCustomRichMemo.SetParaMetric(
const AWinControl: TWinControl; TextStart, TextLen: Integer; const AWinControl: TWinControl; TextStart, TextLen: Integer;
const AMetric: TIntParaMetric); const AMetric: TIntParaMetric);
@ -316,6 +349,8 @@ var
fl : double; fl : double;
t : double; t : double;
v : Integer; v : Integer;
attr : PGtkTextAttributes;
fp : TFontParams;
const const
ScreenDPI = 96; // todo: might change, should be received dynamically ScreenDPI = 96; // todo: might change, should be received dynamically
PageDPI = 72; // not expected to be changed PageDPI = 72; // not expected to be changed
@ -333,6 +368,10 @@ begin
end else end else
fl:=fl-h; fl:=fl-h;
attr:=GetAttrAtPos(AWinControl, TextStart);
GtkTextAttrToFontParams(attr^, fp);
gtk_text_attributes_unref(attr);
GetWidgetBuffer(AWinControl, w, buffer); GetWidgetBuffer(AWinControl, w, buffer);
tag := gtk_text_buffer_create_tag (buffer, nil, tag := gtk_text_buffer_create_tag (buffer, nil,
'pixels-above-lines', [ gint(round(AMetric.SpaceBefore*DPIFactor)), 'pixels-above-lines', [ gint(round(AMetric.SpaceBefore*DPIFactor)),
@ -345,9 +384,10 @@ begin
'right-margin-set', gboolean(gTRUE), 'right-margin-set', gboolean(gTRUE),
'indent', gint(round(fl*DPIFactor)), 'indent', gint(round(fl*DPIFactor)),
'indent-set', gboolean(gTRUE), 'indent-set', gboolean(gTRUE),
'pixels-inside-wrap', gint(round(fp.Size*1.2*(AMetric.LineSpacing-1)*DPIFactor)),
'pixels-inside_wrap-set', gboolean(gTRUE),
nil]); nil]);
ApplyTag(buffer, tag, TextStart, TextLen, true); ApplyTag(buffer, tag, TextStart, TextLen, true);
end; end;
class procedure TGtk2WSCustomRichMemo.InDelText(const AWinControl: TWinControl; class procedure TGtk2WSCustomRichMemo.InDelText(const AWinControl: TWinControl;
@ -367,6 +407,40 @@ begin
gtk_text_buffer_insert(b, @istart, @textUTF8[1], length(TextUTF8)); gtk_text_buffer_insert(b, @istart, @textUTF8[1], length(TextUTF8));
end; end;
class function TGtk2WSCustomRichMemo.ImageFromFile(
const ARichMemo: TCustomRichMemo; APos: Integer; const FileNameUTF8: string;
const AImgSize: TSize): Boolean;
var
t: PGtkWidget;
b: PGtkTextBuffer;
istart: TGtkTextIter;
pix: PGdkPixbuf;
err: PGError;
const
ScreenDPI = 96; // todo: might change, should be received dynamically
PageDPI = 72; // not expected to be changed
DPIFactor = ScreenDPI / PageDPI;
begin
Result:=false;
GetWidgetBuffer(ARichMemo, t, b);
if not Assigned(b) then Exit;
err:=nil;
if (AImgSize.cx=0) and (AImgSize.cy=0) then
pix := gdk_pixbuf_new_from_file(PChar(FileNameUTF8), @err)
else
pix := gdk_pixbuf_new_from_file_at_size(PChar(FileNameUTF8),
round(AImgSize.cx * DPIFactor), round(AImgSize.cy * DPIFactor), @err);
Result:=Assigned(pix);
if Result then begin
gtk_text_buffer_get_iter_at_offset(b, @istart, APos);
gtk_text_buffer_insert_pixbuf(b, @istart, pix);
end else
writeln(err^.message);
end;
class function TGtk2WSCustomRichMemo.GetTextAttributes(const AWinControl: TWinControl; TextStart: Integer; var Params: TIntFontParams): Boolean; class function TGtk2WSCustomRichMemo.GetTextAttributes(const AWinControl: TWinControl; TextStart: Integer; var Params: TIntFontParams): Boolean;
var var
@ -380,5 +454,16 @@ begin
end; end;
end; end;
function GtkInsertImageFromFile(const ARichMemo: TCustomRichMemo; APos: Integer;
const FileNameUTF8: string;
const AImgSize: TSize
): Boolean;
begin
Result:=TGtk2WSCustomRichMemo.ImageFromFile(ARichMemo, APos, FileNameUTF8, AImgSize);
end;
initialization
InsertImageFromFile := @GtkInsertImageFromFile;
end. end.