mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-18 01:39:25 +02:00
Gtk3: Fixed sizing of group box and relatives checkgroup and radiogroup, fixed radiobutton gtk asserts because of HiddenRadioButton
This commit is contained in:
parent
0d73603378
commit
fd3a20f5c9
@ -22,6 +22,8 @@ const
|
|||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
type
|
type
|
||||||
|
Pcairo_bool_t = ^TCairo_bool_t;
|
||||||
|
TCairo_bool_t = LongInt;
|
||||||
Tcairo_status_t = (
|
Tcairo_status_t = (
|
||||||
Tcairo_status_tMinValue = -$7FFFFFFF,
|
Tcairo_status_tMinValue = -$7FFFFFFF,
|
||||||
CAIRO_STATUS_SUCCESS = 0,
|
CAIRO_STATUS_SUCCESS = 0,
|
||||||
@ -605,8 +607,8 @@ procedure cairo_show_page(cr: Pcairo_t); cdecl; external LIB_CAIRO;
|
|||||||
|
|
||||||
(* Insideness testing *)
|
(* Insideness testing *)
|
||||||
|
|
||||||
//function cairo_in_stroke(cr: Pcairo_t; x, y: Double): Tcairo_bool_t; cdecl; external LIB_CAIRO;
|
function cairo_in_stroke(cr: Pcairo_t; x, y: Double): Tcairo_bool_t; cdecl; external LIB_CAIRO;
|
||||||
//function cairo_in_fill(cr: Pcairo_t; x, y: Double): Tcairo_bool_t; cdecl; external LIB_CAIRO;
|
function cairo_in_fill(cr: Pcairo_t; x, y: Double): Tcairo_bool_t; cdecl; external LIB_CAIRO;
|
||||||
|
|
||||||
(* Rectangular extents *)
|
(* Rectangular extents *)
|
||||||
|
|
||||||
|
160
lcl/interfaces/gtk3/gtk3lclframe.inc
Normal file
160
lcl/interfaces/gtk3/gtk3lclframe.inc
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
{%MainUnit gtk3widgets.pas}
|
||||||
|
const
|
||||||
|
GTK_FRAME_CLASS_SIZE = SizeOf(TGtkFrameClass);
|
||||||
|
GTK_FRAME_INSTANCE_SIZE = SizeOf(TGtkFrame);
|
||||||
|
|
||||||
|
procedure LCLGtkFrameGetPreferredWidth(widget: PGtkWidget; min_width, nat_width: Pgint); cdecl;
|
||||||
|
var
|
||||||
|
AControl: TGtk3Widget;
|
||||||
|
ParentClass: PGtkWidgetClass;
|
||||||
|
begin
|
||||||
|
if not Assigned(min_width) or not Assigned(nat_width) then
|
||||||
|
begin
|
||||||
|
DebugLn('Error: LCLGtkFrameGetPreferredWidth invalid params.');
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if not Gtk3IsWidget(widget) then
|
||||||
|
begin
|
||||||
|
DebugLn('Error: LCLGtkFrameGetPreferredWidth widget param is not PGtkWidget.');
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
ParentClass := PGtkWidgetClass(g_type_class_peek_parent(widget^.g_type_instance.g_class));
|
||||||
|
if not Assigned(ParentClass) then
|
||||||
|
begin
|
||||||
|
DebugLn('Error: LCLGtkFrameGetPreferredWidth cannot get ParentClass !');
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Call parent class implementation
|
||||||
|
ParentClass^.get_preferred_width(widget, min_width, nat_width);
|
||||||
|
// writeln('LCLFrame preferred min_width=',min_width^,' natural w=',nat_width^);
|
||||||
|
AControl := TGtk3Widget(HwndFromGtkWidget(widget));
|
||||||
|
if not Assigned(AControl) then
|
||||||
|
begin
|
||||||
|
DebugLn('Error: LCLGtkFrameGetPreferredWidth cannot get TGtk3Widget for widget parameter.');
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
// LCL does not like when ws calculates autosize dimensions
|
||||||
|
// writeln('====> FGPW(',dbgsName(AControl.LCLObject),'): AutoSize=', AControl.LCLObject.AutoSize,' minW=',min_width^,' natW=',nat_width^,' LCLWidth=',AControl.LCLWidth,' LCLHeight=',AControl.LCLHeight);
|
||||||
|
if AControl.LCLObject.AutoSize then
|
||||||
|
begin
|
||||||
|
//if AControl.LCLWidth > min_width^ then
|
||||||
|
// nat_width^ := AControl.LCLWidth;
|
||||||
|
//min_width^ := Max(min_width^, AControl.LCLObject.Width);
|
||||||
|
//if AControl.LCLWidth > 0 then
|
||||||
|
// nat_width^ := Max(min_width^, AControl.LCLWidth);
|
||||||
|
// exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if AControl.LCLWidth = 0 then
|
||||||
|
begin
|
||||||
|
min_width^ := Max(min_width^ div 2, AControl.LCLObject.Width);
|
||||||
|
nat_width^ := Max(min_width^ div 2, AControl.LCLObject.Width);
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
min_width^ := Max(min_width^ div 2, AControl.LCLWidth);
|
||||||
|
nat_width^ := Max(min_width^ div 2, AControl.LCLWidth);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure LCLGtkFrameGetPreferredHeight(widget: PGtkWidget; min_height, nat_height: Pgint); cdecl;
|
||||||
|
var
|
||||||
|
AControl: TGtk3Widget;
|
||||||
|
ParentClass: PGtkWidgetClass;
|
||||||
|
begin
|
||||||
|
if not Assigned(min_height) or not Assigned(nat_height) then
|
||||||
|
begin
|
||||||
|
DebugLn('Error: LCLGtkFrameGetPreferredHeight invalid params.');
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if not Gtk3IsWidget(widget) then
|
||||||
|
begin
|
||||||
|
DebugLn('Error: LCLGtkFrameGetPreferredHeight widget param is not PGtkWidget.');
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
ParentClass := PGtkWidgetClass(g_type_class_peek_parent(widget^.g_type_instance.g_class));
|
||||||
|
if not Assigned(ParentClass) then
|
||||||
|
begin
|
||||||
|
DebugLn('Error: LCLGtkFrameGetPreferredHeight cannot get ParentClass !');
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Call parent class implementation
|
||||||
|
ParentClass^.get_preferred_height(widget, min_height, nat_height);
|
||||||
|
|
||||||
|
AControl := TGtk3Widget(HwndFromGtkWidget(widget));
|
||||||
|
if not Assigned(AControl) then
|
||||||
|
begin
|
||||||
|
DebugLn('Error: LCLGtkFrameGetPreferredHeight cannot get TGtk3Widget for widget parameter.');
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
// fixme. min_height and nat_height reports complete box size, but lcl sets client size ?
|
||||||
|
// LCL does not like when ws calculates autosize dimensions.
|
||||||
|
// writeln('====> FGPH(',dbgsName(AControl.LCLObject),'): AutoSize=', AControl.LCLObject.AutoSize,' minH=',min_height^,' natH=',nat_height^,' LCLWidth=',AControl.LCLWidth,' Height=',AControl.LCLHeight);
|
||||||
|
if AControl.LCLObject.AutoSize then
|
||||||
|
begin
|
||||||
|
// if AControl.LCLHeight > nat_height^ then
|
||||||
|
// nat_height^ := AControl.LCLHeight;
|
||||||
|
// exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if AControl.LCLHeight = 0 then
|
||||||
|
begin
|
||||||
|
min_height^ := Max(min_height^ div 2, AControl.LCLObject.Height);
|
||||||
|
nat_height^ := Max(min_height^ div 2, AControl.LCLObject.Height);
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
min_height^ := Max(min_height^ div 2, AControl.LCLHeight);
|
||||||
|
nat_height^ := Max(min_height^ div 2, AControl.LCLHeight);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure LCLGtkFrameClassInit(klass: PGTypeClass; {%H-}data: Pointer); cdecl;
|
||||||
|
var
|
||||||
|
AWidgetClass: PGtkWidgetClass;
|
||||||
|
begin
|
||||||
|
AWidgetClass := PGtkWidgetClass(klass);
|
||||||
|
AWidgetClass^.get_preferred_width := @LCLGtkFrameGetPreferredWidth;
|
||||||
|
AWidgetClass^.get_preferred_height := @LCLGtkFrameGetPreferredHeight;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure LCLGtkFrameInstanceInit(instance: PGTypeInstance; {%H-}klass: PGTypeClass); cdecl;
|
||||||
|
begin
|
||||||
|
//
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
LCLGtkFrameType: TGType = 0;
|
||||||
|
|
||||||
|
function LCLGtkFrameGetType: TGType; cdecl;
|
||||||
|
const
|
||||||
|
lcl_frame_type_info: TGTypeInfo = (
|
||||||
|
class_size: GTK_FRAME_CLASS_SIZE;
|
||||||
|
base_init: nil;
|
||||||
|
base_finalize: nil;
|
||||||
|
class_init: @LCLGtkFrameClassInit;
|
||||||
|
class_finalize: nil;
|
||||||
|
class_data: nil;
|
||||||
|
instance_size: GTK_FRAME_INSTANCE_SIZE;
|
||||||
|
n_preallocs: 0;
|
||||||
|
instance_init: @LCLGtkFrameInstanceInit;
|
||||||
|
value_table: nil;
|
||||||
|
);
|
||||||
|
begin
|
||||||
|
if LCLGtkFrameType = 0 then
|
||||||
|
LCLGtkFrameType := g_type_register_static(gtk_frame_get_type, 'LCLGtkFrame', @lcl_frame_type_info, G_TYPE_FLAG_NONE);
|
||||||
|
Result := LCLGtkFrameType;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function LCLGtkFrameNew: PGtkFrame;
|
||||||
|
begin
|
||||||
|
{in gtk3 this is default shadow}
|
||||||
|
Result := PGtkFrame(g_object_new(LCLGtkFrameGetType(),'shadow-type',[GTK_SHADOW_ETCHED_IN, nil]));
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -58,6 +58,8 @@ type
|
|||||||
wtWindow, wtDialog, wtHintWindow, wtGLArea);
|
wtWindow, wtDialog, wtHintWindow, wtGLArea);
|
||||||
TGtk3WidgetTypes = set of TGtk3WidgetType;
|
TGtk3WidgetTypes = set of TGtk3WidgetType;
|
||||||
|
|
||||||
|
TGtk3GroupBoxType = (gbtGroupBox, gbtCheckGroup, gbtRadioGroup);
|
||||||
|
|
||||||
{ TGtk3Widget }
|
{ TGtk3Widget }
|
||||||
|
|
||||||
TGtk3Widget = class(TGtk3Object, IUnknown)
|
TGtk3Widget = class(TGtk3Object, IUnknown)
|
||||||
@ -674,11 +676,20 @@ type
|
|||||||
{ TGtk3GroupBox }
|
{ TGtk3GroupBox }
|
||||||
|
|
||||||
TGtk3GroupBox = class(TGtk3Bin)
|
TGtk3GroupBox = class(TGtk3Bin)
|
||||||
|
strict private
|
||||||
|
class procedure GroupBoxSizeAllocate(AWidget: PGtkWidget; AGdkRect: PGdkRectangle; Data: gpointer); cdecl; static;
|
||||||
|
private
|
||||||
|
FGroupBoxType:TGtk3GroupBoxType;
|
||||||
|
function GetInnerClientRect(Frame:PGtkWidget):TRect;
|
||||||
protected
|
protected
|
||||||
|
procedure ConnectSizeAllocateSignal(ToWidget: PGtkWidget); override;
|
||||||
function CreateWidget(const {%H-}Params: TCreateParams):PGtkWidget; override;
|
function CreateWidget(const {%H-}Params: TCreateParams):PGtkWidget; override;
|
||||||
function getText: String; override;
|
function getText: String; override;
|
||||||
procedure setText(const AValue: String); override;
|
procedure setText(const AValue: String); override;
|
||||||
public
|
public
|
||||||
|
procedure SetBounds(ALeft,ATop,AWidth,AHeight:integer); override;
|
||||||
|
function getClientRect:TRect; override;
|
||||||
|
property GroupBoxType: TGtk3GroupBoxType read FGroupBoxType write FGroupBoxType;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TGtk3ComboBox }
|
{ TGtk3ComboBox }
|
||||||
@ -762,16 +773,17 @@ type
|
|||||||
protected
|
protected
|
||||||
function CreateWidget(const {%H-}Params: TCreateParams):PGtkWidget; override;
|
function CreateWidget(const {%H-}Params: TCreateParams):PGtkWidget; override;
|
||||||
public
|
public
|
||||||
|
procedure SetBounds(ALeft,ATop,AWidth,AHeight:integer); override;
|
||||||
property State: TCheckBoxState read GetState write SetState;
|
property State: TCheckBoxState read GetState write SetState;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TGtk3RadioButton }
|
{ TGtk3RadioButton }
|
||||||
|
|
||||||
TGtk3RadioButton = class(TGtk3CheckBox)
|
TGtk3RadioButton = class(TGtk3CheckBox)
|
||||||
private
|
|
||||||
protected
|
protected
|
||||||
function CreateWidget(const {%H-}Params: TCreateParams):PGtkWidget; override;
|
function CreateWidget(const {%H-}Params: TCreateParams):PGtkWidget; override;
|
||||||
public
|
public
|
||||||
|
function getClientRect:TRect; override;
|
||||||
procedure InitializeWidget; override;
|
procedure InitializeWidget; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1049,6 +1061,7 @@ end;
|
|||||||
{$i gtk3lclentry.inc}
|
{$i gtk3lclentry.inc}
|
||||||
{$i gtk3lclbutton.inc}
|
{$i gtk3lclbutton.inc}
|
||||||
{$i gtk3lclspinbutton.inc}
|
{$i gtk3lclspinbutton.inc}
|
||||||
|
{$i gtk3lclframe.inc}
|
||||||
|
|
||||||
class function TGtk3Widget.WidgetEvent(widget: PGtkWidget; event: PGdkEvent; data: GPointer): gboolean; cdecl;
|
class function TGtk3Widget.WidgetEvent(widget: PGtkWidget; event: PGdkEvent; data: GPointer): gboolean; cdecl;
|
||||||
begin
|
begin
|
||||||
@ -3005,7 +3018,6 @@ function TGtk3Widget.getClientRect: TRect;
|
|||||||
var
|
var
|
||||||
AAlloc: TGtkAllocation;
|
AAlloc: TGtkAllocation;
|
||||||
begin
|
begin
|
||||||
//writeln('GetClientRect ',LCLObject.Name,':',LCLObject.Name);
|
|
||||||
Result := LCLObject.BoundsRect;
|
Result := LCLObject.BoundsRect;
|
||||||
if not IsWidgetOK then
|
if not IsWidgetOK then
|
||||||
exit;
|
exit;
|
||||||
@ -3019,7 +3031,7 @@ begin
|
|||||||
FWidget^.get_allocation(@AAlloc);
|
FWidget^.get_allocation(@AAlloc);
|
||||||
Result := Rect(AAlloc.x, AAlloc.y, AAlloc.width + AAlloc.x,AAlloc.height + AAlloc.y);
|
Result := Rect(AAlloc.x, AAlloc.y, AAlloc.width + AAlloc.x,AAlloc.height + AAlloc.y);
|
||||||
end;
|
end;
|
||||||
OffsetRect(Result, -Result.Left, -Result.Top);
|
Types.OffsetRect(Result, -Result.Left, -Result.Top);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TGtk3Widget.getClientBounds: TRect;
|
function TGtk3Widget.getClientBounds: TRect;
|
||||||
@ -3485,14 +3497,13 @@ end;
|
|||||||
function TGtk3GroupBox.CreateWidget(const Params: TCreateParams): PGtkWidget;
|
function TGtk3GroupBox.CreateWidget(const Params: TCreateParams): PGtkWidget;
|
||||||
begin
|
begin
|
||||||
FHasPaint := True;
|
FHasPaint := True;
|
||||||
//dont use layout for now
|
FGroupBoxType := gbtGroupBox;
|
||||||
FWidgetType := [wtWidget, wtContainer, wtGroupBox];
|
FWidgetType := [wtWidget, wtContainer, wtGroupBox];
|
||||||
Result := TGtkFrame.new(PChar(Self.LCLObject.Caption));
|
Result := LCLGtkFrameNew;
|
||||||
//FCentralWidget := TGtkLayout.new(nil,nil);
|
|
||||||
FCentralWidget := TGtkFixed.new;
|
FCentralWidget := TGtkFixed.new;
|
||||||
PGtkBin(Result)^.add(FCentralWidget);
|
PGtkBin(Result)^.add(FCentralWidget);
|
||||||
FCentralWidget^.set_has_window(True);
|
FCentralWidget^.set_has_window(True);
|
||||||
PgtkFrame(result)^.set_label_align(0.1,0.5);
|
PGtkFrame(result)^.set_label_align(0.1,0.5);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TGtk3GroupBox.getText: String;
|
function TGtk3GroupBox.getText: String;
|
||||||
@ -3502,7 +3513,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
if PGtkFrame(Widget)^.get_label_widget = nil then
|
if PGtkFrame(Widget)^.get_label_widget = nil then
|
||||||
exit;
|
exit;
|
||||||
Result := ReplaceUnderscoresWithAmpersands(PGtkFrame(Widget)^.get_label);
|
Result := {%H-}ReplaceUnderscoresWithAmpersands(PGtkFrame(Widget)^.get_label);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -3512,16 +3523,178 @@ begin
|
|||||||
begin
|
begin
|
||||||
if AValue = '' then
|
if AValue = '' then
|
||||||
PGtkFrame(Widget)^.set_label_widget(nil)
|
PGtkFrame(Widget)^.set_label_widget(nil)
|
||||||
// maybe DoAdjustClientRect here
|
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
if PGtkFrame(Widget)^.get_label_widget = nil then
|
if PGtkFrame(Widget)^.get_label_widget = nil then
|
||||||
PGtkFrame(Widget)^.set_label_widget(TGtkLabel.new(''));
|
PGtkFrame(Widget)^.set_label_widget(TGtkLabel.new(''));
|
||||||
PGtkFrame(Widget)^.set_label(PgChar(ReplaceAmpersandsWithUnderscores(AValue)));
|
{%H-}PGtkFrame(Widget)^.set_label(PgChar({%H-}ReplaceAmpersandsWithUnderscores(AValue)));
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TGtk3GroupBox.SetBounds(ALeft,ATop,AWidth,AHeight:integer);
|
||||||
|
var
|
||||||
|
Alloc:TGtkAllocation;
|
||||||
|
begin
|
||||||
|
{$IF DEFINED(GTK3DEBUGSIZE) OR DEFINED(GTK3DEBUGGROUPBOX)}
|
||||||
|
writeln(Format('TGtk3GroupBox.setBounds l %d t %d w %d h %d',[ALeft, ATop, AWidth, AHeight]));
|
||||||
|
{$ENDIF}
|
||||||
|
LCLWidth := AWidth;
|
||||||
|
LCLHeight := AHeight;
|
||||||
|
Alloc.x := ALeft;
|
||||||
|
Alloc.y := ATop;
|
||||||
|
Alloc.width := AWidth;
|
||||||
|
Alloc.Height := AHeight;
|
||||||
|
Widget^.set_allocation(@Alloc);
|
||||||
|
Move(ALeft, ATop);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{$IF DEFINED(GTK3DEBUGSIZE) OR DEFINED(GTK3DEBUGGROUPBOX)}
|
||||||
|
procedure ContainerChildrenCallback(widget: PGtkWidget; data: gpointer); cdecl;
|
||||||
|
begin
|
||||||
|
// This callback is called for each child of the GtkFixed container
|
||||||
|
WriteLn('TGtk3GroupBox Child widget pointer: ', PtrUInt(widget),' ACtl=',dbgsName(TGtk3WIdget(data)));
|
||||||
|
|
||||||
|
// Example: Print the widget type name
|
||||||
|
WriteLn('TGtk3GroupBox Widget type: ', gtk_widget_get_name(widget));
|
||||||
|
end;
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
class procedure TGtk3GroupBox.GroupBoxSizeAllocate(AWidget:PGtkWidget;AGdkRect:
|
||||||
|
PGdkRectangle;Data:gpointer);cdecl;
|
||||||
|
var
|
||||||
|
Msg: TLMSize;
|
||||||
|
NewSize: TSize;
|
||||||
|
ACtl: TGtk3GroupBox;
|
||||||
|
AState: TGdkWindowState;
|
||||||
|
Alloc: TGtkAllocation;
|
||||||
|
AList:PGList;
|
||||||
|
AFixed: PGtkFixed;
|
||||||
|
i:Integer;
|
||||||
|
begin
|
||||||
|
if AWidget=nil then ;
|
||||||
|
|
||||||
|
ACtl := TGtk3GroupBox(Data);
|
||||||
|
|
||||||
|
{$IF DEFINED(GTK3DEBUGSIZE) OR DEFINED(GTK3DEBUGGROUPBOX)}
|
||||||
|
with AGdkRect^ do
|
||||||
|
DebugLn('**** GroupBoxSizeAllocate **** ....',dbgsName(ACtl.LCLObject),
|
||||||
|
' ',Format('GTK x %d y %d w %d h %d',[x, y, width, height]),
|
||||||
|
Format(' LCL W=%d H=%d LLW %d LLH %d upd=%s',[ACtl.LCLObject.Width, ACtl.LCLObject.Height, ACtl.LCLWidth, ACtl.LCLHeight, BoolToStr(ACtl.InUpdate, True)]));
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
with Alloc do
|
||||||
|
begin
|
||||||
|
x := AGdkRect^.x;
|
||||||
|
y := AGdkRect^.y;
|
||||||
|
Width := AGdkRect^.width;
|
||||||
|
Height := AGdkRect^.height;
|
||||||
|
end;
|
||||||
|
|
||||||
|
gtk_widget_set_clip(AWidget, @Alloc);
|
||||||
|
|
||||||
|
if not Assigned(ACtl.LCLObject) then exit;
|
||||||
|
|
||||||
|
// return size w/o frame
|
||||||
|
NewSize.cx := AGdkRect^.width;
|
||||||
|
NewSize.cy := AGdkRect^.height;
|
||||||
|
|
||||||
|
if not (csDesigning in ACtl.LCLObject.ComponentState) then
|
||||||
|
begin
|
||||||
|
if ACtl.InUpdate then
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{$IF DEFINED(GTK3DEBUGSIZE) OR DEFINED(GTK3DEBUGGROUPBOX)}
|
||||||
|
if not ACtl.LCLObject.AutoSize and (ACtl.LCLWidth > 0) and (ACtl.LCLHeight > 0) and
|
||||||
|
ACtl.LCLObject.ClientRectNeedsInterfaceUpdate then
|
||||||
|
begin
|
||||||
|
if (AGdkRect^.Width = ACtl.LCLWidth) and (AGdkRect^.Height = ACtl.LCLHeight) then
|
||||||
|
begin
|
||||||
|
//ACtl.LCLObject.DoAdjustClientRectChange;
|
||||||
|
AFixed := PGtkFixed(ACtl.getContainerWidget);
|
||||||
|
if AFixed^.compute_expand(GTK_ORIENTATION_VERTICAL) then
|
||||||
|
AFixed^.resize_children;
|
||||||
|
// PGtkLayout(AFixed)^.set_size(AFixed^.get_allocated_width, AFixed^.get_allocated_height);
|
||||||
|
gtk_container_foreach(AFixed, @ContainerChildrenCallback, ACtl);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
FillChar(Msg{%H-}, SizeOf(Msg), #0);
|
||||||
|
|
||||||
|
Msg.Msg := LM_SIZE;
|
||||||
|
Msg.SizeType := SIZE_RESTORED;
|
||||||
|
|
||||||
|
Msg.SizeType := Msg.SizeType or Size_SourceIsInterface;
|
||||||
|
|
||||||
|
Msg.Width := Word(NewSize.cx);
|
||||||
|
Msg.Height := Word(NewSize.cy);
|
||||||
|
ACtl.DeliverMessage(Msg);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{This routine is used as long as gtk3 is beta and getClientRect needs debugging}
|
||||||
|
function TGtk3GroupBox.GetInnerClientRect(Frame: PGtkWidget): TRect;
|
||||||
|
var
|
||||||
|
Allocation: TGdkRectangle;
|
||||||
|
AStyleContext: PGtkStyleContext;
|
||||||
|
Padding, Border: TGtkBorder;
|
||||||
|
LabelWidget: PGtkWidget;
|
||||||
|
FinalRect: TGdkRectangle;
|
||||||
|
minH:gint;
|
||||||
|
natH:gint;
|
||||||
|
begin
|
||||||
|
Result := Rect(0, 0, 0, 0);
|
||||||
|
|
||||||
|
gtk_widget_get_allocation(Frame, @Allocation);
|
||||||
|
LabelWidget := gtk_frame_get_label_widget(PGtkFrame(Frame));
|
||||||
|
|
||||||
|
AStyleContext := gtk_widget_get_style_context(Frame);
|
||||||
|
gtk_style_context_get_padding(AStyleContext, GTK_STATE_FLAG_NORMAL, @Padding);
|
||||||
|
gtk_style_context_get_border(AStyleContext, GTK_STATE_FLAG_NORMAL, @Border);
|
||||||
|
|
||||||
|
FinalRect.X := Allocation.X + Border.Left + Padding.Left;
|
||||||
|
FinalRect.Y := Allocation.Y + Border.Top + Padding.Top;
|
||||||
|
FinalRect.Width := Allocation.Width - Border.Left - Border.Right - Padding.Left - Padding.Right;
|
||||||
|
FinalRect.Height := Allocation.Height - Border.Top - Border.Bottom - Padding.Top - Padding.Bottom;
|
||||||
|
|
||||||
|
if PGtkFrame(Frame)^.get_shadow_type > GTK_SHADOW_NONE then
|
||||||
|
begin
|
||||||
|
// this looks like a bug in gtk3, that's why I separated this part of code. Zeljan.
|
||||||
|
if (Border.left = 0) and (Border.Right = 0) then
|
||||||
|
dec(FinalRect.Width, 2);
|
||||||
|
if (Border.Top = 0) and (Border.Bottom = 0) then
|
||||||
|
dec(FinalRect.Height, 2);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if Assigned(LabelWidget) then
|
||||||
|
begin
|
||||||
|
PGtkLabel(LabelWidget)^.get_preferred_height(@minH, @natH);
|
||||||
|
FinalRect.Y := FinalRect.Y + natH;
|
||||||
|
FinalRect.Height := FinalRect.Height - natH;
|
||||||
|
{$IF DEFINED(GTK3DEBUGSIZE) OR DEFINED(GTK3DEBUGGROUPBOX)}
|
||||||
|
writeln('LabelAllocation LCLObject.Caption=',LCLObject.Caption,' LabelText=',PGtkLabel(LabelWidget)^.get_text,' MinH=',MinH,' NatH=',NatH);
|
||||||
|
{$ENDIF}
|
||||||
|
end;
|
||||||
|
|
||||||
|
Result := RectFromGdkRect(FinalRect);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TGtk3GroupBox.ConnectSizeAllocateSignal(ToWidget:PGtkWidget);
|
||||||
|
begin
|
||||||
|
g_signal_connect_data(ToWidget,'size-allocate',TGCallback(@GroupBoxSizeAllocate), Self, nil, G_CONNECT_DEFAULT);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function TGtk3GroupBox.getClientRect:TRect;
|
||||||
|
var
|
||||||
|
Alloc:TGtkAllocation;
|
||||||
|
R: TRect;
|
||||||
|
begin
|
||||||
|
Result := GetInnerClientRect(Widget);
|
||||||
|
Types.OffsetRect(Result, -Result.Left, -Result.Top);
|
||||||
|
end;
|
||||||
|
|
||||||
{ TGtk3Editable }
|
{ TGtk3Editable }
|
||||||
|
|
||||||
@ -5668,7 +5841,6 @@ begin
|
|||||||
VOffset := Bar^.get_allocated_width
|
VOffset := Bar^.get_allocated_width
|
||||||
else
|
else
|
||||||
VOffset := 0;
|
VOffset := 0;
|
||||||
|
|
||||||
AViewPort^.get_view_window^.get_geometry(@x, @y, @w, @h);
|
AViewPort^.get_view_window^.get_geometry(@x, @y, @w, @h);
|
||||||
Result := Bounds(x, y, w - VOffset, h - HOffset);
|
Result := Bounds(x, y, w - VOffset, h - HOffset);
|
||||||
end else
|
end else
|
||||||
@ -7816,6 +7988,24 @@ begin
|
|||||||
check^.set_use_underline(True);
|
check^.set_use_underline(True);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TGtk3CheckBox.SetBounds(ALeft,ATop,AWidth,AHeight:integer);
|
||||||
|
var
|
||||||
|
Alloc:TGtkAllocation;
|
||||||
|
begin
|
||||||
|
if LCLObject.Name = 'HiddenRadioButton' then
|
||||||
|
exit;
|
||||||
|
LCLWidth := AWidth;
|
||||||
|
LCLHeight := AHeight;
|
||||||
|
// not needed
|
||||||
|
// Widget^.set_size_request(AWidth, AHeight);
|
||||||
|
Alloc.x := ALeft;
|
||||||
|
Alloc.y := ATop;
|
||||||
|
Alloc.width := AWidth;
|
||||||
|
Alloc.height := AHeight;
|
||||||
|
Widget^.set_allocation(@Alloc);
|
||||||
|
Move(ALeft, ATop);
|
||||||
|
end;
|
||||||
|
|
||||||
{ TGtk3RadioButton }
|
{ TGtk3RadioButton }
|
||||||
|
|
||||||
function TGtk3RadioButton.CreateWidget(const Params: TCreateParams): PGtkWidget;
|
function TGtk3RadioButton.CreateWidget(const Params: TCreateParams): PGtkWidget;
|
||||||
@ -7879,6 +8069,21 @@ begin
|
|||||||
inherited InitializeWidget;
|
inherited InitializeWidget;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TGtk3RadioButton.getClientRect:TRect;
|
||||||
|
var
|
||||||
|
Alloc:TGtkAllocation;
|
||||||
|
R: TRect;
|
||||||
|
begin
|
||||||
|
Result := Rect(0, 0, 0, 0);
|
||||||
|
//Famous "HiddenRadioButton"
|
||||||
|
if (Widget = nil) then
|
||||||
|
exit;
|
||||||
|
Widget^.get_allocation(@Alloc);
|
||||||
|
Result := Bounds(Alloc.x, Alloc.y, Alloc.Width, Alloc.Height);
|
||||||
|
Types.OffsetRect(Result, -Result.Left, -Result.Top);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
{ TGtk3CustomControl }
|
{ TGtk3CustomControl }
|
||||||
|
|
||||||
function TGtk3CustomControl.CreateWidget(const Params: TCreateParams): PGtkWidget;
|
function TGtk3CustomControl.CreateWidget(const Params: TCreateParams): PGtkWidget;
|
||||||
|
@ -89,6 +89,7 @@ type
|
|||||||
|
|
||||||
TGtk3WSCustomRadioGroup = class(TWSCustomRadioGroup)
|
TGtk3WSCustomRadioGroup = class(TWSCustomRadioGroup)
|
||||||
published
|
published
|
||||||
|
class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLHandle; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TGtk3WSRadioGroup }
|
{ TGtk3WSRadioGroup }
|
||||||
@ -101,6 +102,7 @@ type
|
|||||||
|
|
||||||
TGtk3WSCustomCheckGroup = class(TWSCustomCheckGroup)
|
TGtk3WSCustomCheckGroup = class(TWSCustomCheckGroup)
|
||||||
published
|
published
|
||||||
|
class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLHandle; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TGtk3WSCheckGroup }
|
{ TGtk3WSCheckGroup }
|
||||||
@ -148,7 +150,7 @@ type
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
gtk3widgets;
|
gtk3widgets, Gtk3WSStdCtrls;
|
||||||
|
|
||||||
{ TGtk3WSCustomSplitter }
|
{ TGtk3WSCustomSplitter }
|
||||||
|
|
||||||
@ -161,6 +163,20 @@ begin
|
|||||||
Result := TLCLHandle(ASplitter);
|
Result := TLCLHandle(ASplitter);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
class function TGtk3WSCustomRadioGroup.CreateHandle(const AWinControl:TWinControl;
|
||||||
|
const AParams:TCreateParams):TLCLHandle;
|
||||||
|
begin
|
||||||
|
Result := TGtk3WSCustomGroupBox.CreateHandle(AWinControl,AParams);
|
||||||
|
TGtk3GroupBox(Result).GroupBoxType := gbtRadioGroup;
|
||||||
|
end;
|
||||||
|
|
||||||
|
class function TGtk3WSCustomCheckGroup.CreateHandle(const AWinControl:TWinControl;
|
||||||
|
const AParams:TCreateParams):TLCLHandle;
|
||||||
|
begin
|
||||||
|
Result:= TGtk3WSCustomGroupBox.CreateHandle(AWinControl,AParams);
|
||||||
|
TGtk3GroupBox(Result).GroupBoxType := gbtCheckGroup;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TGtk3WSCustomPanel }
|
{ TGtk3WSCustomPanel }
|
||||||
|
|
||||||
class function TGtk3WSCustomPanel.CreateHandle(const AWinControl: TWinControl;
|
class function TGtk3WSCustomPanel.CreateHandle(const AWinControl: TWinControl;
|
||||||
|
@ -437,16 +437,14 @@ end;
|
|||||||
|
|
||||||
function RegisterCustomRadioGroup: Boolean; alias : 'WSRegisterCustomRadioGroup';
|
function RegisterCustomRadioGroup: Boolean; alias : 'WSRegisterCustomRadioGroup';
|
||||||
begin
|
begin
|
||||||
// RegisterWSComponent(TCustomRadioGroup, TGtk2WSCustomRadioGroup);
|
RegisterWSComponent(TCustomRadioGroup, TGtk3WSCustomRadioGroup);
|
||||||
// RegisterWSComponent(TRadioGroup, TGtk2WSRadioGroup);
|
Result := True;
|
||||||
Result := False;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function RegisterCustomCheckGroup: Boolean; alias : 'WSRegisterCustomCheckGroup';
|
function RegisterCustomCheckGroup: Boolean; alias : 'WSRegisterCustomCheckGroup';
|
||||||
begin
|
begin
|
||||||
// RegisterWSComponent(TCustomCheckGroup, TGtk2WSCustomCheckGroup);
|
RegisterWSComponent(TCustomCheckGroup, TGtk3WSCustomCheckGroup);
|
||||||
// RegisterWSComponent(TCheckGroup, TGtk2WSCheckGroup);
|
Result := True;
|
||||||
Result := False;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function RegisterCustomLabeledEdit: Boolean; alias : 'WSRegisterCustomLabeledEdit';
|
function RegisterCustomLabeledEdit: Boolean; alias : 'WSRegisterCustomLabeledEdit';
|
||||||
|
@ -309,11 +309,10 @@ uses
|
|||||||
|
|
||||||
class function TGtk3WSCustomGroupBox.CreateHandle(
|
class function TGtk3WSCustomGroupBox.CreateHandle(
|
||||||
const AWinControl: TWinControl; const AParams: TCreateParams): TLCLHandle;
|
const AWinControl: TWinControl; const AParams: TCreateParams): TLCLHandle;
|
||||||
var
|
|
||||||
AGroupBox: TGtk3GroupBox;
|
|
||||||
begin
|
begin
|
||||||
AGroupBox := TGtk3GroupBox.Create(AWinControl, AParams);
|
Result := TLCLHandle(TGtk3GroupBox.Create(AWinControl, AParams));
|
||||||
Result := TLCLHandle(AGroupBox);
|
//Gtk3Frame needs label before first call of GetClientRect
|
||||||
|
TGtk3GroupBox(Result).Text := AWinControl.Caption;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class procedure TGtk3WSCustomGroupBox.GetPreferredSize(
|
class procedure TGtk3WSCustomGroupBox.GetPreferredSize(
|
||||||
@ -383,6 +382,7 @@ class procedure TGtk3WSScrollBar.SetKind(const AScrollBar: TCustomScrollBar;
|
|||||||
begin
|
begin
|
||||||
if not WSCheckHandleAllocated(AScrollBar, 'SetKind') then
|
if not WSCheckHandleAllocated(AScrollBar, 'SetKind') then
|
||||||
Exit;
|
Exit;
|
||||||
|
//TODO: try with PGtkOrientable(Widget)^.set_orientation instead of RecreateWnd.
|
||||||
RecreateWnd(AScrollBar);
|
RecreateWnd(AScrollBar);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user