The Accidental Rubyist

invalid byte sequence in UTF-8

Archive for January 2009

First real app with Ruby-Curses (rbcurse)

leave a comment »

I decided to start doing a small app to test out the widgets (VIDEO). More real life than the eye-candy I’ve been posting till now. Its a TODO like app which will actually manage my TODO, FIXME, DONE list that I am using for this. The base is a YAML file – not the best idea compared to a database, I know, since the list will grow with time.

So a lot of minor issues and bugs or gaps are getting taken care of. Yes, occasionally a bug creeps in too!
I am realizing that for real-life table sorting and filtering is required — without touching the table model, else I wont be able to write back to disk. I have it in mind, an intermediate view that maps to the table model.

I will be adding more options or customizations so the widgets suit real needs rather than just look cute.
Here’s the first rough screen-shot after half a day of work. I _am_ using it! This link will have an updated screenshot, updated daily once. Another.

Todo app with cursor on category combo list

Todo app with cursor on category combo list

Briefly, Category is a combo and refreshes the table with items for that category such as TODO, DONE, FIXME etc.
The :CHANGED event is bound to refresh the table.
Within the table, Module and Status are combos too. Priority is numeric, and Task is wider than displayed and will horizontally scroll. Within the table, TAB and backtab will go from cell to cell. After the last cell, they go to next row. When no more row, they go to next field. Alt-Tab and Alt-backtab immediately moved to next/previous field.

Down and UP arrow, C-n and C-p, do vertical navigation or paging. Interestingly, combos use UP and DOWN for changing the value, however, this app unbinds the combos UP and DOWN so it can be used by Table for navigation. One can still change combo values using M-Down (alt-down). One rarely modifies Module anyway. This is one example of actual usage making me change or tweak widgets.

Editing automatically happens on entering a cell. In the demo video, editing on a cell required hitting ENTER. Otherwise the cells were readonly, and navigation was fast. This is optional now. Tables that have very little editing such as a Finder/File Explorer can require user to press ENTER to make a cell editable.

Hopefully, by Jan end, I can release a V0.1.

Check todo.yml and testtodo.rb on github. VIDEO LINK.

Update: I have added an ApplicationHeader class and KeyLabels like alpine (email client) has at top and bottom. See latest screenshot. In this image, cursor moves to the Tasks Table and the keys printed below change. Table Row is updated as you scroll down the table.

Advertisements

Written by totalrecall

January 18, 2009 at 8:25 pm

Posted in ncurses, rbcurse, ruby

Editable Multi-column tables

leave a comment »

Quite excited to share that I’ve just got editable tables coded and running. String, numeric, checkboxes (for boolean) and combolists. That sort of covers the minimum requirements of an editable table. Also see earlier post with a non-edit table that allowed column moving, resizing etc.

Editable table

Editable table

A quicktime file demos this 2.6 MB).  Updated on Jan 16th.

1. Keys! One needs to decide whether editing should automatically happen when you enter a field (I have used that approach in the editable lists) or upon a key.
In tables, I’ve starting editing on hitting ENTER. Save also on hitting ENTER. Esc or C-c cancels edit.

The demos shows me editing a couple of string fields, cancelling an edit, toggling a checkbox and then changing values in a combo list on 2 rows. All this is easily possible due to CellRenderers and CellEditors. Thus, one can easily add another widget onto a table, and just run some tests to ensure it’s working and displaying fine.

I guess now for some time, I will tweak and clean up – nothing new. I shall try writing some sample apps, to figure out anything missing, integrating this with some yaml files and a database. Perhaps a table row sorter could happen (I love writing new stuff!)

Edit: Updated demo. You can also see events being fired in the Events field below.

Screenshot.
Demo.

Written by totalrecall

January 13, 2009 at 1:58 am

Posted in ncurses, rbcurse, ruby

Editable lists: Fields, Checkboxes, ComboBoxes

leave a comment »

Thanks to CellRenderers and CellEditors, we may edit existing lists with just this line added:


  cell_editing_allowed true
  

If you want row selectors to be shown:


    show_selector true
  

The selector itself may be changed, the default is a gt sign: “>”

Editable list using Field class

Editable list using Field class

Since the rows are selectable, therefore you can make a list of items, and select some as you would in a checklist, or todo list. However, now the user can edit and add to the list also. However, editing facilities means that keys for selection and navigation need to be selected so they do not clash with editing keys. Earlier, space bar selected.

Here is the result on a list of strings. When the cursor falls on the row, the default CellEditor which uses a Field is used for accepting keys. You may extend and install your own editor, as we have done for checkboxes and combos.

By default, boolean values would show as “true” and “false”, so we needed to create a CheckBoxCellRenderer, that display true and false just as a checkbox does. As far as the CellEditor is concerned, just pass a Checkbox in the constructor. It will be reused for editing each row.(link)

The 2 important lines are:


          # create and set a cell renderer

          cell_renderer RubyCurses::CheckBoxCellRenderer.new nil, {"parent" => self, "display_length"=> @width-2}

          # create and set a cell editor, passing a checkbox
          cell_editor RubyCurses::CellEditor.new(RubyCurses::CheckBox.new nil, {"focusable"=>false, "visible"=>false})

  

A listing of the box code is as follows. alist is the list of boolean values.


        alist = [true, false, true, false, true, false, true, false, true]
        cblist = RVariable.new alist
        listcb = Listbox.new @form do
          name   "cblist"
          row  1
          col  96
          width 8
          height 10
#         list mylist
          list_variable cblist
          #selection_mode :SINGLE
          title "Checklist"
          title_attrib 'reverse'
          cell_renderer RubyCurses::CheckBoxCellRenderer.new nil, {"parent" => self, "display_length"=> @width-2}
          cell_editing_allowed true
          cell_editor RubyCurses::CellEditor.new(RubyCurses::CheckBox.new nil, {"focusable"=>false, "visible"=>false})
        end
  

The above will be of more practical value when we allow editable multi-column tables, with columns containing Fields, checkboxes etc.

A list of editable checkboxes, and one of combolists

A list of editable checkboxes, and one of combolists

The next example is of a list of comboboxes. The main lines are those setting the CellRenderer (not really required, i think, since the combobox extends Field. However, the editor is created with a combobox passed in the constructor of the editor. Note that the constructor of the combobox must pass in the list or list_data_model, as before.


          cell_renderer RubyCurses::ComboBoxCellRenderer.new nil, {"parent" => self, "display_length"=> width()-2}
          cell_editing_allowed true
          cell_editor RubyCurses::CellEditor.new(RubyCurses::ComboBox.new nil, {"focusable"=>false, "visible"=>false, "list"=>colist, "display_length"=>width()-2})

  

Written by totalrecall

January 11, 2009 at 9:41 pm

Posted in rbcurse, ruby

Big internal changes amiss

leave a comment »

Some major changes (internal)

### firing property change

1. In order not to repaint the entire form each time, we must only repaint a widget when modified. However, as can be seen, widgets are being modified by other widgets. Thus whenever a property is changed, we need a flag to be set that repainting is required.

### dsl_property

Thus, copied dsl_accessorand made dsl_property. Whenever, such props are modified, a property change is now fired, and repaint_required is set to true. I am currently changing this. What this means is that on startup, fire_prop_change will be called many times, and i need to avoid this on first time instantiation. TODO.

2. The tricky part was text_variables. When their value changes, any widget (such as label) automatically changes. NOW: When a text_variable is defined for field, internally that field, adds itself as a dependent. When its value is changed, it fires a change to the dependent field.

3. The real worrisome part was this:

When user passes in a hash in the constructor, i was directly setting variables, NOT calling methods. Tracked this down. Now i am calling methods and not setting variables. See rwidget.rb variable_set (top). Only thorough testing will tell how much this change will affect stuff. Maybe not.

4. Rewriting Listboxes: the scrolling and painting logic was crap. I did not understand modules then. I think I have had an insight into modules and classes now. Also, a ListCellRenderer is being used, as in Table.

So basically, things are going to be unstable for a week or so.

Written by totalrecall

January 8, 2009 at 1:50 am

Posted in rbcurse, ruby

Those alternating rows everyone craves

leave a comment »

Just thought i’d override the TableCellRenderer and set it, and voila, those alternating colored rows some folks want.

testtable.rb contains various column manipulations, as well as a sample of editing table cells using an external field.

alternate colors on rows

alternate colors on rows

Written by totalrecall

January 7, 2009 at 1:26 am

Posted in ruby

class Table : rough release

leave a comment »

A wip release of Table, tabular data based on the MVC architecture. Default models and listeners and created and can be manipulated for specific behaviour. CellRenderers are used for columns and headers which may be set or modified.

Besides selection of rows, and scrolling, column add/delete/move/resizing are supported. Listeners on selection and change are to be worked on. Currently, editing is not provided, but coming in future release.

The demo (1.3 mb) shows columns being widened and narrowed, column deletion, etc.
The first screenshot shows 2 selected rows, and one focussed row.

Ruby Curses Table with row selection

Ruby Curses Table with row selection

The second screenshot is after moving a row, and narrowing the first row. Demo link.

Row moving and resizing

Row moving and resizing

Written by totalrecall

January 6, 2009 at 1:17 am

Posted in rbcurse, ruby