If the window has been resized, then it is no longer possible to restore the exact original state. In such cases it should do what seems to be most user-friendly. This is what this document is about.
Undo/Redo should attempt to restore the view position, plus the cursor-position-within-view. In certain cases the view position cannot be retored, eg: resize. Therefore we must try to do the best we can and restore it into a state as close as possible to the original one. In order to do this 'nice' restoration, then our memento must also store cursor-position-within-view and view-height.
| t0 | t01 | t1 | t12 | t2 | t23 | t3 |
|---|---|---|---|---|---|---|
![]() | pagedown | ![]() | undo (pagedown) | ![]() | redo (pagedown) | ![]() |
| a typical page down operation. | everything will be restored, exactly as it were before. | you will not be able to tell the difference, wheter pagedown or redo occured. |
As you can see both (t0 == t2) and (t1 == t3) is true. The corresponding test code looks like this:
def test_pagedown_normal1
i = fake_setup(2, 2, 1, 4)
assert_equal([2, 2, 1, 4], i.status)
i.execute :do_move_page_down
assert_equal([5, 2, 1, 1], i.status)
i.undo
assert_equal([2, 2, 1, 4], i.status)
i.redo
assert_equal([5, 2, 1, 1], i.status)
end
Another interesting case is when the we hit the bottom of the file, this look like the following diagram:
| t0 | t01 | t1 | t12 | t2 | t23 | t3 |
|---|---|---|---|---|---|---|
![]() | pagedown | ![]() | undo (pagedown) | ![]() | redo (pagedown) | ![]() |
| We will hit the bottom of the buffer. | everything will be restored, exactly as it were before. Obsrve that NO scrolling occurs, eg: the view should not be locked in this case. How does this special case work out if resize is involved? | you will not be able to tell the difference, wheter pagedown or redo occured. |
Resize is an operation which cannot be undone, therefore it doesn't store any any memento data.
Observe that Resize let the cursor-position stay untouched! If you resize the view by grapping at the bottom-border, then only the bottom lines is affected. The cursor is frozen and locked on to the same (x, y) position in the display.
| t0 | t01 | t1 | t12 | t2 | t23 | t3 | t34 | t4 |
|---|---|---|---|---|---|---|---|---|
![]() | pagedown | ![]() | resize | ![]() | undo (pagedown) | ![]() | redo (pagedown) | ![]() |
| a typical page down operation. | By resizing + moving + resizing the window, we will get this output! | Preservation of the cursor, so you get the feeling that its the opposite of pagedown(pageup). | Preservation of the cursor, so you get the feeling that its pagedown. |
Changing the view-height from 4 lines into 2 lines.
| t0 | t01 | t1 | t12 | t2 | t23 | t3 | t34 | t4 |
|---|---|---|---|---|---|---|---|---|
![]() | pagedown | ![]() | resize | ![]() | undo (pagedown) | ![]() | redo (pagedown) | ![]() |
| a typical page down operation. | Shrinking the height of the view affects indirectly redo! | Undoing behaves quite differently from a ordinary page-up operation. This is because of resize! | If we redo, then the page-down operation is no longer a typical behavier. Therefore watch out redoing page-down, when the height has changed! |
Changing the view-height from 4 lines into 7 lines.
| t0 | t01 | t1 | t12 | t2 | t23 | t3 | t34 | t4 |
|---|---|---|---|---|---|---|---|---|
![]() | pagedown | ![]() | resize | ![]() | undo (pagedown) | ![]() | redo (pagedown) | ![]() |
| a typical page down operation. | Widening the height of the view affects indirectly redo! | Preserve the cursors relative position within the view. | Preserve the cursors relative position within the view. |
At the buffer-top it has serious consequences.
| t0 | t01 | t1 | t12 | t2 | t23 | t3 | t34 | t4 |
|---|---|---|---|---|---|---|---|---|
![]() | pagedown | ![]() | resize | ![]() | undo (pagedown) | ![]() | redo (pagedown) | ![]() |
| a typical page down operation. | Widening the height of the view affects indirectly redo! | Undoing behaves quite differently from a ordinary page-up operation.
This is because of resize!
Preservation of the cursor-position-within-view is not possible. Thus observe that the cursor position within the view is changed. This is because we have hit buffer-begin. | I think it would be a bad idea to preserve the cursor position from t2. This just works as an nomal pagedown operation. |
At the buffer-bottom there doesn't seems to be any problems, at least there is no problems here.
| t0 | t01 | t1 | t12 | t2 | t23 | t3 | t34 | t4 |
|---|---|---|---|---|---|---|---|---|
![]() | pagedown | ![]() | resize | ![]() | undo (pagedown) | ![]() | redo (pagedown) | ![]() |
| a typical page down operation. | Widening the height of the view affects indirectly redo! | Preservation of the cursor. | Preservation of the cursor. |
But at the buffer-bottom there IS a minor problem.
Compare case t23 above with below, observe that scrolling
occurs in the above case and NO scrolling occurs in the below case!
Which behaver should one choose to implement?
Hmmm.. I think the case below is bad, because it doesn't
behave like pageup, its behavier reminds me more of move_one_line_up.
Therefore the above case is much better.
| t0 | t01 | t1 | t12 | t2 | t23 | t3 |
|---|---|---|---|---|---|---|
![]() | pagedown | ![]() | resize | ![]() | undo (pagedown) | ![]() |
| a typical page down operation. | Widening the height of the view! | Preserving the cursor position is bad in this paticular case. It is much better to disable lock_view. |
Is it really worth the efforts, making pagedown user-friendly?
Yes, undo of Pagedown can easily be confusing to the observer when
doing pair-programming, this is vital for improving user-frindlyness for the
observer!
The solution is simple: In the border-cases (bottom/top) to use move the cursor within the view. In the normal case scrolling is done. During set_memento, you can specify if the view should be locked.
Most of these cases also work for pageup, but not all. This is because up/down are assymetric. At the bottom there is virtual-lines. At the top there is nothing. BTW: The resize concept also applyes to sideway scrolling!
If we use softwrap, then changing the width of the window is equal to changing the height of the window!