ref: 79cda97b806baf2adfc0045537675684d1edfe75
parent: 20868574345b23c2212bfb7c0234436cf481a882
author: qwx <[email protected]>
date: Mon Aug 26 07:38:41 EDT 2024
rework zoom: try to center on current position
--- a/draw.c
+++ b/draw.c
@@ -342,11 +342,10 @@
bgscalf = 32767. / bgscalyl;
}
-void
-redraw(int all)
+static void
+resetview(int all)
{
usize span;
- Dot d;
lockdisplay(display);
T = (vlong)(dot.totalsz / zoom / Dx(screen->r)) & ~3;
@@ -360,6 +359,14 @@
if(all)
resetdraw();
unlockdisplay(display);
+}
+
+void
+redraw(int all)
+{
+ Dot d;
+
+ resetview(all);
if(paused)
refresh(Drawall);
d = dot;
@@ -369,20 +376,28 @@
}
void
-setzoom(int Δz, int mul)
+setzoom(int Δz, int x)
{
- double z;
+ double z, span, Δx;
- if(!mul)
- z = zoom + Δz;
- else if(Δz < 0)
- z = zoom / pow(2, -Δz);
+ if(Δz < 0)
+ z = zoom / pow(1.025, -Δz);
else
- z = zoom * pow(2, Δz);
- if(z < 1.0 || z > (dot.totalsz / Sampsz) / Dx(screen->r))
+ z = zoom * pow(1.025, Δz);
+ if(z < 1.0)
+ z = 1.0;
+ else if(z > (dot.totalsz / Sampsz) / Dx(screen->r))
+ z = (dot.totalsz / Sampsz) / Dx(screen->r);
+ if(z == zoom)
return;
zoom = z;
- redraw(0);
+ span = T;
+ resetview(0);
+ span -= T;
+ span *= Dx(screen->r);
+ Δx = ((double)x / Dx(screen->r)) * span / T;
+ if(!setpan(Δx))
+ redraw(0);
}
int
@@ -405,14 +420,14 @@
return 0;
}
-void
+int
setpan(int Δx)
{
usize new;
Δx *= T;
- if(zoom == 1)
- return;
+ if(zoom == 1.0)
+ return 0;
if(Δx < 0 && -Δx > views)
new = 0;
else if(views + Δx >= viewmax)
@@ -420,9 +435,10 @@
else
new = views + Δx;
if(new == views)
- return;
+ return 0;
views = new;
redraw(0);
+ return 1;
}
void
--- a/fns.h
+++ b/fns.h
@@ -11,11 +11,12 @@
int cmd(char*);
void appendfile(char*);
void refresh(int);
+void setcenter(int);
void setzoom(int, int);
int zoominto(vlong, vlong);
void setrange(usize, usize);
int setloop(vlong);
-void setpan(int);
+int setpan(int);
void setpage(int);
int setjump(vlong);
vlong ss2view(int);
--- a/pplay.c
+++ b/pplay.c
@@ -106,7 +106,7 @@
threadmain(int argc, char **argv)
{
char *p;
- Mouse mo;
+ Mouse m, mo;
Rune r;
notriob = 0;
@@ -146,24 +146,26 @@
for(;;){
switch(alt(a)){
case 0:
+ mo = mc->Mouse;
lockdisplay(display);
if(getwindow(display, Refnone) < 0)
sysfatal("resize failed: %r");
unlockdisplay(display);
redraw(1);
- mo = mc->Mouse;
break;
case 1:
- if(eqpt(mo.xy, ZP))
- mo = mc->Mouse;
+ m = mc->Mouse;
+ if(mo.msec == 0)
+ mo = m;
switch(mc->buttons){
- case 1: setjump(view2ss(mc->xy.x - screen->r.min.x)); break;
- case 2: setloop(view2ss(mc->xy.x - screen->r.min.x)); break;
- case 4: setpan(mo.xy.x - mc->xy.x); break;
- case 8: setzoom(1, 1); break;
- case 16: setzoom(-1, 1); break;
+ case 1: setjump(view2ss(m.xy.x - screen->r.min.x)); break;
+ case 2: setloop(view2ss(m.xy.x - screen->r.min.x)); break;
+ case 4: setpan(mo.xy.x - m.xy.x); break;
+ case 5: setzoom(m.xy.y - mo.xy.y, mo.xy.x - screen->r.min.x); m.xy.x = mo.xy.x; break;
+ case 8: setzoom(1.0, mo.xy.x - screen->r.min.x); m.xy.x = mo.xy.x; break;
+ case 16: setzoom(-1.0, mo.xy.x - screen->r.min.x); m.xy.x = mo.xy.x; break;
}
- mo = mc->Mouse;
+ mo = m;
break;
case 2:
switch(r){
@@ -171,10 +173,10 @@
case Kesc: setrange(0, dot.totalsz); break;
case '\n': zoominto(dot.from, dot.to); break;
case '\t': chan = chan + 1 & 1; break;
- case '-': setzoom(-1, 0); break;
- case '=': setzoom(1, 0); break;
- case '_': setzoom(-1, 1); break;
- case '+': setzoom(1, 1); break;
+ case '-': setzoom(-20.0, mo.xy.x - screen->r.min.x); m.xy.x = mo.xy.x; break;
+ case '=': setzoom(20.0, mo.xy.x - screen->r.min.x); m.xy.x = mo.xy.x; break;
+ case '_': setzoom(-1.0, mo.xy.x - screen->r.min.x); m.xy.x = mo.xy.x; break;
+ case '+': setzoom(1.0, mo.xy.x - screen->r.min.x); m.xy.x = mo.xy.x; break;
case '1': bound = 0; break;
case '2': bound = 1; break;
case 'S': stereo ^= 1; redraw(1); break;
--- a/pplay.man
+++ b/pplay.man
@@ -49,13 +49,11 @@
.IR tmdate (2)),
or the number of stereo samples so far if toggled.
.PP
-When the selected range is the entire data and only the
-.I @
-timestamp is displayed.
-The
-.I ‡
-timestamp is displayed if a cursor has been set
-see section "Loop points and selection" below).
+The view can be moved horizontally with the cursor keys,
+or by holding the right mouse button.
+Zooming in decreases the sample period (and vice-versa)
+via keyboard shortcuts, the mouse scroll buttons,
+or by holding the left mouse button while panning.
.SS "Loop points and selection"
Playback is constrained to a range defined by two positional markers,
the start and end loop points, initially the entire data.