View Issue Details

IDProjectCategoryView StatusLast Update
0036255LazarusWidgetsetpublic2019-12-08 10:47
ReporterCudaText manAssigned ToZeljan Rikalo 
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionreopened 
PlatformUbuntu 19 x64OSOS Version
Product Version2.1 (SVN)Product Build 
Target VersionFixed in Version 
Summary0036255: gtk3: MainManu items don't handle & accelerator chars
Description& symbols are not handled in MainMenu items (top level items + sub items).
demo added.
TagsNo tags attached.
Fixed in Revisionr62190, r62191, r62353
LazTarget-
WidgetsetGTK 3
Attached Files
  • tst-gtk3-mainmenu-accelerators.zip (2,213 bytes)
  • und.diff (3,053 bytes)
    Index: lcl/interfaces/gtk3/gtk3objects.pas
    ===================================================================
    --- lcl/interfaces/gtk3/gtk3objects.pas	(revision 62182)
    +++ lcl/interfaces/gtk3/gtk3objects.pas	(working copy)
    @@ -290,6 +290,8 @@
     function Gtk3DefaultContext: TGtk3DeviceContext;
     function Gtk3ScreenContext: TGtk3DeviceContext;
     
    +function ReplaceAmpersandsWithUnderscores(const S: string): string; inline;
    +
     implementation
     uses math, gtk3int, gtk3procs;
     
    @@ -1918,6 +1920,11 @@
     
     //various routines for text , copied from gtk2.
     
    +function ReplaceAmpersandsWithUnderscores(const S: string): string; inline;
    +begin
    +  Result := StringReplace(S, '&', '_', [rfReplaceAll]);
    +end;
    +
     {-------------------------------------------------------------------------------
       function RemoveAmpersands(Src: PChar; LineLength : Longint) : PChar;
     
    Index: lcl/interfaces/gtk3/gtk3widgets.pas
    ===================================================================
    --- lcl/interfaces/gtk3/gtk3widgets.pas	(revision 62182)
    +++ lcl/interfaces/gtk3/gtk3widgets.pas	(working copy)
    @@ -4008,7 +4008,7 @@
       for i:=0 to AToolbar.ButtonCount-1 do
       begin
         btn:=AToolBar.Buttons[i];
    -    bs:=StringReplace(btn.Caption,'&','_',[rfReplaceAll]);
    +    bs:= ReplaceAmpersandsWithUnderscores(btn.Caption);
         wicon:=nil;
         if btn is TToolButton then
         begin
    @@ -4525,7 +4525,8 @@
     
       if MenuItem.Caption <> cLineCaption then
       begin
    -    PGtkMenuItem(Result)^.set_label(PgChar(MenuItem.Caption));
    +    PGtkMenuItem(Result)^.use_underline := True;
    +    PGtkMenuItem(Result)^.set_label(PgChar(ReplaceAmpersandsWithUnderscores(MenuItem.Caption)));
         PGtkMenuItem(Result)^.set_sensitive(MenuItem.Enabled);
         // there's nothing like this in Gtk3
         // if MenuItem.RightJustify then
    @@ -6393,13 +6394,12 @@
     begin
       if IsWidgetOk then
       begin
    -    PGtkButton(FWidget)^.set_label(PgChar(StringReplace(AValue,'&','_',[rfReplaceAll])));
    +    PGtkButton(FWidget)^.set_label(PgChar(ReplaceAmpersandsWithUnderscores(AValue)));
       end;
     end;
     
     function TGtk3Button.CreateWidget(const Params: TCreateParams): PGtkWidget;
     var
    -  img:PGtkImage;
       btn:PGtkButton absolute Result;
     begin
       Result := PGtkWidget(TGtkButton.new);
    @@ -6477,8 +6477,12 @@
     end;
     
     function TGtk3CheckBox.CreateWidget(const Params: TCreateParams): PGtkWidget;
    +var
    +  check: PGtkCheckButton;
     begin
    -  Result := PGtkWidget(TGtkCheckButton.new);
    +  check := TGtkCheckButton.new;
    +  Result := PGtkWidget(check);
    +  check^.set_use_underline(True);
     end;
     
     { TGtk3RadioButton }
    @@ -6485,6 +6489,7 @@
     
     function TGtk3RadioButton.CreateWidget(const Params: TCreateParams): PGtkWidget;
     var
    +  btn: PGtkRadioButton;
       w: PGtkWidget;
       ctl, Parent: TWinControl;
       rb: TRadioButton;
    @@ -6492,7 +6497,9 @@
     begin
       if Self.LCLObject.Name='HiddenRadioButton' then
         exit;
    -  Result := PGtkWidget(TGtkRadioButton.new(nil));
    +  btn := TGtkRadioButton.new(nil);
    +  btn^.use_underline := True;
    +  Result := PGtkWidget(btn);
       ctl := Self.LCLObject;
       if Assigned(ctl) then
       begin
    
    und.diff (3,053 bytes)
  • tog.diff (542 bytes)
    Index: lcl/interfaces/gtk3/gtk3widgets.pas
    ===================================================================
    --- lcl/interfaces/gtk3/gtk3widgets.pas	(revision 62190)
    +++ lcl/interfaces/gtk3/gtk3widgets.pas	(working copy)
    @@ -6455,8 +6455,12 @@
     end;
     
     function TGtk3ToggleButton.CreateWidget(const Params: TCreateParams): PGtkWidget;
    +var
    +  btn: PGtkToggleButton;
     begin
    -  Result := PGtkWidget(TGtkToggleButton.new);
    +  btn := TGtkToggleButton.new;
    +  btn^.use_underline := True;
    +  Result := PGtkWidget(btn);
     end;
     
     { TGtk3CheckBox }
    
    tog.diff (542 bytes)
  • g3cap.diff (598 bytes)
    Index: lcl/interfaces/gtk3/gtk3objects.pas
    ===================================================================
    --- lcl/interfaces/gtk3/gtk3objects.pas	(revision 62333)
    +++ lcl/interfaces/gtk3/gtk3objects.pas	(working copy)
    @@ -1937,7 +1937,8 @@
     
     function ReplaceAmpersandsWithUnderscores(const S: string): string; inline;
     begin
    -  Result := StringReplace(S, '&', '_', [rfReplaceAll]);
    +  Result := StringReplace(S, '_', '__', [rfReplaceAll]);
    +  Result := StringReplace(Result, '&', '_', [rfReplaceAll]);
     end;
     
     {-------------------------------------------------------------------------------
    
    g3cap.diff (598 bytes)

Activities

CudaText man

2019-11-03 18:38

reporter  

tst-gtk3-mainmenu-accelerators.zip (2,213 bytes)

CudaText man

2019-11-03 18:39

reporter  

CudaText man

2019-11-03 23:59

reporter   ~0119033

Patch. adds support for & chars in TMenuItem, TCheckbox, TRadioButton. adds helper function ReplaceAmpersandsWithUnderscores.

und.diff (3,053 bytes)
Index: lcl/interfaces/gtk3/gtk3objects.pas
===================================================================
--- lcl/interfaces/gtk3/gtk3objects.pas	(revision 62182)
+++ lcl/interfaces/gtk3/gtk3objects.pas	(working copy)
@@ -290,6 +290,8 @@
 function Gtk3DefaultContext: TGtk3DeviceContext;
 function Gtk3ScreenContext: TGtk3DeviceContext;
 
+function ReplaceAmpersandsWithUnderscores(const S: string): string; inline;
+
 implementation
 uses math, gtk3int, gtk3procs;
 
@@ -1918,6 +1920,11 @@
 
 //various routines for text , copied from gtk2.
 
+function ReplaceAmpersandsWithUnderscores(const S: string): string; inline;
+begin
+  Result := StringReplace(S, '&', '_', [rfReplaceAll]);
+end;
+
 {-------------------------------------------------------------------------------
   function RemoveAmpersands(Src: PChar; LineLength : Longint) : PChar;
 
Index: lcl/interfaces/gtk3/gtk3widgets.pas
===================================================================
--- lcl/interfaces/gtk3/gtk3widgets.pas	(revision 62182)
+++ lcl/interfaces/gtk3/gtk3widgets.pas	(working copy)
@@ -4008,7 +4008,7 @@
   for i:=0 to AToolbar.ButtonCount-1 do
   begin
     btn:=AToolBar.Buttons[i];
-    bs:=StringReplace(btn.Caption,'&','_',[rfReplaceAll]);
+    bs:= ReplaceAmpersandsWithUnderscores(btn.Caption);
     wicon:=nil;
     if btn is TToolButton then
     begin
@@ -4525,7 +4525,8 @@
 
   if MenuItem.Caption <> cLineCaption then
   begin
-    PGtkMenuItem(Result)^.set_label(PgChar(MenuItem.Caption));
+    PGtkMenuItem(Result)^.use_underline := True;
+    PGtkMenuItem(Result)^.set_label(PgChar(ReplaceAmpersandsWithUnderscores(MenuItem.Caption)));
     PGtkMenuItem(Result)^.set_sensitive(MenuItem.Enabled);
     // there's nothing like this in Gtk3
     // if MenuItem.RightJustify then
@@ -6393,13 +6394,12 @@
 begin
   if IsWidgetOk then
   begin
-    PGtkButton(FWidget)^.set_label(PgChar(StringReplace(AValue,'&','_',[rfReplaceAll])));
+    PGtkButton(FWidget)^.set_label(PgChar(ReplaceAmpersandsWithUnderscores(AValue)));
   end;
 end;
 
 function TGtk3Button.CreateWidget(const Params: TCreateParams): PGtkWidget;
 var
-  img:PGtkImage;
   btn:PGtkButton absolute Result;
 begin
   Result := PGtkWidget(TGtkButton.new);
@@ -6477,8 +6477,12 @@
 end;
 
 function TGtk3CheckBox.CreateWidget(const Params: TCreateParams): PGtkWidget;
+var
+  check: PGtkCheckButton;
 begin
-  Result := PGtkWidget(TGtkCheckButton.new);
+  check := TGtkCheckButton.new;
+  Result := PGtkWidget(check);
+  check^.set_use_underline(True);
 end;
 
 { TGtk3RadioButton }
@@ -6485,6 +6489,7 @@
 
 function TGtk3RadioButton.CreateWidget(const Params: TCreateParams): PGtkWidget;
 var
+  btn: PGtkRadioButton;
   w: PGtkWidget;
   ctl, Parent: TWinControl;
   rb: TRadioButton;
@@ -6492,7 +6497,9 @@
 begin
   if Self.LCLObject.Name='HiddenRadioButton' then
     exit;
-  Result := PGtkWidget(TGtkRadioButton.new(nil));
+  btn := TGtkRadioButton.new(nil);
+  btn^.use_underline := True;
+  Result := PGtkWidget(btn);
   ctl := Self.LCLObject;
   if Assigned(ctl) then
   begin
und.diff (3,053 bytes)

Zeljan Rikalo

2019-11-04 10:23

developer   ~0119041

Please test and close if ok. Thanks for the patch.

CudaText man

2019-11-04 14:44

reporter   ~0119051

And patch to support & in TToggleBox.
Seems TLabeledEdit works ok, TBitBtn works ok, TSpeedButton too.
Seems i cannot support this in TGroupBox caption.

tog.diff (542 bytes)
Index: lcl/interfaces/gtk3/gtk3widgets.pas
===================================================================
--- lcl/interfaces/gtk3/gtk3widgets.pas	(revision 62190)
+++ lcl/interfaces/gtk3/gtk3widgets.pas	(working copy)
@@ -6455,8 +6455,12 @@
 end;
 
 function TGtk3ToggleButton.CreateWidget(const Params: TCreateParams): PGtkWidget;
+var
+  btn: PGtkToggleButton;
 begin
-  Result := PGtkWidget(TGtkToggleButton.new);
+  btn := TGtkToggleButton.new;
+  btn^.use_underline := True;
+  Result := PGtkWidget(btn);
 end;
 
 { TGtk3CheckBox }
tog.diff (542 bytes)

Zeljan Rikalo

2019-11-04 15:35

developer   ~0119052

Please test and close if ok.

CudaText man

2019-12-07 11:16

reporter   ~0119676

g3cap.diff fixes button captions with "_" - they must be escaped for gtk.

g3cap.diff (598 bytes)
Index: lcl/interfaces/gtk3/gtk3objects.pas
===================================================================
--- lcl/interfaces/gtk3/gtk3objects.pas	(revision 62333)
+++ lcl/interfaces/gtk3/gtk3objects.pas	(working copy)
@@ -1937,7 +1937,8 @@
 
 function ReplaceAmpersandsWithUnderscores(const S: string): string; inline;
 begin
-  Result := StringReplace(S, '&', '_', [rfReplaceAll]);
+  Result := StringReplace(S, '_', '__', [rfReplaceAll]);
+  Result := StringReplace(Result, '&', '_', [rfReplaceAll]);
 end;
 
 {-------------------------------------------------------------------------------
g3cap.diff (598 bytes)

Juha Manninen

2019-12-08 09:48

developer   ~0119690

I applied the last patch. Thanks.
In the future please take your time testing your changes. When you notice that something is wrong or missing, you can fix it BEFORE creating a patch.

CudaText man

2019-12-08 10:47

reporter   ~0119691

I just didn't note that "_" escaping was needed.

Issue History

Date Modified Username Field Change
2019-11-03 18:38 CudaText man New Issue
2019-11-03 18:38 CudaText man File Added: tst-gtk3-mainmenu-accelerators.zip
2019-11-03 18:39 CudaText man File Added: Screenshot from 2019-11-03 20-38-51.png
2019-11-03 23:59 CudaText man File Added: und.diff
2019-11-03 23:59 CudaText man Note Added: 0119033
2019-11-04 09:20 Zeljan Rikalo Assigned To => Zeljan Rikalo
2019-11-04 09:20 Zeljan Rikalo Status new => assigned
2019-11-04 10:23 Zeljan Rikalo Status assigned => resolved
2019-11-04 10:23 Zeljan Rikalo Resolution open => fixed
2019-11-04 10:23 Zeljan Rikalo Fixed in Revision => 62190
2019-11-04 10:23 Zeljan Rikalo LazTarget => -
2019-11-04 10:23 Zeljan Rikalo Widgetset GTK 3 => GTK 3
2019-11-04 10:23 Zeljan Rikalo Note Added: 0119041
2019-11-04 14:44 CudaText man File Added: tog.diff
2019-11-04 14:44 CudaText man Note Added: 0119051
2019-11-04 14:44 CudaText man Status resolved => assigned
2019-11-04 14:44 CudaText man Resolution fixed => reopened
2019-11-04 15:35 Zeljan Rikalo Status assigned => resolved
2019-11-04 15:35 Zeljan Rikalo Fixed in Revision 62190 => 62190,62191
2019-11-04 15:35 Zeljan Rikalo Widgetset GTK 3 => GTK 3
2019-11-04 15:35 Zeljan Rikalo Note Added: 0119052
2019-12-07 11:16 CudaText man File Added: g3cap.diff
2019-12-07 11:16 CudaText man Note Added: 0119676
2019-12-07 11:16 CudaText man Status resolved => assigned
2019-12-08 09:48 Juha Manninen Status assigned => resolved
2019-12-08 09:48 Juha Manninen Fixed in Revision 62190,62191 => r62190, r62191, r62353
2019-12-08 09:48 Juha Manninen Widgetset GTK 3 => GTK 3
2019-12-08 09:48 Juha Manninen Note Added: 0119690
2019-12-08 10:47 CudaText man Note Added: 0119691