View Issue Details

IDProjectCategoryView StatusLast Update
0036416LazarusWidgetsetpublic2020-04-20 13:16
ReporterChris Rorden Assigned ToZeljan Rikalo  
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionreopened 
PlatformRyzen 3900XOSUbuntu 
Product Version2.1 (SVN) 
Summary0036416: GTK3: TColorDialog not implemented
DescriptionTColorDialog not provided for GTK3
Steps To ReproducePlace TColorDialog on Form, call
  if not ColorDialog1.execute then exit;
Run as QT5 (works), GTK2 (works) and GTK3 (no dialog shown).
TagsNo tags attached.
Fixed in Revision63008,63020
LazTarget-
WidgetsetGTK 3
Attached Files

Activities

Anton Kavalenka

2019-12-11 16:31

reporter   ~0119755

For reference: https://developer.gnome.org/gtk3/stable/GtkColorChooserDialog.html

CudaText man

2019-12-19 17:00

reporter   ~0119956

First steps
gtk3/gtk3wsdialogs.pp
  TGtk3WSColorDialog = class(TWSColorDialog)
  protected
    class procedure SetCallbacks(const AGtkWidget: PGtkWidget; const AWidgetInfo: TGtk3Dialog); virtual;
  published
    class function CreateHandle(const ACommonDialog: TCommonDialog): THandle; override;
    class procedure ShowModal(const ACommonDialog: TCommonDialog); override;
  end;
....

class function TGtk3WSColorDialog.CreateHandle(const ACommonDialog: TCommonDialog): THandle;
var
  Widget: PGtkWidget;
begin
  Widget := gtk_color_chooser_dialog_new(PChar(ACommonDialog.Title), nil);
  Result := THandle({%H-}PtrUInt(Widget));
end;

class procedure TGtk3WSColorDialog.ShowModal(const ACommonDialog: TCommonDialog);
var
  Dlg: PGtkColorChooser;
  ColorValue: TGdkRGBA;
begin
  Dlg := PGtkColorChooser(ACommonDialog.Handle);
  ColorValue := TColortoTGdkRGBA((ACommonDialog as TColorDialog).Color);
  gtk_color_chooser_set_use_alpha(Dlg, False);
  gtk_color_chooser_set_rgba(Dlg, @ColorValue);
  gtk_widget_show(PGtkWidget(Dlg));
  {
  gtk_color_chooser_get_rgba(Dlg, @ColorValue);
  (ACommonDialog as TColorDialog).Color := TGdkRGBAToTColor(ColorValue);
  }
end;


gtk3/gtk3wsfactory.pas

function RegisterColorDialog: Boolean; alias : 'WSRegisterColorDialog';
begin
  RegisterWSComponent(TColorDialog, TGtk3WSColorDialog);
  Result := True;
end;

Zeljan Rikalo

2019-12-19 17:21

developer   ~0119957

That's bad. Gtk3 widget should not be exposed to LCL as handle

Anton Kavalenka

2020-04-17 18:22

reporter   ~0122202

Proposed first approach in implementing GTK3 font dialog and color dialog.
All the classes properly wrapped as TGtk3Dialog descendants,
Callback connections moved to base class to make possible refactoring of TFileDialog
gtk3dialogs.diff (18,194 bytes)   
Index: lcl/interfaces/gtk3/gtk3widgets.pas
===================================================================
--- lcl/interfaces/gtk3/gtk3widgets.pas	(revision 63007)
+++ lcl/interfaces/gtk3/gtk3widgets.pas	(working copy)
@@ -794,11 +794,21 @@
   { TGtk3Dialog }
 
   TGtk3Dialog = class(TGtk3Widget)
+  private
+    class function CloseCB(dlg:TGtk3Dialog): GBoolean; cdecl;
+    class function CloseQueryCB(w:PGtkWidget;dlg:TGtk3Dialog): GBoolean; cdecl;
+    class function DestroyCB(dlg:TGtk3Dialog): GBoolean; cdecl;
+    class function ResponseCB(response_id:gint; dlg: TGtk3Dialog): GBoolean; cdecl;
+    class function RealizeCB(dlg:TGtk3Dialog): GBoolean; cdecl;
   protected
+    function response_handler(response_id:gint):boolean;virtual;
+    function close_handler():boolean;virtual;
+    procedure SetCallbacks;virtual;
     function CreateWidget(const Params: TCreateParams):PGtkWidget; override;
   public
     CommonDialog: TCommonDialog;
     procedure InitializeWidget; override;
+    procedure CloseDialog;virtual;
   end;
 
   { TGtk3FileDialog }
@@ -815,11 +825,33 @@
 
   TGtk3FontSelectionDialog = class(TGtk3Dialog)
   protected
-    function CreateWidget(const Params: TCreateParams): PGtkWidget; override;
+    procedure InitializeWidget; override;
+    function response_handler(resp_id:gint):boolean;override;
   public
     constructor Create(const ACommonDialog: TCommonDialog); virtual; overload;
   end;
 
+  { TGtk3ColorSelectionDialog }
+
+  TGtk3ColorSelectionDialog = class(TGtk3Dialog)
+  protected
+    procedure InitializeWidget;override;
+  public
+    constructor Create(const ACommonDialog: TCommonDialog); virtual; overload;
+  end;
+
+  { TGtk3newColorSelectionDialog }
+
+  TGtk3newColorSelectionDialog = class(TGtk3Dialog)
+  protected
+    function response_handler(resp_id:gint):boolean;override;
+  public
+    constructor Create(const ACommonDialog: TCommonDialog); virtual; overload;
+    procedure InitializeWidget;override;
+    class procedure color_to_rgba(clr:TColor;var rgba:TgdkRGBA);
+    class function rgba_to_color(const rgba:TgdkRGBA):TColor;
+  end;
+
   { TGtk3GLArea }
   TGtk3GLArea = class(TGtk3Widget)
   protected
@@ -1458,8 +1490,14 @@
 
   Msg.SizeType := Msg.SizeType or Size_SourceIsInterface;
 
-  if {ACtl is TGtk3Window} ACtl.WidgetType*[wtWindow,wtDialog]<>[] then
+  if ACtl.WidgetType*[wtEntry,wtComboBox,wtGroupBox,wtScrollBar,wtSpinEdit]<>[] then
   begin
+    Msg.Width := ACtl.LCLObject.Width;//Word(NewSize.cx);
+    Msg.Height := ACtl.LCLObject.Height;//Word(NewSize.cy);
+  end else
+  if {ACtl is TGtk3Window} ACtl.WidgetType*[wtWindow,wtDialog,
+     {wtScrollingWinControl,}wtScrollingWin,wtNotebook,wtContainer]<>[] then
+  begin
     Msg.Width := Word(NewSize.cx);
     Msg.Height := Word(NewSize.cy);
   end else
@@ -1674,6 +1712,7 @@
   // DebugLn('Gtk3ScrollEvent for ', dbgsName(TGtk3Widget(AData).LCLObject),' Result ',dbgs(Result));
 end;
 
+
 { TGtk3SplitterSide }
 
 function TGtk3SplitterSide.CreateWidget(const Params: TCreateParams): PGtkWidget;
@@ -4061,9 +4100,14 @@
 { TGtk3Page }
 
 procedure TGtk3Page.setText(const AValue: String);
+var
+  bs:string;
 begin
   if Assigned(FPageLabel) then
-    FPageLabel^.set_text(PChar(AValue));
+  begin
+    bs:=ReplaceAmpersandsWithUnderscores(Avalue);
+    FPageLabel^.set_text(PChar(bs));
+  end;
 end;
 
 function TGtk3Page.getText: String;
@@ -4078,6 +4122,7 @@
 begin
   FWidgetType := FWidgetType + [wtContainer];
   FPageLabel:= TGtkLabel.new(PChar(Params.Caption));
+  FPageLabel^.set_use_underline(true);
   Self.FHasPaint:=true;
   // ref it to save it in case TabVisble is set to false
   FPageLabel^.ref;
@@ -7117,6 +7162,151 @@
 
 { TGtk3Dialog }
 
+procedure TGtk3Dialog.SetCallbacks;
+begin
+  // common callbacks for all kind of dialogs
+  g_signal_connect_data(fWidget,
+    'destroy', TGCallback(@TGtk3Dialog.DestroyCB), Self, nil, 0);
+  g_signal_connect_data(fWidget,
+    'delete-event', TGCallback(@TGtk3Dialog.CloseQueryCB), Self, nil, 0);
+
+  g_signal_connect_data(fWidget,
+    'response', TGCallback(@Tgtk3DIalog.ResponseCB), Self, nil, 0);
+
+  g_signal_connect_data(fWidget,
+    'close', TGCallback(@Tgtk3DIalog.CloseCB), Self, nil, 0);
+
+
+(*  g_signal_connect_data(fWidget,
+    'key-press-event', TGCallback(@GTKDialogKeyUpDownCB), Self, nil, 0);
+  g_signal_connect_data(fWidget,
+    'key-release-event', TGCallback(@GTKDialogKeyUpDownCB), Self, nil, 0);*)
+
+  g_signal_connect_data(fWidget,
+    'realize', TGCallback(@Tgtk3Dialog.RealizeCB), Self, nil, 0);
+end;
+
+class function Tgtk3Dialog.RealizeCB(dlg: TGtk3Dialog): GBoolean; cdecl;
+begin
+  Result := False;
+  if (dlg=nil) then exit;
+  // actually key intercepion is not required
+  {if dlg.FWidget^.get_has_window and Gtk3IsGdkWindow(dlg.FWidget^.window) then
+  begin
+    gdk_window_set_events(dlg.FWidget^.window,
+      gdk_window_get_events(dlg.FWidget^.window)
+        or GDK_KEY_RELEASE_MASK or GDK_KEY_PRESS_MASK);
+
+  end;}
+  if (wtDialog in dlg.WidgetType) then
+  begin
+    if Assigned(dlg.CommonDialog) then
+      TCommonDialog(dlg.CommonDialog).DoShow;
+  end;
+  Result := True;
+end;
+
+
+class function TGtk3Dialog.DestroyCB(dlg:TGtk3Dialog): GBoolean; cdecl;
+begin
+  Result := True;
+//  if (AWidget=nil) then ;
+  if not Assigned(dlg) then exit;
+  dlg.CommonDialog.UserChoice := mrCancel;
+  dlg.CommonDialog.Close;
+end;
+
+class function TGtk3Dialog.ResponseCB(response_id:gint; dlg: TGtk3Dialog): GBoolean; cdecl;
+begin
+  if Assigned(dlg) then
+    Result:=dlg.response_handler(response_id)
+  else
+    Result:= false;
+end;
+
+function TGtk3Dialog.response_handler(response_id:gint):boolean;
+begin
+ (* case response_id of
+  GTK_RESPONSE_NONE:;
+  GTK_RESPONSE_REJECT: ;
+  GTK_RESPONSE_ACCEPT:;
+  GTK_RESPONSE_DELETE_EVENT:;
+  GTK_RESPONSE_OK:;
+  GTK_RESPONSE_CANCEL:;
+  GTK_RESPONSE_CLOSE:;
+  GTK_RESPONSE_YES:;
+  GTK_RESPONSE_NO:;
+  GTK_RESPONSE_APPLY:;
+  GTK_RESPONSE_HELP:;
+  end;*)
+  if response_id=GTK_RESPONSE_YES then
+  begin
+    Self.CommonDialog.UserChoice:=mrYes;
+    CloseDialog;
+  end else
+  if response_id=GTK_RESPONSE_NO then
+  begin
+    Self.CommonDialog.UserChoice:=mrNo;
+    CloseDialog;
+  end else
+  if response_id=GTK_RESPONSE_OK then
+  begin
+    Self.CommonDialog.UserChoice:=mrOk;
+    CloseDialog;
+  end else
+  if response_id=GTK_RESPONSE_CANCEL then
+  begin
+    Self.CommonDialog.UserChoice:=mrCancel;
+    CloseDialog;
+  end else
+  if response_id=GTK_RESPONSE_CLOSE then
+  begin
+    Self.CommonDialog.UserChoice:=mrClose;
+    CloseDialog;
+  end;
+  Result:=false;
+end;
+
+function TGtk3Dialog.close_handler(): boolean;
+begin
+  Result:=false;
+end;
+
+class function TGtk3Dialog.CloseCB(dlg: TGtk3Dialog): GBoolean;
+  cdecl;
+begin
+  if Assigned(dlg) then
+    Result:=dlg.close_handler()
+  else
+    Result:= true;
+end;
+
+class function TGtk3Dialog.CloseQueryCB(w:PGtkWidget;dlg:TGtk3Dialog): GBoolean;
+  cdecl;
+var
+  theDialog : TCommonDialog;
+  CanClose: boolean;
+  AHandle: HWND;
+begin
+  Result := False; // true = do nothing, false = destroy or hide window
+  if (dlg=nil) then exit;
+  // data is not the commondialog. Get it manually.
+//  AHandle := HwndFromGtkWidget(AWidget);
+  if (dlg <> nil) and (wtDialog in TGtk3Widget(dlg).WidgetType) then
+  begin
+    theDialog := dlg.CommonDialog;
+    if theDialog = nil then exit;
+    if theDialog.OnCanClose<>nil then
+    begin
+      CanClose:=True;
+      theDialog.DoCanClose(CanClose);
+      Result := not CanClose;
+    end;
+  end;
+end;
+
+
+
 function TGtk3Dialog.CreateWidget(const Params: TCreateParams): PGtkWidget;
 begin
   FWidgetType := [wtWidget, wtDialog];
@@ -7129,7 +7319,13 @@
   g_object_set_data(FWidget,'lclwidget', Self);
 end;
 
+procedure TGtk3Dialog.CloseDialog;
+begin
+  if fWidget<>nil then
+    fWidget^.destroy_;
+end;
 
+
 { TGtk3FileDialog }
 
 function TGtk3FileDialog.CreateWidget(const Params: TCreateParams): PGtkWidget;
@@ -7200,12 +7396,39 @@
 
 { TGtk3FontSelectionDialog }
 
-function TGtk3FontSelectionDialog.CreateWidget(const Params: TCreateParams
-  ): PGtkWidget;
+procedure TGtk3FontSelectionDialog.InitializeWidget;
 begin
-  Result := TGtkFontSelectionDialog.new;
+  fWidget:=TGtkFontChooserDialog.new(PChar(CommonDialog.Title),nil);
+  inherited InitializeWidget;
 end;
 
+function TGtk3FontSelectionDialog.response_handler(resp_id: gint): boolean;
+var
+  fnt:TFont;
+  pch:PgtkFontChooser;
+  pfc:PPangoFontFace;
+  pfd:PPangoFontDescription;
+  sz:integer;
+  sname:string;
+begin
+  if resp_id=GTK_RESPONSE_OK then
+  begin
+    fnt:=TFontDialog(CommonDialog).Font;
+    pch:=PGtkFontChooser(fWidget);
+    pfc:=pch^.get_font_face();
+    pfd:=pfc^.describe;
+    { this stuff is implemened in gtk3objects.Tgtk3Font.UpdateLogFont
+      so this is backward mapping of properties }
+    sname:=pfd^.get_family();
+    sz:=pfd^.get_size() div PANGO_SCALE;
+    fnt.Name:=sname;
+   // fnt.Size:=sz;
+
+
+  end;
+  Result:=inherited response_handler(resp_id);
+end;
+
 constructor TGtk3FontSelectionDialog.Create(const ACommonDialog: TCommonDialog);
 begin
   inherited Create;
@@ -7223,8 +7446,122 @@
 
   // FHasPaint := False;
   CommonDialog := ACommonDialog;
+  InitializeWidget;
+  Self.SetCallbacks;
 end;
 
+{ TGtk3ColorSelectionDialog }
+
+procedure TGtk3ColorSelectionDialog.InitializeWidget;
+var
+  clr:TColor;
+  rgba:TGdkRGBA;
+begin
+  fWidget := TGtkColorSelectionDialog.new(PChar(Self.CommonDialog.Title));
+  clr:=ColorToRgb(TColorDialog(Self.CommonDialog).Color);
+  rgba.red:=Red(clr)/255;
+  rgba.blue:=Blue(clr)/255;
+  rgba.green:=Green(clr)/255;
+  rgba.alpha:=(clr shl 24)/255;
+  gtk_color_selection_set_current_rgba (
+     PgtkColorSelection(PGtkColorSelectionDialog(fWidget)^.color_selection),
+     @rgba);
+end;
+
+constructor TGtk3ColorSelectionDialog.Create(const ACommonDialog: TCommonDialog
+  );
+begin
+  inherited Create;
+  FContext := 0;
+  FHasPaint := False;
+  FWidget := nil;
+  FOwner := nil;
+  FCentralWidget := nil;
+  FOwnWidget := True;
+  // Initializes the properties
+  FProps := nil;
+  LCLObject := nil;
+  FKeysToEat := [VK_TAB, VK_RETURN, VK_ESCAPE];
+  FWidgetType := [wtWidget, wtDialog];
+
+  // FHasPaint := False;
+  CommonDialog := ACommonDialog;
+  TGtk3Widget(Self).InitializeWidget;
+  Self.SetCallbacks;
+end;
+
+
+{ TGtk3newColorSelectionDialog }
+
+procedure TGtk3newColorSelectionDialog.InitializeWidget;
+var
+  rgba:TGdkRGBA;
+begin
+  fWidget:= TGtkColorChooserDialog.new(PChar(Self.CommonDialog.Title),nil);
+  self.color_to_rgba(TColorDialog(Self.CommonDialog).Color,rgba);
+  PGtkColorChooser(fWidget)^.use_alpha:=false;
+  PGtkColorChooser(fWidget)^.set_rgba(@rgba);
+  inherited;
+end;
+
+function TGtk3newColorSelectionDialog.response_handler(resp_id: gint): boolean;
+var
+  clr:TColor;
+  rgba:TGdkRGBA;
+begin
+  if resp_id=GTK_RESPONSE_OK then
+  begin
+    PGtkColorChooser(fWidget)^.get_rgba(@rgba);
+    clr:=self.rgba_to_color(rgba);
+    TColorDialog(Self.CommonDialog).Color:=clr;
+  end;
+  Result:=inherited response_handler(resp_id);
+end;
+
+constructor TGtk3newColorSelectionDialog.Create(const ACommonDialog: TCommonDialog
+  );
+begin
+  inherited Create;
+  FContext := 0;
+  FHasPaint := False;
+  FWidget := nil;
+  FOwner := nil;
+  FCentralWidget := nil;
+  FOwnWidget := True;
+  // Initializes the properties
+  FProps := nil;
+  LCLObject := nil;
+  FKeysToEat := [VK_TAB, VK_RETURN, VK_ESCAPE];
+  FWidgetType := [wtWidget, wtDialog];
+
+  // FHasPaint := False;
+  CommonDialog := ACommonDialog;
+  TGtk3Widget(Self).InitializeWidget;
+  Self.SetCallbacks;
+end;
+
+class procedure TGtk3newColorSelectionDialog.color_to_rgba(clr: TColor;
+  var rgba: TgdkRGBA);
+begin
+  clr:=ColorToRgb(clr);
+  rgba.red:=Red(clr)/255;
+  rgba.blue:=Blue(clr)/255;
+  rgba.green:=Green(clr)/255;
+  rgba.alpha:=(clr shl 24)/255;
+end;
+
+class function TGtk3newColorSelectionDialog.rgba_to_color(const rgba: TgdkRGBA
+  ): TColor;
+var
+  q:array[0..3] of byte absolute Result;
+begin
+  q[0]:= round(255*rgba.red);
+  q[1]:= round(255*rgba.green);
+  q[2]:= round(255*rgba.blue);
+  q[3]:= round(255*rgba.alpha);
+end;
+
+
 { TGtk3GLArea }
 
 procedure TGtk3GLArea.Update(ARect: PRect);
Index: lcl/interfaces/gtk3/gtk3wsdialogs.pp
===================================================================
--- lcl/interfaces/gtk3/gtk3wsdialogs.pp	(revision 63007)
+++ lcl/interfaces/gtk3/gtk3wsdialogs.pp	(working copy)
@@ -85,7 +85,6 @@
 
   TGtk3WSColorDialog = class(TWSColorDialog)
   protected
-    class procedure SetCallbacks(const AGtkWidget: PGtkWidget; const AWidgetInfo: TGtk3Dialog); virtual;
   published
     class function CreateHandle(const ACommonDialog: TCommonDialog): THandle; override;
   end;
@@ -100,7 +99,6 @@
 
   TGtk3WSFontDialog = class(TWSFontDialog)
   protected
-    class procedure SetCallbacks(const AGtkWidget: PGtkWidget; const AWidgetInfo: TGtk3Dialog); virtual;
   published
     class function  CreateHandle(const ACommonDialog: TCommonDialog): THandle; override;
   end;
@@ -1554,117 +1552,17 @@
 
 { TGtk3WSColorDialog }
 
-
-class procedure TGtk3WSColorDialog.SetCallbacks(const AGtkWidget: PGtkWidget;
-  const AWidgetInfo: TGtk3Dialog);
-begin
-  TGtk3WSCommonDialog.SetCallbacks(AGtkWidget, AWidgetInfo);
-  (* TODO: must hack into colorselection dialog to get button pointers.
-  g_signal_connect_data(PGtkColorSelectionDialog(AGtkWidget)^.ok_button,
-    'clicked', TGCallback(@gtkDialogOKclickedCB), AWidgetInfo, nil, 0);
-  g_signal_connect_data(PGtkObject(PGtkColorSelectionDialog(AGtkWidget)^.cancel_button),
-    'clicked', TGCallback(@gtkDialogCancelclickedCB), AWidgetInfo, nil, 0);
-  *)
-end;
-
 class function TGtk3WSColorDialog.CreateHandle(
   const ACommonDialog: TCommonDialog): THandle;
-var
-  Widget: PGtkWidget;
-  // WidgetInfo: PWidgetInfo;
 begin
-  (*
-  Widget := gtk_color_selection_dialog_new(PChar(ACommonDialog.Title));
-
-  Result := THandle({%H-}PtrUInt(Widget));
-  WidgetInfo := CreateWidgetInfo(Widget);
-  WidgetInfo^.LCLObject := ACommonDialog;
-  TGtk3WSCommonDialog.SetSizes(Widget, WidgetInfo);
-  // SetCallbacks(Widget, WidgetInfo);
-  *)
+  Result:=THandle(TGtk3newColorSelectionDialog.Create(ACommonDialog));
 end;
 
 { TGtk3WSFontDialog }
 
-
-class procedure TGtk3WSFontDialog.SetCallbacks(const AGtkWidget: PGtkWidget;
-  const AWidgetInfo: TGtk3Dialog);
-begin
-  TGtk3WSCommonDialog.SetCallbacks(AGtkWidget, AWidgetInfo);
-  // connect Ok, Cancel and Apply Button
-  (*TODO: must hack into private to get button pointers
-  g_signal_connect_data(
-    PGtkObject(PGtkFontSelectionDialog(AGtkWidget)^.ok_button),
-    'clicked', TGCallback(@gtkDialogOKclickedCB), AWidgetInfo, nil, 0);
-  g_signal_connect_data(
-    PGtkObject(PGtkFontSelectionDialog(AGtkWidget)^.cancel_button),
-    'clicked', TGCallback(@gtkDialogCancelclickedCB), AWidgetInfo, nil, 0);
-  g_signal_connect_data(
-    PGtkObject(PGtkFontSelectionDialog(AGtkWidget)^.apply_button),
-    'clicked', TGCallback(@gtkDialogApplyclickedCB), AWidgetInfo, nil, 0);
-  *)
-end;
-
 class function TGtk3WSFontDialog.CreateHandle(const ACommonDialog: TCommonDialog): THandle;
-var
-  FontDesc: PPangoFontDescription;
-  TmpStr: pChar;
-
-  Widget: PGtkWidget;
-  // WidgetInfo: PWidgetInfo;
-  FontDialog: TFontDialog absolute ACommonDialog;
 begin
-
-  (*
-  GtkFontSelectionDialog is deprecated since gtk3-3.2, we must use
-  GtkFontChooserDialog - >   gtk_font_chooser_dialog_new();
-  Widget := gtk_font_selection_dialog_new(PChar(ACommonDialog.Title));
-
-  if fdApplyButton in FontDialog.Options then
-    gtk_widget_show(PGtkFontSelectionDialog(Widget)^.apply_button);
-  // set preview text
-  if FontDialog.PreviewText <> '' then
-    gtk_font_selection_dialog_set_preview_text(PGtkFontSelectionDialog(Widget),
-      PChar(FontDialog.PreviewText));
-
-  // set font name in XLFD format
-  if IsFontNameXLogicalFontDesc(FontDialog.Font.Name) then
-    gtk_font_selection_dialog_set_font_name(PGtkFontSelectionDialog(Widget),
-      PChar(FontDialog.Font.Name))
-  else
-  begin
-    FontDesc := pango_font_description_new;
-    with FontDialog.Font do
-    begin
-      pango_font_description_set_size(FontDesc, Size * PANGO_SCALE);
-
-      if fsBold in Style then
-        pango_font_description_set_weight(FontDesc, PANGO_WEIGHT_BOLD)
-      else
-        pango_font_description_set_weight(FontDesc, PANGO_WEIGHT_NORMAL);
-
-      if fsItalic in Style then
-        pango_font_description_set_style(FontDesc, PANGO_STYLE_ITALIC)
-      else
-        pango_font_description_set_style(FontDesc, PANGO_STYLE_NORMAL);
-
-      pango_font_description_set_family(FontDesc, PChar(Name));
-    end;
-    TmpStr := pango_font_description_to_string(FontDesc);
-    gtk_font_selection_dialog_set_font_name(PGtkFontSelectionDialog(Widget), TmpStr);
-    g_free(TmpStr);
-    pango_font_description_free(FontDesc);
-  end;
-
-  { This functionality does not seem to be available in GTK2 }
-  // Honor selected TFontDialogOption flags
-
-  Result := THandle({%H-}PtrUInt(Widget));
-  WidgetInfo := CreateWidgetInfo(Widget);
-  WidgetInfo^.LCLObject := ACommonDialog;
-  TGtk3WSCommonDialog.SetSizes(Widget, WidgetInfo);
-  // SetCallbacks(Widget, WidgetInfo);
-  *)
+  Result:=THandle(TGtk3FontSelectionDialog.Create(ACommonDialog));
 end;
 
 end.
Index: lcl/interfaces/gtk3/gtk3wsfactory.pas
===================================================================
--- lcl/interfaces/gtk3/gtk3wsfactory.pas	(revision 63007)
+++ lcl/interfaces/gtk3/gtk3wsfactory.pas	(working copy)
@@ -285,8 +285,8 @@
 
 function RegisterColorDialog: Boolean; alias : 'WSRegisterColorDialog';
 begin
-  // RegisterWSComponent(TColorDialog, TGtk3WSColorDialog);
-  Result := False;
+  RegisterWSComponent(TColorDialog, TGtk3WSColorDialog);
+  Result := True;
 end;
 
 function RegisterColorButton: Boolean; alias : 'WSRegisterColorButton';
@@ -297,8 +297,8 @@
 
 function RegisterFontDialog: Boolean; alias : 'WSRegisterFontDialog';
 begin
-  // RegisterWSComponent(TFontDialog, TGtk3WSFontDialog);
-  Result := False;
+  RegisterWSComponent(TFontDialog, TGtk3WSFontDialog);
+  Result := True;
 end;
 
 // StdCtrls
gtk3dialogs.diff (18,194 bytes)   

Anton Kavalenka

2020-04-17 18:23

reporter  

Anton Kavalenka

2020-04-17 18:28

reporter  

Anton Kavalenka

2020-04-17 18:31

reporter   ~0122204

two-button test app
test_app.zip (108,785 bytes)

Zeljan Rikalo

2020-04-17 19:02

developer   ~0122209

@Anton, thanks for the patch.
Please close if ok.

Chris Rorden

2020-04-18 13:00

reporter   ~0122223

1. This looks great. Thanks!
2. I do not think we should close this issue, as this does not yet behave like the ColorDialog in other widgetsets. Specifically, selecting a color should cause the ColorDialog to return "true", but it returns false. Therefore, in the script below pressing Button1 does not change the caption, and pressing Button2 has the button report "noExec", even though the reported color is the one set by the user. In brief, the execute function always returns false.

procedure TForm1.Button1Click(Sender: TObject);
var
  clr : TColor;
begin
     clr := RGBToColor(115,0,10);
     ColorDialog1.Color := clr;
     if not ColorDialog1.Execute then exit;
     caption := format('%d %d %d', [Red(ColorDialog1.Color), Green(ColorDialog1.Color), Blue(ColorDialog1.Color)]);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  clr : TColor;
begin
     clr := RGBToColor(115,0,10);
     ColorDialog1.Color := clr;
     if not ColorDialog1.Execute then
         caption := format('noExec: %d %d %d', [Red(ColorDialog1.Color), Green(ColorDialog1.Color), Blue(ColorDialog1.Color)])
     else
         caption := format('%d %d %d', [Red(ColorDialog1.Color), Green(ColorDialog1.Color), Blue(ColorDialog1.Color)]);
end;

Chris Rorden

2020-04-18 13:02

reporter   ~0122224

TColorDialog.execute always returns false, should return true if user selects color.

Anton Kavalenka

2020-04-19 10:08

reporter   ~0122242

Patch on patch with small fix to TColorDialog
gtk3dialogs-2.diff (1,791 bytes)   
Index: lcl/interfaces/gtk3/gtk3widgets.pas
===================================================================
--- lcl/interfaces/gtk3/gtk3widgets.pas	(revision 63011)
+++ lcl/interfaces/gtk3/gtk3widgets.pas	(working copy)
@@ -7242,27 +7242,22 @@
   if response_id=GTK_RESPONSE_YES then
   begin
     Self.CommonDialog.UserChoice:=mrYes;
-    CloseDialog;
   end else
   if response_id=GTK_RESPONSE_NO then
   begin
     Self.CommonDialog.UserChoice:=mrNo;
-    CloseDialog;
   end else
   if response_id=GTK_RESPONSE_OK then
   begin
     Self.CommonDialog.UserChoice:=mrOk;
-    CloseDialog;
   end else
   if response_id=GTK_RESPONSE_CANCEL then
   begin
     Self.CommonDialog.UserChoice:=mrCancel;
-    CloseDialog;
   end else
   if response_id=GTK_RESPONSE_CLOSE then
   begin
     Self.CommonDialog.UserChoice:=mrClose;
-    CloseDialog;
   end;
   Result:=false;
 end;
@@ -7409,7 +7404,8 @@
   pfc:PPangoFontFace;
   pfd:PPangoFontDescription;
   sz:integer;
-  sname:string;
+  sface,sfamily:string;
+  fnts:TfontStyles;
 begin
   if resp_id=GTK_RESPONSE_OK then
   begin
@@ -7419,12 +7415,20 @@
     pfd:=pfc^.describe;
     { this stuff is implemened in gtk3objects.Tgtk3Font.UpdateLogFont
       so this is backward mapping of properties }
-    sname:=pfd^.get_family();
-    sz:=pfd^.get_size() div PANGO_SCALE;
-    fnt.Name:=sname;
-   // fnt.Size:=sz;
+    sfamily:=pfd^.get_family();
+    sface:=lowercase(pch^.get_font_face()^.get_face_name());
 
+    sz:=pch^.get_font_size() div PANGO_SCALE;
+    fnt.Name:=sfamily;
+    fnt.Size:=sz;
+    fnts:=[];
+    if (pos('bold',sface)>0) then
+      include(fnts,fsBold);
 
+    if (pos('italic',sface)>0) then
+      include(fnts,fsItalic);
+    fnt.Style:=fnts;
+
   end;
   Result:=inherited response_handler(resp_id);
 end;
gtk3dialogs-2.diff (1,791 bytes)   

Zeljan Rikalo

2020-04-19 15:34

developer   ~0122254

Please test and close if ok.

Chris Rorden

2020-04-20 13:16

reporter   ~0122272

Thanks!

Issue History

Date Modified Username Field Change
2019-12-09 17:36 Chris Rorden New Issue
2019-12-11 16:31 Anton Kavalenka Note Added: 0119755
2019-12-19 17:00 CudaText man Note Added: 0119956
2019-12-19 17:21 Zeljan Rikalo Note Added: 0119957
2020-04-17 18:22 Anton Kavalenka File Added: gtk3dialogs.diff
2020-04-17 18:22 Anton Kavalenka Note Added: 0122202
2020-04-17 18:23 Anton Kavalenka File Added: Здымак экрана, 2020-04-17 19-22-46.png
2020-04-17 18:28 Anton Kavalenka File Added: Здымак экрана, 2020-04-17 19-28-15.png
2020-04-17 18:31 Anton Kavalenka File Added: test_app.zip
2020-04-17 18:31 Anton Kavalenka Note Added: 0122204
2020-04-17 19:02 Zeljan Rikalo Assigned To => Zeljan Rikalo
2020-04-17 19:02 Zeljan Rikalo Status new => resolved
2020-04-17 19:02 Zeljan Rikalo Resolution open => fixed
2020-04-17 19:02 Zeljan Rikalo Fixed in Revision => 63008
2020-04-17 19:02 Zeljan Rikalo LazTarget => -
2020-04-17 19:02 Zeljan Rikalo Widgetset GTK 3 => GTK 3
2020-04-17 19:02 Zeljan Rikalo Note Added: 0122209
2020-04-18 13:00 Chris Rorden Note Added: 0122223
2020-04-18 13:02 Chris Rorden Status resolved => assigned
2020-04-18 13:02 Chris Rorden Resolution fixed => reopened
2020-04-18 13:02 Chris Rorden Note Added: 0122224
2020-04-19 10:08 Anton Kavalenka Note Added: 0122242
2020-04-19 10:08 Anton Kavalenka File Added: gtk3dialogs-2.diff
2020-04-19 15:34 Zeljan Rikalo Status assigned => resolved
2020-04-19 15:34 Zeljan Rikalo Fixed in Revision 63008 => 63008,63020
2020-04-19 15:34 Zeljan Rikalo Widgetset GTK 3 => GTK 3
2020-04-19 15:34 Zeljan Rikalo Note Added: 0122254
2020-04-20 13:16 Chris Rorden Status resolved => closed
2020-04-20 13:16 Chris Rorden Note Added: 0122272