summaryrefslogtreecommitdiff
path: root/interface/pager.py
diff options
context:
space:
mode:
authorBen Connors <benconnors@outlook.com>2019-10-18 23:02:12 -0400
committerBen Connors <benconnors@outlook.com>2019-10-18 23:02:12 -0400
commit755d1dda2a1eb1c26fa7bc12328e2bca25256257 (patch)
tree272a917fea560e93f28602806727f0d2b315d185 /interface/pager.py
parentbd3feef1499353af4410a52ee88dcb07f5dd08c0 (diff)
Get a decent start on the actual interface
- Can edit, create, delete scenes - Basic saving
Diffstat (limited to 'interface/pager.py')
-rwxr-xr-xinterface/pager.py149
1 files changed, 149 insertions, 0 deletions
diff --git a/interface/pager.py b/interface/pager.py
new file mode 100755
index 0000000..2203e52
--- /dev/null
+++ b/interface/pager.py
@@ -0,0 +1,149 @@
+#!/usr/bin/env python3
+
+import curses
+import threading
+
+from .globals import CURSES_LOCK
+
+class Pager:
+ def set_dim(self, height, width):
+ if height < 4 or width < 10:
+ raise ValueError("Size too small")
+
+ with self._lock:
+ if (height, width) != (self._height, self._width):
+ self.win.erase()
+ self.win.noutrefresh()
+
+ self.win.resize(height, width)
+ self.win.redrawwin()
+
+ self._height = height
+ self._width = width
+ self._regen_actual()
+ self._redraw()
+
+ def set_pos(self, y, x):
+ with self._lock:
+ if (y, x) != (self._y, self._x):
+ self.win.mvwin(y, x)
+ self._y = y
+ self._x = x
+ self.win.noutrefresh()
+
+ def _redraw(self):
+ with self._lock, CURSES_LOCK:
+ start = max(0, self._bottom_a - self._height + 2)
+ end = self._bottom_a
+ todisp = self._actual[start:end]
+ if len(todisp) < self._height-2 and len(todisp) < len(self._actual):
+ end = self._bottom_a+self._height-2-len(todisp)
+ todisp += self._actual[self._bottom_a:end]
+ self.win.erase()
+ self.win.border()
+ if start > 0:
+ self.win.addch(0, self._width//2, '⯅')
+ for n, l in enumerate(todisp, 1):
+ self.win.addstr(n, 1, l)
+ if end < len(self._actual):
+ self.win.addch(self._height-1, self._width//2, '⯆')
+ self.win.refresh()
+
+ def _split_line(self, l):
+ with self._lock:
+ lines = []
+
+ while len(l) >= self._width-2:
+ lines.append(l[:self._width-3] + '…')
+ l = "⮡ "+l[self._width-3:]
+ lines.append(l)
+
+ return lines
+
+ def _regen_actual(self):
+ with self._lock:
+ self._actual = []
+ for n, l in enumerate(self._lines):
+ self._actual += self._split_line(l)
+ if n == self._bottom:
+ self._bottom_a = len(self._actual)
+ self._bottom_a = max(self._bottom_a, self._height-2)
+
+ def display_many(self, s, split=False):
+ with self._lock:
+ if split:
+ self._lines.append("")
+ self._actual.append("")
+ for l in s:
+ self._lines.append(l)
+ self._actual += self._split_line(l)
+ self._bottom = len(self._lines) - 1
+ self._bottom_a = len(self._actual)
+ self._redraw()
+
+ def display(self, s):
+ self.display_many((s, ))
+
+ def user_page(self, refresh=None):
+ curses.curs_set(0)
+
+ while True:
+ l = self.win.getch()
+
+ with self._lock:
+ if l == curses.KEY_RESIZE:
+ if refresh is not None:
+ refresh()
+ elif l == ord('q'):
+ break
+ elif l in (ord('k'), curses.KEY_UP):
+ if self._bottom_a > self._height-2:
+ self._bottom_a -= 1
+ self._redraw()
+ elif l in (ord('j'), curses.KEY_DOWN):
+ if self._bottom_a < len(self._actual):
+ self._bottom_a += 1
+ self._redraw()
+ elif l == curses.KEY_NPAGE:
+ if self._bottom_a < len(self._actual):
+ self._bottom_a = min(len(self._actual), self._bottom_a + self._height - 2)
+ self._redraw()
+ elif l == curses.KEY_PPAGE:
+ if self._bottom_a > 0:
+ self._bottom_a = max(self._height - 2, self._bottom_a - self._height + 2)
+ self._redraw()
+ elif l == curses.KEY_HOME:
+ if self._bottom_a > self._height - 2:
+ self._bottom_a = self._height - 2
+ self._redraw()
+ elif l == curses.KEY_END:
+ if self._bottom_a < len(self._actual):
+ self._bottom_a = len(self._actual)
+ self._redraw()
+
+ curses.curs_set(1)
+
+ def clear(self):
+ with self._lock:
+ self._lines = []
+ self._actual = []
+ self._bottom_a = 0
+ self._bottom = -1
+ self._redraw()
+
+ def __init__(self, y, x, height, width):
+ with CURSES_LOCK:
+ self.win = curses.newwin(height, width, y, x)
+ self.win.keypad(True)
+ self._lock = threading.RLock()
+ self._height = height
+ self._width = width
+ self._y = -1
+ self._x = -1
+ self._lines = []
+ self._actual = []
+ self._bottom = -1
+ self._bottom_a = 0
+
+ self.set_pos(y, x)
+ self.set_dim(height, width)