Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Layouts should perhaps not be widgets #9

Closed
almarklein opened this issue Jun 11, 2015 · 5 comments
Closed

Layouts should perhaps not be widgets #9

almarklein opened this issue Jun 11, 2015 · 5 comments

Comments

@almarklein
Copy link
Member

I initially thought that layout being widgets made things simpler, and it also felt natural because layout are html elements too. However, it makes things less flexible. As Chris put it:

An *extremely* simple case is toggling the layout based on the width
of the parent. This can be changing the orientation of a box layout
or switching from a wrapping flow layout to a vbox layout or
something else.

A more complicated case arises when you build an app which hosts
user-defined content. In these cases you'll typically provide a
widget to user code to use as a host for the user content (which
you know nothing about). If layouts are separate from widgets, you
can just provide an empty widget and the user can assign whatever
layout they please. If not, you have to just choose a host widget
like a VBox, and if that's not what the user wants, they have to
add another level of nesting to achieve their desired layout.

Also interesting: in both Qt and wx, a splitter is a widget, but hbox is a layout. In Qt there is the QStackedLayout, but also the QStackedWidget as a convenience.

Disadvantages of Layouts being widgets:

  • Deep hierarchies. In a custom widget, the self._some_widget.parent will typically not refer to self, but to a layout. To get to self, you may need to .parent several times. This is not a performance thing, because regardless of what we choose, the nesting is this deep in the DOM. It's about how the gui hierarchy feels to the user.
  • The hierarchy (and possibly depth of nesting) changes when you change the layout; you cannot rely on a widgets position in a hierarchy. But maybe you also shouldn't.
  • Toggling the layout of a widget is possible, but a bit awkward.

Disadvantages of Layouts being separate:

  • You have two systems, two hierarchies that are separate, but not quite.
  • If I dynamically add a widget to a custom widget, I need to also add it to the hierarchy, whereas with Layout-Widgets you can just do someWidget.parent = myWidget.hbox.
@almarklein
Copy link
Member Author

If we change this, the way to write app definitions also changes (#10). Actually, it does not, really.

The difference is that with LayoutsAsWidgets you could do:

with HBox():
    with MyCustomWidget():
        with HBox():
           ...

.... but you wouldn't. You would write these "layout descriptions" in each custom (high level) widget, and in the main widget/window/app.

@almarklein
Copy link
Member Author

Idea: add layout.swap(other_layout). This would work for the first case, but not for the second. Although in that case, you could instead ask the user to provide a widget, instead of giving a widget to populate.

@almarklein
Copy link
Member Author

You'd want to be able to do something like this:

    class MyTool(ui.Widget):
        def init(self):
            with ui.VBox():
                self._list = ui.ListBox()
                with self.HBox():
                    ui.Widget(flex=1)  # spacer
                    self._filter = ui.ComboBox()
                    self._menu = ui.MenuButton()

            ... set up to make this work

        def onMenuChange(self):
            ... etc

    class MainWindow(??):
        def init(self):

            with ui.HSplitter():
                ui.TextField(flex=1)
                with ui.VBox():
                    self._tool = MyTool(flex=1)
                    self._status = ui.Label()

The MyTool should derive from Widget, since you do not know how its going to be used. This is a variant on the argument above. To work with this case, a layout in a widget should occupy the full size of that widget, or maybe let the Widget class not have a node associated with them (pop it out).

Actually, if Layouts are not widgets, the same applies to the DOM, so there is no difference in that respect. Where the two approaches do differ is that when Layouts are Widgets. self._tool._filter.parent.parent.parent.parent.amIThereYet? is the main window, whereas if Layout is separated, it would be self._tool._filter.parent.parent.

Write an event handler:

    def onMenuChange(self, event):
        ... calc new options
        self._filter.set_new_options(options)

    def onMenuChange(self, event):
        ... calc new options
        filter = event.owner.children[-1]
        filter.set_new_options(options)

The second one would be problematic with LayoutsAsWidgets. But you should probably use this approach anyway. But if this were a JS callback, we'd have to be able to refer to the filter object. Regardless of the approach, we need a solution for this.

@almarklein
Copy link
Member Author

Note Layouts are Widgets in Kivy

@almarklein
Copy link
Member Author

Layouts are widgets ("panels") in Phosphor now as well. Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant