Skip to content

Commit

Permalink
Merge pull request #87 from ceccopierangiolieugenio/WindowFlags
Browse files Browse the repository at this point in the history
Window flags #81
  • Loading branch information
ceccopierangiolieugenio authored Dec 20, 2022
2 parents 1c5f5b8 + 1854604 commit bfe4b4a
Show file tree
Hide file tree
Showing 11 changed files with 221 additions and 66 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -97,5 +97,5 @@ test: .venv
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics --exclude .venv,build,tmp ; \
pytest tests/pytest/test_003_string.py ; \
pytest tests/pytest/test_002_textedit.py ; \
pytest tests/pytest/test_001_demo.py ;
pytest -v tests/pytest/test_001_demo.py ;

25 changes: 10 additions & 15 deletions TermTk/TTkCore/canvas.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,10 +192,10 @@ def drawTTkString(self, pos, text, width=None, color=TTkColor.RST, alignment=TTk
else:
self._colors[y][x+i] = colors[i].mod(x+i,y)
# Check the full wide chars on the edge of the two canvasses
if self._data[y][x+a] == '':
if ((0 <= (x+a) < self._width) and self._data[y][x+a] == ''):
self._data[y][x+a] = TTkCfg.theme.unicodeWideOverflowCh[0]
self._colors[y][x+a] = TTkCfg.theme.unicodeWideOverflowColor
if TTkString._isWideCharData(self._data[y][x+b-1]):
if ((0 <= (x+b-1) < self._width) and TTkString._isWideCharData(self._data[y][x+b-1])):
self._data[y][x+b-1] = TTkCfg.theme.unicodeWideOverflowCh[1]
self._colors[y][x+b-1] = TTkCfg.theme.unicodeWideOverflowColor

Expand Down Expand Up @@ -598,32 +598,27 @@ def paintCanvas(self, canvas, geom, slice, bound):
w = min(w,self._width-x)
h = min(h,self._height-y)

# if x>=self._width: x=self._width-1
# if y>=self._height: y=self._height-1
# if w>=self._width-x: w=self._width-x
# if h>=self._height-y: h=self._height-y

xoffset = 0 if x>=bx else bx-x
yoffset = 0 if y>=by else by-y
wslice = w if x+w < bx+bw else bx+bw-x
hslice = h if y+h < by+bh else by+bh-y
xoffset = min(max(0,bx-x),canvas._width-1)
yoffset = min(max(0,by-y),canvas._height-1)
wslice = min(w if x+w < bx+bw else bx+bw-x,canvas._width)
hslice = min(h if y+h < by+bh else by+bh-y,canvas._height)

for iy in range(yoffset,hslice):
a, b = x+xoffset, x+wslice
self._data[y+iy][a:b] = canvas._data[iy][xoffset:wslice]
self._colors[y+iy][a:b] = canvas._colors[iy][xoffset:wslice]

# Check the full wide chars on the edge of the two canvasses
if self._data[y+iy][a]=='':
if ((0 <= a < self._width) and self._data[y+iy][a]==''):
self._data[y+iy][a] = TTkCfg.theme.unicodeWideOverflowCh[0]
self._colors[y+iy][a] = TTkCfg.theme.unicodeWideOverflowColor
if TTkString._isWideCharData(self._data[y+iy][b-1]):
if ((0 < b <= self._width) and TTkString._isWideCharData(self._data[y+iy][b-1])):
self._data[y+iy][b-1] = TTkCfg.theme.unicodeWideOverflowCh[1]
self._colors[y+iy][b-1] = TTkCfg.theme.unicodeWideOverflowColor
if TTkString._isWideCharData(self._data[y+iy][a-1]):
if ((0 < a <= self._width) and TTkString._isWideCharData(self._data[y+iy][a-1])):
self._data[y+iy][a-1] = TTkCfg.theme.unicodeWideOverflowCh[1]
self._colors[y+iy][a-1] = TTkCfg.theme.unicodeWideOverflowColor
if ( b<self._width-1 and self._data[y+iy][b]=='' ):
if ((0 <= b < self._width) and self._data[y+iy][b]==''):
self._data[y+iy][b] = TTkCfg.theme.unicodeWideOverflowCh[0]
self._colors[y+iy][b] = TTkCfg.theme.unicodeWideOverflowColor

Expand Down
16 changes: 9 additions & 7 deletions TermTk/TTkCore/constant.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,14 +289,16 @@ class WindowFlag:
# ''' Gives the window a title bar.'''
# WindowSystemMenuHint = 0x00002000
# ''' Adds a window system menu, and possibly a close button (for example on Mac). If you need to hide or show a close button, it is more portable to use WindowCloseButtonHint.'''
# WindowMinimizeButtonHint = 0x00004000
# ''' Adds a minimize button. On some platforms this implies Qt::WindowSystemMenuHint for it to work.'''
# WindowMaximizeButtonHint = 0x00008000
# ''' Adds a maximize button. On some platforms this implies Qt::WindowSystemMenuHint for it to work.'''
# WindowMinMaxButtonsHint = WindowMinimizeButtonHint
# ''' | WindowMaximizeButtonHint Adds a minimize and a maximize button. On some platforms this implies Qt::WindowSystemMenuHint for it to work.'''
WindowReduceButtonHint = 0x00000200
''' Adds a reduce button.'''
WindowMinimizeButtonHint = 0x00004000
''' Adds a minimize button.'''
WindowMaximizeButtonHint = 0x00008000
''' Adds a maximize button.'''
WindowMinMaxButtonsHint = WindowMinimizeButtonHint | WindowMaximizeButtonHint
''' Adds a minimize and a maximize button.'''
WindowCloseButtonHint = 0x08000000
''' Adds a close button. On some platforms this implies Qt::WindowSystemMenuHint for it to work.'''
''' Adds a close button.'''
# WindowFullscreenButtonHint = 0x80000000
# ''' On macOS adds a fullscreen button.'''
# WindowShadeButtonHint = 0x00020000
Expand Down
10 changes: 5 additions & 5 deletions TermTk/TTkCore/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def addShortcut(widget, letter):
def execShortcut(letter, widget=None):
if not isinstance(letter, str): return
for sc in TTkHelper._shortcut:
if sc._letter == letter.lower() and sc._widget.isVisible():
if sc._letter == letter.lower() and sc._widget.isVisibleAndParent():
if not widget or TTkHelper.isParent(widget, sc._widget):
sc._widget.shortcutEvent()
return
Expand All @@ -76,7 +76,7 @@ def updateAll():

@staticmethod
def addUpdateWidget(widget):
if not widget.isVisible(): return
if not widget.isVisibleAndParent(): return
if widget not in TTkHelper._updateWidget:
TTkHelper._updateWidget.append(widget)

Expand Down Expand Up @@ -249,7 +249,7 @@ def paintAll():

# TTkLog.debug(f"{len(TTkHelper._updateBuffer)} {len(TTkHelper._updateWidget)}")
for widget in TTkHelper._updateWidget:
if not widget.isVisible(): continue
if not widget.isVisibleAndParent(): continue
parent = widget.parentWidget()
while parent is not None:
if parent not in updateBuffers:
Expand All @@ -263,7 +263,7 @@ def paintAll():

# Paint all the canvas
for widget in updateBuffers:
if not widget.isVisible(): continue
if not widget.isVisibleAndParent(): continue
# Resize the canvas just before the paintEvent
# to avoid too many allocations
widget.getCanvas().updateSize()
Expand All @@ -277,7 +277,7 @@ def paintAll():
sortedUpdateWidget = sorted(sortedUpdateWidget, key=lambda w: -w[1])
for w in sortedUpdateWidget:
widget = w[0]
if not widget.isVisible(): continue
if not widget.isVisibleAndParent(): continue
pushToTerminal = True
widget.paintChildCanvas()

Expand Down
6 changes: 3 additions & 3 deletions TermTk/TTkWidgets/TTkPickers/colorpicker.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ def __init__(self, *args, **kwargs):
self.colorSelected = pyTTkSignal(TTkColor)
TTkWindow.__init__(self, *args, **kwargs)
TColor.__init__(self, *args, **kwargs)
self._name = kwargs.get('name' , 'TTkColorPicker' )
self.setWindowFlag(TTkK.WindowFlag.WindowMaximizeButtonHint | TTkK.WindowFlag.WindowCloseButtonHint)
self.setLayout(TTkGridLayout())

colorLayout = TTkGridLayout() # Right
Expand Down Expand Up @@ -308,8 +308,8 @@ def _controlSetColor(color):
@pyTTkSlot()
def _leHTMLChanged():
text = leHTML.text()
if re.match('#[a-f0-9]{6}', text.lower()):
_controlSetRGBColor(int(text[1:], 16))
if re.match('#[a-f0-9]{6}', str(text).lower()):
_controlSetRGBColor(int(str(text)[1:], 16))

leHTML.returnPressed.connect(_leHTMLChanged)

Expand Down
4 changes: 2 additions & 2 deletions TermTk/TTkWidgets/TTkPickers/filepicker.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ def __init__(self, *args, **kwargs):
self.filesPicked = pyTTkSignal(list)
self.folderPicked = pyTTkSignal(str)

TTkWindow.__init__(self, *args, **kwargs)
self._name = kwargs.get('name' , 'TTkFileDialogPicker' )
super().__init__(*args, **kwargs)
self.setWindowFlag(TTkK.WindowFlag.WindowMaximizeButtonHint | TTkK.WindowFlag.WindowCloseButtonHint)

self._recentPathId = -1
self._recentPath = []
Expand Down
24 changes: 5 additions & 19 deletions TermTk/TTkWidgets/widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -520,29 +520,12 @@ def setMinimumWidth(self, minw):
self._minw = minw
self.update(updateLayout=True, updateParent=True)

@staticmethod
def _propagateShowToLayout(layout):
''' .. caution:: Don't touch this! '''
if layout is None: return
for item in layout.zSortedItems:
if item.layoutItemType == TTkK.WidgetItem and not item.isEmpty():
child = item.widget()
child._propagateShow()
else:
TTkWidget._propagateShowToLayout(item)

def _propagateShow(self):
''' .. caution:: Don't touch this! '''
if not self._visible: return
self.update(updateLayout=True, updateParent=True)
TTkWidget._propagateShowToLayout(self.rootLayout())

@pyTTkSlot()
def show(self):
if self._visible: return
self._visible = True
self._canvas.show()
self._propagateShow()
self.update(updateLayout=True, updateParent=True)

@pyTTkSlot()
def hide(self):
Expand Down Expand Up @@ -578,12 +561,15 @@ def setVisible(self, visible):
if visible: self.show()
else: self.hide()

def isVisible(self):
def isVisibleAndParent(self):
if self._parent is None:
return self._visible
else:
return self._visible & self._parent.isVisible()

def isVisible(self):
return self._visible

# Event to be sent
# TODO: Remove This
def layoutUpdated(self): pass
Expand Down
89 changes: 78 additions & 11 deletions TermTk/TTkWidgets/window.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,24 @@
from TermTk.TTkWidgets.button import TTkButton
from TermTk.TTkWidgets.resizableframe import TTkResizableFrame

class _MinimizedButton(TTkButton):
__slots__ = ('_windowWidget')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._windowWidget = kwargs.get('windowWidget')
def _cb():
self._windowWidget.show()
self.close()
self.clicked.connect(_cb)

class TTkWindow(TTkResizableFrame):
__slots__ = (
'_title', '_mouseDelta', '_draggable',
'_btnClose', '_btnMax', '_btnMin', '_btnReduce',
'_flags', '_winTopLayout' )
'_flags', '_winTopLayout',
'_maxBk', '_redBk' )
def __init__(self, *args, **kwargs):
TTkResizableFrame.__init__(self, *args, **kwargs)
super().__init__(*args, **kwargs)
self._title = kwargs.get('title' , '' )
self._flags = TTkK.NONE
self.setPadding(3,1,1,1)
Expand All @@ -48,31 +58,88 @@ def __init__(self, *args, **kwargs):
# Add the top Layout to keep the windows action buttons
self._winTopLayout = TTkGridLayout()
self.rootLayout().addItem(self._winTopLayout)
self._winTopLayout.setGeometry(1,1,self.width()-2,1)
# Close Button
self._btnClose = TTkButton(border=False, text="x", size=(3,1), maxWidth=3, minWidth=3, visible=False)
self._btnClose.clicked.connect(self.close)
# Max Button
self._maxBk = None
self._btnMax = TTkButton(border=False, text="^", size=(3,1), maxWidth=3, minWidth=3, visible=False)
self._btnMax.clicked.connect(self._maximize)
# Min Button
self._btnMin = TTkButton(border=False, text="_", size=(3,1), maxWidth=3, minWidth=3, visible=False)
self._btnMin.clicked.connect(self._minimize)
# Button Reduce_border
self._redBk = None
self._btnReduce = TTkButton(border=False, text=".", size=(3,1), maxWidth=3, minWidth=3, visible=False)
self._btnReduce.clicked.connect(self._reduce)

self._winTopLayout.addItem(TTkLayout(),0,0)
self._winTopLayout.addWidget(self._btnClose,0,1)
self._winTopLayout.addWidget(self._btnClose, 0,4)
self._winTopLayout.addWidget(self._btnMax, 0,3)
self._winTopLayout.addWidget(self._btnMin, 0,2)
self._winTopLayout.addWidget(self._btnReduce,0,1)
self._winTopLayout.setGeometry(1,1,self.width()-2,1)
self._winTopLayout.update()

self.setWindowFlag(kwargs.get('flags', TTkK.NONE))
self.setWindowFlag(kwargs.get('flags', TTkK.WindowFlag.WindowCloseButtonHint))

def _maximize(self):
if not (pw := self.parentWidget()): return
if self._maxBk:
self.setGeometry(*self._maxBk)
self._maxBk = None
else:
bk = self.geometry()
maxw,maxh = pw.layout().size()
self.setGeometry(0,0,maxw,maxh)
self._maxBk = bk

def _reduce(self):
if self._redBk:
self.resize(*self._redBk)
self._redBk = None
else:
bk = self.size()
self.resize(self.width(),4)
self._redBk = bk

def _minimize(self):
if not (pw := self.parentWidget()): return
stack = []
for li in pw.rootLayout().children():
if li.layoutItemType == TTkK.WidgetItem and issubclass(type(w:=li.widget()),_MinimizedButton):
stack.append(w.y())
stack = sorted(stack)
lx,ly = pw.layout().pos()
pos = ly
for v in stack:
if (pos+2) < v or (v+2) < pos:
break
pos += 3
mb = _MinimizedButton(windowWidget=self,text=self._title,border=True,pos=(lx,pos),size=(15,3))
pw.rootLayout().addWidget(mb)
self.hide()

def setTitle(self, title):
self._title = title
self.update()

def windowFlag(self):
return self._flags

def setWindowFlag(self, flag):
if self._flags == flag: return
self._flags = flag
if flag & TTkK.WindowFlag.WindowCloseButtonHint:
self._btnClose.show()
else:
self._btnClose.hide()
self.update()
self._btnClose.setVisible( bool(flag & TTkK.WindowFlag.WindowCloseButtonHint))
self._btnMax.setVisible( bool(flag & TTkK.WindowFlag.WindowMaximizeButtonHint))
self._btnMin.setVisible( bool(flag & TTkK.WindowFlag.WindowMinimizeButtonHint))
self._btnReduce.setVisible(bool(flag & TTkK.WindowFlag.WindowReduceButtonHint))
self._winTopLayout.update()

def resizeEvent(self, w, h):
self._winTopLayout.setGeometry(1,1,self.width()-2,1)
self._maxBk = None
self._redBk = None
self._winTopLayout.setGeometry(1,1,w-2,1)
super().resizeEvent(w,h)

def getTitle(self):
Expand Down
8 changes: 5 additions & 3 deletions demo/demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
from showcase.graph import demoGraph
from showcase.splitter import demoSplitter
from showcase.windows import demoWindows
from showcase.windowsflags import demoWindowsFlags
from showcase.formwidgets import demoFormWidgets
from showcase.scrollarea import demoScrollArea
from showcase.list import demoList
Expand Down Expand Up @@ -91,7 +92,7 @@ def showSource(file):
content = "Nothing"
with open(os.path.join(os.path.dirname(os.path.abspath(__file__)),file)) as f:
content = stupidPythonHighlighter( ttk.TTkString() + f.read() )
sourceWin = ttk.TTkWindow(size=(100,40), title=file, layout=ttk.TTkGridLayout())
sourceWin = ttk.TTkWindow(size=(100,40), title=file, layout=ttk.TTkGridLayout(), flags=ttk.TTkK.WindowFlag.WindowMaximizeButtonHint|ttk.TTkK.WindowFlag.WindowCloseButtonHint)
texEdit = ttk.TTkTextEdit(parent=sourceWin, lineNumber=True)
texEdit.setText(content)
ttk.TTkHelper.overlay(None, sourceWin, 2, 2)
Expand Down Expand Up @@ -198,7 +199,8 @@ def demoShowcase(root=None, border=True):
listMenu.addItem(f"Windows")
tabWindows = ttk.TTkTabWidget(parent=mainFrame, border=False, visible=False)
tabWindows.addTab(demoWindows(), " Windows Test ")
tabWindowsSources = [ 'showcase/windows.py' ]
tabWindows.addTab(demoWindowsFlags()," Windows Flags ")
tabWindowsSources = [ 'showcase/windows.py', 'showcase/windowsflags.py' ]
tabWindows.addMenu("sources", ttk.TTkK.RIGHT).menuButtonClicked.connect(lambda x : showSource(tabWindowsSources[tabWindows.currentIndex()]))

listMenu.addItem(f"Extra")
Expand Down Expand Up @@ -250,7 +252,7 @@ def main():

root = ttk.TTk(title="pyTermTk Demo")
if windowed:
winTabbed1 = ttk.TTkWindow(parent=root,pos=(0,0), size=(120,40), title="pyTermTk Showcase", border=True, layout=ttk.TTkGridLayout())
winTabbed1 = ttk.TTkWindow(parent=root,pos=(0,0), size=(120,40), title="pyTermTk Showcase", border=True, layout=ttk.TTkGridLayout(), flags=ttk.TTkK.NONE)
border = True
else:
root.setLayout(ttk.TTkGridLayout())
Expand Down
Loading

0 comments on commit bfe4b4a

Please sign in to comment.