From 032b6057688ddbc133f48f941ee17bfdb807b99e Mon Sep 17 00:00:00 2001 From: Eugenio Parodi Date: Mon, 13 Mar 2023 23:41:57 +0000 Subject: [PATCH] ttkdesigner, first drop of the rowspan/colspan feature --- TermTk/TTkLayouts/gridlayout.py | 4 +- ttkDesigner/app/designer.py | 2 +- ttkDesigner/app/superobj/supercontrol.py | 3 + ttkDesigner/app/superobj/superlayoutgrid.py | 150 +++++++++++++++++++- 4 files changed, 155 insertions(+), 4 deletions(-) diff --git a/TermTk/TTkLayouts/gridlayout.py b/TermTk/TTkLayouts/gridlayout.py index ba99ee68..d68c29c7 100644 --- a/TermTk/TTkLayouts/gridlayout.py +++ b/TermTk/TTkLayouts/gridlayout.py @@ -295,8 +295,8 @@ class TTkGridLayout(TTkLayout): self._reshapeGrid(self._gridUsedsize()) def itemAtPosition(self, row: int, col: int): - if row >= self._rows or \ - col >= self._cols: + if ( row<0 or row >= self._rows or + col<0 or col >= self._cols ): return None if item := self._gridItems[row][col]: return item diff --git a/ttkDesigner/app/designer.py b/ttkDesigner/app/designer.py index 36ed8870..ff174b3c 100644 --- a/ttkDesigner/app/designer.py +++ b/ttkDesigner/app/designer.py @@ -166,5 +166,5 @@ class TTkDesigner(TTkGridLayout): layout=TTkGridLayout(), flags=TTkK.WindowFlag.WindowMaximizeButtonHint|TTkK.WindowFlag.WindowCloseButtonHint) win.layout().addWidget(widget) - TTkHelper.overlay(None, win, 2, 2) + TTkHelper.overlay(None, win, 2, 2, modal=True) diff --git a/ttkDesigner/app/superobj/supercontrol.py b/ttkDesigner/app/superobj/supercontrol.py index 9eb3eed8..a1d448b4 100644 --- a/ttkDesigner/app/superobj/supercontrol.py +++ b/ttkDesigner/app/superobj/supercontrol.py @@ -47,6 +47,9 @@ class SuperControlWidget(ttk.TTkResizableFrame): self._wid.resize(w-2,h-2) self._wid._canvas.updateSize() + def mouseMoveEvent(self, evt) -> bool: + return True + def mouseReleaseEvent(self, evt) -> bool: self._draggable = False return super().mouseReleaseEvent(evt) diff --git a/ttkDesigner/app/superobj/superlayoutgrid.py b/ttkDesigner/app/superobj/superlayoutgrid.py index 8bde6e6f..70af7de8 100644 --- a/ttkDesigner/app/superobj/superlayoutgrid.py +++ b/ttkDesigner/app/superobj/superlayoutgrid.py @@ -24,11 +24,57 @@ import TermTk as ttk import ttkDesigner.app.superobj as so from .superlayout import SuperLayout +class _superExpandButton(ttk.TTkButton): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._direction = ttk.TTkK.TOP + + def setDirection(self, d): + self._direction = d + + def leaveEvent(self, evt) -> bool: + self.hide() + return super().leaveEvent(evt) + + def paintEvent(self): + canvas = self.getCanvas() + # '▶','◀','▼','▲' + w,h = self.size() + if w==1: + self.getCanvas().drawText(text='╽', pos=(0,0), color=ttk.TTkColor.fg("FFFF00")) + self.getCanvas().drawText(text='╿', pos=(0,h-1), color=ttk.TTkColor.fg("FFFF00")) + for yy in range(1,h-1): + self.getCanvas().drawText(text='┃', pos=(0, yy), color=ttk.TTkColor.fg("FFFF00")) + elif h==1: + txt = '╼'+'━'*(w-2)+'╾' + self.getCanvas().drawText(text=txt, pos=(0,0), width=w, color=ttk.TTkColor.fg("FFFF00")) + + ch = { + ttk.TTkK.TOP : '▲', + ttk.TTkK.BOTTOM : '▼', + ttk.TTkK.LEFT : '◀', + ttk.TTkK.RIGHT : '▶', + }.get(self._direction, 'X') + + x,y = 0,0 + if w==1 and h>4: + y = h//2-2 + h = 4 + elif h==1 and w>4: + x = w//2-2 + w = 4 + canvas.fill(pos=(x,y), size=(w,h), char=ch, color=ttk.TTkColor.fg("#FF0000")+ttk.TTkColor.bg("#FFFF44")) + class SuperLayoutGrid(SuperLayout): def __init__(self, *args, **kwargs): kwargs['layout'] = ttk.TTkGridLayout() super().__init__(*args, **kwargs) + self._expandButton = _superExpandButton() + self.rootLayout().addWidget(self._expandButton) + self._expandButton.hide() + self._expandButton.clicked.connect(self._clickExpand) self._dragOver = None + self._expandStuff = None self._orientation = ttk.TTkK.HORIZONTAL|ttk.TTkK.VERTICAL def dragEnterEvent(self, evt) -> bool: @@ -60,7 +106,28 @@ class SuperLayoutGrid(SuperLayout): self.layout().repack() def mouseMoveEvent(self, evt) -> bool: - return super().mouseMoveEvent(evt) + # ttk.TTkLog.debug(f"Move {evt}") + dir, wid = self._processMouseOver(evt.x, evt.y) + if not wid or not dir: + self._expandButton.hide() + return super().mouseMoveEvent(evt) + x,y,w,h = wid.geometry() + ebs = { + ttk.TTkK.TOP : (x, y, w, 1), + ttk.TTkK.BOTTOM : (x, y+h-1, w, 1), + ttk.TTkK.LEFT : (x, y, 1, h), + ttk.TTkK.RIGHT : (x+w-1, y, 1, h), + }.get(dir, None) + + if not ebs: + self._expandButton.hide() + else: + self._expandButton.setGeometry(*ebs) + self._expandButton.setDirection(dir) + self._expandButton.raiseWidget() + self._expandButton.show() + self._expandStuff = (dir,wid) + return True def addSuperWidget(self, sw): self._dragOver = None @@ -70,6 +137,87 @@ class SuperLayoutGrid(SuperLayout): self.layout().insertRow(self._pushRow) self.layout().addWidget(sw, self._pushRow, self._pushCol,1,1) + ttk.pyTTkSlot() + def _clickExpand(self): + if not self._expandButton.isVisible(): return + self._expandButton.hide() + dir, wid = self._expandStuff + row = wid._row + col = wid._col + rowspan = wid._rowspan + colspan = wid._colspan + self.layout().removeItem(wid) + if ttk.TTkK.TOP and row==0: + self.layout().insertRow(0) + row+=1 + elif ttk.TTkK.LEFT and col==0: + self.layout().insertColumn(0) + col+=1 + rc = { + ttk.TTkK.TOP : (row-1,col, rowspan+1,colspan), + ttk.TTkK.BOTTOM : (row, col, rowspan+1,colspan), + ttk.TTkK.LEFT : (row, col-1,rowspan,colspan+1), + ttk.TTkK.RIGHT : (row, col, rowspan,colspan+1), + }.get(dir, (row,col,rowspan,colspan)) + self.layout().addItem(wid,*rc) + + def _processMouseOver(self, x, y): + # cehck the closest edge + col, row, dir = 0,0,None + wid = None + + if type(self.layout()) != ttk.TTkGridLayout: + return dir,wid + + # Retrieve a list of widths,heights + rows,cols = self.layout().gridSize() + if not rows or not cols: return dir,wid + + horSizes, verSizes = self.layout().getSizes() + + # Find the row/col where the pointer is in + for col,(a,b) in enumerate(horSizes): + if a <= x < a+b: break + for row,(a,b) in enumerate(verSizes): + if a <= y < a+b: break + + ix, iw = horSizes[col] + iy, ih = verSizes[row] + + wid = self.layout().itemAtPosition(row,col) + if wid == None: + return dir,wid + + rowspan = wid._rowspan + colspan = wid._colspan + + maxw,maxh = wid.maximumSize() + + #Top + if (( y==iy ) and maxh>1 and + ( not self.layout().itemAtPosition(row-1,col) ) ): + dir = ttk.TTkK.TOP + #Bottom + elif ((iy+ih==y+1) and maxh>1 and + not self.layout().itemAtPosition(row+rowspan,col)): + dir = ttk.TTkK.BOTTOM + #Left + elif ((x==ix) and maxw>1 and + ( not self.layout().itemAtPosition(row,col-1) ) ): + dir = ttk.TTkK.LEFT + #Right + elif ((ix+iw==x+1) and maxw>1 and + not self.layout().itemAtPosition(row,col+colspan)): + dir = ttk.TTkK.RIGHT + + # ttk.TTkLog.debug(f"Move {dir} {wid}") + + # ttk.TTkLog.debug(f"{horSizes=}") + # ttk.TTkLog.debug(f"{verSizes=}") + # ttk.TTkLog.debug(f"{row=} {col=} {dir=} {self._dragOver=}") + self.update() + return dir, wid + def _processDragOver(self, x, y): # cehck the closest edge col, row, dir = 0,0,None