dankamongmen / panelreels

high-level objects built atop ncurses
https://nick-black.com/dankwiki/index.php/Outcurses
Apache License 2.0
8 stars 1 forks source link

Decide behavior of unfilled reel and reenable validation #74

Closed dankamongmen closed 4 years ago

dankamongmen commented 4 years ago

See #60. When we have an incomplete reel, and change focus, everything is redrawn according to the focus. When we switch from the top to the next tablet, this results in the top tablet being drawn underneath the second. In general, it means that:

The first issue isn't a huge one. We'd need change validation to take it into account, but whatever. Everything's still visible. Much more annoying is the second issue. If I'm focused on the second tablet at y == 5, and the reel is 11 total, and t1 is 5 and t2 is 1, we ought be able to see all of t1 and t2 with no clipping. Instead, we'll get t2 unclipped, and t1 following it at 8. The result is 4 empty lines, t2 unclipped, gapline, and t1 bottom-clipped after two lines of data. 3 lines of actual data are thus missing, along with 1 line of border.

I don't like that, but fixing it means the focused window might have to move, which is also annoying. In the case above, either t2 could move up to line 1, or t2 could move down to line 9, but it can't stay at 5 unless we want to wrap around the bottom.

If we're moving focus to a tablet that is partially off-screen, it's already moving, so that doesn't necessarily seem such a tremendous break from current behavior...

dankamongmen commented 4 years ago

To handle the second issue without wrapping (I think wrapping would greatly complicate things for little benefit), we can do the following:

this prefers complete display of unfocused tablets, and prefers putting them below the focused tablet. one thing i don't like is that a growing tablet underneath the focused tablet will slowly push the focus towards the top (though not off-screen), even if there is good data above it. this thus favors complete unfocused tablets over the focused tablet staying stationary.

But, to be fair, the focus is almost always on an extremity anyway, because that's how it moves...

if we have two tablets, a large one and a smaller one, and they start as t1 and t2, and we switch focus to t2, right now t1 will be drawn after it. under this scheme, t1 would grow until t2 was pushed to the top. if t1+t2 fill the screen out, moving down or up to t2 from t1 will place t2 at the top, and down or up from t2 to t1 will place t1 at the top. that's counter to what we do today in growlight/omphalos, where moving down means you'll always be at the bottom, and the tablets instead switch positions. this is due to the bottom-favoring asymmetry.

so if we instead always give the drawn tablet all possible room, but prefer to keep it on the side of the focused tablet it's currently on, that unifies the broken symmetry. we still get pushed up to the top at all times, though.

so if we instead only give it all possible room when we have an absolute gap, that doesn't push us up arbitrarily, because the last one drawn isn't given all possible space. we then naturally fill in the gap above us with available tablets. if any only if we have space left, give it to the last tablet. we only do this if it was partially drawn. if we have one drawn above us, its space is not given away (unless it shrinks). so let's say we have:

empty line t1 l1 (top) t1 l2 (d1) t1 l3 (bottom) gap line t2 l1 (top) t2 l2 (d1) t2 l3 (d2) l2 l4 (bottom) gap line t3 l1 (top) t3 l2 (d1, clipped footer) .... many lines of t3 hidden....

and focus is on t2 (line 6). t2 has two lines available below it, post-draw. it calls t3 with these 2, which it fills and clips. we then call t1 with the four lines above it. t1 fills three lines. we call t3 with three lines, it fills the three, and we move everything else up one line. next round, t2 is drawn at its current position (line 5). it has three lines below it post-draw. t3 draws 3 lines, clipping. t1 draws three lines, filling the space above us. this time, we do not call t3 a second time. everything is stable unless there is a shrink.

i think that works beautifully.

it still flips t1 below t2 when moving down or up from t1 to t2 in a dyad. we can resolve that by first drawing in the direction opposite our move, if we want to.

the result would be a reel which never has a top gap of more than one line (unless all save one tablet are removed), keeps the focused tablet where it is unless a gap needs to be filled (which can only happen when we're not filling the reel), and doesn't move against the actual direction of move. i think this is a perfect solution.

if we then want to "handle" the case where all tablets have been removed save one, we can just move the stack up at the very end if there's a gap. i'm not sure this is necessary.

dankamongmen commented 4 years ago

So the first thing to do is track our direction of travel, and draw opposite that direction. This ought prevent tablets from flipping around on us. Let's make sure that doesn't have unintended consequences, and then do the hairier gapfilling.

dankamongmen commented 4 years ago

So the problem here is when we "wrap around". Let's say we have t1 and t2. We move down to t2. We're good, but then when we move "down" to t1, it is stuck below us. Likewise, if we initially move "up" to t2, we get swung below t2. I don't understand the first case; regardless of the direction taken to t1, once it's focused, it ought stay where it is...

dankamongmen commented 4 years ago
---------------> moved to next, 0x555a211ab5e0 to 0x555a211be840 <----------
--------> BEGIN REDRAW <--------
tplacement: 0x555a211be840:0x555a211bf100 base 5/5 len 74/37
DRAWING 0x555a211be840 at frontier 14 (dir 0) with 37
RESIZE TRUEY: 6 BEGY: 5 LENY: 37
drawing previous tablets
tplacement: 0x555a211ab5e0:0x555a211bee70 base 5/5 len 74/8
DRAWING 0x555a211ab5e0 at frontier 12 (dir -1) with 8
---------------> moved to next, 0x555a211be840 to 0x555a211ab5e0 <----------
--------> BEGIN REDRAW <--------
tplacement: 0x555a211ab5e0:0x555a211bee70 base 5/5 len 74/37
DRAWING 0x555a211ab5e0 at frontier 5 (dir 0) with 37
RESIZE TRUEY: 8 BEGY: 5 LENY: 37
drawing previous tablets
HIDING 0x555a211be840 at frontier 3 (dir -1) with 39
tplacement: 0x555a211be840:(nil) base 5/14 len 74/28
DRAWING 0x555a211be840 at frontier 14 (dir 1) with 28
tplacement: 0x555a211ab5e0:0x555a211bee70 base 5/21 len 74/21
DRAWING 0x555a211ab5e0 at frontier 21 (dir 1) with 21
RESIZE TRUEY: 8 BEGY: 21 LENY: 21

there's our problem

dankamongmen commented 4 years ago

So the first time, we move to the next, and draw it at 14. We then draw the prev at 12 going up, since our last direction was down. All is well.

The second time, we move to the next, and draw it at 5. We then try to draw the prev at frontier 5, which of course cannot be done. It is hidden, and we then display it drawing down (since it is reachable and hidden).

One way to deal with this would be to check, in _next() and _prev(), whether we're reaching a visible panel in the opposite direction. That's kinda grotesque, but it will work. Might there be a more elegant solution...?

dankamongmen commented 4 years ago

That appears to work perfectly for unfilled reels. On filled reels, I'm seeing us move focus to the top while moving down (sometimes) and move focus to the bottom while moving up (sometimes) (this was happening before these changes). So let's take care of that.

dankamongmen commented 4 years ago

Regarding the above:

dankamongmen commented 4 years ago

Fuck it, I want this done tonight. Rather than trying for something elegant, we're gonna do the following:

It's gross, but it's O(1), and we can do it in thirty minutes. Maybe an hour. And this will be done.

dankamongmen commented 4 years ago

Got it.