mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-23 08:39:35 +02:00
Gtk3: finally fixed gtk philosophy how content size and adjustments should be calculate so gtk is happy, now TCustomControl have correct scrollbars calculations.
This commit is contained in:
parent
315ee83f9e
commit
66a50ddd0e
@ -532,9 +532,13 @@ type
|
||||
class function RangeChangeValue(ARange: PGtkRange; AScrollType: TGtkScrollType;
|
||||
AValue: gdouble; AData: TGtk3Widget): gboolean; cdecl; static;
|
||||
public
|
||||
LCLVAdj: PGtkAdjustment; // used to keep LCL values
|
||||
LCLHAdj: PGtkAdjustment; // used to keep LCL values
|
||||
procedure DestroyWidget; override;
|
||||
{result = true if scrollbar is pressed by mouse, AMouseOver if mouse is over scrollbar pressed or not.}
|
||||
class function CheckIfScrollbarPressed(scrollbar: PGtkWidget; out AMouseOver:
|
||||
boolean; const ACheckModifier: TGdkModifierTypeIdx): boolean;
|
||||
procedure InitializeWidget; override;
|
||||
procedure SetScrollBarsSignalHandlers(const AIsHorizontalScrollBar: boolean);
|
||||
function getClientBounds: TRect; override;
|
||||
function getViewport: PGtkViewport; virtual;
|
||||
@ -838,6 +842,8 @@ type
|
||||
|
||||
TGtk3CustomControl = class(TGtk3ScrollableWin)
|
||||
strict private
|
||||
class procedure CustomControlLayoutSizeAllocate(AWidget: PGtkWidget;
|
||||
AGdkRect: PGdkRectangle; Data: gpointer); cdecl; static; {very important, see note inside method}
|
||||
class procedure RangeValueChanged(range: PGtkRange; data: gpointer); cdecl; static;
|
||||
protected
|
||||
function CreateWidget(const {%H-}Params: TCreateParams):PGtkWidget; override;
|
||||
@ -5935,6 +5941,13 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TGtk3ScrollableWin.InitializeWidget;
|
||||
begin
|
||||
LCLVAdj := nil;
|
||||
LCLHAdj := nil;
|
||||
inherited InitializeWidget;
|
||||
end;
|
||||
|
||||
class function TGtk3ScrollableWin.RangeChangeValue(ARange: PGtkRange; AScrollType: TGtkScrollType;
|
||||
AValue: gdouble; AData: TGtk3Widget): gboolean; cdecl;
|
||||
var
|
||||
@ -5996,6 +6009,17 @@ begin
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
procedure TGtk3ScrollableWin.DestroyWidget;
|
||||
begin
|
||||
if Assigned(LCLHAdj) then
|
||||
LCLHAdj^.unref;
|
||||
if Assigned(LCLVAdj) then
|
||||
LCLVAdj^.unref;
|
||||
LCLHAdj := nil;
|
||||
LCLVAdj := nil;
|
||||
inherited DestroyWidget;
|
||||
end;
|
||||
|
||||
procedure TGtk3ScrollableWin.SetScrollBarsSignalHandlers(const
|
||||
AIsHorizontalScrollBar:boolean);
|
||||
begin
|
||||
@ -8775,6 +8799,41 @@ end;
|
||||
|
||||
{ TGtk3CustomControl }
|
||||
|
||||
class procedure TGtk3CustomControl.CustomControlLayoutSizeAllocate(AWidget: PGtkWidget;
|
||||
AGdkRect: PGdkRectangle; Data: gpointer); cdecl;
|
||||
var
|
||||
hadj, vadj: PGtkAdjustment;
|
||||
AScrollWin: PGtkScrolledWindow;
|
||||
begin
|
||||
{Note: Gtk expects that we set content size and then it calculates scrollbar values. LCL
|
||||
is doing opposite, it sets scrollbar values eg via SetScrollInfo and then content should
|
||||
be automatically calculated by widgetset. Gtk is crazy about it.
|
||||
So, we are in charge here to help both. We save adjusted values
|
||||
in setscrollinfo in LCLVAdj and LCLHAdj, so after GtkLayout sends size-allocate with accurate
|
||||
content size we apply LCL values to adjustments and everybody is happy.
|
||||
TODO: eg TTreeView editor, if scrollbar position is not at lower pos, showing
|
||||
editor moves scrollbar to pos 0, if we apply LCL saved value here, then
|
||||
editor won't show at all. Maybe moving editor and showing should take into
|
||||
account scrollbar position and calculate x,y offset.}
|
||||
|
||||
hadj := PGtkScrollable(aWidget)^.get_hadjustment;
|
||||
vadj := PGtkScrollable(aWidget)^.get_vadjustment;
|
||||
|
||||
PGtkLayout(aWidget)^.set_size(AGdkRect^.width, AGdkRect^.height);
|
||||
{TODO: eg treeview editor, if scrollbar value > 0 then editor resets position to 0,
|
||||
to fix this we must position editor at y pos - adjustment.value}
|
||||
if Assigned(TGtk3CustomControl(Data).LCLVAdj) and Gtk3IsAdjustment(vadj) then
|
||||
with TGtk3CustomControl(Data).LCLVAdj^ do
|
||||
vadj^.configure(vadj^.value, lower, upper, step_increment, page_increment, page_size);
|
||||
|
||||
if Assigned(TGtk3CustomControl(Data).LCLHAdj) and Gtk3IsAdjustment(hadj) then
|
||||
with TGtk3CustomControl(Data).LCLHAdj^ do
|
||||
hadj^.configure(hadj^.value, lower, upper, step_increment, page_increment, page_size);
|
||||
|
||||
if TGtk3CustomControl(Data).LCLObject.ClientRectNeedsInterfaceUpdate then
|
||||
TGtk3CustomControl(Data).LCLObject.DoAdjustClientRectChange;
|
||||
end;
|
||||
|
||||
function TGtk3CustomControl.CreateWidget(const Params: TCreateParams): PGtkWidget;
|
||||
begin
|
||||
FHasPaint := True;
|
||||
@ -8802,6 +8861,13 @@ begin
|
||||
if not (csDesigning in LCLObject.ComponentState) then
|
||||
g_object_set(PGObject(FCentralWidget), 'resize-mode', [GTK_RESIZE_QUEUE, nil]);
|
||||
gtk_layout_set_size(PGtkLayout(FCentralWidget), 1, 1);
|
||||
|
||||
g_signal_connect_data(FCentralWidget,'size-allocate',TGCallback(@CustomControlLayoutSizeAllocate), Self, nil, G_CONNECT_DEFAULT);
|
||||
|
||||
with PGtkScrolledWindow(Result)^.get_vadjustment^ do
|
||||
LCLVAdj := gtk_adjustment_new(value, lower, upper, step_increment, page_increment, page_size);
|
||||
with PGtkScrolledWindow(Result)^.get_hadjustment^ do
|
||||
LCLHAdj := gtk_adjustment_new(value, lower, upper, step_increment, page_increment, page_size);
|
||||
end;
|
||||
|
||||
function TGtk3CustomControl.EatArrowKeys(const AKey: Word): Boolean;
|
||||
@ -8987,6 +9053,10 @@ begin
|
||||
end else
|
||||
begin
|
||||
Result := Rect(0, 0, PGtkLayout(GetContainerWidget)^.get_allocated_width, PGtkLayout(GetContainerWidget)^.get_allocated_height);
|
||||
//we are not ready, provide at least scrolledwindow size as clientrect for now.
|
||||
//TODO: check scrollbar policy here, and if it's < GTK_POLICY_NEVER apply scrollbars sizes from GetSystemMetrics.
|
||||
if (Result.Width <= 1) and (Result.Height <= 1) then
|
||||
Result := Rect(0, 0, Widget^.get_allocated_width, Widget^.get_allocated_height);
|
||||
end;
|
||||
//writeln('CustomControl clientRect=',dbgs(Result));
|
||||
exit;
|
||||
|
@ -4040,6 +4040,22 @@ var
|
||||
end;
|
||||
end;
|
||||
|
||||
if SBStyle = SB_VERT then
|
||||
begin
|
||||
if (AControl is TGtk3CustomControl) and Assigned(TGtk3CustomControl(AControl).LCLVAdj) then
|
||||
begin
|
||||
with Adjustment^ do
|
||||
TGtk3CustomControl(AControl).LCLVAdj^.configure(value, lower, upper, step_increment, page_increment, page_size);
|
||||
end;
|
||||
end else
|
||||
if SBStyle = SB_HORZ then
|
||||
begin
|
||||
if (AControl is TGtk3CustomControl) and Assigned(TGtk3CustomControl(AControl).LCLHAdj) then
|
||||
begin
|
||||
with Adjustment^ do
|
||||
TGtk3CustomControl(AControl).LCLHAdj^.configure(value, lower, upper, step_increment, page_increment, page_size);
|
||||
end;
|
||||
end;
|
||||
gtk_adjustment_changed(Adjustment);
|
||||
{$IFDEF GTK3DEBUGSCROLL}
|
||||
DebugLn(Format('Updated Adjustment: lower=%.2f, upper=%.2f, page_size=%.2f, value=%.2f, page_increment=%.2f InUpdate %s',
|
||||
@ -4065,11 +4081,9 @@ var
|
||||
if AHorzPolicy <> POLICY[IsScrollbarVis] then
|
||||
ScrollWin^.set_policy(POLICY[IsScrollbarVis], AVertPolicy);
|
||||
if Gtk3WidgetSet.OverlayScrolling and Gtk3IsWidget(Scrollbar) and
|
||||
ScrollBar^.get_visible and
|
||||
Gtk3IsGdkWindow(ScrollBar^.window) then
|
||||
ScrollBar^.get_visible then
|
||||
begin
|
||||
ScrollBar^.set_can_focus(False);
|
||||
ScrollBar^.window^.raise_;
|
||||
if (csDesigning in AControl.LCLObject.ComponentState) then
|
||||
ScrollBar^.sensitive := false;
|
||||
end;
|
||||
@ -4079,11 +4093,9 @@ var
|
||||
if AVertPolicy <> POLICY[IsScrollbarVis] then
|
||||
ScrollWin^.set_policy(AHorzPolicy, POLICY[IsScrollbarVis]);
|
||||
if Gtk3WidgetSet.OverlayScrolling and Gtk3IsWidget(Scrollbar) and
|
||||
ScrollBar^.get_visible and
|
||||
Gtk3IsGdkWindow(ScrollBar^.window) then
|
||||
ScrollBar^.get_visible then
|
||||
begin
|
||||
ScrollBar^.set_can_focus(False);
|
||||
ScrollBar^.window^.raise_;
|
||||
if (csDesigning in AControl.LCLObject.ComponentState) then
|
||||
ScrollBar^.sensitive := false;
|
||||
end;
|
||||
|
Loading…
Reference in New Issue
Block a user