mirror of
https://github.com/1j01/textual-paint.git
synced 2024-12-22 14:21:33 +03:00
Set up development features for gallery app
This commit is contained in:
parent
937dabb73c
commit
9140d14405
@ -9,6 +9,7 @@ from textual.app import ScreenStackError
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .paint import PaintApp
|
||||
from .gallery import GalleryApp
|
||||
|
||||
def restart_program() -> None:
|
||||
"""Restarts the current program, after resetting terminal state, and cleaning up file objects and descriptors."""
|
||||
@ -57,7 +58,7 @@ def restart_program() -> None:
|
||||
# os.execl(python, python, *sys.argv)
|
||||
os.execl(sys.executable, *sys.orig_argv)
|
||||
|
||||
def restart_on_changes(app: PaintApp) -> None:
|
||||
def restart_on_changes(app: PaintApp|GalleryApp) -> None:
|
||||
"""Restarts the current program when a file is changed"""
|
||||
|
||||
from watchdog.events import PatternMatchingEventHandler, FileSystemEvent, EVENT_TYPE_CLOSED, EVENT_TYPE_OPENED
|
||||
@ -80,7 +81,7 @@ def restart_on_changes(app: PaintApp) -> None:
|
||||
# or else nothing happens.
|
||||
# However, when _app.action_reload is called from the key binding,
|
||||
# it seems to work fine with or without unsaved changes.
|
||||
if _app.is_document_modified():
|
||||
if isinstance(_app, PaintApp) and _app.is_document_modified():
|
||||
_app.call_from_thread(_app.action_reload)
|
||||
else:
|
||||
restart_program()
|
||||
|
5
src/textual_paint/gallery.css
Normal file
5
src/textual_paint/gallery.css
Normal file
@ -0,0 +1,5 @@
|
||||
GalleryItem {
|
||||
layout: vertical;
|
||||
width: 100%;
|
||||
content-align: center middle;
|
||||
}
|
@ -2,20 +2,29 @@
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
|
||||
from textual.app import App, ComposeResult
|
||||
from textual.widgets import Footer, Header, Static
|
||||
from textual.binding import Binding
|
||||
from textual.containers import HorizontalScroll, Vertical
|
||||
from textual.widgets import Footer, Header, Static
|
||||
|
||||
from .paint import AnsiArtDocument
|
||||
from .__init__ import __version__
|
||||
from .auto_restart import restart_on_changes, restart_program
|
||||
from .paint import AnsiArtDocument
|
||||
|
||||
parser = argparse.ArgumentParser(description='ANSI art gallery', usage='%(prog)s [folder]', prog="python -m src.textual_paint.gallery")
|
||||
parser.add_argument('folder', nargs='?', default=None, help='Path to a folder containing ANSI art.')
|
||||
|
||||
dev_options = parser.add_argument_group('development options')
|
||||
dev_options.add_argument('--inspect-layout', action='store_true', help='Enables DOM inspector (F12) and middle click highlight')
|
||||
dev_options.add_argument('--restart-on-changes', action='store_true', help='Restart the app when the source code is changed')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
def _(text: str) -> str:
|
||||
"""Placeholder for localization function."""
|
||||
return text
|
||||
|
||||
class GalleryItem(Vertical):
|
||||
"""An image with a caption."""
|
||||
|
||||
@ -32,11 +41,31 @@ class GalleryItem(Vertical):
|
||||
yield Static(text)
|
||||
yield Static(self.caption)
|
||||
|
||||
class Gallery(App[None]):
|
||||
class GalleryApp(App[None]):
|
||||
"""ANSI art gallery TUI"""
|
||||
|
||||
TITLE = f"ANSI art gallery v{__version__}"
|
||||
|
||||
CSS_PATH = "gallery.css"
|
||||
|
||||
BINDINGS = [
|
||||
Binding("ctrl+q", "exit", _("Quit")),
|
||||
# dev helper
|
||||
# f5 would be more traditional, but I need something not bound to anything
|
||||
# in the context of the terminal in VS Code, and not used by this app, like Ctrl+R, and detectable in the terminal.
|
||||
# This isn't as important now that I have automatic reloading,
|
||||
# but I still use it regularly.
|
||||
Binding("f2", "reload", _("Reload")),
|
||||
# Temporary quick access to work on a specific dialog.
|
||||
# Can be used together with `--press f3` when using `textual run` to open the dialog at startup.
|
||||
# Would be better if all dialogs were accessible from the keyboard.
|
||||
# Binding("f3", "custom_zoom", _("Custom Zoom")),
|
||||
# Dev tool to inspect the widget tree.
|
||||
Binding("f12", "toggle_inspector", _("Toggle Inspector")),
|
||||
# Update screenshot on readme.
|
||||
# Binding("ctrl+j", "update_screenshot", _("Update Screenshot")),
|
||||
]
|
||||
|
||||
def compose(self) -> ComposeResult:
|
||||
"""Add widgets to the layout."""
|
||||
yield Header(show_clock=True)
|
||||
@ -46,6 +75,15 @@ class Gallery(App[None]):
|
||||
|
||||
yield Footer()
|
||||
|
||||
if not args.inspect_layout:
|
||||
return
|
||||
# importing the inspector adds instrumentation which can slow down startup
|
||||
from .inspector import Inspector
|
||||
inspector = Inspector()
|
||||
inspector.display = False
|
||||
yield inspector
|
||||
|
||||
|
||||
def on_mount(self) -> None:
|
||||
"""Called when the app is mounted to the DOM."""
|
||||
self._load()
|
||||
@ -57,7 +95,7 @@ class Gallery(App[None]):
|
||||
folder = os.path.join(os.path.dirname(__file__), "../../samples")
|
||||
if not os.path.isdir(folder):
|
||||
raise Exception(f"Folder not found: {folder}")
|
||||
|
||||
|
||||
for filename in os.listdir(folder):
|
||||
if not filename.endswith(".ans"):
|
||||
continue
|
||||
@ -68,8 +106,25 @@ class Gallery(App[None]):
|
||||
|
||||
self.scroll.mount(GalleryItem(image, caption=filename))
|
||||
|
||||
def action_reload(self) -> None:
|
||||
"""Reload the program."""
|
||||
restart_program()
|
||||
|
||||
app = Gallery()
|
||||
def action_toggle_inspector(self) -> None:
|
||||
if not args.inspect_layout:
|
||||
return
|
||||
# importing the inspector adds instrumentation which can slow down startup
|
||||
from .inspector import Inspector
|
||||
inspector = self.query_one(Inspector)
|
||||
inspector.display = not inspector.display
|
||||
if not inspector.display:
|
||||
inspector.picking = False
|
||||
|
||||
|
||||
app = GalleryApp()
|
||||
|
||||
if args.restart_on_changes:
|
||||
restart_on_changes(app)
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run()
|
||||
|
Loading…
Reference in New Issue
Block a user