gtk2: use align and box widgets (like gtk2 native buttons) instead of table widget to position text and glyph in TBitBtn. Fixes #8289, #16071, #8539.

git-svn-id: trunk@28647 -
This commit is contained in:
blikblum 2010-12-08 13:35:07 +00:00
parent af4efa5544
commit 102226c772

View File

@ -37,21 +37,23 @@ uses
type type
PBitBtnWidgetInfo = ^TBitBtnWidgetInfo; PBitBtnWidgetInfo = ^TBitBtnWidgetInfo;
TBitBtnWidgetInfo = record TBitBtnWidgetInfo = record
LabelWidget: Pointer;
ImageWidget: Pointer; ImageWidget: Pointer;
SpaceWidget: Pointer; LabelWidget: Pointer;
AlignWidget: Pointer;
TableWidget: Pointer;
end; end;
{ TGtk2WSBitBtn } { TGtk2WSBitBtn }
TGtk2WSBitBtn = class(TWSBitBtn) TGtk2WSBitBtn = class(TWSBitBtn)
private private
class procedure BuildWidget(ABitBtn: TCustomBitBtn; MainWidget: PGtkWidget;
ABitBtnInfo: PBitBtnWidgetInfo; const ACaption: String);
class procedure UnparentWidget(Widget: PGtkWidget);
class procedure UpdateImageWidget(ImageWidget: PGtkImage; Bitmap: TBitmap);
class procedure UpdateLabelFont(LabelWidget: PGtkWidget; Font: TFont);
protected protected
class procedure UpdateGlyph(const ABitBtn: TCustomBitBtn; const AValue: TButtonGlyph; const AButtonState: TButtonState); class function UpdateGlyph(const ABitBtn: TCustomBitBtn; BitBtnInfo: PBitBtnWidgetInfo;
class procedure UpdateLayout(const AInfo: PBitBtnWidgetInfo; const ALayout: TButtonLayout; const AMargin: Integer); const AValue: TButtonGlyph; const AButtonState: TButtonState): Boolean;
class procedure UpdateMargin(const AInfo: PBitBtnWidgetInfo; const ALayout: TButtonLayout; const AMargin: Integer); class procedure UpdateMargin(const ABitBtn: TCustomBitBtn; const AAlignWidget: PGtkAlignment; const AMargin: Integer);
class procedure SetCallbacks(const AGtkWidget: PGtkWidget; const AWidgetInfo: PWidgetInfo); virtual; class procedure SetCallbacks(const AGtkWidget: PGtkWidget; const AWidgetInfo: PWidgetInfo); virtual;
published published
class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override; class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override;
@ -94,39 +96,105 @@ type
TCustomBitBtnAccess = class(TCustomBitBtn) TCustomBitBtnAccess = class(TCustomBitBtn)
end; end;
TWinControlAccess = class(TWinControl)
end;
procedure GtkWSBitBtn_StateChanged(AWidget: PGtkWidget; AState: TGtkStateType; AInfo: PWidgetInfo); cdecl; procedure GtkWSBitBtn_StateChanged(AWidget: PGtkWidget; AState: TGtkStateType; AInfo: PWidgetInfo); cdecl;
var
BitBtn: TCustomBitBtnAccess;
begin begin
//WriteLn(Astate, ' :: ', GTK_WIDGET_STATE(AWidget)); //WriteLn(Astate, ' :: ', GTK_WIDGET_STATE(AWidget));
TGtk2WSBitBtnClass(TCustomBitBtn(AInfo^.LCLObject).WidgetSetClass).UpdateGlyph( BitBtn := TCustomBitBtnAccess(AInfo^.LCLObject);
TBitBtn(AInfo^.LCLObject), TGtk2WSBitBtn.UpdateGlyph(BitBtn, PBitBtnWidgetInfo(AInfo^.UserData),
TCustomBitBtnAccess(AInfo^.LCLObject).FButtonGlyph, BitBtn.FButtonGlyph, GtkStateToButtonState[GTK_WIDGET_STATE(AWidget)]);
GtkStateToButtonState[GTK_WIDGET_STATE(AWidget)]);
end; end;
{ TGtk2WSBitBtn } { TGtk2WSBitBtn }
{ class procedure TGtk2WSBitBtn.BuildWidget(ABitBtn: TCustomBitBtn; MainWidget: PGtkWidget; ABitBtnInfo: PBitBtnWidgetInfo; const ACaption: String);
The interiour of TBitBtn is created with a 4X4 table var
Depending in how the image and label are aligned, only a AlignWidget: PGtkWidget;
columns or rows are used (like a 4x1 or 1x4 table). LabelWidget: PGtkWidget;
This way the table doesn't have to be recreated on changes. ImageWidget: PGtkWidget;
So there are 4 positions 0, 1, 2, 3. ContentWidget: PGtkWidget;
Positions 1 and 2 are used for the label and image. begin
Since this is always the case, spacing can be implemented ImageWidget := ABitBtnInfo^.ImageWidget;
by setting the spacing of row/col 1 // keep a temporary reference to avoid the destruction and remove ImageWidget
To get a margin, a gtkInvisible is needed for bottom and if ImageWidget <> nil then
right, so the invisible is always in position 3. begin
} g_object_ref(ImageWidget);
UnparentWidget(ImageWidget);
end;
// clear the widget (will destroy the children)
ContentWidget := gtk_bin_get_child(PGtkBin(MainWidget));
if ContentWidget <> nil then
gtk_container_remove(PGtkContainer(MainWidget), ContentWidget);
ContentWidget := nil;
// setup label
LabelWidget := nil;
if ACaption <> '' then
begin
LabelWidget := gtk_label_new(nil);
GTK2WidgetSet.SetLabelCaption(PGtkLabel(LabelWidget), ACaption);
UpdateLabelFont(LabelWidget, ABitBtn.Font);
end;
// button with image and label
if (ImageWidget <> nil) and (LabelWidget <> nil) then
begin
if (ABitBtn.Layout in [blGlyphLeft, blGlyphRight]) then
ContentWidget := gtk_hbox_new(False, ABitBtn.Spacing)
else
ContentWidget := gtk_vbox_new(False, ABitBtn.Spacing);
if (ABitBtn.Layout in [blGlyphLeft, blGlyphTop]) then
gtk_box_pack_start(PGtkBox(ContentWidget), ImageWidget, True, True, 0)
else
gtk_box_pack_end(PGtkBox(ContentWidget), ImageWidget, True, True, 0);
if (ABitBtn.Layout in [blGlyphRight, blGlyphBottom]) then
gtk_box_pack_start(PGtkBox(ContentWidget), LabelWidget, True, True, 0)
else
gtk_box_pack_end(PGtkBox(ContentWidget), LabelWidget, True, True, 0);
end
else
begin
// only image or label (or none)
if ImageWidget <> nil then
ContentWidget := ImageWidget
else if LabelWidget <> nil then
ContentWidget := LabelWidget;
end;
// setup align and build the widget
AlignWidget := gtk_alignment_new(0, 0, 0, 0);
UpdateMargin(ABitBtn, PGtkAlignment(AlignWidget), ABitBtn.Margin);
gtk_container_add(PGtkContainer(MainWidget), AlignWidget);
if ContentWidget <> nil then
gtk_container_add(PGtkContainer(AlignWidget), ContentWidget);
gtk_widget_show_all(AlignWidget);
// Release the temporary reference
if ImageWidget <> nil then
g_object_unref(ImageWidget);
ABitBtnInfo^.LabelWidget := LabelWidget;
end;
class procedure TGtk2WSBitBtn.UnparentWidget(Widget: PGtkWidget);
var
ParentWidget: PGtkWidget;
begin
ParentWidget := gtk_widget_get_parent(Widget);
if ParentWidget <> nil then
gtk_container_remove(PGtkContainer(ParentWidget), Widget);
end;
class function TGtk2WSBitBtn.CreateHandle(const AWinControl: TWinControl; class function TGtk2WSBitBtn.CreateHandle(const AWinControl: TWinControl;
const AParams: TCreateParams): TLCLIntfHandle; const AParams: TCreateParams): TLCLIntfHandle;
var var
BitBtn: TCustomBitBtn; BitBtn: TCustomBitBtn absolute AWinControl;
WidgetInfo: PWidgetInfo; WidgetInfo: PWidgetInfo;
BitBtnInfo: PBitBtnWidgetInfo; BitBtnInfo: PBitBtnWidgetInfo;
Allocation: TGTKAllocation; Allocation: TGTKAllocation;
begin begin
BitBtn := AWinControl as TCustomBitBtn;
Result := TLCLIntfHandle(PtrUInt(gtk_button_new)); Result := TLCLIntfHandle(PtrUInt(gtk_button_new));
if Result = 0 then Exit; if Result = 0 then Exit;
{$IFDEF DebugLCLComponents} {$IFDEF DebugLCLComponents}
@ -140,22 +208,7 @@ begin
WidgetInfo^.UserData := BitBtnInfo; WidgetInfo^.UserData := BitBtnInfo;
WidgetInfo^.DataOwner := True; WidgetInfo^.DataOwner := True;
BitBtnInfo^.AlignWidget := gtk_alignment_new(0.5, 0.5, 0, 0); gtk_widget_show(PGtkWidget(Result));
gtk_container_add(Pointer(Result), BitBtnInfo^.AlignWidget);
BitBtnInfo^.TableWidget := gtk_table_new(4, 4, False);
gtk_container_add(BitBtnInfo^.AlignWidget, BitBtnInfo^.TableWidget);
BitBtnInfo^.LabelWidget := gtk_label_new('bitbtn');
gtk_table_attach(BitBtnInfo^.TableWidget, BitBtnInfo^.LabelWidget,
2, 3, 0, 4, GTK_SHRINK or GTK_FILL, GTK_SHRINK or GTK_FILL, 0, 0);
BitBtnInfo^.SpaceWidget := nil;
BitBtnInfo^.ImageWidget := nil;
gtk_widget_show(BitBtnInfo^.AlignWidget);
gtk_widget_show(BitBtnInfo^.TableWidget);
gtk_widget_show(BitBtnInfo^.LabelWidget);
Allocation.X := AParams.X; Allocation.X := AParams.X;
Allocation.Y := AParams.Y; Allocation.Y := AParams.Y;
@ -169,84 +222,95 @@ end;
class procedure TGtk2WSBitBtn.SetGlyph(const ABitBtn: TCustomBitBtn; class procedure TGtk2WSBitBtn.SetGlyph(const ABitBtn: TCustomBitBtn;
const AValue: TButtonGlyph); const AValue: TButtonGlyph);
var
MainWidget: PGtkWidget;
WidgetInfo: PWidgetInfo;
BitBtnInfo: PBitBtnWidgetInfo;
BuildNeeded: Boolean;
begin begin
if not WSCheckHandleAllocated(ABitBtn, 'SetGlyph') if not WSCheckHandleAllocated(ABitBtn, 'SetGlyph') then
then Exit; Exit;
MainWidget := PGtkWidget(ABitBtn.Handle);
UpdateGlyph(ABitBtn, AValue, GtkStateToButtonState[GTK_WIDGET_STATE(PGtkWidget(ABitBtn.Handle))]); WidgetInfo := GetWidgetInfo(MainWidget);
BitBtnInfo := WidgetInfo^.UserData;
BuildNeeded := UpdateGlyph(ABitBtn, BitBtnInfo, AValue, GtkStateToButtonState[GTK_WIDGET_STATE(MainWidget)]);
// at initialization widget will be built in SetLayout
if not (wcfInitializing in TWinControlAccess(ABitBtn).FWinControlFlags) and BuildNeeded then
BuildWidget(ABitBtn, MainWidget, BitBtnInfo, ABitBtn.Caption);
end; end;
class procedure TGtk2WSBitBtn.SetLayout(const ABitBtn: TCustomBitBtn; class procedure TGtk2WSBitBtn.SetLayout(const ABitBtn: TCustomBitBtn;
const AValue: TButtonLayout); const AValue: TButtonLayout);
var var
MainWidget: PGtkWidget;
WidgetInfo: PWidgetInfo; WidgetInfo: PWidgetInfo;
BitBtnInfo: PBitBtnWidgetInfo; BitBtnInfo: PBitBtnWidgetInfo;
begin begin
if not WSCheckHandleAllocated(ABitBtn, 'SetLayout') if not WSCheckHandleAllocated(ABitBtn, 'SetLayout') then
then Exit; Exit;
MainWidget := Pointer(ABitBtn.Handle);
WidgetInfo := GetWidgetInfo(Pointer(ABitBtn.Handle)); WidgetInfo := GetWidgetInfo(MainWidget);
BitBtnInfo := WidgetInfo^.UserData; BitBtnInfo := WidgetInfo^.UserData;
UpdateLayout(BitBtnInfo, AValue, ABitBtn.Margin); BuildWidget(ABitBtn, MainWidget, BitBtnInfo, ABitBtn.Caption);
end; end;
class procedure TGtk2WSBitBtn.SetMargin(const ABitBtn: TCustomBitBtn; class procedure TGtk2WSBitBtn.SetMargin(const ABitBtn: TCustomBitBtn;
const AValue: Integer); const AValue: Integer);
var var
WidgetInfo: PWidgetInfo; MainWidget: PGtkWidget;
BitBtnInfo: PBitBtnWidgetInfo; AlignWidget: PGtkAlignment;
begin begin
if not WSCheckHandleAllocated(ABitBtn, 'SetMargin') if not WSCheckHandleAllocated(ABitBtn, 'SetMargin') then
then Exit; Exit;
MainWidget := PGtkWidget(ABitBtn.Handle);
WidgetInfo := GetWidgetInfo(Pointer(ABitBtn.Handle)); AlignWidget := PGtkAlignment(gtk_bin_get_child(PGtkBin(MainWidget)));
BitBtnInfo := WidgetInfo^.UserData; if GTK_IS_ALIGNMENT(AlignWidget) then
UpdateMargin(BitBtnInfo, ABitBtn.Layout, AValue); UpdateMargin(ABitBtn, AlignWidget, AValue);
end; end;
class procedure TGtk2WSBitBtn.SetSpacing(const ABitBtn: TCustomBitBtn; class procedure TGtk2WSBitBtn.SetSpacing(const ABitBtn: TCustomBitBtn;
const AValue: Integer); const AValue: Integer);
var var
WidgetInfo: PWidgetInfo; MainWidget: PGtkWidget;
BitBtnInfo: PBitBtnWidgetInfo; ChildWidget: PGtkWidget;
begin begin
if not WSCheckHandleAllocated(ABitBtn, 'SetSpacing') if not WSCheckHandleAllocated(ABitBtn, 'SetSpacing') then
then Exit; Exit;
MainWidget := Pointer(ABitBtn.Handle);
WidgetInfo := GetWidgetInfo(Pointer(ABitBtn.Handle)); ChildWidget := gtk_bin_get_child(PGtkBin(MainWidget));
BitBtnInfo := WidgetInfo^.UserData; if GTK_IS_ALIGNMENT(ChildWidget) then
gtk_table_set_col_spacing(BitBtnInfo^.TableWidget, 1, AValue); begin
gtk_table_set_row_spacing(BitBtnInfo^.TableWidget, 1, AValue); ChildWidget := gtk_bin_get_child(PGtkBin(ChildWidget));
if GTK_IS_BOX(ChildWidget) then
gtk_box_set_spacing(PGtkBox(ChildWidget), AValue);
end;
end; end;
class procedure TGtk2WSBitBtn.SetText(const AWinControl: TWinControl; class procedure TGtk2WSBitBtn.SetText(const AWinControl: TWinControl;
const AText: String); const AText: String);
var var
MainWidget: PGtkWidget;
LabelWidget: PGtkWidget;
WidgetInfo: PWidgetInfo; WidgetInfo: PWidgetInfo;
BitBtnInfo: PBitBtnWidgetInfo; BitBtnInfo: PBitBtnWidgetInfo;
begin BuildNeeded: Boolean;
if not WSCheckHandleAllocated(AWincontrol, 'SetText') begin
then Exit; // at initialization widget will be built in SetLayout
if (wcfInitializing in TWinControlAccess(AWinControl).FWinControlFlags)
WidgetInfo := GetWidgetInfo(Pointer(AWinControl.Handle)); or not WSCheckHandleAllocated(AWincontrol, 'SetText') then
BitBtnInfo := WidgetInfo^.UserData; Exit;
MainWidget := Pointer(AWinControl.Handle);
if AText = '' then WidgetInfo := GetWidgetInfo(MainWidget);
BitBtnInfo := WidgetInfo^.UserData;
LabelWidget := BitBtnInfo^.LabelWidget;
BuildNeeded := (LabelWidget = nil) xor (AText = '');
if BuildNeeded then
BuildWidget(TBitBtn(AWinControl), MainWidget, BitBtnInfo, AText)
else
begin begin
gtk_container_remove(BitBtnInfo^.TableWidget, BitBtnInfo^.LabelWidget); if LabelWidget <> nil then
BitBtnInfo^.LabelWidget := nil; Gtk2WidgetSet.SetLabelCaption(PGtkLabel(LabelWidget), AText);
end else
begin
if BitBtnInfo^.LabelWidget = nil then
begin
BitBtnInfo^.LabelWidget := gtk_label_new(nil);
gtk_widget_show(BitBtnInfo^.LabelWidget);
end;
Gtk2WidgetSet.SetLabelCaption(BitBtnInfo^.LabelWidget, AText);
end; end;
UpdateLayout(BitBtnInfo, TBitBtn(AWincontrol).Layout, TBitBtn(AWincontrol).Margin);
end; end;
class procedure TGtk2WSBitBtn.SetColor(const AWinControl: TWinControl); class procedure TGtk2WSBitBtn.SetColor(const AWinControl: TWinControl);
@ -264,236 +328,88 @@ class procedure TGtk2WSBitBtn.SetFont(const AWinControl: TWinControl;
var var
WidgetInfo: PWidgetInfo; WidgetInfo: PWidgetInfo;
BitBtnInfo: PBitBtnWidgetInfo; BitBtnInfo: PBitBtnWidgetInfo;
Widget: PGTKWidget; LabelWidget: PGTKWidget;
begin begin
if not AWinControl.HandleAllocated then exit; if not AWinControl.HandleAllocated then exit;
Widget:= PGtkWidget(AWinControl.Handle);
WidgetInfo := GetWidgetInfo(Widget);
BitBtnInfo := WidgetInfo^.UserData;
if (BitBtnInfo=nil) or (BitBtnInfo^.LabelWidget = nil) then Exit; WidgetInfo := GetWidgetInfo(PGtkWidget(AWinControl.Handle));
Gtk2WidgetSet.SetWidgetColor(BitBtnInfo^.LabelWidget, AFont.Color, BitBtnInfo := WidgetInfo^.UserData;
clNone, LabelWidget := BitBtnInfo^.LabelWidget;
[GTK_STATE_NORMAL,GTK_STATE_ACTIVE,GTK_STATE_PRELIGHT,GTK_STATE_SELECTED]); if LabelWidget <> nil then
Gtk2WidgetSet.SetWidgetFont(BitBtnInfo^.LabelWidget, AFont); UpdateLabelFont(LabelWidget, AFont);
end; end;
class procedure TGtk2WSBitBtn.UpdateGlyph(const ABitBtn: TCustomBitBtn; {
const AValue: TButtonGlyph; const AButtonState: TButtonState); UpdateGlyph: update the bitbtn glyph and returns if the structure changed
}
class function TGtk2WSBitBtn.UpdateGlyph(const ABitBtn: TCustomBitBtn; BitBtnInfo: PBitBtnWidgetInfo;
const AValue: TButtonGlyph; const AButtonState: TButtonState): Boolean;
var var
WidgetInfo: PWidgetInfo; ShowGlyph: Boolean;
BitBtnInfo: PBitBtnWidgetInfo; ImageWidget: PGtkWidget;
GDIObject: PGDIObject;
Pixbuf: PGdkPixbuf;
Mask: PGdkBitmap;
AGlyph: TBitmap; AGlyph: TBitmap;
AIndex: Integer; AIndex: Integer;
AEffect: TGraphicsDrawEffect; AEffect: TGraphicsDrawEffect;
begin begin
WidgetInfo := GetWidgetInfo(Pointer(ABitBtn.Handle)); ShowGlyph := ABitBtn.CanShowGlyph;
BitBtnInfo := WidgetInfo^.UserData; if ShowGlyph then
if ABitBtn.CanShowGlyph then
begin begin
ImageWidget := BitBtnInfo^.ImageWidget;
AGlyph := TBitmap.Create; AGlyph := TBitmap.Create;
AValue.GetImageIndexAndEffect(AButtonState, AIndex, AEffect); AValue.GetImageIndexAndEffect(AButtonState, AIndex, AEffect);
if (AIndex <> -1) and (AValue.Images <> nil) then if (AIndex <> -1) and (AValue.Images <> nil) then
AValue.Images.GetBitmap(AIndex, AGlyph, AEffect); AValue.Images.GetBitmap(AIndex, AGlyph, AEffect);
ShowGlyph := not AGlyph.Empty;
if ShowGlyph then
begin
if ImageWidget = nil then
ImageWidget := gtk_image_new;
UpdateImageWidget(PGtkImage(ImageWidget), AGlyph);
end;
AGlyph.Destroy;
end end
else else
AGlyph := nil; ImageWidget := nil;
// check if an image is needed // Return true if the image was removed or added
if (AGlyph = nil) or AGlyph.Empty then Result := ImageWidget <> BitBtnInfo^.ImageWidget;
if Result then
begin begin
if BitBtnInfo^.ImageWidget <> nil then // BitBtnInfo^.ImageWidget <> nil -> remove from parent
begin if not ShowGlyph then
gtk_container_remove(BitBtnInfo^.TableWidget, BitBtnInfo^.ImageWidget); UnparentWidget(BitBtnInfo^.ImageWidget);
BitBtnInfo^.ImageWidget := nil; BitBtnInfo^.ImageWidget := ImageWidget;
end;
AGlyph.Free;
Exit;
end; end;
GDIObject := PGDIObject(AGlyph.Handle);
Mask := nil;
Pixbuf := nil;
if GDIObject^.GDIBitmapType = gbPixbuf then
Pixbuf := GDIObject^.GDIPixbufObject
else
Mask := CreateGdkMaskBitmap(AGlyph.Handle, AGlyph.MaskHandle);
// check for image
if BitBtnInfo^.ImageWidget = nil then
begin
BitBtnInfo^.ImageWidget := gtk_image_new;
gtk_widget_show(BitBtnInfo^.ImageWidget);
UpdateLayout(BitBtnInfo, ABitBtn.Layout, ABitBtn.Margin);
end;
if Pixbuf <> nil then
begin
gtk_image_set_from_pixbuf(BitBtnInfo^.ImageWidget, Pixbuf);
//DbgDumpPixbuf(Pixbuf);
end else
begin
gtk_image_set_from_pixmap(BitBtnInfo^.ImageWidget, GDIObject^.GDIPixmapObject.Image, Mask);
//DbgDumpPixmap(GDIObject^.GDIPixmapObject.Image);
//DbgDumpBitmap(Mask);
end;
if Mask <> nil then
gdk_pixmap_unref(Mask);
AGlyph.Free;
end; end;
class procedure TGtk2WSBitBtn.UpdateLayout(const AInfo: PBitBtnWidgetInfo; class procedure TGtk2WSBitBtn.UpdateMargin(const ABitBtn: TCustomBitBtn;
const ALayout: TButtonLayout; const AMargin: Integer); const AAlignWidget: PGtkAlignment; const AMargin: Integer);
begin
if (AInfo^.ImageWidget = nil) and (AMargin < 0) then Exit; // nothing to do
// add references and remove it from the table
if AInfo^.LabelWidget <> nil then
begin
gtk_object_ref(AInfo^.LabelWidget);
if PGtkWidget(AInfo^.LabelWidget)^.Parent <> nil then
gtk_container_remove(AInfo^.TableWidget, AInfo^.LabelWidget);
end;
if AInfo^.ImageWidget <> nil then
begin
gtk_object_ref(AInfo^.ImageWidget);
if PGtkWidget(AInfo^.ImageWidget)^.Parent <> nil then
gtk_container_remove(AInfo^.TableWidget, AInfo^.ImageWidget);
end;
if AInfo^.SpaceWidget <> nil then
begin
gtk_object_ref(AInfo^.SpaceWidget);
if PGtkWidget(AInfo^.SpaceWidget)^.Parent <> nil then
gtk_container_remove(AInfo^.TableWidget, AInfo^.SpaceWidget);
end;
if ((AInfo^.LabelWidget = nil) or (PGtkLabel(AInfo^.LabelWidget)^.text = '')) and
(AInfo^.ImageWidget <> nil) then
begin
gtk_table_attach(AInfo^.TableWidget, AInfo^.ImageWidget,
0, 3, 0, 3, GTK_EXPAND or GTK_FILL, GTK_EXPAND or GTK_FILL, 0, 0);
end
else
case ALayout of
blGlyphLeft:
begin
if AInfo^.ImageWidget <> nil then
gtk_table_attach(AInfo^.TableWidget, AInfo^.ImageWidget,
1, 2, 1, 3, GTK_SHRINK or GTK_FILL, GTK_SHRINK or GTK_FILL, 0, 0);
gtk_table_attach(AInfo^.TableWidget, AInfo^.LabelWidget,
2, 3, 1, 3, GTK_SHRINK or GTK_FILL, GTK_SHRINK or GTK_FILL, 0, 0);
end;
blGlyphRight:
begin
gtk_table_attach(AInfo^.TableWidget, AInfo^.LabelWidget,
1, 2, 1, 3, GTK_SHRINK or GTK_FILL, GTK_SHRINK or GTK_FILL, 0, 0);
if AInfo^.ImageWidget <> nil then
gtk_table_attach(AInfo^.TableWidget, AInfo^.ImageWidget,
2, 3, 1, 3, GTK_SHRINK or GTK_FILL, GTK_SHRINK or GTK_FILL, 0, 0);
if AInfo^.SpaceWidget <> nil then
gtk_table_attach(AInfo^.TableWidget, AInfo^.SpaceWidget,
3, 4, 1, 3, GTK_SHRINK or GTK_FILL, GTK_SHRINK or GTK_FILL, 0, 0);
end;
blGlyphTop:
begin
if AInfo^.ImageWidget <> nil then
gtk_table_attach(AInfo^.TableWidget, AInfo^.ImageWidget,
1, 3, 1, 2, GTK_SHRINK or GTK_FILL, GTK_SHRINK or GTK_FILL, 0, 0);
gtk_table_attach(AInfo^.TableWidget, AInfo^.LabelWidget,
1, 3, 2, 3, GTK_SHRINK or GTK_FILL, GTK_SHRINK or GTK_FILL, 0, 0);
end;
blGlyphBottom:
begin
gtk_table_attach(AInfo^.TableWidget, AInfo^.LabelWidget,
1, 3, 1, 2, GTK_SHRINK or GTK_FILL, GTK_SHRINK or GTK_FILL, 0, 0);
if AInfo^.ImageWidget <> nil then
gtk_table_attach(AInfo^.TableWidget, AInfo^.ImageWidget,
1, 3, 2, 3, GTK_SHRINK or GTK_FILL, GTK_SHRINK or GTK_FILL, 0, 0);
if AInfo^.SpaceWidget <> nil then
gtk_table_attach(AInfo^.TableWidget, AInfo^.SpaceWidget,
1, 3, 3, 4, GTK_SHRINK or GTK_FILL, GTK_SHRINK or GTK_FILL, 0, 0);
end;
end;
// remove temp reference
if AInfo^.SpaceWidget <> nil then
gtk_object_unref(AInfo^.SpaceWidget);
if AInfo^.ImageWidget <> nil then
gtk_object_unref(AInfo^.ImageWidget);
if AInfo^.LabelWidget <> nil then
gtk_object_unref(AInfo^.LabelWidget);
if AMargin >= 0 then
UpdateMargin(AInfo, ALayout, AMargin)
end;
class procedure TGtk2WSBitBtn.UpdateMargin(const AInfo: PBitBtnWidgetInfo;
const ALayout: TButtonLayout; const AMargin: Integer);
begin begin
if AMargin < 0 then if AMargin < 0 then
gtk_alignment_set (AAlignWidget, 0.5, 0.5, 0.0, 0.0)
else
begin begin
if AInfo^.SpaceWidget <> nil then case ABitBtn.Layout of
begin blGlyphLeft:
gtk_container_remove(AInfo^.TableWidget, AInfo^.SpaceWidget); begin
AInfo^.SpaceWidget := nil; gtk_alignment_set(AAlignWidget, 0, 0.5, 0, 0);
gtk_alignment_set_padding(AAlignWidget, 0, 0, AMargin, 0);
gtk_alignment_set(AInfo^.AlignWidget, 0.5, 0.5, 0, 0); end;
blGlyphRight:
case ALayout of begin
blGlyphLeft: gtk_table_set_col_spacing(AInfo^.TableWidget, 0, 0); gtk_alignment_set(AAlignWidget, 1, 0.5, 0, 0);
blGlyphRight: gtk_table_set_col_spacing(AInfo^.TableWidget, 2, 0); gtk_alignment_set_padding(AAlignWidget, 0, 0, 0, AMargin);
blGlyphTop: gtk_table_set_row_spacing(AInfo^.TableWidget, 0, 0); end;
blGlyphBottom: gtk_table_set_row_spacing(AInfo^.TableWidget, 2, 0); blGlyphTop:
end; begin
end; gtk_alignment_set(AAlignWidget, 0.5, 0, 0, 0);
end else gtk_alignment_set_padding(AAlignWidget, AMargin, 0, 0, 0);
begin end;
if (AInfo^.SpaceWidget = nil) blGlyphBottom:
and (ALayout in [blGlyphRight, blGlyphBottom]) then begin
begin gtk_alignment_set(AAlignWidget, 0.5, 1, 0, 0);
// do not use gtk_invisible_new - it cannot have parent gtk_alignment_set_padding(AAlignWidget, 0, AMargin, 0, 0);
AInfo^.SpaceWidget := gtk_image_new; end;
UpdateLayout(AInfo, ALayout, AMargin);
end else
begin
case ALayout of
blGlyphLeft:
begin
gtk_alignment_set(AInfo^.AlignWidget, 0, 0.5, 0, 0);
gtk_table_set_col_spacing(AInfo^.TableWidget, 0, AMargin);
gtk_table_set_col_spacing(AInfo^.TableWidget, 2, 0);
gtk_table_set_row_spacing(AInfo^.TableWidget, 0, 0);
gtk_table_set_row_spacing(AInfo^.TableWidget, 2, 0);
end;
blGlyphRight:
begin
gtk_alignment_set(AInfo^.AlignWidget, 1, 0.5, 0, 0);
gtk_table_set_col_spacing(AInfo^.TableWidget, 0, 0);
gtk_table_set_col_spacing(AInfo^.TableWidget, 2, AMargin);
gtk_table_set_row_spacing(AInfo^.TableWidget, 0, 0);
gtk_table_set_row_spacing(AInfo^.TableWidget, 2, 0);
end;
blGlyphTop:
begin
gtk_alignment_set(AInfo^.AlignWidget, 0.5, 0, 0, 0);
gtk_table_set_col_spacing(AInfo^.TableWidget, 0, 0);
gtk_table_set_col_spacing(AInfo^.TableWidget, 2, 0);
gtk_table_set_row_spacing(AInfo^.TableWidget, 0, AMargin);
gtk_table_set_row_spacing(AInfo^.TableWidget, 2, 0);
end;
blGlyphBottom:
begin
gtk_alignment_set(AInfo^.AlignWidget, 0.5, 1, 0, 0);
gtk_table_set_col_spacing(AInfo^.TableWidget, 0, 0);
gtk_table_set_col_spacing(AInfo^.TableWidget, 2, 0);
gtk_table_set_row_spacing(AInfo^.TableWidget, 0, 0);
gtk_table_set_row_spacing(AInfo^.TableWidget, 2, AMargin);
end;
end;
end; end;
end; end;
end; end;
@ -506,4 +422,35 @@ begin
SignalConnect(AGtkWidget, 'state-changed', @GtkWSBitBtn_StateChanged, AWidgetInfo); SignalConnect(AGtkWidget, 'state-changed', @GtkWSBitBtn_StateChanged, AWidgetInfo);
end; end;
class procedure TGtk2WSBitBtn.UpdateImageWidget(ImageWidget: PGtkImage; Bitmap: TBitmap);
var
GDIObject: PGDIObject;
Pixbuf: PGdkPixbuf;
Mask: PGdkBitmap;
begin
GDIObject := PGDIObject(Bitmap.Handle);
Mask := nil;
Pixbuf := nil;
if GDIObject^.GDIBitmapType = gbPixbuf then
Pixbuf := GDIObject^.GDIPixbufObject
else
Mask := CreateGdkMaskBitmap(Bitmap.Handle, Bitmap.MaskHandle);
if Pixbuf <> nil then
gtk_image_set_from_pixbuf(ImageWidget, Pixbuf)
else
gtk_image_set_from_pixmap(ImageWidget, GDIObject^.GDIPixmapObject.Image, Mask);
if Mask <> nil then
g_object_unref(Mask);
end;
class procedure TGtk2WSBitBtn.UpdateLabelFont(LabelWidget: PGtkWidget; Font: TFont);
begin
Gtk2WidgetSet.SetWidgetColor(LabelWidget, Font.Color, clNone,
[GTK_STATE_NORMAL,GTK_STATE_ACTIVE,GTK_STATE_PRELIGHT,GTK_STATE_SELECTED]);
Gtk2WidgetSet.SetWidgetFont(LabelWidget, Font);
end;
end. end.