Implements recently used {directory,files} in {assets,application} windows & file dialogues.

libgui/GuiFrame.py:GuiSubMenuDecorator(): added.
libgui/GuiFrame.py:loadMenus(): process submenu menu items.
libroar/RoarCanvasCommandsFile.py:{_{load,push}Recent,canvasOpenRecent}(): initial implementation.
libroar/RoarCanvasCommandsFile.py:_import{,File}(): return pathname along w/ rc.
libroar/RoarCanvasCommandsFile.py:canvas{Open,SaveAs}(): call _pushRecent() post-{open,save}.
libroar/RoarCanvasCommandsFile.py:__init__(): updated.
librtl/RtlPlatform.py: added.
librtl/RtlPlatform.py:getLocalConfPathName(): initial implementation.
roar.py: manually call _loadRecent() & _pushRecent() post-import.
assets/text/TODO: updated.
This commit is contained in:
Lucio Andrés Illanes Albornoz 2019-09-14 15:16:57 +02:00
parent 075bff0644
commit bdc8bcd494
5 changed files with 83 additions and 10 deletions

View File

@ -13,8 +13,7 @@ High-priority list:
1) geometric primitives: arrow, circle, cloud/speech bubble, curve, heart, hexagon, line, pentagon, polygon, rhombus, triangle, square, star 1) geometric primitives: arrow, circle, cloud/speech bubble, curve, heart, hexagon, line, pentagon, polygon, rhombus, triangle, square, star
2) region filters: crop, duplicate, erase, fill, invert, measure, pick, rotate, scale, select, shift, slice, tile, translate 2) region filters: crop, duplicate, erase, fill, invert, measure, pick, rotate, scale, select, shift, slice, tile, translate
3) text tool: a) allow navigating w/ cursor keys b) Unicode set key & GUI w/ MRU 3) text tool: a) allow navigating w/ cursor keys b) Unicode set key & GUI w/ MRU
4) GUI: {de,in}crease cell size 4) GUI: {de,in}crease cell size on <Ctrl> <Mouse Wheel>
5) GUI: MRU {directories,files} 5) cleanup & refactor
6) cleanup & refactor
vim:ff=dos tw=0 vim:ff=dos tw=0

View File

@ -39,6 +39,17 @@ def GuiSelectDecorator(idx, caption, label, icon, accel, initialState):
return targetObject return targetObject
return GuiSelectDecoratorOuter return GuiSelectDecoratorOuter
# }}} # }}}
# {{{ GuiSubMenuDecorator(targetObject)
def GuiSubMenuDecorator(caption, label, icon, accel, initialState):
def GuiSubMenuDecoratorOuter(targetObject):
if callable(targetObject):
if not hasattr(targetObject, "attrDict"):
setattr(targetObject, "attrDict", [])
setattr(targetObject, "isSubMenu", True)
targetObject.attrDict = {"caption": caption, "label": label, "icon": icon, "accel": accel, "initialState": initialState, "id": None, "menu":None}
return targetObject
return GuiSubMenuDecoratorOuter
# }}}
# #
# Non-items (0xf000-0xffff) # Non-items (0xf000-0xffff)
@ -99,6 +110,9 @@ class GuiFrame(wx.Frame):
self.itemsById[menuItem.attrDict["id"]] = menuItem self.itemsById[menuItem.attrDict["id"]] = menuItem
if hasattr(menuItem, "isSelect"): if hasattr(menuItem, "isSelect"):
menuItemWindow = menuWindow.AppendRadioItem(menuItem.attrDict["id"], menuItem.attrDict["label"], menuItem.attrDict["caption"]) menuItemWindow = menuWindow.AppendRadioItem(menuItem.attrDict["id"], menuItem.attrDict["label"], menuItem.attrDict["caption"])
elif hasattr(menuItem, "isSubMenu"):
menuItem.attrDict["menu"] = wx.Menu()
menuItemWindow = menuWindow.AppendSubMenu(menuItem.attrDict["menu"], menuItem.attrDict["label"], menuItem.attrDict["caption"])
else: else:
menuItemWindow = menuWindow.Append(menuItem.attrDict["id"], menuItem.attrDict["label"], menuItem.attrDict["caption"]) menuItemWindow = menuWindow.Append(menuItem.attrDict["id"], menuItem.attrDict["label"], menuItem.attrDict["caption"])
if menuItem.attrDict["accel"] != None: if menuItem.attrDict["accel"] != None:

View File

@ -16,7 +16,8 @@ try:
except ImportError: except ImportError:
haveUrllib = False haveUrllib = False
from GuiFrame import GuiCommandDecorator, NID_MENU_SEP from GuiFrame import GuiCommandDecorator, GuiSubMenuDecorator, NID_MENU_SEP
from RtlPlatform import getLocalConfPathName
import io, os, wx import io, os, wx
class RoarCanvasCommandsFile(): class RoarCanvasCommandsFile():
@ -39,7 +40,7 @@ class RoarCanvasCommandsFile():
with wx.MessageDialog(self.parentCanvas, "Error: {}".format(error), "", wx.OK | wx.OK_DEFAULT) as dialog: with wx.MessageDialog(self.parentCanvas, "Error: {}".format(error), "", wx.OK | wx.OK_DEFAULT) as dialog:
dialogChoice = dialog.ShowModal() dialogChoice = dialog.ShowModal()
self.parentCanvas.SetCursor(wx.Cursor(wx.NullCursor)) self.parentCanvas.SetCursor(wx.Cursor(wx.NullCursor))
return rc return rc, newPathName
# }}} # }}}
# {{{ _importFile(self, f, newDirty, wildcard) # {{{ _importFile(self, f, newDirty, wildcard)
def _importFile(self, f, newDirty, wildcard): def _importFile(self, f, newDirty, wildcard):
@ -47,11 +48,19 @@ class RoarCanvasCommandsFile():
if self.lastDir != None: if self.lastDir != None:
dialog.SetDirectory(self.lastDir) dialog.SetDirectory(self.lastDir)
if dialog.ShowModal() == wx.ID_CANCEL: if dialog.ShowModal() == wx.ID_CANCEL:
return False return False, None
elif self._promptSaveChanges(): elif self._promptSaveChanges():
pathName = dialog.GetPath(); self.lastDir = os.path.dirname(pathName); pathName = dialog.GetPath(); self.lastDir = os.path.dirname(pathName);
return self._import(f, newDirty, pathName) return self._import(f, newDirty, pathName)
# }}} # }}}
# {{{ _loadRecent(self)
def _loadRecent(self):
localConfFileName = getLocalConfPathName("Recent.lst")
if os.path.exists(localConfFileName):
with open(localConfFileName, "r", encoding="utf-8") as inFile:
for lastFile in inFile.readlines():
self._pushRecent(lastFile.rstrip("\r\n"), False)
# }}}
# {{{ _promptSaveChanges(self) # {{{ _promptSaveChanges(self)
def _promptSaveChanges(self): def _promptSaveChanges(self):
if self.parentCanvas.dirty: if self.parentCanvas.dirty:
@ -69,6 +78,24 @@ class RoarCanvasCommandsFile():
else: else:
return True return True
# }}} # }}}
# {{{ _pushRecent(self, pathName, serialise=True)
def _pushRecent(self, pathName, serialise=True):
menuItemId = wx.NewId()
if not pathName in [l["pathName"] for l in self.lastFiles]:
numLastFiles = len(self.lastFiles) if self.lastFiles != None else 0
if (numLastFiles + 1) > 8:
self.canvasOpenRecent.attrDict["menu"].Delete(self.lastFiles[0]["menuItemId"])
del self.lastFiles[0]
menuItemWindow = self.canvasOpenRecent.attrDict["menu"].Append(menuItemId, "{}".format(pathName), pathName)
self.parentFrame.menuItemsById[self.canvasOpenRecent.attrDict["id"]].Enable(True)
self.parentFrame.Bind(wx.EVT_MENU, lambda event: self.canvasOpenRecent(event, pathName), menuItemWindow)
self.lastFiles += [{"menuItemId":menuItemId, "menuItemWindow":menuItemWindow, "pathName":pathName}]
if serialise:
localConfFileName = getLocalConfPathName("Recent.lst")
with open(localConfFileName, "w", encoding="utf-8") as outFile:
for lastFile in [l["pathName"] for l in self.lastFiles]:
print(lastFile, file=outFile)
# }}}
# {{{ canvasExit(self, event) # {{{ canvasExit(self, event)
@GuiCommandDecorator("Exit", "E&xit", None, [wx.ACCEL_CTRL, ord("X")], None) @GuiCommandDecorator("Exit", "E&xit", None, [wx.ACCEL_CTRL, ord("X")], None)
@ -197,7 +224,17 @@ class RoarCanvasCommandsFile():
def canvasImportmIRC(pathName): def canvasImportmIRC(pathName):
rc, error = self.parentCanvas.canvas.importStore.importTextFile(pathName) rc, error = self.parentCanvas.canvas.importStore.importTextFile(pathName)
return (rc, error, self.parentCanvas.canvas.importStore.outMap, pathName, self.parentCanvas.canvas.importStore.inSize) return (rc, error, self.parentCanvas.canvas.importStore.outMap, pathName, self.parentCanvas.canvas.importStore.inSize)
self._importFile(canvasImportmIRC, False, "mIRC art files (*.txt)|*.txt|All Files (*.*)|*.*") rc, newPathName = self._importFile(canvasImportmIRC, False, "mIRC art files (*.txt)|*.txt|All Files (*.*)|*.*")
if rc:
self._pushRecent(newPathName)
# }}}
# {{{ canvasOpenRecent(self, event, pathName=None)
@GuiSubMenuDecorator("Open Recent", "Open &Recent", None, None, False)
def canvasOpenRecent(self, event, pathName=None):
def canvasImportmIRC(pathName):
rc, error = self.parentCanvas.canvas.importStore.importTextFile(pathName)
return (rc, error, self.parentCanvas.canvas.importStore.outMap, pathName, self.parentCanvas.canvas.importStore.inSize)
self._import(canvasImportmIRC, False, pathName)
# }}} # }}}
# {{{ canvasSave(self, event) # {{{ canvasSave(self, event)
@GuiCommandDecorator("Save", "&Save", ["", wx.ART_FILE_SAVE], [wx.ACCEL_CTRL, ord("S")], None) @GuiCommandDecorator("Save", "&Save", ["", wx.ART_FILE_SAVE], [wx.ACCEL_CTRL, ord("S")], None)
@ -227,16 +264,17 @@ class RoarCanvasCommandsFile():
return False return False
else: else:
self.canvasPathName = dialog.GetPath(); self.lastDir = os.path.dirname(self.canvasPathName); self.canvasPathName = dialog.GetPath(); self.lastDir = os.path.dirname(self.canvasPathName);
return self.canvasSave(event, newDirty=True) if self.canvasSave(event, newDirty=True):
self._pushRecent(pathName)
# }}} # }}}
# #
# __init__(self) # __init__(self)
def __init__(self): def __init__(self):
self.imgurApiKey, self.lastDir = ImgurApiKey.imgurApiKey if haveImgurApiKey else None, None self.imgurApiKey, self.lastFiles, self.lastDir = ImgurApiKey.imgurApiKey if haveImgurApiKey else None, [], None
self.menus = ( self.menus = (
("&File", ("&File",
self.canvasNew, self.canvasOpen, self.canvasSave, self.canvasSaveAs, NID_MENU_SEP, self.canvasNew, self.canvasOpen, self.canvasOpenRecent, self.canvasSave, self.canvasSaveAs, NID_MENU_SEP,
self.canvasExportAsAnsi, self.canvasExportToClipboard, self.canvasExportImgur, self.canvasExportPastebin, self.canvasExportAsPng, NID_MENU_SEP, self.canvasExportAsAnsi, self.canvasExportToClipboard, self.canvasExportImgur, self.canvasExportPastebin, self.canvasExportAsPng, NID_MENU_SEP,
self.canvasImportAnsi, self.canvasImportFromClipboard, self.canvasImportSauce, NID_MENU_SEP, self.canvasImportAnsi, self.canvasImportFromClipboard, self.canvasImportSauce, NID_MENU_SEP,
self.canvasExit, self.canvasExit,

16
librtl/RtlPlatform.py Normal file
View File

@ -0,0 +1,16 @@
#!/usr/bin/env python3
#
# RtlPlatform.py
# Copyright (c) 2018, 2019 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>
# This project is licensed under the terms of the MIT licence.
#
import os, platform
# {{{ getLocalConfPathName(*args)
def getLocalConfPathName(*args):
vname = "LOCALAPPDATA" if platform.system() == "Windows" else "HOME"
return os.path.join(os.getenv(vname), "roar", *args)
# }}}
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120

View File

@ -9,13 +9,18 @@ import os, sys
["libcanvas", "libgui", "libroar", "librtl", "libtools"]] ["libcanvas", "libgui", "libroar", "librtl", "libtools"]]
from RoarClient import RoarClient from RoarClient import RoarClient
from RtlPlatform import getLocalConfPathName
import wx import wx
# #
# Entry point # Entry point
def main(*argv): def main(*argv):
localConfDirName = getLocalConfPathName()
if not os.path.exists(localConfDirName):
os.makedirs(localConfirName)
wxApp, roarClient = wx.App(False), RoarClient(None) wxApp, roarClient = wx.App(False), RoarClient(None)
argv0, argv = argv[0], argv[1:] argv0, argv = argv[0], argv[1:]
roarClient.canvasPanel.commands._loadRecent()
if len(argv) >= 1: if len(argv) >= 1:
if (len(argv) >= 2) and (argv[1].endswith(".lst")): if (len(argv) >= 2) and (argv[1].endswith(".lst")):
roarClient.assetsWindow._load_list(argv[1]) roarClient.assetsWindow._load_list(argv[1])
@ -24,6 +29,7 @@ def main(*argv):
if rc: if rc:
roarClient.canvasPanel.update(roarClient.canvasPanel.canvas.importStore.inSize, False, roarClient.canvasPanel.canvas.importStore.outMap) roarClient.canvasPanel.update(roarClient.canvasPanel.canvas.importStore.inSize, False, roarClient.canvasPanel.canvas.importStore.outMap)
roarClient.canvasPanel.commands.update(pathName=argv[0], undoLevel=-1) roarClient.canvasPanel.commands.update(pathName=argv[0], undoLevel=-1)
roarClient.canvasPanel.commands._pushRecent(argv[0])
else: else:
print("error: {}".format(error), file=sys.stderr) print("error: {}".format(error), file=sys.stderr)
wxApp.MainLoop() wxApp.MainLoop()