Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F4429
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/CHANGELOG b/CHANGELOG
index fffb668..3069bd3 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,31 +1,33 @@
Copyright (C) 2022 LANNOCC (Shawn A. Wilson [lannocc@yahoo.com])
@%@~LICENSE:MIT~@%@
+saw_073022_6 - Window movement (Linux).
+
saw_073022_5 - Version bump: tested on Linux and Win7.
saw_073022_4 - Print containment on Windows.
saw_073022_3 - Normalized mouse input across platforms.
saw_073022_2 - Mouse input on Windows.
saw_073022_1 - Input wrangling and exception propagation.
saw_072922_3 - Version bump: tested on Linux and Win7.
saw_072922_2 - Beginning Windows backend.
saw_072922_1 - A possible approach to multiple backends.
saw_072822_6 - Some window fun.
saw_072822_5 - Bump version for pip platform dependency test.
saw_072822_4 - Test commit (turned on GPG sign in Windows).
saw_072822_3 - Add Windows support to mouse test script.
saw_072822_2 - Add a mouse test script.
saw_072822_1 - Initial commit (just termio.py from my vipy project).
diff --git a/appscii/app.py b/appscii/app.py
index 8b7ee86..fd814f5 100644
--- a/appscii/app.py
+++ b/appscii/app.py
@@ -1,86 +1,105 @@
from .backend import core
from threading import Thread, current_thread
class Application:
def __init__(self):
self.go = False
self.error = None
self.core = core.Application(self)
self.windows = [ ]
+ self.mouse = (False, False, False) # mouse buttons (left, mid, right)
+ self.moving = None
def exit(self):
self.core.exit()
if self.error:
raise self.error
def run(self):
self.go = True
self.inputs = Thread(target=self.wrap(self.core.inputs),
name='inputs', daemon=True)
self.inputs.start()
- self.refresh_all()
-
self.on_run()
def stop(self, error=None):
if error:
if self.error:
- try:
- raise self.error
+ try: raise self.error
except Exception as e:
- try:
- raise error
+ try: raise error
except Exception as e:
self.error = e
else:
self.error = error
self.go = False
def wrap(self, fn):
def wrapped():
- try:
- fn()
-
+ try: fn()
except Exception as e:
try: raise ThreadException() from e
except Exception as e: self.stop(e)
return wrapped
- def refresh(self):
- self.core.refresh()
+ @property
+ def w(self):
+ return self.core.w
- def refresh_all(self):
- self.refresh()
- for win in self.windows:
- win.refresh()
+ @property
+ def h(self):
+ return self.core.h
def on_run(self):
#raise RuntimeError('yikes')
+
+ #from time import sleep
+ #sleep(1)
+ #self.windows[0].move_to(42, 9)
+
self.inputs.join()
def on_key(self, key):
if key == 27: # escape
self.stop()
def on_mouse(self, x, y, left, mid, right, scroll):
- # this is just for testing:
+ if self.moving:
+ win, mx, my = self.moving
+ if not left:
+ self.moving = None
+
+ if x != mx or y != my:
+ win.move_by(x - mx, y - my)
+ if self.moving:
+ self.moving = (win, x, y)
+
+ elif left and not self.mouse[0]: # left button pushed
+ for win in self.windows:
+ if x >= win.x and x < win.x + win.w \
+ and y >= win.y and y < win.y + win.h:
+ #win.on_mouse(x, y, left, mid, right, scroll)
+
+ self.moving = (win, x, y)
+ break
+
+ self.mouse = (left, mid, right)
+
+ # FIXME this is just for testing (assumes we have at least one window):
self.windows[0].print(f'{x},{y}: {left},{mid},{right},{scroll}')
- self.windows[0].refresh()
- #self.refresh_all()
- pass
class ThreadException(Exception):
def __init__(self):
t = current_thread()
super().__init__('from thread ' \
+ f'"{t.name}"' if t.name else f'{t.ident}')
diff --git a/appscii/backend/curses.py b/appscii/backend/curses.py
index 8e61cf0..b55acf3 100644
--- a/appscii/backend/curses.py
+++ b/appscii/backend/curses.py
@@ -1,114 +1,150 @@
import curses
class Application:
def __init__(self, shell):
self.shell = shell
self.screen = curses.initscr()
curses.flushinp()
curses.curs_set(0)
curses.noecho()
curses.cbreak()
self.screen.keypad(True)
curses.set_escdelay(99)
curses.mousemask(curses.ALL_MOUSE_EVENTS | curses.REPORT_MOUSE_POSITION)
self.mbtns = [False, False, False] # mouse buttons (left, mid, right)
def exit(self):
self.screen.keypad(False)
curses.nocbreak()
curses.echo()
curses.curs_set(1)
curses.flushinp()
curses.endwin()
- def refresh(self):
- self.screen.refresh()
-
def inputs(self):
while self.shell.go:
#raise RuntimeError('my bad')
key = self.screen.getch()
if key == curses.KEY_MOUSE:
_, x, y, _, btn = curses.getmouse()
mbtns = self.mbtns
if btn & curses.BUTTON1_PRESSED:
mbtns[0] = True
elif btn & curses.BUTTON1_RELEASED:
mbtns[0] = False
if btn & curses.BUTTON2_PRESSED:
mbtns[1] = True
elif btn & curses.BUTTON2_RELEASED:
mbtns[1] = False
if btn & curses.BUTTON3_PRESSED:
mbtns[2] = True
elif btn & curses.BUTTON3_RELEASED:
mbtns[2] = False
if btn & curses.BUTTON1_CLICKED \
or btn & curses.BUTTON1_DOUBLE_CLICKED:
self.shell.on_mouse(x, y, True, mbtns[1], mbtns[2], 0)
self.shell.on_mouse(x, y, False, mbtns[1], mbtns[2], 0)
if btn & curses.BUTTON1_DOUBLE_CLICKED:
self.shell.on_mouse(x, y, True, mbtns[1], mbtns[2], 0)
self.shell.on_mouse(x, y, False, mbtns[1], mbtns[2], 0)
elif btn & curses.BUTTON2_CLICKED \
or btn & curses.BUTTON2_DOUBLE_CLICKED:
self.shell.on_mouse(x, y, mbtns[0], True, mbtns[2], 0)
self.shell.on_mouse(x, y, mbtns[0], False, mbtns[2], 0)
if btn & curses.BUTTON2_DOUBLE_CLICKED:
self.shell.on_mouse(x, y, mbtns[0], True, mbtns[2], 0)
self.shell.on_mouse(x, y, mbtns[0], False, mbtns[2], 0)
elif btn & curses.BUTTON3_CLICKED \
or btn & curses.BUTTON3_DOUBLE_CLICKED:
self.shell.on_mouse(x, y, mbtns[0], mbtns[1], True, 0)
self.shell.on_mouse(x, y, mbtns[0], mbtns[1], False, 0)
if btn & curses.BUTTON3_DOUBLE_CLICKED:
self.shell.on_mouse(x, y, mbtns[0], mbtns[1], True, 0)
self.shell.on_mouse(x, y, mbtns[0], mbtns[1], False, 0)
elif btn & curses.BUTTON4_PRESSED:
self.shell.on_mouse(x, y, mbtns[0], mbtns[1], mbtns[2], 1)
elif btn & 2097152:
self.shell.on_mouse(x, y, mbtns[0], mbtns[1], mbtns[2], -1)
else:
self.shell.on_mouse(x, y, mbtns[0], mbtns[1], mbtns[2], 0)
else:
self.shell.on_key(key)
+ @property
+ def w(self):
+ return curses.COLS
+
+ @property
+ def h(self):
+ return curses.LINES
+
class Window:
def __init__(self, app, x, y, w, h):
+ self.app = app
+ assert w >= 2 and h >= 2
+ assert x >= 0 and x + w <= curses.COLS
+ assert y >= 0 and y + h <= curses.LINES
+
win = curses.newwin(h, w, y, x)
win.keypad(True)
win.box()
self.border = win
win = win.derwin(h - 2, w - 2, 1, 1)
win.keypad(True)
win.scrollok(True)
self.content = win
+ self.app.screen.refresh()
+ self.border.refresh()
+
self.newline = ''
def print(self, txt, end):
self.content.addstr(f'{self.newline}{txt}')
self.newline = '\n' if end else ''
+ self.content.refresh()
- def refresh(self):
+ @property
+ def x(self):
+ return self.border.getbegyx()[1]
+
+ @property
+ def y(self):
+ return self.border.getbegyx()[0]
+
+ @property
+ def w(self):
+ return self.border.getmaxyx()[1]
+
+ @property
+ def h(self):
+ return self.border.getmaxyx()[0]
+
+ def set_pos(self, x, y):
+ assert x >= 0 and x + self.w <= self.app.w
+ assert y >= 0 and y + self.h <= self.app.h
+
+ self.app.screen.clear()
+ self.app.screen.refresh()
+ self.border.mvwin(y, x)
+ self.content.mvwin(y + 1, x + 1)
self.border.refresh()
- self.content.refresh()
diff --git a/appscii/win.py b/appscii/win.py
index add2887..7be34d5 100644
--- a/appscii/win.py
+++ b/appscii/win.py
@@ -1,18 +1,46 @@
from .backend import core
class Window:
def __init__(self, app, x, y, w, h):
self.app = app
self.core = core.Window(app.core, x, y, w, h)
self.app.windows.append(self)
- def refresh(self):
- self.core.refresh()
-
def print(self, txt='', end=True):
self.core.print(txt, end)
- #def scroll(self, lines):
- # self.core.scroll(lines)
+ @property
+ def x(self):
+ return self.core.x
+
+ @property
+ def y(self):
+ return self.core.y
+
+ @property
+ def w(self):
+ return self.core.w
+
+ @property
+ def h(self):
+ return self.core.h
+
+ def move_to(self, x, y):
+ self.core.set_pos(x, y)
+
+ def move_by(self, dx, dy):
+ x = self.x + dx
+ if x < 0: x = 0
+ elif x + self.w > self.app.w: x = self.app.w - self.w
+
+ y = self.y + dy
+ if y < 0: y = 0
+ elif y + self.h > self.app.h: y = self.app.h - self.h
+
+ self.move_to(x, y)
+
+ #def on_mouse(self, x, y, left, mid, right, scroll):
+ # # FIXME this is just for testing:
+ # self.print(f'{x},{y}: {left},{mid},{right},{scroll}')
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Sep 14, 10:03 PM (1 w, 2 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3651
Default Alt Text
(10 KB)
Attached To
Mode
rAPPSCII Terminal Framework
Attached
Detach File
Event Timeline
Log In to Comment