mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-18 04:59:08 +02:00
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:
parent
af4efa5544
commit
102226c772
@ -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.
|
||||||
|
Loading…
Reference in New Issue
Block a user