Various bugfixes & usability improvements.

1)  Add background colour toolbar beneath (foreground) colour toolbar.
2)  Add colour flipping command w/ {accelerator,{menu,toolbar} item}.
3)  Add {de,in}crease {brush,canvas} size accelerator.
4)  Add {hide,show} assets window toolbar item.
5)  Circle tool: draw outline with foreground colour.
6)  Circle tool: honour transparency.
7)  Fill tool: change comprehensive fill modifier key from <Shift> to <Ctrl>.
8)  Fill tool: fill with {back,fore}ground colour given <[RL]MB>
9)  Fix arrow keys cursor motion when scrolled down.
10  Instantly reflect {brush size,colour,tool} changes in canvas.
11) Object tool: honour transparency w/ non-external objects.
12) Object tool: update selection rectangle during <LMB> whilst dragging, set w/ release of <LMB>.
13) Rectangle tool: draw outline with foreground colour.
14) Rectangle tool: honour transparency.
15) Replace wx.ToolBar() w/ wx.lib.agw.aui.AuiToolBar() & custom wx.lib.agw.aui.AuiDefaultToolBarArt().
16) Restore scrolling position after resizing canvas.

.TODO: deleted.
assets/audio/roar{arab8,spoke11}.wav: added.
assets/text/hotkeys.txt: added to document hotkeys.
assets/text/requirements.txt, requirements.txt: moved.
assets/text/TODO: updated.
{assets/tools,lib{canvas,gui,roar,rtl,tools}}/*.py: remove Vim fold markers.
libroar/RoarCanvasCommandsFile.py:_importFile(): update wx.FileDialog() message.
libroar/RoarCanvasCommandsOperators.py:canvasOperator(): update invert colours {caption,label}.
This commit is contained in:
Lucio Andrés Illanes Albornoz 2019-09-23 18:49:33 +02:00
parent 14d3560b70
commit ced45fa0d4
38 changed files with 488 additions and 523 deletions

1
.TODO
View File

@ -1 +0,0 @@
text bug: a) select text tool b) paste stuff c) undo d) artifacts

BIN
assets/audio/roararab8.wav Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 B

View File

@ -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

15
assets/text/hotkeys.txt Normal file
View File

@ -0,0 +1,15 @@
<Ctrl> 0-9, <Ctrl> <Shift> 0-5, <Ctrl> <Shift> 6 Set foreground colour to #0-9, #10-15, transparent colour, resp.
<Ctrl> <Alt> 0-9, <Ctrl> <Alt> <Shift> 0-5, <Ctrl> <Alt> <Shift> 6 Set background colour to #0-9, #10-15, transparent colour, resp.
<Ctrl> C U F L R E T Switch to circle, cursor, fill, line, rectangle, object, text tool
<Ctrl> I Flip colours
<Ctrl> N New canvas
<Ctrl> O Open mIRC art file
<Ctrl> S Save canvas as mIRC art file
<Ctrl> X Exit
<Ctrl> Y, Z Redo, undo, resp.
<Shift> <Pause> Break into Python debugger
(Canvas) <Down>, <Left>, <Right>, <Up> Move canvas cursor
(Canvas) <Left mouse button>, <Space> Apply current tool with foreground colour or initiate tool action (line and object tool)
(Canvas) <Right mouse button> Apply current tool with background colour
(Fill tool) <Ctrl> <Left mouse button>, <Right mouse button> Fill entire region ignoring character cells
(Object tool) <Ctrl> <Left mouse button> Move selection instead of cloning

View File

@ -0,0 +1 @@
.

View File

@ -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

View File

@ -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

View File

@ -4,7 +4,6 @@
# Copyright (c) 2018, 2019 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>
#
# {{{ 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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -4,11 +4,10 @@
# Copyright (c) 2018, 2019 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>
#
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

View File

@ -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

View File

@ -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

View File

@ -14,19 +14,19 @@ 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)):
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(toolBitmapColour), wx.BRUSHSTYLE_SOLID)
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)
RoarCanvasCommandsEdit.canvasColour.attrList[numColour]["icon"] = ["", None, toolBitmap]
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);
@ -36,10 +36,11 @@ class RoarCanvasCommands(RoarCanvasCommandsFile, RoarCanvasCommandsEdit, RoarCan
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]
# }}}
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 = 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

View File

@ -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,

View File

@ -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,

View File

@ -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

View File

@ -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),

View File

@ -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),

View File

@ -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

View File

@ -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)

View File

@ -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")

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -12,22 +12,37 @@ 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, " "]
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:
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

View File

@ -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):

View File

@ -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)

View File

@ -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):

View File

@ -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

View File

@ -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) \
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)

View File

@ -1 +0,0 @@
.

1
requirements.txt Symbolic link
View File

@ -0,0 +1 @@
assets/text/requirements.txt