On Tue, Oct 16, 2012 at 11:51 AM, Patrick Totzke
<[email protected]> wrote:
> Quoting Ian Ward (2012-10-14 15:18:05)
>> On Sat, Oct 13, 2012 at 12:42 PM, Patrick Totzke
>> <[email protected]> wrote:
>> > Quoting Ian Ward (2012-10-13 14:47:04)
>> >> On Fri, Oct 12, 2012 at 6:23 PM, Patrick Totzke <[email protected]> 
>> >> wrote:
>> > What does Pile do if there is too little space for its entire content?
>
> question remains..

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
) 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.

>> >> Here's another idea: do the decoration in a ListWalker subclass that
>> >> takes a tree walker object which only implements tree operations (not
>> >> a superclass or subclass of ListWalker).  This way we can mix and
>> >> match different types of trees and different decorations.
>> >
>> > I don't like this idea to be honest. Its not much different from
>> > making TreeBox a WidgetWrap'ed ListBox, adding some padding to the left in 
>> > each line.
>> > In fact, *this* would be the easy way to come up with a Widget for 
>> > displaying TreeWalker.
>> > Maybe I'll build this as a short term solution. But its not pretty.
>> > I'd like to keep the Walkers semantical objects only: no decorations, no 
>> > info on folding.
>> > In my opinion these Walkers form some topology that one can explore by 
>> > means of a TreeBox-Widget
>> > that defines the way one sees and moves in the structure. </metaphermode>
>
> OK I added a widget to my POC repository that does exactly this.
> check out https://github.com/pazz/urwidtrees
> But we should be aware that this can only be a short term solution
> as this means that the screen width and indentation level imply a fixed!
> tree-depth one can display. In the long run I think a "TreeBox"
> that generalizes ListBox, scrolling in two dimensions is inevitable!
>
>> Maybe I explained that poorly.
>>
>> 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.

Your ListWalkerAdapter would then subclass BaseTreeWalker to implement
the particular decoration you want.  Your WidgetTree would know how to
traverse the tree.  All concerns nicely separated, no?

>> Subclasses of BaseTreeWalker could implement any decoration they like,
>> and implement folding with the widgets they return if they so choose.
>
> agreed (for now)
>
>> I believe that folding is tied closely to the decoration.  It might
>> have a clickable [+] for example
>
> definitely. folding and decoration should be handeled in the same class:
> in the Widget that displays a TreeWalker.
> In my code this is TreeBox (via its ListWalkerAdapter).
>
>> Classes that implement the tree API act as an adapter for their
>> particular tree format and return widgets corresponding to the
>> elements in the tree but not the decorations.
>
> yes.
>
>
>> >> Horizontal scrolling means the widgets in the ListBox would have to be
>> >> fixed widgets not flow widgets.
>> >
>> > Yes, agreed: this is problematic. Maybe there should be some complement 
>> > method of
>> > `pack` (that if i understand correctly computes the most compact way one 
>> > can display the widget),
>> > namely one method that returns the size of the widget if one gives it as 
>> > much horizontal
>> > space as it wants. For Text for instance, this would return the maximal 
>> > length of any contained
>> > text line. One had to ensure that all basic widgets return a finite value 
>> > here. then this would
>> > propagate to higher level containers.
>>
>> Text already does :-)
>>
>>   >>> Text('Hello World').pack()
>>   (11, 1)
>>   >>> Text('Hello World').pack((10,))
>>   (5, 2)
>
> Well, I meant something that gives you the horizontal space needed if you 
> provide
> the vertical space. Something like
>
>   >>> Text('Hello World').vpack()
>   11
>   >>> Text('Hello\nWorld!').vpack()
>   6

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.

> Lets get to the nitty gritty :)
>> >> > - set_focus_valign this is to position the visible area around the 
>> >> > focussed widget.
>> >> >   It needs to be overwritten for TreeBox as the visible area is now two 
>> >> > dimensional.
>> >> >   Whats the difference to `shift_focus` and why does the latter need to 
>> >> > know the size
>> >> >   of the whole TreeBox?
>> >>
>> >> One acts immediately and the other does the next time one of the
>> >> normal widget APIs gets the "current" size.  Remember widgets
>> >> don't have a size:
>> >> http://urwid.readthedocs.org/en/latest/manual/widgets.html#custom-widgets
>> >
>> > I agree with the concept that a Widget itself has no size and can be 
>> > rendered
>> > on a Canvas in different sizes. This means that whenever you want to 
>> > `render`,
>> > you need to provide a size, OK.
>> > But i fail to see why one would ever need that size while reacting to 
>> > input.
>> > I get some input, i make some internal changes, if these trigger changes 
>> > that need to be made
>> > visible, then i trigger a 'modified' signal (or sth similar) and this in 
>> > turn
>> > will result in the Mainloop re-rendering this Widget and *then* will 
>> > provide the necessary
>> > dimension to `render`. Maybe I'm not seeing something obvious here but 
>> > `keypress` itself should
>> > not need that parameter right?
>>
>> One case where it is needed is in an Edit widget where the text is
>> wrapped.  keypress(down/up) needs to know how the text is wrapped to
>> figure out what the new cursor position is.  ListBox also needs to
>> know the size to figure out how and when update the scrolling position
>> in response to up/down/page up/page down.
>
> Edit: I see that if you press key down/up in a Edit, then the next cursor 
> position
> depends on the way the Widget *is* currently rendered, because this is what 
> the user bases
> his keypress on: he wants to move to the word that is currently displayes in 
> direction X.
> But this information you can get by remembering the last size given to 
> render().
> (if the widget wasn't rendered before that input was pointless).

I don't like the requirement that a widget must have been rendered
once before accepting keyboard input works.  Also in the (admittedly
silly) case where a single Edit widget was rendered two different
sizes it wouldn't work.  A less silly case is a widget that was just
scrolled in to view by a keypress -- you would have to render it in
the middle of processing input, somehow.

> 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.

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().

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.

Ian

_______________________________________________
Urwid mailing list
[email protected]
http://lists.excess.org/mailman/listinfo/urwid

Reply via email to