On Sat, Oct 20, 2012 at 9:20 AM, Patrick Totzke <[email protected]> wrote:
> Quoting Ian Ward (2012-10-19 01:50:27)
>> On Tue, Oct 16, 2012 at 11:51 AM, Patrick Totzke
>> <[email protected]> wrote:
>> At the moment I believe it only trims canvases at the bottom end.
>> I've recently updated Columns so that it tries to keep the column in
>> focus visible (see the new horizontal example in the tutorial:
>> http://urwid.readthedocs.org/en/latest/tutorial/index.html#horizontal-menu
>
> This could be helpful for building variable width tree widgets. Will look
> into that.
>
>> ) so it might be better to make Pile do the same thing. I don't know
>> how many people are using Pile that way though.
>
> If Pile could keep the focus on screen and thus display more widgets that fit
> on the screen
> then it would not be all too different from ListBox would it?
> I think this is a good idea. It would certainly relax the need for this
> ueber-widget ListBox :)
Note that Filler already tries to keep the *cursor* visible. So a
Filler(Pile(...flow widgets...), 'top') behaves almost like a ListBox
when in focus and displaying Edits, Buttons etc.
>> >> ListBox: knows about scrolling and selection for vertically stacked
>> >> widgets (implements widget API)
>> >> BaseTreeWalker: provides vertically stacked widget view of a tree of
>> >> widgets (implements list walker API)
>> > ..called ListWalkerAdapter in my code.
>> >
>> >> WidgetTree: provides tree of widgets (implents new tree API
>> >> get_parent, get_sibling, etc)
>> > Called TreeWalker in my code.
>>
>> No that's not quite what I was getting at. Your ListWalkerAdapter
>> points to *another* list walker. I was suggesting having a
>> BaseTreeWalker that would use the new "tree" API in a non-list-walker
>> WidgetTree. i.e. WidgetTree wouldn't implement the list walker API
>> (get_next, get_prev, ..) but it would keep the methods related to
>> traversing a tree.
>
> Not sure if i get your point here:
> You suggest one would use a LixtBox that works on a "BaseTreeWalker", that
> subclasses ListWalker.
> BaseTreeWalker gets its data from a "WidgetTree", a walker like object that
> implements my
> tree-walker api (which happens to be a superset of the list-walker api).
yes right up until the "superset of the list-walker api" part.
> So in a way, BaseTreeWalker translates a Tree-Walker to a List-Walker, adding
> some decoration.
> This is exactly what I'm doing. My "ListWalkerAdapter" uses a "TreeWalker"
> object to implement the
> List walker API, by adding decoration.
> What was missing in your description was some Widget that can not only display
> a given ListWalkerAdapter(TreeWalker()), but also trigger focus movement
> based on the tree
> structure. This is what's called "TreeBox" in my code. It wraps ListBox and
> overwrites keypress().
>
>> Your ListWalkerAdapter would then subclass BaseTreeWalker to implement
>> the particular decoration you want.
> I agree that one will want to subclass "ListWalkerAdapter" (what you called
> "BaseTreeWalker")
> to implement different or more complicated decorations.
> Note that if you do not want any decoration - just display a DF-flattened
> tree as List -
> you can simply not wrap the TreeWalker and directly put it into a ListBox.
> This is because the ListWalker API is a subset of the TreeWalker API.
> If you want no decorations but keep the ability to move focus based on the
> tree structure,
> you'd stick a TreeWalker into a TreeBox. This will then omit the adapter that
> introduces the
> decoration.
> I think we're basically saying the same thing up to isomorphism :)
Pretty much. The only thing I'm trying to say is "don't make the
WidgetTree API a superset of the ListWalker API". Then if you really
wanted an undecorated view of a tree you could use the BaseTreeWalker
(decorations are defined in its subclasses) around your WidgetTree.
The end result is that the WidgetTree API becomes simpler -- and maybe
even usable in things other than a ListBox.
>> What's the difference between that and this?
>>
>> >>> Text('Hello World').pack()[0]
>> 11
>> >>> Text('Hello\nWorld!').pack()[0]
>> 6
>>
>> If you actually mean to calculate the minimum columns required given a
>> number of rows with *any* wrapping, that's not supported by text
>> layouts at the moment, but it could be added if there was a need for
>> it.
>
> You are right, it's he same thing.
> So if all Widgets can do this, then it should not be so difficult to
> introduce horizontal
> scrolling? simply pack() flow widgets to display them side by side..
That's the thing. Only Text (and fixed widgets) implement pack()
usefully at the moment.
Implementing pack() for containers would be great. I haven't done it
yet because I'm a little leery about caching problems that might come
up in making it perform well.
>> > ListBox: I do not understand why keypress is so complicated in ListBox:
>> > Sure, the visible part needs to be determined and this depends on the
>> > focus.
>> > But you only really need to update this visible area when it is rendered.
>> > So Im my opinion, keypress yould simply update the focus position
>> > and all the complicated update-visible-part stuff should go into render(),
>> > which already knows the size.
>> >
>> > All in all it is good practice to keep the API as clean as possible
>> > reagrding
>> > accepted parameters: for a user of the API it is hard to grasp why
>> > keypress should
>> > depend in any way on the size or colour of the widget in question.
>>
>> I don't see how we can remove the size parameter from keypress without
>> requiring that every widget is rendered in advance. And that can't
>> even be done in general.
>
> Note that you are talking implementation details whereas I was
> stating oddities in the API. Still:
Ok, but doesn't "oddities in the API" here mean "keypress has a size parameter"?
> I see that there are some complications with widgets like Edit that maintain
> a cursor
> position when they are displayed multiple times on a screen. If one could
> switch focus to the widget that was rendered first one would move the cursor
> depending on the stored size of the other widget, because this touched the
> stored size last.
> But is this even possible? would the widget not be re-rendered when focussed?
>
> How could/would one want to delegate a keypress to a not yet rendered Widget?
> This seems *so* artificial..
Not at all. Urwid tries to put off rendering until after *all* input
is handled. If it didn't applications would start falling behind user
input and screen resize events. This means there are likely a few
keys to handle between each call to draw_screen(). So if those keys
happen to be ['down', 'down'] and the first one causes a new Edit
widget to scroll in to view and take focus (never rendered) then we
must know the size of that widget to properly handle the second 'down'
key.
>> I wrote ListBox so that it would behave like "less" when nothing in it
>> is selectable, like "gedit" if it's full of Edit widgets, and like a
>> web browser with focus moving between fields when there is a mix.
>> Some selectable widgets can put the cursor anywhere, some can't. Some
>> widgets might be larger than the ListBox itself, but scrolling should
>> still work. When you resize the ListBox the focus position should
>> stay approximately where it was before resizing. All of these
>> considerations taken together make for the mess of exceptions and
>> corner cases you see in ListBox.keypress().
>
> I must say I like your earlier Idea to "pimp" Pile to work on arbitrary
> many widgets. This would keep things simple and one could subclass it
> to implement the stated features of ListBox if required.
> Of course ListBox as it is now must be complicated considering all those
> features.
> Lets see how we can decompose it into smaller and maintainable classes.
>
>> If you have any ideas about how those could be separated out cleanly
>> (especially so they could be modified or extended by the user) I'm
>> interested to hear them.
>
> ListBox.keypress and kids:
> https://github.com/wardi/urwid/blob/master/urwid/listbox.py#L1015 and
> https://github.com/wardi/urwid/blob/master/urwid/listbox.py#L1039 up until
> L1087
> seems to be duplicated code in _keypress_up and _keypress_down.
> Some of it also seems to be present in _keypress_pageup/down.
> I'm not sure what it does exactly, but its certainly a good candidate for a
> helper method.
> Maybe you also want a ListBox._make_focus_visible() and just call this in
> render()
> before doing anything else.
Wait, did I say ideas? I meant patches. Silly me. ;-) Failing
that put it in a ticket so I can look at it when I have time.
Ian
_______________________________________________
Urwid mailing list
[email protected]
http://lists.excess.org/mailman/listinfo/urwid