MiRCART{Canvas,Frame}.py: adds circle & line tools.

MiRCARTTool{Circle,Line}.py: initial implementation.
This commit is contained in:
Lucio Andrés Illanes Albornoz 2018-01-08 16:12:11 +01:00
parent 7aecb6fd58
commit 1edb7cc626
7 changed files with 199 additions and 38 deletions

View File

@ -23,14 +23,13 @@
# #
from MiRCARTFrame import MiRCARTFrame from MiRCARTFrame import MiRCARTFrame
from MiRCARTToolRect import MiRCARTToolRect
import sys, wx import sys, wx
# #
# Entry point # Entry point
def main(*argv): def main(*argv):
wxApp = wx.App(False) wxApp = wx.App(False)
MiRCARTFrame(None, canvasTools=[MiRCARTToolRect]) MiRCARTFrame(None)
wxApp.MainLoop() wxApp.MainLoop()
if __name__ == "__main__": if __name__ == "__main__":
main(*sys.argv) main(*sys.argv)

View File

@ -31,10 +31,11 @@ class MiRCARTCanvas(wx.Panel):
"""XXX""" """XXX"""
parentFrame = None parentFrame = None
canvasPos = canvasSize = canvasWinSize = cellSize = None canvasPos = canvasSize = canvasWinSize = cellSize = None
canvasBitmap = canvasMap = canvasTools = None canvasBitmap = canvasMap = None
brushColours = brushPos = brushSize = None brushColours = brushPos = brushSize = None
mircBrushes = mircPens = None mircBrushes = mircPens = None
canvasJournal = canvasStore = None canvasJournal = canvasStore = None
canvasCurTool = None
# {{{ _initBrushesAndPens(self): XXX # {{{ _initBrushesAndPens(self): XXX
def _initBrushesAndPens(self): def _initBrushesAndPens(self):
@ -112,12 +113,12 @@ class MiRCARTCanvas(wx.Panel):
tmpDc.SelectObject(self.canvasBitmap) tmpDc.SelectObject(self.canvasBitmap)
eventPoint = event.GetLogicalPosition(eventDc) eventPoint = event.GetLogicalPosition(eventDc)
mapPoint = self._eventPointToMapPoint(eventPoint) mapPoint = self._eventPointToMapPoint(eventPoint)
for tool in self.canvasTools: tool = self.canvasCurTool
mapPatches = tool.onMouseEvent( \ mapPatches = tool.onMouseEvent( \
event, mapPoint, self.brushColours, self.brushSize, \ event, mapPoint, self.brushColours, self.brushSize, \
event.Dragging(), event.LeftIsDown(), event.RightIsDown()) event.Dragging(), event.LeftIsDown(), event.RightIsDown())
self.canvasJournal.merge(mapPatches, eventDc, tmpDc, mapPoint) self.canvasJournal.merge(mapPatches, eventDc, tmpDc, mapPoint)
self.parentFrame.onCanvasUpdate() self.parentFrame.onCanvasUpdate()
self.parentFrame.onCanvasMotion(event, mapPoint) self.parentFrame.onCanvasMotion(event, mapPoint)
# }}} # }}}
# {{{ onMouseWindowEvent(self, event): XXX # {{{ onMouseWindowEvent(self, event): XXX
@ -211,17 +212,17 @@ class MiRCARTCanvas(wx.Panel):
# }}} # }}}
# #
# _init__(self, parent, parentFrame, canvasPos, cellSize, canvasSize, canvasTools): initialisation method # _init__(self, parent, parentFrame, canvasPos, canvasSize, cellSize): initialisation method
def __init__(self, parent, parentFrame, canvasPos, canvasSize, canvasTools, cellSize): def __init__(self, parent, parentFrame, canvasPos, canvasSize, cellSize):
self.parentFrame = parentFrame self.parentFrame = parentFrame
self.canvasPos = canvasPos; self.canvasSize = canvasSize; self.canvasPos = canvasPos; self.canvasSize = canvasSize;
self.canvasTools = [canvasTool(self) for canvasTool in canvasTools]
self.cellSize = cellSize self.cellSize = cellSize
self.brushColours = [4, 1]; self._initBrushesAndPens(); self.brushColours = [4, 1]; self._initBrushesAndPens();
self.brushPos = [0, 0]; self.brushSize = [1, 1]; self.brushPos = [0, 0]; self.brushSize = [1, 1];
self.canvasJournal = MiRCARTCanvasJournal(parentCanvas=self) self.canvasJournal = MiRCARTCanvasJournal(parentCanvas=self)
self.canvasStore = MiRCARTCanvasStore(parentCanvas=self) self.canvasStore = MiRCARTCanvasStore(parentCanvas=self)
self.canvasCurTool = None
super().__init__(parent, pos=canvasPos, \ super().__init__(parent, pos=canvasPos, \
size=[w*h for w,h in zip(canvasSize, cellSize)]) size=[w*h for w,h in zip(canvasSize, cellSize)])

View File

@ -46,17 +46,12 @@ class MiRCARTCanvasJournal():
self.patchesUndoLevel = 0 self.patchesUndoLevel = 0
patchesUndo = [] patchesUndo = []
for patch in patches: for patch in patches:
absMapPoint = self._relMapPointToAbsMapPoint(patch[0][0], atPoint) patchesUndo.append([ \
patchesUndo.append([ \ [patch[0], *patch[0][1:]], \
[absMapPoint, *patch[0][1:]], \ [patch[0], *patch[1][1:]]])
[absMapPoint, *patch[1][1:]]])
if len(patchesUndo) > 0: if len(patchesUndo) > 0:
self.patchesUndo.insert(0, patchesUndo) self.patchesUndo.insert(0, patchesUndo)
# }}} # }}}
# {{{ _relMapPointToAbsMapPoint(self, relMapPoint, atPoint): XXX
def _relMapPointToAbsMapPoint(self, relMapPoint, atPoint):
return [a+b for a,b in zip(atPoint, relMapPoint)]
# }}}
# {{{ merge(self, mapPatches, eventDc, tmpDc, atPoint): XXX # {{{ merge(self, mapPatches, eventDc, tmpDc, atPoint): XXX
def merge(self, mapPatches, eventDc, tmpDc, atPoint): def merge(self, mapPatches, eventDc, tmpDc, atPoint):
patchesUndo = [] patchesUndo = []
@ -65,18 +60,17 @@ class MiRCARTCanvasJournal():
if mapPatchTmp: if mapPatchTmp:
self._popTmp(eventDc, tmpDc) self._popTmp(eventDc, tmpDc)
for patch in mapPatch[1]: for patch in mapPatch[1]:
absMapPoint = self._relMapPointToAbsMapPoint(patch[0], atPoint) if patch[0][0] >= self.parentCanvas.canvasSize[0] \
if absMapPoint[0] >= self.parentCanvas.canvasSize[0] \ or patch[0][1] >= self.parentCanvas.canvasSize[1]:
or absMapPoint[1] >= self.parentCanvas.canvasSize[1]:
continue continue
elif mapPatchTmp: elif mapPatchTmp:
self._pushTmp(absMapPoint) self._pushTmp(patch[0])
self.parentCanvas.onJournalUpdate(mapPatchTmp, \ self.parentCanvas.onJournalUpdate(mapPatchTmp, \
absMapPoint, patch, eventDc, tmpDc, atPoint) patch[0], patch, eventDc, tmpDc, (0, 0))
else: else:
patchUndo = \ patchUndo = \
self.parentCanvas.onJournalUpdate(mapPatchTmp, \ self.parentCanvas.onJournalUpdate(mapPatchTmp, \
absMapPoint, patch, eventDc, tmpDc, atPoint, True) patch[0], patch, eventDc, tmpDc, (0, 0), True)
patchesUndo.append([patchUndo, patch]) patchesUndo.append([patchUndo, patch])
if len(patchesUndo) > 0: if len(patchesUndo) > 0:
self._pushUndo(atPoint, patchesUndo) self._pushUndo(atPoint, patchesUndo)

View File

@ -26,13 +26,16 @@ from MiRCARTCanvas import MiRCARTCanvas, haveUrllib
from MiRCARTColours import MiRCARTColours from MiRCARTColours import MiRCARTColours
from MiRCARTGeneralFrame import MiRCARTGeneralFrame, \ from MiRCARTGeneralFrame import MiRCARTGeneralFrame, \
TID_ACCELS, TID_COMMAND, TID_LIST, TID_MENU, TID_NOTHING, TID_SELECT, TID_TOOLBAR TID_ACCELS, TID_COMMAND, TID_LIST, TID_MENU, TID_NOTHING, TID_SELECT, TID_TOOLBAR
from MiRCARTToolCircle import MiRCARTToolCircle
from MiRCARTToolLine import MiRCARTToolLine
from MiRCARTToolRect import MiRCARTToolRect
import os, wx import os, wx
class MiRCARTFrame(MiRCARTGeneralFrame): class MiRCARTFrame(MiRCARTGeneralFrame):
"""XXX""" """XXX"""
panelCanvas = canvasPathName = None panelCanvas = canvasPathName = None
canvasPos = canvasSize = canvasTools = cellSize = None canvasPos = canvasSize = cellSize = None
# {{{ Commands # {{{ Commands
# Id Type Id Labels Icon bitmap Accelerator [Initial state] # Id Type Id Labels Icon bitmap Accelerator [Initial state]
@ -355,11 +358,17 @@ class MiRCARTFrame(MiRCARTGeneralFrame):
elif cid == self.CID_SOLID_BRUSH[0]: elif cid == self.CID_SOLID_BRUSH[0]:
pass pass
elif cid == self.CID_RECT[0]: elif cid == self.CID_RECT[0]:
pass self.menuItemsById[cid].Check(True)
self.panelCanvas.canvasCurTool = \
MiRCARTToolRect(self.panelCanvas)
elif cid == self.CID_CIRCLE[0]: elif cid == self.CID_CIRCLE[0]:
pass self.menuItemsById[cid].Check(True)
self.panelCanvas.canvasCurTool = \
MiRCARTToolCircle(self.panelCanvas)
elif cid == self.CID_LINE[0]: elif cid == self.CID_LINE[0]:
pass self.menuItemsById[cid].Check(True)
self.panelCanvas.canvasCurTool = \
MiRCARTToolLine(self.panelCanvas)
elif cid >= self.CID_COLOUR00[0] \ elif cid >= self.CID_COLOUR00[0] \
and cid <= self.CID_COLOUR15[0]: and cid <= self.CID_COLOUR15[0]:
numColour = cid - self.CID_COLOUR00[0] numColour = cid - self.CID_COLOUR00[0]
@ -376,16 +385,16 @@ class MiRCARTFrame(MiRCARTGeneralFrame):
# }}} # }}}
# #
# __init__(self, parent, appSize=(800, 600), canvasPos=(25, 50), cellSize=(7, 14), canvasSize=(100, 30), canvasTools=[]): initialisation method # __init__(self, parent, appSize=(800, 600), canvasPos=(25, 50), canvasSize=(100, 30), cellSize=(7, 14)): initialisation method
def __init__(self, parent, appSize=(800, 600), canvasPos=(25, 50), cellSize=(7, 14), canvasSize=(100, 30), canvasTools=[]): def __init__(self, parent, appSize=(800, 600), canvasPos=(25, 50), canvasSize=(100, 30), cellSize=(7, 14)):
panelSkin = super().__init__(parent, wx.ID_ANY, "MiRCART", size=appSize) panelSkin = super().__init__(parent, wx.ID_ANY, "MiRCART", size=appSize)
self._setPaletteToolBitmaps() self._setPaletteToolBitmaps()
self.canvasPos = canvasPos; self.cellSize = cellSize; self.canvasSize = canvasSize; self.canvasPos = canvasPos; self.cellSize = cellSize; self.canvasSize = canvasSize;
self.canvasPathName = None self.canvasPathName = None
self.canvasTools = canvasTools
self.panelCanvas = MiRCARTCanvas(panelSkin, parentFrame=self, \ self.panelCanvas = MiRCARTCanvas(panelSkin, parentFrame=self, \
canvasPos=self.canvasPos, canvasSize=self.canvasSize, \ canvasPos=self.canvasPos, canvasSize=self.canvasSize, \
canvasTools=self.canvasTools, cellSize=self.cellSize) cellSize=self.cellSize)
self.panelCanvas.canvasCurTool = MiRCARTToolRect(self.panelCanvas)
self.canvasNew() self.canvasNew()
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120 # vim:expandtab foldmethod=marker sw=4 ts=4 tw=120

56
MiRCARTToolCircle.py Normal file
View File

@ -0,0 +1,56 @@
#!/usr/bin/env python3
#
# MiRCARTToolCircle.py -- XXX
# Copyright (c) 2018 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
from MiRCARTTool import MiRCARTTool
class MiRCARTToolCircle(MiRCARTTool):
"""XXX"""
#
# onMouseEvent(self, event, atPoint, brushColours, brushSize, isDragging, isLeftDown, isRightDown): XXX
def onMouseEvent(self, event, atPoint, brushColours, brushSize, isDragging, isLeftDown, isRightDown):
brushColours = brushColours.copy()
if isLeftDown:
brushColours[1] = brushColours[0]
elif isRightDown:
brushColours[0] = brushColours[1]
else:
brushColours[1] = brushColours[0]
brushPatches = []
_brushSize = brushSize[0]*2
originPoint = (_brushSize/2, _brushSize/2)
radius = _brushSize
for brushY in range(-radius, radius + 1):
for brushX in range(-radius, radius + 1):
if ((brushX**2)+(brushY**2) < (((radius**2)+radius)*0.8)):
brushPatches.append([ \
[atPoint[0] + int(originPoint[0]+brushX), \
atPoint[1] + int(originPoint[1]+brushY)], \
brushColours, 0, " "])
if isLeftDown or isRightDown:
return [[False, brushPatches], [True, brushPatches]]
else:
return [[True, brushPatches]]
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120

100
MiRCARTToolLine.py Normal file
View File

@ -0,0 +1,100 @@
#!/usr/bin/env python3
#
# MiRCARTToolLine.py -- XXX
# Copyright (c) 2018 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
from MiRCARTTool import MiRCARTTool
class MiRCARTToolLine(MiRCARTTool):
"""XXX"""
toolOriginPoint = toolState = None
TS_NONE = 0
TS_ORIGIN = 1
# {{{ _pointDelta(self, a, b): XXX
def _pointDelta(self, a, b):
return [a2-a1 for a1, a2 in zip(a, b)]
# }}}
# {{{ _pointSwap(self, a, b): XXX
def _pointSwap(self, a, b):
return [b, a]
# }}}
# {{{ _getLine(self, brushColours, originPoint, targetPoint): XXX
def _getLine(self, brushColours, originPoint, targetPoint):
originPoint = originPoint.copy(); targetPoint = targetPoint.copy();
pointDelta = self._pointDelta(originPoint, targetPoint)
lineXSign = 1 if pointDelta[0] > 0 else -1;
lineYSign = 1 if pointDelta[1] > 0 else -1;
pointDelta = [abs(a) for a in pointDelta]
if pointDelta[0] > pointDelta[1]:
lineXX, lineXY, lineYX, lineYY = lineXSign, 0, 0, lineYSign
else:
pointDelta = [pointDelta[1], pointDelta[0]]
lineXX, lineXY, lineYX, lineYY = 0, lineYSign, lineXSign, 0
lineD = 2 * pointDelta[1] - pointDelta[0]; lineY = 0;
linePatches = []
for lineX in range(pointDelta[0] + 1):
linePatches.append([[ \
originPoint[0] + lineX*lineXX + lineY*lineYX, \
originPoint[1] + lineX*lineXY + lineY*lineYY], \
brushColours, 0, " "])
if lineD > 0:
lineD -= pointDelta[0]; lineY += 1;
lineD += pointDelta[1]
return linePatches
# }}}
#
# onMouseEvent(self, event, atPoint, brushColours, brushSize, isDragging, isLeftDown, isRightDown): XXX
def onMouseEvent(self, event, atPoint, brushColours, brushSize, isDragging, isLeftDown, isRightDown):
brushColours = brushColours.copy()
if isLeftDown:
brushColours[1] = brushColours[0]
elif isRightDown:
brushColours[0] = brushColours[1]
else:
brushColours[1] = brushColours[0]
brushPatches = []; tmpPatches = [];
if self.toolState == self.TS_NONE:
if isLeftDown or isRightDown:
self.toolOriginPoint = list(atPoint)
self.toolState = self.TS_ORIGIN
tmpPatches.append([atPoint, brushColours, 0, " "])
return [[True, tmpPatches]]
elif self.toolState == self.TS_ORIGIN:
targetPoint = list(atPoint)
originPoint = self.toolOriginPoint
brushPatches = self._getLine(brushColours, originPoint, targetPoint)
if isLeftDown or isRightDown:
self.toolState = self.TS_NONE
return [[False, brushPatches], [True, brushPatches]]
else:
return [[True, brushPatches]]
# __init__(self, *args): initialisation method
def __init__(self, *args):
super().__init__(*args)
self.toolOriginPoint = None
self.toolState = self.TS_NONE
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120

View File

@ -40,7 +40,9 @@ class MiRCARTToolRect(MiRCARTTool):
brushPatches = [] brushPatches = []
for brushRow in range(brushSize[1]): for brushRow in range(brushSize[1]):
for brushCol in range(brushSize[0] * 2): for brushCol in range(brushSize[0] * 2):
brushPatches.append([[brushCol, brushRow], \ brushPatches.append([[ \
atPoint[0] + brushCol, \
atPoint[1] + brushRow], \
brushColours, 0, " "]) brushColours, 0, " "])
if isLeftDown or isRightDown: if isLeftDown or isRightDown:
return [[False, brushPatches], [True, brushPatches]] return [[False, brushPatches], [True, brushPatches]]