diff --git a/.TODO b/.TODO deleted file mode 100644 index 1ce9cf2..0000000 --- a/.TODO +++ /dev/null @@ -1 +0,0 @@ -text bug: a) select text tool b) paste stuff c) undo d) artifacts diff --git a/assets/audio/roararab8.wav b/assets/audio/roararab8.wav new file mode 100644 index 0000000..b1d2029 Binary files /dev/null and b/assets/audio/roararab8.wav differ diff --git a/assets/audio/roarspoke11.wav b/assets/audio/roarspoke11.wav new file mode 100644 index 0000000..4ae5853 Binary files /dev/null and b/assets/audio/roarspoke11.wav differ diff --git a/assets/images/toolColoursFlip.png b/assets/images/toolColoursFlip.png new file mode 100644 index 0000000..991d12f Binary files /dev/null and b/assets/images/toolColoursFlip.png differ diff --git a/assets/images/toolHideAssetsWindow.png b/assets/images/toolHideAssetsWindow.png new file mode 100644 index 0000000..fe8c162 Binary files /dev/null and b/assets/images/toolHideAssetsWindow.png differ diff --git a/assets/images/toolShowAssetsWindow.png b/assets/images/toolShowAssetsWindow.png new file mode 100644 index 0000000..58a2cc3 Binary files /dev/null and b/assets/images/toolShowAssetsWindow.png differ diff --git a/assets/text/TODO b/assets/text/TODO index 1355111..6ae013f 100644 --- a/assets/text/TODO +++ b/assets/text/TODO @@ -1,26 +1,29 @@ -Low-priority list: -1) Implement ANSI CSI CU[BDPU] sequences & italic -2) Layers & layout (e.g. for comics, zines, etc.) -3) Implement instrumentation & unit tests, document -4) Open and toggle a reference image in the background -5) Client-Server or Peer-to-Peer realtime collaboration -6) Arbitrary {format,palette}s ({4,8} bit ANSI/mIRC, etc.) -7) {record,replay} {keyboard,mouse,...} events in debugging builds -8) Incremental auto{load,save} & {backup,restore} (needs Settings window) -9) Composition, parametrisation & keying of tools from higher-order operators (brushes, functions, filters, outlines, patterns & shaders) and unit tools -10) Sprites & scripted (Python?) animation on the basis of asset traits and {composable,parametrised} patterns (metric flow, particle system, rigging, ...) -11) Integrate ENNTool code in the form of OpenGL-based animation window (see 9) and 10)) - -High-priority list: -1) unit tools: arrow, {cloud,speech bubble}, curve, measure, pick, polygon, triangle, unicode -2) operators: rotate, scale, shift, slice, tile -3) cleanup & refactor, switch to GTK -4) GUI: +1) Finish Arabic/RTL text tool support +2) ANSI CSI CU[BDPU] sequences & italic +3) Operators: crop, scale, shift, slice +4) Documentation, instrumentation & unit tests +5) Layers & layout (e.g. for comics, zines, etc.) +6) Open and toggle a reference image in the background +7) Client-Server or Peer-to-Peer realtime collaboration +8) Arbitrary {format,palette}s ({4,8} bit ANSI/mIRC, etc.) +9) {record,replay} {keyboard,mouse,...} events in debugging builds +10) Incremental auto{load,save} & {backup,restore} (needs Settings window) +11) Unit tools: arrow, {cloud,speech bubble}, curve, measure, polygon, triangle +12) Integrate ENNTool code in the form of OpenGL-based animation window (see 13) and 14)) +13) Composition, parametrisation & keying of tools from higher-order operators (brushes, functions, filters, outlines, patterns & shaders) and unit tools +14) Sprites & scripted (Python?) animation on the basis of asset traits and {composable,parametrised} patterns (metric flow, particle system, rigging, ...) +15) GUI TODO list: a) replace logo w/ canvas panel in About dialogue b) purge MRU list menu item, remove files from MRU list if inaccessible c) Settings/Settings window (e.g. autosave, hide cursor on leaving window, ...) d) replace resize buttons w/ {-,edit box,+} buttons & lock button re: ratio (ty lol3) e) {copy,cut,delete,insert from,paste}, {edit asset in new canvas,import from {canvas,object}} -5) finish Arabic/RTL text implementation + +High-priority list: +1) a) select line tool b) set origin point c) move mouse about d) incr brush size e) set target point d) undo + a) new canvas/startup b) place rect c) move mouse d) undo status changes + a) text tool b) paste text c) undo +2) add hotkeys.txt mIRC art canvas to help menu +2) tools: erase, pick, unicode block elements vim:ff=dos tw=0 diff --git a/assets/text/hotkeys.txt b/assets/text/hotkeys.txt new file mode 100644 index 0000000..67b47e9 --- /dev/null +++ b/assets/text/hotkeys.txt @@ -0,0 +1,15 @@ + 0-9, 0-5, 6 Set foreground colour to #0-9, #10-15, transparent colour, resp. + 0-9, 0-5, 6 Set background colour to #0-9, #10-15, transparent colour, resp. + C U F L R E T Switch to circle, cursor, fill, line, rectangle, object, text tool + I Flip colours + N New canvas + O Open mIRC art file + S Save canvas as mIRC art file + X Exit + Y, Z Redo, undo, resp. + Break into Python debugger +(Canvas) , , , Move canvas cursor +(Canvas) , Apply current tool with foreground colour or initiate tool action (line and object tool) +(Canvas) Apply current tool with background colour +(Fill tool) , Fill entire region ignoring character cells +(Object tool) Move selection instead of cloning \ No newline at end of file diff --git a/assets/text/requirements.txt b/assets/text/requirements.txt new file mode 100644 index 0000000..9c558e3 --- /dev/null +++ b/assets/text/requirements.txt @@ -0,0 +1 @@ +. diff --git a/assets/tools/IrcMiRCARTBot.py b/assets/tools/IrcMiRCARTBot.py index 7e3e4c9..a1dd705 100755 --- a/assets/tools/IrcMiRCARTBot.py +++ b/assets/tools/IrcMiRCARTBot.py @@ -19,17 +19,14 @@ class IrcMiRCARTBot(IrcClient): """IRC<->MiRC2png bot""" imgurApiKey = ImgurApiKey.imgurApiKey - # {{{ ContentTooLargeException(Exception): Raised by _urlretrieveReportHook() given download size > 1 MB class ContentTooLargeException(Exception): pass - # }}} - # {{{ _dispatch001(self, message): Dispatch single 001 (RPL_WELCOME) + def _dispatch001(self, message): self._log("Registered on {}:{} as {}, {}, {}.".format(self.serverHname, self.serverPort, self.clientNick, self.clientIdent, self.clientGecos)) self._log("Attempting to join {} on {}:{}...".format(self.clientChannel, self.serverHname, self.serverPort)) self.queue("JOIN", self.clientChannel) - # }}} - # {{{ _dispatch353(self, message): Dispatch single 353 (RPL_NAMREPLY) + def _dispatch353(self, message): if message[4].lower() == self.clientChannel.lower(): for channelNickSpec in message[5].split(" "): @@ -38,20 +35,17 @@ class IrcMiRCARTBot(IrcClient): and len(channelNickSpec[1:]): self.clientChannelOps.append(channelNickSpec[1:].lower()) self._log("Authorising {} on {}".format(channelNickSpec[1:].lower(), message[4].lower())) - # }}} - # {{{ _dispatchJoin(self, message): Dispatch single JOIN message from server + def _dispatchJoin(self, message): self._log("Joined {} on {}:{}.".format(message[2].lower(), self.serverHname, self.serverPort)) self.clientNextTimeout = None; self.clientChannelRejoin = False; - # }}} - # {{{ _dispatchKick(self, message): Dispatch single KICK message from server + def _dispatchKick(self, message): if message[2].lower() == self.clientChannel.lower() \ and message[3].lower() == self.clientNick.lower(): self._log("Kicked from {} by {}, rejoining in 15 seconds".format(message[2].lower(), message[0])) self.clientNextTimeout = time.time() + 15; self.clientChannelRejoin = True; - # }}} - # {{{ _dispatchMode(self, message): Dispatch single MODE message from server + def _dispatchMode(self, message): if message[2].lower() == self.clientChannel.lower(): channelModeType = "+"; channelModeArg = 4; @@ -78,17 +72,14 @@ class IrcMiRCARTBot(IrcClient): channelAuthDel = channelAuthDel.lower() self._log("Deauthorising {} on {}".format(channelAuthDel, message[2].lower())) self.clientChannelOps.remove(channelAuthDel) - # }}} - # {{{ _dispatchNone(self): Dispatch None message from server + def _dispatchNone(self): self._log("Disconnected from {}:{}.".format(self.serverHname, self.serverPort)) self.close() - # }}} - # {{{ _dispatchPing(self, message): Dispatch single PING message from server + def _dispatchPing(self, message): self.queue("PONG", message[2]) - # }}} - # {{{ _dispatchPrivmsg(self, message): Dispatch single PRIVMSG message from server + def _dispatchPrivmsg(self, message): if message[2].lower() == self.clientChannel.lower() \ and message[3].startswith("!pngbot "): @@ -155,19 +146,16 @@ class IrcMiRCARTBot(IrcClient): os.remove(asciiTmpFilePath) if os.path.isfile(imgTmpFilePath): os.remove(imgTmpFilePath) - # }}} - # {{{ _dispatchTimer(self): Dispatch single client timer expiration + def _dispatchTimer(self): if self.clientChannelRejoin: self._log("Attempting to join {} on {}:{}...".format(self.clientChannel, self.serverHname, self.serverPort)) self.queue("JOIN", self.clientChannel) self.clientNextTimeout = time.time() + 15; self.clientChannelRejoin = True; - # }}} - # {{{ _log(self, msg): Log single message to stdout w/ timestamp + def _log(self, msg): print(time.strftime("%Y/%m/%d %H:%M:%S") + " " + msg) - # }}} - # {{{ _uploadToImgur(self, imgFilePath, imgName, imgTitle, apiKey): Upload single file to Imgur + def _uploadToImgur(self, imgFilePath, imgName, imgTitle, apiKey): with open(imgFilePath, "rb") as requestImage: requestImageData = requestImage.read() @@ -188,13 +176,11 @@ class IrcMiRCARTBot(IrcClient): return [200, responseDict.get("data").get("link")] else: return [responseHttp.status_code, responseHttp.text] - # }}} - # {{{ _urlretrieveReportHook(count, blockSize, totalSize): Limit downloads to 1 MB + def _urlretrieveReportHook(count, blockSize, totalSize): if (totalSize > pow(2,20)): raise IrcMiRCARTBot.ContentTooLargeException - # }}} - # {{{ connect(self, localAddr=None, preferFamily=0, timeout=None): Connect to server and (re)initialise w/ optional timeout + def connect(self, localAddr=None, preferFamily=0, timeout=None): self._log("Connecting to {}:{}...".format(self.serverHname, self.serverPort)) if super().connect(localAddr=localAddr, preferFamily=preferFamily, timeout=timeout): @@ -206,8 +192,7 @@ class IrcMiRCARTBot(IrcClient): return True else: return False - # }}} - # {{{ dispatch(self): Read, parse, and dispatch single line from server + def dispatch(self): while True: if self.clientNextTimeout: @@ -245,7 +230,7 @@ class IrcMiRCARTBot(IrcClient): self.clientHasPing = False elif serverMessage[1] == "PRIVMSG": self._dispatchPrivmsg(serverMessage) - # }}} + # # __init__(self, serverHname, serverPort="6667", clientNick="pngbot", clientIdent="pngbot", clientGecos="pngbot", clientChannel="#MiRCART"): initialisation method diff --git a/libcanvas/Canvas.py b/libcanvas/Canvas.py index bc652ab..2b8065c 100644 --- a/libcanvas/Canvas.py +++ b/libcanvas/Canvas.py @@ -9,12 +9,10 @@ from CanvasImportStore import CanvasImportStore from CanvasJournal import CanvasJournal class Canvas(): - # {{{ _commitPatch(self, patch) def _commitPatch(self, patch): self.map[patch[1]][patch[0]] = patch[2:] - # }}} - # {{{ dispatchPatch(self, isCursor, patch, commitUndo=True) + def dispatchPatch(self, isCursor, patch, commitUndo=True): if (patch[0] >= self.size[0]) or (patch[1] >= self.size[1]): return False @@ -27,8 +25,7 @@ class Canvas(): self.journal.begin(); self.journal.updateCurrentDeltas(patch, patchDelta); self.journal.end(); self._commitPatch(patch) return True - # }}} - # {{{ dispatchPatchSingle(self, isCursor, patch, commitUndo=True) + def dispatchPatchSingle(self, isCursor, patch, commitUndo=True): if (patch[0] >= self.size[0]) or (patch[1] >= self.size[1]): return False @@ -41,8 +38,7 @@ class Canvas(): self.journal.updateCurrentDeltas(patch, patchDelta) self._commitPatch(patch) return True - # }}} - # {{{ resize(self, newSize, commitUndo=True) + def resize(self, newSize, commitUndo=True): if newSize != self.size: if self.map == None: @@ -87,8 +83,7 @@ class Canvas(): return True else: return False - # }}} - # {{{ update(self, newSize, newCanvas=None) + def update(self, newSize, newCanvas=None): for numRow in range(self.size[1]): for numCol in range(self.size[0]): @@ -96,7 +91,7 @@ class Canvas(): and (numRow < len(newCanvas)) \ and (numCol < len(newCanvas[numRow])): self._commitPatch([numCol, numRow, *newCanvas[numRow][numCol]]) - # }}} + # # __init__(self, size): initialisation method diff --git a/libcanvas/CanvasColours.py b/libcanvas/CanvasColours.py index ecfe9d2..21f876f 100644 --- a/libcanvas/CanvasColours.py +++ b/libcanvas/CanvasColours.py @@ -4,7 +4,6 @@ # Copyright (c) 2018, 2019 Lucio Andrés Illanes Albornoz # -# {{{ AnsiBgToMiRCARTColours AnsiBgToMiRCARTColours = { 107: 0, # Bright White 40: 1, # Black @@ -23,8 +22,7 @@ AnsiBgToMiRCARTColours = { 100: 14, # Grey 47: 15, # Light Grey }; -# }}} -# {{{ AnsiFgBoldToMiRCARTColours + AnsiFgBoldToMiRCARTColours = { 97: 0, # Bright White 30: 14, # Grey @@ -43,8 +41,7 @@ AnsiFgBoldToMiRCARTColours = { 90: 14, # Grey 37: 0, # Bright White }; -# }}} -# {{{ AnsiFgToMiRCARTColours + AnsiFgToMiRCARTColours = { 97: 0, # Bright White 30: 1, # Black @@ -63,8 +60,7 @@ AnsiFgToMiRCARTColours = { 90: 14, # Grey 37: 15, # Light Grey }; -# }}} -# {{{ ColourMapBold: mIRC colour number to RGBA map given ^B (bold) + ColourMapBold = [ [255, 255, 255], # Bright White [85, 85, 85], # Black @@ -83,8 +79,7 @@ ColourMapBold = [ [85, 85, 85], # Grey [255, 255, 255], # Light Grey ] -# }}} -# {{{ ColourMapNormal: mIRC colour number to RGBA map given none of ^[BFV_] (bold, italic, reverse, underline) + ColourMapNormal = [ [255, 255, 255], # Bright White [0, 0, 0], # Black @@ -103,8 +98,7 @@ ColourMapNormal = [ [85, 85, 85], # Grey [187, 187, 187], # Light Grey ] -# }}} -# {{{ MiRCARTToAnsiColours + MiRCARTToAnsiColours = [ 97, # Bright White 30, # Black @@ -123,6 +117,6 @@ MiRCARTToAnsiColours = [ 90, # Grey 37, # Light Grey ]; -# }}} + # vim:expandtab foldmethod=marker sw=4 ts=4 tw=120 diff --git a/libcanvas/CanvasExportStore.py b/libcanvas/CanvasExportStore.py index 546e9e7..9e1b413 100644 --- a/libcanvas/CanvasExportStore.py +++ b/libcanvas/CanvasExportStore.py @@ -20,25 +20,22 @@ except ImportError: haveUrllib = False class CanvasExportStore(): - # {{{ _CellState(): Cell state class _CellState(): CS_NONE = 0x00 CS_BOLD = 0x01 CS_ITALIC = 0x02 CS_UNDERLINE = 0x04 - # }}} + ImgurUploadUrl = "https://api.imgur.com/3/upload.json" PastebinPostUrl = "https://pastebin.com/api/api_post.php" - # {{{ _drawUnderline(self, curPos, fillColour, fontSize, imgDraw) def _drawUnderLine(self, curPos, fillColour, fontSize, imgDraw): imgDraw.line( \ xy=(curPos[0], curPos[1] + (fontSize[1] - 2), \ curPos[0] + fontSize[0], curPos[1] + (fontSize[1] - 2)), \ fill=fillColour) - # }}} - # {{{ exportAnsiFile(self, canvasMap, canvasSize, outFile) + def exportAnsiFile(self, canvasMap, canvasSize, outFile): outBuffer = "" for inCurRow in range(len(canvasMap)): @@ -71,8 +68,7 @@ class CanvasExportStore(): return (True, None) else: return (False, "empty buffer generated") - # }}} - # {{{ exportBitmapToImgur(self, apiKey, canvasBitmap, imgName, imgTitle, imgType) + def exportBitmapToImgur(self, apiKey, canvasBitmap, imgName, imgTitle, imgType): tmpPathName = tempfile.mkstemp() os.close(tmpPathName[0]) @@ -94,12 +90,10 @@ class CanvasExportStore(): imgurResult = (False, responseHttp.status_code, responseDict.get("data")) os.remove(tmpPathName[1]) return imgurResult - # }}} - # {{{ exportBitmapToPngFile(self, canvasBitmap, outPathName, outType) + def exportBitmapToPngFile(self, canvasBitmap, outPathName, outType): return canvasBitmap.ConvertToImage().SaveFile(outPathName, outType) - # }}} - # {{{ exportPastebin(self, apiDevKey, canvasMap, canvasSize, pasteName="", pastePrivate=0) + def exportPastebin(self, apiDevKey, canvasMap, canvasSize, pasteName="", pastePrivate=0): if haveUrllib: outFile = io.StringIO() @@ -117,8 +111,7 @@ class CanvasExportStore(): return (False, str(responseHttp.status_code)) else: return (False, "missing requests and/or urllib3 module(s)") - # }}} - # {{{ exportPngFile(self, canvasMap, fontFilePath, fontSize, outPathName) + def exportPngFile(self, canvasMap, fontFilePath, fontSize, outPathName): if havePIL: inSize = (len(canvasMap[0]), len(canvasMap)) @@ -161,8 +154,7 @@ class CanvasExportStore(): return (True, None) else: return (False, "missing PIL modules") - # }}} - # {{{ exportTextBuffer(self, canvasMap, canvasSize) + def exportTextBuffer(self, canvasMap, canvasSize): outBuffer = "" for canvasRow in range(canvasSize[1]): @@ -213,11 +205,10 @@ class CanvasExportStore(): return (True, outBuffer) else: return (False, "empty buffer generated") - # }}} - # {{{ exportTextFile(self, canvasMap, canvasSize, outFile) + def exportTextFile(self, canvasMap, canvasSize, outFile): rc, outBuffer = self.exportTextBuffer(canvasMap, canvasSize) return outFile.write(outBuffer) if rc else (rc, outBuffer) - # }}} + # vim:expandtab foldmethod=marker sw=4 ts=4 tw=120 diff --git a/libcanvas/CanvasImportStore.py b/libcanvas/CanvasImportStore.py index 0f284c9..ba5bd99 100644 --- a/libcanvas/CanvasImportStore.py +++ b/libcanvas/CanvasImportStore.py @@ -9,20 +9,17 @@ from CanvasColours import AnsiBgToMiRCARTColours, AnsiFgToMiRCARTColours, AnsiFg import io, os, re, struct, sys class CanvasImportStore(): - # {{{ _CellState(): Cell state class _CellState(): CS_NONE = 0x00 CS_BOLD = 0x01 CS_ITALIC = 0x02 CS_UNDERLINE = 0x04 - # }}} - # {{{ _flipCellStateBit(self, bit, cellState) + def _flipCellStateBit(self, bit, cellState): return cellState & ~bit if cellState & bit else cellState | bit - # }}} - # {{{ importAnsiBuffer(self, inBuffer, encoding="cp437", width=None) + def importAnsiBuffer(self, inBuffer, encoding="cp437", width=None): curBg, curBgAnsi, curBoldAnsi, curFg, curFgAnsi = -1, 30, False, 15, 37 done, outMap, outMaxCols = False, [[]], 0 @@ -74,12 +71,10 @@ class CanvasImportStore(): return (True, None) else: return (False, "empty output map") - # }}} - # {{{ importAnsiFile(self, inPathName, encoding="cp437") + def importAnsiFile(self, inPathName, encoding="cp437"): return self.importAnsiBuffer(open(inPathName, "rb").read(), encoding) - # }}} - # {{{ importSauceFile(self, inPathName, encoding="cp437") + def importSauceFile(self, inPathName, encoding="cp437"): with open(inPathName, "rb") as inFile: inFileStat = os.stat(inPathName) @@ -90,8 +85,7 @@ class CanvasImportStore(): return self.importAnsiBuffer(inFileData, encoding, width) else: return (False, "only character based ANSi SAUCE files are supported") - # }}} - # {{{ importTextBuffer(self, inFile) + def importTextBuffer(self, inFile): try: inLine, outMap, outMaxCols = inFile.readline(), [], 0 @@ -137,12 +131,11 @@ class CanvasImportStore(): return (False, "empty output map") except: return (False, sys.exc_info()[1]) - # }}} - # {{{ importTextFile(self, pathName) + def importTextFile(self, pathName): with open(pathName, "r", encoding="utf-8-sig") as inFile: return self.importTextBuffer(inFile) - # }}} + # # __init__(self, inFile=None): initialisation method diff --git a/libcanvas/CanvasJournal.py b/libcanvas/CanvasJournal.py index 76e63f3..9934b7e 100644 --- a/libcanvas/CanvasJournal.py +++ b/libcanvas/CanvasJournal.py @@ -5,68 +5,58 @@ # class CanvasJournal(): - # {{{ begin(self) def begin(self): deltaItem = [[], []]; self.patchesUndo.insert(self.patchesUndoLevel, deltaItem); - # }}} - # {{{ end(self) + def end(self): if self.patchesUndo[self.patchesUndoLevel] == [[], []]: del self.patchesUndo[self.patchesUndoLevel] else: if self.patchesUndoLevel > 0: del self.patchesUndo[:self.patchesUndoLevel]; self.patchesUndoLevel = 0; - # }}} - # {{{ popCursor(self) + def popCursor(self): if len(self.patchesCursor): patchesCursor = self.patchesCursor; self.patchesCursor = []; return patchesCursor else: return [] - # }}} - # {{{ popRedo(self) + def popRedo(self): if self.patchesUndoLevel > 0: self.patchesUndoLevel -= 1; patches = self.patchesUndo[self.patchesUndoLevel]; return patches[1] else: return [] - # }}} - # {{{ popUndo(self) + def popUndo(self): if self.patchesUndo[self.patchesUndoLevel] != None: patches = self.patchesUndo[self.patchesUndoLevel]; self.patchesUndoLevel += 1; return patches[0] else: return [] - # }}} - # {{{ pushCursor(self, patches) + def pushCursor(self, patches): self.patchesCursor.append(patches) - # }}} - # {{{ resetCursor(self) + def resetCursor(self): if self.patchesCursor != None: self.patchesCursor.clear() self.patchesCursor = [] - # }}} - # {{{ resetUndo(self) + def resetUndo(self): if self.patchesUndo != None: self.patchesUndo.clear() self.patchesUndo = [None]; self.patchesUndoLevel = 0; - # }}} - # {{{ updateCurrentDeltas(self, redoPatches, undoPatches) + def updateCurrentDeltas(self, redoPatches, undoPatches): self.patchesUndo[self.patchesUndoLevel][0].append(undoPatches) self.patchesUndo[self.patchesUndoLevel][1].append(redoPatches) - # }}} - # {{{ __del__(self): destructor method + def __del__(self): self.resetCursor(); self.resetUndo(); - # }}} + # # __init__(self): initialisation method diff --git a/libgui/GuiCanvasWxBackend.py b/libgui/GuiCanvasWxBackend.py index fed2bdb..3b94456 100644 --- a/libgui/GuiCanvasWxBackend.py +++ b/libgui/GuiCanvasWxBackend.py @@ -9,12 +9,10 @@ from GuiCanvasColours import Colours import math, os, platform, wx class GuiBufferedDC(wx.MemoryDC): - # {{{ __del__(self) def __del__(self): self.dc.Blit(0, 0, *self.viewSize, self, 0, 0) self.SelectObject(wx.NullBitmap) - # }}} - # {{{ __init__(self, backend, buffer, clientSize, dc, viewRect) + def __init__(self, backend, buffer, clientSize, dc, viewRect): super().__init__() canvasSize = [a - b for a, b in zip(backend.canvasSize, viewRect)] @@ -24,10 +22,9 @@ class GuiBufferedDC(wx.MemoryDC): viewSize = [m * n for m, n in zip(backend.cellSize, viewSize)] self.SelectObject(buffer); self.SetDeviceOrigin(*viewRect); self.dc, self.viewRect, self.viewSize = dc, viewRect, viewSize - # }}} + class GuiCanvasWxBackend(): - # {{{ arabicShapes{} arabicShapes = { u'\u0621': (u'\uFE80'), u'\u0622': (u'\uFE81', None, None, u'\uFE82'), @@ -67,23 +64,20 @@ class GuiCanvasWxBackend(): u'\u0649': (u'\uFEEF', None, None, u'\uFEF0'), u'\u064A': (u'\uFEF1', u'\uFEF3', u'\uFEF4', u'\uFEF2'), } - # }}} - # {{{ _CellState(): Cell state + class _CellState(): CS_NONE = 0x00 CS_BOLD = 0x01 CS_ITALIC = 0x02 CS_UNDERLINE = 0x04 - # }}} - # {{{ _drawBrushPatch(self, eventDc, patch, point) + def _drawBrushPatch(self, eventDc, patch, point): absPoint = self._xlatePoint(point) brushBg, brushFg, pen = self._getBrushPatchColours(patch) self._setBrushDc(brushBg, brushFg, eventDc, pen) eventDc.DrawRectangle(*absPoint, *self.cellSize) - # }}} - # {{{ _drawCharPatch(self, eventDc, patch, point) + def _drawCharPatch(self, eventDc, patch, point): absPoint, fontBitmap = self._xlatePoint(point), wx.Bitmap(*self.cellSize) brushBg, brushFg, pen = self._getCharPatchColours(patch) @@ -99,14 +93,12 @@ class GuiCanvasWxBackend(): if patch[3] != "_": fontDc.DrawText(patch[3], 0, 0) eventDc.Blit(*absPoint, *self.cellSize, fontDc, 0, 0) - # }}} - # {{{ _finiBrushesAndPens(self) + def _finiBrushesAndPens(self): [brush.Destroy() for brush in self._brushes or []] [pen.Destroy() for pen in self._pens or []] self._brushes, self._lastBrushBg, self._lastBrushFg, self._lastPen, self._pens = None, None, None, None, None - # }}} - # {{{ _getBrushPatchColours(self, patch) + def _getBrushPatchColours(self, patch): if (patch[0] != -1) and (patch[1] != -1): brushBg, brushFg, pen = self._brushes[patch[1]], self._brushes[patch[1]], self._pens[patch[1]] @@ -117,8 +109,7 @@ class GuiCanvasWxBackend(): elif patch[1] == -1: brushBg, brushFg, pen = self._brushAlpha, self._brushAlpha, self._penAlpha return (brushBg, brushFg, pen) - # }}} - # {{{ _getCharPatchColours(self, patch) + def _getCharPatchColours(self, patch): if (patch[0] != -1) and (patch[1] != -1): brushBg, brushFg, pen = self._brushes[patch[1]], self._brushes[patch[1]], self._pens[patch[1]] @@ -129,8 +120,7 @@ class GuiCanvasWxBackend(): elif patch[1] == -1: brushBg, brushFg, pen = self._brushAlpha, self._brushAlpha, self._penAlpha return (brushBg, brushFg, pen) - # }}} - # {{{ _initBrushesAndPens(self) + def _initBrushesAndPens(self): self._brushes, self._pens = [None for x in range(len(Colours))], [None for x in range(len(Colours))] for mircColour in range(len(Colours)): @@ -139,8 +129,7 @@ class GuiCanvasWxBackend(): self._brushAlpha = wx.Brush(wx.Colour(Colours[14][:4]), wx.BRUSHSTYLE_SOLID) self._penAlpha = wx.Pen(wx.Colour(Colours[14][:4]), 1) self._lastBrushBg, self._lastBrushFg, self._lastPen = None, None, None - # }}} - # {{{ _reshapeArabic(self, canvas, eventDc, patch, point) + def _reshapeArabic(self, canvas, eventDc, patch, point): lastCell = point[0] while True: @@ -173,8 +162,7 @@ class GuiCanvasWxBackend(): else: runCell[3] = self.arabicShapes[patch[5]][0] self._drawCharPatch(eventDc, runCell, [point[0], point[1]]) - # }}} - # {{{ _setBrushDc(self, brushBg, brushFg, dc, pen) + def _setBrushDc(self, brushBg, brushFg, dc, pen): if self._lastBrushBg != brushBg: dc.SetBackground(brushBg); self._lastBrushBg = brushBg; @@ -182,17 +170,14 @@ class GuiCanvasWxBackend(): dc.SetBrush(brushFg); self._lastBrushFg = brushFg; if self._lastPen != pen: dc.SetPen(pen); self._lastPen = pen; - # }}} - # {{{ _xlatePoint(self, point) + def _xlatePoint(self, point): return [a * b for a, b in zip(point, self.cellSize)] - # }}} - # {{{ drawCursorMaskWithJournal(self, canvas, canvasJournal, eventDc) + def drawCursorMaskWithJournal(self, canvas, canvasJournal, eventDc): [self.drawPatch(canvas, eventDc, patch) for patch in canvasJournal.popCursor()] - # }}} - # {{{ drawPatch(self, canvas, eventDc, patch) + def drawPatch(self, canvas, eventDc, patch): point = patch[:2] if [(c >= 0) and (c < s) for c, s in zip(point, self.canvasSize)] == [True, True]: @@ -210,8 +195,7 @@ class GuiCanvasWxBackend(): return True else: return False - # }}} - # {{{ getDeviceContext(self, clientSize, parentWindow, viewRect=None) + def getDeviceContext(self, clientSize, parentWindow, viewRect=None): if viewRect == None: viewRect = parentWindow.GetViewStart() @@ -221,16 +205,14 @@ class GuiCanvasWxBackend(): eventDc = GuiBufferedDC(self, self.canvasBitmap, clientSize, wx.ClientDC(parentWindow), viewRect) self._lastBrushBg, self._lastBrushFg, self._lastPen = None, None, None return eventDc - # }}} - # {{{ onPaint(self, clientSize, panelWindow, viewRect) + def onPaint(self, clientSize, panelWindow, viewRect): if self.canvasBitmap != None: if viewRect == (0, 0): eventDc = wx.BufferedPaintDC(panelWindow, self.canvasBitmap) else: eventDc = GuiBufferedDC(self, self.canvasBitmap, clientSize, wx.PaintDC(panelWindow), viewRect) - # }}} - # {{{ resize(self, canvasSize, cellSize): + def resize(self, canvasSize, cellSize): winSize = [a * b for a, b in zip(canvasSize, cellSize)] if self.canvasBitmap == None: @@ -246,21 +228,19 @@ class GuiCanvasWxBackend(): self._font = wx.TheFontList.FindOrCreateFont(cellSize[0] + 1, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, self.fontName) else: self._font = wx.Font(cellSize[0] + 1, wx.FONTFAMILY_TELETYPE, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL) - # }}} - # {{{ xlateEventPoint(self, event, eventDc, viewRect) + def xlateEventPoint(self, event, eventDc, viewRect): eventPoint = event.GetLogicalPosition(eventDc) rectX, rectY = eventPoint.x - (eventPoint.x % self.cellSize[0]), eventPoint.y - (eventPoint.y % self.cellSize[1]) mapX, mapY = int(rectX / self.cellSize[0] if rectX else 0), int(rectY / self.cellSize[1] if rectY else 0) return [m + n for m, n in zip((mapX, mapY), viewRect)] - # }}} - # {{{ __del__(self): destructor method + def __del__(self): if self.canvasBitmap != None: self.canvasBitmap.Destroy(); self.canvasBitmap = None; self._finiBrushesAndPens() - # }}} + # # __init__(self, canvasSize, cellSize, fontName="Dejavu Sans Mono", fontPathName=os.path.join("assets", "fonts", "DejaVuSansMono.ttf")): initialisation method diff --git a/libgui/GuiFrame.py b/libgui/GuiFrame.py index 1cdc681..394888f 100644 --- a/libgui/GuiFrame.py +++ b/libgui/GuiFrame.py @@ -4,11 +4,10 @@ # Copyright (c) 2018, 2019 Lucio Andrés Illanes Albornoz # -import os, sys, wx +import os, sys, wx, wx.lib.agw.aui # # Decorators -# {{{ GuiCommandDecorator(targetObject) def GuiCommandDecorator(caption, label, icon, accel, initialState): def GuiCommandDecoratorOuter(targetObject): if callable(targetObject): @@ -17,8 +16,7 @@ def GuiCommandDecorator(caption, label, icon, accel, initialState): targetObject.attrDict = {"caption": caption, "label": label, "icon": icon, "accel": accel, "initialState": initialState, "id": None} return targetObject return GuiCommandDecoratorOuter -# }}} -# {{{ GuiCommandListDecorator(targetObject) + def GuiCommandListDecorator(idx, caption, label, icon, accel, initialState): def GuiCommandListDecoratorOuter(targetObject): if callable(targetObject): @@ -27,8 +25,7 @@ def GuiCommandListDecorator(idx, caption, label, icon, accel, initialState): targetObject.attrList.insert(0, {"caption": caption, "label": label, "icon": icon, "accel": accel, "initialState": initialState, "id": None, "idx": idx}) return targetObject return GuiCommandListDecoratorOuter -# }}} -# {{{ GuiSelectDecorator(targetObject) + def GuiSelectDecorator(idx, caption, label, icon, accel, initialState): def GuiSelectDecoratorOuter(targetObject): if callable(targetObject): @@ -38,8 +35,7 @@ def GuiSelectDecorator(idx, caption, label, icon, accel, initialState): targetObject.attrList.insert(0, {"caption": caption, "label": label, "icon": icon, "accel": accel, "initialState": initialState, "id": None, "idx": idx}) return targetObject return GuiSelectDecoratorOuter -# }}} -# {{{ GuiSubMenuDecorator(targetObject) + def GuiSubMenuDecorator(caption, label, icon, accel, initialState): def GuiSubMenuDecoratorOuter(targetObject): if callable(targetObject): @@ -49,7 +45,19 @@ def GuiSubMenuDecorator(caption, label, icon, accel, initialState): targetObject.attrDict = {"caption": caption, "label": label, "icon": icon, "accel": accel, "initialState": initialState, "id": None, "menu":None} return targetObject return GuiSubMenuDecoratorOuter -# }}} + + +class GuiToolBarArtProvider(wx.lib.agw.aui.AuiDefaultToolBarArt): + def DrawBackground(self, dc, wnd, _rect, horizontal=True): + dc.SetBrush(wx.Brush(wx.Colour(240, 240, 240, 0), wx.BRUSHSTYLE_SOLID)); dc.SetPen(wx.Pen(wx.Colour(240, 240, 240, 0), 1)); + dc.DrawRectangle(*_rect) + dc.SetPen(wx.Pen(wx.Colour(180, 180, 180, 0), 1)) + dc.DrawLine(0, _rect[3]-1, _rect[2], _rect[3]-1); dc.DrawLine(_rect[2]-1, 0, _rect[2]-1, _rect[3]-1); + dc.SetPen(wx.Pen(wx.Colour(255, 255, 255, 0), 1)) + dc.DrawLine(0, 0, _rect[2]-1, 0); dc.DrawLine(0, 0, 0, _rect[3]-1); + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) # # Non-items (0xf000-0xffff) @@ -57,13 +65,11 @@ NID_MENU_SEP = 0xf000 NID_TOOLBAR_HSEP = 0xf001 class GuiFrame(wx.Frame): - # {{{ _initIcon(self, iconPathName) def _initIcon(self, iconPathName): icon = wx.Icon() icon.CopyFromBitmap(wx.Bitmap(iconPathName, wx.BITMAP_TYPE_ANY)) self.SetIcon(icon) - # }}} - # {{{ _initMenu(self, menuItem, menuWindow) + def _initMenu(self, menuItem, menuWindow): if menuItem == NID_MENU_SEP: menuWindow.AppendSeparator() @@ -87,10 +93,9 @@ class GuiFrame(wx.Frame): menuItemWindow.Check(menuItem.attrDict["initialState"]) else: menuItemWindow.Enable(menuItem.attrDict["initialState"]) - # }}} - # {{{ loadAccels(self, menus, toolBars) - def loadAccels(self, menus, toolBars): + + def loadAccels(self, accelsIn, menus, toolBars): def loadAccels_(accels): nonlocal accelTableEntries accels_ = [] @@ -110,10 +115,9 @@ class GuiFrame(wx.Frame): self.itemsById[accel.attrDict["id"]] = accel self.Bind(wx.EVT_MENU, self.onMenu, id=accel.attrDict["id"]) accelTableEntries = [] - [loadAccels_(menu[1:]) for menu in menus]; [loadAccels_(toolBar) for toolBar in toolBars]; + [loadAccels_(accel) for accel in accelsIn]; [loadAccels_(menu[1:]) for menu in menus]; [loadAccels_(toolBar) for toolBar in toolBars]; self.SetAcceleratorTable(wx.AcceleratorTable(accelTableEntries)) - # }}} - # {{{ loadBitmap(self, basePathName, descr, size=(16, 16)) + def loadBitmap(self, basePathName, descr, size=(16, 16)): if descr == None: descr = ["", None, wx.ArtProvider.GetBitmap(wx.ART_HELP, wx.ART_TOOLBAR, size)] @@ -126,8 +130,7 @@ class GuiFrame(wx.Frame): elif len(descr) == 3: descr = ("", None, descr[2]) return descr - # }}} - # {{{ loadMenus(self, menus) + def loadMenus(self, menus): self.menuBar = wx.MenuBar() for menu in menus: @@ -142,11 +145,11 @@ class GuiFrame(wx.Frame): self._initMenu(menuItem, menuWindow) self.menuBar.Append(menuWindow, menu[0]) self.SetMenuBar(self.menuBar) - # }}} - # {{{ loadToolBars(self, toolBars) + def loadToolBars(self, toolBars): for toolBar in toolBars: - self.toolBars.append(wx.ToolBar(self.panelSkin, -1, style=wx.TB_FLAT | wx.HORIZONTAL | wx.TB_NODIVIDER)) + self.toolBars.append(wx.lib.agw.aui.AuiToolBar(self.panelSkin, -1)) + self.toolBars[-1].SetArtProvider(GuiToolBarArtProvider()) self.toolBars[-1].SetToolBitmapSize((16, 16)) for toolBarItem in toolBar: if toolBarItem == NID_TOOLBAR_HSEP: @@ -156,42 +159,40 @@ class GuiFrame(wx.Frame): toolBarItem.attrDict["id"] = wx.NewId() self.itemsById[toolBarItem.attrDict["id"]] = toolBarItem if hasattr(toolBarItem, "isSelect"): - toolBarItemWindow = self.toolBars[-1].AddRadioTool(toolBarItem.attrDict["id"], toolBarItem.attrDict["caption"], toolBarItem.attrDict["icon"][2], shortHelp=toolBarItem.attrDict["label"]) + toolBarItemWindow = self.toolBars[-1].AddRadioTool(toolBarItem.attrDict["id"], toolBarItem.attrDict["caption"], toolBarItem.attrDict["icon"][2], wx.NullBitmap, short_help_string=toolBarItem.attrDict["caption"]) else: - toolBarItemWindow = self.toolBars[-1].AddTool(toolBarItem.attrDict["id"], toolBarItem.attrDict["caption"], toolBarItem.attrDict["icon"][2], shortHelp=toolBarItem.attrDict["label"]) - self.toolBarItemsById[toolBarItem.attrDict["id"]] = toolBarItemWindow + toolBarItemWindow = self.toolBars[-1].AddTool(toolBarItem.attrDict["id"], toolBarItem.attrDict["caption"], toolBarItem.attrDict["icon"][2], wx.NullBitmap, wx.ITEM_NORMAL, short_help_string=toolBarItem.attrDict["caption"]) + self.toolBarItemsById[toolBarItem.attrDict["id"]] = (self.toolBars[-1], toolBarItemWindow,) self.Bind(wx.EVT_TOOL, self.onMenu, toolBarItemWindow) self.Bind(wx.EVT_TOOL_RCLICKED, self.onMenu, toolBarItemWindow) if toolBarItem.attrDict["initialState"] != None: if hasattr(toolBarItem, "isSelect"): - toolBarItemWindow.Toggle(toolBarItem.attrDict["initialState"]) + if toolBarItem.attrDict["initialState"]: + self.toolBars[-1].ToggleTool(toolBarItemWindow, True) else: - toolBarItemWindow.Enable(toolBarItem.attrDict["initialState"]) + self.toolBars[-1].EnableTool(toolBarItem.attrDict["id"], toolBarItem.attrDict["initialState"]) + self.toolBars[-1].Refresh() for toolBar in self.toolBars: self.sizerSkin.Add(toolBar, 0, wx.ALIGN_LEFT | wx.ALL, 3) toolBar.Realize(); toolBar.Fit(); - # }}} - # {{{ addWindow(self, window, border=14, expand=False) + def addWindow(self, window, border=14, expand=False): flags = wx.ALL; flags = flags | wx.EXPAND if expand else flags; self.sizerSkin.Add(window, 0, flags, border); self.sizerSkin.Fit(self.panelSkin); - # }}} - # {{{ onChar(self, event) + def onChar(self, event): event.Skip() - # }}} - # {{{ onMenu(self, event) + def onMenu(self, event): eventId = event.GetId() if eventId in self.itemsById: self.itemsById[eventId](event) else: event.Skip() - # }}} - # {{{ onMouseWheel(self, event) + def onMouseWheel(self, event): event.Skip() - # }}} + # # __init__(self, iconPathName, size, parent=None, title=""): initialisation method diff --git a/libgui/GuiWindow.py b/libgui/GuiWindow.py index 48c1dc0..9ed5f20 100644 --- a/libgui/GuiWindow.py +++ b/libgui/GuiWindow.py @@ -7,7 +7,6 @@ import wx class GuiWindow(wx.ScrolledWindow): - # {{{ _updateScrollBars(self) def _updateScrollBars(self): if self.size != None: clientSize = self.GetClientSize() @@ -16,48 +15,39 @@ class GuiWindow(wx.ScrolledWindow): elif self.scrollFlag \ and ((self.size[0] <= clientSize[0]) or (self.size[1] <= clientSize[1])): self.scrollFlag = False; super().SetVirtualSize((0, 0)); - # }}} - # {{{ onClose(self, event) + def onClose(self, event): self.Destroy() - # }}} - # {{{ onEnterWindow(self, event) + def onEnterWindow(self, event): event.Skip() - # }}} - # {{{ onKeyboardInput(self, event) + def onKeyboardInput(self, event): return False - # }}} - # {{{ onLeaveWindow(self, event) + def onLeaveWindow(self, event): event.Skip() - # }}} - # {{{ onMouseInput(self, event) + def onMouseInput(self, event): return False - # }}} - # {{{ onPaint(self, event) + def onPaint(self, event): event.Skip() - # }}} - # {{{ onScroll(self, event) + def onScroll(self, event): event.Skip() - # }}} - # {{{ onSize(self, event) + def onSize(self, event): self._updateScrollBars(); event.Skip(); - # }}} - # {{{ resize(self, newSize) + def resize(self, newSize): self.size = newSize; self._updateScrollBars(); self.SetMinSize(self.size); self.SetSize(wx.DefaultCoord, wx.DefaultCoord, *self.size); curWindow = self while curWindow != None: curWindow.Layout(); curWindow = curWindow.GetParent(); - # }}} + # # __init__(self, parent, pos, scrollStep, style=0): initialisation method diff --git a/libroar/RoarAssetsWindow.py b/libroar/RoarAssetsWindow.py index 8600f3b..37e21ab 100644 --- a/libroar/RoarAssetsWindow.py +++ b/libroar/RoarAssetsWindow.py @@ -10,12 +10,10 @@ from GuiWindow import GuiWindow import json, os, sys, wx class RoarAssetsWindow(GuiMiniFrame): - # {{{ _drawPatch(self, canvas, eventDc, isCursor, patch) def _drawPatch(self, canvas, eventDc, isCursor, patch): if not isCursor: self.backend.drawPatch(canvas, eventDc, patch) - # }}} - # {{{ _import(self, f, pathName) + def _import(self, f, pathName): rc = False self.SetCursor(wx.Cursor(wx.CURSOR_WAIT)) @@ -28,8 +26,7 @@ class RoarAssetsWindow(GuiMiniFrame): rc, error, newMap, newPathName, newSize = False, str(e), None, None, None self.SetCursor(wx.Cursor(wx.NullCursor)) return rc, error, canvas, newMap, newPathName, newSize - # }}} - # {{{ _importFiles(self, f, wildcard) + def _importFiles(self, f, wildcard): resultList = [] with wx.FileDialog(self, "Load...", os.getcwd(), "", wildcard, wx.FD_MULTIPLE | wx.FD_OPEN) as dialog: @@ -42,8 +39,7 @@ class RoarAssetsWindow(GuiMiniFrame): resultList += [self._import(f, pathName)] self.lastDir = os.path.dirname(pathName) return resultList - # }}} - # {{{ _load_list(self, pathName) + def _load_list(self, pathName): try: with open(pathName, "r") as fileObject: @@ -84,8 +80,7 @@ class RoarAssetsWindow(GuiMiniFrame): self.SetCursor(wx.Cursor(wx.NullCursor)) with wx.MessageDialog(self, "Error: {}".format(str(e)), "", wx.OK | wx.OK_DEFAULT) as dialog: dialogChoice = dialog.ShowModal() - # }}} - # {{{ _updateScrollBars(self) + def _updateScrollBars(self): clientSize = self.panelCanvas.GetClientSize() if self.currentIndex != None: @@ -99,9 +94,8 @@ class RoarAssetsWindow(GuiMiniFrame): elif self.scrollFlag \ and ((panelSize[0] <= clientSize[0]) or (panelSize[1] <= clientSize[1])): self.scrollFlag = False; super(wx.ScrolledWindow, self.panelCanvas).SetVirtualSize((0, 0)); - # }}} - # {{{ drawCanvas(self, canvas) + def drawCanvas(self, canvas): panelSize = [a * b for a, b in zip(canvas.size, self.cellSize)] self.panelCanvas.SetMinSize(panelSize); self.panelCanvas.SetSize(wx.DefaultCoord, wx.DefaultCoord, *panelSize); @@ -115,12 +109,10 @@ class RoarAssetsWindow(GuiMiniFrame): for numCol in range(canvas.size[0]): self.backend.drawPatch(canvas, eventDc, [numCol, numRow, *canvas.map[numRow][numCol]]) eventDc.SetDeviceOrigin(*eventDcOrigin) - # }}} - # {{{ onPaint(self, event) + def onPaint(self, event): self.backend.onPaint(self.panelCanvas.GetClientSize(), self.panelCanvas, self.panelCanvas.GetViewStart()) - # }}} - # {{{ onPanelLeftDown(self, event) + def onPanelLeftDown(self, event): self.panelCanvas.SetFocus() if (self.currentIndex != None): @@ -130,16 +122,13 @@ class RoarAssetsWindow(GuiMiniFrame): dropSource.SetData(textDataObject) result = dropSource.DoDragDrop(True) event.Skip() - # }}} - # {{{ onPanelPaint(self, event) + def onPanelPaint(self, event): self.backend.onPaint(self.panelCanvas.GetClientSize(), self.panelCanvas, self.panelCanvas.GetViewStart()) - # }}} - # {{{ onPanelSize(self, event) + def onPanelSize(self, event): self._updateScrollBars(); event.Skip(); - # }}} - # {{{ resize(self, canvas, newSize) + def resize(self, canvas, newSize): oldSize = [0, 0] if canvas.map == None else canvas.size deltaSize = [b - a for a, b in zip(oldSize, newSize)] @@ -161,8 +150,7 @@ class RoarAssetsWindow(GuiMiniFrame): for numNewCol in range(newSize[0]): self._drawPatch(canvas, eventDc, False, [numNewCol, numNewRow, 1, 1, 0, " "]) eventDc.SetDeviceOrigin(*eventDcOrigin) - # }}} - # {{{ update(self, canvas, newSize, newCanvas=None) + def update(self, canvas, newSize, newCanvas=None): self.resize(canvas, newSize); canvas.update(newSize, newCanvas); @@ -172,21 +160,17 @@ class RoarAssetsWindow(GuiMiniFrame): for numCol in range(canvas.size[0]): self.backend.drawPatch(canvas, eventDc, [numCol, numRow, *canvas.map[numRow][numCol]]) eventDc.SetDeviceOrigin(*eventDcOrigin) - # }}} - # {{{ onImportAnsi(self, event) + def onImportAnsi(self, event): event.Skip() - # }}} - # {{{ onImportFromClipboard(self, event) + def onImportFromClipboard(self, event): event.Skip() - # }}} - # {{{ onImportSauce(self, event) + def onImportSauce(self, event): event.Skip() - # }}} - # {{{ onChar(self, event) + def onChar(self, event): if (event.GetModifiers() == wx.MOD_NONE) \ and (event.GetKeyCode() in (wx.WXK_DOWN, wx.WXK_UP)): @@ -194,8 +178,7 @@ class RoarAssetsWindow(GuiMiniFrame): return wx.PostEvent(self.listView, event) else: event.Skip() - # }}} - # {{{ onListViewChar(self, event) + def onListViewChar(self, event): index, rc = self.listView.GetFirstSelected(), False if index != -1: @@ -204,14 +187,12 @@ class RoarAssetsWindow(GuiMiniFrame): self.currentIndex, rc = index, True; self.onRemove(None); if not rc: event.Skip() - # }}} - # {{{ onListViewItemSelected(self, event) + def onListViewItemSelected(self, event): self.currentIndex = event.GetItem().GetId() item = [self.listView.GetItem(self.currentIndex, col).GetText() for col in (0, 1)] self.drawCanvas(self.canvasList[self.currentIndex][0]) - # }}} - # {{{ onListViewRightDown(self, event) + def onListViewRightDown(self, event): eventPoint = event.GetPosition() if self.currentIndex == None: @@ -223,8 +204,7 @@ class RoarAssetsWindow(GuiMiniFrame): else: self.contextMenuItems[4].Enable(True) self.PopupMenu(self.contextMenu, eventPoint) - # }}} - # {{{ onLoad(self, event) + def onLoad(self, event): def importmIRC(canvas, pathName): rc, error = canvas.importStore.importTextFile(pathName) @@ -250,7 +230,7 @@ class RoarAssetsWindow(GuiMiniFrame): dialogChoice = dialog.ShowModal() if dialogChoice == wx.ID_CANCEL: break - # }}} + # {{{ onLoadList(self, event) def onLoadList(self, event): rc = True @@ -260,8 +240,7 @@ class RoarAssetsWindow(GuiMiniFrame): if dialog.ShowModal() != wx.ID_CANCEL: pathName = dialog.GetPath(); self.lastDir = os.path.dirname(pathName); self._load_list(pathName) - # }}} - # {{{ onRemove(self, event) + def onRemove(self, event): del self.canvasList[self.currentIndex]; self.listView.DeleteItem(self.currentIndex); itemCount = self.listView.GetItemCount() @@ -280,8 +259,7 @@ class RoarAssetsWindow(GuiMiniFrame): self.currentIndex = None [self.listView.SetColumnWidth(col, wx.LIST_AUTOSIZE_USEHEADER) for col in (0, 1)] self.drawCanvas(Canvas((0, 0))) - # }}} - # {{{ onSaveList(self, event) + def onSaveList(self, event): rc = True if len(self.canvasList): @@ -299,7 +277,7 @@ class RoarAssetsWindow(GuiMiniFrame): if not rc: with wx.MessageDialog(self, "Error: {}".format(error), "", wx.OK | wx.OK_DEFAULT) as dialog: dialogChoice = dialog.ShowModal() - # }}} + # # __init__(self, backend, cellSize, parent, pos=None, size=(400, 400), title="Assets"): initialisation method diff --git a/libroar/RoarCanvasCommands.py b/libroar/RoarCanvasCommands.py index 62d53ed..b840ff5 100644 --- a/libroar/RoarCanvasCommands.py +++ b/libroar/RoarCanvasCommands.py @@ -14,32 +14,33 @@ from RoarCanvasCommandsTools import RoarCanvasCommandsTools import os, wx class RoarCanvasCommands(RoarCanvasCommandsFile, RoarCanvasCommandsEdit, RoarCanvasCommandsTools, RoarCanvasCommandsOperators, RoarCanvasCommandsHelp): - # {{{ _initColourBitmaps(self) def _initColourBitmaps(self): - for numColour in range(len(RoarCanvasCommandsEdit.canvasColour.attrList)): - if numColour < len(Colours): - toolBitmapColour = Colours[numColour][0:4] - toolBitmap = wx.Bitmap((16, 16)) - toolBitmapDc = wx.MemoryDC(); toolBitmapDc.SelectObject(toolBitmap); - toolBitmapBrush = wx.Brush(wx.Colour(toolBitmapColour), wx.BRUSHSTYLE_SOLID) - toolBitmapDc.SetBrush(toolBitmapBrush) - toolBitmapDc.SetBackground(toolBitmapBrush) - toolBitmapDc.SetPen(wx.Pen(wx.Colour(toolBitmapColour), 1)) - toolBitmapDc.DrawRectangle(0, 0, 16, 16) - RoarCanvasCommandsEdit.canvasColour.attrList[numColour]["icon"] = ["", None, toolBitmap] - toolBitmapColours = ((0, 0, 0, 255), (255, 255, 255, 255)) - toolBitmap = wx.Bitmap((16, 16)) - toolBitmapDc = wx.MemoryDC(); toolBitmapDc.SelectObject(toolBitmap); - toolBitmapBrush = [wx.Brush(wx.Colour(c), wx.BRUSHSTYLE_SOLID) for c in toolBitmapColours] - toolBitmapDc.SetBrush(toolBitmapBrush[1]) - toolBitmapDc.SetBackground(toolBitmapBrush[1]) - toolBitmapDc.SetPen(wx.Pen(wx.Colour(toolBitmapColours[1]), 1)) - toolBitmapDc.DrawRectangle(0, 0, 8, 8) - toolBitmapDc.DrawRectangle(8, 8, 16, 16) - RoarCanvasCommandsEdit.canvasColourAlpha.attrList[0]["icon"] = ["", None, toolBitmap] - # }}} + def _initColourBitmaps_(cmd, cmdAlpha, div): + for numColour in range(len(cmd.attrList)): + if numColour < len(Colours): + toolBitmapColour = Colours[numColour][0:4] + toolBitmap = wx.Bitmap((16, 16)) + toolBitmapDc = wx.MemoryDC(); toolBitmapDc.SelectObject(toolBitmap); + toolBitmapBrush = wx.Brush(wx.Colour([*[int(c / div) for c in toolBitmapColour[:3]], 255]), wx.BRUSHSTYLE_SOLID) + toolBitmapDc.SetBrush(toolBitmapBrush) + toolBitmapDc.SetBackground(toolBitmapBrush) + toolBitmapDc.SetPen(wx.Pen(wx.Colour(toolBitmapColour), 1)) + toolBitmapDc.DrawRectangle(0, 0, 16, 16) + cmd.attrList[numColour]["icon"] = ["", None, toolBitmap] + toolBitmapColours = ((0, 0, 0, 255), (255, 255, 255, 255)) + toolBitmap = wx.Bitmap((16, 16)) + toolBitmapDc = wx.MemoryDC(); toolBitmapDc.SelectObject(toolBitmap); + toolBitmapBrush = [wx.Brush(wx.Colour(c), wx.BRUSHSTYLE_SOLID) for c in toolBitmapColours] + toolBitmapDc.SetBrush(toolBitmapBrush[1]) + toolBitmapDc.SetBackground(toolBitmapBrush[1]) + toolBitmapDc.SetPen(wx.Pen(wx.Colour(toolBitmapColours[1]), 1)) + toolBitmapDc.DrawRectangle(0, 0, 8, 8) + toolBitmapDc.DrawRectangle(8, 8, 16, 16) + cmdAlpha.attrList[0]["icon"] = ["", None, toolBitmap] + _initColourBitmaps_(RoarCanvasCommandsEdit.canvasColour, RoarCanvasCommandsEdit.canvasColourAlpha, 1.0) + _initColourBitmaps_(RoarCanvasCommandsEdit.canvasColourBackground, RoarCanvasCommandsEdit.canvasColourAlphaBackground, 0.5) + - # {{{ update(self, **kwargs) def update(self, **kwargs): self.lastPanelState.update(kwargs); textItems = []; if "cellPos" in self.lastPanelState: @@ -53,8 +54,20 @@ class RoarCanvasCommands(RoarCanvasCommandsFile, RoarCanvasCommandsEdit, RoarCan textItems.append("{} on {}".format( Colours[self.lastPanelState["colours"][0]][4] if self.lastPanelState["colours"][0] != -1 else "Transparent", Colours[self.lastPanelState["colours"][1]][4] if self.lastPanelState["colours"][1] != -1 else "Transparent")) - toolBar = self.parentFrame.toolBarItemsById[self.canvasColour(self.canvasColour, self.lastPanelState["colours"][0]).attrDict["id"]].GetToolBar() - toolBar.ToggleTool(self.canvasColour(self.canvasColour, self.lastPanelState["colours"][0]).attrDict["id"], True) + toolBar = self.parentFrame.toolBarItemsById[self.canvasColour(self.canvasColour, self.lastPanelState["colours"][0]).attrDict["id"]][0] + toolBarBg = self.parentFrame.toolBarItemsById[self.canvasColourBackground(self.canvasColourBackground, self.lastPanelState["colours"][1]).attrDict["id"]][0] + if self.lastPanelState["colours"][0] != -1: + toolBar.ToggleTool(self.canvasColour(self.canvasColour, self.lastPanelState["colours"][0]).attrDict["id"], True) + toolBar.Refresh() + else: + toolBar.ToggleTool(self.canvasColourAlpha(self.canvasColourAlpha, 0).attrDict["id"], True) + toolBar.Refresh() + if self.lastPanelState["colours"][1] != -1: + toolBarBg.ToggleTool(self.canvasColourBackground(self.canvasColourBackground, self.lastPanelState["colours"][1]).attrDict["id"], True) + toolBarBg.Refresh() + else: + toolBarBg.ToggleTool(self.canvasColourAlphaBackground(self.canvasColourAlphaBackground, 0).attrDict["id"], True) + toolBarBg.Refresh() if "pathName" in self.lastPanelState: if self.lastPanelState["pathName"] != None: basePathName = os.path.basename(self.lastPanelState["pathName"]) @@ -75,35 +88,37 @@ class RoarCanvasCommands(RoarCanvasCommandsFile, RoarCanvasCommandsEdit, RoarCan and (self.lastPanelState["undoInhibit"]): for item in (self.canvasRedo, self.canvasUndo): self.parentFrame.menuItemsById[item.attrDict["id"]].Enable(False) - toolBar = self.parentFrame.toolBarItemsById[item.attrDict["id"]].GetToolBar() - toolBar.EnableTool(item.attrDict["id"], False) + toolBar = self.parentFrame.toolBarItemsById[item.attrDict["id"]][0] + toolBar.EnableTool(item.attrDict["id"], False); toolBar.Refresh(); elif "undoLevel" in self.lastPanelState: if (self.lastPanelState["undoLevel"] >= 0) \ and (self.lastPanelState["undoLevel"] < (len(self.parentCanvas.canvas.journal.patchesUndo) - 1)): self.parentFrame.menuItemsById[self.canvasUndo.attrDict["id"]].Enable(True) - toolBar = self.parentFrame.toolBarItemsById[self.canvasUndo.attrDict["id"]].GetToolBar() - toolBar.EnableTool(self.canvasUndo.attrDict["id"], True) + toolBar = self.parentFrame.toolBarItemsById[self.canvasUndo.attrDict["id"]][0] + toolBar.EnableTool(self.canvasUndo.attrDict["id"], True); toolBar.Refresh(); else: self.parentFrame.menuItemsById[self.canvasUndo.attrDict["id"]].Enable(False) - toolBar = self.parentFrame.toolBarItemsById[self.canvasUndo.attrDict["id"]].GetToolBar() - toolBar.EnableTool(self.canvasUndo.attrDict["id"], False) + toolBar = self.parentFrame.toolBarItemsById[self.canvasUndo.attrDict["id"]][0] + toolBar.EnableTool(self.canvasUndo.attrDict["id"], False); toolBar.Refresh(); if self.lastPanelState["undoLevel"] > 0: self.parentFrame.menuItemsById[self.canvasRedo.attrDict["id"]].Enable(True) - toolBar = self.parentFrame.toolBarItemsById[self.canvasRedo.attrDict["id"]].GetToolBar() - toolBar.EnableTool(self.canvasRedo.attrDict["id"], True) + toolBar = self.parentFrame.toolBarItemsById[self.canvasRedo.attrDict["id"]][0] + toolBar.EnableTool(self.canvasRedo.attrDict["id"], True); toolBar.Refresh(); else: self.parentFrame.menuItemsById[self.canvasRedo.attrDict["id"]].Enable(False) - toolBar = self.parentFrame.toolBarItemsById[self.canvasRedo.attrDict["id"]].GetToolBar() - toolBar.EnableTool(self.canvasRedo.attrDict["id"], False) - # }}} + toolBar = self.parentFrame.toolBarItemsById[self.canvasRedo.attrDict["id"]][0] + toolBar.EnableTool(self.canvasRedo.attrDict["id"], False); toolBar.Refresh(); + # # __init__(self, parentCanvas, parentFrame): def __init__(self, parentCanvas, parentFrame): - menus, toolBars = [], [] + accels, menus, toolBars = [], [], [] self.canvasPathName, self.lastPanelState, self.parentCanvas, self.parentFrame = None, {}, parentCanvas, parentFrame for classObject in self.__class__.__bases__: classObject.__init__(self) + if len(self.accels): + accels += self.accels if len(self.menus): menus += self.menus if len(self.toolBars): @@ -115,20 +130,27 @@ class RoarCanvasCommands(RoarCanvasCommandsFile, RoarCanvasCommandsEdit, RoarCan [self.canvasNew, self.canvasOpen, self.canvasSave, self.canvasSaveAs, NID_TOOLBAR_HSEP, self.canvasUndo, self.canvasRedo, NID_TOOLBAR_HSEP, self.canvasCut, self.canvasCopy, self.canvasPaste, self.canvasDelete, NID_TOOLBAR_HSEP, - self.canvasCanvasSize(self.canvasCanvasSize, 1, True), self.canvasCanvasSize(self.canvasCanvasSize, 1, False), self.canvasCanvasSize(self.canvasCanvasSize, 0, True), self.canvasCanvasSize(self.canvasCanvasSize, 0, False), NID_TOOLBAR_HSEP, - self.canvasCanvasSize(self.canvasCanvasSize, 2, True), self.canvasCanvasSize(self.canvasCanvasSize, 2, False), NID_TOOLBAR_HSEP, + self.canvasAssetsWindowHide, self.canvasAssetsWindowShow, NID_TOOLBAR_HSEP, self.canvasTool(self.canvasTool, 1), self.canvasTool(self.canvasTool, 5), self.canvasTool(self.canvasTool, 0), self.canvasTool(self.canvasTool, 2), self.canvasTool(self.canvasTool, 3), self.canvasTool(self.canvasTool, 6), self.canvasTool(self.canvasTool, 4), ]) - # XXX toolBars.append( [self.canvasColour(self.canvasColour, 0), self.canvasColour(self.canvasColour, 1), self.canvasColour(self.canvasColour, 2), self.canvasColour(self.canvasColour, 3), self.canvasColour(self.canvasColour, 4), self.canvasColour(self.canvasColour, 5), self.canvasColour(self.canvasColour, 6), self.canvasColour(self.canvasColour, 7), self.canvasColour(self.canvasColour, 8), self.canvasColour(self.canvasColour, 9), self.canvasColour(self.canvasColour, 10), self.canvasColour(self.canvasColour, 11), self.canvasColour(self.canvasColour, 12), self.canvasColour(self.canvasColour, 13), self.canvasColour(self.canvasColour, 14), self.canvasColour(self.canvasColour, 15), - self.canvasColourAlpha(self.canvasColourAlpha, 0), NID_TOOLBAR_HSEP, + self.canvasColourAlpha(self.canvasColourAlpha, 0), self.canvasColoursFlip, NID_TOOLBAR_HSEP, self.canvasBrushSize(self.canvasBrushSize, 1, True), self.canvasBrushSize(self.canvasBrushSize, 0, False), self.canvasBrushSize(self.canvasBrushSize, 1, True), self.canvasBrushSize(self.canvasBrushSize, 1, False), NID_TOOLBAR_HSEP, self.canvasBrushSize(self.canvasBrushSize, 2, True), self.canvasBrushSize(self.canvasBrushSize, 2, False), ]) - self.menus, self.toolBars = menus, toolBars + toolBars.append( + [self.canvasColourBackground(self.canvasColourBackground, 0), self.canvasColourBackground(self.canvasColourBackground, 1), self.canvasColourBackground(self.canvasColourBackground, 2), self.canvasColourBackground(self.canvasColourBackground, 3), + self.canvasColourBackground(self.canvasColourBackground, 4), self.canvasColourBackground(self.canvasColourBackground, 5), self.canvasColourBackground(self.canvasColourBackground, 6), self.canvasColourBackground(self.canvasColourBackground, 7), + self.canvasColourBackground(self.canvasColourBackground, 8), self.canvasColourBackground(self.canvasColourBackground, 9), self.canvasColourBackground(self.canvasColourBackground, 10), self.canvasColourBackground(self.canvasColourBackground, 11), + self.canvasColourBackground(self.canvasColourBackground, 12), self.canvasColourBackground(self.canvasColourBackground, 13), self.canvasColourBackground(self.canvasColourBackground, 14), self.canvasColourBackground(self.canvasColourBackground, 15), + self.canvasColourAlphaBackground(self.canvasColourAlphaBackground, 0), self.canvasColoursFlip, NID_TOOLBAR_HSEP, + self.canvasCanvasSize(self.canvasCanvasSize, 1, True), self.canvasCanvasSize(self.canvasCanvasSize, 1, False), self.canvasCanvasSize(self.canvasCanvasSize, 0, True), self.canvasCanvasSize(self.canvasCanvasSize, 0, False), NID_TOOLBAR_HSEP, + self.canvasCanvasSize(self.canvasCanvasSize, 2, True), self.canvasCanvasSize(self.canvasCanvasSize, 2, False), + ]) + self.accels, self.menus, self.toolBars = accels, menus, toolBars # vim:expandtab foldmethod=marker sw=4 ts=4 tw=0 diff --git a/libroar/RoarCanvasCommandsEdit.py b/libroar/RoarCanvasCommandsEdit.py index 4475bd7..677e640 100644 --- a/libroar/RoarCanvasCommandsEdit.py +++ b/libroar/RoarCanvasCommandsEdit.py @@ -8,21 +8,26 @@ from GuiFrame import GuiCommandDecorator, GuiCommandListDecorator, GuiSelectDeco import wx class RoarCanvasCommandsEdit(): - # {{{ canvasAssetsWindowHide(self, event) - @GuiCommandDecorator("Hide assets window", "Hide assets window", None, None, False) + @GuiCommandDecorator("Hide assets window", "Hide assets window", ["toolHideAssetsWindow.png"], None, False) def canvasAssetsWindowHide(self, event): self.parentFrame.assetsWindow.Show(False) self.parentFrame.menuItemsById[self.canvasAssetsWindowHide.attrDict["id"]].Enable(False) self.parentFrame.menuItemsById[self.canvasAssetsWindowShow.attrDict["id"]].Enable(True) - # }}} - # {{{ canvasAssetsWindowShow(self, event) - @GuiCommandDecorator("Show assets window", "Show assets window", None, None, False) + toolBar = self.parentFrame.toolBarItemsById[self.canvasAssetsWindowHide.attrDict["id"]][0] + toolBar.EnableTool(self.canvasAssetsWindowHide.attrDict["id"], False) + toolBar.EnableTool(self.canvasAssetsWindowShow.attrDict["id"], True) + toolBar.Refresh() + + @GuiCommandDecorator("Show assets window", "Show assets window", ["toolShowAssetsWindow.png"], None, False) def canvasAssetsWindowShow(self, event): self.parentFrame.assetsWindow.Show(True) self.parentFrame.menuItemsById[self.canvasAssetsWindowHide.attrDict["id"]].Enable(True) self.parentFrame.menuItemsById[self.canvasAssetsWindowShow.attrDict["id"]].Enable(False) - # }}} - # {{{ canvasBrush(self, f, idx) + toolBar = self.parentFrame.toolBarItemsById[self.canvasAssetsWindowHide.attrDict["id"]][0] + toolBar.EnableTool(self.canvasAssetsWindowHide.attrDict["id"], True) + toolBar.EnableTool(self.canvasAssetsWindowShow.attrDict["id"], False) + toolBar.Refresh() + @GuiSelectDecorator(0, "Solid brush", "Solid brush", None, None, True) def canvasBrush(self, f, idx): def canvasBrush_(self, event): @@ -30,14 +35,13 @@ class RoarCanvasCommandsEdit(): setattr(canvasBrush_, "attrDict", f.attrList[idx]) setattr(canvasBrush_, "isSelect", True) return canvasBrush_ - # }}} - # {{{ canvasBrushSize(self, f, dimension, incrFlag) + @GuiCommandListDecorator(0, "Decrease brush width", "Decrease brush width", ["toolDecrBrushW.png"], None, None) @GuiCommandListDecorator(1, "Decrease brush height", "Decrease brush height", ["toolDecrBrushH.png"], None, None) - @GuiCommandListDecorator(2, "Decrease brush size", "Decrease brush size", ["toolDecrBrushHW.png"], None, None) + @GuiCommandListDecorator(2, "Decrease brush size", "Decrease brush size", ["toolDecrBrushHW.png"], [wx.ACCEL_CTRL, ord("-")], None) @GuiCommandListDecorator(3, "Increase brush width", "Increase brush width", ["toolIncrBrushW.png"], None, None) @GuiCommandListDecorator(4, "Increase brush height", "Increase brush height", ["toolIncrBrushH.png"], None, None) - @GuiCommandListDecorator(5, "Increase brush size", "Increase brush size", ["toolIncrBrushHW.png"], None, None) + @GuiCommandListDecorator(5, "Increase brush size", "Increase brush size", ["toolIncrBrushHW.png"], [wx.ACCEL_CTRL, ord("+")], None) def canvasBrushSize(self, f, dimension, incrFlag): def canvasBrushSize_(event): if (dimension < 2) and not incrFlag: @@ -49,16 +53,18 @@ class RoarCanvasCommandsEdit(): self.update(brushSize=self.parentCanvas.brushSize) elif dimension == 2: [self.canvasBrushSize(f, dimension_, incrFlag)(None) for dimension_ in [0, 1]] + viewRect = self.parentCanvas.GetViewStart() + eventDc = self.parentCanvas.backend.getDeviceContext(self.parentCanvas.GetClientSize(), self.parentCanvas, viewRect) + self.parentCanvas.applyTool(eventDc, True, None, None, None, self.parentCanvas.brushPos, False, False, False, self.currentTool, viewRect, force=True) setattr(canvasBrushSize_, "attrDict", f.attrList[dimension + (0 if not incrFlag else 3)]) return canvasBrushSize_ - # }}} - # {{{ canvasCanvasSize(self, f, dimension, incrFlag) + @GuiCommandListDecorator(0, "Decrease canvas height", "Decrease canvas height", ["toolDecrCanvasH.png"], None, None) @GuiCommandListDecorator(1, "Decrease canvas width", "Decrease canvas width", ["toolDecrCanvasW.png"], None, None) - @GuiCommandListDecorator(2, "Decrease canvas size", "Decrease canvas size", ["toolDecrCanvasHW.png"], None, None) + @GuiCommandListDecorator(2, "Decrease canvas size", "Decrease canvas size", ["toolDecrCanvasHW.png"], [wx.ACCEL_CTRL | wx.ACCEL_SHIFT, ord("-")], None) @GuiCommandListDecorator(3, "Increase canvas height", "Increase canvas height", ["toolIncrCanvasH.png"], None, None) @GuiCommandListDecorator(4, "Increase canvas width", "Increase canvas width", ["toolIncrCanvasW.png"], None, None) - @GuiCommandListDecorator(5, "Increase canvas size", "Increase canvas size", ["toolIncrCanvasHW.png"], None, None) + @GuiCommandListDecorator(5, "Increase canvas size", "Increase canvas size", ["toolIncrCanvasHW.png"], [wx.ACCEL_CTRL | wx.ACCEL_SHIFT, ord("+")], None) def canvasCanvasSize(self, f, dimension, incrFlag): def canvasCanvasSize_(event): if (dimension < 2) and not incrFlag: @@ -77,8 +83,7 @@ class RoarCanvasCommandsEdit(): [self.canvasCanvasSize(f, dimension_, incrFlag)(None) for dimension_ in [0, 1]] setattr(canvasCanvasSize_, "attrDict", f.attrList[dimension + (0 if not incrFlag else 3)]) return canvasCanvasSize_ - # }}} - # {{{ canvasColour(self, f, idx) + @GuiSelectDecorator(0, "Colour #00", "Colour #00 (Bright White)", None, [wx.ACCEL_CTRL, ord("0")], False) @GuiSelectDecorator(1, "Colour #01", "Colour #01 (Black)", None, [wx.ACCEL_CTRL, ord("1")], False) @GuiSelectDecorator(2, "Colour #02", "Colour #02 (Blue)", None, [wx.ACCEL_CTRL, ord("2")], False) @@ -102,11 +107,13 @@ class RoarCanvasCommandsEdit(): elif event.GetEventType() == wx.wxEVT_TOOL_RCLICKED: self.parentCanvas.brushColours[1] = idx self.update(colours=self.parentCanvas.brushColours) + viewRect = self.parentCanvas.GetViewStart() + eventDc = self.parentCanvas.backend.getDeviceContext(self.parentCanvas.GetClientSize(), self.parentCanvas, viewRect) + self.parentCanvas.applyTool(eventDc, True, None, None, None, self.parentCanvas.brushPos, False, False, False, self.currentTool, viewRect, force=True) setattr(canvasColour_, "attrDict", f.attrList[idx]) setattr(canvasColour_, "isSelect", True) return canvasColour_ - # }}} - # {{{ canvasColourAlpha(self, f, idx) + @GuiSelectDecorator(0, "Transparent colour", "Transparent colour", None, [wx.ACCEL_CTRL | wx.ACCEL_SHIFT, ord("6")], False) def canvasColourAlpha(self, f, idx): def canvasColourAlpha_(event): @@ -115,55 +122,105 @@ class RoarCanvasCommandsEdit(): elif event.GetEventType() == wx.wxEVT_TOOL_RCLICKED: self.parentCanvas.brushColours[1] = -1 self.update(colours=self.parentCanvas.brushColours) + viewRect = self.parentCanvas.GetViewStart() + eventDc = self.parentCanvas.backend.getDeviceContext(self.parentCanvas.GetClientSize(), self.parentCanvas, viewRect) + self.parentCanvas.applyTool(eventDc, True, None, None, None, self.parentCanvas.brushPos, False, False, False, self.currentTool, viewRect, force=True) setattr(canvasColourAlpha_, "attrDict", f.attrList[idx]) setattr(canvasColourAlpha_, "isSelect", True) return canvasColourAlpha_ - # }}} - # {{{ canvasCopy(self, event) + + @GuiSelectDecorator(0, "Transparent colour", "Transparent colour", None, [wx.ACCEL_CTRL | wx.ACCEL_ALT | wx.ACCEL_SHIFT, ord("6")], False) + def canvasColourAlphaBackground(self, f, idx): + def canvasColourAlphaBackground_(event): + self.parentCanvas.brushColours[1] = -1 + self.update(colours=self.parentCanvas.brushColours) + viewRect = self.parentCanvas.GetViewStart() + eventDc = self.parentCanvas.backend.getDeviceContext(self.parentCanvas.GetClientSize(), self.parentCanvas, viewRect) + self.parentCanvas.applyTool(eventDc, True, None, None, None, self.parentCanvas.brushPos, False, False, False, self.currentTool, viewRect, force=True) + setattr(canvasColourAlphaBackground_, "attrDict", f.attrList[idx]) + setattr(canvasColourAlphaBackground_, "isSelect", True) + return canvasColourAlphaBackground_ + + @GuiSelectDecorator(0, "Colour #00", "Colour #00 (Bright White)", None, [wx.ACCEL_CTRL | wx.ACCEL_ALT, ord("0")], False) + @GuiSelectDecorator(1, "Colour #01", "Colour #01 (Black)", None, [wx.ACCEL_CTRL | wx.ACCEL_ALT, ord("1")], False) + @GuiSelectDecorator(2, "Colour #02", "Colour #02 (Blue)", None, [wx.ACCEL_CTRL | wx.ACCEL_ALT, ord("2")], False) + @GuiSelectDecorator(3, "Colour #03", "Colour #03 (Green)", None, [wx.ACCEL_CTRL | wx.ACCEL_ALT, ord("3")], False) + @GuiSelectDecorator(4, "Colour #04", "Colour #04 (Red)", None, [wx.ACCEL_CTRL | wx.ACCEL_ALT, ord("4")], False) + @GuiSelectDecorator(5, "Colour #05", "Colour #05 (Light Red)", None, [wx.ACCEL_CTRL | wx.ACCEL_ALT, ord("5")], False) + @GuiSelectDecorator(6, "Colour #06", "Colour #06 (Pink)", None, [wx.ACCEL_CTRL | wx.ACCEL_ALT, ord("6")], False) + @GuiSelectDecorator(7, "Colour #07", "Colour #07 (Yellow)", None, [wx.ACCEL_CTRL | wx.ACCEL_ALT, ord("7")], False) + @GuiSelectDecorator(8, "Colour #08", "Colour #08 (Light Yellow)", None, [wx.ACCEL_CTRL | wx.ACCEL_ALT, ord("8")], False) + @GuiSelectDecorator(9, "Colour #09", "Colour #09 (Light Green)", None, [wx.ACCEL_CTRL | wx.ACCEL_ALT, ord("9")], False) + @GuiSelectDecorator(10, "Colour #10", "Colour #10 (Cyan)", None, [wx.ACCEL_CTRL | wx.ACCEL_ALT | wx.ACCEL_SHIFT, ord("0")], False) + @GuiSelectDecorator(11, "Colour #11", "Colour #11 (Light Cyan)", None, [wx.ACCEL_CTRL | wx.ACCEL_ALT | wx.ACCEL_SHIFT, ord("1")], False) + @GuiSelectDecorator(12, "Colour #12", "Colour #12 (Light Blue)", None, [wx.ACCEL_CTRL | wx.ACCEL_ALT | wx.ACCEL_SHIFT, ord("2")], False) + @GuiSelectDecorator(13, "Colour #13", "Colour #13 (Light Pink)", None, [wx.ACCEL_CTRL | wx.ACCEL_ALT | wx.ACCEL_SHIFT, ord("3")], False) + @GuiSelectDecorator(14, "Colour #14", "Colour #14 (Grey)", None, [wx.ACCEL_CTRL | wx.ACCEL_ALT | wx.ACCEL_SHIFT, ord("4")], False) + @GuiSelectDecorator(15, "Colour #15", "Colour #15 (Light Grey)", None, [wx.ACCEL_CTRL | wx.ACCEL_ALT | wx.ACCEL_SHIFT, ord("5")], False) + def canvasColourBackground(self, f, idx): + def canvasColourBackground_(event): + self.parentCanvas.brushColours[1] = idx + self.update(colours=self.parentCanvas.brushColours) + viewRect = self.parentCanvas.GetViewStart() + eventDc = self.parentCanvas.backend.getDeviceContext(self.parentCanvas.GetClientSize(), self.parentCanvas, viewRect) + self.parentCanvas.applyTool(eventDc, True, None, None, None, self.parentCanvas.brushPos, False, False, False, self.currentTool, viewRect, force=True) + setattr(canvasColourBackground_, "attrDict", f.attrList[idx]) + setattr(canvasColourBackground_, "isSelect", True) + return canvasColourBackground_ + + @GuiCommandDecorator("Flip colours", "Flip colours", ["toolColoursFlip.png"], [wx.ACCEL_CTRL, ord("I")], True) + def canvasColoursFlip(self, event): + self.parentCanvas.brushColours = [self.parentCanvas.brushColours[1], self.parentCanvas.brushColours[0]] + self.update(colours=self.parentCanvas.brushColours) + viewRect = self.parentCanvas.GetViewStart() + eventDc = self.parentCanvas.backend.getDeviceContext(self.parentCanvas.GetClientSize(), self.parentCanvas, viewRect) + self.parentCanvas.applyTool(eventDc, True, None, None, None, self.parentCanvas.brushPos, False, False, False, self.currentTool, viewRect, force=True) + + + @GuiCommandDecorator("Copy", "&Copy", ["", wx.ART_COPY], None, False) def canvasCopy(self, event): pass - # }}} - # {{{ canvasCut(self, event) + @GuiCommandDecorator("Cut", "Cu&t", ["", wx.ART_CUT], None, False) def canvasCut(self, event): pass - # }}} - # {{{ canvasDelete(self, event) + @GuiCommandDecorator("Delete", "De&lete", ["", wx.ART_DELETE], None, False) def canvasDelete(self, event): pass - # }}} - # {{{ canvasPaste(self, event) + @GuiCommandDecorator("Paste", "&Paste", ["", wx.ART_PASTE], None, False) def canvasPaste(self, event): pass - # }}} - # {{{ canvasRedo(self, event) + @GuiCommandDecorator("Redo", "&Redo", ["", wx.ART_REDO], [wx.ACCEL_CTRL, ord("Y")], False) def canvasRedo(self, event): self.parentCanvas.dispatchDeltaPatches(self.parentCanvas.canvas.journal.popRedo()) self.update(size=self.parentCanvas.canvas.size, undoLevel=self.parentCanvas.canvas.journal.patchesUndoLevel) - # }}} - # {{{ canvasUndo(self, event) + @GuiCommandDecorator("Undo", "&Undo", ["", wx.ART_UNDO], [wx.ACCEL_CTRL, ord("Z")], False) def canvasUndo(self, event): self.parentCanvas.dispatchDeltaPatches(self.parentCanvas.canvas.journal.popUndo()) self.update(size=self.parentCanvas.canvas.size, undoLevel=self.parentCanvas.canvas.journal.patchesUndoLevel) - # }}} + # # __init__(self) def __init__(self): + self.accels = ( + (self.canvasColourBackground(self.canvasColourBackground, 0), self.canvasColourBackground(self.canvasColourBackground, 1), self.canvasColourBackground(self.canvasColourBackground, 2), self.canvasColourBackground(self.canvasColourBackground, 3), self.canvasColourBackground(self.canvasColourBackground, 4), self.canvasColourBackground(self.canvasColourBackground, 5), self.canvasColourBackground(self.canvasColourBackground, 6), self.canvasColourBackground(self.canvasColourBackground, 7), self.canvasColourBackground(self.canvasColourBackground, 8), self.canvasColourBackground(self.canvasColourBackground, 9), self.canvasColourBackground(self.canvasColourBackground, 10), self.canvasColourBackground(self.canvasColourBackground, 11), self.canvasColourBackground(self.canvasColourBackground, 12), self.canvasColourBackground(self.canvasColourBackground, 13), self.canvasColourBackground(self.canvasColourBackground, 14), self.canvasColourBackground(self.canvasColourBackground, 15), self.canvasColourAlphaBackground(self.canvasColourAlphaBackground, 0),), + ) self.menus = ( ("&Edit", self.canvasUndo, self.canvasRedo, NID_MENU_SEP, self.canvasCut, self.canvasCopy, self.canvasPaste, self.canvasDelete, NID_MENU_SEP, - ("Canvas size", self.canvasCanvasSize(self.canvasCanvasSize, 1, True), self.canvasCanvasSize(self.canvasCanvasSize, 1, False), self.canvasCanvasSize(self.canvasCanvasSize, 0, True), self.canvasCanvasSize(self.canvasCanvasSize, 0, False), NID_MENU_SEP, - self.canvasCanvasSize(self.canvasCanvasSize, 2, True), self.canvasCanvasSize(self.canvasCanvasSize, 2, False),), ("Brush size", self.canvasBrushSize(self.canvasBrushSize, 0, True), self.canvasBrushSize(self.canvasBrushSize, 0, False), self.canvasBrushSize(self.canvasBrushSize, 1, True), self.canvasBrushSize(self.canvasBrushSize, 1, False), NID_MENU_SEP, self.canvasBrushSize(self.canvasBrushSize, 2, True), self.canvasBrushSize(self.canvasBrushSize, 2, False),), + ("Canvas size", self.canvasCanvasSize(self.canvasCanvasSize, 1, True), self.canvasCanvasSize(self.canvasCanvasSize, 1, False), self.canvasCanvasSize(self.canvasCanvasSize, 0, True), self.canvasCanvasSize(self.canvasCanvasSize, 0, False), NID_MENU_SEP, + self.canvasCanvasSize(self.canvasCanvasSize, 2, True), self.canvasCanvasSize(self.canvasCanvasSize, 2, False),), + self.canvasColoursFlip, NID_MENU_SEP, self.canvasBrush(self.canvasBrush, 0), NID_MENU_SEP, self.canvasAssetsWindowHide, self.canvasAssetsWindowShow, diff --git a/libroar/RoarCanvasCommandsFile.py b/libroar/RoarCanvasCommandsFile.py index a87b884..0e51535 100644 --- a/libroar/RoarCanvasCommandsFile.py +++ b/libroar/RoarCanvasCommandsFile.py @@ -21,7 +21,6 @@ from RtlPlatform import getLocalConfPathName import io, os, wx class RoarCanvasCommandsFile(): - # {{{ _import(self, f, newDirty, pathName) def _import(self, f, newDirty, pathName): rc = False self.parentCanvas.SetCursor(wx.Cursor(wx.CURSOR_WAIT)) @@ -41,10 +40,9 @@ class RoarCanvasCommandsFile(): dialogChoice = dialog.ShowModal() self.parentCanvas.SetCursor(wx.Cursor(wx.NullCursor)) return rc, newPathName - # }}} - # {{{ _importFile(self, f, newDirty, wildcard) + def _importFile(self, f, newDirty, wildcard): - with wx.FileDialog(self.parentCanvas, "Open", os.getcwd(), "", wildcard, wx.FD_OPEN) as dialog: + with wx.FileDialog(self.parentCanvas, "Open...", os.getcwd(), "", wildcard, wx.FD_OPEN) as dialog: if self.lastDir != None: dialog.SetDirectory(self.lastDir) if dialog.ShowModal() == wx.ID_CANCEL: @@ -52,16 +50,14 @@ class RoarCanvasCommandsFile(): elif self._promptSaveChanges(): pathName = dialog.GetPath(); self.lastDir = os.path.dirname(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) + def _promptSaveChanges(self): if self.parentCanvas.dirty: message = "Do you want to save changes to {}?".format(self.canvasPathName if self.canvasPathName != None else "(Untitled)") @@ -77,8 +73,7 @@ class RoarCanvasCommandsFile(): return False else: 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]: @@ -95,16 +90,14 @@ class RoarCanvasCommandsFile(): 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) + @GuiCommandDecorator("Exit", "E&xit", None, [wx.ACCEL_CTRL, ord("X")], None) def canvasExit(self, event): if self._promptSaveChanges(): self.parentFrame.Close(True) - # }}} - # {{{ canvasExportAsAnsi(self, event) + @GuiCommandDecorator("Export as ANSI...", "Export as &ANSI...", None, None, None) def canvasExportAsAnsi(self, event): with wx.FileDialog(self.parentFrame, "Save As...", os.getcwd(), "", "ANSI files (*.ans;*.txt)|*.ans;*.txt|All Files (*.*)|*.*", wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) as dialog: @@ -119,8 +112,7 @@ class RoarCanvasCommandsFile(): self.parentCanvas.canvas.exportStore.exportAnsiFile(self.parentCanvas.canvas.map, self.parentCanvas.canvas.size, outFile) self.parentCanvas.SetCursor(wx.Cursor(wx.NullCursor)) return True - # }}} - # {{{ canvasExportAsPng(self, event) + @GuiCommandDecorator("Export as PNG...", "Export as PN&G...", None, None, None) def canvasExportAsPng(self, event): with wx.FileDialog(self.parentFrame, "Save As...", os.getcwd(), "", "PNG (*.png)|*.png|All Files (*.*)|*.*", wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) as dialog: @@ -134,8 +126,7 @@ class RoarCanvasCommandsFile(): self.parentCanvas.canvas.exportStore.exportBitmapToPngFile(self.parentCanvas.backend.canvasBitmap, outPathName, wx.BITMAP_TYPE_PNG) self.parentCanvas.SetCursor(wx.Cursor(wx.NullCursor)) return True - # }}} - # {{{ canvasExportImgur(self, event) + @GuiCommandDecorator("Export to Imgur...", "Export to I&mgur...", None, None, haveImgurApiKey and haveUrllib) def canvasExportImgur(self, event): self.parentCanvas.SetCursor(wx.Cursor(wx.CURSOR_WAIT)) @@ -147,8 +138,7 @@ class RoarCanvasCommandsFile(): wx.MessageBox("Exported to Imgur: {}".format(result), "Export to Imgur", wx.ICON_INFORMATION | wx.OK) else: wx.MessageBox("Failed to export to Imgur: {}".format(result), "Export to Imgur", wx.ICON_EXCLAMATION | wx.OK) - # }}} - # {{{ canvasExportPastebin(self, event) + @GuiCommandDecorator("Export to Pastebin...", "Export to Pasteb&in...", None, None, haveUrllib) def canvasExportPastebin(self, event): self.parentCanvas.SetCursor(wx.Cursor(wx.CURSOR_WAIT)) @@ -162,8 +152,7 @@ class RoarCanvasCommandsFile(): wx.MessageBox("Exported to Pastebin: " + pasteResult, "Export to Pastebin", wx.OK|wx.ICON_INFORMATION) else: wx.MessageBox("Failed to export to Pastebin: " + pasteResult, "Export to Pastebin", wx.OK|wx.ICON_EXCLAMATION) - # }}} - # {{{ canvasExportToClipboard(self, event) + @GuiCommandDecorator("Export to clipboard", "Export to &clipboard", None, None, None) def canvasExportToClipboard(self, event): self.parentCanvas.SetCursor(wx.Cursor(wx.CURSOR_WAIT)) @@ -173,17 +162,15 @@ class RoarCanvasCommandsFile(): wx.TheClipboard.Close() self.parentCanvas.SetCursor(wx.Cursor(wx.NullCursor)) return True - # }}} - # {{{ canvasImportAnsi(self, event) + @GuiCommandDecorator("Import ANSI...", "Import &ANSI...", None, None, None) def canvasImportAnsi(self, event): def canvasImportAnsi_(pathName): rc, error = self.parentCanvas.canvas.importStore.importAnsiFile(pathName) return (rc, error, self.parentCanvas.canvas.importStore.outMap, pathName, self.parentCanvas.canvas.importStore.inSize) self._importFile(canvasImportAnsi_, True, "ANSI files (*.ans;*.txt)|*.ans;*.txt|All Files (*.*)|*.*") - # }}} - # {{{ canvasImportFromClipboard(self, event) + @GuiCommandDecorator("Import from clipboard", "Import from &clipboard", None, None, None) def canvasImportFromClipboard(self, event): def canvasImportFromClipboard_(pathName): @@ -199,17 +186,15 @@ class RoarCanvasCommandsFile(): return (rc, error, self.parentCanvas.canvas.importStore.outMap, None, self.parentCanvas.canvas.importStore.inSize) if self._promptSaveChanges(): self._import(canvasImportFromClipboard_, True, None) - # }}} - # {{{ canvasImportSauce(self, event) + @GuiCommandDecorator("Import SAUCE...", "Import &SAUCE...", None, None, None) def canvasImportSauce(self, event): def canvasImportSauce_(pathName): rc, error = self.parentCanvas.canvas.importStore.importSauceFile(pathName) return (rc, error, self.parentCanvas.canvas.importStore.outMap, pathName, self.parentCanvas.canvas.importStore.inSize) self._importFile(canvasImportSauce_, True, "SAUCE files (*.ans;*.txt)|*.ans;*.txt|All Files (*.*)|*.*") - # }}} - # {{{ canvasNew(self, event, newCanvasSize=None) + @GuiCommandDecorator("New", "&New", ["", wx.ART_NEW], [wx.ACCEL_CTRL, ord("N")], None) def canvasNew(self, event, newCanvasSize=None): def canvasImportEmpty(pathName): @@ -220,8 +205,7 @@ class RoarCanvasCommandsFile(): return (True, "", newMap, None, newCanvasSize) if self._promptSaveChanges(): self._import(canvasImportEmpty, False, None) - # }}} - # {{{ canvasOpen(self, event) + @GuiCommandDecorator("Open", "&Open", ["", wx.ART_FILE_OPEN], [wx.ACCEL_CTRL, ord("O")], None) def canvasOpen(self, event): def canvasImportmIRC(pathName): @@ -230,16 +214,14 @@ class RoarCanvasCommandsFile(): 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) + @GuiCommandDecorator("Save", "&Save", ["", wx.ART_FILE_SAVE], [wx.ACCEL_CTRL, ord("S")], None) def canvasSave(self, event, newDirty=False): if self.canvasPathName == None: @@ -256,8 +238,7 @@ class RoarCanvasCommandsFile(): return True except IOError as error: return False - # }}} - # {{{ canvasSaveAs(self, event) + @GuiCommandDecorator("Save As...", "Save &As...", ["", wx.ART_FILE_SAVE_AS], None, None) def canvasSaveAs(self, event): with wx.FileDialog(self.parentCanvas, "Save As", os.getcwd(), "", "mIRC art files (*.txt)|*.txt|All Files (*.*)|*.*", wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) as dialog: @@ -269,12 +250,13 @@ class RoarCanvasCommandsFile(): self.canvasPathName = dialog.GetPath(); self.lastDir = os.path.dirname(self.canvasPathName); if self.canvasSave(event, newDirty=True): self._pushRecent(self.canvasPathName) - # }}} + # # __init__(self) def __init__(self): self.imgurApiKey, self.lastFiles, self.lastDir = ImgurApiKey.imgurApiKey if haveImgurApiKey else None, [], None + self.accels = () self.menus = ( ("&File", self.canvasNew, self.canvasOpen, self.canvasOpenRecent, self.canvasSave, self.canvasSaveAs, NID_MENU_SEP, diff --git a/libroar/RoarCanvasCommandsHelp.py b/libroar/RoarCanvasCommandsHelp.py index a7f266b..7066bdd 100644 --- a/libroar/RoarCanvasCommandsHelp.py +++ b/libroar/RoarCanvasCommandsHelp.py @@ -8,15 +8,15 @@ from GuiFrame import GuiCommandDecorator from RoarWindowAbout import RoarWindowAbout class RoarCanvasCommandsHelp(): - # {{{ canvasAbout(self, event) @GuiCommandDecorator("About", "&About", None, None, True) def canvasAbout(self, event): RoarWindowAbout(self.parentFrame) - # }}} + # # __init__(self) def __init__(self): + self.accels = () self.menus, self.toolBars = (("&Help", self.canvasAbout,),), () # vim:expandtab foldmethod=marker sw=4 ts=4 tw=0 diff --git a/libroar/RoarCanvasCommandsOperators.py b/libroar/RoarCanvasCommandsOperators.py index f02867d..a13014d 100644 --- a/libroar/RoarCanvasCommandsOperators.py +++ b/libroar/RoarCanvasCommandsOperators.py @@ -14,10 +14,9 @@ from ToolObject import ToolObject import copy, wx class RoarCanvasCommandsOperators(): - # {{{ canvasOperator(self, f, idx) @GuiCommandListDecorator(0, "Flip", "&Flip", None, None, None) @GuiCommandListDecorator(1, "Flip horizontally", "Flip &horizontally", None, None, None) - @GuiCommandListDecorator(2, "Invert", "&Invert", None, None, None) + @GuiCommandListDecorator(2, "Invert colours", "&Invert colours", None, None, None) @GuiCommandListDecorator(3, "Rotate", "&Rotate", None, None, None) @GuiCommandListDecorator(4, "Tile", "&Tile", None, None, None) def canvasOperator(self, f, idx): @@ -27,11 +26,12 @@ class RoarCanvasCommandsOperators(): self.parentCanvas.applyOperator(self.currentTool, self.parentCanvas.brushPos, None, False, self.currentOperator, self.parentCanvas.GetViewStart()) setattr(canvasOperator_, "attrDict", f.attrList[idx]) return canvasOperator_ - # }}} + # # __init__(self) def __init__(self): + self.accels = () self.menus = ( ("&Operators", self.canvasOperator(self.canvasOperator, 0), self.canvasOperator(self.canvasOperator, 1), self.canvasOperator(self.canvasOperator, 2), self.canvasOperator(self.canvasOperator, 3), self.canvasOperator(self.canvasOperator, 4), diff --git a/libroar/RoarCanvasCommandsTools.py b/libroar/RoarCanvasCommandsTools.py index 05e3491..d13c7bd 100644 --- a/libroar/RoarCanvasCommandsTools.py +++ b/libroar/RoarCanvasCommandsTools.py @@ -14,7 +14,6 @@ from ToolText import ToolText import wx class RoarCanvasCommandsTools(): - # {{{ canvasTool(self, f, idx) @GuiSelectDecorator(0, "Circle", "&Circle", ["toolCircle.png"], [wx.ACCEL_CTRL, ord("C")], False) @GuiSelectDecorator(1, "Cursor", "C&ursor", ["toolCursor.png"], [wx.ACCEL_CTRL, ord("U")], False) @GuiSelectDecorator(2, "Fill", "&Fill", ["toolFill.png"], [wx.ACCEL_CTRL, ord("F")], False) @@ -33,23 +32,24 @@ class RoarCanvasCommandsTools(): self.currentTool = self.currentTool() self.currentOperator, self.operatorState = None, None self.parentFrame.menuItemsById[self.canvasTool.attrList[idx]["id"]].Check(True) - toolBar = self.parentFrame.toolBarItemsById[self.canvasTool.attrList[idx]["id"]].GetToolBar() - toolBar.ToggleTool(self.canvasTool.attrList[idx]["id"], True) + toolBar = self.parentFrame.toolBarItemsById[self.canvasTool.attrList[idx]["id"]][0] + toolBar.ToggleTool(self.canvasTool.attrList[idx]["id"], True); toolBar.Refresh(); if self.currentTool != None: self.update(toolName=self.currentTool.name) - viewRect = self.parentCanvas.GetViewStart() - eventDc = self.parentCanvas.backend.getDeviceContext(self.parentCanvas.GetClientSize(), self.parentCanvas, viewRect) - self.parentCanvas.applyTool(eventDc, True, None, None, None, self.parentCanvas.brushPos, False, False, False, self.currentTool, viewRect) else: self.update(toolName="Cursor") + viewRect = self.parentCanvas.GetViewStart() + eventDc = self.parentCanvas.backend.getDeviceContext(self.parentCanvas.GetClientSize(), self.parentCanvas, viewRect) + self.parentCanvas.applyTool(eventDc, True, None, None, None, self.parentCanvas.brushPos, False, False, False, self.currentTool, viewRect, force=True) setattr(canvasTool_, "attrDict", f.attrList[idx]) setattr(canvasTool_, "isSelect", True) return canvasTool_ - # }}} + # # __init__(self) def __init__(self): + self.accels = () self.menus = ( ("&Tools", self.canvasTool(self.canvasTool, 1), self.canvasTool(self.canvasTool, 5), self.canvasTool(self.canvasTool, 0), self.canvasTool(self.canvasTool, 2), self.canvasTool(self.canvasTool, 3), self.canvasTool(self.canvasTool, 6), self.canvasTool(self.canvasTool, 4), diff --git a/libroar/RoarCanvasWindow.py b/libroar/RoarCanvasWindow.py index 450509d..fb097d3 100644 --- a/libroar/RoarCanvasWindow.py +++ b/libroar/RoarCanvasWindow.py @@ -10,11 +10,9 @@ from ToolText import ToolText import copy, json, wx, sys class RoarCanvasWindowDropTarget(wx.TextDropTarget): - # {{{ done(self) def done(self): self.inProgress = False - # }}} - # {{{ OnDropText(self, x, y, data) + def OnDropText(self, x, y, data): rc = False if ((self.parent.commands.currentTool.__class__ != ToolObject) \ @@ -37,14 +35,12 @@ class RoarCanvasWindowDropTarget(wx.TextDropTarget): with wx.MessageDialog(self.parent, "Error: {}".format(sys.exc_info()[1]), "", wx.OK | wx.OK_DEFAULT) as dialog: dialogChoice = dialog.ShowModal() return rc - # }}} - # {{{ __init__(self, parent) + def __init__(self, parent): super().__init__(); self.inProgress, self.parent = False, parent; - # }}} + class RoarCanvasWindow(GuiWindow): - # {{{ _drawPatch(self, eventDc, isCursor, patch) def _drawPatch(self, eventDc, isCursor, patch): if not self.canvas.dirtyCursor: self.backend.drawCursorMaskWithJournal(self.canvas, self.canvas.journal, eventDc) @@ -52,9 +48,8 @@ class RoarCanvasWindow(GuiWindow): if self.backend.drawPatch(self.canvas, eventDc, patch) and isCursor: patchDeltaCell = self.canvas.map[patch[1]][patch[0]]; patchDelta = [*patch[0:2], *patchDeltaCell]; self.canvas.journal.pushCursor(patchDelta) - # }}} - # {{{ applyOperator(self, currentTool, mapPoint, mouseLeftDown, mousePoint, operator, viewRect) + def applyOperator(self, currentTool, mapPoint, mouseLeftDown, mousePoint, operator, viewRect): self.canvas.dirtyCursor = False if (currentTool.__class__ == ToolObject) \ @@ -94,15 +89,14 @@ class RoarCanvasWindow(GuiWindow): self.canvas.journal.end() self.commands.update(dirty=self.dirty, undoLevel=self.canvas.journal.patchesUndoLevel) eventDc.SetDeviceOrigin(*eventDcOrigin) - # }}} - # {{{ applyTool(self, eventDc, eventMouse, keyChar, keyCode, keyModifiers, mapPoint, mouseDragging, mouseLeftDown, mouseRightDown, tool, viewRect) - def applyTool(self, eventDc, eventMouse, keyChar, keyCode, keyModifiers, mapPoint, mouseDragging, mouseLeftDown, mouseRightDown, tool, viewRect): + + def applyTool(self, eventDc, eventMouse, keyChar, keyCode, keyModifiers, mapPoint, mouseDragging, mouseLeftDown, mouseRightDown, tool, viewRect, force=False): eventDcOrigin = eventDc.GetDeviceOrigin(); eventDc.SetDeviceOrigin(0, 0); - if mapPoint != None: - mapPoint = [a + b for a, b in zip(mapPoint, viewRect)] dirty, self.canvas.dirtyCursor, rc = False, False, False self.canvas.journal.begin() if eventMouse: + if force: + self.lastCellState = None if ((mapPoint[0] < self.canvas.size[0]) \ and (mapPoint[1] < self.canvas.size[1])) \ and ((self.lastCellState == None) \ @@ -140,8 +134,7 @@ class RoarCanvasWindow(GuiWindow): self.commands.update(undoInhibit=False) eventDc.SetDeviceOrigin(*eventDcOrigin) return rc - # }}} - # {{{ dispatchDeltaPatches(self, deltaPatches) + def dispatchDeltaPatches(self, deltaPatches): eventDc = self.backend.getDeviceContext(self.GetClientSize(), self) eventDcOrigin = eventDc.GetDeviceOrigin(); eventDc.SetDeviceOrigin(0, 0); @@ -158,19 +151,17 @@ class RoarCanvasWindow(GuiWindow): else: self.canvas._commitPatch(patch); self.backend.drawPatch(self.canvas, eventDc, patch) eventDc.SetDeviceOrigin(*eventDcOrigin) - # }}} - # {{{ dispatchPatch(self, eventDc, isCursor, patch) + def dispatchPatch(self, eventDc, isCursor, patch): if self.canvas.dispatchPatch(isCursor, patch, False if isCursor else True): self._drawPatch(eventDc, isCursor, patch) - # }}} - # {{{ dispatchPatchSingle(self, eventDc, isCursor, patch) + def dispatchPatchSingle(self, eventDc, isCursor, patch): if self.canvas.dispatchPatchSingle(isCursor, patch, False if isCursor else True): self._drawPatch(eventDc, isCursor, patch) - # }}} - # {{{ resize(self, newSize, commitUndo=True) + def resize(self, newSize, commitUndo=True): + viewRect = self.GetViewStart() oldSize = [0, 0] if self.canvas.map == None else self.canvas.size deltaSize = [b - a for a, b in zip(oldSize, newSize)] if self.canvas.resize(newSize, commitUndo): @@ -187,9 +178,9 @@ class RoarCanvasWindow(GuiWindow): for numNewCol in range(newSize[0]): self._drawPatch(eventDc, False, [numNewCol, numNewRow, 1, 1, 0, " "]) eventDc.SetDeviceOrigin(*eventDcOrigin) + self.Scroll(*viewRect) self.commands.update(size=newSize, undoLevel=self.canvas.journal.patchesUndoLevel) - # }}} - # {{{ update(self, newSize, commitUndo=True, newCanvas=None) + def update(self, newSize, commitUndo=True, newCanvas=None): self.resize(newSize, commitUndo) self.canvas.update(newSize, newCanvas) @@ -199,9 +190,8 @@ class RoarCanvasWindow(GuiWindow): for numCol in range(newSize[0]): self.backend.drawPatch(self.canvas, eventDc, [numCol, numRow, *self.canvas.map[numRow][numCol]]) eventDc.SetDeviceOrigin(*eventDcOrigin) - # }}} - # {{{ onKeyboardInput(self, event) + def onKeyboardInput(self, event): keyCode, keyModifiers = event.GetKeyCode(), event.GetModifiers() viewRect = self.GetViewStart(); eventDc = self.backend.getDeviceContext(self.GetClientSize(), self, viewRect); @@ -245,12 +235,10 @@ class RoarCanvasWindow(GuiWindow): else: if not self.applyTool(eventDc, False, chr(event.GetUnicodeKey()), keyCode, keyModifiers, None, None, None, None, self.commands.currentTool, viewRect): event.Skip() - # }}} - # {{{ onEnterWindow(self, event) + def onEnterWindow(self, event): self.lastCellState = None - # }}} - # {{{ onLeaveWindow(self, event) + def onLeaveWindow(self, event): if False: eventDc = self.backend.getDeviceContext(self.GetClientSize(), self, self.GetViewStart()) @@ -258,12 +246,13 @@ class RoarCanvasWindow(GuiWindow): self.backend.drawCursorMaskWithJournal(self.canvas, self.canvas.journal, eventDc) eventDc.SetDeviceOrigin(*eventDcOrigin) self.lastCellState = None - # }}} - # {{{ onMouseInput(self, event) + def onMouseInput(self, event): viewRect = self.GetViewStart(); eventDc = self.backend.getDeviceContext(self.GetClientSize(), self, viewRect); mouseDragging, mouseLeftDown, mouseRightDown = event.Dragging(), event.LeftIsDown(), event.RightIsDown() mapPoint = self.backend.xlateEventPoint(event, eventDc, viewRect) + if viewRect != (0, 0): + mapPoint = [a + b for a, b in zip(mapPoint, viewRect)] if self.commands.currentOperator != None: self.applyOperator(self.commands.currentTool, mapPoint, mouseLeftDown, event.GetLogicalPosition(eventDc), self.commands.currentOperator, viewRect) elif mouseRightDown \ @@ -272,8 +261,7 @@ class RoarCanvasWindow(GuiWindow): self.popupEventDc = eventDc; self.PopupMenu(self.operatorsMenu); self.popupEventDc = None; elif not self.applyTool(eventDc, True, None, None, event.GetModifiers(), mapPoint, mouseDragging, mouseLeftDown, mouseRightDown, self.commands.currentTool, viewRect): event.Skip() - # }}} - # {{{ onMouseWheel(self, event) + def onMouseWheel(self, event): if event.GetModifiers() == wx.MOD_CONTROL: cd = +1 if event.GetWheelRotation() >= event.GetWheelDelta() else -1 @@ -290,15 +278,14 @@ class RoarCanvasWindow(GuiWindow): eventDc.SetDeviceOrigin(*eventDcOrigin) else: event.Skip() - # }}} - # {{{ onPaint(self, event) + def onPaint(self, event): eventDc = self.backend.getDeviceContext(self.GetClientSize(), self) eventDcOrigin = eventDc.GetDeviceOrigin(); eventDc.SetDeviceOrigin(0, 0); self.backend.drawCursorMaskWithJournal(self.canvas, self.canvas.journal, eventDc) eventDc.SetDeviceOrigin(*eventDcOrigin) self.backend.onPaint(self.GetClientSize(), self, self.GetViewStart()) - # }}} + # # __init__(self, backend, canvas, cellSize, commands, parent, parentFrame, pos, scrollStep, size): initialisation method diff --git a/libroar/RoarClient.py b/libroar/RoarClient.py index 84efa9d..23774d0 100644 --- a/libroar/RoarClient.py +++ b/libroar/RoarClient.py @@ -15,27 +15,23 @@ from glob import glob import os, random, sys, wx class RoarClient(GuiFrame): - # {{{ _getIconPathName(self) def _getIconPathName(self): iconPathNames = glob(os.path.join("assets", "images", "logo*.bmp")) return iconPathNames[random.randint(0, len(iconPathNames) - 1)] - # }}} - # {{{ _initToolBitmaps(self, toolBars) + def _initToolBitmaps(self, toolBars): basePathName = os.path.join(os.path.dirname(sys.argv[0]), "assets", "images") for toolBar in toolBars: for toolBarItem in [i for i in toolBar if i != NID_TOOLBAR_HSEP]: toolBarItem.attrDict["icon"] = self.loadBitmap(basePathName, toolBarItem.attrDict["icon"]) - # }}} - # {{{ onChar(self, event) + def onChar(self, event): self.canvasPanel.onKeyboardInput(event) - # }}} - # {{{ onMouseWheel(self, event) + def onMouseWheel(self, event): self.canvasPanel.GetEventHandler().ProcessEvent(event) - # }}} + # # __init__(self, parent, defaultCanvasPos=(0, 75), defaultCanvasSize=(100, 30), defaultCellSize=(7, 14), size=(840, 630), title=""): initialisation method @@ -43,7 +39,7 @@ class RoarClient(GuiFrame): super().__init__(self._getIconPathName(), size, parent, title) self.canvas = Canvas(defaultCanvasSize) self.canvasPanel = RoarCanvasWindow(GuiCanvasWxBackend, self.canvas, defaultCellSize, RoarCanvasCommands, self.panelSkin, self, defaultCanvasPos, defaultCellSize, defaultCanvasSize) - self.loadAccels(self.canvasPanel.commands.menus, self.canvasPanel.commands.toolBars) + self.loadAccels(self.canvasPanel.commands.accels, self.canvasPanel.commands.menus, self.canvasPanel.commands.toolBars) self.loadMenus(self.canvasPanel.commands.menus) self._initToolBitmaps(self.canvasPanel.commands.toolBars) self.loadToolBars(self.canvasPanel.commands.toolBars) diff --git a/libroar/RoarWindowAbout.py b/libroar/RoarWindowAbout.py index df93021..f6217fe 100644 --- a/libroar/RoarWindowAbout.py +++ b/libroar/RoarWindowAbout.py @@ -8,10 +8,9 @@ from glob import glob import os, random, wx, wx.adv class RoarWindowAbout(wx.Dialog): - # {{{ onButtonRoar(self, event) def onButtonRoar(self, event): self.Destroy() - # }}} + # # __init__(self, parent, minSize=(320, 300), title="About roar") diff --git a/librtl/IrcClient.py b/librtl/IrcClient.py index 15c3697..7f1cec4 100644 --- a/librtl/IrcClient.py +++ b/librtl/IrcClient.py @@ -11,13 +11,11 @@ import select, socket, time class IrcClient: """Non-blocking abstraction over the IRC protocol""" - # {{{ close(self): Close connection to server def close(self): if self.clientSocket != None: self.clientSocket.close() self.clientSocket = self.clientSocketFile = None; - # }}} - # {{{ connect(self, localAddr=None, preferFamily=socket.AF_INET, timeout=None): Connect to server and register w/ optional timeout + def connect(self, localAddr=None, preferFamily=socket.AF_INET, timeout=None): gaiInfo = socket.getaddrinfo(self.serverHname, self.serverPort, preferFamily, socket.SOCK_STREAM, socket.IPPROTO_TCP) @@ -41,8 +39,7 @@ class IrcClient: self.queue("NICK", self.clientNick) self.queue("USER", self.clientIdent, "0", "0", self.clientGecos) return True - # }}} - # {{{ queue(self, *args): Parse and queue single line to server from list + def queue(self, *args): msg = ""; argNumMax = len(args); for argNum in range(argNumMax): @@ -51,8 +48,7 @@ class IrcClient: else: msg += args[argNum] + " " self.clientQueue.append((msg + "\r\n").encode()) - # }}} - # {{{ readline(self, timeout=30): Read and parse single line from server into canonicalised list, honouring timers + def readline(self, timeout=30): if self.clientNextTimeout: timeNow = time.time() @@ -85,8 +81,7 @@ class IrcClient: else: msg = [""] + msg[0:] return msg - # }}} - # {{{ unqueue(self, timeout=15): Send all queued lines to server, honouring timers + def unqueue(self, timeout=15): while self.clientQueue: msg = self.clientQueue[0]; msgLen = len(msg); msgBytesSent = 0; @@ -111,7 +106,7 @@ class IrcClient: msg = msg[msgBytesSent:]; msgLen -= msgBytesSent; del self.clientQueue[0] return True - # }}} + # # __init__(self, serverHname, serverPort, clientNick, clientIdent, clientGecos): initialisation method diff --git a/librtl/RtlPlatform.py b/librtl/RtlPlatform.py index 4da6389..b2e4d96 100644 --- a/librtl/RtlPlatform.py +++ b/librtl/RtlPlatform.py @@ -7,10 +7,9 @@ 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 diff --git a/libtools/Tool.py b/libtools/Tool.py index e23bd84..56801b2 100644 --- a/libtools/Tool.py +++ b/libtools/Tool.py @@ -5,13 +5,11 @@ # class Tool(object): - # {{{ onKeyboardEvent(self, atPoint, brushColours, brushPos, brushSize, canvas, dispatchFn, eventDc, keyChar, keyCode, keyModifiers, mapPoint) def onKeyboardEvent(self, atPoint, brushColours, brushPos, brushSize, canvas, dispatchFn, eventDc, keyChar, keyCode, keyModifiers, mapPoint): return False, False - # }}} - # {{{ onMouseEvent(self, atPoint, brushColours, brushPos, brushSize, dispatchFn, eventDc, mapPoint, mouseDragging, mouseLeftDown, mouseRightDown) + def onMouseEvent(self, atPoint, brushColours, brushPos, brushSize, canvas, dispatchFn, eventDc, keyModifiers, mapPoint, mouseDragging, mouseLeftDown, mouseRightDown): return False, False - # }}} + # vim:expandtab foldmethod=marker sw=4 ts=4 tw=120 diff --git a/libtools/ToolCircle.py b/libtools/ToolCircle.py index 1cf3960..f2c0cc4 100644 --- a/libtools/ToolCircle.py +++ b/libtools/ToolCircle.py @@ -12,28 +12,43 @@ class ToolCircle(Tool): # # onMouseEvent(self, atPoint, brushColours, brushPos, brushSize, canvas, dispatchFn, eventDc, keyModifiers, mapPoint, mouseDragging, mouseLeftDown, mouseRightDown) def onMouseEvent(self, atPoint, brushColours, brushPos, brushSize, canvas, dispatchFn, eventDc, keyModifiers, mapPoint, mouseDragging, mouseLeftDown, mouseRightDown): - brushColours, dirty = brushColours.copy(), False - if mouseLeftDown: - brushColours[1] = brushColours[0] - elif mouseRightDown: - brushColours[0] = brushColours[1] - else: - brushColours[1] = brushColours[0] - _brushSize = brushSize[0] * 2 - originPoint, radius = (_brushSize / 2, _brushSize / 2), _brushSize + brushColours, brushSize, dirty = list(brushColours), [brushSize[0] * 2, brushSize[1]], False + originPoint, radius = (brushSize[0] / 2, brushSize[0] / 2), brushSize[0] + if mouseRightDown: + brushColours = [brushColours[1], brushColours[0]] + cells = [] for brushY in range(-radius, radius + 1): + cells += [[]] for brushX in range(-radius, radius + 1): if ((brushX ** 2) + (brushY ** 2) < (((radius ** 2) + radius) * 0.8)): - patch = [ \ - mapPoint[0] + int(originPoint[0] + brushX), \ - mapPoint[1] + int(originPoint[1] + brushY), \ - *brushColours, 0, " "] - if mouseLeftDown or mouseRightDown: - if not dirty: - dirty = True - dispatchFn(eventDc, False, patch); dispatchFn(eventDc, True, patch); + cells[-1] += [[mapPoint[i] + int(originPoint[i] + o) for i, o in zip((0, 1,), (brushX, brushY,))]] + if cells[-1] == []: + del cells[-1] + for numRow in range(len(cells)): + for numCol in range(len(cells[numRow])): + if ((numRow == 0) or (numRow == (len(cells) - 1))) \ + or ((numCol == 0) or (numCol == (len(cells[numRow]) - 1))): + patch = [*cells[numRow][numCol], brushColours[0], brushColours[0], 0, " "] + elif ((numRow > 0) and (cells[numRow][numCol][0] < cells[numRow - 1][0][0])) \ + or ((numRow < len(cells)) and (cells[numRow][numCol][0] < cells[numRow + 1][0][0])): + patch = [*cells[numRow][numCol], brushColours[0], brushColours[0], 0, " "] + elif ((numRow > 0) and (cells[numRow][numCol][0] > cells[numRow - 1][-1][0])) \ + or ((numRow < len(cells)) and (cells[numRow][numCol][0] > cells[numRow + 1][-1][0])): + patch = [*cells[numRow][numCol], brushColours[0], brushColours[0], 0, " "] + elif brushColours[1] == -1: + if (cells[numRow][numCol][0] < canvas.size[0]) \ + and (cells[numRow][numCol][1] < canvas.size[1]): + patch = [cells[numRow][numCol][0], cells[numRow][numCol][1], *canvas.map[cells[numRow][numCol][1]][cells[numRow][numCol][0]]] else: - dispatchFn(eventDc, True, patch) + patch = [*cells[numRow][numCol], brushColours[1], brushColours[1], 0, " "] + else: + patch = [*cells[numRow][numCol], brushColours[1], brushColours[1], 0, " "] + if mouseLeftDown or mouseRightDown: + if not dirty: + dirty = True + dispatchFn(eventDc, False, patch); dispatchFn(eventDc, True, patch); + else: + dispatchFn(eventDc, True, patch) return True, dirty # vim:expandtab foldmethod=marker sw=4 ts=4 tw=120 diff --git a/libtools/ToolFill.py b/libtools/ToolFill.py index 90280d0..1888c16 100644 --- a/libtools/ToolFill.py +++ b/libtools/ToolFill.py @@ -5,6 +5,7 @@ # from Tool import Tool +import wx class ToolFill(Tool): name = "Fill" @@ -14,15 +15,19 @@ class ToolFill(Tool): def onMouseEvent(self, atPoint, brushColours, brushPos, brushSize, canvas, dispatchFn, eventDc, keyModifiers, mapPoint, mouseDragging, mouseLeftDown, mouseRightDown): dirty, pointsDone, pointStack, testChar, testColour = False, [], [list(mapPoint)], canvas.map[mapPoint[1]][mapPoint[0]][3], canvas.map[mapPoint[1]][mapPoint[0]][0:2] if mouseLeftDown or mouseRightDown: + if mouseLeftDown: + fillColour = brushColours[0] + else: + fillColour = brushColours[1] while len(pointStack) > 0: point = pointStack.pop() pointCell = canvas.map[point[1]][point[0]] - if ((pointCell[1] == testColour[1]) and ((pointCell[3] == testChar) or mouseRightDown)) \ + if ((pointCell[1] == testColour[1]) and ((pointCell[3] == testChar) or (keyModifiers == wx.MOD_CONTROL))) \ or ((pointCell[3] == " ") and (pointCell[1] == testColour[1])): if not point in pointsDone: if not dirty: dirty = True - dispatchFn(eventDc, False, [*point, brushColours[0], brushColours[0], 0, " "]) + dispatchFn(eventDc, False, [*point, fillColour, fillColour, 0, " "]) if point[0] > 0: pointStack.append([point[0] - 1, point[1]]) if point[0] < (canvas.size[0] - 1): diff --git a/libtools/ToolLine.py b/libtools/ToolLine.py index 8e7a2f9..298cbe1 100644 --- a/libtools/ToolLine.py +++ b/libtools/ToolLine.py @@ -11,7 +11,6 @@ class ToolLine(Tool): TS_NONE = 0 TS_ORIGIN = 1 - # {{{ _getLine(self, brushColours, brushSize, dispatchFn, eventDc, isCursor, originPoint, targetPoint) def _getLine(self, brushColours, brushSize, dispatchFn, eventDc, isCursor, originPoint, targetPoint): dirty = False originPoint, targetPoint = originPoint.copy(), targetPoint.copy() @@ -40,15 +39,13 @@ class ToolLine(Tool): lineD -= pointDelta[0]; lineY += 1; lineD += pointDelta[1] return dirty - # }}} - # {{{ _pointDelta(self, a, b) + def _pointDelta(self, a, b): return [a2 - a1 for a1, a2 in zip(a, b)] - # }}} - # {{{ _pointSwap(self, a, b) + def _pointSwap(self, a, b): return [b, a] - # }}} + # # onMouseEvent(self, atPoint, brushColours, brushPos, brushSize, canvas, dispatchFn, eventDc, keyModifiers, mapPoint, mouseDragging, mouseLeftDown, mouseRightDown) diff --git a/libtools/ToolObject.py b/libtools/ToolObject.py index 55c0638..da81524 100644 --- a/libtools/ToolObject.py +++ b/libtools/ToolObject.py @@ -14,7 +14,6 @@ class ToolObject(Tool): TS_SELECT = 2 TS_TARGET = 3 - # {{{ _dispatchSelectEvent(self, canvas, dispatchFn, eventDc, keyModifiers, mapPoint, mouseLeftDown, selectRect) def _dispatchSelectEvent(self, canvas, dispatchFn, eventDc, keyModifiers, mapPoint, mouseLeftDown, selectRect): if mouseLeftDown: disp, isCursor = [mapPoint[m] - self.lastAtPoint[m] for m in [0, 1]], True @@ -26,8 +25,7 @@ class ToolObject(Tool): self._drawSelectRect(newTargetRect, dispatchFn, eventDc) self.targetRect = newTargetRect return dirty - # }}} - # {{{ _drawSelectRect(self, rect, dispatchFn, eventDc) + def _drawSelectRect(self, rect, dispatchFn, eventDc): rectFrame = [[rect[m][n] for n in [0, 1]] for m in (0, 1)] if rectFrame[0][0] > rectFrame[1][0]: @@ -43,8 +41,7 @@ class ToolObject(Tool): curColours = [1, 1] if curColours == [0, 0] else [0, 0] dispatchFn(eventDc, True, [rectFrame[0][0], rectY, *curColours, 0, " "]) dispatchFn(eventDc, True, [rectFrame[1][0], rectY, *curColours, 0, " "]) - # }}} - # {{{ _mouseEventTsNone(self, brushColours, canvas, dispatchFn, eventDc, keyModifiers, mapPoint, mouseDragging, mouseLeftDown) + def _mouseEventTsNone(self, brushColours, canvas, dispatchFn, eventDc, keyModifiers, mapPoint, mouseDragging, mouseLeftDown): self.substract = False if self.external: @@ -55,11 +52,10 @@ class ToolObject(Tool): else: dispatchFn(eventDc, True, [*mapPoint, *brushColours, 0, " "]) return False - # }}} - # {{{ _mouseEventTsOrigin(self, brushColours, canvas, dispatchFn, eventDc, keyModifiers, mapPoint, mouseDragging, mouseLeftDown) + def _mouseEventTsOrigin(self, brushColours, canvas, dispatchFn, eventDc, keyModifiers, mapPoint, mouseDragging, mouseLeftDown): self.targetRect[1] = list(mapPoint) - if mouseLeftDown: + if not mouseLeftDown: if self.targetRect[0][0] > self.targetRect[1][0]: self.targetRect[0][0], self.targetRect[1][0] = self.targetRect[1][0], self.targetRect[0][0] if self.targetRect[0][1] > self.targetRect[1][1]: @@ -74,8 +70,7 @@ class ToolObject(Tool): else: self._drawSelectRect(self.targetRect, dispatchFn, eventDc) return False - # }}} - # {{{ _mouseEventTsSelect(self, brushColours, canvas, dispatchFn, eventDc, keyModifiers, mapPoint, mouseDragging, mouseLeftDown) + def _mouseEventTsSelect(self, brushColours, canvas, dispatchFn, eventDc, keyModifiers, mapPoint, mouseDragging, mouseLeftDown): dirty = False if mouseLeftDown: @@ -91,8 +86,7 @@ class ToolObject(Tool): else: dirty = self._dispatchSelectEvent(canvas, dispatchFn, eventDc, keyModifiers, mapPoint, mouseLeftDown, self.targetRect) return dirty - # }}} - # {{{ _mouseEventTsTarget(self, brushColours, canvas, dispatchFn, eventDc, keyModifiers, mapPoint, mouseDragging, mouseLeftDown) + def _mouseEventTsTarget(self, brushColours, canvas, dispatchFn, eventDc, keyModifiers, mapPoint, mouseDragging, mouseLeftDown): if (keyModifiers == wx.MOD_CONTROL) and (self.srcRect == self.targetRect): self.substract = True @@ -102,13 +96,11 @@ class ToolObject(Tool): else: self.toolState = self.TS_SELECT return dirty - # }}} - # {{{ getRegion(self, canvas) + def getRegion(self, canvas): return self.objectMap - # }}} - # {{{ onMouseEvent(self, atPoint, brushColours, brushPos, brushSize, canvas, dispatchFn, eventDc, keyModifiers, mapPoint, mouseDragging, mouseLeftDown, mouseRightDown) + def onMouseEvent(self, atPoint, brushColours, brushPos, brushSize, canvas, dispatchFn, eventDc, keyModifiers, mapPoint, mouseDragging, mouseLeftDown, mouseRightDown): dirty = False if self.toolState == self.TS_NONE: @@ -122,8 +114,7 @@ class ToolObject(Tool): else: return False, dirty return True, dirty - # }}} - # {{{ onSelectEvent(self, canvas, disp, dispatchFn, eventDc, isCursor, keyModifiers, newTargetRect, selectRect) + def onSelectEvent(self, canvas, disp, dispatchFn, eventDc, isCursor, keyModifiers, newTargetRect, selectRect): dirty = False if self.external: @@ -149,10 +140,13 @@ class ToolObject(Tool): cellOld = self.objectMap[numRow][numCol] rectX, rectY = selectRect[0][0] + numCol, selectRect[0][1] + numRow dirty = False if isCursor else True - dispatchFn(eventDc, isCursor, [rectX + disp[0], rectY + disp[1], *cellOld]) + cellNew = self.objectMap[numRow][numCol] + if (cellNew[1] == -1) and (cellNew[3] == " "): + if ((rectY + disp[1]) < canvas.size[1]) and ((rectX + disp[0]) < canvas.size[0]): + cellNew = canvas.map[rectY + disp[1]][rectX + disp[0]] + dispatchFn(eventDc, isCursor, [rectX + disp[0], rectY + disp[1], *cellNew]) return dirty - # }}} - # {{{ setRegion(self, canvas, mapPoint, objectMap, objectSize, external=True) + def setRegion(self, canvas, mapPoint, objectMap, objectSize, external=True): self.external, self.toolState = external, self.TS_SELECT if mapPoint != None: @@ -166,7 +160,7 @@ class ToolObject(Tool): if self.srcRect == None: self.srcRect = self.targetRect self.objectMap, self.objectSize = objectMap, objectSize - # }}} + # __init__(self, *args): initialisation method def __init__(self, *args): diff --git a/libtools/ToolRect.py b/libtools/ToolRect.py index 61ab343..b36e8b1 100644 --- a/libtools/ToolRect.py +++ b/libtools/ToolRect.py @@ -12,19 +12,26 @@ class ToolRect(Tool): # # onMouseEvent(self, atPoint, brushColours, brushPos, brushSize, canvas, dispatchFn, eventDc, keyModifiers, mapPoint, mouseDragging, mouseLeftDown, mouseRightDown) def onMouseEvent(self, atPoint, brushColours, brushPos, brushSize, canvas, dispatchFn, eventDc, keyModifiers, mapPoint, mouseDragging, mouseLeftDown, mouseRightDown): - brushColours, dirty = brushColours.copy(), False - if mouseLeftDown: - brushColours[1] = brushColours[0] - elif mouseRightDown: - brushColours[0] = brushColours[1] - else: - brushColours[1] = brushColours[0] - brushSize = brushSize.copy() + brushColours, brushSize, dirty = list(brushColours), list(brushSize), False + if mouseRightDown: + brushColours = [brushColours[1], brushColours[0]] if brushSize[0] > 1: brushSize[0] *= 2 for brushRow in range(brushSize[1]): for brushCol in range(brushSize[0]): - patch = [mapPoint[0] + brushCol, mapPoint[1] + brushRow, *brushColours, 0, " "] + if (brushCol in [0, brushSize[0] - 1]) \ + or (brushRow in [0, brushSize[1] - 1]): + patchColours = [brushColours[0]] * 2 + patch = [mapPoint[0] + brushCol, mapPoint[1] + brushRow, *patchColours, 0, " "] + elif brushColours[1] == -1: + if ((mapPoint[0] + brushCol) < canvas.size[0]) \ + and ((mapPoint[1] + brushRow) < canvas.size[1]): + patch = [mapPoint[0] + brushCol, mapPoint[1] + brushRow, *canvas.map[mapPoint[1] + brushRow][mapPoint[0] + brushCol]] + else: + patch = [mapPoint[0] + brushCol, mapPoint[1] + brushRow, -1, -1, 0, " "] + else: + patchColours = [brushColours[1]] * 2 + patch = [mapPoint[0] + brushCol, mapPoint[1] + brushRow, *patchColours, 0, " "] if mouseLeftDown or mouseRightDown: if not dirty: dirty = True diff --git a/libtools/ToolText.py b/libtools/ToolText.py index 5d71b24..d87d7b0 100644 --- a/libtools/ToolText.py +++ b/libtools/ToolText.py @@ -13,7 +13,6 @@ class ToolText(Tool): arabicRegEx = r'^[\u0621-\u063A\u0640-\u064A]+$' rtlRegEx = r'^[\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC]+$' - # {{{ _checkRtl(self, canvas, brushPos, keyChar) def _checkRtl(self, canvas, brushPos, keyChar): rtlFlag = False if (keyChar != None) and re.match(self.rtlRegEx, keyChar): @@ -41,13 +40,11 @@ class ToolText(Tool): else: break return rtlFlag - # }}} - # {{{ _processKeyChar(self, brushColours, brushPos, canvas, dispatchFn, eventDc, keyChar, keyModifiers) + def _processKeyChar(self, brushColours, brushPos, canvas, dispatchFn, eventDc, keyChar, keyModifiers): - if (ord(keyChar) != wx.WXK_NONE) \ + if (ord(keyChar) != wx.WXK_NONE) \ and (not keyChar in set("\t\n\v\f\r")) \ - and ((ord(keyChar) >= 32) if ord(keyChar) < 127 else True) \ - and (keyModifiers in (wx.MOD_NONE, wx.MOD_SHIFT)): + and ((ord(keyChar) >= 32) if ord(keyChar) < 127 else True): dispatchFn(eventDc, False, [*brushPos, *brushColours, 0, keyChar]); if not self._checkRtl(canvas, brushPos, keyChar): if brushPos[0] < (canvas.size[0] - 1): @@ -67,7 +64,7 @@ class ToolText(Tool): else: rc, dirty = False, False return rc, dirty - # }}} + # # onKeyboardEvent(self, atPoint, brushColours, brushPos, brushSize, canvas, dispatchFn, eventDc, keyChar, keyCode, keyModifiers, mapPoint) diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 9c558e3..0000000 --- a/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -. diff --git a/requirements.txt b/requirements.txt new file mode 120000 index 0000000..06d6b82 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +assets/text/requirements.txt \ No newline at end of file