diff --git a/TermTk/TTkCore/canvas.py b/TermTk/TTkCore/canvas.py index 6d9b9717..3468a06a 100644 --- a/TermTk/TTkCore/canvas.py +++ b/TermTk/TTkCore/canvas.py @@ -100,8 +100,34 @@ class TTkCanvas: self._data[_y][_x] = _ch self._colors[_y][_x] = _col.mod(_x,_y) - ''' + def drawVLine(self, pos, size, color=TTkColor.RST): + if size == 0: return + x,y = pos + ln = TTkCfg.theme.vline + self._set(y, x, ln[0], color) + self._set(y+size-1, x, ln[2], color) + if size > 2: + for i in range(1,size-1): + self._set(y+i, x, ln[1], color) + + def drawHLine(self, pos, size, color=TTkColor.RST): + if size == 0: return + x,y = pos + ln = TTkCfg.theme.hline + if size == 1: + txt = ln[0] + elif size == 2: + txt = ln[0]+ln[2] + else: + txt = ln[0]+(ln[1]*(size-2))+ln[2] + self.drawText(pos=pos, text=txt, color=color) + ''' + pos = (x:int, y:int) + items = [str] # list of str to be written (for each column) + size = [int] # list of output sizes (for each column) + colors = [TTkColor] # list of colors (for each column) + alignments = [TTkK.alignment] # list of txtalignments (for each column) ''' def drawTableLine(self, pos, items, sizes, colors, alignments ): x,y = pos diff --git a/TermTk/TTkGui/theme.py b/TermTk/TTkGui/theme.py index 35682dda..f71cc1bc 100644 --- a/TermTk/TTkGui/theme.py +++ b/TermTk/TTkGui/theme.py @@ -39,6 +39,10 @@ class TTkTheme(): └───────────────────┘▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ''' + + hline = ('╞','═','╡') + vline = ('╥','║','╨') + box = ( '═','║', '╔','╗', '╚','╝') diff --git a/TermTk/TTkTestWidgets/__init__.py b/TermTk/TTkTestWidgets/__init__.py new file mode 100644 index 00000000..89d7e830 --- /dev/null +++ b/TermTk/TTkTestWidgets/__init__.py @@ -0,0 +1,2 @@ +from .testwidget import * +from .testwidgetsizes import * diff --git a/TermTk/TTkWidgets/testwidget.py b/TermTk/TTkTestWidgets/testwidget.py similarity index 100% rename from TermTk/TTkWidgets/testwidget.py rename to TermTk/TTkTestWidgets/testwidget.py diff --git a/TermTk/TTkTestWidgets/testwidgetsizes.py b/TermTk/TTkTestWidgets/testwidgetsizes.py new file mode 100644 index 00000000..8ec31360 --- /dev/null +++ b/TermTk/TTkTestWidgets/testwidgetsizes.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2021 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. + +from TermTk.TTkCore.log import TTkLog +from TermTk.TTkCore.color import TTkColor +from TermTk.TTkWidgets.frame import * + +class TTkTestWidgetSizes(TTkFrame): + ID = 1 + __slots__ = ('_name') + def __init__(self, *args, **kwargs): + TTkFrame.__init__(self, *args, **kwargs) + self._name = kwargs.get('name' , f"TestWidgetSizes-{TTkTestWidgetSizes.ID}" ) + TTkTestWidgetSizes.ID+=1 + + def paintEvent(self): + TTkFrame.paintEvent(self) + t,_,l,_ = self.getPadding() + self._canvas.drawText(pos=(l,t+0), text=f"Test Widget [{self._name}]") + self._canvas.drawText(pos=(l,t+1), text=f"x,y ({self._x},{self._y})") + self._canvas.drawText(pos=(l,t+2), text=f"w,h ({self._width},{self._height})") + self._canvas.drawText(pos=(l,t+3), text=f"max w,h ({self._maxw},{self._maxh})") + self._canvas.drawText(pos=(l,t+4), text=f"min w,h ({self._minw},{self._minh})") diff --git a/TermTk/TTkWidgets/__init__.py b/TermTk/TTkWidgets/__init__.py index b5ea8178..c61f288c 100644 --- a/TermTk/TTkWidgets/__init__.py +++ b/TermTk/TTkWidgets/__init__.py @@ -2,6 +2,7 @@ from .widget import * from .spacer import * from .frame import * from .resizableframe import * +from .splitter import * from .label import * from .button import * from .checkbox import * @@ -12,4 +13,3 @@ from .scrollbar import * from .window import * from .table import * from .logviewer import * -from .testwidget import * diff --git a/TermTk/TTkWidgets/resizableframe.py b/TermTk/TTkWidgets/resizableframe.py index 36d4bf0c..23adcf2a 100644 --- a/TermTk/TTkWidgets/resizableframe.py +++ b/TermTk/TTkWidgets/resizableframe.py @@ -33,8 +33,8 @@ class TTkResizableFrame(TTkFrame): self._name = kwargs.get('name' , 'TTkResizableFrame' ) self.setBorder(True) self._mouseDelta = (0,0) - self.setFocusPolicy(TTkK.ClickFocus) self._resizable = TTkK.NONE + self.setFocusPolicy(TTkK.ClickFocus) def mousePressEvent(self, evt): diff --git a/TermTk/TTkWidgets/splitter.py b/TermTk/TTkWidgets/splitter.py index 64c470c2..989b8257 100644 --- a/TermTk/TTkWidgets/splitter.py +++ b/TermTk/TTkWidgets/splitter.py @@ -22,7 +22,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. - +from TermTk.TTkCore.constant import TTkK from TermTk.TTkCore.log import TTkLog from TermTk.TTkCore.color import TTkColor from TermTk.TTkCore.ttk import * @@ -30,24 +30,107 @@ from TermTk.TTkWidgets.widget import * from TermTk.TTkWidgets.frame import * class TTkSplitter(TTkFrame): - __slots__ = ('_widgets', '_orientation', '_splitters', '_selected') + __slots__ = ('_orientation','_separators', '_separatorSelected', '_mouseDelta') def __init__(self, *args, **kwargs): + self._separators = [] + self._separatorSelected = None TTkFrame.__init__(self, *args, **kwargs) - self._name = kwargs.get('name' , 'TTkSplitter' ) - self._widgets = [] - self._splitters = [] - self._orientation = kwargs.get('orientation' , TTkK.HORIZONTAL ) - - def addWidget(self, widget): - # NOTE: Check with the max/min size if the new widget can fit - self._widgets.append(widget) - self._splitters.append(0x10000) - self._rearrange() - - def _rearrange(self): - w, h = self.size() + self._name = kwargs.get('name' , 'TTkSpacer') + self._orientation = kwargs.get('orientation', TTkK.HORIZONTAL) + self.setBorder(False) + self.setFocusPolicy(TTkK.ClickFocus) + + def addWidget(self, widget, size=None): + TTkFrame.addWidget(self, widget) + _,_,w,h = self.geometry() + + if self._orientation == TTkK.HORIZONTAL: + fullSize = w + else: + fullSize = h + + if self._separators: + newSep = (self._separators[-1] + fullSize) // 2 + else: + newSep = -1 + self._separators.append(newSep) + self._updateGeometries() + + #widgetsNum = self.layout().count() + #lastId = widgetsNum - 2 + #newId = widgetsNum - 1 + #lastSep = -1 + #if self._separators: + # lastSep = self._separators[-1] + #self._separators.append(newSep) + #if self._orientation == TTkK.HORIZONTAL: + # self.layout().itemAt(oldId).setGeometry(lastSep+1, 0, newSep-lastSep-1, h) + # self.layout().itemAt(newId).setGeometry(newSep+1, 0, w-newSep-1, h) + #else: + # self.layout().itemAt(oldId).setGeometry(0, lastSep+1, w, newSep-lastSep-1) + # self.layout().itemAt(newId).setGeometry(0, newSep+1, w, h-newSep-1) + + def _updateGeometries(self): + _,_,w,h = self.geometry() + sep = self._separators + for i in range(len(sep)): + item = self.layout().itemAt(i) + if self._orientation == TTkK.HORIZONTAL: + x = sep[i]+1 + x1 = w if i>len(sep)-2 else sep[i+1] + y = 0 + item.setGeometry(x,y,x1-x,h) + else: + x = 0 + y = sep[i]+1 + y1 = h if i>len(sep)-2 else sep[i+1] + item.setGeometry(x,y,w,y1-y) + + def resizeEvent(self, w, h): + self._updateGeometries() + + def paintEvent(self): + w,h = self.size() if self._orientation == TTkK.HORIZONTAL: - pass + for i in self._separators: + self._canvas.drawVLine(pos=(i,0), size=h) else: - pass + for i in self._separators: + self._canvas.drawHLine(pos=(0,i), size=w) + + def mousePressEvent(self, evt): + self._separatorSelected = None + self._mouseDelta = (evt.x, evt.y) + x,y = evt.x, evt.y + TTkLog.debug(f"{self._separators} {evt}") + for i in range(len(self._separators)): + val = self._separators[i] + if self._orientation == TTkK.HORIZONTAL: + if x == val: + self._separatorSelected = i + self.update() + self._updateGeometries() + return True + else: + if y == val: + self._separatorSelected = i + self.update() + self._updateGeometries() + return True + def mouseDragEvent(self, evt): + if self._separatorSelected is not None: + # TTkLog.debug(f"{self._resizable}") + x,y,w,h = self.geometry() + maxw, maxh = self.maximumSize() + minw, minh = self.minimumSize() + dx = evt.x-self._mouseDelta[0] + dy = evt.y-self._mouseDelta[1] + if self._orientation == TTkK.HORIZONTAL: + self._separators[self._separatorSelected] = evt.x + else: + self._separators[self._separatorSelected] = evt.y + self._updateGeometries() + self.update() + return True + return False diff --git a/TermTk/TTkWidgets/table.py b/TermTk/TTkWidgets/table.py index 0ce97019..71591ae3 100644 --- a/TermTk/TTkWidgets/table.py +++ b/TermTk/TTkWidgets/table.py @@ -30,7 +30,6 @@ from TermTk.TTkCore.color import TTkColor from TermTk.TTkLayouts.gridlayout import TTkGridLayout from TermTk.TTkWidgets.widget import TTkWidget from TermTk.TTkWidgets.frame import TTkFrame -from TermTk.TTkWidgets.testwidget import TTkTestWidget from TermTk.TTkWidgets.spacer import TTkSpacer from TermTk.TTkWidgets.scrollbar import TTkScrollBar diff --git a/TermTk/__init__.py b/TermTk/__init__.py index 8c7597c6..904632ad 100644 --- a/TermTk/__init__.py +++ b/TermTk/__init__.py @@ -1,4 +1,5 @@ from .TTkCore import * from .TTkGui import * from .TTkLayouts import * -from .TTkWidgets import * \ No newline at end of file +from .TTkWidgets import * +from .TTkTestWidgets import * \ No newline at end of file diff --git a/tests/test.ui.010.splitter.py b/tests/test.ui.010.splitter.py new file mode 100755 index 00000000..248c1dd5 --- /dev/null +++ b/tests/test.ui.010.splitter.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2021 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.TTkLog.use_default_file_logging() + +root = ttk.TTk() + +winSplitter1 = ttk.TTkWindow(parent=root,pos = (1,1), size=(100,40), title="Test Splitter", border=True, layout=ttk.TTkGridLayout()) +vsplitter1_1 = ttk.TTkSplitter(parent=winSplitter1, orientation=ttk.TTkK.VERTICAL) +ttk.TTkTestWidgetSizes(parent=vsplitter1_1 ,border=True, title="Frame1.1") +hsplitter1_1 = ttk.TTkSplitter(parent=vsplitter1_1) +ttk.TTkTestWidgetSizes(parent=vsplitter1_1 ,border=True, title="Frame1.2") +ttk.TTkTestWidgetSizes(parent=hsplitter1_1 ,border=True, title="Frame2") +ttk.TTkTestWidgetSizes(parent=hsplitter1_1 ,border=True, title="Frame3") + +winSplitter2 = ttk.TTkWindow(parent=root,pos = (1,1), size=(100,40), title="Test Splitter", border=True, layout=ttk.TTkGridLayout()) +vsplitter2_1 = ttk.TTkSplitter(parent=winSplitter2, orientation=ttk.TTkK.VERTICAL) +ttk.TTkTestWidgetSizes(parent=vsplitter2_1 ,border=True, title="Frame1.1") +hsplitter2_1 = ttk.TTkSplitter(parent=vsplitter2_1) +ttk.TTkTestWidgetSizes(parent=vsplitter2_1 ,border=True, title="Frame1.2") +ttk.TTkTestWidgetSizes(parent=vsplitter2_1 ,border=True, title="Frame1.3") +ttk.TTkTestWidgetSizes(parent=hsplitter2_1 ,border=True, title="Frame2") +ttk.TTkTestWidgetSizes(parent=hsplitter2_1 ,border=True, title="Frame3") +ttk.TTkTestWidgetSizes(parent=hsplitter2_1 ,border=True, title="Frame4") + + +root.mainloop() \ No newline at end of file