-
Notifications
You must be signed in to change notification settings - Fork 13
/
NOTES
2114 lines (1558 loc) · 78.5 KB
/
NOTES
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
NOTES
=====
/// vim:ts=4:sw=4:tw=80:ai:formatoptions=tcqnl:
/// this was posted with appenddiary.sh
Subject: Update rubyforge
-------------------------
To update the file named index.html on rubyforge use this. password is in
rubyforge config file.
scp index.html [email protected]:/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.