Thread overview
How to use ResizerWidget in Dlangui app..?
Dec 30, 2019
ShadoLight
Jan 01, 2020
Ron Tarrant
Jan 01, 2020
ShadoLight
Jan 02, 2020
Rémy Mouëza
Jan 02, 2020
ShadoLight
Jan 03, 2020
ShadoLight
December 30, 2019
Hi,

I suspect I'm missing something obvious, but ResizerWidget is not working for me on Windows - it shows the 'dragging'-cursor when hovering the mouse on the ResizerWidget, but dragging with the left mouse button does nothing.

Reduced very simple example:

///app.d
import dlangui;
import gui;

mixin APP_ENTRY_POINT;


/// entry point for dlangui based application
extern (C) int UIAppMain(string[] args) {
    // create window
    Window window = Platform.instance.createWindow("DlangUI example", null);

    //Make main layout
    auto mainGui = new GuiHandler();
    window.mainWidget = mainGui.makeGui(window);
    // show window
    window.show();

    // run message loop
    return Platform.instance.enterMessageLoop();
}

/// gui.d
import dlangui;

class GuiHandler : ResizeHandler {

	Widget makeGui(Window w) {
		//Make main layout
		auto vlayout = new VerticalLayout();
		vlayout.margins = 20;
		vlayout.padding = 10;ets
		vlayout.backgroundColor = 0xFFFFC0;
		vlayout.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);

		// Layout for editors
		auto editorsLayout = new LinearLayout();
		editorsLayout.orientation = Orientation.Vertical;
		
		//Make edit + trace windows
		auto editor = new EditBox();
		editorsLayout.addChild(editor);
		
		auto resizer = new ResizerWidget();
//		resizer.resizeEvent.connect(this); //Connect for handling events in onResize.
		editorsLayout.addChild(resizer);
		
		auto tracer = new LogWidget();
		editorsLayout.addChild(tracer);
		
		editorsLayout.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
		vlayout.addChild(editorsLayout);
	
		return vlayout;
	}
	
	override void onResize(ResizerWidget source, ResizerEventType event, int currentPosition) {
             //Not shown...
	}
}

I searched through all the dlangui examples where ResizerWidget is used, and none of them provides any onResize event handler as shown above. But, since none of them work (symptoms exactly the same as mine), I am wondering if this is required?

Also checking in DlanguiIDE - nowhere does it implements the onResize event handler for ResizerWidget either. I find this a bit odd - in none of the projects where ResizerWidget are used does it work, but none of these projects provide the onResize event handler either.  Which makes me suspect it is supposed to work 'out of the box' and does not require the event handler for the basic dragging functionality - similar how resizing the whole window works without requiring that you implement it yourself in the OnResize event handler for the main Widget. Also - I can hardly believe that Vadim would have kept putting it in examples, but without it working, so I suspect some regression here if I am not doing something stupid myself (which is always possible!).

There are plenty of 'deprecated' warnings when building dlangui and, since dlangui has not been updated since 2018, I'm concerned it may be breaking with new versions of the compiler.

Alternatively I'm missing something elementary here..? Has anyone used ResizerWidget successfully with a recent version of the compiler on Windows?

win 7
DMD32 D Compiler v2.089.1
dlangui-0.9.182

January 01, 2020
On Monday, 30 December 2019 at 23:32:37 UTC, ShadoLight wrote:
> dragging with the left mouse button does nothing.

>     Window window = Platform.instance.createWindow("DlangUI example", null);

I'm not familiar with this toolkit, but my guess is that you didn't pass in a `flags` value and therefore you aren't using the appropriate overload of the createWindow() function to achieve what you're after.

The following is from the DLangUI GitHub site (https://github.com/buggins/dlangui/wiki/Getting-Started). Take a look at the third argument:

Window createWindow(
    dstring windowCaption, // window caption
    Window parent,         // parent window, pass null for main (first) window.
    uint flags = WindowFlag.Resizable, // various flags - bit fields from WindowFlag enum values
    uint width = 0,        // initial window width
    uint height = 0        // initial window height
);


January 01, 2020
On Wednesday, 1 January 2020 at 10:52:02 UTC, Ron Tarrant wrote:
> On Monday, 30 December 2019 at 23:32:37 UTC, ShadoLight wrote:
>> dragging with the left mouse button does nothing.
>
>>     Window window = Platform.instance.createWindow("DlangUI example", null);
>
> I'm not familiar with this toolkit, but my guess is that you didn't pass in a `flags` value and therefore you aren't using the appropriate overload of the createWindow() function to achieve what you're after.
>
> The following is from the DLangUI GitHub site (https://github.com/buggins/dlangui/wiki/Getting-Started). Take a look at the third argument:
>
> Window createWindow(
>     dstring windowCaption, // window caption
>     Window parent,         // parent window, pass null for main (first) window.
>     uint flags = WindowFlag.Resizable, // various flags - bit fields from WindowFlag enum values
>     uint width = 0,        // initial window width
>     uint height = 0        // initial window height
> );

Thanks for the reply, Ron.

Yes, as you say WindowFlag.Resizable is the default value for the 'flags' argument in the createWindow call, so that was the setting I had.

But the problem is actually not in resizing the full app window (that actually works - including keeping the relative proportions of the widget children sizes), but rather in resizing 2 widgets that are separated by a ResizerWidget inside the app window. The app window size should actually not be affected since, as 1 widget on one side of the ResizerWidget shrinks by N pixels in height or width (depending on the orientation of the ResizerWidget), the opposite widget should grow by the same N pixels in height/width, leaving the parent size unaffected.

I can see that is actually what is coded, but it is not working when I run the app.

But I thought you may be on to something and I should check if children widgets of the app window inherits some settings from the parent, so I checked the WindowFlag flags. According to [1] you can have:
- Fullscreen
- Modal
- Resizable

However, checking the code there are additional options:
/// window creation flags
enum WindowFlag : uint {
    /// window can be resized
    Resizable = 1,
    /// window should be shown in fullscreen mode
    Fullscreen = 2,
    /// modal window - grabs input focus
    Modal = 4,
    /// measure window size on window.show() - helps if you want scrollWindow but on show() you want to set window to mainWidget measured size
    MeasureSize = 8,
    /// window without decorations
    Borderless = 16,
    /// expand window size if main widget minimal size is greater than size defined in window constructor
    ExpandSize = 32,
}

So it looks like the documentation isn't completely up to date either. Anyway, I also tried to pass WindowFlag.Resizable | WindowFlag.MeasureSize as flags argument in the call to createWindow, but it did not help.

I was hoping for a quick answer on the forum from someone who has run into the same, but I think I'm going to need to dig into dlangui code to figure out what is going wrong.

[1]: http://buggins.github.io/dlangui/ddox/dlangui/platforms/common/platform/WindowFlag.html


January 02, 2020
On Monday, 30 December 2019 at 23:32:37 UTC, ShadoLight wrote:
> Hi,
>
> I suspect I'm missing something obvious, but ResizerWidget is not working for me on Windows - it shows the 'dragging'-cursor when hovering the mouse on the ResizerWidget, but dragging with the left mouse button does nothing.
>

I ran into the same issue. The resizeEvent callback is not implemented yet. Below is my custom implementation.


/** A completed resizer widget.
  As of 2016-12-30, the ResizerWidget does not work out of the box.
  This class implement the missing piece.
 */
class Resizer : ResizerWidget {

    /// Default initialization.
    this () {
        super ();
        initResizeCb ();
    }

    /// Create with ID parameter.
    this (string ID, Orientation orient = Orientation.Vertical) {
        super (ID, orient);
        initResizeCb ();
    }

    /// Initialize the resize on drag behaviour callback.
    protected void initResizeCb () {
        this.resizeEvent
            = (ResizerWidget source,
               ResizerEventType event,
               int currentPosition)
        {
            if (event != ResizerEventType.Dragging) {
                return;
            }

            if (_orientation == Orientation.Horizontal) {
                auto delta = _previousWidget.width - currentPosition;
                auto pw    = max (0, _previousWidget.width - delta);
                auto mw    = max (0,     _nextWidget.width + delta);

                _previousWidget
                    .minWidth (pw)
                    .maxWidth (pw);

                _nextWidget
                    .minWidth (mw)
                    .maxWidth (mw);
            }
            else if (_orientation == Orientation.Vertical) {
                auto delta = _previousWidget.height - currentPosition;
                auto pw    = max (0, _previousWidget.height - delta);
                auto mw    = max (0,     _nextWidget.height + delta);

                _previousWidget
                    .minHeight (pw)
                    .maxHeight (pw);

                _nextWidget
                    .minHeight (mw)
                    .maxHeight (mw);
            }

            parent.requestLayout ();
        };
    }
}



January 02, 2020
On Thursday, 2 January 2020 at 05:24:33 UTC, Rémy Mouëza wrote:
> On Monday, 30 December 2019 at 23:32:37 UTC, ShadoLight wrote:
>> Hi,
>>
>> I suspect I'm missing something obvious, but ResizerWidget is not working for me on Windows - it shows the 'dragging'-cursor when hovering the mouse on the ResizerWidget, but dragging with the left mouse button does nothing.
>>
>
> I ran into the same issue. The resizeEvent callback is not implemented yet. Below is my custom implementation.
>
[snip]

OK, I suspected as much. But thanks a lot Rémy! You are saving me a lot of work - much appreciated!


January 03, 2020
On Thursday, 2 January 2020 at 05:24:33 UTC, Rémy Mouëza wrote:
> On Monday, 30 December 2019 at 23:32:37 UTC, ShadoLight wrote:
>> Hi,
>>
>> I suspect I'm missing something obvious, but ResizerWidget is not working for me on Windows - it shows the 'dragging'-cursor when hovering the mouse on the ResizerWidget, but dragging with the left mouse button does nothing.
>>
>
> I ran into the same issue. The resizeEvent callback is not implemented yet. Below is my custom implementation.
>
>
> /** A completed resizer widget.
>   As of 2016-12-30, the ResizerWidget does not work out of the box.
>   This class implement the missing piece.
>  */
> class Resizer : ResizerWidget {
>
>     /// Default initialization.
>     this () {
>         super ();
>         initResizeCb ();
>     }
>
>     /// Create with ID parameter.
>     this (string ID, Orientation orient = Orientation.Vertical) {
>         super (ID, orient);
>         initResizeCb ();
>     }
>
>     /// Initialize the resize on drag behaviour callback.
>     protected void initResizeCb () {
>         this.resizeEvent
>             = (ResizerWidget source,
>                ResizerEventType event,
>                int currentPosition)
>         {
>             if (event != ResizerEventType.Dragging) {
>                 return;
>             }
>
>             if (_orientation == Orientation.Horizontal) {
>                 auto delta = _previousWidget.width - currentPosition;
>                 auto pw    = max (0, _previousWidget.width - delta);
>                 auto mw    = max (0,     _nextWidget.width + delta);
>
>                 _previousWidget
>                     .minWidth (pw)
>                     .maxWidth (pw);
>
>                 _nextWidget
>                     .minWidth (mw)
>                     .maxWidth (mw);
>             }
>             else if (_orientation == Orientation.Vertical) {
>                 auto delta = _previousWidget.height - currentPosition;
>                 auto pw    = max (0, _previousWidget.height - delta);
>                 auto mw    = max (0,     _nextWidget.height + delta);
>
>                 _previousWidget
>                     .minHeight (pw)
>                     .maxHeight (pw);
>
>                 _nextWidget
>                     .minHeight (mw)
>                     .maxHeight (mw);
>             }
>
>             parent.requestLayout ();
>         };
>     }
> }

Remy, just a quick note to say thank you again!

I had to make a small adjustment to make the Resizer class completely generic for all cases, but I can only guess you did not need this as your use case probably had the ResizerWidget parent as the outermost widget.

The issue is that the currentPosition argument in the resizeEvent handler is in terms of the application window, and not in terms of the ResizerWidget parent. So, if you have another widget above the ResizerWidget parent (in the Orientation.Vertical case) or to the left of the ResizerWidget parent (in the Orientation.Horizontal case), you have a small offset issue. The same applies if you have margins or padding on the ResizerWidget parent (or any of its parent(s)).

Anyway, the fix is quite trivial:

    /// Initialize the resize on drag behaviour callback.
    protected void initResizeCb () {
        this.resizeEvent
            = delegate(ResizerWidget source,
               ResizerEventType event,
               int currentPosition)
        {
            if (event != ResizerEventType.Dragging) {
                return;
            }

			int delta;
			int pw;
			int mw;
			int localPos;
            if (_orientation == Orientation.Horizontal) {
		localPos = currentPosition - parent.left;
                delta = _previousWidget.width - localPos;
                pw    = max (0, _previousWidget.width - delta);
                mw    = max (0,     _nextWidget.width + delta);

                _previousWidget
                    .minWidth (pw)
                    .maxWidth (pw);

                _nextWidget
                    .minWidth (mw)
                    .maxWidth (mw);
            }
            else if (_orientation == Orientation.Vertical) {
		localPos = currentPosition - parent.top;
                delta = _previousWidget.height - localPos;
                pw    = max (0, _previousWidget.height - delta);
                mw    = max (0,     _nextWidget.height + delta);

                _previousWidget
                    .minHeight (pw)
                    .maxHeight (pw);

                _nextWidget
                    .minHeight (mw)
                    .maxHeight (mw);
            }

            parent.requestLayout ();
        };
    }
}