diff --git a/IrcMiRCARTBot.py b/IrcMiRCARTBot.py index 4b9b4ca..6d75554 100755 --- a/IrcMiRCARTBot.py +++ b/IrcMiRCARTBot.py @@ -25,8 +25,9 @@ import base64 import os, sys, time import json -import IrcClient, MiRC2png +import IrcClient import requests, urllib.request +from MiRCARTToPngFile import MiRCARTToPngFile class IrcMiRCARTBot(IrcClient.IrcClient): """IRC<->MiRC2png bot""" @@ -138,7 +139,7 @@ class IrcMiRCARTBot(IrcClient.IrcClient): self._log("Unknown URL type specified!") self.queue("PRIVMSG", message[2], "4/!\\ Unknown URL type specified!") return - MiRC2png.MiRC2png(asciiTmpFilePath, imgTmpFilePath, "DejaVuSansMono.ttf", 11) + MiRCARTToPngFile(asciiTmpFilePath, "DejaVuSansMono.ttf", 11).export(imgTmpFilePath) imgurResponse = self._uploadToImgur(imgTmpFilePath, "MiRCART image", "MiRCART image", "c9a6efb3d7932fd") if imgurResponse[0] == 200: self._log("Uploaded as: {}".format(imgurResponse[1])) diff --git a/MiRC2png.py b/MiRC2png.py deleted file mode 100755 index ec5ca9d..0000000 --- a/MiRC2png.py +++ /dev/null @@ -1,256 +0,0 @@ -#!/usr/bin/env python3 -# -# MiRC2png.py -- convert ASCII w/ mIRC control codes to monospaced PNG (for EFnet #MiRCART) -# Copyright (c) 2018 Lucio Andrés Illanes Albornoz -# -# 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. -# - -from enum import Enum -from PIL import Image, ImageDraw, ImageFont -import string, sys - -class MiRC2png: - """Abstraction over ASCIIs containing mIRC control codes""" - inFilePath = inFile = None; - inLines = inColsMax = inRows = None; - - outFontFilePath = outFontSize = None; - outImg = outImgDraw = outImgFont = None; - outCurColourBg = outCurColourFg = None; - outCurX = outCurY = None; - - inCurBold = inCurItalic = inCurUnderline = None; - inCurColourSpec = None; - state = None; - inCurCol = inCurDigits = None; - - # {{{ _ColourMapBold: mIRC colour number to RGBA map given ^B (bold) - _ColourMapBold = [ - (255, 255, 255, 255), # White - (85, 85, 85, 255), # Grey - (85, 85, 255, 255), # Light Blue - (85, 255, 85, 255), # Light Green - (255, 85, 85, 255), # Light Red - (255, 85, 85, 255), # Light Red - (255, 85, 255, 255), # Pink - (255, 255, 85, 255), # Light Yellow - (255, 255, 85, 255), # Light Yellow - (85, 255, 85, 255), # Light Green - (85, 255, 255, 255), # Light Cyan - (85, 255, 255, 255), # Light Cyan - (85, 85, 255, 255), # Light Blue - (255, 85, 255, 255), # Pink - (85, 85, 85, 255), # Grey - (255, 255, 255, 255), # White - ] - # }}} - # {{{ _ColourMapNormal: mIRC colour number to RGBA map given none of ^[BFV_] (bold, italic, reverse, underline) - _ColourMapNormal = [ - (255, 255, 255, 255), # White - (0, 0, 0, 255), # Black - (0, 0, 187, 255), # Blue - (0, 187, 0, 255), # Green - (255, 85, 85, 255), # Light Red - (187, 0, 0, 255), # Red - (187, 0, 187, 255), # Purple - (187, 187, 0, 255), # Yellow - (255, 255, 85, 255), # Light Yellow - (85, 255, 85, 255), # Light Green - (0, 187, 187, 255), # Cyan - (85, 255, 255, 255), # Light Cyan - (85, 85, 255, 255), # Light Blue - (255, 85, 255, 255), # Pink - (85, 85, 85, 255), # Grey - (187, 187, 187, 255), # Light Grey - ] - # }}} - # {{{ _State(Enum): Parsing loop state - class _State(Enum): - STATE_CHAR = 1 - STATE_COLOUR_SPEC = 2 - STATE_CSPEC_DIGIT0 = 2 - STATE_CSPEC_DIGIT1 = 3 - # }}} - - # {{{ _countChar(self, char): XXX - def _countChar(self, char): - return True - # }}} - # {{{ _countColourSpecState(self, colourSpec): XXX - def _countColourSpecState(self, colourSpec): - return 0 - # }}} - # {{{ _render(self): XXX - def _render(self): - self.outCurX = 0; self.outCurY = 0; - for inCurRow in range(0, len(self.inLines)): - self.inCurBold = 0; self.inCurItalic = 0; self.inCurUnderline = 0; - self.inCurColourSpec = ""; self._State = self._State.STATE_CHAR; - self.inCurCol = 0; self.inCurDigits = 0; - while self.inCurCol < len(self.inLines[inCurRow]): - if self._State == self._State.STATE_CHAR: - self._parseAsChar( \ - self.inLines[inCurRow][self.inCurCol], \ - self._syncChar) - elif self._State == self._State.STATE_CSPEC_DIGIT0 \ - or self._State == self._State.STATE_CSPEC_DIGIT1: \ - self._parseAsColourSpec( \ - self.inLines[inCurRow][self.inCurCol], \ - self._syncColourSpecState) - self.outCurX = 0; self.outCurY += self.outImgFontSize[1]; - # }}} - # {{{ _getMaxCols(self, lines): Calculate widest row in lines, ignoring non-printable & mIRC control code sequences - def _getMaxCols(self, lines): - maxCols = 0; - for inCurRow in range(0, len(lines)): - self.inCurBold = 0; self.inCurItalic = 0; self.inCurUnderline = 0; - self.inCurColourSpec = ""; self._State = self._State.STATE_CHAR; - self.inCurCol = 0; self.inCurDigits = 0; curRowCols = 0; - while self.inCurCol < len(self.inLines[inCurRow]): - if self._State == self._State.STATE_CHAR: - if self._parseAsChar( \ - self.inLines[inCurRow][self.inCurCol], self._countChar): - curRowCols += 1 - elif self._State == self._State.STATE_CSPEC_DIGIT0 \ - or self._State == self._State.STATE_CSPEC_DIGIT1: - self._parseAsColourSpec( \ - self.inLines[inCurRow][self.inCurCol], \ - self._countColourSpecState) - maxCols = max(maxCols, curRowCols) - return maxCols - # }}} - # {{{ _parseAsChar(self, char, fn): Parse single character as regular character and mutate state - def _parseAsChar(self, char, fn): - if char == "": - self._State = self._State.STATE_CSPEC_DIGIT0; self.inCurCol += 1; - return False - else: - self.inCurCol += 1; return fn(char); - # }}} - # {{{ _parseAsColourSpec(self, char, fn): Parse single character as mIRC colour control code sequence and mutate state - def _parseAsColourSpec(self, char, fn): - if self._State == self._State.STATE_CSPEC_DIGIT0 \ - and char == ",": - self.inCurColourSpec += char; self.inCurCol += 1; - self._State = self._State.STATE_CSPEC_DIGIT1; - self.inCurDigits = 0 - return [False] - elif self._State == self._State.STATE_CSPEC_DIGIT0 \ - and char in set("0123456789") \ - and self.inCurDigits <= 1: - self.inCurColourSpec += char; self.inCurCol += 1; - self.inCurDigits += 1 - return [False] - elif self._State == self._State.STATE_CSPEC_DIGIT1 \ - and char in set("0123456789") \ - and self.inCurDigits <= 1: - self.inCurColourSpec += char; self.inCurCol += 1; - self.inCurDigits += 1 - return [False] - else: - result = fn(self.inCurColourSpec) - self.inCurColourSpec = ""; self._State = self._State.STATE_CHAR; - self.inCurDigits = 0 - return [True, result] - # }}} - # {{{ _syncChar(self, char): XXX - def _syncChar(self, char): - if char == "": - self.inCurBold = 0 if self.inCurBold else 1; - elif char == "": - self.inCurItalic = 0 if self.inCurItalic else 1; - elif char == "": - self.inCurBold = 0; self.inCurItalic = 0; self.inCurUnderline = 0; - self.inCurColourSpec = ""; - elif char == "": - self.outCurColourBg, self.outCurColourFg = self.outCurColourFg, self.outCurColourBg; - elif char == "": - self.inCurUnderline = 0 if self.inCurUnderline else 1; - elif char == " ": - if self.inCurBold: - colourBg = self._ColourMapBold[self.outCurColourBg] - else: - colourBg = self._ColourMapNormal[self.outCurColourBg] - self.outImgDraw.rectangle(((self.outCurX, self.outCurY), (self.outCurX + self.outImgFontSize[0], self.outCurY + self.outImgFontSize[1])), fill=colourBg) - if self.inCurUnderline: - self.outImgDraw.line((self.outCurX, self.outCurY + (self.outImgFontSize[1] - 2), self.outCurX + self.outImgFontSize[0], self.outCurY + (self.outImgFontSize[1] - 2)), fill=colourFg) - self.outCurX += self.outImgFontSize[0]; - else: - if self.inCurBold: - colourBg = self._ColourMapBold[self.outCurColourBg] - colourFg = self._ColourMapBold[self.outCurColourFg] - else: - colourBg = self._ColourMapNormal[self.outCurColourBg] - colourFg = self._ColourMapNormal[self.outCurColourFg] - self.outImgDraw.rectangle(((self.outCurX, self.outCurY), (self.outCurX + self.outImgFontSize[0], self.outCurY + self.outImgFontSize[1])), fill=colourBg) - # XXX implement italic - self.outImgDraw.text((self.outCurX, self.outCurY), char, colourFg, self.outImgFont) - if self.inCurUnderline: - self.outImgDraw.line((self.outCurX, self.outCurY + (self.outImgFontSize[1] - 2), self.outCurX + self.outImgFontSize[0], self.outCurY + (self.outImgFontSize[1] - 2)), fill=colourFg) - self.outCurX += self.outImgFontSize[0]; - return True - # }}} - # {{{ _syncColourSpecState(self, colourSpec): XXX - def _syncColourSpecState(self, colourSpec): - if len(colourSpec) > 0: - colourSpec = colourSpec.split(",") - if len(colourSpec) == 2: - self.outCurColourFg = int(colourSpec[0]) - self.outCurColourBg = int(colourSpec[1] or self.outCurColourBg) - elif len(colourSpec) == 1: - self.outCurColourFg = int(colourSpec[0]) - else: - self.outCurColourBg = 1; self.outCurColourFg = 15; - return True - # }}} - - # - # __init__(self, inFilePath, imgFilePath, fontFilePath="DejaVuSansMono.ttf", fontSize=11): initialisation method - def __init__(self, inFilePath, imgFilePath, fontFilePath="DejaVuSansMono.ttf", fontSize=11): - self.inFilePath = inFilePath; self.inFile = open(inFilePath, "r"); - self.inLines = self.inFile.readlines() - self.inColsMax = self._getMaxCols(self.inLines) - self.inRows = len(self.inLines) - self.outFontFilePath = fontFilePath; self.outFontSize = int(fontSize); - self.outImgFont = ImageFont.truetype(self.outFontFilePath, self.outFontSize) - self.outImgFontSize = list(self.outImgFont.getsize(" ")); self.outImgFontSize[1] += 3; - self.outImg = Image.new("RGBA", (self.inColsMax * self.outImgFontSize[0], self.inRows * self.outImgFontSize[1]), self._ColourMapNormal[1]) - self.outImgDraw = ImageDraw.Draw(self.outImg) - self.outCurColourBg = 1; self.outCurColourFg = 15; - self._render() - self.inFile.close(); - self.outImg.save(imgFilePath); - -# -# Entry point -def main(*argv): - MiRC2png(*argv[1:]) -if __name__ == "__main__": - if ((len(sys.argv) - 1) < 2)\ - or ((len(sys.argv) - 1) > 4): - print("usage: {} " \ - " " \ - " " \ - "[] " \ - "[]".format(sys.argv[0]), file=sys.stderr) - else: - main(*sys.argv) - -# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120 diff --git a/MiRCART.py b/MiRCART.py index 9095dd7..28e9d36 100755 --- a/MiRCART.py +++ b/MiRCART.py @@ -22,523 +22,15 @@ # SOFTWARE. # -import enum -import wx -import os, sys - -# {{{ mircColours: mIRC colour number to RGBA map given none of ^[BFV_] (bold, italic, reverse, underline) -mircColours = [ - (255, 255, 255, 255), # White - (0, 0, 0, 255), # Black - (0, 0, 187, 255), # Blue - (0, 187, 0, 255), # Green - (255, 85, 85, 255), # Light Red - (187, 0, 0, 255), # Red - (187, 0, 187, 255), # Purple - (187, 187, 0, 255), # Yellow - (255, 255, 85, 255), # Light Yellow - (85, 255, 85, 255), # Light Green - (0, 187, 187, 255), # Cyan - (85, 255, 255, 255), # Light Cyan - (85, 85, 255, 255), # Light Blue - (255, 85, 255, 255), # Pink - (85, 85, 85, 255), # Grey - (187, 187, 187, 255), # Light Grey -] -# }}} - -class MiRCARTCanvasJournal(): - """XXX""" - parentCanvas = None - patchesTmp = patchesUndo = patchesUndoLevel = None - - # {{{ _popTmp(self, eventDc, tmpDc): XXX - def _popTmp(self, eventDc, tmpDc): - if self.patchesTmp: - for patch in self.patchesTmp: - patch[2:] = self.parentCanvas._getMapCell([patch[0], patch[1]]) - self.parentCanvas.onJournalUpdate(True, \ - (patch[0:2]), patch, eventDc, tmpDc, (0, 0)) - self.patchesTmp = [] - # }}} - # {{{ _pushTmp(self, atPoint, patch): XXX - def _pushTmp(self, absMapPoint): - self.patchesTmp.append([*absMapPoint, None, None, None]) - # }}} - # {{{ _pushUndo(self, atPoint, patch): XXX - def _pushUndo(self, atPoint, patch, mapItem): - if self.patchesUndoLevel > 0: - del self.patchesUndo[0:self.patchesUndoLevel] - self.patchesUndoLevel = 0 - absMapPoint = self._relMapPointToAbsMapPoint((patch[0], patch[1]), atPoint) - self.patchesUndo.insert(0, ( \ - (absMapPoint[0], absMapPoint[1], mapItem[0], mapItem[1], mapItem[2]), \ - (absMapPoint[0], absMapPoint[1], patch[2], patch[3], patch[4]))) - # }}} - # {{{ _relMapPointToAbsMapPoint(self, relMapPoint, atPoint): XXX - def _relMapPointToAbsMapPoint(self, relMapPoint, atPoint): - return (atPoint[0] + relMapPoint[0], atPoint[1] + relMapPoint[1]) - # }}} - # {{{ merge(self, mapPatches, eventDc, tmpDc, atPoint): XXX - def merge(self, mapPatches, eventDc, tmpDc, atPoint): - for mapPatch in mapPatches: - mapPatchTmp = mapPatch[0] - if mapPatchTmp: - self._popTmp(eventDc, tmpDc) - for patch in mapPatch[1]: - absMapPoint = self._relMapPointToAbsMapPoint(patch[0:2], atPoint) - mapItem = self.parentCanvas._getMapCell(absMapPoint) - if mapPatchTmp: - self._pushTmp(absMapPoint) - self.parentCanvas.onJournalUpdate(mapPatchTmp, \ - absMapPoint, patch, eventDc, tmpDc, atPoint) - elif mapItem != patch[2:5]: - self._pushUndo(atPoint, patch, mapItem) - self.parentCanvas.onJournalUpdate(mapPatchTmp, \ - absMapPoint, patch, eventDc, tmpDc, atPoint) - # }}} - # {{{ redo(self): XXX - def redo(self): - if self.patchesUndoLevel > 0: - self.patchesUndoLevel -= 1 - redoPatch = self.patchesUndo[self.patchesUndoLevel][1] - self.parentCanvas.onJournalUpdate(False, \ - (redoPatch[0:2]), redoPatch, None, None, (0, 0)) - return True - else: - return False - # }}} - # {{{ undo(self): XXX - def undo(self): - if self.patchesUndo[self.patchesUndoLevel] != None: - undoPatch = self.patchesUndo[self.patchesUndoLevel][0] - self.patchesUndoLevel += 1 - self.parentCanvas.onJournalUpdate(False, \ - (undoPatch[0:2]), undoPatch, None, None, (0, 0)) - return True - else: - return False - # }}} - # {{{ __init__(self, parentCanvas): initialisation method - def __init__(self, parentCanvas): - self.parentCanvas = parentCanvas - self.patchesTmp = [] - self.patchesUndo = [None]; self.patchesUndoLevel = 0; - # }}} - -class MiRCARTCanvas(wx.Panel): - """XXX""" - parentFrame = None - canvasPos = canvasSize = canvasWinSize = cellPos = cellSize = None - canvasBitmap = canvasMap = canvasTools = None - mircBg = mircFg = mircBrushes = mircPens = None - canvasJournal = None - - # {{{ _drawPatch(self, patch, eventDc, tmpDc, atPoint): XXX - def _drawPatch(self, patch, eventDc, tmpDc, atPoint): - absPoint = self._relMapPointToAbsPoint((patch[0], patch[1]), atPoint) - brushFg = self.mircBrushes[patch[2]]; brushBg = self.mircBrushes[patch[3]]; - pen = self.mircPens[patch[2]] - for dc in (eventDc, tmpDc): - dc.SetBrush(brushFg); dc.SetBackground(brushBg); dc.SetPen(pen); - dc.DrawRectangle(absPoint[0], absPoint[1], self.cellSize[0], self.cellSize[1]) - # }}} - # {{{ _eventPointToMapPoint(self, eventPoint): XXX - def _eventPointToMapPoint(self, eventPoint): - rectX = eventPoint.x - (eventPoint.x % self.cellSize[0]) - rectY = eventPoint.y - (eventPoint.y % self.cellSize[1]) - mapX = int(rectX / self.cellSize[0] if rectX else 0) - mapY = int(rectY / self.cellSize[1] if rectY else 0) - return (mapX, mapY) - # }}} - # {{{ _getMapCell(self, absMapPoint): XXX - def _getMapCell(self, absMapPoint): - return self.canvasMap[absMapPoint[1]][absMapPoint[0]] - # }}} - # {{{ _relMapPointToAbsPoint(self, relMapPoint, atPoint): XXX - def _relMapPointToAbsPoint(self, relMapPoint, atPoint): - absX = (atPoint[0] + relMapPoint[0]) * self.cellSize[0] - absY = (atPoint[1] + relMapPoint[1]) * self.cellSize[1] - return (absX, absY) - # }}} - # {{{ _setMapCell(self, absMapPoint, colourFg, colourBg, char): XXX - def _setMapCell(self, absMapPoint, colourFg, colourBg, char): - self.canvasMap[absMapPoint[1]][absMapPoint[0]] = [colourFg, colourBg, char] - # }}} - - # {{{ onJournalUpdate(self, isTmp, absMapPoint, patch, eventDc, tmpDc, atPoint): - def onJournalUpdate(self, isTmp, absMapPoint, patch, eventDc, tmpDc, atPoint): - if eventDc == None: - eventDc = wx.ClientDC(self); tmpDc = wx.MemoryDC(); - if tmpDc == None: - tmpDc.SelectObject(self.canvasBitmap) - if isTmp == True: - self._drawPatch(patch, eventDc, tmpDc, atPoint) - else: - self._setMapCell(absMapPoint, *patch[2:5]) - self._drawPatch(patch, eventDc, tmpDc, atPoint) - self.parentFrame.onCanvasUpdate() - # }}} - # {{{ onMouseEvent(self, event): XXX - def onMouseEvent(self, event): - eventObject = event.GetEventObject() - eventDc = wx.ClientDC(self); tmpDc = wx.MemoryDC(); - tmpDc.SelectObject(self.canvasBitmap) - eventPoint = event.GetLogicalPosition(eventDc) - mapPoint = self._eventPointToMapPoint(eventPoint) - for tool in self.canvasTools: - mapPatches = tool.onMouseEvent(event, mapPoint, event.Dragging(), \ - event.LeftIsDown(), event.RightIsDown()) - self.canvasJournal.merge(mapPatches, eventDc, tmpDc, mapPoint) - # }}} - # {{{ onPaint(self, event): XXX - def onPaint(self, event): - eventDc = wx.BufferedPaintDC(self, self.canvasBitmap) - # }}} - # {{{ redo(self): XXX - def redo(self): - return self.canvasJournal.redo() - # }}} - # {{{ undo(self): XXX - def undo(self): - return self.canvasJournal.undo() - # }}} - # {{{ __init__(self, parent, parentFrame, canvasPos, cellSize, canvasSize, canvasTools): Initialisation method - def __init__(self, parent, parentFrame, canvasPos, cellSize, canvasSize, canvasTools): - self.parentFrame = parentFrame - canvasWinSize = (cellSize[0] * canvasSize[0], cellSize[1] * canvasSize[1]) - super().__init__(parent, pos=canvasPos, size=canvasWinSize) - self.canvasPos = canvasPos; self.canvasSize = canvasSize; self.canvasWinSize = canvasWinSize; - self.cellPos = (0, 0); self.cellSize = cellSize; - - self.canvasBitmap = wx.Bitmap(canvasWinSize) - self.canvasMap = [[[1, 1, " "] for x in range(canvasSize[0])] for y in range(canvasSize[1])] - self.canvasTools = [] - for canvasTool in canvasTools: - self.canvasTools.append(canvasTool(self)) - - self.mircBg = 1; self.mircFg = 4; - self.mircBrushes = [None for x in range(len(mircColours))] - self.mircPens = [None for x in range(len(mircColours))] - for mircColour in range(0, len(mircColours)): - self.mircBrushes[mircColour] = wx.Brush( \ - wx.Colour(mircColours[mircColour]), wx.BRUSHSTYLE_SOLID) - self.mircPens[mircColour] = wx.Pen( \ - wx.Colour(mircColours[mircColour]), 1) - - self.canvasJournal = MiRCARTCanvasJournal(self) - - self.Bind(wx.EVT_LEFT_DOWN, self.onMouseEvent) - self.Bind(wx.EVT_MOTION, self.onMouseEvent) - self.Bind(wx.EVT_PAINT, self.onPaint) - self.Bind(wx.EVT_RIGHT_DOWN, self.onMouseEvent) - # }}} - -class MiRCARTTool(): - """XXX""" - parentCanvas = None - - # {{{ onMouseEvent(self, event, mapPoint, isDragging, isLeftDown, isRightDown): XXX - def onMouseEvent(self, event, mapPoint, isDragging, isLeftDown, isRightDown): - pass - # }}} - # {{{ __init__(self, parentCanvas): initialisation method - def __init__(self, parentCanvas): - self.parentCanvas = parentCanvas - # }}} - -class MiRCARTToolRect(MiRCARTTool): - """XXX""" - - # {{{ onMouseEvent(self, event, mapPoint, isDragging, isLeftDown, isRightDown): XXX - def onMouseEvent(self, event, mapPoint, isDragging, isLeftDown, isRightDown): - if isLeftDown: - return [[False, [[0, 0, \ - self.parentCanvas.mircFg, \ - self.parentCanvas.mircFg, " "]]], - [True, [[0, 0, \ - self.parentCanvas.mircFg, \ - self.parentCanvas.mircFg, " "]]]] - elif isRightDown: - return [[False, [[0, 0, \ - self.parentCanvas.mircBg, \ - self.parentCanvas.mircBg, " "]]], \ - [True, [[0, 0, \ - self.parentCanvas.mircBg, \ - self.parentCanvas.mircBg, " "]]]] - else: - return [[True, [[0, 0, \ - self.parentCanvas.mircFg, \ - self.parentCanvas.mircFg, " "]]]] - # }}} - -class MiRCARTFrame(wx.Frame): - """XXX""" - panelSkin = panelCanvas = None - menuItemsById = menuBar = toolBar = accelTable = statusBar = None - - # {{{ Types - TID_COMMAND = (0x001) - TID_NOTHING = (0x002) - TID_MENU = (0x003) - TID_TOOLBAR = (0x004) - TID_ACCELS = (0x005) - # }}} - # {{{ Commands - # Id Type Id Labels Icon bitmap Accelerator - CID_NEW = (0x100, TID_COMMAND, "New", "&New", [wx.ART_NEW], None) - CID_OPEN = (0x101, TID_COMMAND, "Open", "&Open", [wx.ART_FILE_OPEN], None) - CID_SAVE = (0x102, TID_COMMAND, "Save", "&Save", [wx.ART_FILE_SAVE], None) - CID_SAVEAS = (0x103, TID_COMMAND, "Save As...", "Save &As...", [wx.ART_FILE_SAVE_AS], None) - CID_EXPORT_PASTEBIN = (0x104, TID_COMMAND, "Export to Pastebin...", "Export to Pasteb&in...", (), None) - CID_EXPORT_AS_PNG = (0x105, TID_COMMAND, "Export as PNG...", "Export as PN&G...", (), None) - CID_EXIT = (0x106, TID_COMMAND, "Exit", "E&xit", (), None) - CID_UNDO = (0x107, TID_COMMAND, "Undo", "&Undo", [wx.ART_UNDO], (wx.ACCEL_CTRL, ord("Z"))) - CID_REDO = (0x108, TID_COMMAND, "Redo", "&Redo", [wx.ART_REDO], (wx.ACCEL_CTRL, ord("Y"))) - CID_CUT = (0x109, TID_COMMAND, "Cut", "Cu&t", [wx.ART_CUT], None) - CID_COPY = (0x10a, TID_COMMAND, "Copy", "&Copy", [wx.ART_COPY], None) - CID_PASTE = (0x10b, TID_COMMAND, "Paste", "&Paste", [wx.ART_PASTE], None) - CID_DELETE = (0x10c, TID_COMMAND, "Delete", "De&lete", [wx.ART_DELETE], None) - CID_INCRBRUSH = (0x10d, TID_COMMAND, "Increase brush size", "&Increase brush size", [wx.ART_PLUS], None) - CID_DECRBRUSH = (0x10e, TID_COMMAND, "Decrease brush size", "&Decrease brush size", [wx.ART_MINUS], None) - CID_SOLIDBRUSH = (0x10f, TID_COMMAND, "Solid brush", "&Solid brush", [None], None) - CID_RECT = (0x110, TID_COMMAND, "Rectangle", "&Rectangle", [None], None) - CID_CIRCLE = (0x111, TID_COMMAND, "Circle", "&Circle", [None], None) - CID_LINE = (0x112, TID_COMMAND, "Line", "&Line", [None], None) - CID_COLOUR00 = (0x113, TID_COMMAND, "Colour #00", "Colour #00", mircColours[0], None) - CID_COLOUR01 = (0x114, TID_COMMAND, "Colour #01", "Colour #01", mircColours[1], None) - CID_COLOUR02 = (0x115, TID_COMMAND, "Colour #02", "Colour #02", mircColours[2], None) - CID_COLOUR03 = (0x116, TID_COMMAND, "Colour #03", "Colour #03", mircColours[3], None) - CID_COLOUR04 = (0x117, TID_COMMAND, "Colour #04", "Colour #04", mircColours[4], None) - CID_COLOUR05 = (0x118, TID_COMMAND, "Colour #05", "Colour #05", mircColours[5], None) - CID_COLOUR06 = (0x119, TID_COMMAND, "Colour #06", "Colour #06", mircColours[6], None) - CID_COLOUR07 = (0x11a, TID_COMMAND, "Colour #07", "Colour #07", mircColours[7], None) - CID_COLOUR08 = (0x11b, TID_COMMAND, "Colour #08", "Colour #08", mircColours[8], None) - CID_COLOUR09 = (0x11c, TID_COMMAND, "Colour #09", "Colour #09", mircColours[9], None) - CID_COLOUR10 = (0x11d, TID_COMMAND, "Colour #10", "Colour #10", mircColours[10], None) - CID_COLOUR11 = (0x11e, TID_COMMAND, "Colour #11", "Colour #11", mircColours[11], None) - CID_COLOUR12 = (0x11f, TID_COMMAND, "Colour #12", "Colour #12", mircColours[12], None) - CID_COLOUR13 = (0x120, TID_COMMAND, "Colour #13", "Colour #13", mircColours[13], None) - CID_COLOUR14 = (0x121, TID_COMMAND, "Colour #14", "Colour #14", mircColours[14], None) - CID_COLOUR15 = (0x122, TID_COMMAND, "Colour #15", "Colour #15", mircColours[15], None) - # }}} - # {{{ Non-items - NID_MENU_SEP = (0x200, TID_NOTHING) - NID_TOOLBAR_SEP = (0x201, TID_NOTHING) - # }}} - # {{{ Menus - MID_FILE = (0x300, TID_MENU, "File", "&File", ( \ - CID_NEW, CID_OPEN, CID_SAVE, CID_SAVEAS, NID_MENU_SEP, \ - CID_EXPORT_PASTEBIN, CID_EXPORT_AS_PNG, NID_MENU_SEP, \ - CID_EXIT)) - MID_EDIT = (0x301, TID_MENU, "Edit", "&Edit", ( \ - CID_UNDO, CID_REDO, NID_MENU_SEP, \ - CID_CUT, CID_COPY, CID_PASTE, CID_DELETE, NID_MENU_SEP, \ - CID_INCRBRUSH, CID_DECRBRUSH, CID_SOLIDBRUSH)) - MID_TOOLS = (0x302, TID_MENU, "Tools", "&Tools", ( \ - CID_RECT, CID_CIRCLE, CID_LINE)) - # }}} - # {{{ Toolbars - BID_TOOLBAR = (0x400, TID_TOOLBAR, ( \ - CID_NEW, CID_OPEN, CID_SAVE, CID_SAVEAS, NID_TOOLBAR_SEP, \ - CID_UNDO, CID_REDO, NID_TOOLBAR_SEP, \ - CID_CUT, CID_COPY, CID_PASTE, CID_DELETE, NID_TOOLBAR_SEP, \ - CID_INCRBRUSH, CID_DECRBRUSH, CID_SOLIDBRUSH, NID_TOOLBAR_SEP, \ - CID_RECT, CID_CIRCLE, CID_LINE, NID_TOOLBAR_SEP, \ - CID_COLOUR00, CID_COLOUR01, CID_COLOUR02, CID_COLOUR03, CID_COLOUR04, \ - CID_COLOUR05, CID_COLOUR06, CID_COLOUR07, CID_COLOUR08, CID_COLOUR09, \ - CID_COLOUR10, CID_COLOUR11, CID_COLOUR12, CID_COLOUR13, CID_COLOUR14, \ - CID_COLOUR15)) - # }}} - # {{{ Accelerators (hotkeys) - AID_EDIT = (0x500, TID_ACCELS, (CID_UNDO, CID_REDO)) - # }}} - - # {{{ _drawIcon(self, solidColour): XXX - def _drawIcon(self, solidColour): - iconBitmap = wx.Bitmap((16,16)) - iconDc = wx.MemoryDC(); iconDc.SelectObject(iconBitmap); - iconBrush = wx.Brush(wx.Colour(solidColour), wx.BRUSHSTYLE_SOLID) - iconDc.SetBrush(iconBrush); iconDc.SetBackground(iconBrush); - iconDc.SetPen(wx.Pen(wx.Colour(solidColour), 1)) - iconDc.DrawRectangle(0, 0, 16, 16) - return iconBitmap - # }}} - # {{{ _initAccelTable(self, accelsDescr, handler): XXX - def _initAccelTable(self, accelsDescr, handler): - accelTableEntries = [wx.AcceleratorEntry() for n in range(0, len(accelsDescr[2]))] - for numAccel in range(0, len(accelsDescr[2])): - accelDescr = accelsDescr[2][numAccel] - if accelDescr[5] != None: - accelTableEntries[numAccel].Set(accelDescr[5][0], accelDescr[5][1], 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() - else: - menuItemWindow = menuWindow.Append(menuItem[0], menuItem[3], menuItem[2]) - self.menuItemsById[menuItem[0]] = menuItemWindow - self.Bind(wx.EVT_MENU, handler, menuItemWindow) - 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 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) - # }}} - # {{{ _saveAs(self, pathName): XXX - def _saveAs(self, pathName): - try: - with open(pathName, "w") as file: - canvasMap = self.panelCanvas.canvasMap - canvasHeight = self.panelCanvas.canvasSize[1] - canvasWidth = self.panelCanvas.canvasSize[0] - for canvasRow in range(0, canvasHeight): - colourLastBg = colourLastFg = None; - for canvasCol in range(0, canvasWidth): - canvasColBg = canvasMap[canvasRow][canvasCol][0] - canvasColFg = canvasMap[canvasRow][canvasCol][1] - canvasColText = canvasMap[canvasRow][canvasCol][2] - if colourLastBg != canvasColBg \ - or colourLastFg != canvasColFg: - colourLastBg = canvasColBg; colourLastFg = canvasColFg; - file.write("" + str(canvasColFg) + "," + str(canvasColBg)) - file.write(canvasColText) - file.write("\n") - return [True] - except IOError as error: - return [False, error] - # }}} - # {{{ _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) - # }}} - - # {{{ onCanvasUpdate(self): XXX - def onCanvasUpdate(self): - if self.panelCanvas.canvasJournal.patchesUndo[self.panelCanvas.canvasJournal.patchesUndoLevel] != None: - self.menuItemsById[self.CID_UNDO[0]].Enable(True) - else: - self.menuItemsById[self.CID_UNDO[0]].Enable(False) - if self.panelCanvas.canvasJournal.patchesUndoLevel > 0: - self.menuItemsById[self.CID_REDO[0]].Enable(True) - else: - self.menuItemsById[self.CID_REDO[0]].Enable(False) - # }}} - # {{{ onFrameCommand(self, event): XXX - def onFrameCommand(self, event): - cid = event.GetId() - if cid == self.CID_NEW[0]: - pass - elif cid == self.CID_OPEN[0]: - pass - elif cid == self.CID_SAVE[0]: - pass - elif cid == self.CID_SAVEAS[0]: - with wx.FileDialog(self, self.CID_SAVEAS[2], os.getcwd(), "", \ - "*.txt", wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) as dialog: - if dialog.ShowModal() == wx.ID_CANCEL: - return - else: - self._saveAs(dialog.GetPath()) - elif cid == self.CID_EXPORT_PASTEBIN[0]: - pass - elif cid == self.CID_EXPORT_AS_PNG[0]: - pass - elif cid == self.CID_EXIT[0]: - self.Close(True) - elif cid == self.CID_UNDO[0]: - self.panelCanvas.undo() - elif cid == self.CID_REDO[0]: - self.panelCanvas.redo() - elif cid == self.CID_CUT[0]: - pass - elif cid == self.CID_COPY[0]: - pass - elif cid == self.CID_PASTE[0]: - pass - elif cid == self.CID_DELETE[0]: - pass - elif cid == self.CID_INCRBRUSH[0]: - pass - elif cid == self.CID_DECRBRUSH[0]: - pass - elif cid == self.CID_SOLIDBRUSH[0]: - pass - elif cid == self.CID_RECT[0]: - pass - elif cid == self.CID_CIRCLE[0]: - pass - elif cid == self.CID_LINE[0]: - pass - elif cid >= self.CID_COLOUR00[0] \ - and cid <= self.CID_COLOUR15[0]: - numColour = cid - self.CID_COLOUR00[0] - if event.GetEventType() == wx.wxEVT_TOOL: - self.panelCanvas.mircFg = numColour - elif event.GetEventType() == wx.wxEVT_TOOL_RCLICKED: - self.panelCanvas.mircBg = numColour - self._updateStatusBar() - # }}} - # {{{ __init__(self, parent, appSize=(800, 600), canvasPos=(25, 50), cellSize=(7, 14), canvasSize=(80, 25)): initialisation method - def __init__(self, parent, appSize=(800, 600), canvasPos=(25, 50), cellSize=(7, 14), canvasSize=(80, 25)): - super().__init__(parent, wx.ID_ANY, "MiRCART", size=appSize) - self.panelSkin = wx.Panel(self, wx.ID_ANY) - self.panelCanvas = MiRCARTCanvas(self.panelSkin, \ - parentFrame=self, canvasPos=canvasPos, cellSize=cellSize, \ - canvasSize=canvasSize, canvasTools=[MiRCARTToolRect]) - - 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.statusBar = self.CreateStatusBar(); self._updateStatusBar(); - self.SetFocus(); self.Show(True); self.onCanvasUpdate(); - # }}} +from MiRCARTFrame import MiRCARTFrame +from MiRCARTToolRect import MiRCARTToolRect +import sys, wx # # Entry point def main(*argv): wxApp = wx.App(False) - MiRCARTFrame(None) + MiRCARTFrame(None, canvasTools=[MiRCARTToolRect]) wxApp.MainLoop() if __name__ == "__main__": main(*sys.argv) diff --git a/MiRCARTCanvas.py b/MiRCARTCanvas.py new file mode 100644 index 0000000..3743b5c --- /dev/null +++ b/MiRCARTCanvas.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python3 +# +# MiRCARTCanvas.py -- XXX +# Copyright (c) 2018 Lucio Andrés Illanes Albornoz +# +# 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. +# + +from MiRCARTCanvasJournal import MiRCARTCanvasJournal +from MiRCARTColours import MiRCARTColours +import wx + +class MiRCARTCanvas(wx.Panel): + """XXX""" + parentFrame = None + canvasPos = canvasSize = canvasWinSize = cellPos = cellSize = None + canvasBitmap = canvasMap = canvasTools = None + mircBg = mircFg = mircBrushes = mircPens = None + canvasJournal = None + + # {{{ _drawPatch(self, patch, eventDc, tmpDc, atPoint): XXX + def _drawPatch(self, patch, eventDc, tmpDc, atPoint): + absPoint = self._relMapPointToAbsPoint((patch[0], patch[1]), atPoint) + if patch[4] == " ": + brushFg = self.mircBrushes[patch[3]]; brushBg = self.mircBrushes[patch[3]]; + pen = self.mircPens[patch[3]] + else: + brushFg = self.mircBrushes[patch[2]]; brushBg = self.mircBrushes[patch[3]]; + pen = self.mircPens[patch[2]] + for dc in (eventDc, tmpDc): + dc.SetBrush(brushFg); dc.SetBackground(brushBg); dc.SetPen(pen); + dc.DrawRectangle(absPoint[0], absPoint[1], self.cellSize[0], self.cellSize[1]) + # }}} + # {{{ _eventPointToMapPoint(self, eventPoint): XXX + def _eventPointToMapPoint(self, eventPoint): + rectX = eventPoint.x - (eventPoint.x % self.cellSize[0]) + rectY = eventPoint.y - (eventPoint.y % self.cellSize[1]) + mapX = int(rectX / self.cellSize[0] if rectX else 0) + mapY = int(rectY / self.cellSize[1] if rectY else 0) + return (mapX, mapY) + # }}} + # {{{ _getMapCell(self, absMapPoint): XXX + def _getMapCell(self, absMapPoint): + return self.canvasMap[absMapPoint[1]][absMapPoint[0]] + # }}} + # {{{ _relMapPointToAbsPoint(self, relMapPoint, atPoint): XXX + def _relMapPointToAbsPoint(self, relMapPoint, atPoint): + absX = (atPoint[0] + relMapPoint[0]) * self.cellSize[0] + absY = (atPoint[1] + relMapPoint[1]) * self.cellSize[1] + return (absX, absY) + # }}} + # {{{ _setMapCell(self, absMapPoint, colourFg, colourBg, char): XXX + def _setMapCell(self, absMapPoint, colourFg, colourBg, char): + self.canvasMap[absMapPoint[1]][absMapPoint[0]] = [colourFg, colourBg, char] + # }}} + # {{{ onClose(self, event): XXX + def onClose(self, event): + self.Destroy(); self.__del__(); + # }}} + # {{{ onJournalUpdate(self, isTmp, absMapPoint, patch, eventDc, tmpDc, atPoint): + def onJournalUpdate(self, isTmp, absMapPoint, patch, eventDc, tmpDc, atPoint): + if eventDc == None: + eventDc = wx.ClientDC(self); tmpDc = wx.MemoryDC(); + if tmpDc == None: + tmpDc.SelectObject(self.canvasBitmap) + if isTmp == True: + self._drawPatch(patch, eventDc, tmpDc, atPoint) + else: + self._setMapCell(absMapPoint, *patch[2:5]) + self._drawPatch(patch, eventDc, tmpDc, atPoint) + self.parentFrame.onCanvasUpdate() + # }}} + # {{{ onMouseEvent(self, event): XXX + def onMouseEvent(self, event): + eventObject = event.GetEventObject() + eventDc = wx.ClientDC(self); tmpDc = wx.MemoryDC(); + tmpDc.SelectObject(self.canvasBitmap) + eventPoint = event.GetLogicalPosition(eventDc) + mapPoint = self._eventPointToMapPoint(eventPoint) + for tool in self.canvasTools: + mapPatches = tool.onMouseEvent(event, mapPoint, event.Dragging(), \ + event.LeftIsDown(), event.RightIsDown()) + self.canvasJournal.merge(mapPatches, eventDc, tmpDc, mapPoint) + # }}} + # {{{ onPaint(self, event): XXX + def onPaint(self, event): + eventDc = wx.BufferedPaintDC(self, self.canvasBitmap) + # }}} + # {{{ redo(self): XXX + def redo(self): + return self.canvasJournal.redo() + # }}} + # {{{ undo(self): XXX + def undo(self): + return self.canvasJournal.undo() + # }}} + # {{{ __del__(self): destructor method + def __del__(self): + if self.canvasBitmap != None: + self.canvasBitmap.Destroy(); self.canvasBitmap = None; + for brush in self.mircBrushes or []: + brush.Destroy() + self.mircBrushes = None + for pen in self.mircPens or []: + pen.Destroy() + self.mircPens = None + # }}} + + # + # _init__(self, parent, parentFrame, canvasPos, cellSize, canvasSize, canvasTools): initialisation method + def __init__(self, parent, parentFrame, canvasPos, cellSize, canvasSize, canvasTools): + self.parentFrame = parentFrame + canvasWinSize = (cellSize[0] * canvasSize[0], cellSize[1] * canvasSize[1]) + super().__init__(parent, pos=canvasPos, size=canvasWinSize) + self.canvasPos = canvasPos; self.canvasSize = canvasSize; self.canvasWinSize = canvasWinSize; + self.cellPos = (0, 0); self.cellSize = cellSize; + + self.canvasBitmap = wx.Bitmap(canvasWinSize) + self.canvasMap = [[[1, 1, " "] for x in range(canvasSize[0])] for y in range(canvasSize[1])] + self.canvasTools = [] + for canvasTool in canvasTools: + self.canvasTools.append(canvasTool(self)) + + self.mircBg = 1; self.mircFg = 4; + self.mircBrushes = [None for x in range(len(MiRCARTColours))] + self.mircPens = [None for x in range(len(MiRCARTColours))] + for mircColour in range(0, len(MiRCARTColours)): + self.mircBrushes[mircColour] = wx.Brush( \ + wx.Colour(MiRCARTColours[mircColour]), wx.BRUSHSTYLE_SOLID) + self.mircPens[mircColour] = wx.Pen( \ + wx.Colour(MiRCARTColours[mircColour]), 1) + + self.canvasJournal = MiRCARTCanvasJournal(self) + + self.Bind(wx.EVT_CLOSE, self.onClose) + self.Bind(wx.EVT_LEFT_DOWN, self.onMouseEvent) + self.Bind(wx.EVT_MOTION, self.onMouseEvent) + self.Bind(wx.EVT_PAINT, self.onPaint) + self.Bind(wx.EVT_RIGHT_DOWN, self.onMouseEvent) + +# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120 diff --git a/MiRCARTCanvasJournal.py b/MiRCARTCanvasJournal.py new file mode 100644 index 0000000..03e5f93 --- /dev/null +++ b/MiRCARTCanvasJournal.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 +# +# MiRCARTCanvasJournal.py -- XXX +# Copyright (c) 2018 Lucio Andrés Illanes Albornoz +# +# 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. +# + +class MiRCARTCanvasJournal(): + """XXX""" + parentCanvas = None + patchesTmp = patchesUndo = patchesUndoLevel = None + + # {{{ _popTmp(self, eventDc, tmpDc): XXX + def _popTmp(self, eventDc, tmpDc): + if self.patchesTmp: + for patch in self.patchesTmp: + patch[2:] = self.parentCanvas._getMapCell([patch[0], patch[1]]) + self.parentCanvas.onJournalUpdate(True, \ + (patch[0:2]), patch, eventDc, tmpDc, (0, 0)) + self.patchesTmp = [] + # }}} + # {{{ _pushTmp(self, atPoint, patch): XXX + def _pushTmp(self, absMapPoint): + self.patchesTmp.append([*absMapPoint, None, None, None]) + # }}} + # {{{ _pushUndo(self, atPoint, patch): XXX + def _pushUndo(self, atPoint, patch, mapItem): + if self.patchesUndoLevel > 0: + del self.patchesUndo[0:self.patchesUndoLevel] + self.patchesUndoLevel = 0 + absMapPoint = self._relMapPointToAbsMapPoint((patch[0], patch[1]), atPoint) + self.patchesUndo.insert(0, ( \ + (absMapPoint[0], absMapPoint[1], mapItem[0], mapItem[1], mapItem[2]), \ + (absMapPoint[0], absMapPoint[1], patch[2], patch[3], patch[4]))) + # }}} + # {{{ _relMapPointToAbsMapPoint(self, relMapPoint, atPoint): XXX + def _relMapPointToAbsMapPoint(self, relMapPoint, atPoint): + return (atPoint[0] + relMapPoint[0], atPoint[1] + relMapPoint[1]) + # }}} + # {{{ merge(self, mapPatches, eventDc, tmpDc, atPoint): XXX + def merge(self, mapPatches, eventDc, tmpDc, atPoint): + for mapPatch in mapPatches: + mapPatchTmp = mapPatch[0] + if mapPatchTmp: + self._popTmp(eventDc, tmpDc) + for patch in mapPatch[1]: + absMapPoint = self._relMapPointToAbsMapPoint(patch[0:2], atPoint) + mapItem = self.parentCanvas._getMapCell(absMapPoint) + if mapPatchTmp: + self._pushTmp(absMapPoint) + self.parentCanvas.onJournalUpdate(mapPatchTmp, \ + absMapPoint, patch, eventDc, tmpDc, atPoint) + elif mapItem != patch[2:5]: + self._pushUndo(atPoint, patch, mapItem) + self.parentCanvas.onJournalUpdate(mapPatchTmp, \ + absMapPoint, patch, eventDc, tmpDc, atPoint) + # }}} + # {{{ redo(self): XXX + def redo(self): + if self.patchesUndoLevel > 0: + self.patchesUndoLevel -= 1 + redoPatch = self.patchesUndo[self.patchesUndoLevel][1] + self.parentCanvas.onJournalUpdate(False, \ + (redoPatch[0:2]), redoPatch, None, None, (0, 0)) + return True + else: + return False + # }}} + # {{{ undo(self): XXX + def undo(self): + if self.patchesUndo[self.patchesUndoLevel] != None: + undoPatch = self.patchesUndo[self.patchesUndoLevel][0] + self.patchesUndoLevel += 1 + self.parentCanvas.onJournalUpdate(False, \ + (undoPatch[0:2]), undoPatch, None, None, (0, 0)) + return True + else: + return False + # }}} + + # + # __init__(self, parentCanvas): initialisation method + def __init__(self, parentCanvas): + self.parentCanvas = parentCanvas + self.patchesTmp = [] + self.patchesUndo = [None]; self.patchesUndoLevel = 0; + +# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120 diff --git a/MiRCARTColours.py b/MiRCARTColours.py new file mode 100755 index 0000000..9489b08 --- /dev/null +++ b/MiRCARTColours.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +# +# MiRCARTColours.py -- XXX +# Copyright (c) 2018 Lucio Andrés Illanes Albornoz +# +# 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. +# + +# +# MiRCARTColours: mIRC colour number to RGBA map given none of ^[BFV_] (bold, italic, reverse, underline) +# +MiRCARTColours = [ + (255, 255, 255, 255), # White + (0, 0, 0, 255), # Black + (0, 0, 187, 255), # Blue + (0, 187, 0, 255), # Green + (255, 85, 85, 255), # Light Red + (187, 0, 0, 255), # Red + (187, 0, 187, 255), # Purple + (187, 187, 0, 255), # Yellow + (255, 255, 85, 255), # Light Yellow + (85, 255, 85, 255), # Light Green + (0, 187, 187, 255), # Cyan + (85, 255, 255, 255), # Light Cyan + (85, 85, 255, 255), # Light Blue + (255, 85, 255, 255), # Pink + (85, 85, 85, 255), # Grey + (187, 187, 187, 255), # Light Grey +] + +# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120 diff --git a/MiRCARTFrame.py b/MiRCARTFrame.py new file mode 100644 index 0000000..4e84a8b --- /dev/null +++ b/MiRCARTFrame.py @@ -0,0 +1,375 @@ +#!/usr/bin/env python3 +# +# MiRCARTFrame.py -- XXX +# Copyright (c) 2018 Lucio Andrés Illanes Albornoz +# +# 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. +# + +from MiRCARTCanvas import MiRCARTCanvas +from MiRCARTColours import MiRCARTColours +from MiRCARTFromTextFile import MiRCARTFromTextFile +from MiRCARTToTextFile import MiRCARTToTextFile +import os, wx + +try: + from MiRCARTToPastebin import MiRCARTToPastebin + haveMiRCARTToPastebin = True +except ImportError: + haveMiRCARTToPastebin = False + +try: + from MiRCARTToPngFile import MiRCARTToPngFile + haveMiRCARTToPngFile = True +except ImportError: + haveMiRCARTToPngFile = False + +class MiRCARTFrame(wx.Frame): + """XXX""" + panelSkin = panelCanvas = canvasPathName = None + canvasPos = canvasSize = canvasTools = cellSize = None + menuItemsById = menuBar = toolBar = accelTable = statusBar = None + + # {{{ Types + TID_COMMAND = (0x001) + TID_NOTHING = (0x002) + TID_MENU = (0x003) + TID_TOOLBAR = (0x004) + TID_ACCELS = (0x005) + # }}} + # {{{ Commands + # Id Type Id Labels Icon bitmap Accelerator + CID_NEW = (0x100, TID_COMMAND, "New", "&New", [wx.ART_NEW], None) + CID_OPEN = (0x101, TID_COMMAND, "Open", "&Open", [wx.ART_FILE_OPEN], None) + CID_SAVE = (0x102, TID_COMMAND, "Save", "&Save", [wx.ART_FILE_SAVE], 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) + CID_EXPORT_PASTEBIN = (0x105, TID_COMMAND, "Export to Pastebin...", "Export to Pasteb&in...", (), None) + CID_EXIT = (0x106, TID_COMMAND, "Exit", "E&xit", (), None) + CID_UNDO = (0x107, TID_COMMAND, "Undo", "&Undo", [wx.ART_UNDO], (wx.ACCEL_CTRL, ord("Z"))) + CID_REDO = (0x108, TID_COMMAND, "Redo", "&Redo", [wx.ART_REDO], (wx.ACCEL_CTRL, ord("Y"))) + CID_CUT = (0x109, TID_COMMAND, "Cut", "Cu&t", [wx.ART_CUT], None) + CID_COPY = (0x10a, TID_COMMAND, "Copy", "&Copy", [wx.ART_COPY], None) + CID_PASTE = (0x10b, TID_COMMAND, "Paste", "&Paste", [wx.ART_PASTE], None) + CID_DELETE = (0x10c, TID_COMMAND, "Delete", "De&lete", [wx.ART_DELETE], None) + CID_INCRBRUSH = (0x10d, TID_COMMAND, "Increase brush size", "&Increase brush size", [wx.ART_PLUS], None) + CID_DECRBRUSH = (0x10e, TID_COMMAND, "Decrease brush size", "&Decrease brush size", [wx.ART_MINUS], None) + CID_SOLIDBRUSH = (0x10f, TID_COMMAND, "Solid brush", "&Solid brush", [None], None) + CID_RECT = (0x110, TID_COMMAND, "Rectangle", "&Rectangle", [None], None) + CID_CIRCLE = (0x111, TID_COMMAND, "Circle", "&Circle", [None], None) + CID_LINE = (0x112, TID_COMMAND, "Line", "&Line", [None], None) + CID_COLOUR00 = (0x113, TID_COMMAND, "Colour #00", "Colour #00", MiRCARTColours[0], None) + CID_COLOUR01 = (0x114, TID_COMMAND, "Colour #01", "Colour #01", MiRCARTColours[1], None) + CID_COLOUR02 = (0x115, TID_COMMAND, "Colour #02", "Colour #02", MiRCARTColours[2], None) + CID_COLOUR03 = (0x116, TID_COMMAND, "Colour #03", "Colour #03", MiRCARTColours[3], None) + CID_COLOUR04 = (0x117, TID_COMMAND, "Colour #04", "Colour #04", MiRCARTColours[4], None) + CID_COLOUR05 = (0x118, TID_COMMAND, "Colour #05", "Colour #05", MiRCARTColours[5], None) + CID_COLOUR06 = (0x119, TID_COMMAND, "Colour #06", "Colour #06", MiRCARTColours[6], None) + CID_COLOUR07 = (0x11a, TID_COMMAND, "Colour #07", "Colour #07", MiRCARTColours[7], None) + CID_COLOUR08 = (0x11b, TID_COMMAND, "Colour #08", "Colour #08", MiRCARTColours[8], None) + CID_COLOUR09 = (0x11c, TID_COMMAND, "Colour #09", "Colour #09", MiRCARTColours[9], None) + CID_COLOUR10 = (0x11d, TID_COMMAND, "Colour #10", "Colour #10", MiRCARTColours[10], None) + CID_COLOUR11 = (0x11e, TID_COMMAND, "Colour #11", "Colour #11", MiRCARTColours[11], None) + CID_COLOUR12 = (0x11f, TID_COMMAND, "Colour #12", "Colour #12", MiRCARTColours[12], None) + CID_COLOUR13 = (0x120, TID_COMMAND, "Colour #13", "Colour #13", MiRCARTColours[13], None) + CID_COLOUR14 = (0x121, TID_COMMAND, "Colour #14", "Colour #14", MiRCARTColours[14], None) + CID_COLOUR15 = (0x122, TID_COMMAND, "Colour #15", "Colour #15", MiRCARTColours[15], None) + # }}} + # {{{ Non-items + NID_MENU_SEP = (0x200, TID_NOTHING) + NID_TOOLBAR_SEP = (0x201, TID_NOTHING) + # }}} + # {{{ Menus + MID_FILE = (0x300, TID_MENU, "File", "&File", ( \ + CID_NEW, CID_OPEN, CID_SAVE, CID_SAVEAS, NID_MENU_SEP, \ + CID_EXPORT_PASTEBIN, CID_EXPORT_AS_PNG, NID_MENU_SEP, \ + CID_EXIT)) + MID_EDIT = (0x301, TID_MENU, "Edit", "&Edit", ( \ + CID_UNDO, CID_REDO, NID_MENU_SEP, \ + CID_CUT, CID_COPY, CID_PASTE, CID_DELETE, NID_MENU_SEP, \ + CID_INCRBRUSH, CID_DECRBRUSH, CID_SOLIDBRUSH)) + MID_TOOLS = (0x302, TID_MENU, "Tools", "&Tools", ( \ + CID_RECT, CID_CIRCLE, CID_LINE)) + # }}} + # {{{ Toolbars + BID_TOOLBAR = (0x400, TID_TOOLBAR, ( \ + CID_NEW, CID_OPEN, CID_SAVE, CID_SAVEAS, NID_TOOLBAR_SEP, \ + CID_UNDO, CID_REDO, NID_TOOLBAR_SEP, \ + CID_CUT, CID_COPY, CID_PASTE, CID_DELETE, NID_TOOLBAR_SEP, \ + CID_INCRBRUSH, CID_DECRBRUSH, CID_SOLIDBRUSH, NID_TOOLBAR_SEP, \ + CID_RECT, CID_CIRCLE, CID_LINE, NID_TOOLBAR_SEP, \ + CID_COLOUR00, CID_COLOUR01, CID_COLOUR02, CID_COLOUR03, CID_COLOUR04, \ + CID_COLOUR05, CID_COLOUR06, CID_COLOUR07, CID_COLOUR08, CID_COLOUR09, \ + CID_COLOUR10, CID_COLOUR11, CID_COLOUR12, CID_COLOUR13, CID_COLOUR14, \ + CID_COLOUR15)) + # }}} + # {{{ Accelerators (hotkeys) + AID_EDIT = (0x500, TID_ACCELS, (CID_UNDO, CID_REDO)) + # }}} + + # {{{ _drawIcon(self, solidColour): XXX + def _drawIcon(self, solidColour): + iconBitmap = wx.Bitmap((16,16)) + iconDc = wx.MemoryDC(); iconDc.SelectObject(iconBitmap); + iconBrush = wx.Brush(wx.Colour(solidColour), wx.BRUSHSTYLE_SOLID) + iconDc.SetBrush(iconBrush); iconDc.SetBackground(iconBrush); + iconDc.SetPen(wx.Pen(wx.Colour(solidColour), 1)) + iconDc.DrawRectangle(0, 0, 16, 16) + return iconBitmap + # }}} + # {{{ _initAccelTable(self, accelsDescr, handler): XXX + def _initAccelTable(self, accelsDescr, handler): + accelTableEntries = [wx.AcceleratorEntry() for n in range(0, len(accelsDescr[2]))] + for numAccel in range(0, len(accelsDescr[2])): + accelDescr = accelsDescr[2][numAccel] + if accelDescr[5] != None: + accelTableEntries[numAccel].Set(accelDescr[5][0], accelDescr[5][1], 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() + else: + menuItemWindow = menuWindow.Append(menuItem[0], menuItem[3], menuItem[2]) + self.menuItemsById[menuItem[0]] = menuItemWindow + self.Bind(wx.EVT_MENU, handler, menuItemWindow) + 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 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 + def canvasExportAsPng(self): + with wx.FileDialog(self, self.CID_SAVEAS[2], os.getcwd(), "", \ + "*.png", wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) as dialog: + if dialog.ShowModal() == wx.ID_CANCEL: + return False + else: + outPathName = dialog.GetPath() + outTmpFile = io.StringIO() + outToTextFile = MiRCARTToTextFile( \ + self.panelCanvas.canvasMap, self.canvasSize) + outToTextFile.export(outTmpFile) + MiRCARTToPngFile(tmpFile).export(outPathName) + return True + # }}} + # {{{ canvasExportPastebin(self): XXX + def canvasExportPastebin(self): + MiRCARTToPastebin("253ce2f0a45140ee0a44ca99aa49260", \ + self.panelCanvas.canvasMap, self.canvasSize).export() + # }}} + # {{{ canvasNew(self, canvasPos=None, canvasSize=None, cellSize=None): XXX + def canvasNew(self, canvasPos=None, canvasSize=None, cellSize=None): + canvasPos = canvasPos if canvasPos != None else self.canvasPos + canvasSize = canvasSize if canvasSize != None else self.canvasSize + cellSize = cellSize if cellSize != None else self.cellSize + if self.panelCanvas != None: + self.panelCanvas.Close(); self.panelCanvas = None; + self.canvasPos = canvasPos; self.canvasSize = canvasSize; + self.cellSize = cellSize + self.panelCanvas = MiRCARTCanvas(self.panelSkin, parentFrame=self, \ + canvasPos=self.canvasPos, cellSize=self.cellSize, \ + canvasSize=self.canvasSize, canvasTools=self.canvasTools) + self._updateStatusBar(); self.onCanvasUpdate(); + # }}} + # {{{ canvasOpen(self): XXX + def canvasOpen(self): + with wx.FileDialog(self, self.CID_OPEN[2], os.getcwd(), "", \ + "*.txt", wx.FD_OPEN) as dialog: + if dialog.ShowModal() == wx.ID_CANCEL: + return False + else: + self.canvasPathName = dialog.GetPath() + with open(self.canvasPathName, "r") as newFile: + newFromTextFile = MiRCARTFromTextFile(newFile) + newMap = newFromTextFile.getMap() + self.canvasNew(canvasSize=newFromTextFile.getSize()) + eventDc = wx.ClientDC(self); tmpDc = wx.MemoryDC(); + tmpDc.SelectObject(self.panelCanvas.canvasBitmap) + for newNumRow in range(0, len(newMap)): + for newNumCol in range(0, len(newMap[newNumRow])): + self.panelCanvas.onJournalUpdate(False, \ + (newNumCol, newNumRow), \ + [newNumCol, newNumRow, \ + newMap[newNumRow][newNumCol][0][0], \ + newMap[newNumRow][newNumCol][0][1], \ + newMap[newNumRow][newNumCol][2]], \ + eventDc, tmpDc, (0, 0)) + wx.SafeYield() + return True + # }}} + # {{{ canvasSave(self): XXX + def canvasSave(self): + if self.canvasPathName == None: + if self.canvasSaveAs() == False: + return + try: + with open(self.canvasPathName, "w") as outFile: + MiRCARTToTextFile(self.panelCanvas.canvasMap, \ + self.panelCanvas.canvasSize).export(outFile) + except IOError as error: + pass + # }}} + # {{{ canvasSaveAs(self): XXX + def canvasSaveAs(self): + with wx.FileDialog(self, self.CID_SAVEAS[2], os.getcwd(), "", \ + "*.txt", wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) as dialog: + if dialog.ShowModal() == wx.ID_CANCEL: + return False + else: + self.canvasPathName = dialog.GetPath() + return True + # }}} + # {{{ onCanvasUpdate(self): XXX + def onCanvasUpdate(self): + if self.panelCanvas.canvasJournal.patchesUndo[self.panelCanvas.canvasJournal.patchesUndoLevel] != None: + self.menuItemsById[self.CID_UNDO[0]].Enable(True) + else: + self.menuItemsById[self.CID_UNDO[0]].Enable(False) + if self.panelCanvas.canvasJournal.patchesUndoLevel > 0: + self.menuItemsById[self.CID_REDO[0]].Enable(True) + else: + self.menuItemsById[self.CID_REDO[0]].Enable(False) + # }}} + # {{{ onClose(self, event): XXX + def onClose(self, event): + self.Destroy(); self.__del__(); + # }}} + # {{{ onFrameCommand(self, event): XXX + def onFrameCommand(self, event): + cid = event.GetId() + if cid == self.CID_NEW[0]: + self.canvasNew() + elif cid == self.CID_OPEN[0]: + self.canvasOpen() + elif cid == self.CID_SAVE[0]: + self.canvasSave() + elif cid == self.CID_SAVEAS[0]: + self.canvasSaveAs() + elif cid == self.CID_EXPORT_AS_PNG[0]: + self.canvasExportAsPng() + elif cid == self.CID_EXPORT_PASTEBIN[0]: + self.canvasExportPastebin() + elif cid == self.CID_EXIT[0]: + self.Close(True) + elif cid == self.CID_UNDO[0]: + self.panelCanvas.undo() + elif cid == self.CID_REDO[0]: + self.panelCanvas.redo() + elif cid == self.CID_CUT[0]: + pass + elif cid == self.CID_COPY[0]: + pass + elif cid == self.CID_PASTE[0]: + pass + elif cid == self.CID_DELETE[0]: + pass + elif cid == self.CID_INCRBRUSH[0]: + pass + elif cid == self.CID_DECRBRUSH[0]: + pass + elif cid == self.CID_SOLIDBRUSH[0]: + pass + elif cid == self.CID_RECT[0]: + pass + elif cid == self.CID_CIRCLE[0]: + pass + elif cid == self.CID_LINE[0]: + pass + elif cid >= self.CID_COLOUR00[0] \ + and cid <= self.CID_COLOUR15[0]: + numColour = cid - self.CID_COLOUR00[0] + if event.GetEventType() == wx.wxEVT_TOOL: + self.panelCanvas.mircFg = numColour + elif event.GetEventType() == wx.wxEVT_TOOL_RCLICKED: + self.panelCanvas.mircBg = numColour + self._updateStatusBar() + # }}} + # {{{ __del__(self): destructor method + def __del__(self): + if self.panelCanvas != None: + self.panelCanvas.Close(); self.panelCanvas = None; + # }}} + + # + # __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=[]): + super().__init__(parent, wx.ID_ANY, "MiRCART", size=appSize) + self.panelSkin = wx.Panel(self, wx.ID_ANY) + 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) + if not haveMiRCARTToPastebin: + self.menuItemsById[self.CID_EXPORT_PASTEBIN[0]].Enable(False) + if not haveMiRCARTToPngFile: + self.menuItemsById[self.CID_EXPORT_AS_PNG[0]].Enable(False) + + 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.canvasNew(canvasPos, canvasSize, cellSize) + +# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120 diff --git a/MiRCARTFromTextFile.py b/MiRCARTFromTextFile.py new file mode 100644 index 0000000..6459877 --- /dev/null +++ b/MiRCARTFromTextFile.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 +# +# MiRCARTFromTextFile.py -- XXX +# Copyright (c) 2018 Lucio Andrés Illanes Albornoz +# +# 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. +# + +class MiRCARTFromTextFile(): + """XXX""" + inFile = inSize = outMap = None + + # + # _CellState(): Cell state + class _CellState(): + CS_NONE = 0x00 + CS_BOLD = 0x01 + CS_ITALIC = 0x02 + CS_UNDERLINE = 0x04 + + # + # _ParseState(): Parsing loop state + class _ParseState(): + PS_CHAR = 1 + PS_COLOUR_DIGIT0 = 2 + PS_COLOUR_DIGIT1 = 3 + + # {{{ _parseCharAsColourSpec(self, colourSpec, curColours): XXX + def _parseCharAsColourSpec(self, colourSpec, curColours): + if len(colourSpec) > 0: + colourSpec = colourSpec.split(",") + if len(colourSpec) == 2: + return (int(colourSpec[0] or curColours[0]), \ + int(colourSpec[1])) + elif len(colourSpec) == 1: + return (int(colourSpec[0]), curColours[0]) + else: + return (15, 1) + # }}} + # {{{ _flipCellStateBit(self, cellState, bit): XXX + def _flipCellStateBit(self, cellState, bit): + if cellState & bit: + return cellState & ~bit + else: + return cellState | bit + # }}} + # {{{ _transform(self): XXX + def _transform(self): + inCurColourSpec = ""; inCurRow = -1; + inLine = self.inFile.readline() + inSize = [0, 0]; outMap = []; inMaxCols = 0; + while inLine: + inCellState = self._CellState.CS_NONE + inParseState = self._ParseState.PS_CHAR + inCurCol = 0; inMaxCol = len(inLine); + inCurColourDigits = 0; inCurColours = (15, 1); inCurColourSpec = ""; + inCurRow += 1; outMap.append([]); inRowCols = 0; inSize[1] += 1; + while inCurCol < inMaxCol: + inChar = inLine[inCurCol] + if inChar in set("\r\n"): \ + inCurCol += 1 + elif inParseState == self._ParseState.PS_CHAR: + inCurCol += 1 + if inChar == "": + inCellState = self._flipCellStateBit( \ + inCellState, self._CellState.CS_BOLD) + elif inChar == "": + inParseState = self._ParseState.PS_COLOUR_DIGIT0 + elif inChar == "": + inCellState = self._flipCellStateBit( \ + inCellState, self._CellState.CS_ITALIC) + elif inChar == "": + inCellState |= self._CellState.CS_NONE + inCurColours = (15, 1) + elif inChar == "": + inCurColours = (inCurColours[1], inCurColours[0]) + elif inChar == "": + inCellState = self._flipCellStateBit( \ + inCellState, self._CellState.CS_UNDERLINE) + else: + inRowCols += 1 + outMap[inCurRow].append((inCurColours, inCellState, inChar)) + elif inParseState == self._ParseState.PS_COLOUR_DIGIT0 \ + or inParseState == self._ParseState.PS_COLOUR_DIGIT1: + if inChar == "," \ + and inParseState == self._ParseState.PS_COLOUR_DIGIT0: + inCurCol += 1 + inCurColourDigits = 0; inCurColourSpec += inChar; + inParseState = self._ParseState.PS_COLOUR_DIGIT1 + elif inChar in set("0123456789") \ + and inCurColourDigits == 0: + inCurCol += 1 + inCurColourDigits += 1; inCurColourSpec += inChar; + elif inChar in set("0123456789") \ + and inCurColourDigits == 1 \ + and inCurColourSpec[-1] == "0": + inCurCol += 1 + inCurColourDigits += 1; inCurColourSpec += inChar; + elif inChar in set("012345") \ + and inCurColourDigits == 1 \ + and inCurColourSpec[-1] == "1": + inCurCol += 1 + inCurColourDigits += 1; inCurColourSpec += inChar; + else: + inCurColours = self._parseCharAsColourSpec( \ + inCurColourSpec, inCurColours) + inCurColourDigits = 0; inCurColourSpec = ""; + inParseState = self._ParseState.PS_CHAR + inMaxCols = max(inMaxCols, inRowCols) + inLine = self.inFile.readline() + inSize[0] = inMaxCols; self.inSize = inSize; self.outMap = outMap; + # }}} + # {{{ getMap(self): XXX + def getMap(self): + if self.outMap == None: + self._transform() + return self.outMap + # }}} + # {{{ getSize(self): XXX + def getSize(self): + if self.inSize == None: + self._transform() + return self.inSize + # }}} + + # + # __init__(self): initialisation method + def __init__(self, inFile): + self.inFile = inFile; self.inSize = None; self.outMap = None; + +# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120 diff --git a/MiRCARTToPastebin.py b/MiRCARTToPastebin.py new file mode 100644 index 0000000..88b25bc --- /dev/null +++ b/MiRCARTToPastebin.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 +# +# MiRCARTToPastebin.py -- XXX +# Copyright (c) 2018 Lucio Andrés Illanes Albornoz +# +# 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. +# + +from MiRCARTToTextFile import MiRCARTToTextFile +import io +import base64 +import requests, urllib.request + +class MiRCARTToPastebin(): + apiDevKey = outFile = outToTextFile = None + + # export(self): XXX + def export(self): + self.outToTextFile.export(self.outFile, pasteName="", pastePrivate=0) + requestData = { \ + "api_dev_key": self.apiDevKey, \ + "api_option": "paste", \ + "api_paste_code": base64.b64encode(self.outFile.read()), \ + "api_paste_name": pasteName, \ + "api_paste_private": pastePrivate} + responseHttp = requests.post("https://pastebin.com/post.php", \ + data=requestData) + if responseHttp.status_code == 200: + return responseHttp.text + else: + return None + + # __init__(self, canvasMap, canvasSize): XXX + def __init__(self, apiDevKey, canvasMap, canvasSize): + self.apiDevKey = apiDevKey + self.outFile = io.StringIO() + self.outToTextFile = MiRCARTToTextFile(canvasMap, canvasSize) + +# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120 diff --git a/MiRCARTToPngFile.py b/MiRCARTToPngFile.py new file mode 100755 index 0000000..8503b41 --- /dev/null +++ b/MiRCARTToPngFile.py @@ -0,0 +1,145 @@ +#!/usr/bin/env python3 +# +# MiRCARTToPngFile.py -- convert ASCII w/ mIRC control codes to monospaced PNG (for EFnet #MiRCART) +# Copyright (c) 2018 Lucio Andrés Illanes Albornoz +# +# 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. +# + +from PIL import Image, ImageDraw, ImageFont +from MiRCARTFromTextFile import MiRCARTFromTextFile +import string, sys + +class MiRCARTToPngFile: + """XXX""" + inFile = inFilePath = inFromTextFile = None + outFontFilePath = outFontSize = None + + # {{{ _ColourMapBold: mIRC colour number to RGBA map given ^B (bold) + _ColourMapBold = [ + [255, 255, 255], # White + [85, 85, 85], # Grey + [85, 85, 255], # Light Blue + [85, 255, 85], # Light Green + [255, 85, 85], # Light Red + [255, 85, 85], # Light Red + [255, 85, 255], # Pink + [255, 255, 85], # Light Yellow + [255, 255, 85], # Light Yellow + [85, 255, 85], # Light Green + [85, 255, 255], # Light Cyan + [85, 255, 255], # Light Cyan + [85, 85, 255], # Light Blue + [255, 85, 255], # Pink + [85, 85, 85], # Grey + [255, 255, 255], # White + ] + # }}} + # {{{ _ColourMapNormal: mIRC colour number to RGBA map given none of ^[BFV_] (bold, italic, reverse, underline) + _ColourMapNormal = [ + [255, 255, 255], # White + [0, 0, 0], # Black + [0, 0, 187], # Blue + [0, 187, 0], # Green + [255, 85, 85], # Light Red + [187, 0, 0], # Red + [187, 0, 187], # Purple + [187, 187, 0], # Yellow + [255, 255, 85], # Light Yellow + [85, 255, 85], # Light Green + [0, 187, 187], # Cyan + [85, 255, 255], # Light Cyan + [85, 85, 255], # Light Blue + [255, 85, 255], # Pink + [85, 85, 85], # Grey + [187, 187, 187], # Light Grey + ] + # }}} + # {{{ _drawUnderline(self, curPos, fontSize, imgDraw): XXX + def _drawUnderLine(self, curPos, fontSize, imgDraw): + imgDraw.line( \ + (curPos[0], \ + curPos[1] + (fontSize[1] - 2)), \ + (curPos[0] + fontSize[0], \ + curPos[1] + (fontSize[1] - 2)), fill=outColours[0]) + # }}} + # {{{ export(self, outFilePath): XXX + def export(self, outFilePath): + inSize = self.inFromTextFile.getSize(); + outSize = [inSize[n] * self.outImgFontSize[n] for n in range(0, 2)] + outCurPos = [0, 0] + outImg = Image.new("RGBA", outSize, (*self._ColourMapNormal[1], 255)) + outImgDraw = ImageDraw.Draw(outImg) + for inCurRow in range(0, inSize[1]): + for inCurCol in range(0, len(self.inFromTextFile.outMap[inCurRow])): + inCurCell = self.inFromTextFile.outMap[inCurRow][inCurCol] + outColours = [0, 0] + if inCurCell[1] & MiRCARTFromTextFile._CellState.CS_BOLD: + if inCurCell[2] != " ": + outColours[0] = self._ColourMapBold[inCurCell[0][0]] + outColours[1] = self._ColourMapBold[inCurCell[0][1]] + else: + if inCurCell[2] != " ": + outColours[0] = self._ColourMapNormal[inCurCell[0][0]] + outColours[1] = self._ColourMapNormal[inCurCell[0][1]] + outImgDraw.rectangle((*outCurPos, \ + outCurPos[0] + self.outImgFontSize[0], \ + outCurPos[1] + self.outImgFontSize[1]), \ + fill=(*outColours[1], 255)) + if inCurCell[2] != " " \ + and outColours[0] != outColours[1]: + # XXX implement italic + outImgDraw.text(outCurPos, \ + inCurCell[2], (*outColours[0], 255), self.outImgFont) + if inCurCell[1] & MiRCARTFromTextFile._CellState.CS_UNDERLINE: + self._drawUnderLine(curPos, self.outImgFontSize, outImgDraw) + outCurPos[0] += self.outImgFontSize[0]; + outCurPos[0] = 0 + outCurPos[1] += self.outImgFontSize[1] + outImg.save(outFilePath); + # }}} + + # + # __init__(self, inFilePath, fontFilePath="DejaVuSansMono.ttf", fontSize=11): initialisation method + def __init__(self, inFilePath, fontFilePath="DejaVuSansMono.ttf", fontSize=11): + self.inFilePath = inFilePath; self.inFile = open(inFilePath, "r"); + self.inFromTextFile = MiRCARTFromTextFile(self.inFile) + + self.outFontFilePath = fontFilePath; self.outFontSize = int(fontSize); + self.outImgFont = ImageFont.truetype( \ + self.outFontFilePath, self.outFontSize) + self.outImgFontSize = [*self.outImgFont.getsize(" ")] + self.outImgFontSize[1] += 3 + +# +# Entry point +def main(*argv): + MiRCARTToPngFile(argv[1], *argv[3:]).export(argv[2]) +if __name__ == "__main__": + if ((len(sys.argv) - 1) < 2)\ + or ((len(sys.argv) - 1) > 4): + print("usage: {} " \ + " " \ + " " \ + "[] " \ + "[]".format(sys.argv[0]), file=sys.stderr) + else: + main(*sys.argv) + +# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120 diff --git a/MiRCARTToTextFile.py b/MiRCARTToTextFile.py new file mode 100644 index 0000000..ee0950d --- /dev/null +++ b/MiRCARTToTextFile.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +# +# MiRCARTToTextFile.py -- XXX +# Copyright (c) 2018 Lucio Andrés Illanes Albornoz +# +# 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. +# + +class MiRCARTToTextFile(): + canvasMap = canvasSize = None + + # export(self, outFile): XXX + def export(self, outFile): + for canvasRow in range(0, self.canvasSize[1]): + canvasLastColours = [] + for canvasCol in range(0, self.canvasSize[0]): + canvasColColours = self.canvasMap[canvasRow][canvasCol][0:2] + canvasColText = self.canvasMap[canvasRow][canvasCol][2] + if canvasColColours != canvasLastColours: + canvasLastColours = canvasColColours + outFile.write("\x03" + \ + str(canvasColColours[0]) + \ + "," + str(canvasColColours[1])) + outFile.write(canvasColText) + outFile.write("\n") + + # __init__(self, canvasMap, canvasSize): XXX + def __init__(self, canvasMap, canvasSize): + self.canvasMap = canvasMap; self.canvasSize = canvasSize; + +# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120 diff --git a/MiRCARTTool.py b/MiRCARTTool.py new file mode 100644 index 0000000..0dad5ad --- /dev/null +++ b/MiRCARTTool.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# +# MiRCARTTool.py -- XXX +# Copyright (c) 2018 Lucio Andrés Illanes Albornoz +# +# 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. +# + +class MiRCARTTool(): + """XXX""" + parentCanvas = None + + # {{{ onMouseEvent(self, event, mapPoint, isDragging, isLeftDown, isRightDown): XXX + def onMouseEvent(self, event, mapPoint, isDragging, isLeftDown, isRightDown): + pass + # }}} + + # + # __init__(self, parentCanvas): initialisation method + def __init__(self, parentCanvas): + self.parentCanvas = parentCanvas + +# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120 diff --git a/MiRCARTToolRect.py b/MiRCARTToolRect.py new file mode 100644 index 0000000..b9e9fb2 --- /dev/null +++ b/MiRCARTToolRect.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +# +# MiRCARTToolRect.py -- XXX +# Copyright (c) 2018 Lucio Andrés Illanes Albornoz +# +# 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. +# + +from MiRCARTTool import MiRCARTTool + +class MiRCARTToolRect(MiRCARTTool): + """XXX""" + + # + # onMouseEvent(self, event, mapPoint, isDragging, isLeftDown, isRightDown): XXX + def onMouseEvent(self, event, mapPoint, isDragging, isLeftDown, isRightDown): + if isLeftDown: + return [[False, [[0, 0, \ + self.parentCanvas.mircFg, \ + self.parentCanvas.mircFg, " "]]], + [True, [[0, 0, \ + self.parentCanvas.mircFg, \ + self.parentCanvas.mircFg, " "]]]] + elif isRightDown: + return [[False, [[0, 0, \ + self.parentCanvas.mircBg, \ + self.parentCanvas.mircBg, " "]]], \ + [True, [[0, 0, \ + self.parentCanvas.mircBg, \ + self.parentCanvas.mircBg, " "]]]] + else: + return [[True, [[0, 0, \ + self.parentCanvas.mircFg, \ + self.parentCanvas.mircFg, " "]]]] + +# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120 diff --git a/README.md b/README.md index 736ccee..5785840 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ * Prerequisites: python3 && python3-{json,requests,urllib3} on Debian-family Linux distributions * IrcMiRCARTBot.py usage: IrcMiRCARTBot.py `` [``] [``] [``] [``] [``] -# MiRC2png.py -- convert ASCII w/ mIRC control codes to monospaced PNG (pending cleanup) +# MiRCARTToPngFile.py -- convert ASCII w/ mIRC control codes to monospaced PNG (pending cleanup) * Prerequisites: python3 && python3-pil on Debian-family Linux distributions * MiRC2png.py usage: MiRC2png.py `` `` [``] [``]