mirror of
https://github.com/lalbornoz/roar.git
synced 2024-12-22 20:36:37 +00:00
Various bugfixes & usability improvements.
1) Assets window: adds clear list context menu item. 2) Assets window: allow deleting multiple selected items. 3) Assets window: fix list view cursor key navigation. 4) Backend: correctly blend transparent background cursor cells with canvas character cells. 5) Backend: correctly determine cell size & set font size. 6) Backend: correctly unmask cursor. 7) Backend: disable font anti-aliasing on Windows. 8) Backend: render transparent background cells as RGBA #303030FF. 9) Canvas window: adds <F1> accelerator for `View melp?' menu item. 10) Canvas window: implement {dockable,floating} toolbars w/ wx' AUI framework. 11) Canvas window: separate tools toolbar from edit commands toolbar & dock both on right-hand side alongside each other. 12) Flip horizontally tool: flip characters, including some Unicode symbols. 13) Flip vertically tool: flip additional Unicode symbols. 14) Text tool: don't process keyboard events w/ either of <{Alt,AltGr,Ctrl}> modifiers. assets/images/roar.png: updated.
This commit is contained in:
parent
c279086c57
commit
d5935dfbba
Binary file not shown.
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
@ -19,10 +19,10 @@
|
||||
|
||||
Release roadmap:
|
||||
1) {copy,cut,delete,insert from,paste}, edit asset in new canvas, import from {canvas,object}
|
||||
2) operators: crop, scale, shift, slice
|
||||
3) tools: unicode block elements
|
||||
4) floating/dockable toolbar https://wxpython.org/Phoenix/docs/html/wx.aui.AuiManager.html
|
||||
5) reimplement cursor unmasking w/ simple list of points
|
||||
6) auto{load,save} & {backup,restore}
|
||||
2) reimplement cursor unmasking w/ simple list of points
|
||||
3) operators: crop, scale, shift, slice
|
||||
4) auto{load,save} & {backup,restore}
|
||||
5) tools: unicode block elements
|
||||
6) bugs: a) undock all toolbars & resize window b) increase cell size, scroll down
|
||||
|
||||
vim:ff=dos tw=0
|
||||
|
@ -12,6 +12,7 @@ Global hotkeys:
|
||||
<Ctrl> S Save canvas as mIRC art file
|
||||
<Ctrl> X Exit
|
||||
<Ctrl> Y, Z Redo, undo last action
|
||||
<F1> View melp?
|
||||
<Shift> <Pause> Break into Python debugger
|
||||
|
||||
Canvas hotkeys:
|
||||
|
@ -83,7 +83,7 @@ class GuiCanvasWxBackend():
|
||||
|
||||
def _initBrushesAndPens(self):
|
||||
self._brushes, self._brushesBlend, self._lastBrush, self._lastPen, self._pens, self._pensBlend = [], {}, None, None, [], {}
|
||||
self._brushAlpha, self._penAlpha = wx.Brush(wx.Colour(Colours[14][:4]), wx.BRUSHSTYLE_SOLID), wx.Pen(wx.Colour(Colours[14][:4]), 1)
|
||||
self._brushAlpha, self._penAlpha = wx.Brush(wx.Colour(48, 48, 48, 255), wx.BRUSHSTYLE_SOLID), wx.Pen(wx.Colour(48, 48, 48, 255), 1)
|
||||
for mircColour in range(len(Colours)):
|
||||
self._brushes += [wx.Brush(wx.Colour(Colours[mircColour][:4]), wx.BRUSHSTYLE_SOLID)]; self._brushesBlend[mircColour] = {};
|
||||
self._pens += [wx.Pen(wx.Colour(Colours[mircColour][:4]), 1)]; self._pensBlend[mircColour] = {};
|
||||
@ -148,7 +148,7 @@ class GuiCanvasWxBackend():
|
||||
|
||||
def drawCursorMaskWithJournal(self, canvas, canvasJournal, eventDc):
|
||||
eventDcOrigin = eventDc.GetDeviceOrigin(); eventDc.SetDeviceOrigin(0, 0);
|
||||
self.drawPatches(canvas, eventDc, canvasJournal.popCursor(), True)
|
||||
self.drawPatches(canvas, eventDc, canvasJournal.popCursor(), False)
|
||||
eventDc.SetDeviceOrigin(*eventDcOrigin)
|
||||
|
||||
def drawPatches(self, canvas, eventDc, patches, isCursor=False):
|
||||
@ -164,14 +164,12 @@ class GuiCanvasWxBackend():
|
||||
for patchRender in patchesRender:
|
||||
absPoint, charFlag = [a * b for a, b in zip(self.cellSize, patchRender[:2])], False
|
||||
if (patchRender[5] == " ") and (patchRender[3] == -1):
|
||||
charFlag, patchRender = True, [*patchRender[:-1], "░"]
|
||||
textBg, textFg = wx.Colour(Colours[patchRender[3]][:4]), wx.Colour(Colours[patchRender[2]][:4])
|
||||
if isCursor and (patchRender[5] == " ") and ((canvas.map[patchRender[1]][patchRender[0]][3] != " ") or (canvas.map[patchRender[1]][patchRender[0]][2] & self._CellState.CS_UNDERLINE)):
|
||||
charFlag, patchRender, textFg = True, [*patchRender[:-1], "░"], wx.Colour(0, 0, 0, 255)
|
||||
elif isCursor and (patchRender[5] == " ") and ((canvas.map[patchRender[1]][patchRender[0]][3] != " ") or (canvas.map[patchRender[1]][patchRender[0]][2] & self._CellState.CS_UNDERLINE)):
|
||||
charFlag, patchRender = True, [*patchRender[:-2], *canvas.map[patchRender[1]][patchRender[0]][2:]]
|
||||
textFg = wx.Colour(self._blendColours(canvas.map[patchRender[1]][patchRender[0]][0], patchRender[2]))
|
||||
textFg = wx.Colour(self._blendColours(canvas.map[patchRender[1]][patchRender[0]][0], patchRender[3]))
|
||||
elif (patchRender[5] != " ") or (patchRender[4] & self._CellState.CS_UNDERLINE):
|
||||
charFlag = True
|
||||
textBg, textFg = wx.Colour(Colours[patchRender[3]][:4]), wx.Colour(Colours[patchRender[2]][:4])
|
||||
charFlag, textFg = True, wx.Colour(Colours[patchRender[2]][:4])
|
||||
brush, pen = self._setBrushColours(eventDc, isCursor, patchRender[2:], canvas.map[patchRender[1]][patchRender[0]])
|
||||
eventDc.DrawRectangle(*absPoint, *self.cellSize)
|
||||
if charFlag:
|
||||
@ -208,8 +206,17 @@ class GuiCanvasWxBackend():
|
||||
else:
|
||||
eventDc = GuiBufferedDC(self, self.canvasBitmap, clientSize, wx.PaintDC(panelWindow), viewRect)
|
||||
|
||||
def resize(self, canvasSize, cellSize):
|
||||
winSize = [a * b for a, b in zip(canvasSize, cellSize)]
|
||||
def resize(self, canvasSize):
|
||||
if platform.system() == "Windows":
|
||||
self._font = wx.TheFontList.FindOrCreateFont(self.fontSize, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, self.fontName)
|
||||
fontInfoDesc = self._font.GetNativeFontInfoDesc().split(";"); fontInfoDesc[12] = "3";
|
||||
self._font.SetNativeFontInfo(";".join(fontInfoDesc))
|
||||
dc = wx.MemoryDC()
|
||||
dc.SetFont(self._font); self.cellSize = dc.GetTextExtent("_");
|
||||
dc.Destroy()
|
||||
else:
|
||||
self._font = wx.Font(self.cellSize[0] + 1, wx.FONTFAMILY_TELETYPE, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
|
||||
winSize = [a * b for a, b in zip(canvasSize, self.cellSize)]
|
||||
if self.canvasBitmap == None:
|
||||
self.canvasBitmap = wx.Bitmap(winSize)
|
||||
else:
|
||||
@ -218,11 +225,7 @@ class GuiCanvasWxBackend():
|
||||
newDc.Blit(0, 0, *self.canvasBitmap.GetSize(), oldDc, 0, 0)
|
||||
oldDc.SelectObject(wx.NullBitmap)
|
||||
self.canvasBitmap.Destroy(); self.canvasBitmap = newBitmap;
|
||||
self.canvasSize, self.cellSize = canvasSize, cellSize
|
||||
if platform.system() == "Windows":
|
||||
self._font = wx.TheFontList.FindOrCreateFont(cellSize[0] + 1, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, self.fontName)
|
||||
else:
|
||||
self._font = wx.Font(cellSize[0] + 1, wx.FONTFAMILY_TELETYPE, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
|
||||
self.canvasSize = canvasSize
|
||||
|
||||
def xlateEventPoint(self, event, eventDc, viewRect):
|
||||
eventPoint = event.GetLogicalPosition(eventDc)
|
||||
@ -235,11 +238,11 @@ class GuiCanvasWxBackend():
|
||||
self.canvasBitmap.Destroy(); self.canvasBitmap = None;
|
||||
self._finiBrushesAndPens()
|
||||
|
||||
def __init__(self, canvasSize, cellSize, fontName="Dejavu Sans Mono", fontPathName=os.path.join("assets", "fonts", "DejaVuSansMono.ttf")):
|
||||
def __init__(self, canvasSize, fontName="Dejavu Sans Mono", fontPathName=os.path.join("assets", "fonts", "DejaVuSansMono.ttf"), fontSize=8):
|
||||
self._brushes, self._font, self._lastBrush, self._lastPen, self._pens = None, None, None, None, None
|
||||
self.canvasBitmap, self.cellSize, self.fontName, self.fontPathName = None, None, fontName, fontPathName
|
||||
self.canvasBitmap, self.cellSize, self.fontName, self.fontPathName, self.fontSize = None, None, fontName, fontPathName, fontSize
|
||||
if platform.system() == "Windows":
|
||||
WinDLL("gdi32.dll").AddFontResourceW(self.fontPathName.encode("utf16"))
|
||||
self._initBrushesAndPens(); self.resize(canvasSize, cellSize);
|
||||
self._initBrushesAndPens(); self.resize(canvasSize);
|
||||
|
||||
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120
|
||||
|
@ -146,7 +146,7 @@ class GuiFrame(wx.Frame):
|
||||
|
||||
def loadToolBars(self, toolBars):
|
||||
for toolBar in toolBars:
|
||||
self.toolBars.append(wx.lib.agw.aui.AuiToolBar(self.panelSkin, -1))
|
||||
self.toolBars.append(wx.lib.agw.aui.AuiToolBar(self, -1))
|
||||
self.toolBars[-1].SetArtProvider(GuiToolBarArtProvider())
|
||||
self.toolBars[-1].SetToolBitmapSize((16, 16))
|
||||
for toolBarItem in toolBar:
|
||||
@ -170,13 +170,16 @@ class GuiFrame(wx.Frame):
|
||||
else:
|
||||
self.toolBars[-1].EnableTool(toolBarItem.attrDict["id"], toolBarItem.attrDict["initialState"])
|
||||
self.toolBars[-1].Refresh()
|
||||
self.toolBarPanes, row = [], 0
|
||||
for toolBar in self.toolBars:
|
||||
self.sizerSkin.Add(toolBar, 0, wx.ALIGN_LEFT | wx.ALL, 3)
|
||||
toolBar.Realize(); toolBar.Fit();
|
||||
self.toolBarPanes += [wx.lib.agw.aui.AuiPaneInfo().ToolbarPane().CaptionVisible(False).CloseButton(False).Dockable(True).Floatable(True).Gripper(True).Row(row).Top()]
|
||||
self.auiManager.AddPane(toolBar, self.toolBarPanes[-1]); row += 1;
|
||||
self.auiManager.Update()
|
||||
|
||||
def addWindow(self, window, border=14, expand=False):
|
||||
flags = wx.ALL; flags = flags | wx.EXPAND if expand else flags;
|
||||
self.sizerSkin.Add(window, 0, flags, border); self.sizerSkin.Fit(self.panelSkin);
|
||||
def addWindow(self, window):
|
||||
self.auiManager.AddPane(window, wx.lib.agw.aui.AuiPaneInfo().CaptionVisible(False).Centre().CloseButton(False).Dockable(False).Floatable(False).Gripper(False))
|
||||
self.auiManager.Update()
|
||||
|
||||
def onChar(self, event):
|
||||
event.Skip()
|
||||
@ -193,11 +196,10 @@ class GuiFrame(wx.Frame):
|
||||
|
||||
def __init__(self, iconPathName, size, parent=None, title=""):
|
||||
super().__init__(parent, wx.ID_ANY, title, size=size)
|
||||
self.itemsById, self.menuItemsById, self.toolBarItemsById = {}, {}, {}
|
||||
self.panelSkin, self.sizerSkin, self.toolBars = wx.Panel(self, wx.ID_ANY), wx.BoxSizer(wx.VERTICAL), []
|
||||
self.sizerSkin.AddSpacer(5); self.panelSkin.SetSizer(self.sizerSkin); self.panelSkin.SetAutoLayout(1);
|
||||
self.auiManager = wx.lib.agw.aui.AuiManager(); self.auiManager.SetManagedWindow(self);
|
||||
self.itemsById, self.menuItemsById, self.toolBarItemsById, self.toolBars = {}, {}, {}, []
|
||||
self._initIcon(iconPathName); self.statusBar = self.CreateStatusBar();
|
||||
self.sizerSkin.Fit(self.panelSkin); self.SetFocus(); self.Show(True);
|
||||
self.SetFocus(); self.Show(True);
|
||||
for event, f in ((wx.EVT_CHAR, self.onChar), (wx.EVT_MENU, self.onMenu), (wx.EVT_MOUSEWHEEL, self.onMouseWheel)):
|
||||
self.Bind(event, f)
|
||||
|
||||
|
@ -8,8 +8,8 @@ import wx
|
||||
|
||||
class GuiWindow(wx.ScrolledWindow):
|
||||
def _updateScrollBars(self):
|
||||
if self.size != None:
|
||||
clientSize = self.GetClientSize()
|
||||
if (self.scrollStep != None) and (self.size != None):
|
||||
self.SetScrollRate(*self.scrollStep); clientSize = self.GetClientSize();
|
||||
if (self.size[0] > clientSize[0]) or (self.size[1] > clientSize[1]):
|
||||
self.scrollFlag = True; super().SetVirtualSize(self.size);
|
||||
elif self.scrollFlag \
|
||||
@ -48,16 +48,16 @@ class GuiWindow(wx.ScrolledWindow):
|
||||
while curWindow != None:
|
||||
curWindow.Layout(); curWindow = curWindow.GetParent();
|
||||
|
||||
def __init__(self, parent, pos, scrollStep, style=0):
|
||||
def __init__(self, parent, pos, style=0):
|
||||
super().__init__(parent, pos=pos, style=style) if style != 0 else super().__init__(parent, pos=pos)
|
||||
self.parent = parent
|
||||
self.pos, self.scrollFlag, self.scrollStep, self.size = pos, False, scrollStep, None
|
||||
self.pos, self.scrollFlag, self.scrollStep, self.size = pos, False, None, None
|
||||
for eventType, f in (
|
||||
(wx.EVT_CHAR, self.onKeyboardInput), (wx.EVT_CLOSE, self.onClose), (wx.EVT_ENTER_WINDOW, self.onEnterWindow),
|
||||
(wx.EVT_LEAVE_WINDOW, self.onLeaveWindow), (wx.EVT_LEFT_DOWN, self.onMouseInput), (wx.EVT_MOTION, self.onMouseInput),
|
||||
(wx.EVT_PAINT, self.onPaint), (wx.EVT_RIGHT_DOWN, self.onMouseInput), (wx.EVT_SCROLLWIN_LINEDOWN, self.onScroll),
|
||||
(wx.EVT_SCROLLWIN_LINEUP, self.onScroll), (wx.EVT_SIZE, self.onSize)):
|
||||
self.Bind(eventType, f)
|
||||
self.SetScrollRate(*self.scrollStep); self._updateScrollBars();
|
||||
self._updateScrollBars()
|
||||
|
||||
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120
|
||||
|
@ -6,13 +6,26 @@
|
||||
|
||||
from Operator import Operator
|
||||
|
||||
# TODO <https://en.wikipedia.org/wiki/Box_Drawing_(Unicode_block)>
|
||||
|
||||
class OperatorFlipHorizontal(Operator):
|
||||
name = "Flip horizontally"
|
||||
flipPairs = {
|
||||
"/":"\\", "╱":"╲",
|
||||
"▀":"▄", "▁":"▔", "▖":"▘", "▗":"▝",
|
||||
"▙":"▛", "▚":"▞", "▜":"▟",
|
||||
}
|
||||
|
||||
def apply(self, region):
|
||||
region.reverse(); return region;
|
||||
region.reverse()
|
||||
for numRow in range(len(region)):
|
||||
for numCol in range(len(region[numRow])):
|
||||
if region[numRow][numCol][3] in self.flipPairs:
|
||||
region[numRow][numCol][3] = self.flipPairs[region[numRow][numCol][3]]
|
||||
return region
|
||||
|
||||
def __init__(self, *args):
|
||||
pass
|
||||
for flipPairKey in list(self.flipPairs.keys()):
|
||||
self.flipPairs[self.flipPairs[flipPairKey]] = flipPairKey
|
||||
|
||||
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120
|
||||
|
@ -6,15 +6,15 @@
|
||||
|
||||
from Operator import Operator
|
||||
|
||||
# TODO <https://en.wikipedia.org/wiki/Box_Drawing_(Unicode_block)>
|
||||
|
||||
class OperatorFlipVertical(Operator):
|
||||
name = "Flip"
|
||||
flipPairs = {
|
||||
"(":")", ")":"(",
|
||||
"/":"\\", "\\":"/",
|
||||
"\[":"]", "]":"\[",
|
||||
"\{":"\}", "\}":"\{",
|
||||
"<":">", ">":"<",
|
||||
"`":"'",
|
||||
"(":")", "/":"\\", "╱":"╲", "[":"]", "{":"}", "<":">", "`":"'",
|
||||
"▌":"▐", "▏":"▕",
|
||||
"▖":"▗", "▘":"▝",
|
||||
"▟":"▙", "▛":"▜", "▚":"▞",
|
||||
}
|
||||
|
||||
def apply(self, region):
|
||||
@ -26,6 +26,7 @@ class OperatorFlipVertical(Operator):
|
||||
return region
|
||||
|
||||
def __init__(self, *args):
|
||||
pass
|
||||
for flipPairKey in list(self.flipPairs.keys()):
|
||||
self.flipPairs[self.flipPairs[flipPairKey]] = flipPairKey
|
||||
|
||||
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120
|
||||
|
@ -86,6 +86,28 @@ class RoarAssetsWindow(GuiMiniFrame):
|
||||
with open(localConfFileName, "r", encoding="utf-8") as inFile:
|
||||
self.lastDir = inFile.read().rstrip("\r\n")
|
||||
|
||||
def _removeAsset(self, idx):
|
||||
del self.canvasList[idx]; self.listView.DeleteItem(idx);
|
||||
itemCount = self.listView.GetItemCount()
|
||||
if itemCount > 0:
|
||||
self.listView.Select(self.currentIndex, on=0)
|
||||
for numCanvas in [n for n in sorted(self.canvasList.keys()) if n >= idx]:
|
||||
self.canvasList[numCanvas - 1] = self.canvasList[numCanvas]; del self.canvasList[numCanvas];
|
||||
[self.listView.SetColumnWidth(col, wx.LIST_AUTOSIZE) for col in (0, 1)]
|
||||
if (idx == 0) or (idx >= itemCount):
|
||||
idx = 0 if itemCount > 0 else None
|
||||
else:
|
||||
idx = idx if idx < itemCount else None
|
||||
self.currentIndex = idx
|
||||
if self.currentIndex != None:
|
||||
self.listView.Select(self.currentIndex, on=1)
|
||||
self.drawCanvas(self.canvasList[self.currentIndex][0])
|
||||
else:
|
||||
self.currentIndex = None
|
||||
[self.listView.SetColumnWidth(col, wx.LIST_AUTOSIZE_USEHEADER) for col in (0, 1)]
|
||||
self.drawCanvas(Canvas((0, 0)))
|
||||
return self.currentIndex
|
||||
|
||||
def _storeLastDir(self, pathName):
|
||||
localConfFileName = getLocalConfPathName("RecentAssetsDir.txt")
|
||||
with open(localConfFileName, "w", encoding="utf-8") as outFile:
|
||||
@ -106,12 +128,12 @@ class RoarAssetsWindow(GuiMiniFrame):
|
||||
self.scrollFlag = False; super(wx.ScrolledWindow, self.panelCanvas).SetVirtualSize((0, 0));
|
||||
|
||||
def drawCanvas(self, canvas):
|
||||
panelSize = [a * b for a, b in zip(canvas.size, self.cellSize)]
|
||||
panelSize = [a * b for a, b in zip(canvas.size, self.backend.cellSize)]
|
||||
self.panelCanvas.SetMinSize(panelSize); self.panelCanvas.SetSize(wx.DefaultCoord, wx.DefaultCoord, *panelSize);
|
||||
curWindow = self.panelCanvas
|
||||
while curWindow != None:
|
||||
curWindow.Layout(); curWindow = curWindow.GetParent();
|
||||
self.backend.resize(canvas.size, self.cellSize)
|
||||
self.backend.resize(canvas.size)
|
||||
eventDc = self.backend.getDeviceContext(self.panelCanvas.GetClientSize(), self.panelCanvas)
|
||||
eventDcOrigin = eventDc.GetDeviceOrigin(); eventDc.SetDeviceOrigin(0, 0);
|
||||
patches = []
|
||||
@ -144,12 +166,12 @@ class RoarAssetsWindow(GuiMiniFrame):
|
||||
oldSize = [0, 0] if canvas.map == None else canvas.size
|
||||
deltaSize = [b - a for a, b in zip(oldSize, newSize)]
|
||||
if canvas.resize(newSize, False):
|
||||
panelSize = [a * b for a, b in zip(canvas.size, self.cellSize)]
|
||||
panelSize = [a * b for a, b in zip(canvas.size, self.backend.cellSize)]
|
||||
self.panelCanvas.SetMinSize(panelSize); self.panelCanvas.SetSize(wx.DefaultCoord, wx.DefaultCoord, *panelSize);
|
||||
curWindow = self.panelCanvas
|
||||
while curWindow != None:
|
||||
curWindow.Layout(); curWindow = curWindow.GetParent();
|
||||
self.backend.resize(newSize, self.cellSize)
|
||||
self.backend.resize(newSize)
|
||||
eventDc = self.backend.getDeviceContext(self.panelCanvas.GetClientSize(), self.panelCanvas)
|
||||
eventDcOrigin = eventDc.GetDeviceOrigin(); eventDc.SetDeviceOrigin(0, 0);
|
||||
patches = []
|
||||
@ -193,14 +215,27 @@ class RoarAssetsWindow(GuiMiniFrame):
|
||||
else:
|
||||
event.Skip()
|
||||
|
||||
def onClearList(self, event):
|
||||
while len(self.canvasList):
|
||||
self._removeAsset(list(self.canvasList.keys())[0])
|
||||
|
||||
def onListViewChar(self, event):
|
||||
index, rc = self.listView.GetFirstSelected(), False
|
||||
if index != -1:
|
||||
keyChar, keyModifiers = event.GetKeyCode(), event.GetModifiers()
|
||||
if (keyChar, keyModifiers) == (wx.WXK_DELETE, wx.MOD_NONE):
|
||||
self.currentIndex, rc = index, True; self.onRemove(None);
|
||||
if not rc:
|
||||
event.Skip()
|
||||
keyCode = event.GetKeyCode()
|
||||
if (event.GetModifiers() == wx.MOD_NONE) \
|
||||
and (keyCode in (wx.WXK_DOWN, wx.WXK_UP)) \
|
||||
and (self.currentIndex != None):
|
||||
self.listView.Select(self.currentIndex, on=0)
|
||||
id = +1 if keyCode == wx.WXK_DOWN else -1
|
||||
self.currentIndex = (self.currentIndex + id) % len(self.canvasList)
|
||||
self.listView.Select(self.currentIndex, on=1)
|
||||
else:
|
||||
index, rc = self.listView.GetFirstSelected(), False
|
||||
if index != -1:
|
||||
keyChar, keyModifiers = event.GetKeyCode(), event.GetModifiers()
|
||||
if (keyChar, keyModifiers) == (wx.WXK_DELETE, wx.MOD_NONE):
|
||||
self.currentIndex, rc = index, True; self.onRemove(None);
|
||||
if not rc:
|
||||
event.Skip()
|
||||
|
||||
def onListViewItemSelected(self, event):
|
||||
self.currentIndex = event.GetItem().GetId()
|
||||
@ -217,6 +252,10 @@ class RoarAssetsWindow(GuiMiniFrame):
|
||||
self.contextMenuItems[4].Enable(False)
|
||||
else:
|
||||
self.contextMenuItems[4].Enable(True)
|
||||
if len(self.canvasList) == 0:
|
||||
self.contextMenuItems[7].Enable(False)
|
||||
else:
|
||||
self.contextMenuItems[7].Enable(True)
|
||||
self.PopupMenu(self.contextMenu, eventPoint)
|
||||
|
||||
def onLoad(self, event):
|
||||
@ -256,23 +295,15 @@ class RoarAssetsWindow(GuiMiniFrame):
|
||||
self._load_list(pathName)
|
||||
|
||||
def onRemove(self, event):
|
||||
del self.canvasList[self.currentIndex]; self.listView.DeleteItem(self.currentIndex);
|
||||
itemCount = self.listView.GetItemCount()
|
||||
if itemCount > 0:
|
||||
for numCanvas in [n for n in sorted(self.canvasList.keys()) if n >= self.currentIndex]:
|
||||
self.canvasList[numCanvas - 1] = self.canvasList[numCanvas]; del self.canvasList[numCanvas];
|
||||
[self.listView.SetColumnWidth(col, wx.LIST_AUTOSIZE) for col in (0, 1)]
|
||||
if (self.currentIndex == 0) or (self.currentIndex >= itemCount):
|
||||
self.currentIndex = 0 if itemCount > 0 else None
|
||||
items = [self.listView.GetFirstSelected()]
|
||||
while True:
|
||||
item = self.listView.GetNextSelected(items[-1])
|
||||
if item != -1:
|
||||
items += [item]
|
||||
else:
|
||||
self.currentIndex = self.currentIndex if self.currentIndex < itemCount else None
|
||||
if self.currentIndex != None:
|
||||
self.listView.Select(self.currentIndex, on=1)
|
||||
self.drawCanvas(self.canvasList[self.currentIndex][0])
|
||||
else:
|
||||
self.currentIndex = None
|
||||
[self.listView.SetColumnWidth(col, wx.LIST_AUTOSIZE_USEHEADER) for col in (0, 1)]
|
||||
self.drawCanvas(Canvas((0, 0)))
|
||||
break
|
||||
while len(items):
|
||||
self._removeAsset(items[0]); del items[0]; items = [i - 1 for i in items];
|
||||
|
||||
def onSaveList(self, event):
|
||||
rc = True
|
||||
@ -293,12 +324,12 @@ class RoarAssetsWindow(GuiMiniFrame):
|
||||
with wx.MessageDialog(self, "Error: {}".format(error), "", wx.OK | wx.OK_DEFAULT) as dialog:
|
||||
dialogChoice = dialog.ShowModal()
|
||||
|
||||
def __init__(self, backend, cellSize, parent, pos=None, size=(400, 400), title="Assets"):
|
||||
def __init__(self, backend, parent, pos=None, size=(400, 400), title="Assets"):
|
||||
if pos == None:
|
||||
parentRect = parent.GetScreenRect(); pos = (parentRect.x + parentRect.width, parentRect.y);
|
||||
super().__init__(parent, size, title, pos=pos)
|
||||
self.backend, self.canvasList, self.lastDir = backend((0, 0), cellSize), {}, None
|
||||
self.cellSize, self.currentIndex, self.leftDown, self.parent, self.scrollFlag = cellSize, None, False, parent, False
|
||||
self.backend, self.canvasList, self.lastDir = backend((0, 0)), {}, None
|
||||
self.currentIndex, self.leftDown, self.parent, self.scrollFlag = None, False, parent, False
|
||||
self.Bind(wx.EVT_CHAR, self.onChar)
|
||||
self._loadLastDir()
|
||||
|
||||
@ -311,7 +342,9 @@ class RoarAssetsWindow(GuiMiniFrame):
|
||||
("&Remove", self.onRemove),
|
||||
(None, None),
|
||||
("Load from l&ist...", self.onLoadList),
|
||||
("Sa&ve as list...", self.onSaveList),):
|
||||
("Sa&ve as list...", self.onSaveList),
|
||||
(None, None),
|
||||
("Cl&ear list", self.onClearList),):
|
||||
if (text, f) == (None, None):
|
||||
self.contextMenu.AppendSeparator()
|
||||
else:
|
||||
@ -325,7 +358,8 @@ class RoarAssetsWindow(GuiMiniFrame):
|
||||
self.listView.Bind(wx.EVT_LIST_ITEM_SELECTED, self.onListViewItemSelected)
|
||||
self.listView.Bind(wx.EVT_RIGHT_DOWN, self.onListViewRightDown)
|
||||
|
||||
self.panelCanvas = GuiWindow(self, (0, 0), cellSize, wx.BORDER_SUNKEN)
|
||||
self.panelCanvas = GuiWindow(self, (0, 0), wx.BORDER_SUNKEN)
|
||||
self.panelCanvas.Bind(wx.EVT_CHAR, self.onChar)
|
||||
self.panelCanvas.Bind(wx.EVT_LEFT_DOWN, self.onPanelLeftDown)
|
||||
self.panelCanvas.Bind(wx.EVT_PAINT, self.onPanelPaint)
|
||||
self.panelCanvas.Bind(wx.EVT_SIZE, self.onPanelSize)
|
||||
|
@ -123,7 +123,9 @@ class RoarCanvasCommands(RoarCanvasCommandsFile, RoarCanvasCommandsEdit, RoarCan
|
||||
self.canvasUndo, self.canvasRedo, NID_TOOLBAR_HSEP,
|
||||
self.canvasCut, self.canvasCopy, self.canvasPaste, self.canvasDelete, NID_TOOLBAR_HSEP,
|
||||
self.canvasAssetsWindowHide, self.canvasAssetsWindowShow, NID_TOOLBAR_HSEP,
|
||||
self.canvasTool(self.canvasTool, 1), self.canvasTool(self.canvasTool, 7), self.canvasTool(self.canvasTool, 0), self.canvasTool(self.canvasTool, 3), self.canvasTool(self.canvasTool, 4), self.canvasTool(self.canvasTool, 8), self.canvasTool(self.canvasTool, 5), self.canvasTool(self.canvasTool, 2), self.canvasTool(self.canvasTool, 6),
|
||||
])
|
||||
toolBars.append(
|
||||
[self.canvasTool(self.canvasTool, 1), self.canvasTool(self.canvasTool, 7), self.canvasTool(self.canvasTool, 0), self.canvasTool(self.canvasTool, 3), self.canvasTool(self.canvasTool, 4), self.canvasTool(self.canvasTool, 8), self.canvasTool(self.canvasTool, 5), self.canvasTool(self.canvasTool, 2), self.canvasTool(self.canvasTool, 6),
|
||||
])
|
||||
toolBars.append(
|
||||
[self.canvasColour(self.canvasColour, 0), self.canvasColour(self.canvasColour, 1), self.canvasColour(self.canvasColour, 2), self.canvasColour(self.canvasColour, 3),
|
||||
|
@ -7,14 +7,14 @@
|
||||
from GuiFrame import GuiCommandDecorator, NID_MENU_SEP
|
||||
from RoarWindowAbout import RoarWindowAbout
|
||||
from RoarWindowMelp import RoarWindowMelp
|
||||
import webbrowser
|
||||
import webbrowser, wx
|
||||
|
||||
class RoarCanvasCommandsHelp():
|
||||
@GuiCommandDecorator("About roar", "&About roar", None, None, True)
|
||||
def canvasAbout(self, event):
|
||||
RoarWindowAbout(self.parentFrame)
|
||||
|
||||
@GuiCommandDecorator("View melp?", "View &melp?", None, None, True)
|
||||
@GuiCommandDecorator("View melp?", "View &melp?", None, [wx.MOD_NONE, wx.WXK_F1], True)
|
||||
def canvasMelp(self, event):
|
||||
RoarWindowMelp(self.parentFrame)
|
||||
|
||||
|
@ -212,12 +212,12 @@ class RoarCanvasWindow(GuiWindow):
|
||||
|
||||
def onMouseWheel(self, event):
|
||||
if event.GetModifiers() == wx.MOD_CONTROL:
|
||||
cd = +1 if event.GetWheelRotation() >= event.GetWheelDelta() else -1
|
||||
newCellSize = [cs + cd for cs in self.backend.cellSize]
|
||||
if (newCellSize[0] > 0) and (newCellSize[1] > 0):
|
||||
self.backend.cellSize = newCellSize
|
||||
fd = +1 if event.GetWheelRotation() >= event.GetWheelDelta() else -1
|
||||
newFontSize = self.backend.fontSize + fd
|
||||
if newFontSize > 0:
|
||||
self.backend.fontSize = newFontSize
|
||||
self.backend.resize(self.canvas.size)
|
||||
super().resize([a * b for a, b in zip(self.canvas.size, self.backend.cellSize)])
|
||||
self.backend.resize(self.canvas.size, self.backend.cellSize)
|
||||
eventDc = self.backend.getDeviceContext(self.GetClientSize(), self)
|
||||
eventDcOrigin = eventDc.GetDeviceOrigin(); eventDc.SetDeviceOrigin(0, 0);
|
||||
patches = []
|
||||
@ -239,8 +239,8 @@ class RoarCanvasWindow(GuiWindow):
|
||||
oldSize = [0, 0] if self.canvas.map == None else self.canvas.size
|
||||
deltaSize = [b - a for a, b in zip(oldSize, newSize)]
|
||||
if self.canvas.resize(newSize, commitUndo):
|
||||
self.backend.resize(newSize); self.scrollStep = self.backend.cellSize;
|
||||
super().resize([a * b for a, b in zip(newSize, self.backend.cellSize)])
|
||||
self.backend.resize(newSize, self.backend.cellSize)
|
||||
eventDc = self.backend.getDeviceContext(self.GetClientSize(), self)
|
||||
eventDcOrigin = eventDc.GetDeviceOrigin(); eventDc.SetDeviceOrigin(0, 0);
|
||||
patches = []
|
||||
@ -268,10 +268,10 @@ class RoarCanvasWindow(GuiWindow):
|
||||
self.backend.drawPatches(self.canvas, eventDc, patches, isCursor=False)
|
||||
eventDc.SetDeviceOrigin(*eventDcOrigin)
|
||||
|
||||
def __init__(self, backend, canvas, cellSize, commands, parent, parentFrame, pos, scrollStep, size):
|
||||
super().__init__(parent, pos, scrollStep)
|
||||
def __init__(self, backend, canvas, commands, parent, pos, size):
|
||||
super().__init__(parent, pos)
|
||||
self.size = size
|
||||
self.backend, self.canvas, self.cellSize, self.commands, self.parentFrame = backend(self.size, cellSize), canvas, cellSize, commands(self, parentFrame), parentFrame
|
||||
self.backend, self.canvas, self.commands, self.parentFrame = backend(self.size), canvas, commands(self, parent), parent
|
||||
self.brushColours, self.brushPos, self.brushSize, self.dirty, self.lastCellState = [4, 1], [0, 0], [1, 1], False, None
|
||||
self.popupEventDc = None
|
||||
self.dropTarget = RoarCanvasWindowDropTarget(self)
|
||||
|
@ -39,13 +39,10 @@ class RoarClient(GuiFrame):
|
||||
if closeFlag:
|
||||
event.Skip();
|
||||
|
||||
def onSize(self, event):
|
||||
self.canvasPanel.SetMinSize(self.GetSize()); self.canvasPanel.SetSize(wx.DefaultCoord, wx.DefaultCoord, *self.GetSize()); event.Skip();
|
||||
|
||||
def __init__(self, parent, defaultCanvasPos=(0, 75), defaultCanvasSize=(100, 30), defaultCellSize=(7, 14), size=(840, 640), title=""):
|
||||
def __init__(self, parent, defaultCanvasPos=(0, 75), defaultCanvasSize=(100, 30), size=(840, 640), title=""):
|
||||
super().__init__(self._getIconPathName(), size, parent, title)
|
||||
self.canvas = Canvas(defaultCanvasSize)
|
||||
self.canvasPanel = RoarCanvasWindow(GuiCanvasWxBackend, self.canvas, defaultCellSize, RoarCanvasCommands, self.panelSkin, self, defaultCanvasPos, defaultCellSize, defaultCanvasSize)
|
||||
self.canvasPanel = RoarCanvasWindow(GuiCanvasWxBackend, self.canvas, RoarCanvasCommands, self, defaultCanvasPos, defaultCanvasSize)
|
||||
self.loadAccels(self.canvasPanel.commands.accels, self.canvasPanel.commands.menus, self.canvasPanel.commands.toolBars)
|
||||
self.loadMenus(self.canvasPanel.commands.menus)
|
||||
self._initToolBitmaps(self.canvasPanel.commands.toolBars)
|
||||
@ -54,8 +51,8 @@ class RoarClient(GuiFrame):
|
||||
self.canvasPanel.commands.canvasNew(None)
|
||||
self.canvasPanel.commands.canvasTool(self.canvasPanel.commands.canvasTool, 1)(None)
|
||||
self.canvasPanel.commands.update(brushSize=self.canvasPanel.brushSize, colours=self.canvasPanel.brushColours)
|
||||
self.addWindow(self.canvasPanel, expand=True)
|
||||
self.assetsWindow = RoarAssetsWindow(GuiCanvasWxBackend, defaultCellSize, self)
|
||||
self.addWindow(self.canvasPanel)
|
||||
self.assetsWindow = RoarAssetsWindow(GuiCanvasWxBackend, self)
|
||||
self.canvasPanel.commands.canvasAssetsWindowShow(None)
|
||||
|
||||
self.canvasPanel.operatorsMenu = wx.Menu()
|
||||
@ -67,6 +64,6 @@ class RoarClient(GuiFrame):
|
||||
menuItemWindow = self.canvasPanel.commands.canvasOpenRecent.attrDict["menu"].Append(self.canvasPanel.commands.canvasClearRecent.attrDict["id"], self.canvasPanel.commands.canvasClearRecent.attrDict["label"], self.canvasPanel.commands.canvasClearRecent.attrDict["caption"])
|
||||
self.canvasPanel.commands.canvasOpenRecent.attrDict["menu"].Bind(wx.EVT_MENU, self.canvasPanel.commands.canvasClearRecent, menuItemWindow)
|
||||
self.Bind(wx.EVT_CLOSE, self.onClose)
|
||||
self.Bind(wx.EVT_SIZE, self.onSize)
|
||||
self.toolBarPanes[0].BestSize(0, 0).Right(); self.toolBarPanes[1].BestSize(0, 0).Right(); self.auiManager.Update();
|
||||
|
||||
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120
|
||||
|
@ -111,7 +111,7 @@ class ToolText(Tool):
|
||||
else:
|
||||
brushPos[0], brushPos[1] = 0, 0
|
||||
rc = True; patchesCursor += [[*brushPos, *brushColours, 0, "_"]];
|
||||
else:
|
||||
elif not (keyModifiers in (wx.MOD_ALT, wx.MOD_ALTGR, wx.MOD_CONTROL)):
|
||||
rc, patches_ = self._processKeyChar(brushColours, brushPos, canvas, keyChar, keyModifiers)
|
||||
patches += patches_
|
||||
if rc:
|
||||
|
Loading…
Reference in New Issue
Block a user