[Lazarus] TPairSplitter, Callback when splitter moved

Mattias Gaertner nc-gaertnma at netcologne.de
Sun Aug 25 12:35:09 CEST 2013

On Sun, 25 Aug 2013 11:22:37 +0200
Jürgen Hestermann <juergen.hestermann at gmx.de> wrote:

> Am 2013-08-24 22:58, schrieb Mattias Gaertner:
> > On Fri, 23 Aug 2013 13:50:16 +0200
> > Jürgen Hestermann <juergen.hestermann at gmx.de> wrote:
> >
> >> I can ensure that the ratio between upper and lower panel is a certain ratio by adding an OnResize method like this:
> >> PairSplitter1.Position := Round(PairSplitter1.Height*SplitterRatio);
> >> with SplitterRatio beeing something between 0 and 1 (I used 0.5 to make both (nearly) the same size).
> >>
> >> But if the user now changes the ratio manually I need to update SplitterRatio.
> >> What event is driven when the splitter is moved manually so that I can recalculate SplitterRatio?
> > When the splitter is moved the size of the first side is changed. So,
> > you could use Sides[0].OnResize.
> >
> Well, unfortunately it's not that easy.
> The panel sizes are changed too when the whole form size changes.
> That's what I wanted it to do.
> In this case the new ratio should *not* be recalculated, just the opposite:
> It should resize the 2 controls according to the original ratio.

Store the size of the first side and the pairsplitter control.
In the OnResize compare last sizes with current sizes.
If pairsplitter has same size, then splitter was moved.
As you do below.

> So the same ratio between both sides should exist even after resizing except
> when resizing is caused by moving the splitter in which case a new ratio should be calculated.
> But OnResize is called in all cases and I can't distinguish between the user
> having moved the splitter or the form has changed (and I reapply the old ratio).
> But I found a solution by saving the old height (or width) of the TPairSplitter component:
> -------------------------------------------------------------------------------------
> var SplitterHeightOld : LongInt;
> procedure TForm1.PairSplitter1Resize(Sender : TObject);
> begin
> PairSplitter1.Position := Round(PairSplitter1.Height*SplitterRatio);
> SplitterHeightOld        := PairSplitter1.Height;
> end;
> procedure TForm1.PairSplitterSide1Resize(Sender : TObject);
> begin
> if SplitterHeightOld=PairSplitter1.Height then
>     SplitterRatio := PairSplitter1.Position/PairSplitter1.Height;
> end;
> -------------------------------------------------------------------------------------
> How would I do this when using TSplitter instead of TPairSplitter?

Use Splitter.Parent.OnResize and Splitter.OnMoved.

> It seems I need yet another panel that contains the splitter and the 2 other controls

Sometimes panels are needed, sometimes not. Depends on your controls
and layout.

> so that I can distinguish between size change caused by change of window size or
> by moving the splitter.
> In general, I am astonished that this kind of proportial resizing is not implemented and the default in TPairSplitter.
> I would think that nearly everybody wants this behaviour when two controls should share the same space.
> Why should one of the controls *not* grow when the windows is enlarged (or shrink when it is made smaller)?

Most applications have either a fixed ratio or a manually draggable
splitter. You want a combination.
Feel free to implement that and send a patch. Keep in mind rounding
errors, extreme cases (e.g. too small) and constraints.

> At least an event for the splitter move would be needed.

What's wrong with OnMoved?

> Or even 2 properties "ProportialSizing" (with TRUE as default) and "SizingRatio" (with 0.5 as default).
> But too bad if TPaisSplitter will be removed at all.
> Why is it still there if it should be removed since so many years?

It does not hurt much. The laz devels try to avoid breaking
compatibility without good reason. But since new widgetsets will not
support it it is marked as deprecated.

> I thought that internally it is built with TSplitter anyway,
> so why is it a problem on certain WidgetSets?

That's the reason. It is not implemented with TSplitter, but every
widgetset has to implement it.
If you implement a compatible replacement with TSplitter and two panels
instead, then TPairSplitter can stay.


More information about the Lazarus mailing list