From b0bb367f81a4d43fdda4ec71b25adad8e5482012 Mon Sep 17 00:00:00 2001 From: Eugenio Parodi Date: Tue, 30 May 2023 00:13:45 +0100 Subject: [PATCH 1/3] Reworked the standard menuBar api t keep the more compliant with the standard TermTk api --- TermTk/TTkCore/helper.py | 8 ++++ TermTk/TTkWidgets/__init__.py | 2 +- TermTk/TTkWidgets/frame.py | 33 +++++++++++-- TermTk/TTkWidgets/menubar.py | 8 ++-- demo/showcase/menubar.py | 32 ++++++------- tests/test.ui.015.scrollArea.03.py | 2 +- tests/test.ui.030.menu.01.py | 4 +- tests/test.ui.030.menu.02.bar.py | 75 ++++++++++++++++++++++++++++++ ttkDesigner/app/designer.py | 6 +-- 9 files changed, 138 insertions(+), 32 deletions(-) create mode 100755 tests/test.ui.030.menu.02.bar.py diff --git a/TermTk/TTkCore/helper.py b/TermTk/TTkCore/helper.py index 949d8ba6..ad7ee984 100644 --- a/TermTk/TTkCore/helper.py +++ b/TermTk/TTkCore/helper.py @@ -100,6 +100,10 @@ class TTkHelper: def quit(): if TTkHelper._rootWidget: TTkHelper._rootWidget.quit() + + @staticmethod + def getTerminalSize(): + return TTkGlbl.term_w, TTkGlbl.term_h @staticmethod def rootOverlay(widget): @@ -163,6 +167,10 @@ class TTkHelper: if forceBoundaries: wx = max(0, wx+x if wx+x+w < TTkGlbl.term_w else TTkGlbl.term_w-w ) wy = max(0, wy+y if wy+y+h < TTkGlbl.term_h else TTkGlbl.term_h-h ) + mw,mh = widget.minimumSize() + ww = min(w,max(mw, TTkGlbl.term_w)) + wh = min(h,max(mh, TTkGlbl.term_h)) + widget.resize(ww,wh) else: wx += x wy += y diff --git a/TermTk/TTkWidgets/__init__.py b/TermTk/TTkWidgets/__init__.py index b0cb012b..5cb7a80d 100644 --- a/TermTk/TTkWidgets/__init__.py +++ b/TermTk/TTkWidgets/__init__.py @@ -13,7 +13,7 @@ from .label import TTkLabel from .lineedit import TTkLineEdit from .list_ import TTkList from .listwidget import TTkListWidget -from .menubar import TTkMenuLayout +from .menubar import TTkMenuBarLayout from .menu import TTkMenu, TTkMenuButton from .progressbar import TTkProgressBar, TTkLookAndFeelPBar from .radiobutton import TTkRadioButton diff --git a/TermTk/TTkWidgets/frame.py b/TermTk/TTkWidgets/frame.py index 883f91f3..32a8c936 100644 --- a/TermTk/TTkWidgets/frame.py +++ b/TermTk/TTkWidgets/frame.py @@ -51,7 +51,7 @@ class TTkFrame(TTkWidget): ''' __slots__ = ( '_border','_title', '_titleColor', '_titleAlign','_borderColor', - '_menubarTop', '_menubarTopPosition', '_menubarBottom') + '_menubarTop', '_menubarTopPosition', '_menubarBottom', '_menubarBottomPosition') def __init__(self, *args, **kwargs): self._borderColor = kwargs.get('borderColor', TTkCfg.theme.frameBorderColor ) self._titleColor = kwargs.get('titleColor', TTkCfg.theme.frameTitleColor ) @@ -59,24 +59,47 @@ class TTkFrame(TTkWidget): self._title = TTkString(kwargs.get('title' , '' )) self._border = kwargs.get('border', True ) self._menubarTopPosition = 0 + self._menubarBottomPosition = 0 self._menubarTop = None self._menubarBottom = None TTkWidget.__init__(self, *args, **kwargs) self.setBorder(self._border) - def menubarTop(self): + def newMenubarTop(self): if not self._menubarTop: - from TermTk.TTkWidgets.menubar import TTkMenuLayout - self._menubarTop = TTkMenuLayout(borderColor=self._borderColor) + from TermTk.TTkWidgets.menubar import TTkMenuBarLayout + self._menubarTop = TTkMenuBarLayout(borderColor=self._borderColor) self.rootLayout().addItem(self._menubarTop) self._menubarTop.setGeometry(1,self._menubarTopPosition,self.width()-2,1) if not self._border and self._padt == 0: - self.setPadding(1,0,0,0) + self.setPadding(self._menubarTopPosition,0,0,0) return self._menubarTop + + def menuBar(self, position=TTkK.TOP): + if position == TTkK.TOP: + return self._menubarTop + else: + return self._menubarBottom + + def setMenuBar(self, menuBar, position=TTkK.TOP): + self.rootLayout().addItem(menuBar) + if position == TTkK.TOP: + self._menubarTop = menuBar + menuBar.setGeometry(1,self._menubarTopPosition,self.width()-2,1) + else: + self._menubarBottom = menuBar + menuBar.setGeometry(1,self.height()-1-self._menubarBottomPosition,self.width()-2,1) + if not self._border: + pt,pb,pl,pr = self.getPadding() + pt = 1 if position==TTkK.TOP else pt + pb = 1 if position==TTkK.BOTTOM else pb + self.setPadding(pt,pb,pl,pr) def resizeEvent(self, w, h): if self._menubarTop: self._menubarTop.setGeometry(1,self._menubarTopPosition,w-2,1) + if self._menubarBottom: + self._menubarBottom.setGeometry(1,h-1-self._menubarBottomPosition,w-2,1) super().resizeEvent(w,h) def title(self): diff --git a/TermTk/TTkWidgets/menubar.py b/TermTk/TTkWidgets/menubar.py index 5bf688e4..a839bcdb 100644 --- a/TermTk/TTkWidgets/menubar.py +++ b/TermTk/TTkWidgets/menubar.py @@ -58,9 +58,9 @@ class TTkMenuBarButton(TTkAbstractListItem): self.setMaximumSize(txtlen+2,1) self.listItemClicked.connect(self.menuButtonEvent) - def addMenu(self, text): + def addMenu(self, text, data:object=None, checkable:bool=False, checked:bool=False): '''addMenu''' - button = TTkMenuButton(text=text, borderColor=self._borderColor, border=False) + button = TTkMenuButton(text=text, data=data, checkable=checkable, checked=checked) self._menu.append(button) return button @@ -118,8 +118,8 @@ class TTkMenuBarButton(TTkAbstractListItem): def focusOutEvent(self): self.highlighted=False -class TTkMenuLayout(TTkHBoxLayout): - '''TTkMenuLayout''' +class TTkMenuBarLayout(TTkHBoxLayout): + '''TTkMenuBarLayout''' __slots__ = ('_borderColor', '_itemsLeft', '_itemsCenter', '_itemsRight', '_buttons') def __init__(self, *args, **kwargs): self._buttons = [] diff --git a/demo/showcase/menubar.py b/demo/showcase/menubar.py index b7f84baf..0a3b0fdd 100755 --- a/demo/showcase/menubar.py +++ b/demo/showcase/menubar.py @@ -33,23 +33,23 @@ def demoMenuBar(root=None): frameTop = ttk.TTkFrame(parent=frame, border=False) frameBottom = ttk.TTkFrame(parent=frame, border=True,layout=ttk.TTkVBoxLayout()) - fileMenu = frameTop.menubarTop().addMenu("&File") + fileMenu = frameTop.newMenubarTop().addMenu("&File") fileMenu.addMenu("Open") fileMenu.addMenu("Close") fileMenu.addMenu("Exit") - frameTop.menubarTop().addMenu("&Edit") - frameTop.menubarTop().addMenu("&Selection") + frameTop.newMenubarTop().addMenu("&Edit") + frameTop.newMenubarTop().addMenu("&Selection") - frameTop.menubarTop().addMenu("&Center 1", alignment=ttk.TTkK.CENTER_ALIGN) - frameTop.menubarTop().addMenu("Cen&te&r 2", alignment=ttk.TTkK.CENTER_ALIGN) + frameTop.newMenubarTop().addMenu("&Center 1", alignment=ttk.TTkK.CENTER_ALIGN) + frameTop.newMenubarTop().addMenu("Cen&te&r 2", alignment=ttk.TTkK.CENTER_ALIGN) - frameTop.menubarTop().addMenu("_", alignment=ttk.TTkK.RIGHT_ALIGN) - frameTop.menubarTop().addMenu("^", alignment=ttk.TTkK.RIGHT_ALIGN) - frameTop.menubarTop().addMenu("X", alignment=ttk.TTkK.RIGHT_ALIGN) + frameTop.newMenubarTop().addMenu("_", alignment=ttk.TTkK.RIGHT_ALIGN) + frameTop.newMenubarTop().addMenu("^", alignment=ttk.TTkK.RIGHT_ALIGN) + frameTop.newMenubarTop().addMenu("X", alignment=ttk.TTkK.RIGHT_ALIGN) window = ttk.TTkWindow(title="Test MenuBar", parent=frameTop,pos=(1,1), size=(60,10), border=True) - fileMenu2 = window.menubarTop().addMenu("&Fi&le") + fileMenu2 = window.newMenubarTop().addMenu("&Fi&le") fileMenu2.addMenu("New File") fileMenu2.addMenu("Old File") fileMenu2.addSpacer() @@ -69,7 +69,7 @@ def demoMenuBar(root=None): fileMenu2.addSpacer() fileMenu2.addMenu("Exit") - editMenu2 = window.menubarTop().addMenu("&E&dit") + editMenu2 = window.newMenubarTop().addMenu("&E&dit") editMenu2.addMenu("Undo") editMenu2.addMenu("Redo") editMenu2.addMenu("Cut") @@ -78,20 +78,20 @@ def demoMenuBar(root=None): editMenu2.addMenu("Find") editMenu2.addMenu("Replace") - window.menubarTop().addMenu("&Selection") + window.newMenubarTop().addMenu("&Selection") - window.menubarTop().addMenu("&Center 3", alignment=ttk.TTkK.CENTER_ALIGN) + window.newMenubarTop().addMenu("&Center 3", alignment=ttk.TTkK.CENTER_ALIGN) - window.menubarTop().addMenu("X", alignment=ttk.TTkK.RIGHT_ALIGN) + window.newMenubarTop().addMenu("X", alignment=ttk.TTkK.RIGHT_ALIGN) - fileMenu3 = frameBottom.menubarTop().addMenu("&File 2") + fileMenu3 = frameBottom.newMenubarTop().addMenu("&File 2") fileMenu3.addMenu("Open") fileMenu3.addMenu("Close") fileMenu3.addMenu("Exit") - frameBottom.menubarTop().addMenu("&Edit 2") - frameBottom.menubarTop().addMenu("&Selection 2") + frameBottom.newMenubarTop().addMenu("&Edit 2") + frameBottom.newMenubarTop().addMenu("&Selection 2") ttk.TTkLogViewer(parent=frameBottom) diff --git a/tests/test.ui.015.scrollArea.03.py b/tests/test.ui.015.scrollArea.03.py index d65c880c..010cf13f 100755 --- a/tests/test.ui.015.scrollArea.03.py +++ b/tests/test.ui.015.scrollArea.03.py @@ -33,7 +33,7 @@ def main(): root = ttk.TTk() f = ttk.TTkFrame(parent=root, pos=(2,2), size=(30,5)) - fm = f.menubarTop().addMenu("F&orm") + fm = f.newMenubarTop().addMenu("F&orm") fm.addMenu("Preview...") root.mainloop() diff --git a/tests/test.ui.030.menu.01.py b/tests/test.ui.030.menu.01.py index c078d6fe..55b5af42 100755 --- a/tests/test.ui.030.menu.01.py +++ b/tests/test.ui.030.menu.01.py @@ -103,11 +103,11 @@ fileMenu.addSpacer() fileMenu.addMenu("Exit") window = ttk.TTkWindow(title="Test MenuBar", parent=root,pos=(30,1), size=(60,10), border=True) -fileMenu2 = window.menubarTop().addMenu("&Fi&le") +fileMenu2 = window.newMenubarTop().addMenu("&Fi&le") fileMenu2.addMenu("New File") fileMenu2.addMenu("Old File") fileMenu2.addSpacer() -fileMenu2.addMenu("Open") +fileMenu2.addMenu("Open",checkable=True) fileMenu2.addMenu("Save") fileMenu2.addMenu("Save as") fileMenu2.addSpacer() diff --git a/tests/test.ui.030.menu.02.bar.py b/tests/test.ui.030.menu.02.bar.py new file mode 100755 index 00000000..39535ee7 --- /dev/null +++ b/tests/test.ui.030.menu.02.bar.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2023 Eugenio Parodi +# +# 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. + +import sys, os +sys.path.append(os.path.join(sys.path[0],'..')) +import TermTk as ttk + +ttk.TTkTheme.loadTheme(ttk.TTkTheme.NERD) + +root = ttk.TTk(mouseTrack=True) + +def setMenu(curMenu): + curMenu.addMenu("New File") + curMenu.addMenu("Old File") + curMenu.addSpacer() + curMenu.addMenu("Open",checkable=True) + curMenu.addMenu("Save",checkable=True,checked=True) + curMenu.addMenu("Save as").setDisabled() + curMenu.addSpacer() + exportFileMenu = curMenu.addMenu("E&xport") + txtExportFileMenu = exportFileMenu.addMenu("t&xt") + txtExportFileMenu.addMenu("ASCII") + txtExportFileMenu.addMenu("URF-8") + txtExportFileMenu.addMenu("PETSCII") + exportFileMenu.addMenu("&json") + exportFileMenu.addMenu("&yaml") + curMenu.addSpacer() + curMenu.addMenu("Closeeeeeeeee1234567890") + curMenu.addMenu("Close") + curMenu.addSpacer() + curMenu.addMenu("Exit") + +window = ttk.TTkWindow(title="Test MenuBar", parent=root,pos=(30,1), size=(60,10), border=True) +menuTop = ttk.TTkMenuBarLayout() +setMenu(menuTop.addMenu("&Fi&le")) +window.setMenuBar(menuTop) +menuBottom = ttk.TTkMenuBarLayout() +setMenu(menuBottom.addMenu("&Fi&le")) +window.setMenuBar(menuBottom, ttk.TTkK.BOTTOM) + +window = ttk.TTkFrame(title="Test MenuBar", parent=root,pos=(0,0), size=(60,10), border=True) +menuTop = ttk.TTkMenuBarLayout() +setMenu(menuTop.addMenu("&Fi&le")) +window.setMenuBar(menuTop) +menuBottom = ttk.TTkMenuBarLayout() +setMenu(menuBottom.addMenu("&Fi&le")) +window.setMenuBar(menuBottom, ttk.TTkK.BOTTOM) + + + +window = ttk.TTkWindow(title="LOG", parent=root, pos=(0,20), size=(100,10), border=True, layout=ttk.TTkGridLayout()) +ttk.TTkLogViewer(parent=window) + +root.mainloop() \ No newline at end of file diff --git a/ttkDesigner/app/designer.py b/ttkDesigner/app/designer.py index ad21d728..d57611d5 100644 --- a/ttkDesigner/app/designer.py +++ b/ttkDesigner/app/designer.py @@ -131,14 +131,14 @@ class TTkDesigner(TTkGridLayout): self.weModified.connect(self._treeInspector.refresh) - fileMenu = topMenuFrame.menubarTop().addMenu("&File") + fileMenu = topMenuFrame.newMenubarTop().addMenu("&File") fileMenu.addMenu("New").menuButtonClicked.connect(self.new) fileMenu.addMenu("Open").menuButtonClicked.connect(self.open) fileMenu.addMenu("Save").menuButtonClicked.connect(self.save) fileMenu.addMenu("Save As...").menuButtonClicked.connect(self.saveAs) fileMenu.addMenu("Exit").menuButtonClicked.connect(TTkHelper.quit) - extraMenu = topMenuFrame.menubarTop().addMenu("E&xtra") + extraMenu = topMenuFrame.newMenubarTop().addMenu("E&xtra") extraMenu.addMenu("Scratchpad").menuButtonClicked.connect(self.scratchpad) extraMenu.addSpacer() extraMenu.addMenu("Preview...").menuButtonClicked.connect(self.preview) @@ -148,7 +148,7 @@ class TTkDesigner(TTkGridLayout): def _showAboutTTk(btn): TTkHelper.overlay(None, TTkAbout(), 30,10) - helpMenu = topMenuFrame.menubarTop().addMenu("&Help", alignment=TTkK.RIGHT_ALIGN) + helpMenu = topMenuFrame.newMenubarTop().addMenu("&Help", alignment=TTkK.RIGHT_ALIGN) helpMenu.addMenu("About ...").menuButtonClicked.connect(_showAbout) helpMenu.addMenu("About ttk").menuButtonClicked.connect(_showAboutTTk) From d9f9e4a5140ffa07faf42786a5a310cba32d274d Mon Sep 17 00:00:00 2001 From: Ceccopierangiolieugenio Date: Tue, 30 May 2023 10:24:36 +0100 Subject: [PATCH 2/3] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d78babd9..4b4bf9ec 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ pip3 install --upgrade pyTermTk #### Clone ```bash -clone https://github.com/ceccopierangiolieugenio/pyTermTk.git +git clone https://github.com/ceccopierangiolieugenio/pyTermTk.git cd pyTermTk ``` From a973c599f1f12096da440dec584f4f5c935d405f Mon Sep 17 00:00:00 2001 From: Eugenio Parodi Date: Tue, 30 May 2023 17:31:35 +0100 Subject: [PATCH 3/3] Handled the bottom menu in a borderless frame --- TermTk/TTkWidgets/frame.py | 11 +++++++---- TermTk/TTkWidgets/menu.py | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/TermTk/TTkWidgets/frame.py b/TermTk/TTkWidgets/frame.py index 32a8c936..d90103ae 100644 --- a/TermTk/TTkWidgets/frame.py +++ b/TermTk/TTkWidgets/frame.py @@ -74,13 +74,13 @@ class TTkFrame(TTkWidget): if not self._border and self._padt == 0: self.setPadding(self._menubarTopPosition,0,0,0) return self._menubarTop - + def menuBar(self, position=TTkK.TOP): if position == TTkK.TOP: return self._menubarTop else: return self._menubarBottom - + def setMenuBar(self, menuBar, position=TTkK.TOP): self.rootLayout().addItem(menuBar) if position == TTkK.TOP: @@ -141,5 +141,8 @@ class TTkFrame(TTkWidget): align=self._titleAlign, color=self._borderColor, colorText=self._titleColor) - elif self._menubarTop: - canvas.drawMenuBarBg(pos=(0,0),size=self.width(),color=self._borderColor) + else: + if self._menubarTop: + canvas.drawMenuBarBg(pos=(0,0),size=self.width(),color=self._borderColor) + if self._menubarBottom: + canvas.drawMenuBarBg(pos=(0,self.height()-1),size=self.width(),color=self._borderColor) diff --git a/TermTk/TTkWidgets/menu.py b/TermTk/TTkWidgets/menu.py index 35b841aa..82d4442d 100644 --- a/TermTk/TTkWidgets/menu.py +++ b/TermTk/TTkWidgets/menu.py @@ -347,7 +347,7 @@ class TTkMenu(TTkResizableFrame): def addMenu(self, *args, **kwargs): ret = self._scrollView.addMenu(*args, **kwargs) w,h = self._scrollView.viewFullAreaSize() - self.resize(w+2,h+2) + self.resize(w+3,h+2) return ret def keyEvent(self, evt) -> bool: