Initial release sans tools.

This commit is contained in:
Lucio Andrés Illanes Albornoz 2018-01-07 16:43:41 +01:00
parent f6911293c3
commit 84ab4eee5a
12 changed files with 503 additions and 332 deletions

View File

@ -90,7 +90,7 @@ class IrcClient:
# {{{ queue(self, *args): Parse and queue single line to server from list # {{{ queue(self, *args): Parse and queue single line to server from list
def queue(self, *args): def queue(self, *args):
msg = ""; argNumMax = len(args); msg = ""; argNumMax = len(args);
for argNum in range(0, argNumMax): for argNum in range(argNumMax):
if argNum == (argNumMax - 1): if argNum == (argNumMax - 1):
msg += ":" + args[argNum] msg += ":" + args[argNum]
else: else:

View File

@ -27,6 +27,7 @@ import os, sys, time
import json import json
import IrcClient import IrcClient
import requests, urllib.request import requests, urllib.request
from MiRCARTCanvasStore import MiRCARTCanvasStore
from MiRCARTToPngFile import MiRCARTToPngFile from MiRCARTToPngFile import MiRCARTToPngFile
class IrcMiRCARTBot(IrcClient.IrcClient): class IrcMiRCARTBot(IrcClient.IrcClient):
@ -139,7 +140,9 @@ class IrcMiRCARTBot(IrcClient.IrcClient):
self._log("Unknown URL type specified!") self._log("Unknown URL type specified!")
self.queue("PRIVMSG", message[2], "4/!\\ Unknown URL type specified!") self.queue("PRIVMSG", message[2], "4/!\\ Unknown URL type specified!")
return return
MiRCARTToPngFile(asciiTmpFilePath, "DejaVuSansMono.ttf", 11).export(imgTmpFilePath)
canvasStore = MiRCARTCanvasStore(inFile=asciiTmpFilePath)
MiRCARTToPngFile(canvasStore.outMap, "DejaVuSansMono.ttf", 11).export(imgTmpFilePath)
imgurResponse = self._uploadToImgur(imgTmpFilePath, "MiRCART image", "MiRCART image", "c9a6efb3d7932fd") imgurResponse = self._uploadToImgur(imgTmpFilePath, "MiRCART image", "MiRCART image", "c9a6efb3d7932fd")
if imgurResponse[0] == 200: if imgurResponse[0] == 200:
self._log("Uploaded as: {}".format(imgurResponse[1])) self._log("Uploaded as: {}".format(imgurResponse[1]))

View File

@ -23,40 +23,43 @@
# #
from MiRCARTCanvasJournal import MiRCARTCanvasJournal from MiRCARTCanvasJournal import MiRCARTCanvasJournal
from MiRCARTCanvasStore import MiRCARTCanvasStore from MiRCARTCanvasStore import MiRCARTCanvasStore, haveMiRCARTToPngFile, haveUrllib
from MiRCARTColours import MiRCARTColours from MiRCARTColours import MiRCARTColours
import wx import wx
class MiRCARTCanvas(wx.Panel): class MiRCARTCanvas(wx.Panel):
"""XXX""" """XXX"""
parentFrame = None parentFrame = None
canvasPos = canvasSize = canvasWinSize = cellPos = cellSize = None canvasPos = canvasSize = canvasWinSize = cellSize = None
canvasBitmap = canvasMap = canvasTools = None canvasBitmap = canvasMap = canvasTools = None
mircBg = mircFg = mircBrushes = mircPens = None brushColours = brushPos = brushSize = None
mircBrushes = mircPens = None
canvasJournal = canvasStore = None canvasJournal = canvasStore = None
# {{{ _initBrushesAndPens(self): XXX # {{{ _initBrushesAndPens(self): XXX
def _initBrushesAndPens(self): def _initBrushesAndPens(self):
self.mircBrushes = [None for x in range(len(MiRCARTColours))] self.mircBrushes = [None for x in range(len(MiRCARTColours))]
self.mircPens = [None for x in range(len(MiRCARTColours))] self.mircPens = [None for x in range(len(MiRCARTColours))]
for mircColour in range(0, len(MiRCARTColours)): for mircColour in range(len(MiRCARTColours)):
self.mircBrushes[mircColour] = wx.Brush( \ self.mircBrushes[mircColour] = wx.Brush( \
wx.Colour(MiRCARTColours[mircColour]), wx.BRUSHSTYLE_SOLID) wx.Colour(MiRCARTColours[mircColour][0:4]), wx.BRUSHSTYLE_SOLID)
self.mircPens[mircColour] = wx.Pen( \ self.mircPens[mircColour] = wx.Pen( \
wx.Colour(MiRCARTColours[mircColour]), 1) wx.Colour(MiRCARTColours[mircColour][0:4]), 1)
# }}} # }}}
# {{{ _drawPatch(self, patch, eventDc, tmpDc, atPoint): XXX # {{{ _drawPatch(self, patch, eventDc, tmpDc, atPoint): XXX
def _drawPatch(self, patch, eventDc, tmpDc, atPoint): def _drawPatch(self, patch, eventDc, tmpDc, atPoint):
absPoint = self._relMapPointToAbsPoint((patch[0], patch[1]), atPoint) absPoint = self._relMapPointToAbsPoint(patch[0], atPoint)
if patch[4] == " ": if patch[3] == " ":
brushFg = self.mircBrushes[patch[3]]; brushBg = self.mircBrushes[patch[3]]; brushFg = self.mircBrushes[patch[1][1]]
pen = self.mircPens[patch[3]] brushBg = self.mircBrushes[patch[1][0]]
pen = self.mircPens[patch[1][1]]
else: else:
brushFg = self.mircBrushes[patch[2]]; brushBg = self.mircBrushes[patch[3]]; brushFg = self.mircBrushes[patch[1][0]]
pen = self.mircPens[patch[2]] brushBg = self.mircBrushes[patch[1][1]]
pen = self.mircPens[patch[1][0]]
for dc in (eventDc, tmpDc): for dc in (eventDc, tmpDc):
dc.SetBrush(brushFg); dc.SetBackground(brushBg); dc.SetPen(pen); dc.SetBrush(brushFg); dc.SetBackground(brushBg); dc.SetPen(pen);
dc.DrawRectangle(absPoint[0], absPoint[1], self.cellSize[0], self.cellSize[1]) dc.DrawRectangle(*absPoint, *self.cellSize)
# }}} # }}}
# {{{ _eventPointToMapPoint(self, eventPoint): XXX # {{{ _eventPointToMapPoint(self, eventPoint): XXX
def _eventPointToMapPoint(self, eventPoint): def _eventPointToMapPoint(self, eventPoint):
@ -72,13 +75,11 @@ class MiRCARTCanvas(wx.Panel):
# }}} # }}}
# {{{ _relMapPointToAbsPoint(self, relMapPoint, atPoint): XXX # {{{ _relMapPointToAbsPoint(self, relMapPoint, atPoint): XXX
def _relMapPointToAbsPoint(self, relMapPoint, atPoint): def _relMapPointToAbsPoint(self, relMapPoint, atPoint):
absX = (atPoint[0] + relMapPoint[0]) * self.cellSize[0] return [(a+b)*c for a,b,c in zip(atPoint, relMapPoint, self.cellSize)]
absY = (atPoint[1] + relMapPoint[1]) * self.cellSize[1]
return (absX, absY)
# }}} # }}}
# {{{ _setMapCell(self, absMapPoint, colourFg, colourBg, char): XXX # {{{ _setMapCell(self, absMapPoint, colours, charAttrs, char): XXX
def _setMapCell(self, absMapPoint, colourFg, colourBg, char): def _setMapCell(self, absMapPoint, colours, charAttrs, char):
self.canvasMap[absMapPoint[1]][absMapPoint[0]] = [colourFg, colourBg, char] self.canvasMap[absMapPoint[1]][absMapPoint[0]] = [colours, charAttrs, char]
# }}} # }}}
# {{{ onClose(self, event): XXX # {{{ onClose(self, event): XXX
@ -86,17 +87,24 @@ class MiRCARTCanvas(wx.Panel):
self.Destroy(); self.__del__(); self.Destroy(); self.__del__();
# }}} # }}}
# {{{ onJournalUpdate(self, isTmp, absMapPoint, patch, eventDc, tmpDc, atPoint): # {{{ onJournalUpdate(self, isTmp, absMapPoint, patch, eventDc, tmpDc, atPoint):
def onJournalUpdate(self, isTmp, absMapPoint, patch, eventDc, tmpDc, atPoint): def onJournalUpdate(self, isTmp, absMapPoint, patch, eventDc, tmpDc, atPoint, isInherit=False):
if eventDc == None: if eventDc == None:
eventDc = wx.ClientDC(self); tmpDc = wx.MemoryDC(); eventDc = wx.ClientDC(self); tmpDc = wx.MemoryDC();
if tmpDc == None: if tmpDc == None:
tmpDc.SelectObject(self.canvasBitmap) tmpDc.SelectObject(self.canvasBitmap)
if isTmp == True: if isTmp == True:
if isInherit:
patch[1:] = self._getMapCell(patch[0])
self._drawPatch(patch, eventDc, tmpDc, atPoint) self._drawPatch(patch, eventDc, tmpDc, atPoint)
else: else:
self._setMapCell(absMapPoint, *patch[2:5]) if isInherit:
patchOld = patch.copy()
patchOld[1:] = self._getMapCell(patchOld[0])
self._setMapCell(absMapPoint, *patch[1:])
self._drawPatch(patch, eventDc, tmpDc, atPoint) self._drawPatch(patch, eventDc, tmpDc, atPoint)
self.parentFrame.onCanvasUpdate() self.parentFrame.onCanvasUpdate()
if isInherit:
return patchOld
# }}} # }}}
# {{{ onMouseEvent(self, event): XXX # {{{ onMouseEvent(self, event): XXX
def onMouseEvent(self, event): def onMouseEvent(self, event):
@ -106,14 +114,58 @@ class MiRCARTCanvas(wx.Panel):
eventPoint = event.GetLogicalPosition(eventDc) eventPoint = event.GetLogicalPosition(eventDc)
mapPoint = self._eventPointToMapPoint(eventPoint) mapPoint = self._eventPointToMapPoint(eventPoint)
for tool in self.canvasTools: for tool in self.canvasTools:
mapPatches = tool.onMouseEvent(event, mapPoint, event.Dragging(), \ mapPatches = tool.onMouseEvent( \
event.LeftIsDown(), event.RightIsDown()) event, mapPoint, self.brushColours, self.brushSize, \
event.Dragging(), event.LeftIsDown(), event.RightIsDown())
self.canvasJournal.merge(mapPatches, eventDc, tmpDc, mapPoint) self.canvasJournal.merge(mapPatches, eventDc, tmpDc, mapPoint)
self.parentFrame.onCanvasMotion(event, mapPoint)
# }}}
# {{{ onMouseWindowEvent(self, event): XXX
def onMouseWindowEvent(self, event):
eventObject = event.GetEventObject()
eventDc = wx.ClientDC(self); tmpDc = wx.MemoryDC();
tmpDc.SelectObject(self.canvasBitmap)
self.canvasJournal.resetCursor(eventDc, tmpDc)
self.parentFrame.onCanvasMotion(event)
# }}} # }}}
# {{{ onPaint(self, event): XXX # {{{ onPaint(self, event): XXX
def onPaint(self, event): def onPaint(self, event):
eventDc = wx.BufferedPaintDC(self, self.canvasBitmap) eventDc = wx.BufferedPaintDC(self, self.canvasBitmap)
# }}} # }}}
# {{{ onStoreUpdate(self, newCanvasSize, newCanvas=None):
def onStoreUpdate(self, newCanvasSize, newCanvas=None):
if newCanvasSize != None:
self.resize(newCanvasSize)
self.canvasJournal.reset()
if newCanvas != None:
self.canvasMap = newCanvas.copy()
for numRow in range(self.canvasSize[1]):
numRowCols = len(self.canvasMap[numRow])
if numRowCols < self.canvasSize[0]:
colsDelta = self.canvasSize[0] - numRowCols
self.canvasMap[numRow][self.canvasSize[0]:] = \
[[(1, 1), 0, " "] for y in range(colsDelta)]
else:
del self.canvasMap[numRow][self.canvasSize[0]:]
else:
self.canvasMap = [[[(1, 1), 0, " "] \
for x in range(self.canvasSize[0])] \
for y in range(self.canvasSize[1])]
canvasWinSize = [a*b for a,b in zip(self.canvasSize, self.cellSize)]
if self.canvasBitmap != None:
self.canvasBitmap.Destroy()
self.canvasBitmap = wx.Bitmap(canvasWinSize)
eventDc = wx.ClientDC(self); tmpDc = wx.MemoryDC();
tmpDc.SelectObject(self.canvasBitmap)
for numRow in range(self.canvasSize[1]):
for numCol in range(self.canvasSize[0]):
self.onJournalUpdate(False, \
(numCol, numRow), \
[(numCol, numRow), \
*self.canvasMap[numRow][numCol]], \
eventDc, tmpDc, (0, 0))
wx.SafeYield()
# }}}
# {{{ redo(self): XXX # {{{ redo(self): XXX
def redo(self): def redo(self):
return self.canvasJournal.redo() return self.canvasJournal.redo()
@ -124,12 +176,12 @@ class MiRCARTCanvas(wx.Panel):
self.SetSize(*self.canvasPos, \ self.SetSize(*self.canvasPos, \
newCanvasSize[0] * self.cellSize[0], \ newCanvasSize[0] * self.cellSize[0], \
newCanvasSize[1] * self.cellSize[1]) newCanvasSize[1] * self.cellSize[1])
for numRow in range(0, self.canvasSize[1]): for numRow in range(self.canvasSize[1]):
for numNewCol in range(self.canvasSize[0], newCanvasSize[0]): for numNewCol in range(self.canvasSize[0], newCanvasSize[0]):
self.canvasMap[numRow].append([1, 1, " "]) self.canvasMap[numRow].append([1, 1, " "])
for numNewRow in range(self.canvasSize[1], newCanvasSize[1]): for numNewRow in range(self.canvasSize[1], newCanvasSize[1]):
self.canvasMap.append([]) self.canvasMap.append([])
for numNewCol in range(0, newCanvasSize[0]): for numNewCol in range(newCanvasSize[0]):
self.canvasMap[numNewRow].append([1, 1, " "]) self.canvasMap[numNewRow].append([1, 1, " "])
self.canvasSize = newCanvasSize self.canvasSize = newCanvasSize
canvasWinSize = ( \ canvasWinSize = ( \
@ -162,14 +214,16 @@ class MiRCARTCanvas(wx.Panel):
self.canvasTools = [canvasTool(self) for canvasTool in canvasTools] self.canvasTools = [canvasTool(self) for canvasTool in canvasTools]
self.cellSize = cellSize self.cellSize = cellSize
self.cellPos = (0, 0) self.brushColours = [4, 1]; self._initBrushesAndPens();
self.mircBg = 1; self.mircFg = 4; self._initBrushesAndPens(); self.brushPos = [0, 0]; self.brushSize = [1, 1];
self.canvasJournal = MiRCARTCanvasJournal(parentCanvas=self) self.canvasJournal = MiRCARTCanvasJournal(parentCanvas=self)
self.canvasStore = MiRCARTCanvasStore(parentCanvas=self) self.canvasStore = MiRCARTCanvasStore(parentCanvas=self)
super().__init__(parent, pos=canvasPos, \ super().__init__(parent, pos=canvasPos, \
size=[w*h for w,h in zip(canvasSize, cellSize)]) size=[w*h for w,h in zip(canvasSize, cellSize)])
self.Bind(wx.EVT_CLOSE, self.onClose) self.Bind(wx.EVT_CLOSE, self.onClose)
self.Bind(wx.EVT_ENTER_WINDOW, self.onMouseWindowEvent)
self.Bind(wx.EVT_LEAVE_WINDOW, self.onMouseWindowEvent)
self.Bind(wx.EVT_LEFT_DOWN, self.onMouseEvent) self.Bind(wx.EVT_LEFT_DOWN, self.onMouseEvent)
self.Bind(wx.EVT_MOTION, self.onMouseEvent) self.Bind(wx.EVT_MOTION, self.onMouseEvent)
self.Bind(wx.EVT_PAINT, self.onPaint) self.Bind(wx.EVT_PAINT, self.onPaint)

View File

@ -31,28 +31,26 @@ class MiRCARTCanvasJournal():
def _popTmp(self, eventDc, tmpDc): def _popTmp(self, eventDc, tmpDc):
if self.patchesTmp: if self.patchesTmp:
for patch in self.patchesTmp: for patch in self.patchesTmp:
patch[2:] = self.parentCanvas._getMapCell([patch[0], patch[1]])
self.parentCanvas.onJournalUpdate(True, \ self.parentCanvas.onJournalUpdate(True, \
(patch[0:2]), patch, eventDc, tmpDc, (0, 0)) patch[0], patch, eventDc, tmpDc, (0, 0), True)
self.patchesTmp = [] self.patchesTmp = []
# }}} # }}}
# {{{ _pushTmp(self, atPoint, patch): XXX # {{{ _pushTmp(self, atPoint, patch): XXX
def _pushTmp(self, absMapPoint): def _pushTmp(self, absMapPoint):
self.patchesTmp.append([*absMapPoint, None, None, None]) self.patchesTmp.append([absMapPoint, None, None, None])
# }}} # }}}
# {{{ _pushUndo(self, atPoint, patch): XXX # {{{ _pushUndo(self, atPoint, patchUndo, patchRedo): XXX
def _pushUndo(self, atPoint, patch, mapItem): def _pushUndo(self, atPoint, patchUndo, patchRedo):
if self.patchesUndoLevel > 0: if self.patchesUndoLevel > 0:
del self.patchesUndo[0:self.patchesUndoLevel] del self.patchesUndo[0:self.patchesUndoLevel]
self.patchesUndoLevel = 0 self.patchesUndoLevel = 0
absMapPoint = self._relMapPointToAbsMapPoint((patch[0], patch[1]), atPoint) absMapPoint = self._relMapPointToAbsMapPoint(patchUndo[0], atPoint)
self.patchesUndo.insert(0, ( \ self.patchesUndo.insert(0, [ \
(absMapPoint[0], absMapPoint[1], mapItem[0], mapItem[1], mapItem[2]), \ [absMapPoint, *patchUndo[1:]], [absMapPoint, *patchRedo[1:]]])
(absMapPoint[0], absMapPoint[1], patch[2], patch[3], patch[4])))
# }}} # }}}
# {{{ _relMapPointToAbsMapPoint(self, relMapPoint, atPoint): XXX # {{{ _relMapPointToAbsMapPoint(self, relMapPoint, atPoint): XXX
def _relMapPointToAbsMapPoint(self, relMapPoint, atPoint): def _relMapPointToAbsMapPoint(self, relMapPoint, atPoint):
return (atPoint[0] + relMapPoint[0], atPoint[1] + relMapPoint[1]) return [a+b for a,b in zip(atPoint, relMapPoint)]
# }}} # }}}
# {{{ merge(self, mapPatches, eventDc, tmpDc, atPoint): XXX # {{{ merge(self, mapPatches, eventDc, tmpDc, atPoint): XXX
def merge(self, mapPatches, eventDc, tmpDc, atPoint): def merge(self, mapPatches, eventDc, tmpDc, atPoint):
@ -61,16 +59,16 @@ class MiRCARTCanvasJournal():
if mapPatchTmp: if mapPatchTmp:
self._popTmp(eventDc, tmpDc) self._popTmp(eventDc, tmpDc)
for patch in mapPatch[1]: for patch in mapPatch[1]:
absMapPoint = self._relMapPointToAbsMapPoint(patch[0:2], atPoint) absMapPoint = self._relMapPointToAbsMapPoint(patch[0], atPoint)
mapItem = self.parentCanvas._getMapCell(absMapPoint)
if mapPatchTmp: if mapPatchTmp:
self._pushTmp(absMapPoint) self._pushTmp(absMapPoint)
self.parentCanvas.onJournalUpdate(mapPatchTmp, \ self.parentCanvas.onJournalUpdate(mapPatchTmp, \
absMapPoint, patch, eventDc, tmpDc, atPoint) absMapPoint, patch, eventDc, tmpDc, atPoint)
elif mapItem != patch[2:5]: else:
self._pushUndo(atPoint, patch, mapItem) patchUndo = \
self.parentCanvas.onJournalUpdate(mapPatchTmp, \ self.parentCanvas.onJournalUpdate(mapPatchTmp, \
absMapPoint, patch, eventDc, tmpDc, atPoint) absMapPoint, patch, eventDc, tmpDc, atPoint, True)
self._pushUndo(atPoint, patchUndo, patch)
# }}} # }}}
# {{{ redo(self): XXX # {{{ redo(self): XXX
def redo(self): def redo(self):
@ -78,15 +76,20 @@ class MiRCARTCanvasJournal():
self.patchesUndoLevel -= 1 self.patchesUndoLevel -= 1
redoPatch = self.patchesUndo[self.patchesUndoLevel][1] redoPatch = self.patchesUndo[self.patchesUndoLevel][1]
self.parentCanvas.onJournalUpdate(False, \ self.parentCanvas.onJournalUpdate(False, \
(redoPatch[0:2]), redoPatch, None, None, (0, 0)) redoPatch[0], redoPatch, None, None, (0, 0))
return True return True
else: else:
return False return False
# }}} # }}}
# {{{ reset(self): XXX # {{{ reset(self): XXX
def reset(self): def reset(self):
self.patchesTmp = []; self.patchesUndo = [None]; self.patchesUndoLevel = 0;
# }}}
# {{{ resetCursor(self, eventDc, tmpDc): XXX
def resetCursor(self, eventDc, tmpDc):
if len(self.patchesTmp):
self._popTmp(eventDc, tmpDc)
self.patchesTmp = [] self.patchesTmp = []
self.patchesUndo = [None]; self.patchesUndoLevel = 0;
# }}} # }}}
# {{{ undo(self): XXX # {{{ undo(self): XXX
def undo(self): def undo(self):
@ -94,7 +97,7 @@ class MiRCARTCanvasJournal():
undoPatch = self.patchesUndo[self.patchesUndoLevel][0] undoPatch = self.patchesUndo[self.patchesUndoLevel][0]
self.patchesUndoLevel += 1 self.patchesUndoLevel += 1
self.parentCanvas.onJournalUpdate(False, \ self.parentCanvas.onJournalUpdate(False, \
(undoPatch[0:2]), undoPatch, None, None, (0, 0)) undoPatch[0], undoPatch, None, None, (0, 0))
return True return True
else: else:
return False return False

View File

@ -22,9 +22,13 @@
# SOFTWARE. # SOFTWARE.
# #
import base64
import io import io
try:
import wx import wx
haveWx = True
except ImportError:
haveWx = False
try: try:
from MiRCARTToPngFile import MiRCARTToPngFile from MiRCARTToPngFile import MiRCARTToPngFile
@ -78,43 +82,48 @@ class MiRCARTCanvasStore():
return cellState | bit return cellState | bit
# }}} # }}}
# {{{ exportPastebin(self, apiDevKey): XXX # {{{ exportBitmapToPngFile(self, canvasBitmap, outPathName, outType): XXX
def exportPastebin(self, apiDevKey): def exportBitmapToPngFile(self, canvasBitmap, outPathName, outType):
return canvasBitmap.ConvertToImage().SaveFile(outPathName, outType)
# }}}
# {{{ exportPastebin(self, apiDevKey, canvasMap, canvasSize, pasteName="", pastePrivate=0): XXX
def exportPastebin(self, apiDevKey, canvasMap, canvasSize, pasteName="", pastePrivate=0):
if haveUrllib: if haveUrllib:
outFile = io.StringIO(); self.exportTextFile(outFile); outFile = io.StringIO()
self.exportTextFile(canvasMap, canvasSize, outFile)
requestData = { \ requestData = { \
"api_dev_key": self.apiDevKey, \ "api_dev_key": apiDevKey, \
"api_option": "paste", \ "api_option": "paste", \
"api_paste_code": base64.b64encode(outFile.read()), \ "api_paste_code": outFile.getvalue().encode(), \
"api_paste_name": pasteName, \ "api_paste_name": pasteName, \
"api_paste_private": pastePrivate} "api_paste_private": pastePrivate}
responseHttp = requests.post("https://pastebin.com/post.php", \ responseHttp = requests.post("https://pastebin.com/api/api_post.php", \
data=requestData) data=requestData)
if responseHttp.status_code == 200: if responseHttp.status_code == 200:
return responseHttp.text if responseHttp.text.startswith("http"):
return (True, responseHttp.text)
else: else:
return None return (False, responseHttp.text)
else: else:
return None return (False, str(responseHttp.status_code))
else:
return (False, "missing requests and/or urllib3 module(s)")
# }}} # }}}
# {{{ exportPngFile(self): XXX # {{{ exportPngFile(self, canvasMap, outPathName): XXX
def exportPngFile(self, pathName): def exportPngFile(self, canvasMap, outPathName):
if haveMiRCARTToPngFile: if haveMiRCARTToPngFile:
outFile = io.StringIO(); self.exportTextFile(outFile); MiRCARTToPngFile(canvasMap).export(outPathName)
MiRCARTToPng(outFile).export(pathName)
return True return True
else: else:
return False return False
# }}} # }}}
# {{{ exportTextFile(self, outFile): XXX # {{{ exportTextFile(self, canvasMap, canvasSize, outFile): XXX
def exportTextFile(self, outFile): def exportTextFile(self, canvasMap, canvasSize, outFile):
canvasMap = self.parentCanvas.canvasMap for canvasRow in range(canvasSize[1]):
canvasSize = self.parentCanvas.canvasSize
for canvasRow in range(0, canvasSize[1]):
canvasLastColours = [] canvasLastColours = []
for canvasCol in range(0, canvasSize[0]): for canvasCol in range(canvasSize[0]):
canvasColColours = canvasMap[canvasRow][canvasCol][0:2] canvasColColours = canvasMap[canvasRow][canvasCol][0]
canvasColText = self.canvasMap[canvasRow][canvasCol][2] canvasColText = canvasMap[canvasRow][canvasCol][2]
if canvasColColours != canvasLastColours: if canvasColColours != canvasLastColours:
canvasLastColours = canvasColColours canvasLastColours = canvasColColours
outFile.write("\x03" + \ outFile.write("\x03" + \
@ -125,19 +134,7 @@ class MiRCARTCanvasStore():
# }}} # }}}
# {{{ importIntoPanel(self): XXX # {{{ importIntoPanel(self): XXX
def importIntoPanel(self): def importIntoPanel(self):
canvasSize = self.inSize; self.parentCanvas.resize(canvasSize); self.parentCanvas.onStoreUpdate(self.inSize, self.outMap)
self.parentCanvas.canvasJournal.reset()
eventDc = wx.ClientDC(self.parentCanvas); tmpDc = wx.MemoryDC();
tmpDc.SelectObject(self.parentCanvas.canvasBitmap)
for numRow in range(0, len(self.outMap)):
for numCol in range(0, len(self.outMap[numRow])):
self.parentCanvas.onJournalUpdate(False, \
(numCol, numRow), [numCol, numRow, \
self.outMap[numRow][numCol][0][0], \
self.outMap[numRow][numCol][0][1], \
self.outMap[numRow][numCol][2]], \
eventDc, tmpDc, (0, 0))
wx.SafeYield()
# }}} # }}}
# {{{ importTextFile(self, pathName): XXX # {{{ importTextFile(self, pathName): XXX
def importTextFile(self, pathName): def importTextFile(self, pathName):
@ -210,26 +207,7 @@ class MiRCARTCanvasStore():
# }}} # }}}
# {{{ importNew(self, newCanvasSize=None): XXX # {{{ importNew(self, newCanvasSize=None): XXX
def importNew(self, newCanvasSize=None): def importNew(self, newCanvasSize=None):
if newCanvasSize != None: self.parentCanvas.onStoreUpdate(newCanvasSize)
self.parentCanvas.resize(newCanvasSize)
self.parentCanvas.canvasJournal.reset()
self.parentCanvas.canvasMap = [[[1, 1, " "] \
for x in range(self.parentCanvas.canvasSize[0])] \
for y in range(self.parentCanvas.canvasSize[1])]
canvasWinSize = ( \
self.parentCanvas.cellSize[0] * self.parentCanvas.canvasSize[0], \
self.parentCanvas.cellSize[1] * self.parentCanvas.canvasSize[1])
if self.parentCanvas.canvasBitmap != None:
self.parentCanvas.canvasBitmap.Destroy()
self.parentCanvas.canvasBitmap = wx.Bitmap(canvasWinSize)
eventDc = wx.ClientDC(self.parentCanvas); tmpDc = wx.MemoryDC();
tmpDc.SelectObject(self.parentCanvas.canvasBitmap)
for numRow in range(0, len(self.parentCanvas.canvasMap)):
for numCol in range(0, len(self.parentCanvas.canvasMap[numRow])):
self.parentCanvas.onJournalUpdate(False, \
(numCol, numRow), [numCol, numRow, 1, 1, " "], \
eventDc, tmpDc, (0, 0))
wx.SafeYield()
# }}} # }}}
# #

View File

@ -23,25 +23,25 @@
# #
# #
# MiRCARTColours: mIRC colour number to RGBA map given none of ^[BFV_] (bold, italic, reverse, underline) # MiRCARTColours: mIRC colour number to RGBA map given none of ^[BFV_] (bold, italic, reverse, underline],
# #
MiRCARTColours = [ MiRCARTColours = [
(255, 255, 255, 255), # White [255, 255, 255, 255, "White"],
(0, 0, 0, 255), # Black [0, 0, 0, 255, "Black"],
(0, 0, 187, 255), # Blue [0, 0, 187, 255, "Blue"],
(0, 187, 0, 255), # Green [0, 187, 0, 255, "Green"],
(255, 85, 85, 255), # Light Red [255, 85, 85, 255, "Light Red"],
(187, 0, 0, 255), # Red [187, 0, 0, 255, "Red"],
(187, 0, 187, 255), # Purple [187, 0, 187, 255, "Purple"],
(187, 187, 0, 255), # Yellow [187, 187, 0, 255, "Yellow"],
(255, 255, 85, 255), # Light Yellow [255, 255, 85, 255, "Light Yellow"],
(85, 255, 85, 255), # Light Green [85, 255, 85, 255, "Light Green"],
(0, 187, 187, 255), # Cyan [0, 187, 187, 255, "Cyan"],
(85, 255, 255, 255), # Light Cyan [85, 255, 255, 255, "Light Cyan"],
(85, 85, 255, 255), # Light Blue [85, 85, 255, 255, "Light Blue"],
(255, 85, 255, 255), # Pink [255, 85, 255, 255, "Pink"],
(85, 85, 85, 255), # Grey [85, 85, 85, 255, "Grey"],
(187, 187, 187, 255), # Light Grey [187, 187, 187, 255, "Light Grey"],
] ]
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120 # vim:expandtab foldmethod=marker sw=4 ts=4 tw=120

View File

@ -22,61 +22,59 @@
# SOFTWARE. # SOFTWARE.
# #
from MiRCARTCanvas import MiRCARTCanvas from MiRCARTCanvas import MiRCARTCanvas, haveUrllib
from MiRCARTColours import MiRCARTColours from MiRCARTColours import MiRCARTColours
from MiRCARTGeneralFrame import MiRCARTGeneralFrame, \
TID_COMMAND, TID_MENU, TID_NOTHING, TID_SELECT, TID_TOOLBAR, TID_ACCELS
import os, wx import os, wx
class MiRCARTFrame(wx.Frame): class MiRCARTFrame(MiRCARTGeneralFrame):
"""XXX""" """XXX"""
panelSkin = panelCanvas = canvasPathName = None panelCanvas = canvasPathName = None
canvasPos = canvasSize = canvasTools = cellSize = None canvasPos = canvasSize = canvasTools = cellSize = None
menuItemsById = menuBar = toolBar = accelTable = statusBar = None
# {{{ Types
TID_COMMAND = (0x001)
TID_NOTHING = (0x002)
TID_MENU = (0x003)
TID_SELECT = (0x004)
TID_TOOLBAR = (0x005)
TID_ACCELS = (0x006)
# }}}
# {{{ Commands # {{{ Commands
# Id Type Id Labels Icon bitmap Accelerator [Initial state] # Id Type Id Labels Icon bitmap Accelerator [Initial state]
CID_NEW = (0x100, TID_COMMAND, "New", "&New", [wx.ART_NEW], None) CID_NEW = (0x100, TID_COMMAND, "New", "&New", wx.ART_NEW, (wx.ACCEL_CTRL, ord("N")))
CID_OPEN = (0x101, TID_COMMAND, "Open", "&Open", [wx.ART_FILE_OPEN], None) CID_OPEN = (0x101, TID_COMMAND, "Open", "&Open", wx.ART_FILE_OPEN, (wx.ACCEL_CTRL, ord("O")))
CID_SAVE = (0x102, TID_COMMAND, "Save", "&Save", [wx.ART_FILE_SAVE], None) CID_SAVE = (0x102, TID_COMMAND, "Save", "&Save", wx.ART_FILE_SAVE, (wx.ACCEL_CTRL, ord("S")))
CID_SAVEAS = (0x103, TID_COMMAND, "Save As...", "Save &As...", [wx.ART_FILE_SAVE_AS], None) CID_SAVEAS = (0x103, TID_COMMAND, "Save As...", "Save &As...", wx.ART_FILE_SAVE_AS, None)
CID_EXPORT_AS_PNG = (0x104, TID_COMMAND, "Export as PNG...", "Export as PN&G...", (), None, False) CID_EXPORT_AS_PNG = (0x104, TID_COMMAND, "Export as PNG...", \
CID_EXPORT_PASTEBIN = (0x105, TID_COMMAND, "Export to Pastebin...", "Export to Pasteb&in...", (), None, False) "Export as PN&G...", None, None)
CID_EXIT = (0x106, TID_COMMAND, "Exit", "E&xit", (), None) CID_EXPORT_PASTEBIN = (0x105, TID_COMMAND, "Export to Pastebin...", \
CID_UNDO = (0x107, TID_COMMAND, "Undo", "&Undo", [wx.ART_UNDO], (wx.ACCEL_CTRL, ord("Z")), False) "Export to Pasteb&in...", None, None, haveUrllib)
CID_REDO = (0x108, TID_COMMAND, "Redo", "&Redo", [wx.ART_REDO], (wx.ACCEL_CTRL, ord("Y")), False) CID_EXIT = (0x106, TID_COMMAND, "Exit", "E&xit", None, None)
CID_CUT = (0x109, TID_COMMAND, "Cut", "Cu&t", [wx.ART_CUT], None, False) CID_UNDO = (0x107, TID_COMMAND, "Undo", "&Undo", wx.ART_UNDO, (wx.ACCEL_CTRL, ord("Z")), False)
CID_COPY = (0x10a, TID_COMMAND, "Copy", "&Copy", [wx.ART_COPY], None, False) CID_REDO = (0x108, TID_COMMAND, "Redo", "&Redo", wx.ART_REDO, (wx.ACCEL_CTRL, ord("Y")), False)
CID_PASTE = (0x10b, TID_COMMAND, "Paste", "&Paste", [wx.ART_PASTE], None, False) CID_CUT = (0x109, TID_COMMAND, "Cut", "Cu&t", wx.ART_CUT, None, False)
CID_DELETE = (0x10c, TID_COMMAND, "Delete", "De&lete", [wx.ART_DELETE], None, False) CID_COPY = (0x10a, TID_COMMAND, "Copy", "&Copy", wx.ART_COPY, None, False)
CID_INCRBRUSH = (0x10d, TID_COMMAND, "Increase brush size", "&Increase brush size", [wx.ART_PLUS], None) CID_PASTE = (0x10b, TID_COMMAND, "Paste", "&Paste", wx.ART_PASTE, None, False)
CID_DECRBRUSH = (0x10e, TID_COMMAND, "Decrease brush size", "&Decrease brush size", [wx.ART_MINUS], None) CID_DELETE = (0x10c, TID_COMMAND, "Delete", "De&lete", wx.ART_DELETE, None, False)
CID_SOLID_BRUSH = (0x10f, TID_SELECT, "Solid brush", "&Solid brush", [None], None, True) CID_INCRBRUSH = (0x10d, TID_COMMAND, "Increase brush size", \
CID_RECT = (0x110, TID_SELECT, "Rectangle", "&Rectangle", [None], None, True) "&Increase brush size", wx.ART_PLUS, None)
CID_CIRCLE = (0x111, TID_SELECT, "Circle", "&Circle", [None], None, False) CID_DECRBRUSH = (0x10e, TID_COMMAND, "Decrease brush size", \
CID_LINE = (0x112, TID_SELECT, "Line", "&Line", [None], None, False) "&Decrease brush size", wx.ART_MINUS, None)
CID_COLOUR00 = (0x113, TID_COMMAND, "Colour #00", "Colour #00", MiRCARTColours[0], None) CID_SOLID_BRUSH = (0x10f, TID_SELECT, "Solid brush", "&Solid brush", None, None, True)
CID_COLOUR01 = (0x114, TID_COMMAND, "Colour #01", "Colour #01", MiRCARTColours[1], None) CID_RECT = (0x110, TID_SELECT, "Rectangle", "&Rectangle", None, None, True)
CID_COLOUR02 = (0x115, TID_COMMAND, "Colour #02", "Colour #02", MiRCARTColours[2], None) CID_CIRCLE = (0x111, TID_SELECT, "Circle", "&Circle", None, None, False)
CID_COLOUR03 = (0x116, TID_COMMAND, "Colour #03", "Colour #03", MiRCARTColours[3], None) CID_LINE = (0x112, TID_SELECT, "Line", "&Line", None, None, False)
CID_COLOUR04 = (0x117, TID_COMMAND, "Colour #04", "Colour #04", MiRCARTColours[4], None) CID_COLOUR00 = (0x113, TID_COMMAND, "Colour #00", "Colour #00", None, None)
CID_COLOUR05 = (0x118, TID_COMMAND, "Colour #05", "Colour #05", MiRCARTColours[5], None) CID_COLOUR01 = (0x114, TID_COMMAND, "Colour #01", "Colour #01", None, None)
CID_COLOUR06 = (0x119, TID_COMMAND, "Colour #06", "Colour #06", MiRCARTColours[6], None) CID_COLOUR02 = (0x115, TID_COMMAND, "Colour #02", "Colour #02", None, None)
CID_COLOUR07 = (0x11a, TID_COMMAND, "Colour #07", "Colour #07", MiRCARTColours[7], None) CID_COLOUR03 = (0x116, TID_COMMAND, "Colour #03", "Colour #03", None, None)
CID_COLOUR08 = (0x11b, TID_COMMAND, "Colour #08", "Colour #08", MiRCARTColours[8], None) CID_COLOUR04 = (0x117, TID_COMMAND, "Colour #04", "Colour #04", None, None)
CID_COLOUR09 = (0x11c, TID_COMMAND, "Colour #09", "Colour #09", MiRCARTColours[9], None) CID_COLOUR05 = (0x118, TID_COMMAND, "Colour #05", "Colour #05", None, None)
CID_COLOUR10 = (0x11d, TID_COMMAND, "Colour #10", "Colour #10", MiRCARTColours[10], None) CID_COLOUR06 = (0x119, TID_COMMAND, "Colour #06", "Colour #06", None, None)
CID_COLOUR11 = (0x11e, TID_COMMAND, "Colour #11", "Colour #11", MiRCARTColours[11], None) CID_COLOUR07 = (0x11a, TID_COMMAND, "Colour #07", "Colour #07", None, None)
CID_COLOUR12 = (0x11f, TID_COMMAND, "Colour #12", "Colour #12", MiRCARTColours[12], None) CID_COLOUR08 = (0x11b, TID_COMMAND, "Colour #08", "Colour #08", None, None)
CID_COLOUR13 = (0x120, TID_COMMAND, "Colour #13", "Colour #13", MiRCARTColours[13], None) CID_COLOUR09 = (0x11c, TID_COMMAND, "Colour #09", "Colour #09", None, None)
CID_COLOUR14 = (0x121, TID_COMMAND, "Colour #14", "Colour #14", MiRCARTColours[14], None) CID_COLOUR10 = (0x11d, TID_COMMAND, "Colour #10", "Colour #10", None, None)
CID_COLOUR15 = (0x122, TID_COMMAND, "Colour #15", "Colour #15", MiRCARTColours[15], None) CID_COLOUR11 = (0x11e, TID_COMMAND, "Colour #11", "Colour #11", None, None)
CID_COLOUR12 = (0x11f, TID_COMMAND, "Colour #12", "Colour #12", None, None)
CID_COLOUR13 = (0x120, TID_COMMAND, "Colour #13", "Colour #13", None, None)
CID_COLOUR14 = (0x121, TID_COMMAND, "Colour #14", "Colour #14", None, None)
CID_COLOUR15 = (0x122, TID_COMMAND, "Colour #15", "Colour #15", None, None)
# }}} # }}}
# {{{ Non-items # {{{ Non-items
NID_MENU_SEP = (0x200, TID_NOTHING) NID_MENU_SEP = (0x200, TID_NOTHING)
@ -107,79 +105,61 @@ class MiRCARTFrame(wx.Frame):
CID_COLOUR15)) CID_COLOUR15))
# }}} # }}}
# {{{ Accelerators (hotkeys) # {{{ Accelerators (hotkeys)
AID_EDIT = (0x500, TID_ACCELS, (CID_UNDO, CID_REDO)) AID_EDIT = (0x500, TID_ACCELS, ( \
CID_NEW, CID_OPEN, CID_SAVE, CID_UNDO, CID_REDO))
# }}} # }}}
# {{{ _drawIcon(self, solidColour): XXX # {{{ _dialogSaveChanges(self)
def _drawIcon(self, solidColour): def _dialogSaveChanges(self):
iconBitmap = wx.Bitmap((16,16)) with wx.MessageDialog(self, \
iconDc = wx.MemoryDC(); iconDc.SelectObject(iconBitmap); "Do you want to save changes to {}?".format( \
iconBrush = wx.Brush(wx.Colour(solidColour), wx.BRUSHSTYLE_SOLID) self.canvasPathName), "MiRCART", \
iconDc.SetBrush(iconBrush); iconDc.SetBackground(iconBrush); wx.CANCEL|wx.CANCEL_DEFAULT|wx.ICON_QUESTION|wx.YES_NO) as dialog:
iconDc.SetPen(wx.Pen(wx.Colour(solidColour), 1)) dialogChoice = dialog.ShowModal()
iconDc.DrawRectangle(0, 0, 16, 16) return dialogChoice
return iconBitmap
# }}} # }}}
# {{{ _initAccelTable(self, accelsDescr, handler): XXX # {{{ _setPaletteToolBitmaps(self): XXX
def _initAccelTable(self, accelsDescr, handler): def _setPaletteToolBitmaps(self):
accelTableEntries = [wx.AcceleratorEntry() for n in range(0, len(accelsDescr[2]))] paletteDescr = ( \
for numAccel in range(0, len(accelsDescr[2])): self.CID_COLOUR00, self.CID_COLOUR01, self.CID_COLOUR02, self.CID_COLOUR03, self.CID_COLOUR04, \
accelDescr = accelsDescr[2][numAccel] self.CID_COLOUR05, self.CID_COLOUR06, self.CID_COLOUR07, self.CID_COLOUR08, self.CID_COLOUR09, \
if accelDescr[5] != None: self.CID_COLOUR10, self.CID_COLOUR11, self.CID_COLOUR12, self.CID_COLOUR13, self.CID_COLOUR14, \
accelTableEntries[numAccel].Set(accelDescr[5][0], accelDescr[5][1], accelDescr[0]) self.CID_COLOUR15)
self.Bind(wx.EVT_MENU, handler, id=accelDescr[0]) for numColour in range(len(paletteDescr)):
return accelTableEntries toolBitmapColour = MiRCARTColours[numColour][0:4]
toolBitmap = wx.Bitmap((16,16))
toolBitmapDc = wx.MemoryDC(); toolBitmapDc.SelectObject(toolBitmap);
toolBitmapBrush = wx.Brush( \
wx.Colour(toolBitmapColour), wx.BRUSHSTYLE_SOLID)
toolBitmapDc.SetBrush(toolBitmapBrush)
toolBitmapDc.SetBackground(toolBitmapBrush)
toolBitmapDc.SetPen(wx.Pen(wx.Colour(toolBitmapColour), 1))
toolBitmapDc.DrawRectangle(0, 0, 16, 16)
self.toolBar.SetToolNormalBitmap( \
paletteDescr[numColour][0], toolBitmap)
# }}} # }}}
# {{{ _initMenus(self, menuBar, menusDescr, handler): XXX # {{{ _updateStatusBar(self, showColours=None, showFileName=True, showPos=None): XXX
def _initMenus(self, menuBar, menusDescr, handler): def _updateStatusBar(self, showColours=True, showFileName=True, showPos=True):
for menuDescr in menusDescr: if showColours == True:
menuWindow = wx.Menu() showColours = self.panelCanvas.brushColours
for menuItem in menuDescr[4]: if showPos == True:
if menuItem == self.NID_MENU_SEP: showPos = self.panelCanvas.brushPos
menuWindow.AppendSeparator() if showFileName == True:
elif menuItem[1] == self.TID_SELECT: showFileName = self.canvasPathName
menuItemWindow = menuWindow.AppendRadioItem(menuItem[0], menuItem[3], menuItem[2]) textItems = []
self.menuItemsById[menuItem[0]] = menuItemWindow if showPos != None:
self.Bind(wx.EVT_MENU, handler, menuItemWindow) textItems.append("X: {:03d} Y: {:03d}".format( \
if len(menuItem) == 7: showPos[0], showPos[1]))
menuItemWindow.Check(menuItem[6]) if showColours != None:
else: textItems.append("FG: {:02d}, BG: {:02d}".format( \
menuItemWindow = menuWindow.Append(menuItem[0], menuItem[3], menuItem[2]) showColours[0],showColours[1]))
self.menuItemsById[menuItem[0]] = menuItemWindow textItems.append("{} on {}".format( \
self.Bind(wx.EVT_MENU, handler, menuItemWindow) MiRCARTColours[showColours[0]][4], \
if len(menuItem) == 7: MiRCARTColours[showColours[1]][4]))
menuItemWindow.Enable(menuItem[6]) if showFileName != None:
menuBar.Append(menuWindow, menuDescr[3]) textItems.append("Current file: {}".format( \
# }}} os.path.basename(showFileName)))
# {{{ _initToolBars(self, toolBar, toolBarsDescr, handler): XXX self.statusBar.SetStatusText(" | ".join(textItems))
def _initToolBars(self, toolBar, toolBarsDescr, handler):
for toolBarDescr in toolBarsDescr:
for toolBarItem in toolBarDescr[2]:
if toolBarItem == self.NID_TOOLBAR_SEP:
toolBar.AddSeparator()
else:
if len(toolBarItem[4]) == 4:
toolBarItemIcon = self._drawIcon(toolBarItem[4])
elif len(toolBarItem[4]) == 1 \
and toolBarItem[4][0] != None:
toolBarItemIcon = wx.ArtProvider.GetBitmap( \
toolBarItem[4][0], wx.ART_TOOLBAR, (16,16))
else:
toolBarItemIcon = wx.ArtProvider.GetBitmap( \
wx.ART_HELP, wx.ART_TOOLBAR, (16,16))
toolBarItemWindow = self.toolBar.AddTool( \
toolBarItem[0], toolBarItem[2], toolBarItemIcon)
self.Bind(wx.EVT_TOOL, handler, toolBarItemWindow)
self.Bind(wx.EVT_TOOL_RCLICKED, handler, toolBarItemWindow)
# }}}
# {{{ _updateStatusBar(self): XXX
def _updateStatusBar(self):
text = "Foreground colour:"
text += " " + str(self.panelCanvas.mircFg)
text += " | "
text += "Background colour:"
text += " " + str(self.panelCanvas.mircBg)
self.statusBar.SetStatusText(text)
# }}} # }}}
# {{{ canvasExportAsPng(self): XXX # {{{ canvasExportAsPng(self): XXX
@ -189,30 +169,56 @@ class MiRCARTFrame(wx.Frame):
if dialog.ShowModal() == wx.ID_CANCEL: if dialog.ShowModal() == wx.ID_CANCEL:
return False return False
else: else:
try:
outPathName = dialog.GetPath() outPathName = dialog.GetPath()
self.panelCanvas.exportPngFile(outhPathName) self.panelCanvas.canvasStore.exportBitmapToPngFile( \
self.panelCanvas.canvasBitmap, outPathName, \
wx.BITMAP_TYPE_PNG)
return True return True
except IOError as error:
pass
# }}} # }}}
# {{{ canvasExportPastebin(self): XXX # {{{ canvasExportPastebin(self): XXX
def canvasExportPastebin(self): def canvasExportPastebin(self):
try: pasteStatus, pasteResult = \
self.panelCanvas.exportPastebin("") self.panelCanvas.canvasStore.exportPastebin( \
return True "", \
except IOError as error: self.panelCanvas.canvasMap, \
pass self.panelCanvas.canvasSize)
if pasteStatus:
if not wx.TheClipboard.IsOpened():
wx.TheClipboard.Open()
wx.TheClipboard.SetData(wx.TextDataObject(pasteResult))
wx.TheClipboard.Close()
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)
# }}} # }}}
# {{{ canvasNew(self, newCanvasSize=None): XXX # {{{ canvasNew(self, newCanvasSize=None): XXX
def canvasNew(self, newCanvasSize=None): def canvasNew(self, newCanvasSize=None):
if self.canvasPathName != None:
saveChanges = self._dialogSaveChanges()
if saveChanges == wx.ID_CANCEL:
return
elif saveChanges == wx.ID_NO:
pass
elif saveChanges == wx.ID_YES:
self.canvasSave()
if newCanvasSize == None: if newCanvasSize == None:
newCanvasSize = (100, 30) newCanvasSize = (100, 30)
self.panelCanvas.canvasStore.importNew(newCanvasSize) self.panelCanvas.canvasStore.importNew(newCanvasSize)
self.canvasPathName = None
self._updateStatusBar(); self.onCanvasUpdate(); self._updateStatusBar(); self.onCanvasUpdate();
# }}} # }}}
# {{{ canvasOpen(self): XXX # {{{ canvasOpen(self): XXX
def canvasOpen(self): def canvasOpen(self):
if self.canvasPathName != None:
saveChanges = self._dialogSaveChanges()
if saveChanges == wx.ID_CANCEL:
return
elif saveChanges == wx.ID_NO:
pass
elif saveChanges == wx.ID_YES:
self.canvasSave()
with wx.FileDialog(self, self.CID_OPEN[2], os.getcwd(), "", \ with wx.FileDialog(self, self.CID_OPEN[2], os.getcwd(), "", \
"*.txt", wx.FD_OPEN) as dialog: "*.txt", wx.FD_OPEN) as dialog:
if dialog.ShowModal() == wx.ID_CANCEL: if dialog.ShowModal() == wx.ID_CANCEL:
@ -230,10 +236,13 @@ class MiRCARTFrame(wx.Frame):
if self.canvasSaveAs() == False: if self.canvasSaveAs() == False:
return return
try: try:
self.panelCanvas.exportTextFile(self.canvasPathName) with open(self.canvasPathName, "w") as outFile:
self.panelCanvas.canvasStore.exportTextFile( \
self.panelCanvas.canvasMap, \
self.panelCanvas.canvasSize, outFile)
return True return True
except IOError as error: except IOError as error:
pass return False
# }}} # }}}
# {{{ canvasSaveAs(self): XXX # {{{ canvasSaveAs(self): XXX
def canvasSaveAs(self): def canvasSaveAs(self):
@ -243,22 +252,32 @@ class MiRCARTFrame(wx.Frame):
return False return False
else: else:
self.canvasPathName = dialog.GetPath() self.canvasPathName = dialog.GetPath()
return True return self.canvasSave()
# }}}
# {{{ onCanvasMotion(self, event): XXX
def onCanvasMotion(self, event, mapPoint=None):
eventType = event.GetEventType()
if eventType == wx.wxEVT_ENTER_WINDOW:
pass
elif eventType == wx.wxEVT_MOTION:
self._updateStatusBar(showPos=mapPoint)
elif eventType == wx.wxEVT_LEAVE_WINDOW:
pass
# }}} # }}}
# {{{ onCanvasUpdate(self): XXX # {{{ onCanvasUpdate(self): XXX
def onCanvasUpdate(self): def onCanvasUpdate(self):
if self.panelCanvas.canvasJournal.patchesUndo[self.panelCanvas.canvasJournal.patchesUndoLevel] != None: if self.panelCanvas.canvasJournal.patchesUndo[self.panelCanvas.canvasJournal.patchesUndoLevel] != None:
self.menuItemsById[self.CID_UNDO[0]].Enable(True) self.menuItemsById[self.CID_UNDO[0]].Enable(True)
self.toolBar.EnableTool(self.CID_UNDO[0], True)
else: else:
self.menuItemsById[self.CID_UNDO[0]].Enable(False) self.menuItemsById[self.CID_UNDO[0]].Enable(False)
self.toolBar.EnableTool(self.CID_UNDO[0], False)
if self.panelCanvas.canvasJournal.patchesUndoLevel > 0: if self.panelCanvas.canvasJournal.patchesUndoLevel > 0:
self.menuItemsById[self.CID_REDO[0]].Enable(True) self.menuItemsById[self.CID_REDO[0]].Enable(True)
self.toolBar.EnableTool(self.CID_REDO[0], True)
else: else:
self.menuItemsById[self.CID_REDO[0]].Enable(False) self.menuItemsById[self.CID_REDO[0]].Enable(False)
# }}} self.toolBar.EnableTool(self.CID_REDO[0], False)
# {{{ onClose(self, event): XXX
def onClose(self, event):
self.Destroy(); self.__del__();
# }}} # }}}
# {{{ onFrameCommand(self, event): XXX # {{{ onFrameCommand(self, event): XXX
def onFrameCommand(self, event): def onFrameCommand(self, event):
@ -305,9 +324,9 @@ class MiRCARTFrame(wx.Frame):
and cid <= self.CID_COLOUR15[0]: and cid <= self.CID_COLOUR15[0]:
numColour = cid - self.CID_COLOUR00[0] numColour = cid - self.CID_COLOUR00[0]
if event.GetEventType() == wx.wxEVT_TOOL: if event.GetEventType() == wx.wxEVT_TOOL:
self.panelCanvas.mircFg = numColour self.panelCanvas.brushColours[0] = numColour
elif event.GetEventType() == wx.wxEVT_TOOL_RCLICKED: elif event.GetEventType() == wx.wxEVT_TOOL_RCLICKED:
self.panelCanvas.mircBg = numColour self.panelCanvas.brushColours[1] = numColour
self._updateStatusBar() self._updateStatusBar()
# }}} # }}}
# {{{ __del__(self): destructor method # {{{ __del__(self): destructor method
@ -319,31 +338,12 @@ class MiRCARTFrame(wx.Frame):
# #
# __init__(self, parent, appSize=(800, 600), canvasPos=(25, 50), cellSize=(7, 14), canvasSize=(100, 30), canvasTools=[]): initialisation method # __init__(self, parent, appSize=(800, 600), canvasPos=(25, 50), cellSize=(7, 14), canvasSize=(100, 30), canvasTools=[]): initialisation method
def __init__(self, parent, appSize=(800, 600), canvasPos=(25, 50), cellSize=(7, 14), canvasSize=(100, 30), canvasTools=[]): def __init__(self, parent, appSize=(800, 600), canvasPos=(25, 50), cellSize=(7, 14), canvasSize=(100, 30), canvasTools=[]):
super().__init__(parent, wx.ID_ANY, "MiRCART", size=appSize) panelSkin = super().__init__(parent, wx.ID_ANY, "MiRCART", size=appSize)
self.panelSkin = wx.Panel(self, wx.ID_ANY) self._setPaletteToolBitmaps()
self.canvasPos = canvasPos; self.cellSize = cellSize; self.canvasSize = canvasSize; self.canvasPos = canvasPos; self.cellSize = cellSize; self.canvasSize = canvasSize;
self.canvasPathName = None self.canvasPathName = None
self.menuItemsById = {}; self.menuBar = wx.MenuBar();
self._initMenus(self.menuBar, \
[self.MID_FILE, self.MID_EDIT, self.MID_TOOLS], self.onFrameCommand)
self.SetMenuBar(self.menuBar)
self.toolBar = wx.ToolBar(self.panelSkin, -1, \
style=wx.HORIZONTAL|wx.TB_FLAT|wx.TB_NODIVIDER)
self.toolBar.SetToolBitmapSize((16,16))
self._initToolBars(self.toolBar, [self.BID_TOOLBAR], self.onFrameCommand)
self.toolBar.Realize(); self.toolBar.Fit();
self.accelTable = wx.AcceleratorTable( \
self._initAccelTable(self.AID_EDIT, self.onFrameCommand))
self.SetAcceleratorTable(self.accelTable)
self.Bind(wx.EVT_CLOSE, self.onClose)
self.statusBar = self.CreateStatusBar();
self.SetFocus(); self.Show(True);
self.canvasTools = canvasTools self.canvasTools = canvasTools
self.panelCanvas = MiRCARTCanvas(self.panelSkin, parentFrame=self, \ self.panelCanvas = MiRCARTCanvas(panelSkin, parentFrame=self, \
canvasPos=self.canvasPos, canvasSize=self.canvasSize, \ canvasPos=self.canvasPos, canvasSize=self.canvasSize, \
canvasTools=self.canvasTools, cellSize=self.cellSize) canvasTools=self.canvasTools, cellSize=self.cellSize)
self.canvasNew() self.canvasNew()

140
MiRCARTGeneralFrame.py Normal file
View File

@ -0,0 +1,140 @@
#!/usr/bin/env python3
#
# MiRCARTGeneralFrame.py -- XXX
# Copyright (c) 2018 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
import os, wx
#
# Types
TID_COMMAND = (0x001)
TID_MENU = (0x002)
TID_NOTHING = (0x003)
TID_SELECT = (0x004)
TID_TOOLBAR = (0x005)
TID_ACCELS = (0x006)
class MiRCARTGeneralFrame(wx.Frame):
"""XXX"""
menuItemsById = toolBarItemsById = None
statusBar = toolBar = None
# {{{ _initAccelTable(self, accelsDescr, handler): XXX
def _initAccelTable(self, accelsDescr, handler):
accelTableEntries = [wx.AcceleratorEntry() for n in range(len(accelsDescr[2]))]
for numAccel in range(len(accelsDescr[2])):
accelDescr = accelsDescr[2][numAccel]
if accelDescr[5] != None:
accelTableEntries[numAccel].Set(*accelDescr[5], accelDescr[0])
self.Bind(wx.EVT_MENU, handler, id=accelDescr[0])
return accelTableEntries
# }}}
# {{{ _initMenus(self, menuBar, menusDescr, handler): XXX
def _initMenus(self, menuBar, menusDescr, handler):
for menuDescr in menusDescr:
menuWindow = wx.Menu()
for menuItem in menuDescr[4]:
if menuItem == self.NID_MENU_SEP:
menuWindow.AppendSeparator()
elif menuItem[1] == TID_SELECT:
menuItemWindow = menuWindow.AppendRadioItem(menuItem[0], menuItem[3], menuItem[2])
self.menuItemsById[menuItem[0]] = menuItemWindow
self.Bind(wx.EVT_MENU, handler, menuItemWindow)
if len(menuItem) == 7:
menuItemWindow.Check(menuItem[6])
else:
menuItemWindow = menuWindow.Append(menuItem[0], menuItem[3], menuItem[2])
self.menuItemsById[menuItem[0]] = menuItemWindow
self.Bind(wx.EVT_MENU, handler, menuItemWindow)
if len(menuItem) == 7:
menuItemWindow.Enable(menuItem[6])
menuBar.Append(menuWindow, menuDescr[3])
# }}}
# {{{ _initToolBars(self, toolBar, toolBarsDescr, handler): XXX
def _initToolBars(self, toolBar, toolBarsDescr, handler):
for toolBarDescr in toolBarsDescr:
for toolBarItem in toolBarDescr[2]:
if toolBarItem == self.NID_TOOLBAR_SEP:
toolBar.AddSeparator()
else:
if toolBarItem[4] != None:
toolBarItemIcon = wx.ArtProvider.GetBitmap( \
toolBarItem[4], wx.ART_TOOLBAR, (16,16))
else:
toolBarItemIcon = wx.ArtProvider.GetBitmap( \
wx.ART_HELP, wx.ART_TOOLBAR, (16,16))
toolBarItemWindow = self.toolBar.AddTool( \
toolBarItem[0], toolBarItem[2], toolBarItemIcon)
self.toolBarItemsById[toolBarItem[0]] = toolBarItemWindow
if len(toolBarItem) == 7 \
and toolBarItem[1] == TID_COMMAND:
toolBarItemWindow.Enable(toolBarItem[6])
self.Bind(wx.EVT_TOOL, handler, toolBarItemWindow)
self.Bind(wx.EVT_TOOL_RCLICKED, handler, toolBarItemWindow)
# }}}
# {{{ onClose(self, event): XXX
def onClose(self, event):
self.Destroy(); self.__del__();
# }}}
# {{{ onFrameCommand(self, event): XXX
def onFrameCommand(self, event):
pass
# }}}
#
# __init__(self, *args, **kwargs): initialisation method
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
panelSkin = wx.Panel(self, wx.ID_ANY)
# Initialise menu bar, menus & menu items
self.menuItemsById = {}; menuBar = wx.MenuBar();
self._initMenus(menuBar, \
[self.MID_FILE, self.MID_EDIT, self.MID_TOOLS],
self.onFrameCommand)
self.SetMenuBar(menuBar)
# Initialise toolbar & toolbar items
self.toolBarItemsById = {}
self.toolBar = wx.ToolBar(panelSkin, -1, \
style=wx.HORIZONTAL|wx.TB_FLAT|wx.TB_NODIVIDER)
self.toolBar.SetToolBitmapSize((16,16))
self._initToolBars(self.toolBar, [self.BID_TOOLBAR], self.onFrameCommand)
self.toolBar.Realize(); self.toolBar.Fit();
# Initialise accelerators (hotkeys)
accelTable = wx.AcceleratorTable( \
self._initAccelTable(self.AID_EDIT, self.onFrameCommand))
self.SetAcceleratorTable(accelTable)
# Initialise status bar
self.statusBar = self.CreateStatusBar()
# Bind event handlers
self.Bind(wx.EVT_CLOSE, self.onClose)
# Set focus on & show window
self.SetFocus(); self.Show(True);
return panelSkin
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120

View File

@ -22,13 +22,13 @@
# SOFTWARE. # SOFTWARE.
# #
import MiRCARTCanvasStore
from PIL import Image, ImageDraw, ImageFont from PIL import Image, ImageDraw, ImageFont
from MiRCARTFromTextFile import MiRCARTFromTextFile
import string, sys import string, sys
class MiRCARTToPngFile: class MiRCARTToPngFile:
"""XXX""" """XXX"""
inFile = inFilePath = inFromTextFile = None inFile = inFromTextFile = None
outFontFilePath = outFontSize = None outFontFilePath = outFontSize = None
# {{{ _ColourMapBold: mIRC colour number to RGBA map given ^B (bold) # {{{ _ColourMapBold: mIRC colour number to RGBA map given ^B (bold)
@ -81,16 +81,16 @@ class MiRCARTToPngFile:
# }}} # }}}
# {{{ export(self, outFilePath): XXX # {{{ export(self, outFilePath): XXX
def export(self, outFilePath): def export(self, outFilePath):
inSize = self.inFromTextFile.getSize(); inSize = (len(self.inCanvasMap[0]), len(self.inCanvasMap))
outSize = [inSize[n] * self.outImgFontSize[n] for n in range(0, 2)] outSize = [a*b for a,b in zip(inSize, self.outImgFontSize)]
outCurPos = [0, 0] outCurPos = [0, 0]
outImg = Image.new("RGBA", outSize, (*self._ColourMapNormal[1], 255)) outImg = Image.new("RGBA", outSize, (*self._ColourMapNormal[1], 255))
outImgDraw = ImageDraw.Draw(outImg) outImgDraw = ImageDraw.Draw(outImg)
for inCurRow in range(0, inSize[1]): for inCurRow in range(len(self.inCanvasMap)):
for inCurCol in range(0, len(self.inFromTextFile.outMap[inCurRow])): for inCurCol in range(len(self.inCanvasMap[inCurRow])):
inCurCell = self.inFromTextFile.outMap[inCurRow][inCurCol] inCurCell = self.inCanvasMap[inCurRow][inCurCol]
outColours = [0, 0] outColours = [0, 0]
if inCurCell[1] & MiRCARTFromTextFile._CellState.CS_BOLD: if inCurCell[1] & 0x02:
if inCurCell[2] != " ": if inCurCell[2] != " ":
outColours[0] = self._ColourMapBold[inCurCell[0][0]] outColours[0] = self._ColourMapBold[inCurCell[0][0]]
outColours[1] = self._ColourMapBold[inCurCell[0][1]] outColours[1] = self._ColourMapBold[inCurCell[0][1]]
@ -107,7 +107,7 @@ class MiRCARTToPngFile:
# XXX implement italic # XXX implement italic
outImgDraw.text(outCurPos, \ outImgDraw.text(outCurPos, \
inCurCell[2], (*outColours[0], 255), self.outImgFont) inCurCell[2], (*outColours[0], 255), self.outImgFont)
if inCurCell[1] & MiRCARTFromTextFile._CellState.CS_UNDERLINE: if inCurCell[1] & 0x1f:
self._drawUnderLine(curPos, self.outImgFontSize, outImgDraw) self._drawUnderLine(curPos, self.outImgFontSize, outImgDraw)
outCurPos[0] += self.outImgFontSize[0]; outCurPos[0] += self.outImgFontSize[0];
outCurPos[0] = 0 outCurPos[0] = 0
@ -116,11 +116,9 @@ class MiRCARTToPngFile:
# }}} # }}}
# #
# __init__(self, inFilePath, fontFilePath="DejaVuSansMono.ttf", fontSize=11): initialisation method # __init__(self, inCanvasMap, fontFilePath="DejaVuSansMono.ttf", fontSize=11): initialisation method
def __init__(self, inFilePath, fontFilePath="DejaVuSansMono.ttf", fontSize=11): def __init__(self, inCanvasMap, fontFilePath="DejaVuSansMono.ttf", fontSize=11):
self.inFilePath = inFilePath; self.inFile = open(inFilePath, "r"); self.inCanvasMap = inCanvasMap
self.inFromTextFile = MiRCARTFromTextFile(self.inFile)
self.outFontFilePath = fontFilePath; self.outFontSize = int(fontSize); self.outFontFilePath = fontFilePath; self.outFontSize = int(fontSize);
self.outImgFont = ImageFont.truetype( \ self.outImgFont = ImageFont.truetype( \
self.outFontFilePath, self.outFontSize) self.outFontFilePath, self.outFontSize)
@ -130,7 +128,8 @@ class MiRCARTToPngFile:
# #
# Entry point # Entry point
def main(*argv): def main(*argv):
MiRCARTToPngFile(argv[1], *argv[3:]).export(argv[2]) canvasStore = MiRCARTCanvasStore.MiRCARTCanvasStore(inFile=argv[1])
MiRCARTToPngFile(canvasStore.outMap, *argv[3:]).export(argv[2])
if __name__ == "__main__": if __name__ == "__main__":
if ((len(sys.argv) - 1) < 2)\ if ((len(sys.argv) - 1) < 2)\
or ((len(sys.argv) - 1) > 4): or ((len(sys.argv) - 1) > 4):

View File

@ -26,8 +26,8 @@ class MiRCARTTool():
"""XXX""" """XXX"""
parentCanvas = None parentCanvas = None
# {{{ onMouseEvent(self, event, mapPoint, isDragging, isLeftDown, isRightDown): XXX # {{{ onMouseEvent(self, event, atPoint, brushColours, brushSize, isDragging, isLeftDown, isRightDown): XXX
def onMouseEvent(self, event, mapPoint, isDragging, isLeftDown, isRightDown): def onMouseEvent(self, event, atPoint, brushColours, brushSize, isDragging, isLeftDown, isRightDown):
pass pass
# }}} # }}}

View File

@ -28,25 +28,19 @@ class MiRCARTToolRect(MiRCARTTool):
"""XXX""" """XXX"""
# #
# onMouseEvent(self, event, mapPoint, isDragging, isLeftDown, isRightDown): XXX # onMouseEvent(self, event, atPoint, brushColours, brushSize, isDragging, isLeftDown, isRightDown): XXX
def onMouseEvent(self, event, mapPoint, isDragging, isLeftDown, isRightDown): def onMouseEvent(self, event, atPoint, brushColours, brushSize, isDragging, isLeftDown, isRightDown):
brushColours = brushColours.copy()
if isLeftDown: if isLeftDown:
return [[False, [[0, 0, \ brushColours[1] = brushColours[0]
self.parentCanvas.mircFg, \ return [[False, [[[0, 0], brushColours, 0, " "]]], \
self.parentCanvas.mircFg, " "]]], [True, [[[0, 0], brushColours, 0, " "]]]]
[True, [[0, 0, \
self.parentCanvas.mircFg, \
self.parentCanvas.mircFg, " "]]]]
elif isRightDown: elif isRightDown:
return [[False, [[0, 0, \ brushColours[0] = brushColours[1]
self.parentCanvas.mircBg, \ return [[False, [[[0, 0], brushColours, 0, " "]]], \
self.parentCanvas.mircBg, " "]]], \ [True, [[[0, 0], brushColours, 0, " "]]]]
[True, [[0, 0, \
self.parentCanvas.mircBg, \
self.parentCanvas.mircBg, " "]]]]
else: else:
return [[True, [[0, 0, \ brushColours[1] = brushColours[0]
self.parentCanvas.mircFg, \ return [[True, [[[0, 0], brushColours, 0, " "]]]]
self.parentCanvas.mircFg, " "]]]]
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120 # vim:expandtab foldmethod=marker sw=4 ts=4 tw=120

View File

@ -1,6 +1,6 @@
# MiRCART.py -- mIRC art editor for Windows & Linux (WIP) # MiRCART.py -- mIRC art editor for Windows & Linux (WIP)
* Prerequisites on Windows: install Python v3.6.x[1] and wxPython v4.x.x w/ the following elevated command prompt command line: * Prerequisites on Windows: install Python v3.6.x[1] and script dependencies w/ the following elevated command prompt command line:
`pip install wxPython` `pip install requests urllib3 wxPython`
* Prerequisites on Linux: python3 && python-wx{gtk2.8,tools} on Debian-family Linux distributions * Prerequisites on Linux: python3 && python-wx{gtk2.8,tools} on Debian-family Linux distributions
* Screenshot: * Screenshot:
![Screenshot](https://github.com/lalbornoz/MiRCARTools/raw/master/MiRCART.png "Screenshot") ![Screenshot](https://github.com/lalbornoz/MiRCARTools/raw/master/MiRCART.png "Screenshot")