bear_hug.widgets module

Various useful Widget and Listener classes These widgets and listeners are usable outside the ECS and should be sufficient for simpler games and apps. However, for the sake of clearer architecture, entities are recommended.

bear_hug.widgets.deserialize_widget(serial, atlas=None)

Provided a JSON string, return a widget it encodes.

Specifics of JSON format are described in the Widget class documentation. It is important to know, though, that the Widget subclass that a given JSON encodes should be imported to the code that attempts to call this function.

Parameters:serial – a JSON string or dict
Returns:a Widget instance
bear_hug.widgets.deserialize_animation(serial, atlas=None)

Deserialize an animation from a JSON dump

Parameters:serial – A JSON string or a dict.
Returns:an Animation instance.
class bear_hug.widgets.Widget(chars, colors, z_level=0)

Bases: object

The base class for things that can be placed on the terminal.

This class is inactive and is intended to be either inherited from or used for non-interactive non-animated objects. Event processing and animations are covered by its subclasses; while it has on_event() method, it does nothing. This allows Widgets to work without subscribing to the queue and saves some work on not redrawing them unless the Widget itself considers it necessary.

Under the hood, this class does little more than store two 2-nested lists of chars and colors (for characters that comprise the image and their colors). These two should be exactly the same shape, otherwise a BearException is raised.

Widgets can be serialized into JSON similarly to Components and Entities. repr(widget) is used for serialization and should generate a valid JSON-encoded dict. It should always include a class key which should equal the class name for that component and will be used by a deserializer to determine what to create. chars and ``colors` keys are also necessary. They should encode widget’s chars and colors as arrays of strings and each of these strings should be a list of values for chars’ and colors’ inner lists (str-converted chars and str-converted #ffffff-type colors; comma-separated for colors).

All other keys will be deserialized and treated as kwargs to a newly-created object. To define the deserialization protocol, JSON dict may also contain keys formatted as {kwarg_name}_type’`` which should be a string and will be eval-ed during deserialization. Only Python’s builtin converters (eg str, int or float) are safe; custom ones are currently unsupported.

For example, the following is a valid JSON:

{"class": "MyWidget",
"chars": ["b,b,b", "a,b,a", "b,a,b"],
"colors": ["#fff,#fff,#fff", "#000,#fff,#000", "#fff,#000,#fff"],
"former_owners": ["asd", "zxc", "qwe"],
"former_owners_type": "set"}

Its deserialization is equivalent to the following call:

x = MyWidget(chars=[['bbb'],
                    ['aba'],
                    ['bab']],
             colors=[['#fff','#fff','#fff'],
                     ['#000','#fff','#000'],
                     ['#fff','#000','#fff']],
             former_owners=set(['asd, 'zxc', 'qwe']))

The following keys are forbidden: parent and terminal. Kwarg validity is not controlled except by WidgetSubclass.__init__().

Parameters:
  • chars – a 2-nested list of unicode characters
  • colors – a 2-nested list of colors. Anything that is accepted by terminal.color() goes here (a color name or a 0xAARRGGBB/0xRRGGBB/0xRGB/0xARGB integer are fine, (r, g, b) tuples are unreliable).
  • z_level – a Z-level to determine objects’ overlap. Used by (Scrollable)ECSLayout. Not to be mixed up with a terminal layer, these are two independent systems.
flip(axis)

Flip a widget along one of the axes.

Note that this method has extremely limited uses: first, it only affects chars and colors as they are now. If later the widget gets updated via animation, updating label text, Layout’s children being redrawn, etc., it will be un-flipped again.

Second, most ASCII-art just doesn’t take it well. Unlike raster and vector graphics, there is no general way to flip an ASCII image programmatically (except, of course, flipping chars themselves which I find aesthetically unacceptable for my projects). It may work for random noisy tiles, like littered floors, grass and such, but for complex images it’s better to provide both left and right versions.

Parameters:axis – An axis along which to flip. Either one of {‘x’, ‘horizontal’} or one of {‘y’, ‘vertical’}
Returns:
class bear_hug.widgets.SwitchingWidget(chars=None, colors=None, images_dict=None, initial_image=None, **kwargs)

Bases: bear_hug.widgets.Widget

A widget that can contain a collection of chars/colors pairs and switch them on command.

These char/color pairs should all be the same shape. Does not do any transition animations.

chars and colors args, although accepted during creation, are discarded. They do not affect the created widget in any way, nor are they shown at any moment.

Parameters:
  • images_dict – a dict of {image_id: (chars, colors)}
  • initial_image – an ID of the first image to show. Should be a key in images_dict.
switch_to_image(image_id)

Switch to a given image ID

The ID should be a key in the original image_dict. Otherwise, BearException is raised.

Parameters:image_id – image ID, str.
class bear_hug.widgets.Layout(chars, colors, **kwargs)

Bases: bear_hug.widgets.Widget

A widget that can add others as its children.

All children get drawn to its chars and colors, and are thus displayed within a single bearlibterminal layer. Therefore, if children overlap each other, the lower one is hidden completely. In the resolution of who covers whom, a newer child always wins. The layout does not explicitly pass events to its children, they are expected to subscribe to event queue by themselves.

The Layout is initialized with a single child, which is given chars and colors provided at Layout creation. This child is available as l.children[0] or as l.background. Its type is always Widget.

The Layout automatically redraws itself on tick event, whether its children have updated or not.

Does not support JSON serialization

Parameters:
  • chars – chars for layout BG.
  • colors – colors for layout BG.
add_child(child, pos, skip_checks=False)

Add a widget as a child at a given position.

The child has to be a Widget or a Widget subclass that haven’t yet been added to this Layout and whose dimensions are less than or equal to the Layout’s. The position is in the Layout coordinates, ie relative to its top left corner.

Parameters:
  • child – A widget to add.
  • pos – A widget position, (x, y) 2-tuple
remove_child(child, remove_completely=True)

Remove a child from a Layout.

Parameters:
  • child – the child to remove
  • remove_completely – if False, the child is only removed from the

screen, but remains in the children list. This is not intended to be used and is included only to prevent self.move_child from messing with child order.

move_child(child, new_pos)

Remove the child and add it at a new position.

Parameters:
  • child – A child Widget
  • new_pos – An (x, y) 2-tuple within the layout.
on_event(event)

Redraw itself, if necessary

get_absolute_pos(relative_pos)

Get an absolute position (in terminal coordinates) for any location within self.

Parameters:relative_pos – An (x, y) 2-tuple in Layout coordinates
Returns:An (x, y) 2-tuple for the same point in terminal coordinates.
get_child_on_pos(pos, return_bg=False)

Return the newest child on a given position.

Parameters:
  • pos – Position in Layout coordinates
  • return_bg – If True, return background widget when clicking outside any children. If False, return None in this case. Defaults to False
Returns:

Widget instance or None

class bear_hug.widgets.ScrollBar(orientation='vertical', length=10, colors=('gray', 'white'), **kwargs)

Bases: bear_hug.widgets.Widget

A scrollbar to be used with ScrollableLayout.

Does not accept input, does not support serialization.

Parameters:
  • orientation – Scrolling direction. One of ‘vertical’ or ‘horizontal’
  • length – Scrollbar length, in chars.
  • colors – A 2-tuple of (BG colour, moving thingy colour)
show_pos(position, percentage)

Move the scrollbar.

Parameters:position – Float. The position of the top (or left) side of the

scrollbar, as part of its length

Parameters:percentage – Float. The lengths of the scrollbar, as part of the

total bar length

class bear_hug.widgets.ScrollableLayout(chars, colors, view_pos=(0, 0), view_size=(10, 10), **kwargs)

Bases: bear_hug.widgets.Layout

A Layout that can show only a part of its surface.

Like a Layout, accepts chars and colors on creation, which should be the size of the entire layout, not the visible area. The latter is initialized by view_pos and view_size arguments.

Does not support JSON serialization.

Parameters:
  • chars – Layout BG chars.
  • colors – Layout BG colors.
  • view_pos – a 2-tuple (x,y) for the top left corner of visible area, in Layout coordinates.
  • view_size – a 2-tuple (width, height) for the size of visible area.
scroll_to(pos)

Move field of view to pos.

Raises BearLayoutException on incorrect position

Parameters:pos – A 2-tuple of (x, y) in layout coordinates
scroll_by(shift)

Move field of view by shift[0] to the right and by shift[1] down.

Raises BearLayoutException on incorrect position

Parameters:shift – A 2-tuple of (dx, dy) in layout coordinates
class bear_hug.widgets.InputScrollable(chars, colors, view_pos=(0, 0), view_size=(10, 10), bottom_bar=False, right_bar=False, **kwargs)

Bases: bear_hug.widgets.Layout

A ScrollableLayout wrapper that accepts input events and supports the usual scrollable view bells and whistles. Like ScrollableLayout, accepts chars and colors the size of the entire layout and inits visible area using view_pos and view_size.

If bottom_bar and/or right_bar is set to True, it will be made one char bigger than view_size in the corresponding dimension to add ScrollBar.

Can be scrolled by arrow keys.

Does not support JSON serialization

class bear_hug.widgets.Animation(frames, fps, frame_ids=None)

Bases: object

A data class for animation, ie the sequence of the frames

Animation can be serialized to JSON, preserving fps and either frame dumps (similarly to widget chars and colors) or frame image IDs. For the latter to work, these IDs should be provided during Animation creation via an optional frame_ids kwarg. The deserializer will then use them with whichever atlas is supplied to create the animation.

Since this class has no idea of atlases and is unaware whether it was created with the same atlas as deserializer will use (which REALLY should be the same, doing otherwise is just asking for trouble), frame ID validity is not checked until deserialization and, if incorrect, are not guaranteed to work.

Parameters:
  • frames – a list of (chars, colors) tuples
  • fps – animation speed, in frames per second. If higher than terminal FPS, animation will be shown at terminal FPS.
  • frame_ids – an optional list of frame names in atlas, to avoid dumping frames. Raises BearJSONException if its length isn’t equal to that of frames.
class bear_hug.widgets.SimpleAnimationWidget(animation, *args, is_running=True, emit_ecs=True, z_level=0)

Bases: bear_hug.widgets.Widget

A simple animated widget that cycles through the frames.

Parameters:
  • frames – An iterable of (chars, colors) tuples. These should all be the same size.
  • fps – Animation speed, in frames per second. If higher than terminal FPS, it will be slowed down.
  • emit_ecs – If True, emit ecs_update events on every frame. Useless for widgets outside ECS, but those on ECSLayout are not redrawn unless this event is emitted or something else causes ECSLayout to redraw.
class bear_hug.widgets.MultipleAnimationWidget(animations, initial_animation, emit_ecs=True, cycle=False, z_level=0)

Bases: bear_hug.widgets.Widget

A widget that is able to display multiple animations.

Plays only one of the animations, unless ordered to change it by self.set_animation()

Parameters:
  • animations – A dict of {animation_id: Animation()}
  • initial_animation – the animation to start from.
  • emit_ecs – If True, emit ecs_update events on every frame. Useless for widgets outside ECS, but those on ECSLayout are not redrawn unless this event is emitted or something else causes the layout to redraw.
  • cycle – if True, cycles the animation indefinitely. Otherwise stops at the last frame.
set_animation(anim_id, cycle=False)

Set the next animation to be played.

Parameters:
  • anim_id – Animation ID. Should be present in self.animations
  • cycle – Whether to cycle the animation. Default False.
class bear_hug.widgets.Label(text, chars=None, colors=None, just='left', color='white', width=None, height=None, **kwargs)

Bases: bear_hug.widgets.Widget

A widget that displays text.

Accepts only a single string, whether single- or multiline (ie containing ``

`` or not). Does not support any complex text markup. Label’s text can be

edited at any time by setting label.text property. Note that it overwrites any changes to self.chars and self.colors made after setting self.text the last time.

Unlike text, Label’s height and width cannot be changed. Set these to accomodate all possible inputs during Label creation. If a text is too big to fit into the Label, ValueError is raised.

param text:string to be displayed
param just:horizontal text justification, one of ‘left’, ‘right’

or ‘center’. Default ‘left’.

param color:bearlibterminal-compatible color. Default ‘white’
param width:text area width. Defaults to the length of the longest ``

-delimited substring in ``text.

param height:text area height. Defaults to the line count in text
class bear_hug.widgets.InputField(name='Input field', accept_input=True, finishing=False, **kwargs)

Bases: bear_hug.widgets.Label

A single-line field for keyboard input.

The length of the input line is limited by the InputField size. When the input is finished (by pressing ENTER), InputField emits a BearEvent(event_type='text_input', event_value=(field.name, field.text))

Since BLT has no support for system keyboard layouts, only supports QWERTY Latin. This also applies to non-letter symbols: for example, comma and period are considered to be different keys even in Russian layout, where they are on the same physical key.

finish()

Finish accepting the input and emit the ‘text_input’ event at the next opportunity. This opportunity will not present itself until the next event is passed to self.on_event.

class bear_hug.widgets.MenuWidget(dispatcher, terminal=None, items=[], header=None, color='white', items_pos=(2, 2), background=None, switch_sound=None, activation_sound=None, **kwargs)

Bases: bear_hug.widgets.Layout

A menu widget that includes multiple buttons.

Parameters:
  • dispatcher – BearEventDispatcher instance to which the menu will subscribe
  • items – an iterable of MenuItems
  • background – A background widget for the menu. If not supplied, a default double-thickness box is used. If background widget needs to get events (ie for animation), it should be subscribed by the time it’s passed here.
  • color – A bearlibterminal-compatible color. Used for a menu frame and header text
  • items_pos – A 2-tuple of ints. A position of top-left corner of the 1st MenuItem
  • header – str or None. A menu header. This should not be longer than menu width, otherwise an exception is thrown. Header may look ugly with custom backgrounds, since it’s only intended for non-custom menus.
  • switch_sound – str. A sound which should be played (via play_sound BearEvent) when a button is highlighted.
  • activation_sound – str. A sound which should be played (vai play_sound BearEvent) when a button is pressed
class bear_hug.widgets.MenuItem(text='Test', action=<function MenuItem.<lambda>>, color='white', highlight_color='green', **kwargs)

Bases: bear_hug.widgets.Layout

A button for use inside menus. Includes a label surrounded by a single-width box. Contains a single callable, self.action, which will be called when this button is activated.

MenuItem by itself does not handle any input. It provides self.activate method which should be called by something (presumably a menu containing this button).

Parameters:
  • text – str. A button label
  • action – callable. An action that this MenuItem performs. This should return either None, BearEvent or an iterable of BearEvents
  • color – a bearlibterminal-compatible color that this button has by

default

Parameters:highlight_color – a bearlibterminal-compatible color that this button

has when highlighted via keyboard menu choice or mouse hover.

highlight()

Change button colors to show that it’s highlighted

unhighlight()

Change button colors to show that it’s no longer highlighted :return:

activate()

Perform the button’s action

class bear_hug.widgets.FPSCounter(**kwargs)

Bases: bear_hug.widgets.Label

A simple widget that measures FPS.

Actually just prints 1/(average runtime over the last 100 ticks in seconds), so it takes 100 ticks to get an accurate reading. Not relevant except on the first several seconds of the program run or after FPS has changed, but if it seems like the game takes a second or two to reach the target FPS – it just seems that way.

class bear_hug.widgets.MousePosWidget(**kwargs)

Bases: bear_hug.widgets.Label

A simple widget that reports current mouse position.

In order to work, it needs self.terminal to be set to the current terminal, which means it should either be added to the terminal directly (without any Layouts) or terminal should be set manually before MousePosWidget gets its first tick event. It is also important that this class uses misc_input:TK_MOUSE_MOVE events to determine mouse position, so it would report a default value of ‘000x000’ until the mouse has moved at least once.

class bear_hug.widgets.Listener(terminal=None)

Bases: object

A base class for the things that need to interact with the queue (and maybe the terminal), but aren’t Widgets.

Parameters:terminal – BearTerminal instance
on_event(event)

The event callback. This should be overridden by child classes.

Parameters:event – BearEvent instance
register_terminal(terminal)

Register a terminal with which this listener will interact

Parameters:terminal – A BearTerminal instance
class bear_hug.widgets.ClosingListener

Bases: bear_hug.widgets.Listener

The listener that waits for a TK_CLOSE input event (Alt-F4 or closing window) and sends the shutdown service event to the queue when it gets one.

All widgets are expected to listen to it and immediately save their data or do whatever they need to do about it. On the next tick ClosingListener closes both terminal and queue altogether.

class bear_hug.widgets.LoggingListener(handle)

Bases: bear_hug.widgets.Listener

A listener that logs the events it gets.

It just prints whatever events it gets to sys.stderr. The correct way to use this class is to subscribe an instance to the events of interest and watch the output. If logging non-builtin events, make sure that their event_value can be converted to a string. Converstion uses str(value), not repr(value) to avoid dumping entire JSON representations.