Gtk3: Fixed button sizing/autosizing by introducing LCLGtkButton class, fixed SetScrollInfo, fixed GetClientRect for all scrollable widgets.

This commit is contained in:
zeljan1 2025-01-18 23:33:42 +01:00
parent b230dabbd3
commit 0c0b6882c0
4 changed files with 497 additions and 137 deletions

View File

@ -0,0 +1,150 @@
{%MainUnit gtk3widgets.pas}
const
GTK_BUTTON_CLASS_SIZE = SizeOf(TGtkButtonClass);
GTK_BUTTON_INSTANCE_SIZE = SizeOf(TGtkButton);
procedure LCLGtkButtonGetPreferredWidth(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: LCLGtkButtonGetPreferredWidth invalid params.');
Exit;
end;
if not Gtk3IsWidget(widget) then
begin
DebugLn('Error: LCLGtkButtonGetPreferredWidth 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: cannot get ParentClass !');
Exit;
end;
// Call parent class implementation
ParentClass^.get_preferred_width(widget, min_width, nat_width);
AControl := TGtk3Widget(HwndFromGtkWidget(widget));
if not Assigned(AControl) then
begin
DebugLn('Error: cannot get TGtk3Widget for widget parameter.');
Exit;
end;
// we respect ws width of button if autosize is true.
if AControl.LCLObject.AutoSize then
exit;
// Custom width handling
if AControl.LCLWidth = 0 then
begin
min_width^ := Max(50, AControl.LCLObject.Width);
nat_width^ := Max(50, AControl.LCLObject.Width);
end else
begin
min_width^ := Max(50, AControl.LCLWidth);
nat_width^ := Max(50, AControl.LCLWidth);
end;
end;
procedure LCLGtkButtonGetPreferredHeight(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: LCLGtkButtonGetPreferredHeight invalid params.');
Exit;
end;
if not Gtk3IsWidget(widget) then
begin
DebugLn('Error: LCLGtkButtonGetPreferredHeight 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: 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: cannot get TGtk3Widget for widget parameter.');
Exit;
end;
// we respect ws height if autosize is true.
if AControl.LCLObject.AutoSize then
exit;
// Custom height handling
if AControl.LCLHeight = 0 then
begin
min_height^ := Max(20, AControl.LCLObject.Height);
nat_height^ := Max(20, AControl.LCLObject.Height);
end else
begin
min_height^ := Max(20, AControl.LCLHeight);
nat_height^ := Max(20, AControl.LCLHeight);
end;
end;
procedure LCLGtkButtonClassInit(klass: PGTypeClass; {%H-}data: Pointer); cdecl;
var
AWidgetClass: PGtkWidgetClass;
begin
AWidgetClass := PGtkWidgetClass(klass);
AWidgetClass^.get_preferred_width := @LCLGtkButtonGetPreferredWidth;
AWidgetClass^.get_preferred_height := @LCLGtkButtonGetPreferredHeight;
end;
procedure LCLGtkButtonInstanceInit(instance: PGTypeInstance; {%H-}klass: PGTypeClass); cdecl;
var
buttonWidget: PGtkButton;
begin
buttonWidget := PGtkButton(instance);
// Custom initialization logic (if needed)
end;
var
LCLGtkButtonType: TGType = 0;
function LCLGtkButtonGetType: TGType; cdecl;
const
lcl_button_type_info: TGTypeInfo = (
class_size: GTK_BUTTON_CLASS_SIZE;
base_init: nil;
base_finalize: nil;
class_init: @LCLGtkButtonClassInit;
class_finalize: nil;
class_data: nil;
instance_size: GTK_BUTTON_INSTANCE_SIZE;
n_preallocs: 0;
instance_init: @LCLGtkButtonInstanceInit;
value_table: nil;
);
begin
if LCLGtkButtonType = 0 then
LCLGtkButtonType := g_type_register_static(gtk_button_get_type, 'LCLGtkButton', @lcl_button_type_info, G_TYPE_FLAG_NONE);
Result := LCLGtkButtonType;
end;
function LCLGtkButtonNew: PGtkButton;
begin
Result := PGtkButton(g_object_new(LCLGtkButtonGetType(),'label',['', nil]));
end;

View File

@ -392,6 +392,24 @@ begin
Result := lpGtk3;
end;
//This is the only way to fix missing corner widget in GtkScrolledWindow.
procedure ApplyCustomScrollbarStyles(const APixels: integer);
var
CssProvider: PGtkCssProvider;
begin
CssProvider := gtk_css_provider_new();
gtk_css_provider_load_from_data(CssProvider,
PgChar(Format('scrollbar.horizontal { margin-right: %dpx; }' +
'scrollbar.vertical { margin-bottom: %dpx; }',[APixels, APixels])),
-1, nil);
gtk_style_context_add_provider_for_screen(
gdk_screen_get_default(),
PGtkStyleProvider(CssProvider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION
);
end;
procedure TGtk3WidgetSet.AppInit(var ScreenInfo: TScreenInfo);
var
ScreenDC: HDC;
@ -479,6 +497,11 @@ begin
scrollBarV^.get_preferred_width(@MinH, @PrefH);
FSystemMetricsList.Items[SM_CXVSCROLL] := Max(MinH, PrefH);
//loading distance between scrollbars in corner, since
//gtk3 does not have corner widget, we set it via css.
ApplyCustomScrollbarStyles(Max(0, Floor(PrefH / 2) - 1));
header^.get_preferred_height(@MinH, @PrefH);
FSystemMetricsList.Items[SM_CYCAPTION] := Max(MinH, PrefH);

View File

@ -505,6 +505,7 @@ type
procedure InitializeWidget;override;
procedure SetScrollBarsSignalHandlers;
function getClientBounds: TRect; override;
function getViewport: PGtkViewport; virtual;
function getHorizontalScrollbar: PGtkScrollbar; virtual; abstract;
function getVerticalScrollbar: PGtkScrollbar; virtual; abstract;
function getScrolledWindow: PGtkScrolledWindow; virtual; abstract;
@ -778,6 +779,7 @@ type
function EatArrowKeys(const {%H-}AKey: Word): Boolean; override;
public
procedure InitializeWidget; override;
function getViewport: PGtkViewport; override;
procedure preferredSize(var PreferredWidth, PreferredHeight: integer; {%H-}WithThemeSpace: Boolean); override;
function getClientRect: TRect; override;
function getHorizontalScrollbar: PGtkScrollbar; override;
@ -821,6 +823,7 @@ type
procedure setText(const AValue: String); override;
public
// function getClientBounds: TRect; override;
function getViewport: PGtkViewport; override;
function getClientRect: TRect; override;
function getHorizontalScrollbar: PGtkScrollbar; override;
function getVerticalScrollbar: PGtkScrollbar; override;
@ -1039,6 +1042,7 @@ end;
{$i gtk3lclcombobox.inc}
{$i gtk3lclentry.inc}
{$i gtk3lclbutton.inc}
class function TGtk3Widget.WidgetEvent(widget: PGtkWidget; event: PGdkEvent; data: GPointer): gboolean; cdecl;
begin
@ -5422,17 +5426,139 @@ begin
TGCallback(@Gtk3RangeScrollCB), Self, nil, G_CONNECT_DEFAULT);
end;
{$IFDEF GTK3DEBUGSIZE}
function GetViewportClientAreaWithScrollbars(ScrolledWindow: PGtkScrolledWindow): TRect;
var
Viewport: PGtkViewport;
ViewportAllocation, HScrollbarAllocation, VScrollbarAllocation: TGtkAllocation;
Padding, Border: TGtkBorder;
HScrollbar, VScrollbar: PGtkWidget;
HScrollbarHeight, VScrollbarWidth: Integer;
ScrollPolicyH, ScrollPolicyV: TGtkPolicyType;
StyleContext: PGtkStyleContext;
begin
FillChar(Result, SizeOf(Result), 0);
HScrollbarHeight := 0;
VScrollbarWidth := 0;
Viewport := PGtkViewport(gtk_bin_get_child(PGtkBin(ScrolledWindow)));
if Viewport = nil then
begin
writeln('Viewport not found.');
Exit;
end;
gtk_widget_get_allocation(PGtkWidget(Viewport), @ViewportAllocation);
//Get the style context for padding and border
StyleContext := gtk_widget_get_style_context(PGtkWidget(Viewport));
FillChar(Padding, SizeOf(Padding), 0);
FillChar(Border, SizeOf(Border), 0);
gtk_style_context_get_padding(StyleContext, GTK_STATE_FLAG_NORMAL, @Padding);
gtk_style_context_get_border(StyleContext, GTK_STATE_FLAG_NORMAL, @Border);
// Check scrollbar visibility policies
gtk_scrolled_window_get_policy(ScrolledWindow, @ScrollPolicyH, @ScrollPolicyV);
//Check if the horizontal scrollbar is visible
HScrollbar := gtk_scrolled_window_get_hscrollbar(ScrolledWindow);
if (HScrollbar <> nil) and gtk_widget_get_visible(HScrollbar) and (ScrollPolicyH <> GTK_POLICY_NEVER) then
begin
gtk_widget_get_allocation(HScrollbar, @HScrollbarAllocation);
HScrollbarHeight := HScrollbarAllocation.height;
end;
//Check if the vertical scrollbar is visible
VScrollbar := gtk_scrolled_window_get_vscrollbar(ScrolledWindow);
if (VScrollbar <> nil) and gtk_widget_get_visible(VScrollbar) and (ScrollPolicyV <> GTK_POLICY_NEVER) then
begin
gtk_widget_get_allocation(VScrollbar, @VScrollbarAllocation);
VScrollbarWidth := VScrollbarAllocation.width;
end;
//Now we calculate the client area.
Result.Left := ViewportAllocation.x + Border.left + Padding.left;
Result.Top := ViewportAllocation.y + Border.top + Padding.top;
Result.Right := ViewportAllocation.x + ViewportAllocation.width - Border.right - Padding.right - VScrollbarWidth;
Result.Bottom := ViewportAllocation.y + ViewportAllocation.height - Border.bottom - Padding.bottom - HScrollbarHeight;
writeln(Format('Client Area Calculation: Left=%d, Top=%d, Right=%d, Bottom=%d',
[Result.Left, Result.Top, Result.Right, Result.Bottom]));
end;
{$ENDIF}
function TGtk3ScrollableWin.getClientBounds: TRect;
var
Allocation: TGtkAllocation;
x:gint;
y:gint;
w:gint;
h:gint;
AViewport:PGtkViewport;
AWindow:PGdkWindow;
VOffset, HOffset:gint;
Bar:PGtkScrollbar;
begin
Result := Rect(0, 0, 0, 0);
if IsWidgetOK then
begin
getContainerWidget^.get_allocation(@Allocation);
Result := RectFromGtkAllocation(Allocation);
(*
if (Self is TGtk3CustomControl) then
begin
if Self is TGtk3Window then
Result := GetViewportClientAreaWithScrollbars(PGtkScrolledWindow(TGtk3Window(Self).FScrollWin))
else
Result := GetViewportClientAreaWithScrollbars(PGtkScrolledWindow(FWidget));
//DebugLn('TGtk3ScrollableWin.getClientBounds result ',dbgs(Result),' from viewport ',dbgsName(LCLObject));
exit;
end else
*)
AViewport := getViewPort;
if Assigned(AViewport) and Gtk3IsGdkWindow(AViewport^.get_view_window) then
begin
AWindow := AViewport^.get_view_window;
if Assigned(AWindow) then
begin
Bar := getHorizontalScrollbar;
if (Bar <> nil) and Gtk3IsWidget(Bar) and Bar^.get_visible then
HOffset := Bar^.get_allocated_height
else
HOffset := 0;
Bar := getVerticalScrollbar;
if (Bar <> nil) and Gtk3IsWidget(Bar) and Bar^.get_visible then
VOffset := Bar^.get_allocated_width
else
VOffset := 0;
AViewPort^.get_view_window^.get_geometry(@x, @y, @w, @h);
Result := Bounds(x, y, w - VOffset, h - HOffset);
end else
begin
AViewPort^.get_allocation(@Allocation);
Result := RectFromGtkAllocation(Allocation);
end;
end else
begin
getContainerWidget^.get_allocation(@Allocation);
Result := RectFromGtkAllocation(Allocation);
end;
end;
// DebugLn('TGtk3ScrollableWin.getClientBounds result ',dbgs(Result));
if (Self is TGtk3Window) then
exit;
{$IFDEF GTK3DEBUGSIZE}
if Assigned(AViewPort) then
DebugLn('TGtk3ScrollableWin.getClientBounds result ',dbgs(Result),' from viewport ',dbgsName(LCLObject))
else
;//DebugLn('TGtk3ScrollableWin.getClientBounds result ',dbgs(Result),' no viewport ',dbgsName(LCLObject));
{$ENDIF}
end;
function TGtk3ScrollableWin.getViewport:PGtkViewport;
begin
Result := nil;
end;
{ TGtk3Memo }
@ -7456,7 +7582,7 @@ function TGtk3Button.CreateWidget(const Params: TCreateParams): PGtkWidget;
var
btn:PGtkButton absolute Result;
begin
Result := PGtkWidget(TGtkButton.new);
Result := LCLGtkButtonNew;
btn^.set_use_underline(true);
if not IsDesigning then
@ -7675,6 +7801,11 @@ begin
end;
end;
function TGtk3CustomControl.getViewport:PGtkViewport;
begin
Result := PGtkViewport(PGtkScrolledWindow(Widget)^.get_child);
end;
procedure TGtk3CustomControl.preferredSize(var PreferredWidth,PreferredHeight:
integer;WithThemeSpace:Boolean);
begin
@ -7695,14 +7826,41 @@ var
x: gint;
y: gint;
AViewPort: PGtkViewport;
VOffset, HOffset:gint;
Bar:PGtkScrollbar;
begin
// Result := inherited getClientRect;
AViewPort := PGtkViewPort(FCentralWidget^.get_parent);
AViewPort := getViewport;
if Gtk3IsViewPort(AViewPort) and Gtk3IsGdkWindow(AViewPort^.get_view_window) then
begin
// Result := GetViewportClientAreaWithScrollbars(PGtkScrolledWindow(FWidget));
AViewPort^.get_view_window^.get_geometry(@x, @y, @w, @h);
Result := Rect(0, 0, AViewPort^.get_view_window^.get_width, AViewPort^.get_view_window^.get_height);
// DebugLn('TGtk3CustomControl.GetClientRect via Viewport ',dbgsName(LCLObject),' Result ',dbgs(Result),' X=',dbgs(X),' Y=',dbgs(Y));
Bar := getHorizontalScrollbar;
if (Bar <> nil) and Bar^.get_visible then
HOffset := Bar^.get_allocated_height
else
HOffset := 0;
Bar := getVerticalScrollbar;
if (Bar <> nil) and Gtk3IsWidget(Bar) and Bar^.get_visible then
VOffset := Bar^.get_allocated_width
else
VOffset := 0;
// AViewPort^.get_view_window^.get_frame_extents(@AFrameRect);
Result := Rect(0, 0, AViewPort^.get_view_window^.get_width - VOffset, AViewPort^.get_view_window^.get_height - HOffset);
{$IFDEF GTK3DEBUGSIZE}
DebugLn('TGtk3CustomControl.GetClientRect via Viewport ',dbgsName(LCLObject),' Result ',dbgs(Result),' X=',dbgs(X),' Y=',dbgs(Y),' AllocH=',dbgs(AViewPort^.get_allocated_height));
getContainerWidget^.get_allocation(@Allocation);
with ALlocation do
begin
DebugLn(Format(' GtkFixed alloc x %d y %d width %d height %d',[x, y, width, height]));
end;
{$ENDIF}
exit;
end else
FCentralWidget^.get_allocation(@Allocation);
@ -8065,6 +8223,11 @@ begin
Title := AValue;
end;
function TGtk3Window.getViewport:PGtkViewport;
begin
Result := PGtkViewPort(FScrollWin^.get_child);
end;
function TGtk3Window.getClientRect: TRect;
var
Allocation: TGtkAllocation;

View File

@ -3597,7 +3597,7 @@ begin
if IsRectEmpty(R) then
R := ScrollRect;
{$ENDIF}
gtk_widget_queue_draw(Widget.Widget);
Widget.Update(nil);
end else
if (Flags and SW_INVALIDATE) <> 0 then
begin
@ -3606,13 +3606,15 @@ begin
cairo_region_get_extents(cairoRegion, @UpdateRect);
R := Bounds(UpdateRect.x, UpdateRect.y, UpdateRect.Width, UpdateRect.Height);
prcUpdate := @R;
gtk_widget_queue_draw_area(Widget.GetContainerWidget, UpdateRect.x, UpdateRect.y, UpdateRect.width, UpdateRect.Height);
Widget.Update(@R);
// gtk_widget_queue_draw_area(Widget.GetContainerWidget, UpdateRect.x, UpdateRect.y, UpdateRect.width, UpdateRect.Height);
end else
if prcClip <> nil then
begin
prcUpdate := prcClip;
with prcClip^ do
gtk_widget_queue_draw_area(Widget.GetContainerWidget, Left, Top, Width, Height);
Widget.Update(prcUpdate);
// with prcClip^ do
// gtk_widget_queue_draw_area(Widget.GetContainerWidget, Left, Top, Width, Height);
end;
end;
{$IFDEF DEBUGSCROLLWINDOWEX}
@ -3885,154 +3887,180 @@ end;
function TGtk3WidgetSet.SetScrollInfo(Handle: HWND; SBStyle: Integer;
ScrollInfo: TScrollInfo; bRedraw: Boolean): Integer;
(*
procedure SetRangeUpdatePolicy(Range: PGtkRange);
var
UpdPolicy: TGTKUpdateType;
begin
case ScrollInfo.nTrackPos of
SB_POLICY_DISCONTINUOUS: UpdPolicy := GTK_UPDATE_DISCONTINUOUS;
SB_POLICY_DELAYED: UpdPolicy := GTK_UPDATE_DELAYED;
else
UpdPolicy := GTK_UPDATE_CONTINUOUS;
end;
!!! update policy for gtkRange does not exist anymore in gtk3
so we must mimic that by using events. !!!
gtk_range_set_update_policy(Range, UpdPolicy);
end;
procedure SetScrolledWindowUpdatePolicy(ScrolledWindow:PGTKScrolledWindow);
var
Range: PGtkRange;
begin
case SBStyle of
SB_VERT: Range := PGtkRange(ScrolledWindow^.vscrollbar);
SB_HORZ: Range := PGtkRange(ScrolledWindow^.hscrollbar);
else exit;
end;
SetRangeUpdatePolicy(Range);
end;
*)
const
POLICY: array[BOOLEAN] of TGTKPolicyType = (GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
POLICY: array[Boolean] of TGTKPolicyType = (GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
procedure SetGDouble(var ATarget: Double; ANewValue: Double; var AHasChanged: Boolean);
begin
if ATarget = ANewValue then
Exit;
ATarget := ANewValue;
AHasChanged := True;
end;
var
Adjustment,hadj,vadj: PGtkAdjustment;
AWidget: TGtk3Widget;
ACenter:PGtkWidget;
ARange: PGtkRange;
AScrollWin: PGtkScrolledWindow;
IsScrollbarVis: Boolean;
w,h:gint;
IsScrollbarVis:Boolean;
ScrollWin: PGtkScrolledWindow;
Adjustment: PGtkAdjustment;
IsScrollWindow: Boolean;
HasChanged: Boolean;
ScrollBar: PGtkScrollbar;
W, H: double;
procedure UpdateAdjustment;
var
ATarget: gdouble;
begin
if (ScrollInfo.FMask and SIF_RANGE) <> 0 then
begin
ATarget := Adjustment^.lower;
SetGDouble(ATarget, ScrollInfo.nMin, HasChanged);
Adjustment^.lower := ATarget;
ATarget := Adjustment^.upper;
SetGDouble(ATarget, ScrollInfo.nMax, HasChanged);
Adjustment^.upper := ATarget;
end;
if (ScrollInfo.FMask and SIF_PAGE) <> 0 then
begin
ATarget := Adjustment^.page_size;
SetGDouble(ATarget, ScrollInfo.nPage, HasChanged);
ATarget := Min(Max(ATarget, 0), Adjustment^.upper - Adjustment^.lower + 1);
Adjustment^.page_size := ATarget;
ATarget := Adjustment^.page_increment;
SetGDouble(ATarget, Max(1, (Adjustment^.page_size / 6) + 1), HasChanged);
Adjustment^.page_increment := ATarget;
end;
if (ScrollInfo.FMask and SIF_POS) <> 0 then
begin
ATarget := Adjustment^.value;
SetGDouble(ATarget, ScrollInfo.nPos, HasChanged);
ATarget := Max(ATarget, Adjustment^.lower);
ATarget := Min(ATarget, Adjustment^.upper - Max(Adjustment^.page_size - 1, 0));
Adjustment^.value := ATarget;
end;
end;
procedure HandleRedraw;
var
AHorzPolicy:TGtkPolicyType;
AVertPolicy:TGtkPolicyType;
begin
if bRedraw then
begin
gtk_adjustment_changed(Adjustment);
if IsScrollWindow then // seem that gtk3 does not like this
begin
ScrollWin^.get_policy(@AHorzPolicy, @AVertPolicy);
case SBStyle of
SB_HORZ:
ScrollWin^.set_policy(POLICY[IsScrollbarVis], AVertPolicy);
SB_VERT:
ScrollWin^.set_policy(AHorzPolicy, POLICY[IsScrollbarVis]);
end;
end;
TGtk3Widget(Handle).Update(nil);
end;
end;
begin
Result := 0;
if not IsValidHandle(Handle) then
if not IsValidHandle(Handle) then Exit;
HasChanged := False;
// must implement first
if TGtk3Widget(Handle) is TGtk3Window then
exit;
AWidget := TGtk3Widget(Handle);
Adjustment := nil;
ARange := nil;
AScrollWin := nil;
if wtScrollBar in AWidget.WidgetType then
ScrollWin := nil;
ScrollBar := niL;
if TGtk3Widget(Handle) is TGtk3ScrollBar then
ScrollBar := PGtkScrollBar(TGtk3Widget(Handle).Widget)
else
begin
ARange := PGtkRange(AWidget.Widget);
Adjustment := ARange^.adjustment;
end else
if wtScrollingWin in AWidget.WidgetType then
begin
AScrollWin := TGtk3ScrollableWin(Handle).GetScrolledWindow;
if AScrollWin = nil then
exit;
if not Gtk3IsScrolledWindow(AScrollWin) then
begin
DebugLn('ERROR: TGtk3WidgetSet.SetScrollInfo: Wrong class extracted for scrollwin ',dbgsName(TGtk3Widget(Handle).LCLObject));
AScrollWin := nil;
end;
if Assigned(AScrollWin) then
begin
hadj := AScrollWin^.get_hadjustment;
vadj := AScrollWin^.get_vadjustment;
end else
begin
hadj:=nil;
vadj:=nil;
end;
// TODO: Convert Handle to GtkScrolledWindow, this is not the case with
// TGtk3Window, so we must introduce new function for scrollables
// to return GtkScrollingWindow, like we have with getViewport.
ScrollWin := PGtkScrolledWindow(TGtk3ScrollableWin(Handle).Widget);
if not Assigned(ScrollWin) then Exit;
IsScrollWindow := True;
end;
case SBStyle of
SB_Horz:
SB_HORZ:
begin
if not Assigned(Adjustment) and Assigned(AScrollWin) then
if Assigned(ScrollWin) then
begin
Adjustment := hadj;
if (ScrollInfo.fMask and SIF_RANGE) <> 0 then
Adjustment := gtk_scrolled_window_get_hadjustment(ScrollWin);
ScrollBar := TGtk3ScrollableWin(Handle).getHorizontalScrollbar;
if ((ScrollInfo.fMask and SIF_RANGE) <> 0) and Gtk3IsScrolledWindow(ScrollWin) then
begin
ACenter:=AWidget.GetContainerWidget;
Acenter^.set_size_request(ScrollInfo.nMax - ScrollInfo.nMin,round(vadj^.upper));
H := gtk_scrolled_window_get_vadjustment(ScrollWin)^.upper;
W := (ScrollInfo.nMax - ScrollInfo.nMin) + (gtk_scrolled_window_get_vscrollbar(ScrollWin)^.get_allocated_width * 2{scrollbars overlaps each other, so x2});
W := Max(W, TGtk3ScrollableWin(Handle).getClientRect.Width);
TGtk3ScrollableWin(Handle).GetContainerWidget^.set_size_request(Round(W), Round(H));
end;
end;
end else
Adjustment := ScrollBar^.adjustment;
end;
SB_Vert:
SB_VERT:
begin
if not Assigned(Adjustment) and Assigned(AScrollWin) then
if Assigned(ScrollWin) then
begin
Adjustment := vadj;
if (ScrollInfo.fMask and SIF_RANGE) <> 0 then
Adjustment := gtk_scrolled_window_get_vadjustment(ScrollWin);
ScrollBar := TGtk3ScrollableWin(Handle).getVerticalScrollbar;
if ((ScrollInfo.fMask and SIF_RANGE) <> 0) and Gtk3IsScrolledWindow(ScrollWin) then
begin
ACenter:=AWidget.GetContainerWidget;
Acenter^.set_size_request(round(hadj^.upper),ScrollInfo.nMax - ScrollInfo.nMin);
W := gtk_scrolled_window_get_hadjustment(ScrollWin)^.upper;
H := (ScrollInfo.nMax - ScrollInfo.nMin) + (gtk_scrolled_window_get_hscrollbar(ScrollWin)^.get_allocated_height * 2{scrollbars overlaps each other, so x2});
H := Max(H, TGtk3ScrollAbleWin(Handle).getClientRect.Height);
//writeln(Format('VerticalScrollBar: set new size for Container W=%f H=%f viewport W=%d H=%d HScrollHeight=%d nMax=%f',[W, H, TGtk3ScrollableWin(Handle).getViewport^.get_allocated_width, TGtk3ScrollableWin(Handle).getViewport^.get_allocated_height, gtk_scrolled_window_get_hscrollbar(ScrollWin)^.get_allocated_height, adjustment^.get_upper]));
//writeln(Format('VBAR min %d max %d Scale %d',[ScrollInfo.nMin, ScrollInfo.nMax, ScrollWin^.scale_factor]));
TGtk3ScrollableWin(Handle).GetContainerWidget^.set_size_request(Round(W), Round(H));
end;
end;
end else
Adjustment := ScrollBar^.adjustment;
end;
SB_CTL:
begin
DebugLn('TGtk3WidgetSet.SetScrollInfo SB_CTL error: not implemented ',
dbgsName(AWidget.LCLObject));
if Assigned(ScrollBar) then
Adjustment := ScrollBar^.adjustment
else
if Assigned(ScrollWin) then
begin
//
end else
exit;
end;
SB_BOTH:
begin
DebugLn('TGtk3WidgetSet.SetScrollInfo SB_BOTH error: not implemented ',
dbgsName(AWidget.LCLObject));
DebugLn('[SetScrollInfo] SB_BOTH not implemented yet with gtk3.');
exit;
end;
else
Exit; // Unsupported SBStyle
end;
if Adjustment = nil then
if not Assigned(Adjustment) then
begin
DebugLn('TGtk3WidgetSet.SetScrollInfo error: cannot get PGtkAdjustment from ',
dbgsName(AWidget.LCLObject));
exit;
DebugLn('SetScrollinfo: error adjustment is not assigned !');
Exit;
end;
if (ScrollInfo.fMask and SIF_RANGE) <> 0 then
begin
Adjustment^.lower := ScrollInfo.nMin;
Adjustment^.upper := ScrollInfo.nMax;
end;
if (ScrollInfo.fMask and SIF_PAGE) <> 0 then
begin
// 0 <= nPage <= nMax-nMin+1
Adjustment^.page_size := ScrollInfo.nPage;
Adjustment^.page_size := Min(Max(Adjustment^.page_size,0),
Adjustment^.upper-Adjustment^.lower+1);
Adjustment^.page_increment := (Adjustment^.page_size/6)+1;
end;
if (ScrollInfo.fMask and SIF_POS) <> 0 then
begin
// nMin <= nPos <= nMax - Max(nPage-1,0)
Adjustment^.value := ScrollInfo.nPos;
Adjustment^.value := Max(Adjustment^.value,Adjustment^.lower);
Adjustment^.value := Min(Adjustment^.value,
Adjustment^.upper-Max(Adjustment^.page_size-1,0));
end;
UpdateAdjustment;
// check if scrollbar should be hidden
IsScrollbarVis := True;
if ((ScrollInfo.fMask and (SIF_RANGE or SIF_PAGE)) <> 0) and
((SBStyle=SB_HORZ) or (SBStyle=SB_VERT)) then
begin
((SBStyle=SB_HORZ) or (SBStyle=SB_VERT))
then begin
if (Adjustment^.lower >= (Adjustment^.upper-Max(adjustment^.page_size-1,0)))
then begin
if (ScrollInfo.fMask and SIF_DISABLENOSCROLL) = 0 then
@ -4042,21 +4070,17 @@ begin
// maybe not possible in gtk
end;
end;
if bRedraw then
begin
if (AScrollWin <> nil) then
begin
// DebugLn('Setting scrollstyle of ',dbgsName(AWidget.LCLObject));
if SBStyle = SB_HORZ then
TGtk3ScrollableWin(AWidget).HScrollBarPolicy := POLICY[IsScrollbarVis]
else
if SBStyle = SB_VERT then
TGtk3ScrollableWin(AWidget).VScrollBarPolicy := POLICY[IsScrollbarVis];
end;
AWidget.Update(nil);
Adjustment^.changed;
end;
Result := Round(Adjustment^.value);
if Result < 0 then
begin
DebugLn(Format('WARNING: TGtk3WidgetSet.SetScrollInfo: Result < 0 control %s',[Result, dbgsName(TGtk3Widget(Handle).LCLObject)]));
Result := 0;
end;
HandleRedraw;
end;
function TGtk3WidgetSet.SetSysColors(cElements: Integer; const lpaElements;