Browse Source

Improve fallback scrollbar behaviour

Přemysl Janouch 1 month ago
parent
commit
3fd88d593c
Signed by: Přemysl Janouch <p@janouch.name> GPG Key ID: A0420B94F92B9493
2 changed files with 30 additions and 9 deletions
  1. 1
    1
      LICENSE
  2. 29
    8
      nncmpp.c

+ 1
- 1
LICENSE View File

@@ -1,4 +1,4 @@
1
-Copyright (c) 2016 - 2017, Přemysl Janouch <p@janouch.name>
1
+Copyright (c) 2016 - 2018, Přemysl Janouch <p@janouch.name>
2 2
 
3 3
 Permission to use, copy, modify, and/or distribute this software for any
4 4
 purpose with or without fee is hereby granted.

+ 29
- 8
nncmpp.c View File

@@ -1,7 +1,7 @@
1 1
 /*
2 2
  * nncmpp -- the MPD client you never knew you needed
3 3
  *
4
- * Copyright (c) 2016 - 2017, Přemysl Janouch <p@janouch.name>
4
+ * Copyright (c) 2016 - 2018, Přemysl Janouch <p@janouch.name>
5 5
  *
6 6
  * Permission to use, copy, modify, and/or distribute this software for any
7 7
  * purpose with or without fee is hereby granted.
@@ -66,6 +66,7 @@ enum
66 66
 #include "liberty/liberty.c"
67 67
 #include "liberty/liberty-tui.c"
68 68
 
69
+#include <math.h>
69 70
 #include <locale.h>
70 71
 #include <termios.h>
71 72
 #ifndef TIOCGWINSZ
@@ -1171,6 +1172,29 @@ app_visible_items (void)
1171 1172
 	return MAX (0, app_fitting_items ());
1172 1173
 }
1173 1174
 
1175
+struct scrollbar { long length, start; }
1176
+app_compute_scrollbar (long top, long total, long visible)
1177
+{
1178
+	if (total < visible)
1179
+		return (struct scrollbar) { 0, 0 };
1180
+	if (visible == 1)
1181
+		return (struct scrollbar) { 1, 0 };
1182
+	if (visible == 2)
1183
+		return (struct scrollbar) { 1, top >= total / 2 };
1184
+
1185
+	// Only be at the top or bottom when the top or bottom item can be seen.
1186
+	// The algorithm isn't optimal but it's a bitch to get right.
1187
+	double lenf = 1. + (visible - 2.) * visible / total, length = 0.;
1188
+	long offset = 1. + (visible - 2.) * top / total + modf (lenf, &length);
1189
+
1190
+	if (top == 0)
1191
+		return (struct scrollbar) { length, 0 };
1192
+	if (top + visible >= total)
1193
+		return (struct scrollbar) { length, visible - length };
1194
+
1195
+	return (struct scrollbar) { length, offset };
1196
+}
1197
+
1174 1198
 static void
1175 1199
 app_draw_scrollbar (void)
1176 1200
 {
@@ -1183,18 +1207,15 @@ app_draw_scrollbar (void)
1183 1207
 	struct tab *tab = g.active_tab;
1184 1208
 	int visible_items = app_visible_items ();
1185 1209
 
1210
+	hard_assert (tab->item_count != 0);
1186 1211
 	if (!g.use_partial_boxes)
1187 1212
 	{
1188
-		// Apparently here we don't want the 0.5 rounding constant
1189
-		int length = (float) visible_items / (int) tab->item_count
1190
-			* (visible_items - 1);
1191
-		int start  = (float) tab->item_top / (int) tab->item_count
1192
-			* (visible_items - 1);
1193
-
1213
+		struct scrollbar bar = app_compute_scrollbar
1214
+			(tab->item_top, tab->item_count, visible_items);
1194 1215
 		for (int row = 0; row < visible_items; row++)
1195 1216
 		{
1196 1217
 			move (g.header_height + row, COLS - 1);
1197
-			if (row < start || row > start + length + 1)
1218
+			if (row < bar.start || row >= bar.start + bar.length)
1198 1219
 				addch (' ' | APP_ATTR (SCROLLBAR));
1199 1220
 			else
1200 1221
 				addch (' ' | APP_ATTR (SCROLLBAR) | A_REVERSE);

Loading…
Cancel
Save