Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

2264 lines (1666 sloc) 85.865 kb
NOTES
=====
/// vim:ts=4:sw=4:tw=80:ai:formatoptions=tcqnl:
/// this was posted with appenddiary.sh (notes)
Subject: Update rubyforge
-------------------------
To update the file named index.html on rubyforge use this. password is in
rubyforge config file.
scp index.html rkumar@rubyforge.org:/var/www/gforge-projects/rbcurse
* * *
Subject: subwin benefit
-----------------------
Date: 2009-10-09 23:32
Just found out after playing with subwins that they don't let you write onto
the window below. Perfect for us for components that overwrite!! However, no
way to hide a subwin for later display
* * *
Subject: Upgrading widgets
--------------------------
Date: 2009-11-02 14:45
1. We need to use `create_buffer` either in constructor or repaint or whenever
you are likely to have a width and height. Recommended in beginning of
repaint().
Use `safe_create_buffer`
2. Use `@buffer_modified = true` in repaint
3. Ensure `print_border` and `printstring` are getting correct coordinates. Most
errors happen here.
4. Replace @form.window with @graphic
5. `set_form_col` needs to call `setrowcol` as in rtextarea.
Also, you need to add cols_panned and rows_panned so the widget knows
how much it as been panned, and keeps the cursor in correct place.
6. `set_form_row` needs to call setrowcol as in rtextarea. See above entry
for details.
7. Need to add the following in initialization of container such as rscrollpane
or rsplitpane:
`should_create_buffer true`
Also when creating a widget to put inside a container, use this line (see
samples below), as this needs to happen at construction time.
(This is in the application file when creating an instance, not the widget class).
8. Remove any `dsl_accessor` on height or width since this will override widget.
If you create a method, call `super()`. You need to create a method called
height and width in order to pass delta down to children components if
applicable, also call `super`.
9. You may have to `print_borders()` in `repaint()`, checking for `@repaint_all` (see
rtextview.rb). i.e, don't print just once in constructor, since when the
object is placed inside a splitpane, its size can change.
if @should_create_buffer
$log.debug " overriding editors comp with GRAPHIC #{@graphic} " editor.component.override_graphic(@graphic) # 2010-01-05 00:36 TRYING OUT BUFFERED
end
See testscrollp.rb or testscrollta.rb for working sample.
* * *
Subject: Scrollpane's form
--------------------------
Date: 2009-12-27 20:08
Since scrollpane's child object has no form, scrollpane needs to have its own form
and hand it to child object. However, set_form was overwriting the existing @graphic
so nothing was printed.
Had to put a check so graphic (buffer) not overwritten. Now the child object does
print correctly with a form object. No crashing regarding nil form.
1. Container objects such as scrollpane and splitpane which have widgets
with nil forms require to create a form using existing graphic object
as window and hand that to the child objects.
* * * * * * * *
Subject: Moving cursor in ScrollPane's child
--------------------------------------------
Date: 2009-12-28 23:19
Since child has its own form, had to hack an if clause in child object
(ListScrollable in the case of Textarea) to modify parent forms row and col.
Also added a parent_form in form.
However, this needs to be done in scrollpane or other higher up place, so i
don't have to keep doing it.
ALso what if there are multiple objects in a heirarchy. Splitpane contains
another Splitpane which contains some object. The setting must bubble up all the
way.
* * * * * * * *
Subject: class Form - set_form_rowcol
-------------------------------------
Date: 2009-12-29 15:28
Form should have a method rather than allow direct setting.
This method can percolate up to a parent form if not the same as current.
* * * * * * * *
Subject: More on scrollpane and other widgets
---------------------------------------------
Date: 2009-12-30 18:03
I have added a Form.rows_panned and cols_panned, so that a form know
how much its objects have been panned by. Otherwise there was no way
of Textarea knowing it had been panned. It would keep resetting the
cursor to the wrong value. rows_panned allows it to account for panning
so the cursor can flash at where insertion is happening.
See Scrollpane, handle_keys, around line 224.
* * * * * * * *
Subject: Scrollpane's cursor out of bounds - known bug
------------------------------------------------------
Date: 2009-12-31 09:42
I've tried various ways to handle this - currently a variable named
outofbounds. However, some little logic error causes the cursor
to lose synch with the caret (insertion point).
So until I can sort that out, we live with the cursor going cruising
across the screen, although it does remain very true to the insertion
point so no data can get mucked up.
* * * * * * * *
Subject: more thoughts on cursor display
----------------------------------------
Date: 2009-12-31 17:14
I deleted the todo item regarding widgets maintain cursor display
themselves, but now i think the insertion point is specfic to some
widgets not all, and that the widget should perhaps maintain it
themselves.
Most widgets highlight a line or item within. There is no editing
happening. On a GUI there really is no cursor. However, textfields and
textareas do have an insertion point (caret?). If they maitain their own
insertion points, then when they are hidden or panned, the cursor would
get hidden automatically since i assume its painted onto the buffer or
pad.
For example, tabbedpanes work just fine in these widgets since they take
care fo their ownfocssing and selection.
* * * * * * * *
Subject: Textarea overwrite problem
-----------------------------------
Date: 2010-01-03 17:54
I think it's like this.. (reference test2.rb sample program)
Textarea uses a pad, which does a `prefresh` onto screen.
All the other widgets (unbuffered) write to a window which does a
`wrefresh`. This refresh overwrites the write that `prefresh` did.
Acco to the manpage, certain optimizations are done with what is
already there on the screen. My guess is that a window wrefresh does not
disturb what is on the right, but it does overwrite what's on the left.
Now, scrollpane and splitpane use a `buffer_to_screen` passing their own
graphic object, so the main window is written onto. I need to confirm
this by placing something on the right. Here, since textarea was not a
child or embedded object, a `pad.refresh` was done.
I think i need to ensure that a `copy_pad_to_win` is done in these cases,
by passing a graphic object. At least the source of this bug is now
clear to me now.
* * * * * * * *
Subject: Thoughts on the buffered (pad) approach
------------------------------------------------
Date: 2010-01-05 12:03
Buffering all widgets means that there will be a huge number of pads
beign created for a screen that has a lot of fields. Lots of copying and
possibilities of errors.
In ordinary cases, there should be only one window, as in the old
version. The buffered approach is only required if a scrollpane or
splitpane is being used, even there only what is embedded will create its
own buffer. That simplifies the whole thing. The usual execution path
will be the old simple one.
It may make more sense for the container to pass a buffer to the child
and so on, rather than each level creating a buffer and copying to the
higher level. That may totally eliminate having to create buffered
objects, just have scrollpane and splitpane create a buffer and hand it
down. I need to think this over, why did i not think of this before.
The reason for this is that each level does not know what will be
displayed and what will be truncated. So it writes things out full,
or as much is the widget coordinates. The next level does the relevant
truncation. So the current approach is correct, however, when it can be
avoided and one window used, only one should be. This will be in 99%
cases. In anycase, listbox, textarea and textview and table implement
their own scrolling, so one really does not need scrollpane for them.
Scrollpane may be needed when we create a scrollable form.
So we can have a `should_buffer(boolean)`, which goes the buffer route (if
set true by parent), else things continue with a form.window as before.
added later 2010-01-05 13:24 :
Regarding conditional buffering, what if some component containing components,
such as a listbox or table containing editor components is place in a form which
is placed in a scrollpane. The scrollpane can set `should_buffer` for the child,
but what of all the lower components ? Should this be passed down ?
* * * * * * * *
Subject: Implementing a scrollable form
---------------------------------------
Date: 2010-01-05 12:34
Two approaches come to mind:
1. Create a form using a pad (i/o of a window). Form will have to
handle scroll keys if child does not handle them.
Ensure that pad writes onto physical screen, not a window (like it
used to).
2. Create the usual window and scrollpane.
Make the child a form-widget -- a widget that contains a form, sends
messages to form. However, the form should be based on a pad.
In both cases, a form is based on a pad, so objects can be placed in
a larger area than the physical screen.
* * * * * * * *
Subject: form.setrowcol and rowcol
----------------------------------
Date: 2010-01-05 21:11
i began setting both row and col from `set_form_row`, but it does not know
the current col. `rowcol` seems to return the position where printing
should start, or the cursor should be positioned on entry first time.
So i am now passing nil for c, so col is not disturbed.
test2.rb's listbox is now editing fine, cursor is moving when editing.
However, in scrollpane with pads etc, the cursor is not moving.
* * * * * * * *
Subject: embedded splitpanes
----------------------------
Date: 2010-01-07 19:19
*Case*: splitpane within another splitpane.
*Examples*: ruby doc or java doc. Now think text mode, no mouse, no
dragging. Open ruby docs or java docs in `links`.
Lets take a realistic scenario of a splitpane which contains a splitpane
as one (or both) components. We've defined some key/s to resize a
splitpane, but now which splitpane gets the key. How does the user
specify which level the key pertains to.
In textual browsers such as links, "frames" have been used. So you are
inside a frame. Your key pertains to that frame and you tab between
frames. Using splitpanes, when you are in a component you are inside a
splitpane too. So in the case of a splitpane within another, you are in
2 splitpanes.
When you tab into a splitpane, I'd like to make it easy and put the
focus inside the first component. You can switch between components. But
you are never really focussed on the splitpane. Any keys not processed
by the child components are passed up to the splitpane. Thats how it
does resizing, or changing orientation.
The other option is that you first focus on the splitpane, and then tab
once more to the first component. Ugh ! But it allows you use simple
keys like plus and minus to resize. Thus in a multilevel scrollpane,
you'd need many tabs to get to the actual component.
There's a third option, i do as before, but give a special key to go to
outer splitpane, so conditionally focus can go onto splitpane.
* * * * * * * *
Subject: repaint_all
--------------------
Date: 2010-01-08 20:29
I have added repaint_all and repaint_required in class Widget.
Sometime a parent wants to tell its child to repaint, and there's no
way. The only way was to fire a handler.
Also added a repaint_all, so if some widgets want to print a border or
clear area only on a major change (like dimension change), they can use
this flag. Calling repaint_all, sets repaint_required also. The latter
is for usual data changes.
* * * * * * * *
Subject: Splitpane and cascading dimension changes to child
-----------------------------------------------------------
Date: 2010-01-09 20:37
**Splitpane**, moving divider.
Now by default, changes to width and height are *not* cascaded to child
components.
However, as and when the divider is increased beyond size of first
component, the first component will enlarge and automatically its buffer
is resized.
I've also worked on preventing the crash. Essentially, the screen_buffer
should not become less than the components pane. This can happen in 2
ways, one is the buffer is resized whenever component increases. I was
(by oversight) overriding widget's height having defined a dsl_accessor
in textview.
However, if you don't want to resize the buffer, then one should not
call `set_screen_max_row_col` if it exceeds the warning condition. This
warning is if one is creating a new widget, if it crashes on `copywin`
and Height is more than `smaxrow()` then you'll have a crash. So resize
at that time by simply increasing the widgets height, or else put a
check in widget so that the method is not called for this condition.
* * * * * * * *
Subject: maxlen in rtextview
----------------------------
Date: 2010-01-10 19:28
Made a change in rtextview.
In the constructor, maxlen if nil was set to width-2.
So, if width was changed later maxlen would remain the same. And maxlen
is used as the length (width) of the content to print.
I've never changed the width at runtime, till today, from splitpane, and
this came out. So now unless you explicitly set maxlen, it must remain
nil and be set locally in each method as width-2.
I supposed the same has to be done in rtextarea.
* * * * * * * *
Subject: copy_pad_to_win
------------------------
Date: 2010-01-11 23:47
More and more scenarios are coming up when copy_pad_to_win can either
return a -1 and do nothing, or print less that it should be.
I can't correct more of these in the method, since that would break some
other situation. I have added warnings, though. One will have to check
the log file and see what warnings have been printed. If none, then we
have a new scenario, and the data has to be inspected to figure out.
* * * * * * * *
Subject: regarding create_buffer in repaint
-------------------------------------------
Date: 2010-01-12 12:54
If a widget calls `create_buffer` in repaint, it uses some default values
such as for top and left (0,0). To change these values, from a parent
component such as splitpane, means i change after `repaint()` so the first
paint is off by one row and col. The subsequent paint is okay.
I need to be able to pass values to a widget prior to `repaint()`, so its
`create_buffer` can be influenced.
* * * * * * * *
Subject: cursor positioning form#setrowcol
------------------------------------------
Date: 2010-01-12 22:53
Since i currently go up a heirarchy of forms, passing up the row and col
to be set, i cannot add the col and row offsets of the parent
(enclosing) widgets.
Had i gone up a heirarchy of widgets, I could have added their offsets.
In any case, i think I need to add them as parents, in methods like
`child()` or `first_component`. Then a method will be needed to pass values
up, and when no parent then set in its form. Each level adds its offset.
OTOH, another option would be when setting a child component, to once and for
all pass down cumulative offsets. Thus, one will not have to keep adding.
However, it is inefficient, is it not to propogate each cursor move up. Won't
that be slow ?
For that matter, won't this copying buffer be slow. Is there no faster way out?
In the case of multiple embedded components, can we not pass down the offsets
and boundaries when setting or moving so that each component writes directly,
and the cursor can be set easily without passing up ? There is a one time
passing down on creation, and moving or resizing. Each component knows its own
absolute position on the form, and there's basically only one form (except maybe
for tabbed panes).
Buffers means that scrollpanes for example only scroll a buffer, the widget does
not have to redraw repeatedly. Repainting is higher level code with many type
conversions, slicing, formatting etc, scrolling is merely a low-level copywin()
call. however, copywin() seems a lot more prone to error (new situations).
Direct painting without a buffer means constant repainting on scrolling, like
happens when we use TextViews and listboxes inbuilt scrolling.
Otoh, it means each component has to implement scrolling. With a scrollpane, we
can have scrollpane do the job, although the child has to write onto a pad.
* * * * * * * *
Subject: update to cursor positioning
-------------------------------------
Date: 2010-01-13 18:26
Just studied the code to see how each textview knows where to print
inside splitpanes. Each component's `@col` is set to where printing has to
start, that's all. I was mistakenly using `@orig_col` which is never
updated.
Now its fine, which means I don't need `widget#setformrowcol`, the earlier
`form#setrowcol` is fine. Don;t use orig_col in setting cursor,
applies to rtextarea.rb, too.
* * * * * * * *
Subject: speed of splitpane, copying buffers
--------------------------------------------
Date: 2010-01-14 15:44
One can type fast in a textarea as is and see updates immediately. But
when the textarea is inside a splitpane, due to the buffer copying
happening, fast typing updates take time to show up.
Sequence would be as follows:
1. textarea buffer copies onto splitpane buffer
2. Splitpane buffer copies to main form window (earlier it would copy to
screen directly)
3. form.window does a wrefresh.
Each time you type a character, it goes through the above. We need to
get the innermost widget buffer to write directly to the form.window
somehow.
Also a quick cursor movement, shows the cursor flashing on row below now
and then, although when you move the cursor slowly, it move fine.
* * * * * * * *
Subject: slitpanes in a mouseless CUI environment
-------------------------------------------------
Date: 2010-01-15 13:02
The issue here is navigating between panes, if you have splitpanes
embedded between splitpanes. Typically, control goes to the first
component, and switching happens between the 2 panes of the first
component.
I've defined TAB to do a switch on the outer component, but that only
delays or reduces the problem.
We need another component, more like vim's splits. You can split it as
many times. Each split returns 2 handles. You can split the handle. You
can place a component in the handle. Once it is all in one component,
one can reorder and exchange positions too.
Expanding contracting can de done with current split in focus. With
embedded splitpanes, we don't know which level the user is intending the
resize (or motion) key for.
* * * * * * * *
Subject: cursor positioning in mult splitpanes
----------------------------------------------
Date: 2010-01-15 23:26
When placing textviews inside 2 splitpanes, a funny thing happened, i found that
the cursor was always on 5,5, no matter where the outer split was placed. Appa,
we need to add the outer windows left and top offsets.
I have done that, and now the cursor is in the right place regardless of whether
there are 2 or 1 splitpanes.
Now both setformrowcol and setrowcol are correct. However, i think the form
route of setrowcol is better since a form's offset won't get duplicated.
* * * * * * * *
Subject: container widgets
--------------------------
Date: 2010-01-16 23:57
Widgets such as splitpane, scrollpane, viewport and any future widgets should be
able to pass changes to dimensions down to their children.
So they should have a `height` and `width` method that adds the delta to the
child, or relevant children. and calls `super`, so that buffers can be
rebuilt.
* * * * * * * *
Subject: scrolling and wrefresh
-------------------------------
Date: 2010-01-19 12:26
Suggested optimizations to pad and `wclear.`
Currently, i have to do a `wclear` everytime i scroll a pad or else
previously displayed data if often not cleared off and remains.
**Can this extra clearing be avoided**. i once tried `clr_to_bot` but
did not seem to work.
This happens when we scroll past last row (or last col in horizontal
scrolling).
Options to reduce or obviate `wclear:`
1. Get scroll exactly so that no empty rows or columns shown. Very
dicey.
2. `wclear` only after a point when reaching the end. Setting some flag.
e.g. when `number of rows < scrollatrow().`
3. Don't clear entire window, but only the region you don't paint over.
Try clear to bottom again.
4. Define pad larger (extra rows by size of widget) so that there's
alway that much blank rows there. Same for width.
If displaying 100 rows in a 10 row widget, define pad as 110, so when
scrolling last page, there's always blank space ahead. This should
totally obviate `wclear`.
* * * * * * * *
Subject: scrollpane updates
---------------------------
Date: 2010-01-19 19:40
A scrollpane only clears and repaints the entire area if its size is
changed or it is scrolled. In such cases, the `repaint_all` variable is set
to true.
In all other cases, it only copies the child's buffer up. This is
required otherwise changes to the child will not show up at all. Thus,
changes to `rviewport` and `rscrollpane` have been made.
The awful flashing has stopped, however all test programs that use
Scrollpane have to be retested -- YAY !
Isn't testing over and over again such fun.
* * * * * * * *
Subject: cursor display by widget itself
----------------------------------------
Date: 2010-01-20 22:21
Would be so cool if widgets could display cursor themselves as a mark or
attribute.
That has pros and cons:
- At a terminal level, one cannot change cursor color or attributes. It
would be programmed.
+ OTOH, we would not have to test and ensure that cursor is being set
when an object is embedded and does not have access to the top form
that is setting the cursor.
- But, when the cursor moves, we would have to erase the cursor and add
it elsewhere. that could resul in a cursor left behind in one widget
when we jump to another.
+ In scrolling the mark would just move along. No programming required.
- if a widget forgets to erase or set cursor on events like on_enter
on_leave, we could have multiple cursors.
Perhaps editable widgets such as textarea or ones that allow cursor
movement like listbox and textview could at least show an insertion
point or caret of some sort. So even if cursor always hangs around at
top left corner of active widget, the insertion point can be shown as an
underline or something. (UL's don't work in all TERMS).
Let's think about some kind of mark that is independent of the cursor.
One huge headache for scrollpanes, textareas etc would be taken care
off. Issue is, does TA or TV really know where the insertion point is.
Yes, @current_index and @curpos (i think).
* * * * * * * *
Subject: cursor positioning
---------------------------
Date: 2010-01-20 23:06
If a listbox can paint the row with selection, then surely it can paint
hte curpos position with a red background for cursor (this can be
defined at the widget level and overridden per widget if need be).
Similarly, textareas have a search highlighting. And i do have
current_index and curpos. That can be used for setting a cursor upon
repaint. Worth a try. Should help in the long run.
In any case, its high time a widget is informed of its exact coordinates
no matter how deep it is. Parents can inform children of row and col
changes. Then the child can itself call wmove and not have to set
attributes. Also for that the form that is painting, its value should be
sent (but btw, if the embedded component sets wmove, that will be erased
when the buffer copying happens).
* * * * * * * *
Subject: tabbedpanes vs other containers
----------------------------------------
Date: 2010-01-21 18:49
Other containers contain an object, so they call its on_enter or
set_form_row so that cursor is correctly set no matter how deep the
level of containment.
However, `TabbedPane` contains a form. The caller can set what he wants on
that form. Thus, i am finding that the usual technique that `SplitPanes`
used for setting the cursor is failing here.
This does mean that tabbedpanes can have complete forms inside them with
multiple buttons, checkboxes etc -- that is absolutely necessary.
* * * * * * * *
Subject: vim like splitpanes
----------------------------
Date: 2010-01-22 19:39
Don't know if I've put this down already. Splitpanes within splitpanes
is a bit slow if you intend doing very fast typing within a textarea, for
example.
Also since there is no mouse, which split do you intend widening or
resizing -- a bit of a pain. Setting up sizes of the splits can also be
dicey at present. For a mouseless environment, perhaps vim editor like
splits are better. There is only one level for starters.
To create splits, take the first pane, split it. You get 2 objects
(panes). Split them any way you want. You have handles to each split or
buffer. Place any object you want in each window. Whichever window the
cursor is on is the one that resizing commands apply to. There is only
one level so its easy. Again using TAB to cycle between splits will
work. Similarly, it should be possible to rearrange, kill, add etc at
will. Or to move to the left or right or top tab.
The splits could have scrolling built in, so we don't lose 2 rows and
cols showing the scrollbars. Scrollbars could be fitted into the split
itself.
* * * * * * * *
Subject: form parameter in widget creation
------------------------------------------
Date: 2010-01-22 19:50
I am wondering whether the **form parameter** in `Widget` is clunky. Since
it's often set to nil, in embedded objects, or if you wish to create a
widget first and hand it off to some other form or list or tabbedpane.
The way of creating objects in a DSL'ish way is a bit goofy since I had
problems putting my head around not being able to overload constructors
in ruby.
This (removing form) would be a major change since it would break
everything but for future users it could be neater. A form may be added
to, rather than widgets take the form param and add themselves.
This internally breaks code too, since many objects just expect a form
to be present when created of when some methods are called.
This means that the constructor params can have what's actually needed to
work. Currently even I don't know what's absolutely needed for an object
to work. What are the minimal requirements ? "Just run it and if it
crashes with a null pointer assignment, then you know something has to
be set." That sucks, and embarasses me since I've done *a lot* better in
the past (in other languages).
However, i think that's the way to go.
* * * * * * * *
Subject: cursor handling internally
-----------------------------------
Date: 2010-01-23 20:23
I've got textarea to handle cursor painting by itself, BUT ...
that means each time the widget will have to be copied (for all cursor
motion) even when the screen does not scroll. Currently, when we use
window's `wmove`, we do not need to repaint or copy_pad at all.
Any write to the graphic object (when in buffered mode) requires the
buffer to be copied, and that means setting buffer_modified to true.
Also note that all cursor motion requires the footer to be painted.
Currently, some movements are forgetting to do that, and some are - but
they are repainting the whole textarea just to paint the footer (row and
col in footer).
We should set another flag for updating the footer only. (see `addcol`
and `addrowcol`).
I am thinking of making this method paint_internal_cursor conditional.
* * * * * * * *
Subject: aah the tabbedpane cursor offset issue
-----------------------------------------------
Date: 2010-01-26 20:10
How daft of me! The tabbedpane's own row and col were resulting in the
textarea not being able to calculate the correct cursor offset.
So we do have to look at parent objects and their own row and col, do
we? But what of scrollpanes and splitpanes ?
So basically while setting cursor, i need to add parent's row and col,
too.
* * * * * * * *
Subject: microemacs user setup tabbedpane
-----------------------------------------
Date: 2010-01-30 00:06
Micremacs has user setup tabbedpanes. (Use F1)
Left and right keys are used to move from one tab to another.
Tab jumps to form associated with a tab. Tab does not cycle between
tabs. IN some fields, where there are selectable values (combos) a "v"
is shown but i am not clear how to access that list. Pressing Enter
opens up the config file. (Use spacebar)
* * * * * * * *
Subject: tabbedpanes and scrollpanes
------------------------------------
Date: 2010-02-02 23:04
I've spent more than 2 days battling a scrollpane inside a tabbedpane.
It wont print anything. I know what's going on, but unable to fix it.
Its simple but i am unable to catch it.
When i place a textarea directly in a tabbedpane (TP), it takes TP's
tab form. It does not create its own buffer. It writes to TP's form/pad
which is then copied to TP's own window. This works.
But when i place a textview inside a scrollpane and place that inside a
TP, it takes the TPs form, but then creates a form and pad, required for
the child. The TV writes to its own pad, which is then copied to
Viewport, to Scrollpane, to TP. But at this point, the tab form which
was given to Scrollpane and not used, kicks in and writes to TP.
So whatever was written to TP is overwritten by the unused TP tab
form/pad. Scrollpane should use this, but it creates its own buffer. If
i mess with this, all those other programs could go for a toss.
* * * * * * * *
Subject: scrollpane tabbedpane update
-------------------------------------
Date: 2010-02-03 19:06
I've finally got something displaying and working .. textview inside a
scrollpane inside a tabbedpane.
If the form given to a scrollpane has a pad as a window, then we use the
pad, if its a window, we do the usual create_buffer crap.
However, sadly the positioning is slightly off, the borders and not
printing fully (left and top not there). I've played around with the
`row` and `col`, but seems scrollpanes row and col have no impact. Its a
tricky situation since I have created a second form on the same pad.
I cannot set the same form as that passed in since then the mainform
would own the child inside scrollpane. So its very hackish really - not
clean. Getting messy -- we need to overhaul this whole new buffered
stuff - too much copying of buffers and breaking my nut over `copywin`.
Need to simplify.
* * * * * * * *
Subject: return values for form: false vs UNHANDLED
---------------------------------------------------
Date: 2010-02-04 19:12
Sometimes some methods like `down`, `up` etc return a `false` if they cannot go
down or up or scroll. However, when the `ret` is returned up, repainting
still happens. A form typically won't repaint if the return of
`handle_key` is `:UNHANDLED`. So, in scrollpane, I've had to convert
`ret` to `:UNHANDLED` if false, so no useless repainting happens.
* * * * * * * *
Subject: scrollpane inside tabbepanes PROBLEMS
----------------------------------------------
Date: 2010-02-04 20:52
Okay, I've got an idea what's happening.
This largely is since I've put in an ugly hack to take the PAD of a
parent form, if its a PAD (not a window). Otherwise, what I was
printing on Scrollpane's pad was getting overwritten by the TAB's pad
which was never written to.
1) `ScrollPane` does a `wclear` of the pad. This erases everything earlier
put on the pad, including the border.
2) Since Scrollpane does not know its picked up some other pad, its
border height and width are not correct. They would be fine if it had
created its own pad.
The options are:
1. Hack further so that this case is taken care of.
2. Do the sensible thing. Create own pad, and somehow copy scrollpane's
pad onto it at the end.
Even though i could not get #2 done, I think I should look into that now,
so the code is not mysterious and impossible to understand or maintain.
Also, I've got to simplify ScrollPane *completely*.
* * * * * * * *
Subject: maintaining logs and keystrokes
----------------------------------------
Date: 2010-02-07 11:48
Maybe one way of my tracking down when something breaks, which is
happening and is nerve-wrackig since its all UI stuff...
Maintain the log file. Also somehow mark what keystrokes we run.
That way when things break, i can run the same program with same keys
and compare. Keystrokes actually are already mentioned in file, but it
would be easier to put them separately.
Maybe i could just mail the log files to myself with a comment.
* * * * * * * *
Subject: reworking cursor positioning
-------------------------------------
Date: 2010-02-07 20:44
Two approaches:
1. Pass absolute coordinates down all the way, so widget can set abs
coords for cursor.
This still needs to go all the way up. Also any changes need to be
cascaded all the way down.
I am trying this.
2. A window or pad should print its own cursor. Why pass it to higher
forms. That way only absolute position within a pad or window is
required which is quite simple.
Also changes can be passed down quite easily.
However, when a pad prints cursor, control will come back to setpos
of main form, and it will move the cursor.
So it an inner pad or window is setting cursor, the main should not.
Somehow, mainform should know whether it should set cursor or not.
Actually this sounds simpler than option 1.
The danger of allowing widgets to set the cursor is that if multiple
are being updated in a loop, they will all set the cursor, and only
the last will show up.
Maybe the selected field can have an attrib, manages_cursor - if yes,
main form does nothig, assuming either a cursor is not needed, or
that widget has a form and is handling cursors. Containers will have
a true value.
* * * * * * * *
Subject: Major change: buffered version, splitpane, scrollpane NOW
------------------------------------------------------------------
Date: 2010-02-10 11:09
Too much breakage, too much debugging -- I need to redo the buffered
approach largely meaning that:
1. `SplitPane` and `ScrollPane` will have an almost complete rewrite.
2. Window and Widget will be touched, in terms of repainting - only the
buffered portion, so the classic version of rbcurse should not be
affected.
3. Yesterday, looking at the show_caret routine (carelessly tacked on
recently) in `Listscrollable`, I saw some glaring flaws, fixed it and
now Textviews and Textareas show their own caret (cursor) correctly,
no matter where they are placed. However, what one needs to do when
using this, is display it only on_enter, and hide it when on_exit.
Also, do remember that using this forces a `repaint` even when you move
the cursor inside the textarea. The original cursor routine does not
involve repainting unless scrolling happens due to movement.
However, it does solve a HUGE headache regarding cursor display in
complex setups like scrollpanes within a splitpane within another
splitpane.
To detail point 1.
### Current approach to using buffers (ncurses' Pad):
1. Too many pads which results in slow response, too much copying which
is very prone to bugs, too much impact of change.
Its too complex.
2. Copying pads from inner to outer widgets is too messy, very hard to
debug errors, slow.
3. Need to avoid or minimize pad usage.
### Alternatives:
1. **No pad**
- This means that we `repaint` each time scrolling happens
- Widget takes care of cropping and can make errors. Responsibility
is on each widget to crop. Cropping has to be from both sides, not
just right.
Typically, this cropping will happen for each line of a multi-line
widget. In the `copywin()` case, the widget writes without checking
len or cropping. The lower level `copywin()` takes care of cropping
so that's more efficient.
This does obviate the recreating of pads that happens due to
resizing or even setting the parent object's dimensions.
2. Use only **one pad** for the widget that's actually writing such as
`Textarea` or `Listbox`.
This widget is passed the coordinates to crop and the target window
(typically `form.window`).
It uses `prefresh()` to write onto form.window using coordinates.
Most likely this code can be put in superclass `Widget` so there are no
errors.
The container such as `Splitpane` and `Scrollpane` merely pass down
their bounds, so it doesn't matter how many levels there are. Only
bounds are being passed down and calculated.
Now its possibly that the container *suggests* to inner object to use a
pad. The inner object can if its programmed to, use a pad and use the
cropping, or it can just paint to the target. In the case of optional
pads, the widget will have code to crop each line, so that code will
exist even with a pad.
After that, the `Scrollpane` will put its border or scrollbars directly
onto `form.window` using the bounds it has. Similarly the higher level
`Splitpane` will paint its own border or divider etc onto the
`form.window` and so on.
### Tasks:
1. push all existing code to rbcurse19 branch
2. create a new branch for this change
3. Have `SplitPane` and `ScrollPane` push their dimensions down and paint onto
`@form.window` directly.
4. Have final widget (`TextArea`, `TextView`, `Listbox`) respect the
dimensions passed in, and refresh `Pad` onto actual target
(`@form.window`).
* * * * * * * *
Subject: method rowcol and offset fields
----------------------------------------
Date: 2010-02-11 21:56
method rowcol() is supposed to return the location where form would
place the cursor by default. So it takes row + row_offset.
row_offset usually is 1 by default, if you have a border.
However, there's some issue with placing an item inside a Scrollpane and
perhaps others. The buffer is copied with an offset of 1. So rowcol by
itself does not yield the correct cursor position.
If i add 1 to this, many other routines start printing one off. rowcol
has been used rather extensively because somewhere down the line, i
forgot its purpose (not having thought it necessary to document it).
So i've added a pad_offset in textview, for the pad cases. I know i am
redoing it and already started hacking.
* * * * * * * *
Subject: changes to buffered objects
------------------------------------
Date: 2010-02-11 23:21
Based on what I've done to TextView, to be done to TextArea, ListBox.
1. No references to @form.
win_left and win_top store window's offsets.
2. target_window passed if form not passed.
3. move create_buffer to paint.
Also, paint buffer here only, no passing up.
4. accept buffering_params hash and use for copywin
5. For textarea, suppress borders.
-----
Containers should set should_buffer and pass bounds.
Containers themselves do not create buffers. Just pass down.
Containers only draw their borders etc.
Move this drawing to after the inner object has painted. Paint onto
window. Pass down ext_offset + col_offset.o
Since container are writing to window, add row and col to print-border
and other print statements.
* * * * * * * *
Subject: ext_offsets explanation
--------------------------------
Date: 2010-02-13 10:33
`ext_row_offset` and `ext_col_offset` are essentially for a widget to be
able to place the cursor. This is exactly how to set this variable.
A form, when adding a widget puts its `window.top` and `window.left` as row
and col offset respectively.
In cases, where an object contains another object such as `ScrollPane` or
`SplitPane`, ext_row_offset is set to row + ext_row_offset of parent
class.
child.ext_row_offset = @row + @ext_row_offset.
Thus, this contains the starting point of the widget in absolute terms.
This should not be used by any other programs as this is only to cater
to `set_form_row` and `set_form_col` and could change to accomodate these 2
methods.
However, the above assignment is at present the correct assignment.
* * * * * * * *
Subject: vimsplits or splitpane with subwins
--------------------------------------------
Date: 2010-02-13 20:14
I was just checking out `subwins` today and one thing led to another. I
basically have a very barebones vim-splitty thing which has subwins for
each split - `VimSplit`.
It splits in half, yes, i need to allow moving. I've been wasting time
putting text in each split.
So each split returns 2 subwins. You can either attach a component to a
split, so all keys go to it.
Or else create a form with that window.
Or create a widget with the window, and send keys to it. Attaching a
widget to the window is best since it takes care of everything after
that.
We still have to deal with setting the cursor, not sure if set_form_col
is meant to deal witha subwin. Also its easy to use subwins.wmove but in
our real application, the subwins wmove will get erased by the later
windows that refresh.
* * * * * * * *
Subject: subwin does not resize and move
----------------------------------------
Date: 2010-02-13 23:05
subwins were working great for my splitpane (vimsplit) till i needed to
implement the pane movement. That requires moving and resizing subwins.
This was not happening since the coords are relative to the parent
window, and somehow this link is lost. The moved window lands up with
its relative coordinates as absolute coords now.
The man page says that subwindows resizing and movement should be
avoided. Another page says:
> The subwindow functions (subwin, derwin, mvderwin, wsyncup, wsyncdown,
> wcursyncup, syncok) are flaky, incompletely implemented, and not well
> tested.
I could delete and recreate 2 new windows when a split pane's split is
moved, but the reference to the window would change, and programs using
that ref would keep referring a destroyed window.
It was too good to be true. I guess I have to go back to `pads` and `copywin` which
I've learned to hate.
* * * * * * * *
Subject: subwins > derwin
-------------------------
Date: 2010-02-14 12:06
Okay, i've got ncurses subwins to resize and move, since they have absolute
coordinates (unlike derwins) which lose their orientation. However, my
scrollbar repainting is sucking since i need to paint it on the
underlying window/subwin.
Somehow it prints a line 2 times - duh. Will have to see how far i can
go with approach.
* * * * * * * *
Subject: splitpane nonbuffer change
-----------------------------------
Date: 2010-02-14 18:34
Due to removing buffers, now some methods that had relative coords such
as hline and vline need absolute coordinate, by adding row and col
respectively.
* * * * * * * *
Subject: giving up on splitpanes without buffers
------------------------------------------------
Date: 2010-02-15 00:17
Okay, i am not having fun with subwindows. Too much existing code it has
to work with.
Not having buffers at all is tough, since one can easily print outside
the widget while moving it. Especially the boundaries.
So i might have to just go back to the dreaded buffered version. Only
problem is going back to that version that worked perfectly except for
the one condition in which a scrollpane was inside a splitpane, and only
the cursor was a tad off.
Have to find that version!
* * * * * * * *
Subject: changed to SplitPane (rfed16 version)
----------------------------------------------
Date: 2010-02-16 09:27
Currently, Splitpane was in a sorry state meaning mostly the values
passed by higher functions for locating both the comps and their cursor
values. Parameters passed were based on how things were working inside
and it made no sense.
I've tried to make the parameters logical and sensible, and the inside
functioning should work with those parameters rather than the other way
round.
Similarly, width and height should also make sense in all cases.
Somewhere values of row and col were relative, some places absolute.
Now in setrowcol of widget, i do not add ext_offsets. programs can add
it.
RULE: All widgets should maintain absolute coordinates for row and col, even
for internal objects. It is upto the Pad to remove @top and @left.
* * * * * * * *
Subject: changing width and height
----------------------------------
Date: 2010-02-16 20:49
Wherever an object changes its childs dimensions, it should now also
call `set_buffering` to update `:bottom` and `:right` (or :top and :left),
since we are now using `buffer_to_window` in `Widget` which takes explicit
values from this hash.
Earlier, `Pad` picked up values from the pad, and otherwin and then tried
to make sense of what to use. Thus coincidentally some things worked,
some did not.
Now that our wrapper for `copywin` does no magic, callers are forced to
pass correct values, which means there is complete clarity into waht is
happening at the callers end, the rules for printing a widget in complex
circumstances is becoming clear and less random or coincidental.
* * * * * * * *
Subject: cursor positioning
---------------------------
Date: 2010-02-17 00:25
I can't believe this. It seems I am not longer using ext_offsets any
longer??
I am setting the absolute coords of child components in scrollpane and
splitpanes, which is kinda good, because its simple and no magic
involved. No having 2 sets of coordinates around.
Also, it seems widgtes are using buffer_to_window, which also uses
absolute coordinates for the screen.
Lastly, textview and textarea in set_form_row, don't use ext_offsets.
They were earlier added in widget, later commented out to be added in
indvidial programs. But everythings working without it, so i am free of
one more hassle to look after.
* * * * * * * *
Subject: scrollpanes inside splitpanes
--------------------------------------
Date: 2010-02-17 10:14
The issue with placing a scrollpane a splitpane, esp in the second pane
of a split.
Currently, a SPLP sets its second components (C2's) row and col and
other buffer parameters only after its divider has been set.
Thus, when there is SPLP inside another SPLP, even the inner SPLP is
able to inform its child of location when its divider is recomputed.
However, scrollpane informs its child of its location at the point of
assignment. When the SCRP is the 2nd component in a SPLP, it doesn't yet
have any row and col etc. When that is later updated, it currently has
no means to update its child.
When SCRP's row and col are updated, or its set_buffering is called, it
must further update the same for its child. Earlier that was not
required since each pad was printing to a relative location.
* * * * * * * *
Subject: Now quite some success with splits and scrolls combined
----------------------------------------------------------------
Date: 2010-02-17 14:38
with testsplit3a.rb working (**rfed16** branch), resizing etc is working fine,
finally splitpanes and scrollpanes are in decent shape.
There are still some programs not displaying okay .. 3b 3_1 -- have to
see what's there.
Were those 2 ever working ? or was it only a cursor issue in them that
wrecked everything and made me abandon rbcurse19 branch. I wonder how
that branch is doing.
I think i need to start git tagging. Anyway, i am also taking snapshots.
I need to start releasing gems or atleast tgz's on github.
* * * * * * * *
Subject: broken status
----------------------
Date: 2010-02-17 22:23
Please note that consequent to the simplified buffering, and the way of
calling it from containers the following are broken:
1. listbox (e.g. testscrolllb.rb, testsplit3b.rb)
2. table
3. tabbedpane (container) (e.g. testtpane.rb)
Any program calling buffer_to_screen for a child is broken. The child
now does a buffer_to_window using absolute coordinates.
Containers such as SplitPane and ScrollPane are now passing absolute row
and col to child, and updating exact top, left, bottom and right.
I don't think children should be using ext_col_offset or ext_row_offset.
* * * * * * * *
Subject: splitpane = cascade changes is on (rfed16 branch)
----------------------------------------------------------
Date: 2010-02-18 09:43
In RFED16, i've cut down on `Pad` usage, splitpanes and scrollpanes do not
use pads themselves. Only the final object inserted in it such as a text
are uses a Pad.
Thus there can be cropping issues when a splitpane or scrollpane writes
outside the box. Thus, i switched on `cascade_changes` (which i had
switched off). That's why there's no printing out of the boundary. That means
that any change in the splitpane dimensions or resizing the split,
causes the internal object to resize. Earlier they would not reduce,
since cropping was happening.
Since there is no pad now, it is necessary that splitpane and scrollpane
are never bigger than the splitpane they are on. I had earlier noted
that `cascade_changes` defeats the purpose of a splitpane, however do not
that the internal object is Pad based and can still exceed the
`Splitpane` boundary.
Or rather. If you place a textarea in a splitpane, splitpane will resize
the textarea (since `cascade_changes` in on). However, if you place a
`Textarea` in a scrollpane, and the scrollpane inside a splitpane, then
the `Textarea` is not resized. Only the object directly inside a splitpane
is.
* * * * * * * *
Subject: More on splitpanes
---------------------------
Date: 2010-02-18 20:08
Great news. I've got sample testsplit3_1.rb working which is an example
with 2 splitpanes inside an outer splitpane.
This exposed an issue, that since the second component's (right or
bottom) coordinates are determined not when attached but only when the
divider is set, therefore its too late for it to coomunicate that to
some inner components.
Basically, if your second component is something other than another
Splitpane, its okay. However, in this example, the second is a SplitPane
for the first time, and it seems to get its parameters a bit too late.
So before it repaints the children i update the locations. This is
required even for the first since the first could be the first of the
second - lol. Otherwise, both components on the right were printing at
0th column.
So there could be some more such missing cases, when i put the outer
splitpane as horizontal. But hopefully earlier programs will not break
since i am not touching existing paths.
I've still gotta fix TabbedPanes which are broken, I fixed Listboxes
last night, but only lightly tested - surely there must be breaks
somewhere.
Also, gotta fix Tables. Things looking upbeat with the new "simpler
approach" (see branch RFED16 of rbcurse).
* * * * * * * *
Subject: Fixed breakage in Table. Check testscrolltable.rb
----------------------------------------------------------
Date: 2010-02-19 12:32
Done the tiny changes to `Table`. Working now.
Also, `Scrollpane` increases size of child if child is smaller.
Now to fix `TabbedPanes`, more work involved here since each situation has
to be taken care of in terms of sizing of child. However, hopefully will
be simpler than `Splitpane`.
* * * * * * * *
Subject: scrollpane relevance in terminal apps
----------------------------------------------
Date: 2010-02-22 20:38
Just wondering if scrollpanes have any meaning in a mouseless
environment. The scrollbars have 3 functions:
1. used to drag down. But for that they have to get focus.
I don't make scrollbars focussable since that puts focus on too many
objects. I've seen demos of some curses toolkits that did, besides
being very low quality and buggy, focus was going to too many objects,
it was irritating.
2. show how much more of a document there is.
3. presence of scrollbars indicates to user that he can scroll
vertically or horizontally.
In a mouseless environment, no focus to scrollbar. Keys are used to
scroll. However, we still need to indicate to user that he can scroll.
Also user may want to know percentage of screen.
On a terminal, scrollpanes are taking valuable rows and cols due to
boundary and bars.
Since scrollbars result in added complexity especially wrt placement and
cursor location, can we do away with scrollpanes as a widget and have
them added onto other widgets.
They would just place themselves where the object allows, on the objects
own border. That eliminates a lot of testing.
scrolling can be an option to widgets. they then include this
capability. Needs to be thought out, since Scrollpanes result in insdie
object creating a buffer.
* * * * * * * *
Subject: double key mapping like vim
------------------------------------
Date: 2010-02-24 15:17
The earlier Mapper than i had written was quite good, but integrating that to
get multiple keys into rbcurse would have meant a lot of rework, and perhaps not have
fitted in, with control going to multiple objects and heirarchies of
objects, whereas Mapper takes over control.
So i've got a simple thing going, you can test out "gg" in any textview
and it takes you to the start of the document.
Usually, we check for bindings after going through a case statement.
This means if i've got a binding to "gg" on a listbox but listbox moves
focus to first element with "g", my binding is never invoked.
One could do as follows:
Make a call to process_key first, outside the case structure. If
:UNHANDLED is returned, we go into case.
If the user presses, g once, but not a second time, return :UNHANDLED.
if getch returns a -1, return UNHANDLED, not nil.
That way a double key binding can work, even with a single key binding.
e.g. currently I have "jj" bound to ESC in Vim, but if i type any
character other than j after a j or wait, then a j is typed.
So its a thought. In anycase, if the user wishes to override a binding,
we should evaluate bindings first.
* * * * * * * *
Subject: regarding multiplier in embedded components
----------------------------------------------------
Date: 2010-02-26 13:40
When i have a textarea inside a scrollpane, and i do C-u, who gets the
numeric argument of 4 or 16, the scrollpane or textarea. Currently,
since the scrollpane passes the key to textarea, so textarea increments
multiplier.
Then i press scroll (M-n), but the scrollpanes multiplier is still
unset.
This means that we cannot have a multiplier at an object level -- it
must be a global app level thing. Each object uses the global arguments
and resets after usage.
But where do i trap the C-u key ??
* * * * * * * *
Subject: Undo in text widgets
-----------------------------
Date: 2010-03-06 10:09
1. trap insert and delete events
2. keep a list of
* row
* curpos
* string/char added or deleted
* action: ADD or DEL
@current_position in list
3. Undo() - moves up the list and does the opposite
4. Redo() - moves down the list and does the same action
* * * * * * * *
Subject: entry of string
------------------------
Date: 2010-03-06 20:57
I've brought back entry of a string inside an application.
Until now if one wanted to adhoc ask the user for a string (such as a
search string), one used the dialogs. However, if one wishes to keep the
"gui" to a minimum, `rbgetstr` (from module Io, io.rb) does the job.
It allows user to abort using `C-c`, or get specific help using `C-g`. Or
use the arrow keys or backtab. However, i need to work in
tab-completion, as well as perhaps history.
The main issue is coordinates to prompt. The widget often will not know
where on the screen it should prompt. Dialog boxes solve this by opening
their own window and then erasing it. Here to keep things simple, i just
write on the form.window. The app should define the coordinates perhaps.
In the test, textview writes on its own lower border.
Perhaps, I'll bring back askyesno etc == for which currently the dialog
box options exist.
* * * * * * * *
Subject: "most"-like menus
--------------------------
Date: 2010-03-06 21:03
For menu's we already have 2 ways:
1. a menu bar just like the **Links** browser with sub options, hotkeys, actions etc.
To see this press F2 in test2.rb.
2. Popup-menus - Similar to the above, popup over a component to show
its options. to see this, iirc the todo app example, if it still
works.
3. "Pine"-like option labels at the bottom of the screen. Absolutely
identical -- check the rfe.rb example. This is usually for options
that stay around forever. One can always superimpose another set when
one wants, as moving into a component. This menu shows what's
available, so usually in a data entry app, only control and alt-keys
would be shown.
This is only a display, and does not take over control or focus. It's
like having a cheat-sheet of key-bindings at the bottom of the
screen.
4. I recently have been using most as a pager. It has a simple menu
system available on pressing ":". I've copied it shamefully, so one
can quickly set up multi-level menus with actions (procs or symbols)
attached. The API may need work on. Since the location of this menu
needs to be provided by application and not a widget. Currently,
textview provides a location at 23,0.
Unlike the pine-like labels, this prompts and takes control, so any
letter can be defined per level.
To see this, try any example with a textview and press "m" for menu.
Try testsplit3.rb. I may change the mapping "m" shortly ?
So depending on the kind of application we have, we can choose the kind
of menu system we want.
* * * * * * * *
Subject: undo facility - more on it
-----------------------------------
Date: 2010-03-08 18:09
currently the undo is independent of the textarea and uses the event
object. however, it hardcodes access to the data structures of textarea.
Textarea should make an undo object and pass that. this object would
have an undo and redo method which it has implemented. Also the object
will maintain state of whether it can undo or redo. the undo object may
have an array not just one value.
this way undo's can be clubbed. perhaps a block delete using a number
can create an array of actions rather than separate actions. Hopefully,
typing several chars can also be clubbed into one object to reduce
memory.
* * * * * * * *
Subject: making rbcurse friendlier
----------------------------------
Date: 2010-08-26 19:45
I am wondering whether creating rbcurse widgets or apps requires too
much boiler plate code.
Can I make it simpler. The problem i faced (coming from Java) was
inability to have multiple constructors. So the user, and even I, don't
know for sure what all a widget requires to run.
Can widget creation be made simpler.
I have an idea also for generating widgets and an app through a command
line interface. Later i can also write a ncurses app in rbcurse that can
generate apps. User can select and place widgets, he can see them as he
creates them. He can move them around etc. Finally, he can generate the
code for the widgets on screen.
* * * * * * * *
Subject: other screen patterns
------------------------------
Date: 2010-08-27 21:39
List entry view: Show a simple entry form directly above the total list of items
http://welie.com/patterns/showPattern.php?patternID=list-entry-view
View: much like Hotmail.
http://welie.com/patterns/showPattern.php?patternID=list-entry-view
Product Comparison: Sort of pivot table like, perhaps color columns
http://welie.com/patterns/showPattern.php?patternID=comparison
Directory Navigation
http://welie.com/patterns/showPattern.php?patternID=directory
http://welie.com/patterns/showPattern.php?patternID=doormat
http://welie.com/patterns/showPattern.php?patternID=paging
* * * * * * * *
Subject: some fresh ideas for widgets
-------------------------------------
Date: 2010-08-27 21:45
I was glancing at this
[article](http://designingwebinterfaces.com/designing-web-interfaces-12-screen-patterns)
from reddit about Screen Patterns, and the 3 list widget was mentioned
as Column Browse. Also Master Detail.
## Column Browse
So I think why not create widgets out of this so that users don't have
to mess around with multiple SplitPanes to do this. (Note that the
problem in multiple embedded SplitPanes is that the user does not know
how to traverse to a specific one. In an environment with a mouse, user
can click on some area. Here, if there's no mouse this becomes a
problem.
If I create a widget with 2/3 lists, it will be easier to
programmatically refer to them, and to traverse them.
## Spreadsheet widget
Someone also wrote to me about needing to write a Spreadsheet using
ncurses. And the Table widget is close to that. It can be configured (or
extended) to give quite a bit of functionality of a SS. However,
everytime someone wishes to reuse a SS, he would have to copy the code
-- if he has it.
So why not create a separate Spreadsheet class with just code for SS.
* * * * * * * *
Subject: another take on Vimsplit widget
----------------------------------------
Date: 2010-08-27 23:23
Remember the vimsplit widget. Lets do another take in which we keep one
level of components only. Perhaps i can tile them in one orientation,
and allow user to expand/contract -- should be easy since only one
level. We can find some way to have multiple orientations.
This will be easy to code for user, and also to modify
programmatically at run time.
One can even take the MultiContainer and put a tiling feature in it.
**Convert to tiles**.
Which makes me wonder, if i can use Multicontainer to rewrite
TabbedPane ? Tabbedpane had become very complex. But oh wait, TabbedPane
can have forms in it, which MC cannot have. That's where the complexity
came in.
So in the new vimsplit, splitting while sitting on a split, will not
create a child split, but only an outer split, but half the size of the
current split, or share out the sizes. Traversal will be easy.
If we allow splits to be defined with abso coords then we can have
complex splits. Or perhaps a way of giving preferred size, so it can
expand fully in one direction.
* * * * * * * *
Subject: ffi-ncurses ?
----------------------
Date: 2010-08-30 12:37
there is some talk of ncurses installation which is hindering people
from using rbcurse.
Perhaps we should try moving to ffi-ncurses after all. I heard it was
slow. Is there some way of making it optional, whether a user wishes to
use ffi or ruby-ncurses. For example, i read that mutt can be compiled
for ncurses or slang.
* * * * * * * *
Subject: on_enter
-----------------
Date: 2010-09-02 12:12
i think Form calls `on_enter` of a widget and also fires its `:ENTER`.
However, looking at the on_enter of some widget;s looks like they also
fire :ENTER. So things could get fired 2 times.
* * * * * * * *
Subject: making rbcurse easier
------------------------------
Date: 2010-09-05 10:57
Currently making an application in rbcurse, requires a lot of boiler
plate code. Various methods to be called to setup ... heck even I can't
remember them!
I am trying out a wrapper for rbcurse. Much like a file.open block which
does the dirty work of opening and closing a file while the user only
supplies a block.
Then i need to make wrappers for fields and other widgets so they can be
made easily. This way basic screens can be developed rather easily.
The wrapper is called app.rb and it currently resides in examples since
it is very much in progress and trial. it will keep changing, so its
going to remain in examples till it grows up. If you use it, rename it
first, let me know of any improvements or fixes or changes or ideas.
* * * * * * * *
Subject: shoes changed
----------------------
Date: 2010-09-05 15:08
In rbcurse, we use the block to initialize... shoes uses the block as a
changed action. Is that not better, since there is already a config for
doing the setting. Why 2 ways of setting ?
Is it too late to change, or shall we go this way in the App wrapper.
Internally we can bind to CHANGED. or should i have a changed method
which does this.
* * * * * * * *
Subject: uniformity and less surprises
--------------------------------------
Date: 2010-09-07 20:17
we need more uniformity and less surprise. Let 'text' be the one method
with 'def text' and 'def text =', in buttons rename text to label, so
text can be the answer. Same for all widgets. getvalue and get_value etc
sucks.
If a Variable passed in take its value.
thanks to the DSL approach there's this whole get_ set_ nonsense.
We need to move out the DSLish crap everywhere, even if that means a new
major revision.
* * * * * * * *
Subject: testing of widgets
---------------------------
Date: 2010-09-19 10:59
If we keep the model separate, we can test the model out. Helps if the
model is complex like a tree, but what if the model is an inbuilt one
such as a list ?
If the widget keeps UI separate, which includes ncurses, then we can run
tests on it from command line. However, widgets are instantiated with
form and window.!!! How to do change this ?
Can i create objects without passing a form ? and then call methods on
it, like setting data, set_value, add etc. See that events are fired,
exceptions are raised ?
actually even form is okay, but window printing is the issue. we need to
prevent that, windowless form that handles keys sent by a program. but
no ncurses loaded or displayed.
* * * * * * * *
Subject: temporarily leaving ncurses
------------------------------------
Date: 2010-09-20 13:23
If i want to run some command, temporarily leave ncurses using
def_prog_mode do stuff and then return. SEE:
http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/misc.html#TEMPLEAVE
I think vim does this when you type :ls . One can use this to display
bindings, events etc.
* * * * * * * *
Subject: repainting of containers
---------------------------------
Date: 2010-09-22 18:15
Seem to be screwing this up. Either I am painting all in repaint which
is not good. Yet, i do not know which are updated. Perhaps one component
has been externally updated, and the container does not know. So its
repaint required is still false.
So ... if `repaint_required` is true, it should repaint the borders, the
components, resize etc.
If `repaint_required` is *false*, it still must call `repaint()` on all
components, which will repaint if they have been modified. I've done
this in rvimsplit.
* * * * * * * *
Subject: Listbox and CellRenderer
---------------------------------
Date: 2010-09-23 22:25
Often what is displayed in a listbox is quite different from the data in
the list provided. Such as filenames in the list, but a long list is
dislpayed.
There are several ways to handle this.
I am not addressing obvious performance vs memory issues here. Only
implementation issues and their diffculties wrt display and app
programming.
1. Keep file names in list. But use the cell renderer to show complete
info. The repaint method truncates and treats the values from list,
so scrolling can't happen. The main program has a false idea of line
length. So cell renderers should only be used for format or color the
data, changes in length etc should not happen. Else we will have to
rewrite repaint and do length and scolling in renderer.
2. Keep the formatted data in the list. This makes it difficult to do
work on firing the list. We don't have the filenames. We would have
to maintain a backing store. There are additional issues such as if
we are updating a list, the value shown will be the entire formatted
line, and that will be updated into the formatted list.
3. So now we use `convert_value_to_text` to format the data, so scrolling
can happen. Cellrenderer just does coloring based on select focus etc
which was the original purpose. But since the formatted data is not
in the list, movement methods like end of line, forward word don't
work correctly since they consider the original data not the
formatted data.
Currently, Listbox does not have a separation of methods that act on
displayed data and actual (model) data. It assumes one list.
Listbox already is complicated enough with all the editing.
I've gone back and forth with moving the formatting in and out of hte
list, (in appdirtree and directorylist.rb) and i am doing no more. My
suggestion is. ... perhaps you should put formatted data into the list
itself. Have a backing store of the real data (that's what crow and
row_index are for). However, in some case, you will have to face the
difference between the 2 when updating only the model value.
Some of hte performance considerations. If you have very long lists but
only little of the data is seen by user the creating formatted date for
all rows can be wasteful. Cellrenderer and convert_value_to_text only
work on the rows beign displayed. However, they will keep working on the
rows if you keep viewing them over and over. No cacheing etc.
If you put formatted data in the list, there would be no repeated
formatting. In the directory lister demo, there is no cacheing of file
stat objects. Since the speed is fine, i did not bother to do any
cacheing.
One option is to maintain a cache of only those objects on screen.
Populate the cache in the convert_value_to_text loop. Or in
cell_renderer. Clear it every time you get a row_index of 0 and start
over.
This way all operations that require movement over formatted data can
use that cache.
* * * * * * * *
Subject: grabbars and scrollbar focusing
----------------------------------------
Date: 2010-10-07 11:49
* * * * * * * *
Subject: grabbar and scrollbar focusing
---------------------------------------
Date: 2010-10-07 11:49
Some objects like grabbars should not be in the way. they should be
`focusable` on some key, or condition. I am thinking of Alt-Tab.
Should there be some extra attrib for such since focusable will be
false.
I could register such objects with a `FocusManager` array. Upon pressing some
key (say F2), it cycles through these and makes then focusable. Works as
a toggle.
Or on pressing F2, it goes to next object in its array. So it will cycle
between these objects directly setting focus to them. So they will never
come in the TAB order.
This means i don't have to make a parallel `select_next_field` for such
objects since they will have focusable true.
* * * * * * * *
Subject: grabbars and other strange things
------------------------------------------
Date: 2010-10-08 18:25
I've added these grabbars (dividers) for forms that have many panes. These are
borders (much like a scrollbar) that allow user to drag them left right
or up down and re-size panes. Currently, the alternative has been to use
keys such as C-w - and +, which may not be obvious.
However, we don't want these dividers to take focus each time a user
traverses the form. Thus, dividers are not focusable by default. But we
add them to a module FocusManager. When F3 is pressed, the FocusManager
toggles these dividers (or whatever it has in its list), to focusable.
Now the user can tab into these dividers. Once the user is done, he may
press F3 again and make them non-focusable. FocusManager can be used for
amy objects that should only be focusable when user wants them. I may
make scrollbars focusable in a future version.
* * * * * * * *
Subject: stacks and flows - thoughts
------------------------------------
Date: 2010-10-17 22:40
It should be possible to maintain stacks and flows within the app class.
this way, the app can be asked to reposition the widgets and it can do
so. This is required for when we get into using KEY_RESIZE (window
resizing). So this will only be available within App, but then that's
where stacks and flows are, anyway.
Can we liberate S and F from App and make them independent ?
* * * * * * * *
Subject: color_pair added to widget
-----------------------------------
Date: 2010-10-18 23:04
Now we may directly pass a color_pair to a widget when creating. This
way we can create one color_pair and pass it to multiple widgets, rather
than passing actual colors to each. Also, this is a tad more efficient
since the color won't be calculated each time a repaint is done.
* * * * * * * *
Subject: Usage of preferred_size
--------------------------------
Date: 2010-10-20 13:02
when the user may resize a component, or columns in a components, or
user may specify widths or heights, we should use a `preferred_width`
field.
When we calculate width, use `preferred_width` if present, else calculate
it. Program never updates `preferred_width`.
However, the question is what when a user resizes a component or
sub-component. We want to respect that and not overwrite. So currently,
i suggest that we update preferred_width on resizing, dragging etc. This
does mean that the original specified width is lost, so a
`reset_to_preferred_sizes` is not possible.
* * * * * * * *
Subject: single and multiple selection and keys
-----------------------------------------------
Date: 2010-10-28 23:07
If single selection (by spacebar) then pressing spacebar and pressing
Enter should typically have same action. i.e. select current row and
fire_event.(*)
If multiple selection, then Enter typically fires an action for current
row such as opening an item or giving more details for that item.
Spacebar selects multiple items (or Ctrl-Spacebar), and other keys will
execute some action on selected rows (like delete, flag, move etc).
(*) Exceptions: in tree, Enter collapses or expands, and selects current
row, whereas spacebar only selects and displays in other window.
Spacebar does not expand or collapse tree node.
Typically in multiple select, spacebar selects first row (deselecting
others) and Ctrl-Spacebar continues selection. Have to check this out
with Listbox. including `ListSelectable` should take care of most of this.
* * * * * * * *
Subject: rmessagewindow
-----------------------
Date: 2010-11-04 12:23
Regarding bottomline and rmessagewindow
I was thinking that if i try to do bottomline in a separate window that
just pops up and goes off, then i don't have to worry about having a
window handle (since a new window is created with each call). I tried
out this approach with rmessagewindow.
However, first of all one has to press a key to make the message go off.
Secondly, when the window goes off, so does the message. Whatever was
there before remains. Which is great if that's what you need. (But we
already have alert() and rdialog for that).
This is fine for accepting input at screen bottom, but after ask() we
still want to display some message like "file written" and let it be
there. Which means i still have to write to existing window, so my
problem remains. I need to have handle of existing window.
I've added a bottomline object in each window when we create so we can
use it as `@window.ask`, `@window.agree`.
When you use App, you automatically get `ask()` connected to the root
window, but what happens when one App calls another App!!
However, i really like how i can do a 'M-x' (taken from memacs), and
then tab to see available commands. This way user does not need to
remember key combinations.
* * * * * * * *
Subject: gmail style email completion
-------------------------------------
Date: 2010-11-20 13:26
I've just implemented some gmail style email completion.
As you type in a field, values are shown in a window. You can key UP or
DOWN, or keep typing. Pressing ENTER selects highilghted value. You can
enter multiple emails in one field and get help on each.
However, in this case, the window is not modal, so the form below is
painting itself. There are still some old widgets like Label and Field
(perhaps button) that keep repainting redgarldess of whether changed.
This overrides the non-modal window. I've just fixed field but putting a
@repaint_required == true check in repaint.
Also, i think its possible, that rcommandwindow does a repaint and panel
update more often than required. its called in different ways,
interactive and non-interactive. Need to look into that at some time.
* * * * * * * *
Subject: calcurse
-----------------
Date: 2010-12-01 18:49
Just installed calcurse (port) and was checking the UI. Neat. Some salient
points:
1. Windows or panels. Standard with title, title border, border color
changes when focus in panel or box (that's because it keeps updating
time and thereofre cursor remains on status bar)
2. 2 bottom lines for keys like we have (keylabels)
3. 3rd last row is a sort of status bar like emacs and vim have
4. Data entry in last 2 rows. 2nd last has prompt, last has entry or
edit
5. Similarly menu options selected in last row. A page comes with
options, letter indexed.
6. Allows layout change of panels.
7. Allows color change, immediate change. Displays colors rather than
name. Color chooser for BG and FG.
Subject: App.rb confirm before quit
-----------------------------------
Date: 2011-09-17 11:49
App should be able to configure whether it wants quit-confirm. Or a
procedure to call before quitting, such as saving values. It's okay for
demos where there's no state to just press F1 or q or C-q to quit.
* * * * * * * *
Subject: porting to ffi-ncurses
-------------------------------
Date: 2011-09-17 11:51
I've been working on porting the rbcurse gem to ffi-ncurses, since
ncurses gems is so so hard to install for a lot of people. Thanks to
Sean's support the work and retesting was actually very little. It's
just that there is a lot of testing to do with all the programs,
widgets.
Sean is coming out with a version 0.4.0 which I am using. rbcurse 1.3.0
onwards uses ffi-ncurses.
* * * * * * * *
Subject: color formatting
-------------------------
Date: 2011-11-03 15:03
Alot has happened since moving to ffi. New widgets and containers, a new
tabbedpane that hopefully doesn't suck and is more rubyesque. However,
its amazing how simple the color formatting issue was. Took me only a
few minutes to get working with a good regular expression.
The motivation is to be able to have a document with color formatting. I
am using the color formatting code of tmux, i.e., #[fg=green, bg=blue,
bold] etc. However, I added an "#[end]" tag which pops the previous
color, so now its more like html's span, than the terminal escape
sequences which just override the previous.
I'll ofcourse use this in the statusline, in help screens, and also in
some way in textview, and somehow even in messages, alerts, messageboxes
etc. It's still rough, does no checking for mistakes and I don't have a
routine to wrap text ignoring the color stuff. That will be needed soon.
* * * * * * * *
Subject: bifurcating into core and others
-----------------------------------------
Date: 2011-11-08 18:30
Perhaps it would be better to divide rbcurse into rbcurse-core and then
other packages or gems.
This way *core* can remain more or less frozen and bug fixes can be
released quickly without waiting for other features to stabilize.
Changes in other packages can be made without disturbing core. Core can
be kept backward compatible. And it can remain light with just form,
window, field, buttons, list and perhaps textview.
Other widgets can be put in other gems. The entire extras, UI patterns,
experimental work. There could be a *rbcurse-experimental* which moves to
either core or standard as and when it stabilizes.
1. rbcurse-core - form, field, label, buttons, dialogs, basiclist, messagebox
viewer, menus? , combo - basically whatever is required to run test2 and
test1.rb. We must have a minimal number of programs to test for this.
Actually, test2 incorporates a lot!
2. rbcurse-util
menus?, textarea?, tabbedpane, tree
tables, tabular, keylabel, progress, scrollbar, statusline,
3. rbcurse-extras
vimsplit, multi-containers, masterdetail, directorylist etc
statuswindow, rcommandwindow
link, menulink, container
4. rbcurse-experimental
resultset,
Pad, subwin,derwin from window class, scrollform, app, stack/flow
gmailfield
5. rbcurse-demos
rfe, sqlc/m, dbdemo which can be installed and run from anywhere
appemail
This must be dependent on a specific version of core and util.
6. rbcurse-db
database related work - resultsetview etc
* * * * * * * *
Subject: textpad
----------------
Date: 2013-03-05 20:11
Moving to textpad usage
This would simplify stuff since textview has to do a lot of work each
time it displays, too much truncation of strings and all that, a lot of
memory and gc happening.
Textpad is simpler, however there's one issue. ncurses does not see to
do book-keeping of pads as it does of windows. When a popup or alert
comes up from some part of the app, there's a black box left on the
screen. padrefresh will take care of this, however, the box may cover
not one but several pads, and we need to find all the pads and make them
refresh themselves. until then have to postpone. the ffi-ncurses
example also has a case where the underlyign frame is manuall repainted
which sucks.
Window has the internal pads, not our textpad objects. So although it can delete
pads it cannot do a padrefresh which is our textpad method.
* * * * * * * *
Subject: field history
----------------------
Date: 2013-03-06 14:27
I've added history to get_string. Wonder why it was not there.
However, i think it should be a part of field, optional, since
different fields should maintain their own history. Surely, I've done
something on this, or thought it over.
Okay, Field can maintain its history if you extend FieldHistory, however if
you use a field in a messagebox which is created over and over again, then we
manually have to keep the history and pass it to the field when creating the messagebox.
* * * * * * * *
Subject: pad version of widgets
-------------------------------
Date: 2013-03-26 11:56
We have textpad functioning as a replacement of textview. Should we
replace the code inside textview with pad, this involves a lot of
testing and not knowing what can break. What user apps can break?
Or create parallel widgets. I have used textpad in cygnus for lists,
popups and textviews. Now I need to use it for tree and tabularwidget.
If i keep parallel widgets then there's a naming issue. Should i use
another module name Pad so i have Pad::tree etc or a different name ?
I would go with another module name but same widget name so it is clear
that it is the same widget.
* * * * * * * *
Subject: a new rbcurse
----------------------
Date: 2014-03-16 12:23
Based on cygnus and the new textpad, and its derivatives, I'd like to
branch off into a new project altogether with a much simpler and
stripped down curses gems.
Use basic widgets from rwidget.rb, and use new textpad for all the
others
Redo button which is a mess, and make separate classes (independent) if
need be
Clean up form and window and remove as much as possible.
Remove the DSL nonsense, so a hash has to be used
What about stacks and flows ? Form needs to know so it can redraw.
* * * * * * * *
Subject: More on simplification
-------------------------------
Date: 2014-03-24 10:34
While documenting the tutorial, I have these findings.
The DSL syntax is the cleanest. and it may be required for cases
like containers, trees, and definitely for stack and flow.
I think the hash syntax requires more internal work, but however, hash
works as a var argument, and is passed around. Again, stacks and flows
use the hash. I may not be able to get rid of the hash.
So we may be stuck with all three ways of widget creation.
I was trying smoe benchmarks of all three. I can't say for sure since
the results differ with high iterations but seems that the DSL creation
is slowest. Hash is slightly slower than the conventional method calls.
I will have to think of other ways of simplifying.
* * * * * * * *
Subject: constructors
---------------------
Date: 2014-03-25 22:33
For the purpose of simplifying, I was looking at the libtcltk ruby code.
They essentially use the same approach as I have done.
They also use a hash for options, but i doesn't look like they set it
into vars. they keep it in a hash.
the first param is checked for if its a hash then it is taken to be the
options. this way one doesn't have to pass form as nil.
all symbols are converted to strings. we sort of do the opposite and
prefer symbols.
however, if we only keep in a hash, then any processing that needs to be
done cannot be done. i am concerned about property_changed etc.
to update the hash, there is a configure method.
i suppose the configure method could check for an array of
property_change elements and call the handler. but still no special
processing can be done if we keep a hash only.
Keeping in a hash means that no documentation will be generated.
Interestingly, the menubar uses a spec which is an array with elements
and a proc, so the entire menu can be defined. each menu also can take a
spec as an optional param.
* * * * * * * *
Subject: tabbedpane and buttons
-------------------------------
Date: 2014-03-28 15:35
tabbed panes have buttons
This is fine if mostly used in a window as TabbedWindow. I suppose
having the buttons as part of the widget was necessary rather than
putting them on another form which was really complicating the earlier
code. Earlier, iirc we had 3 forms on for tabs, on for buttons and one
for the main form. Now its one.
However, if we embed a TP in a regular form with other widgets, then the
button is irrelevant. I can ofcourse not give a button_type but still
the lower area is demarcated. I am not sure why the button is used in
the demo, and why the area is printed and taken up if not button.
Is this to be fixed ?
* * * * * * * *
Jump to Line
Something went wrong with that request. Please try again.