Commit Graph

297 Commits

Author SHA1 Message Date
Isaiah Odhner
c3763523bd Visually debug IndexError...
The canvas size isn't getting updated (fully) when loading a document.
2023-04-20 14:45:11 -04:00
Isaiah Odhner
5958ba348b OK maybe this isn't so robust... 2023-04-20 14:42:51 -04:00
Isaiah Odhner
51c370dc24 Instead of clearing, prevent filling filename input in Open dialog
Prevent the filename input from being populated in the first place,
instead of resetting after its unintentionally populated when the
directory tree is expanded.

Nip it in the bud. Head it off at the pass. Stop it at the source.

It still needs this new flag to be cleared on a timer, but at least this
timer is near the code for the other timers it needs to trigger after.

Explicitly set filename for Save As dialog, which SHOULD be populated.
2023-04-20 14:42:51 -04:00
Isaiah Odhner
801c147d4c Clear filename input in Open dialog, which gets set unintentionally 2023-04-20 13:00:05 -04:00
Isaiah Odhner
ec4d044f8a Handle FileNotFoundError coming from os.path.samefile 2023-04-20 12:08:03 -04:00
Isaiah Odhner
61d1532552 Prevent multiple character selector dialogs from opening at once 2023-04-20 11:54:42 -04:00
Isaiah Odhner
74c4af1a5b Refactor meta character mapping to use match 2023-04-20 01:26:00 -04:00
Isaiah Odhner
7cdb35a4ae Start defining an enlarged view for certain characters 2023-04-20 01:25:43 -04:00
Isaiah Odhner
b955aaf361 Input or pick character to draw with 2023-04-20 01:21:06 -04:00
Isaiah Odhner
8727ed27de Use .dialog_window, already specified in one place, instead of .dialog, scattered about 2023-04-20 00:28:45 -04:00
Isaiah Odhner
29bc94efbc Ignore RuntimeError "cannot join current thread" 2023-04-19 21:45:18 -04:00
Isaiah Odhner
ac10d5e500 Tweak error messages to use colons for clarity 2023-04-19 21:34:29 -04:00
Isaiah Odhner
c659418240 Clean up attempt at more optimal color inverting
I don't want to bother importing Rich's Color class in addition to
Textual's Color class.

This also doesn't work, which might be the fastest if it worked:

    style.color.triplet.red = 255 - style.color.triplet.red
    style.color.triplet.green = 255 - style.color.triplet.green
    style.color.triplet.blue = 255 - style.color.triplet.blue
    style.bgcolor.triplet.red = 255 - style.bgcolor.triplet.red
    style.bgcolor.triplet.green = 255 - style.bgcolor.triplet.green
    style.bgcolor.triplet.blue = 255 - style.bgcolor.triplet.blue
2023-04-19 21:20:10 -04:00
Isaiah Odhner
bf16e60509 Clean up old magnifier preview approach 2023-04-19 21:14:07 -04:00
Isaiah Odhner
bd8ebad377 Implement magnifier preview 2023-04-19 21:08:59 -04:00
Isaiah Odhner
0026c06268 Fix inconsistent indentation 2023-04-19 19:58:07 -04:00
Isaiah Odhner
9120d49546 Implement the magnifier tool 2023-04-19 19:44:57 -04:00
Isaiah Odhner
ad6d799db9 Note reset command to recover from bad terminal state 2023-04-19 19:09:02 -04:00
Isaiah Odhner
dd5e646dfe Prompt to save changes before reloading program 2023-04-19 16:00:43 -04:00
Isaiah Odhner
509618c1be Try to clean up the file change observer when restarting
This is all theoretical.
2023-04-19 15:19:27 -04:00
Isaiah Odhner
140ff15ff1 Restart the app on changes 2023-04-19 14:27:12 -04:00
Isaiah Odhner
7b0eaff108 Reload the app with F2, not F4
I'm dumb, I forgot the app uses F4.
2023-04-19 02:45:55 -04:00
Isaiah Odhner
dfa4212548 Fix terminal state after reloading and exiting 2023-04-19 02:23:29 -04:00
Isaiah Odhner
f4075282ce Reload the app with F4 2023-04-19 02:08:01 -04:00
Isaiah Odhner
655d42e414 Change shortcut label for exiting
Alt+F4 is handled by the window manager, we can't handle it.
2023-04-19 00:37:59 -04:00
Isaiah Odhner
4cbafea3cb Show accelerators/shortcuts in menus 2023-04-18 23:34:05 -04:00
Isaiah Odhner
1659f2d75b Improve error handling for saving files 2023-04-18 18:56:29 -04:00
Isaiah Odhner
b8c7e0eb72 Add all of the menu items from MS Paint 2023-04-18 18:56:29 -04:00
Isaiah Odhner
ac8c3819cf Some things aren't translated yet 2023-04-18 18:55:45 -04:00
Isaiah Odhner
c5f7c9f387 Rename "Rectangular Select" to "Select" to match MS Paint and for localization 2023-04-18 18:55:45 -04:00
Isaiah Odhner
f1a4b9736e Improve error handling for saving and loading files 2023-04-18 18:55:45 -04:00
Isaiah Odhner
fcf44a8b94 Handle errors when saving a file 2023-04-18 18:55:44 -04:00
Isaiah Odhner
e715a28e59 Fix error when hitting OK button with no callback 2023-04-18 04:04:46 -04:00
Isaiah Odhner
8c4a5bf583 Handle errors when opening a file 2023-04-18 04:04:46 -04:00
Isaiah Odhner
2d3f05ff12 Rename "Redo" to "Repeat" to match MS Paint and for localization 2023-04-18 03:48:47 -04:00
Isaiah Odhner
a9fd9d090c Enable localization! 2023-04-18 03:31:47 -04:00
Isaiah Odhner
5e994fbc91 Move command line argument parsing to the top
This will make it possible to load localization data for a language
defined by a command-line argument, throughout the program.

Unfortunately this separates the usage of the arguments from their
definitions by a wide margin, making it harder to edit, especially
with AI autocomplete. For now. I could refactor things, either move
the bulk of this file to separate files, or define a configure_app
function up top to use down below.
2023-04-18 03:31:47 -04:00
Isaiah Odhner
8971122581 Wrap strings in _() function for localization 2023-04-18 03:31:47 -04:00
Isaiah Odhner
973f67240d WIP: i18n
Giving up on the python translation of the RC file parsing and pre-processing for now, in favor of simply parsing the JS files already generated, which is a much simpler task.
2023-04-18 03:31:47 -04:00
Isaiah Odhner
baf804f2b1 Fix: use title argument in warning_message_box 2023-04-18 03:08:58 -04:00
Isaiah Odhner
b4468d3a76 Update some comments about ANSI I/O 2023-04-18 02:55:11 -04:00
Isaiah Odhner
87f8faf956 Use choices option for expressing --theme 2023-04-18 01:06:45 -04:00
Isaiah Odhner
6fbcbf9ec3 Refactor ync flag to button_types argument, to support OK-only dialogs 2023-04-17 23:32:20 -04:00
Isaiah Odhner
d950295df7 Simply close the Open dialog if you select the open file 2023-04-17 23:09:13 -04:00
Isaiah Odhner
8ec24a8fdc Prompt to save changes when unloading a document
- Confirm discarding changes for Open, New, or Exit, including for
  exit via Ctrl+C which was previously handled by a built-in binding.
- Await Save As dialog closing, including when Save triggers Save As.
  This is my first time using asynchronous features in Python,
  (as far as I remember,) so it's a bit messy.
- Make DialogWindow callback also for Cancel, which means all
  DialogWindow usage sites care what button is selected.
- Send RequestClose event for Esc key.
2023-04-17 23:09:13 -04:00
Isaiah Odhner
0125374bba Ctrl+MMB to colorize without adding borders to inspect layout without modifying it 2023-04-17 03:12:30 -04:00
Isaiah Odhner
4ee5efe85c Make a filled Unicode warning icon with a border 2023-04-17 03:12:30 -04:00
Isaiah Odhner
a948d7d945 Note parallelogram candidates for eraser icon 2023-04-17 01:57:27 -04:00
Isaiah Odhner
22a251276b Use Unicode for warning icon text art 2023-04-17 01:45:20 -04:00
Isaiah Odhner
5c289e05a8 Add dev helper to inspect layout 2023-04-17 01:21:19 -04:00
Isaiah Odhner
357b68d624 Show file name only, not full path, in Header 2023-04-16 21:12:44 -04:00
Isaiah Odhner
728b4c53b9 Fix Open/Save As dialog starting location when file opened with relative path
The directory tree wasn't expanded because it was searching for e.g.
LICENSE.txt at the root of the filesystem (or perhaps AS the root?)
2023-04-16 21:12:03 -04:00
Isaiah Odhner
4ef6c07826 Add Header to show the current file name 2023-04-16 21:05:55 -04:00
Isaiah Odhner
a02431d19e Add --theme option to CLI 2023-04-16 20:34:56 -04:00
Isaiah Odhner
650584d4b2 Add usage section to readme 2023-04-16 19:38:53 -04:00
Isaiah Odhner
8929ed14b6 Clear screen during development to avoid seeing fixed errors 2023-04-16 18:54:49 -04:00
Isaiah Odhner
cb6b4403a3 Handle passing arguments via textual run
It took a while to figure out this magic.

`textual run --help` says:

>  If you are running a file and want to pass command line arguments, wrap the
>  filename and arguments in quotes:
>
>      textual run "foo.py arg --option"

But it doesn't describe how to handle those arguments.
2023-04-16 16:01:24 -04:00
Isaiah Odhner
3f23a13fe1 Fix mouse coordinates for brush preview when scrolled
Don't hackily offset mouse coordinates when mouse not down
2023-04-16 15:22:38 -04:00
Isaiah Odhner
23ca2b7113 Refactor tool button CSS class handling, and remove unused tool_button class 2023-04-16 02:08:07 -04:00
Isaiah Odhner
79ef514eb2 Make sure not to save the document with a brush preview 2023-04-16 00:50:12 -04:00
Isaiah Odhner
7aab466964 Add Cancel button to Open dialog 2023-04-16 00:11:59 -04:00
Isaiah Odhner
d4becd2da0 Refactor dumb button handling using new class DialogWindow 2023-04-16 00:11:59 -04:00
Isaiah Odhner
ddd89d367b Hide brush preview when you stop hovering over the canvas 2023-04-15 23:45:44 -04:00
Isaiah Odhner
faabe2c88e Play bell/beep when prompting file overwrite confirmation 2023-04-15 23:07:22 -04:00
Isaiah Odhner
ba3ecaa39a Close window only for known buttons 2023-04-15 22:40:10 -04:00
Isaiah Odhner
da3d3b0f06 Rename Save As dialog IDs to match Open dialog IDs
It's a bit verbose, but for Open, I wanted the _dialog part since "open"
can be both a verb and an adjective, and I didn't like it reading as an
adjective. It doesn't technically disambiguate it, but it reads better.

Verb "[to] open", noun "[dialog to] open", adjective "[part of the dialog to] open"
Adjective "[is] open", noun "[dialog that is] open", adjective "[part of the dialog that is] open"

Anyways this commit just makes it consistent.
Perhaps I could use classes more in place of IDs.
2023-04-15 22:37:15 -04:00
Isaiah Odhner
e988bf787f Move window layout fix to Window 2023-04-15 22:04:15 -04:00
Isaiah Odhner
8f5bbe9635 Fix incorrect window layouts 2023-04-15 21:47:14 -04:00
Isaiah Odhner
774547e6f8 Fix opening files outside the current directory (with Open dialog) 2023-04-15 21:19:07 -04:00
Isaiah Odhner
f51f1d9b8c Implement File > Open dialog 2023-04-15 21:11:44 -04:00
Isaiah Odhner
4334d60681 Add File > Exit menu item
I'm leaving the "Quit" naming in the keybindings, because it's Ctrl+Q,
and if the keybindings are ever displayed, that's the mnemonic.
2023-04-15 20:53:53 -04:00
Isaiah Odhner
7d433cc27b Refactor expand_directory_tree and make it a method 2023-04-15 20:39:00 -04:00
Isaiah Odhner
ce2fbe44bb Allow browsing the whole filesystem, but expand to the current directory
This relies on some API internals: tree._get_label_region and node._line
2023-04-15 20:27:19 -04:00
Isaiah Odhner
63f947e7f4 Fix confirmation dialog button functionality 2023-04-15 02:18:36 -04:00
Isaiah Odhner
e814dd6637 Add ASCII art warning icon to confirmation dialog 2023-04-15 01:59:16 -04:00
Isaiah Odhner
b5e0ec8438 Confirm overwriting files
A Textual layout bug is unfortunately making the Yes button HUGE,
and the No button INVISIBLE, until you mouse over the dialog, which is
pretty funny...
"<file> already exists. Do you want to replace it? [Yes]"
2023-04-15 01:49:08 -04:00
Isaiah Odhner
a5b217b3cd Add directory tree to Save As dialog 2023-04-15 01:25:58 -04:00
Isaiah Odhner
c2e86d5eae Implement Save As dialog 2023-04-15 00:57:43 -04:00
Isaiah Odhner
20e2f1a52d Fix brush preview artifacts when undoing/redoing 2023-04-14 02:21:12 -04:00
Isaiah Odhner
98d04f55f6 Add File > New support 2023-04-14 01:51:27 -04:00
Isaiah Odhner
0697784d56 Enable toggling tools/colors boxes from the View menu 2023-04-14 01:46:07 -04:00
Isaiah Odhner
16d3b84015 Set up argparse and make --ascii-only-icons an option 2023-04-14 01:15:42 -04:00
Isaiah Odhner
a857845281 Add ascii-only icons mode 2023-04-14 01:10:09 -04:00
Isaiah Odhner
fda94c31f8 Implement brush previews 2023-04-13 23:07:46 -04:00
Isaiah Odhner
44fe270463 Note some alternate selection tool icons using Braille
These are pretty good candidates, paired together.
For the Free-Form Select icon (⢼⠮), I'm specifically imitating the
asymmetrical star shape from MS Paint.
2023-04-13 23:07:46 -04:00
Isaiah Odhner
baaf0ee8e9 Pick color while dragging 2023-04-13 19:02:44 -04:00
Isaiah Odhner
611e7f10c9 Implement Pick Color tool 2023-04-13 18:54:51 -04:00
Isaiah Odhner
b805d9a488 Implement eraser and airbrush tools 2023-04-13 18:48:24 -04:00
Isaiah Odhner
155df6a998 Collect more symbols 2023-04-13 10:02:31 -04:00
Isaiah Odhner
3652b2bd8e Add flood fill support
* Implemented the Fill With Color tool using the algorithm described as
  "combined-scan-and-fill span filler" on Wikipedia.
* I added handling for the affected region being None, which turned
out more complicated than I would like...
  Some cases may be able to be simplified or removed.
* Also, I moved event.stop() to the top so I don't need to call it in
multiple places when there are multiple return points.
2023-04-13 02:48:32 -04:00
Isaiah Odhner
3dbbbc1c5f Refactor away assumption that tools will affect the document at the cursor
You could imagine having a brush with momentum, that swings around the
mouse without always reaching it. But it's just generally clearer to
not have an inadequate initial region that's then extended.
2023-04-13 01:21:33 -04:00
Isaiah Odhner
de47a62833 Implement line, rectangle, and rounded rectangle tools 2023-04-13 00:52:44 -04:00
Isaiah Odhner
50c3278264 Use tool names from MS Paint, consistently 2023-04-13 00:35:49 -04:00
Isaiah Odhner
303d6942f4 Switch out fill tool icon to avoid text row offset artifacts 2023-04-13 00:32:03 -04:00
Isaiah Odhner
5b1c16ddc3 Use wide A character for text tool icon, centering it 2023-04-13 00:32:03 -04:00
Isaiah Odhner
e11cbb0748 Convert keyboard handling to use BINDINGS
https://textual.textualize.io/guide/input/#bindings
2023-04-12 23:57:11 -04:00
Isaiah Odhner
d748c380b4 Rename all keyboard activated functions to action_* 2023-04-12 23:32:30 -04:00
Isaiah Odhner
b779059208 Add non-functional menu bar 2023-04-12 20:54:21 -04:00
Isaiah Odhner
4fa7784651 Toggle dark mode with Ctrl+D 2023-04-12 15:32:16 -04:00
Isaiah Odhner
5796c5c8b3 Give inset appearance to color wells / selected color 2023-04-12 15:31:52 -04:00
Isaiah Odhner
083b169257 Add ellipse tool support 2023-04-11 22:30:46 -04:00
Isaiah Odhner
f31069e3b2 Add type hints for undos/redos lists 2023-04-11 22:30:46 -04:00
Isaiah Odhner
67d256883d Refactor: don't store reference to the live document in Action
It feels in danger of accidental usage there, or preventing GC.
2023-04-11 21:45:00 -04:00
Isaiah Odhner
30cddbbde5 Save and load ANSI files 2023-04-11 21:18:11 -04:00
Isaiah Odhner
3e84ae7e17 Disable region update debug 2023-04-11 15:20:31 -04:00
Isaiah Odhner
6d5430ad2e Fix error due to action regions exceeding canvas bounds 2023-04-11 14:41:58 -04:00
Isaiah Odhner
0aaa9db839 Make region update debug a flag 2023-04-11 14:37:32 -04:00
Isaiah Odhner
15db3f4538 Store only sub-image for undo/redo 2023-04-11 14:31:50 -04:00
Isaiah Odhner
6d17f085f5 Debug: show regions when undoing/redoing (currently the whole canvas) 2023-04-11 13:49:03 -04:00
Isaiah Odhner
4fa7dda9a0 Clarify doc string for on_button_pressed
Disambiguate with on_key.

Alternately I could say "Called when a button widget is pressed."
2023-04-11 13:47:50 -04:00
Isaiah Odhner
e3e04c59a8 Implement redo
Ctrl+Shift+Z isn't working but Ctrl+Y and F4 are.
2023-04-11 13:40:31 -04:00
Isaiah Odhner
af6bfb4e45 Implement undo 2023-04-11 13:21:19 -04:00
Isaiah Odhner
4c2fc00e45 Select pencil when trying to draw with unimplemented tool 2023-04-11 12:30:47 -04:00
Isaiah Odhner
470e6e119e Make brush tool draw with a diameter 2023-04-11 12:24:25 -04:00
Isaiah Odhner
1f3809999e Remove some garbage unrelated symbols
I mean, let's be honest, most of these symbols are garbage candidates.
But these ones I accidentally left from trying to get ChatGPT to find
emoji for me.
More helpful were https://emojidb.org/ and http://shapecatcher.com/
2023-04-11 12:13:50 -04:00
Isaiah Odhner
5340539133 Refactor bresenham_walk into a generator 2023-04-11 12:01:40 -04:00
Isaiah Odhner
a66df997bb Toggle the color palette with Ctrl+W
Doesn't work in VS Code's terminal, but that's OK.
It works in Ubuntu's Terminal app.
2023-04-11 11:48:08 -04:00
Isaiah Odhner
4d2b667ecb Toggle the tools box with Ctrl+T 2023-04-11 11:40:47 -04:00
Isaiah Odhner
d64a011bb8 Remove extraneous refresh on mount 2023-04-11 11:08:12 -04:00
Isaiah Odhner
ab76aacff3 Stop bubbling of canvas tool events 2023-04-11 11:02:09 -04:00
Isaiah Odhner
c7e27bc3cb Cache canvas widget reference 2023-04-11 11:02:09 -04:00
Isaiah Odhner
ad111e5d6c Refactor: extract tool handling from Canvas
I wanted to avoid duplicating tool-related state between PaintApp and
Canvas, and prepare for adding different tools with more state and which
will want to live in a separate file.

This makes it slower, when running with `textual run --dev paint.py`;
when running with `python3 paint.py`, it's fine.
When running in dev mode with `textual console` devtool connected, it's
extremely much slower. But if it was faster, you'd have more messages
to scroll through, ha. So it's a tradeoff.*
*Ideally you want it to be fast and for the logs to be compacted.

In the future, I could bypass the message system for performance, but
for now I think it's better to stay idiomatic.
2023-04-11 11:02:09 -04:00
Isaiah Odhner
cb37f50564 Fix mouse move event coordinates 2023-04-11 08:48:02 -04:00
Isaiah Odhner
e2c9b4b66c Improve layout 2023-04-11 08:47:47 -04:00
Isaiah Odhner
7d1afed296 Define dimensions for Canvas widget 2023-04-11 08:46:57 -04:00
Isaiah Odhner
abd6468ce8 Refactor related image data into a class 2023-04-11 08:07:02 -04:00
Isaiah Odhner
e19cdff5e7 Exit with Ctrl+Q, in preparation for overriding Ctrl+C 2023-04-11 07:52:26 -04:00
Isaiah Odhner
3844667ff7 Hide characters, use only colors on canvas 2023-04-11 00:48:29 -04:00
Isaiah Odhner
32ac1bd92c Make drawing responsive! 2023-04-11 00:46:07 -04:00
Isaiah Odhner
c3035d171f Fix up the app layout scrollbar situation
- Remove scrollbar from root
- Fix extra height below color palette due to vertical layout giving even heights
- Add container around canvas to make canvas scrollable
2023-04-11 00:19:07 -04:00
Isaiah Odhner
ba0d80bc0d Implement color selection 2023-04-10 23:56:53 -04:00
Isaiah Odhner
1811e1c41c Add palette 2023-04-10 23:56:53 -04:00
Isaiah Odhner
43b827720b Use Bresenham's line algorithm 2023-04-10 22:24:22 -04:00
Isaiah Odhner
f6e9d6676e Capture the mouse when drawing on the canvas 2023-04-10 22:16:50 -04:00
Isaiah Odhner
f4eb6eb1f0 Add bounds checks 2023-04-10 22:16:33 -04:00
Isaiah Odhner
61a25a85bf Rename width/height properties 2023-04-10 22:07:25 -04:00
Isaiah Odhner
8168ef78a3 Fix timing of update_canvas on mouse down 2023-04-10 22:03:31 -04:00
Isaiah Odhner
42ae61c9ab Add color support to the canvas, very inefficiently 2023-04-10 21:51:26 -04:00
Isaiah Odhner
ffca83c1c6 Support drawing, basically 2023-04-10 21:30:11 -04:00
Isaiah Odhner
69ca7eefdb Add a Canvas widget 2023-04-10 21:25:31 -04:00
Isaiah Odhner
b64869eae4 Let buttons fall back to the original color when deselected 2023-04-10 20:52:01 -04:00
Isaiah Odhner
3f8a652fe2 Implement selected_tool state 2023-04-10 19:27:11 -04:00
Isaiah Odhner
6ecdfe3532 Move tool buttons into a ToolsBox container and improve layout 2023-04-10 18:21:09 -04:00
Isaiah Odhner
43169d7df2 Make buttons gray instead of blue 2023-04-10 17:46:08 -04:00
Isaiah Odhner
99fcda2c53 Remove calculator logic/UI 2023-04-10 17:40:59 -04:00
Isaiah Odhner
ad4c94097a Add buttons for Paint tools 2023-04-10 17:29:04 -04:00
Isaiah Odhner
642bf3812c Rename calculator -> paint 2023-04-10 16:54:36 -04:00