Christopher R. Hertel | 5 Jun 2011 20:21

Screens with forms with fixed-length input fields.

I raised a question on IRC and got some very good help.  I was asked to
post both problem and solution to the list, so here goes...

I am working on a module to create old-school input screens.  I used
this code as an example:

  http://bitbucket.org/robla/urwid-demo/wiki/Home

...but I needed slightly different behavior so I written my own module.
(Note: If you want to view the above referenced code, dig through the
web page a little.  There are several versions.  I used the newest I
could find.)

The demo code at that URL uses the urwid Edit widget for all input.  I
needed a couple of changes to meet my goals.  In particular, the Edit
widget does not support fixed-length input.  Here's a code snippet to
show what I've done:

    prompt  = u.Text( "Gimme Input:", align='right' )
    prompt  = u.AttrMap( prompt, 'normal', 'focusprompt' )
    #
    f_widget = u.AttrMap( TextEdit( "", fwidth ), 'normal', 'focusfield' )
    f_widget = u.Padding( f_widget, width=fwidth+1, right=2 )
    f_widget = [ prompt, ('weight', 2, f_widget) ]
    f_widget = u.Columns( f_widget, dividechars=1 )
    f_widget = u.AttrMap( f_widget, None, {'normal':'focusprompt'} )
    self._widgets.append( f_widget )

The first line creates the prompt Text widget from the string "Gimme
Input:". In my code I use a variable.  Promise.  ;)
(Continue reading)

Christopher R. Hertel | 5 Jun 2011 20:59

Re: Screens with forms with fixed-length input fields.

Christopher R. Hertel <crh <at> ubiqx.mn.org> writes:

One more note about this code snippet:

>     prompt  = u.Text( "Gimme Input:", align='right' )
>     prompt  = u.AttrMap( prompt, 'normal', 'focusprompt' )
>     #
>     f_widget = u.AttrMap( TextEdit( "", fwidth ), 'normal', 'focusfield' )
>     f_widget = u.Padding( f_widget, width=fwidth+1, right=2 )
>     f_widget = [ prompt, ('weight', 2, f_widget) ]
>     f_widget = u.Columns( f_widget, dividechars=1 )
>     f_widget = u.AttrMap( f_widget, None, {'normal':'focusprompt'} )
>     self._widgets.append( f_widget )

Note that I set attributes on the prompt twice: in the second line, and in the
penultimate line.

The first time, I set them on the Text object.  The second time, I set them on
the Columns object.  That works, but if I comment out *either* line the prompt
fails to change attributes when the column row is in focus.

I just don't understand why that is the case.

I also don't understand why I don't need to set the normal/focusfield
attributes on the Columns object.  Those attributes work fine.

Chris -)-----
Patrick Totzke | 16 Jun 2011 09:06

mapping of space key


Hi all!
I wonder how I could map the space key in combination with a modifier:
Currently, I use something like

if key == ' ':
  key = 'page down'

so that my UI interprets space as a page down. How do I now map
shift-space to page up? I tried 'shift ', 'shift  ', and 'shift \ '
so far..
Thanks,
/patrick

_______________________________________________
Urwid mailing list
Urwid <at> lists.excess.org
http://lists.excess.org/mailman/listinfo/urwid
Ian Ward | 16 Jun 2011 16:37
Favicon
Gravatar

Re: mapping of space key

Patrick Totzke wrote on 2011-06-16 03:06:
> 
> Hi all!
> I wonder how I could map the space key in combination with a modifier:
> Currently, I use something like
> 
> if key == ' ':
>   key = 'page down'

Take a look at command_map.  It can be used to globally assign space to
'cursor page down' that should have the effect you want.

> 
> so that my UI interprets space as a page down. How do I now map
> shift-space to page up? I tried 'shift ', 'shift  ', and 'shift \ '
> so far..

I don't know of any terminal that sends a different input sequence for
shift+space.  Try input_test.py to see what I mean.  You'll have to
choose a more compatible key combination.

Ian
goffi | 19 Jun 2011 22:55

How to detect that urwid lost focus ?

G'day everybody,

is there a way to detect that Urwid lost focus ? I mean when the user 
leave the term, not just changing the widget with focus.

For my XMPP client, I'd like to know when the user is not on the term to 
show notifications when somebody is writing to him.

My idea is to detect if we are on X, use Xlib to detect the focus 
windows, and look for the term name or my app name in the window title, 
but it seems a big hacky. Is there a more elegant way to do that ?

thx :)

Goffi
Ian Ward | 20 Jun 2011 00:12
Favicon
Gravatar

Re: How to detect that urwid lost focus ?

On 06/19/2011 04:55 PM, goffi wrote:
> G'day everybody,
>
> is there a way to detect that Urwid lost focus ? I mean when the user
> leave the term, not just changing the widget with focus.
>
> For my XMPP client, I'd like to know when the user is not on the term to
> show notifications when somebody is writing to him.
>
> My idea is to detect if we are on X, use Xlib to detect the focus
> windows, and look for the term name or my app name in the window title,
> but it seems a big hacky. Is there a more elegant way to do that ?

sure, if you're willing to rely on having a connection to an X server 
you can get all sorts of focus events.  Try running xev, you can see 
things like

  VisibilityNotify event, serial 34, synthetic NO, window 0x5600001,
      state VisibilityFullyObscured

Ian
g h | 1 Jul 2011 21:51
Picon
Favicon

dynamic Text component within render

Is it possible to get a field to dynamically update on every render call? I'm trying to get a "status panel"
which will display arbitrary information that my update frequently (network statistics, for example)

Or do I need to make a separate thread in Python and call set_text() in that thread?  Is urwid thread safe?

What I have:

class ActionArea(urwid.Pile):
    txt = None
    
    def __init__(self):
        self.txt = urwid.Text(('banner', " Hello World 2 "), align='center')
        
        edit1 = urwid.Edit("field1")
        edit2 = urwid.Edit("field1")
        
        super(ActionArea,self).__init__([txt_box, edit1, edit2], focus_item=1)
        
    def render(self, size, focus=False):
        out = subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE).communicate()[0]
        if self.txt is not None:
            self.txt.set_text(out)
        return super(ActionArea, self).render(size,focus)
Ian Ward | 1 Jul 2011 22:08
Favicon
Gravatar

Re: dynamic Text component within render

Hello g,

g h wrote on 2011-07-01 15:51:
> Is it possible to get a field to dynamically update on every render
> call? I'm trying to get a "status panel" which will display arbitrary
> information that my update frequently (network statistics, for
> example)

render() is generally called only when a widget is on the screen and its
content is marked as having changed.  So, it doesn't really fit the
model you want.

> Or do I need to make a separate thread in Python and call set_text()
> in that thread?  Is urwid thread safe?

No, Urwid is not designed to have widgets updated from one thread and
drawn from another.  it might be safe if the widget's size doesn't
change, but I'm not sure.  You would have to add your own locking or
communication between threads, like a pipe and use event_loop.watch_file
to add a callback.

The easy method for what you want is to call loop.set_alarm_in(1,
update_my_dynamic_fields), where update_my_dynamic_fields is a function
you define.

Ian

Gmane