From c81275bf2f8fcf3abedcf3ad04c0e4e09c90fa65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucio=20Andr=C3=A9s=20Illanes=20Albornoz?= Date: Wed, 4 Sep 2019 15:52:54 +0200 Subject: [PATCH] Implements {un,re}doing resizing. libcanvas/Canvas.py:_dispatchDeltaPatches(): handle `resize' delta patches. libcanvas/Canvas.py:_dispatchPatch(): only commit to journal given commitUndo. libcanvas/Canvas.py:resize(): commit `resize' & {deleted,added} cell deltas to journal. libcanvas/Canvas.py: minor cleanup. libcanvas/Canvas{Backend,{Export,Import}Store,Journal}.py: minor cleanup. assets/text/arab-puke.txt: added from mircart/pack2/. assets/text/TODO: updated. --- assets/text/TODO | 18 +++---- assets/text/arab-puke.txt | 36 +++++++++++++ libcanvas/Canvas.py | 97 ++++++++++++++++++---------------- libcanvas/CanvasBackend.py | 18 +++---- libcanvas/CanvasExportStore.py | 71 ++++++++++++------------- libcanvas/CanvasImportStore.py | 26 ++++----- libcanvas/CanvasJournal.py | 2 +- 7 files changed, 151 insertions(+), 117 deletions(-) create mode 100644 assets/text/arab-puke.txt diff --git a/assets/text/TODO b/assets/text/TODO index 0bdfe7f..1765d93 100644 --- a/assets/text/TODO +++ b/assets/text/TODO @@ -1,12 +1,12 @@ -1) Scrollbar -2) Allow {un,re}doing resizing -3) Incremental auto{load,save} & {backup,restore} -4) Open and toggle a reference image in the background -5) Client-Server or Peer-to-Peer realtime collaboration -6) Arbitrary {format,palette}s ({4,8} bit ANSI/mIRC, etc.) -7) Hotkey & graphical interfaces to {composed,parametrised} tools -8) Layer, layout (e.g. for comics, zines, etc.) & {re,un}do canvas traits -9) Im- and exporting from/to ANSI, Blender, GIF, HTML, mIRC, Pastebin/..., PNG, printer, SAUCE, WEBM, etc. +1) General {cleanup,refactor} +2) Incremental auto{load,save} & {backup,restore} +3) Open and toggle a reference image in the background +4) Client-Server or Peer-to-Peer realtime collaboration +5) Arbitrary {format,palette}s ({4,8} bit ANSI/mIRC, etc.) +6) Hotkey & graphical interfaces to {composed,parametrised} tools +7) Layer, layout (e.g. for comics, zines, etc.) & {re,un}do canvas traits +8) {Insert,{ex,im}port}ing from/to ANSI, Blender, GIF, HTML, mIRC, printer, SAUCE, WEBM, etc. {clipboard,file} +9) GUI: a) rightmost alignment of Help menu b) scrollbar c) switch from wxPython to GTK d) toolbar tooltips 10) Asset management (e.g. kade, lion, etc.) & traits w/ simple linking & synchronised editing respecting layers 11) Sprites & scripted (Python?) animation on the basis of asset traits and {composable,parametrised} patterns (metric flow, particle system, rigging, ...) 12) Composition and parametrisation of tools from higher-order operators (brushes, filters, outlines, patterns & shaders) and unit tools; unit tools: diff --git a/assets/text/arab-puke.txt b/assets/text/arab-puke.txt new file mode 100644 index 0000000..1d22a35 --- /dev/null +++ b/assets/text/arab-puke.txt @@ -0,0 +1,36 @@ +0,1 3,3 0,1 9,9 0,1 9,9 0,1 9,9 0,1 9,9 0,1 9,9 0,1 9,9 0,1 9,9 0,1 3,3 0,1 0,0 1,1 0,1 0,0 0,1 9,9 0,1 9,9 0,1 9,9 0,1 9,9 0,1 9,9 0,1 9,9 0,1 9,9 0,1 9,9 0,1 9,9 0,1 9,9 1,1 9,9 1,1 9,9 1,1 0,1 9,9 0,1 9,9 0,1 9,9 0,1 9,9 0,1 9,9 0,1 +3,3 0,1 3,3 0,1 9,9 0,1 9,9 1,1 9,9 0,1 9,9 0,1 9,9 0,1 9,9 0,1 9,9 0,1 9,9 0,1 0,0 0,1 0,0 0,1 0,0 0,1 9,9 0,1 9,9 0,1 9,9 0,1 9,9 0,1 9,9 0,1 9,9 0,1 1,1 9,9 0,1 9,9 1,1 0,1 9,9 0,1 9,9 0,1 9,9 0,1 9,9 0,1 +0,1 3,3 0,1 9,9 0,1 11,11 10,10 11,11 0,1 9,9 0,1 9,9 0,1 3,3 0,1 3,3 0,1 0,0 0,1 0,0 0,1 0,0 0,1 9,9 0,1 9,9 0,1 9,9 0,1 1,1 9,9 0,1 1,1 0,1 9,9 0,1 9,9 0,1 +0,1 3,3 0,1 3,3 0,1 10,10 11,11 10,10 11,11 10,10 0,1 3,3 0,1 3,3 0,1 0,0 0,1 3,3 0,1 3,3 0,1 1,1 3,3 1,1 3,3 1,1 9,9 1,1 9,9 1,1 3,3 1,1 3,3 1,1 0,1 3,3 0,1 3,3 0,1 +9,9 1,1 3,3 1,1 10,10 11,11 10,10 11,11 10,10 1,1 0,0 1,1 11,11 1,10 1,1 11,11 1,1 3,3 1,1 9,9 1,1 3,3 1,1 11,11 1,1 1,10 11,11 0,1 9,9 +9,9 1,1 10,10 11,11 10,10 11,11 10,10 11,11 1,1 3,3 1,1 11,11 1,10 1,1 11,11 1,1 3,3 1,1 3,3 1,1 11,11 1,1 1,10 11,11 0,1 9,9 +9,9 1,1 10,10 11,11 10,10 11,11 10,10 1,1 8,8 1,1 11,11 1,10 1,1 11,11 1,1 3,3 1,1 11,11 1,1 1,10 11,11 1,1 0,1 9,9 +9,9 1,1 11,11 10,10 11,11 10,10 11,11 10,10 11,11 10,10 1,1 8,8 1,1 8,8 1,1 11,11 1,10 1,1 11,11 1,1 1,10 11,11 1,1 0,1 9,9 +9,9 1,1 11,11 10,10 11,11 10,10 11,10 10,10 11,11 10,10 1,1 8,8 1,1 8,8 1,1 11,11 1,10 1,1 1,10 11,11 1,1 0,1 9,9 +9,9 1,1 11,11 10,10 11,11 10,10 11,11 10,10 1,1 8,8 1,1 8,8 1,1 8,8 1,1 0,0 1,1 8,8 1,1 8,8 1,1 8,8 1,1 11,11 1,10 11,11 1,10 11,11 1,1 0,1 9,9 +1,3 9,9 1,1 11,11 10,10 11,11 10,10 11,11 1,1 8,8 1,1 8,8 1,1 8,8 1,1 0,0 1,1 0,0 1,1 8,8 1,1 8,8 1,1 8,8 1,1 11,11 10,10 11,11 1,1 0,1 9,9 1,3 +3,3 9,9 1,1 3,3 1,1 3,3 1,1 11,11 10,10 1,1 8,8 1,1 8,8 1,1 8,8 1,1 0,0 1,1 8,8 1,1 8,8 1,1 8,8 1,1 3,3 9,9 3,3 1,1 0,1 9,9 1,3 +3,3 9,9 1,1 3,3 1,1 3,3 1,1 3,3 1,1 3,3 1,1 8,8 1,1 8,8 1,1 8,8 1,1 0,0 1,1 8,8 1,1 8,8 1,1 0,0 1,1 8,8 1,1 8,8 1,1 8,8 1,1 3,3 9,9 1,1 0,1 9,9 1,3 +3,3 9,9 1,1 3,3 1,1 3,3 1,1 3,3 1,1 3,3 1,1 8,8 1,1 8,8 1,1 8,8 1,1 0,0 1,1 0,0 1,1 8,8 1,1 8,8 1,1 0,0 1,1 0,0 1,1 8,8 1,1 8,8 1,1 8,8 1,1 3,3 9,9 3,3 1,1 0,1 9,9 1,3 +3,3 9,9 1,1 9,9 1,1 9,9 1,1 9,9 1,1 7,7 8,8 1,1 8,8 1,1 8,8 1,1 0,0 1,1 8,8 1,1 0,0 1,1 8,8 1,1 8,8 1,1 8,8 1,1 9,9 3,3 1,1 0,1 9,9 1,3 +1,3 3,3 9,9 1,1 9,9 1,1 9,9 1,1 9,9 1,1 9,9 1,1 9,9 1,1 9,9 1,1 7,7 8,8 1,1 8,8 1,1 8,8 1,1 3,3 9,9 3,3 1,1 0,1 9,9 1,3 +11,11 3,3 9,9 1,1 7,7 8,8 1,1 8,8 1,1 8,8 1,1 8,8 1,1 3,3 9,9 1,1 0,1 9,9 1,3 11,11 +11,11 3,3 9,9 1,1 3,3 1,1 3,3 1,1 3,3 1,1 3,3 1,1 3,3 1,1 3,3 1,1 7,7 8,8 1,1 0,0 1,1 8,8 1,1 3,3 9,9 3,3 1,1 0,1 9,9 1,3 11,11 +11,11 1,3 3,3 9,9 1,1 9,9 1,1 9,9 1,1 9,9 1,1 9,9 1,1 9,9 1,1 7,7 8,8 1,1 8,8 1,1 9,9 3,3 1,1 0,1 9,9 1,3 11,11 +10,10 3,11 1,3 3,3 9,9 1,1 3,3 1,1 3,3 1,1 7,7 8,8 1,1 0,0 1,1 0,0 1,1 0,0 1,1 8,8 1,1 3,3 1,1 9,9 1,3 3,11 10,10 +10,10 3,11 1,3 3,3 9,9 1,1 3,3 1,1 3,3 1,1 3,3 1,1 3,3 1,1 3,3 1,1 7,7 8,8 8,1 1,1 8,1 8,8 1,1 9,9 3,3 1,1 9,9 1,3 3,11 10,10 +10,10 3,11 1,3 3,3 9,9 1,1 9,9 1,1 9,9 1,1 9,9 1,1 9,9 1,1 7,7 8,8 8,1 0,0 1,1 0,0 1,1 0,0 8,1 8,8 1,1 3,3 9,9 1,3 3,11 10,10 +10,10 3,11 3,3 9,9 7,7 8,8 8,1 1,1 8,1 8,8 7,7 9,9 3,3 1,3 3,11 10,10 +10,10 11,11 3,3 7,7 8,8 8,1 0,0 8,1 8,8 7,7 3,3 11,11 10,10 +10,10 11,11 3,3 9,9 7,7 8,8 8,1 8,8 7,7 9,9 3,3 11,11 10,10 +10,10 11,11 3,3 9,9 3,3 7,7 3,3 9,9 3,3 11,11 10,10 +10,10 11,11 3,3 9,9 3,3 11,11 3,3 9,9 3,3 11,11 10,10 +11,11 3,3 9,9 3,3 11,11 10,10 11,11 3,3 9,9 3,3 11,11 +11,11 3,3 9,9 3,3 11,11 10,10 11,11 10,10 11,11 3,3 9,9 3,3 11,11 +11,11 3,3 9,9 3,3 11,11 10,10 11,11 10,10 11,11 10,10 11,11 3,3 9,9 3,3 11,11 +11,11 3,3 9,9 3,3 11,11 10,10 11,11 10,10 11,11 3,3 9,9 3,3 11,11 +10,10 11,11 3,3 9,9 3,3 11,11 10,10 11,11 3,3 9,9 3,3 11,11 10,10 +10,10 11,11 3,3 9,9 3,3 11,11 3,3 9,9 3,3 11,11 10,10 +10,10 11,11 3,3 9,9 3,3 9,9 3,3 11,11 10,10 +10,10 11,11 3,3 9,9 3,3 11,11 10,10 +10,10 11,11 3,3 11,11 10,10 diff --git a/libcanvas/Canvas.py b/libcanvas/Canvas.py index 743c784..3b212f6 100644 --- a/libcanvas/Canvas.py +++ b/libcanvas/Canvas.py @@ -13,7 +13,6 @@ import wx class Canvas(wx.Panel): """XXX""" - imgurApiKey = ImgurApiKey.imgurApiKey # {{{ _commitPatch(self, patch): XXX def _commitPatch(self, patch): @@ -23,26 +22,29 @@ class Canvas(wx.Panel): def _dispatchDeltaPatches(self, deltaPatches): eventDc = self.canvasBackend.getDeviceContext(self) for patch in deltaPatches: - if self.canvasBackend.drawPatch(eventDc, patch): + if patch[0] == "resize": + del eventDc + self.resize(patch[1:], False) + eventDc = self.canvasBackend.getDeviceContext(self) + elif self.canvasBackend.drawPatch(eventDc, patch): self._commitPatch(patch) self.parentFrame.onCanvasUpdate(undoLevel=self.canvasJournal.patchesUndoLevel) # }}} - # {{{ _dispatchPatch(self, eventDc, isCursor, patch): XXX - def _dispatchPatch(self, eventDc, isCursor, patch): + # {{{ _dispatchPatch(self, eventDc, isCursor, patch, commitUndo=True): XXX + def _dispatchPatch(self, eventDc, isCursor, patch, commitUndo=True): if not self._canvasDirtyCursor: - self.canvasBackend.drawCursorMaskWithJournal( \ - self.canvasJournal, eventDc) + self.canvasBackend.drawCursorMaskWithJournal(self.canvasJournal, eventDc) self._canvasDirtyCursor = True if self.canvasBackend.drawPatch(eventDc, patch): patchDeltaCell = self.canvasMap[patch[1]][patch[0]] patchDelta = [*patch[0:2], *patchDeltaCell] - if isCursor: + if isCursor and commitUndo: self.canvasJournal.pushCursor(patchDelta) else: - if not self._canvasDirty: - self.canvasJournal.pushDeltas([], []) - self._canvasDirty = True - self.canvasJournal.updateCurrentDeltas(patchDelta, patch) + if commitUndo: + if not self._canvasDirty: + self.canvasJournal.pushDeltas([], []); self._canvasDirty = True; + self.canvasJournal.updateCurrentDeltas(patchDelta, patch) self._commitPatch(patch) # }}} @@ -78,16 +80,14 @@ class Canvas(wx.Panel): event.Dragging(), event.LeftIsDown(), event.RightIsDown(), \ self._dispatchPatch, eventDc) if self._canvasDirty: - self.parentFrame.onCanvasUpdate(cellPos=self.brushPos, \ - undoLevel=self.canvasJournal.patchesUndoLevel) + self.parentFrame.onCanvasUpdate(cellPos=self.brushPos, undoLevel=self.canvasJournal.patchesUndoLevel) if eventType == wx.wxEVT_MOTION: self.parentFrame.onCanvasUpdate(cellPos=mapPoint) # }}} # {{{ onPanelLeaveWindow(self, event): XXX def onPanelLeaveWindow(self, event): eventDc = self.canvasBackend.getDeviceContext(self) - self.canvasBackend.drawCursorMaskWithJournal( \ - self.canvasJournal, eventDc) + self.canvasBackend.drawCursorMaskWithJournal(self.canvasJournal, eventDc) # }}} # {{{ onPanelPaint(self, event): XXX def onPanelPaint(self, event): @@ -95,66 +95,71 @@ class Canvas(wx.Panel): # }}} # {{{ onStoreUpdate(self, newCanvasSize, newCanvas=None): XXX def onStoreUpdate(self, newCanvasSize, newCanvas=None): - self.resize(newCanvasSize=newCanvasSize) + self.resize(newCanvasSize=newCanvasSize, commitUndo=False) eventDc = self.canvasBackend.getDeviceContext(self) for numRow in range(self.canvasSize[1]): for numCol in range(self.canvasSize[0]): - if newCanvas != None \ - and numRow < len(newCanvas) \ + if newCanvas != None \ + and numRow < len(newCanvas) \ and numCol < len(newCanvas[numRow]): - self._commitPatch([ \ - numCol, numRow, *newCanvas[numRow][numCol]]) - self.canvasBackend.drawPatch(eventDc, \ - [numCol, numRow, \ - *self.canvasMap[numRow][numCol]]) + self._commitPatch([numCol, numRow, *newCanvas[numRow][numCol]]) + self.canvasBackend.drawPatch(eventDc, [numCol, numRow, *self.canvasMap[numRow][numCol]]) wx.SafeYield() # }}} - # {{{ resize(self, newCanvasSize): XXX - def resize(self, newCanvasSize): + # {{{ resize(self, newCanvasSize, commitUndo=True): XXX + def resize(self, newCanvasSize, commitUndo=True): if newCanvasSize != self.canvasSize: + self._canvasDirty, self._canvasDirtyCursor = False, False if self.canvasMap == None: - self.canvasMap = []; oldCanvasSize = [0, 0]; + self.canvasMap, oldCanvasSize = [], [0, 0] else: oldCanvasSize = self.canvasSize deltaCanvasSize = [b - a for a, b in zip(oldCanvasSize, newCanvasSize)] newWinSize = [a * b for a, b in zip(newCanvasSize, self.canvasBackend.cellSize)] - self.SetMinSize(newWinSize) - self.SetSize(wx.DefaultCoord, wx.DefaultCoord, *newWinSize) + self.SetMinSize(newWinSize); self.SetSize(wx.DefaultCoord, wx.DefaultCoord, *newWinSize); curWindow = self while curWindow != None: - curWindow.Layout() - curWindow = curWindow.GetParent() + curWindow.Layout(); curWindow = curWindow.GetParent(); self.canvasBackend.resize(newCanvasSize, self.canvasBackend.cellSize) eventDc = self.canvasBackend.getDeviceContext(self) - self.canvasJournal.resetCursor(); self.canvasJournal.resetUndo(); + self.canvasJournal.resetCursor() + + if commitUndo: + undoPatches, redoPatches = ["resize", *oldCanvasSize], ["resize", *newCanvasSize] + if not self._canvasDirty: + self.canvasJournal.pushDeltas([], []); self._canvasDirty = True; + self.canvasJournal.updateCurrentDeltas(undoPatches, redoPatches) if deltaCanvasSize[0] < 0: for numRow in range(oldCanvasSize[1]): + if commitUndo: + for numCol in range((oldCanvasSize[0] + deltaCanvasSize[0]), oldCanvasSize[0]): + if not self._canvasDirty: + self.canvasJournal.pushDeltas([], []); self._canvasDirty = True; + self.canvasJournal.updateCurrentDeltas([numCol, numRow, *self.canvasMap[numRow][numCol]], [numCol, numRow, 1, 1, 0, " "]) del self.canvasMap[numRow][-1:(deltaCanvasSize[0]-1):-1] else: for numRow in range(oldCanvasSize[1]): - self.canvasMap[numRow].extend( \ - [[1, 1, 0, " "]] * deltaCanvasSize[0]) + self.canvasMap[numRow].extend([[1, 1, 0, " "]] * deltaCanvasSize[0]) for numNewCol in range(oldCanvasSize[0], newCanvasSize[0]): - self.canvasBackend.drawPatch( \ - eventDc, [numNewCol, numRow, \ - *self.canvasMap[numRow][-1]]) + self._dispatchPatch(eventDc, False, [numNewCol, numRow, 1, 1, 0, " "], commitUndo) if deltaCanvasSize[1] < 0: + if commitUndo: + for numRow in range((oldCanvasSize[1] + deltaCanvasSize[1]), oldCanvasSize[1]): + for numCol in range(oldCanvasSize[0] + deltaCanvasSize[0]): + if not self._canvasDirty: + self.canvasJournal.pushDeltas([], []); self._canvasDirty = True; + self.canvasJournal.updateCurrentDeltas([numCol, numRow, *self.canvasMap[numRow][numCol]], [numCol, numRow, 1, 1, 0, " "]) del self.canvasMap[-1:(deltaCanvasSize[1]-1):-1] else: for numNewRow in range(oldCanvasSize[1], newCanvasSize[1]): - self.canvasMap.extend( \ - [[[1, 1, 0, " "]] * newCanvasSize[0]]) + self.canvasMap.extend([[[1, 1, 0, " "]] * newCanvasSize[0]]) for numNewCol in range(newCanvasSize[0]): - self.canvasBackend.drawPatch( \ - eventDc, [numNewCol, numNewRow, \ - *self.canvasMap[-1][-1]]) + self._dispatchPatch(eventDc, False, [numNewCol, numNewRow, 1, 1, 0, " "], commitUndo) - self.canvasSize = newCanvasSize - wx.SafeYield() - self.parentFrame.onCanvasUpdate(size=newCanvasSize, undoLevel=-1) + self.canvasSize = newCanvasSize; wx.SafeYield(); self.parentFrame.onCanvasUpdate(size=newCanvasSize, undoLevel=self.canvasJournal.patchesUndoLevel) # }}} # {{{ __del__(self): destructor method @@ -169,8 +174,10 @@ class Canvas(wx.Panel): super().__init__(parent, pos=defaultCanvasPos, size=[w * h for w, h in zip(defaultCanvasSize, defaultCellSize)]) self.brushColours, self.brushPos, self.brushSize = [4, 1], [0, 0], [1, 1] + self._canvasDirty, self._canvasDirtyCursor = False, False self.canvasMap, self.canvasPos, self.canvasSize, = None, defaultCanvasPos, defaultCanvasSize self.defaultCanvasPos, self.defaultCanvasSize, self.defaultCellSize = defaultCanvasPos, defaultCanvasSize, defaultCellSize + self.imgurApiKey = ImgurApiKey.imgurApiKey self.parentFrame = parentFrame self.parentFrame.onCanvasUpdate(brushSize=self.brushSize, colours=self.brushColours) @@ -189,4 +196,4 @@ class Canvas(wx.Panel): self.Bind(eventType, self.onPanelInput) self.Bind(wx.EVT_PAINT, self.onPanelPaint) -# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120 +# vim:expandtab foldmethod=marker sw=4 ts=4 tw=0 diff --git a/libcanvas/CanvasBackend.py b/libcanvas/CanvasBackend.py index 97e01dd..cf2ef97 100644 --- a/libcanvas/CanvasBackend.py +++ b/libcanvas/CanvasBackend.py @@ -9,9 +9,6 @@ import wx class CanvasBackend(): """XXX""" - _font = _brushes = _pens = None - _lastBrush = _lastPen = None - canvasBitmap = cellSize = None # {{{ _drawBrushPatch(self, eventDc, patch): XXX def _drawBrushPatch(self, eventDc, patch): @@ -76,6 +73,11 @@ class CanvasBackend(): return [a * b for a, b in zip(patch[0:2], self.cellSize)] # }}} + # {{{ drawCursorMaskWithJournal(self, canvasJournal, eventDc): XXX + def drawCursorMaskWithJournal(self, canvasJournal, eventDc): + for patch in canvasJournal.popCursor(): + self.drawPatch(eventDc, patch) + # }}} # {{{ drawPatch(self, eventDc, patch): XXX def drawPatch(self, eventDc, patch): if patch[0] < self.canvasSize[0] \ @@ -90,15 +92,9 @@ class CanvasBackend(): else: return False # }}} - # {{{ drawCursorMaskWithJournal(self, canvasJournal, eventDc): XXX - def drawCursorMaskWithJournal(self, canvasJournal, eventDc): - for patch in canvasJournal.popCursor(): - self.drawPatch(eventDc, patch) - # }}} # {{{ getDeviceContext(self, parentWindow): XXX def getDeviceContext(self, parentWindow): - eventDc = wx.BufferedDC( \ - wx.ClientDC(parentWindow), self.canvasBitmap) + eventDc = wx.BufferedDC(wx.ClientDC(parentWindow), self.canvasBitmap) self._lastBrushBg = self._lastBrushFg = self._lastPen = None; return eventDc # }}} @@ -151,6 +147,8 @@ class CanvasBackend(): # # __init__(self, canvasSize, cellSize): initialisation method def __init__(self, canvasSize, cellSize): + self._brushes, self._font, self._lastBrush, self._lastPen, self._pens = None, None, None, None, None + self.canvasBitmap, self.cellSize = None, None self._initBrushesAndPens() self.reset(canvasSize, cellSize) diff --git a/libcanvas/CanvasExportStore.py b/libcanvas/CanvasExportStore.py index c37f686..f153bdd 100644 --- a/libcanvas/CanvasExportStore.py +++ b/libcanvas/CanvasExportStore.py @@ -20,22 +20,21 @@ except ImportError: class CanvasExportStore(): """XXX""" - parentCanvas = None + ImgurUploadUrl = "https://api.imgur.com/3/upload.json" + PastebinPostUrl = "https://pastebin.com/api/api_post.php" # {{{ _exportFileToImgur(self, apiKey, imgName, imgTitle, pathName): upload single PNG file to Imgur def _exportFileToImgur(self, apiKey, imgName, imgTitle, pathName): with open(pathName, "rb") as requestImage: requestImageData = requestImage.read() requestData = { \ - "image": base64.b64encode(requestImageData), \ - "key": apiKey, \ - "name": imgName, \ - "title": imgTitle, \ - "type": "base64"} + "image": base64.b64encode(requestImageData), \ + "key": apiKey, \ + "name": imgName, \ + "title": imgTitle, \ + "type": "base64"} requestHeaders = {"Authorization": "Client-ID " + apiKey} - responseHttp = requests.post( \ - "https://api.imgur.com/3/upload.json", \ - data=requestData, headers=requestHeaders) + responseHttp = requests.post(ImgurUploadUrl, data=requestData, headers=requestHeaders) responseDict = json.loads(responseHttp.text) if responseHttp.status_code == 200: return [200, responseDict.get("data").get("link")] @@ -43,10 +42,6 @@ class CanvasExportStore(): return [responseHttp.status_code, ""] # }}} - # {{{ exportBitmapToPngFile(self, canvasBitmap, outPathName, outType): XXX - def exportBitmapToPngFile(self, canvasBitmap, outPathName, outType): - return canvasBitmap.ConvertToImage().SaveFile(outPathName, outType) - # }}} # {{{ exportBitmapToImgur(self, apiKey, canvasBitmap, imgName, imgTitle, imgType): XXX def exportBitmapToImgur(self, apiKey, canvasBitmap, imgName, imgTitle, imgType): tmpPathName = tempfile.mkstemp() @@ -56,19 +51,22 @@ class CanvasExportStore(): os.remove(tmpPathName[1]) return imgurResult # }}} + # {{{ exportBitmapToPngFile(self, canvasBitmap, outPathName, outType): XXX + 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: outFile = io.StringIO() self.exportTextFile(canvasMap, canvasSize, outFile) - requestData = { \ - "api_dev_key": apiDevKey, \ - "api_option": "paste", \ - "api_paste_code": outFile.getvalue().encode(), \ - "api_paste_name": pasteName, \ + requestData = { \ + "api_dev_key": apiDevKey, \ + "api_option": "paste", \ + "api_paste_code": outFile.getvalue().encode(), \ + "api_paste_name": pasteName, \ "api_paste_private": pastePrivate} - responseHttp = requests.post("https://pastebin.com/api/api_post.php", \ - data=requestData) + responseHttp = requests.post(PastebinPostUrl, data=requestData) if responseHttp.status_code == 200: if responseHttp.text.startswith("http"): return (True, responseHttp.text) @@ -91,33 +89,32 @@ class CanvasExportStore(): def exportTextBuffer(self, canvasMap, canvasSize): outBuffer = "" for canvasRow in range(canvasSize[1]): - canvasLastColours = [] + canvasLastColours = [15, 1] for canvasCol in range(canvasSize[0]): canvasColColours = canvasMap[canvasRow][canvasCol][0:2] canvasColText = canvasMap[canvasRow][canvasCol][3] - if canvasColColours != canvasLastColours: + if canvasColColours[0] != canvasLastColours[0] \ + and canvasColColours[1] != canvasLastColours[1]: + if canvasColColours[0] == canvasLastColours[1] \ + and canvasColColours[1] == canvasLastColours[0]: + outBuffer += "\u0016" + else: + outBuffer += "\u0003{},{}".format(canvasColColours[0], canvasColColours[1]) canvasLastColours = canvasColColours - outBuffer += "\x03" + \ - str(canvasColColours[0]) + \ - "," + str(canvasColColours[1]) + elif canvasColColours[1] != canvasLastColours[1]: + outBuffer += "\u0003{},{}".format(canvasLastColours[0], canvasColColours[1]) + canvasLastColours[1] = canvasColColours[1] + elif canvasColColours[0] != canvasLastColours[0]: + outBuffer += "\u0003{}".format(canvasColColours[0]) + canvasLastColours[0] = canvasColColours[0] outBuffer += canvasColText outBuffer += "\n" return outBuffer # }}} # {{{ exportTextFile(self, canvasMap, canvasSize, outFile): XXX def exportTextFile(self, canvasMap, canvasSize, outFile): - for canvasRow in range(canvasSize[1]): - canvasLastColours = [] - for canvasCol in range(canvasSize[0]): - canvasColColours = canvasMap[canvasRow][canvasCol][0:2] - canvasColText = canvasMap[canvasRow][canvasCol][3] - if canvasColColours != canvasLastColours: - canvasLastColours = canvasColColours - outFile.write("\x03" + \ - str(canvasColColours[0]) + \ - "," + str(canvasColColours[1])) - outFile.write(canvasColText) - outFile.write("\n") + outBuffer = self.exportTextBuffer(canvasMap, canvasSize) + outFile.write(outBuffer) # }}} # diff --git a/libcanvas/CanvasImportStore.py b/libcanvas/CanvasImportStore.py index 3ca2114..12058b7 100644 --- a/libcanvas/CanvasImportStore.py +++ b/libcanvas/CanvasImportStore.py @@ -25,20 +25,16 @@ class CanvasImportStore(): # {{{ _flipCellStateBit(self, cellState, bit): XXX def _flipCellStateBit(self, cellState, bit): - if cellState & bit: - return cellState & ~bit - else: - return cellState | bit + return cellState & ~bit if cellState & bit else cellState | bit # }}} # {{{ _parseCharAsColourSpec(self, colourSpec, curColours): XXX def _parseCharAsColourSpec(self, colourSpec, curColours): if len(colourSpec) > 0: colourSpec = colourSpec.split(",") - if len(colourSpec) == 2 \ + if len(colourSpec) == 2 \ and len(colourSpec[1]) > 0: - return (int(colourSpec[0] or curColours[0]), \ - int(colourSpec[1])) - elif len(colourSpec) == 1 \ + return (int(colourSpec[0] or curColours[0]), int(colourSpec[1])) + elif len(colourSpec) == 1 \ or len(colourSpec[1]) == 0: return (int(colourSpec[0]), curColours[1]) else: @@ -49,6 +45,13 @@ class CanvasImportStore(): def importIntoPanel(self): self.parentCanvas.onStoreUpdate(self.inSize, self.outMap) # }}} + # {{{ importNew(self, newCanvasSize=None): XXX + def importNew(self, newCanvasSize=None): + newMap = [[[1, 1, 0, " "] \ + for x in range(newCanvasSize[0])] \ + for y in range(newCanvasSize[1])] + self.parentCanvas.onStoreUpdate(newCanvasSize, newMap) + # }}} # {{{ importTextFile(self, pathName): XXX def importTextFile(self, pathName): return self.importTextFileBuffer(open(pathName, "r", encoding="utf-8-sig")) @@ -127,13 +130,6 @@ class CanvasImportStore(): inSize[0] = inMaxCols; self.inSize, self.outMap = inSize, outMap; inFile.close() # }}} - # {{{ importNew(self, newCanvasSize=None): XXX - def importNew(self, newCanvasSize=None): - newMap = [[[1, 1, 0, " "] \ - for x in range(newCanvasSize[0])] \ - for y in range(newCanvasSize[1])] - self.parentCanvas.onStoreUpdate(newCanvasSize, newMap) - # }}} # # __init__(self, inFile=None, parentCanvas=None): initialisation method diff --git a/libcanvas/CanvasJournal.py b/libcanvas/CanvasJournal.py index a2a617f..6122303 100644 --- a/libcanvas/CanvasJournal.py +++ b/libcanvas/CanvasJournal.py @@ -6,7 +6,6 @@ class CanvasJournal(): """XXX""" - patchesCursor = patchesUndo = patchesUndoLevel = None # {{{ popCursor(self): XXX def popCursor(self): @@ -74,6 +73,7 @@ class CanvasJournal(): # # __init__(self): initialisation method def __init__(self): + self.patchesCursor, self.patchesUndo, self. patchesUndoLevel = None, None, None self.resetCursor(); self.resetUndo(); # vim:expandtab foldmethod=marker sw=4 ts=4 tw=120