Browse Source

improved the layout management in the designer

pull/99/head
Eugenio Parodi 3 years ago
parent
commit
79fdf37731
  1. 2
      TermTk/TTkCore/canvas.py
  2. 2
      TermTk/TTkUiTools/properties/__init__.py
  3. 60
      TermTk/TTkUiTools/properties/layout.py
  4. 18
      TermTk/TTkUiTools/uiloader.py
  5. 3
      TermTk/TTkUiTools/uiproperties.py
  6. 8
      ttkDesigner/app/designer.py
  7. 2
      ttkDesigner/app/propertyeditor.py
  8. 16
      ttkDesigner/app/superobj/superlayout.py
  9. 14
      ttkDesigner/app/superobj/superwidget.py
  10. 65
      ttkDesigner/app/treeinspector.py
  11. 4
      ttkDesigner/app/windoweditor.py

2
TermTk/TTkCore/canvas.py

@ -661,7 +661,7 @@ class TTkCanvas:
self._data[y+iy][a:b] = canvas._data[iy][xoffset:wslice]
self._colors[y+iy][a:b] = canvas._colors[iy][xoffset:wslice]
for iy in range(yoffset,hslice):
# Check the full wide chars on the edge of the two canvasses
if ((0 <= a < cw) and self._data[y+iy][a]==''):
self._data[y+iy][a] = TTkCfg.theme.unicodeWideOverflowCh[0]

2
TermTk/TTkUiTools/properties/__init__.py

@ -22,3 +22,5 @@ from .splitter import TTkSplitterProperties
from .texedit import TTkTextEditProperties
from .widget import TTkWidgetProperties
from .window import TTkWindowProperties
from .layout import TTkLayoutProperties

60
TermTk/TTkUiTools/properties/layout.py

@ -0,0 +1,60 @@
# MIT License
#
# Copyright (c) 2023 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com>
#
# 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.
# MIT License
#
# Copyright (c) 2023 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com>
#
# 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.TTkLayouts.layout import TTkLayout
TTkLayoutProperties = {
'Geometry' : {
'get': { 'cb':TTkLayout.geometry, 'type': [
{ 'name': 'x', 'type':int } ,
{ 'name': 'y', 'type':int } ,
{ 'name': 'width', 'type':int } ,
{ 'name': 'height','type':int } ] },
'set': { 'cb':TTkLayout.setGeometry, 'type': [
{ 'name': 'x', 'type':int } ,
{ 'name': 'y', 'type':int } ,
{ 'name': 'width', 'type':int } ,
{ 'name': 'height','type':int } ] },
}
}

18
TermTk/TTkUiTools/uiloader.py

@ -43,12 +43,13 @@ class TTkUiLoader():
kwargs = {}
# Init params to be configured with the setter
setters = []
layout = _getLayout(widProp['layout'])
for pname in widProp['params']:
if 'init' in properties[pname]:
initp = properties[pname]['init']
name = initp['name']
if initp['type'] is TTkLayout:
value = globals()[widProp['params'][pname]]()
value = layout
elif initp['type'] is TTkColor:
value = TTkColor.ansi(widProp['params'][pname])
else:
@ -59,7 +60,7 @@ class TTkUiLoader():
setp = properties[pname]['set']
setcb = setp['cb']
if setp['type'] is TTkLayout:
value = globals()[widProp['params'][pname]]()
value = layout
elif setp['type'] is TTkColor:
value = TTkColor.ansi(widProp['params'][pname])
else:
@ -76,10 +77,19 @@ class TTkUiLoader():
else:
s['cb'](widget, s['value'])
TTkLog.debug(widget)
for c in widProp['children']:
widget.layout().addWidget(_getWidget(c))
# for c in widProp['children']:
# widget.layout().addWidget(_getWidget(c))
return widget
def _getLayout(layprop):
layout = globals()[layprop['class']]()
for c in layprop['children']:
if issubclass(globals()[c['class']],TTkLayout):
layout.addItem(_getLayout(c))
else:
layout.addWidget(_getWidget(c))
return layout
widgetProperty = json.loads(text)
TTkLog.debug(widgetProperty)
# Yaml=

3
TermTk/TTkUiTools/uiproperties.py

@ -25,6 +25,7 @@ from TermTk.TTkWidgets import *
from .properties import *
TTkUiProperties = {
# Widgets
TTkButton.__name__: TTkButtonProperties,
TTkCheckbox.__name__: TTkCheckboxProperties,
TTkComboBox.__name__: TTkComboBoxProperties,
@ -39,4 +40,6 @@ TTkUiProperties = {
TTkTextEdit.__name__: TTkTextEditProperties,
TTkWidget.__name__: TTkWidgetProperties,
TTkWindow.__name__: TTkWindowProperties,
# Layouts
TTkLayout.__name__: TTkLayoutProperties,
}

8
ttkDesigner/app/designer.py

@ -105,9 +105,9 @@ class TTkDesigner(TTkGridLayout):
rightSplit.addItem(propertyEditor := PropertyEditor())
rightSplit.addWidget(TTkButton(text='E', border=True, maxHeight=3))
treeInspector.widgetSelected.connect(lambda _,s : s.pushSuperControlWidget())
treeInspector.widgetSelected.connect(propertyEditor.setDetail)
self._windowEditor.viewport().widgetSelected.connect(propertyEditor.setDetail)
treeInspector.thingSelected.connect(lambda _,s : s.pushSuperControlWidget())
treeInspector.thingSelected.connect(propertyEditor.setDetail)
self._windowEditor.viewport().thingSelected.connect(propertyEditor.setDetail)
self._windowEditor.viewport().weModified.connect(treeInspector.refresh)
@ -162,7 +162,7 @@ class TTkDesigner(TTkGridLayout):
widget = TTkUiLoader.loadJson(jj)
win = TTkWindow(
title="Mr Terminal",
size=(50,20),
size=(80,30),
layout=TTkGridLayout(),
flags=TTkK.WindowFlag.WindowMaximizeButtonHint|TTkK.WindowFlag.WindowCloseButtonHint)
win.layout().addWidget(widget)

2
ttkDesigner/app/propertyeditor.py

@ -264,7 +264,7 @@ class PropertyEditor(ttk.TTkGridLayout):
self._detail.clear()
for cc in reversed(type(domw).__mro__):
# if hasattr(cc,'_ttkProperties'):
if issubclass(cc, ttk.TTkWidget):
if issubclass(cc, ttk.TTkWidget) or issubclass(cc, ttk.TTkLayout):
ccName = cc.__name__
classItem = ttk.TTkTreeWidgetItem([ccName,''], expanded=True)
self._detail.addTopLevelItem(classItem)

16
ttkDesigner/app/superobj/superlayout.py

@ -26,9 +26,9 @@ import TermTk as ttk
import ttkDesigner.app.superobj as so
class SuperLayout(ttk.TTkWidget):
def __init__(self, lay, weModified, widgetSelected, *args, **kwargs):
def __init__(self, lay, weModified, thingSelected, *args, **kwargs):
self.weModified = weModified
self.widgetSelected = widgetSelected
self.thingSelected = thingSelected
self._lay = lay
self._superRootWidget = kwargs.get('superRootWidget',False)
self._selectable = kwargs.get('selectable', False)
@ -52,7 +52,11 @@ class SuperLayout(ttk.TTkWidget):
self.update()
def dumpDict(self):
ret = {}
children=[]
for w in self.layout().children():
children.append(w.widget().dumpDict())
ret = {'class': 'TTkLayout',
'children':children}
return ret
def updateAll(self):
@ -75,7 +79,7 @@ class SuperLayout(ttk.TTkWidget):
def mouseReleaseEvent(self, evt) -> bool:
if self._superRootWidget or not self._selectable: return False
self.pushSuperControlWidget()
# self.widgetSelected.emit(self._lay,self)
self.thingSelected.emit(self._lay,self)
return True
def mouseDragEvent(self, evt) -> bool:
@ -99,7 +103,7 @@ class SuperLayout(ttk.TTkWidget):
hsx,hsy = evt.hotSpot()
ttk.TTkLog.debug(f"Drop ({data.__class__.__name__}) -> pos={evt.pos()}")
if issubclass(type(data),ttk.TTkLayout):
self.layout().addWidget(sw := so.SuperLayout(lay=data, weModified=self.weModified, widgetSelected=self.widgetSelected, pos=(evt.x-hsx, evt.y-hsy), selectable=True))
self.layout().addWidget(sw := so.SuperLayout(lay=data, weModified=self.weModified, thingSelected=self.thingSelected, pos=(evt.x-hsx, evt.y-hsy), selectable=True))
self._lay.addItem(data)
elif issubclass(type(data), so.SuperLayout):
sw = data
@ -117,7 +121,7 @@ class SuperLayout(ttk.TTkWidget):
self._lay.addWidget(data)
data.move(evt.x-hsx, evt.y-hsy)
elif issubclass(type(data),ttk.TTkWidget):
self.layout().addWidget(sw := so.SuperWidget(wid=data, weModified=self.weModified, widgetSelected=self.widgetSelected, pos=(evt.x-hsx, evt.y-hsy)))
self.layout().addWidget(sw := so.SuperWidget(wid=data, weModified=self.weModified, thingSelected=self.thingSelected, pos=(evt.x-hsx, evt.y-hsy)))
self._lay.addWidget(data)
data.move(evt.x-hsx, evt.y-hsy)
else:

14
ttkDesigner/app/superobj/superwidget.py

@ -27,13 +27,13 @@ import TermTk as ttk
import ttkDesigner.app.superobj as so
class SuperWidget(ttk.TTkWidget):
def __init__(self, wid, weModified, widgetSelected, *args, **kwargs):
def __init__(self, wid, weModified, thingSelected, *args, **kwargs):
self.weModified = weModified
self.widgetSelected = widgetSelected
self.thingSelected = thingSelected
self._wid = wid
self._wid.move(*kwargs['pos'])
self._wid._canvas.show()
self._superLayout = so.SuperLayout(lay=self._wid.layout(), weModified=self.weModified, widgetSelected=self.widgetSelected,)
self._superLayout = so.SuperLayout(lay=self._wid.layout(), weModified=self.weModified, thingSelected=self.thingSelected,)
self._superRootWidget = kwargs.get('superRootWidget',False)
kwargs['layout'] = ttk.TTkGridLayout()
kwargs['layout'].addWidget(self._superLayout)
@ -94,9 +94,7 @@ class SuperWidget(ttk.TTkWidget):
else:
ttk.TTkLog.warn("Type not Recognised")
return ret
children = []
for w in self.layout().children():
children.append(w.widget().dumpDict())
params = {}
for cc in reversed(type(wid).__mro__):
# if hasattr(cc,'_ttkProperties'):
@ -126,7 +124,7 @@ class SuperWidget(ttk.TTkWidget):
ret = {
'class' : wid.__class__.__name__,
'params' : params,
'children': children
'layout': self._superLayout.dumpDict()
}
return ret
@ -149,7 +147,7 @@ class SuperWidget(ttk.TTkWidget):
def mouseReleaseEvent(self, evt) -> bool:
self.pushSuperControlWidget()
self.widgetSelected.emit(self._wid,self)
self.thingSelected.emit(self._wid,self)
return True
def mouseDragEvent(self, evt) -> bool:

65
ttkDesigner/app/treeinspector.py

@ -22,7 +22,8 @@
import TermTk as ttk
from .windoweditor import SuperWidget
from .superobj.superwidget import SuperWidget
from .superobj.superlayout import SuperLayout
class _TTkTomTreeWidgetItem(ttk.TTkTreeWidgetItem):
__slots__ = ('_tomWidget','_tomSuperWidget')
@ -38,7 +39,7 @@ class _TTkTomTreeWidgetItem(ttk.TTkTreeWidgetItem):
class TreeInspector(ttk.TTkGridLayout):
def __init__(self, windowEditor, *args, **kwargs):
super().__init__(*args, **kwargs)
self.widgetSelected = ttk.pyTTkSignal(ttk.TTkWidget, ttk.TTkWidget)
self.thingSelected = ttk.pyTTkSignal(ttk.TTkWidget, ttk.TTkWidget)
self._windowEditor = windowEditor
self._tomTree = ttk.TTkTree()
@ -48,7 +49,7 @@ class TreeInspector(ttk.TTkGridLayout):
@ttk.pyTTkSlot(_TTkTomTreeWidgetItem, int)
def _itemSelected(wi, _):
if tomw := wi.tomWidget():
self.widgetSelected.emit(tomw, wi.tomSuperWidget())
self.thingSelected.emit(tomw, wi.tomSuperWidget())
self._tomTree.itemClicked.connect(_itemSelected)
@ -69,14 +70,14 @@ class TreeInspector(ttk.TTkGridLayout):
# # TTkHelper._rootWidget.setEnabled(True)
# # TTkHelper._rootWidget._input.inputEvent.connect(TTkHelper._rootWidget._processInput)
# ttk.TTkHelper._rootWidget._input.inputEvent.disconnect(self._processInput)
# widget = TTkTomInspector._findWidget(mevt,ttk.TTkHelper._rootWidget.rootLayout())
# ttk.TTkLog.debug(f"{widget=}")
# if widget:
# self._makeDetail(widget)
# thing = TTkTomInspector._findWidget(mevt,ttk.TTkHelper._rootWidget.rootLayout())
# ttk.TTkLog.debug(f"{thing=}")
# if thing:
# self._makeDetail(thing)
# else:
# self._detail = ttk.TTkFrame(title=f"None")
# self._splitter.replaceWidget(1,self._detail)
# self._refresh(widget)
# self._refresh(thing)
@ttk.pyTTkSlot()
def _btnPickCb(self):
@ -84,33 +85,47 @@ class TreeInspector(ttk.TTkGridLayout):
pass
@ttk.pyTTkSlot()
def refresh(self, widget=None):
def refresh(self, thing=None):
self._tomTree.clear()
self._tomTree.addTopLevelItem(TreeInspector._getTomTreeItem(self._windowEditor.getTTk().widgetItem()))
@staticmethod
def _getTomTreeItem(layoutItem, widSelected=None):
if layoutItem.layoutItemType == ttk.TTkK.WidgetItem:
superWidget = widget = layoutItem.widget()
if type(superWidget) is SuperWidget:
widget = widget._wid
expanded = True # ttk.TTkHelper.isParent(widSelected,widget) if widSelected else False
top = _TTkTomTreeWidgetItem([
widget._name, widget.__class__.__name__,
str(widget.isVisible()),
widget.layout().__class__.__name__],
tomWidget=widget,
tomSuperWidget=superWidget,
expanded=expanded)
if issubclass(type(superWidget), SuperWidget):
for c in superWidget._superLayout.layout().children():
superThing = thing = layoutItem.widget()
if issubclass(type(superThing), SuperWidget):
thing = thing._wid
elif issubclass(type(superThing), SuperLayout):
thing = thing._lay
expanded = True # ttk.TTkHelper.isParent(widSelected,thing) if widSelected else False
if issubclass(type(superThing), SuperWidget):
top = _TTkTomTreeWidgetItem([
thing._name, thing.__class__.__name__,
str(thing.isVisible()),
thing.layout().__class__.__name__],
tomWidget=thing,
tomSuperWidget=superThing,
expanded=expanded)
elif issubclass(type(superThing), SuperLayout):
top = _TTkTomTreeWidgetItem([
'Layout', thing.__class__.__name__,
'',
thing.__class__.__name__],
tomWidget=thing,
tomSuperWidget=superThing,
expanded=expanded)
if issubclass(type(superThing), SuperWidget):
for c in superThing._superLayout.layout().children():
top.addChild(TreeInspector._getTomTreeItem(c,widSelected))
elif issubclass(type(superThing), SuperLayout):
for c in superThing.layout().children():
top.addChild(TreeInspector._getTomTreeItem(c,widSelected))
else:
for c in superWidget.layout().children():
for c in superThing.layout().children():
top.addChild(TreeInspector._getTomTreeItem(c,widSelected))
# for c in widget.rootLayout().children():
# if c == widget.layout(): continue
# for c in thing.rootLayout().children():
# if c == thing.layout(): continue
# if c.layoutItemType == ttk.TTkK.LayoutItem:
# top.addChild(tc:=_TTkTomTreeWidgetItem(["layout (Other)", c.__class__.__name__, ""]))
# for cc in c.children():

4
ttkDesigner/app/windoweditor.py

@ -32,10 +32,10 @@ import TermTk as ttk
class WindowEditorView(ttk.TTkAbstractScrollView):
def __init__(self, *args, **kwargs):
self.weModified = ttk.pyTTkSignal()
self.widgetSelected = ttk.pyTTkSignal(ttk.TTkWidget, ttk.TTkWidget)
self.thingSelected = ttk.pyTTkSignal(ttk.TTkWidget, ttk.TTkWidget)
super().__init__(*args, **kwargs)
self.viewChanged.connect(self._viewChangedHandler)
self._ttk = SuperWidget(wid=ttk.TTkWidget(name = 'TTk'), weModified=self.weModified, widgetSelected=self.widgetSelected, pos=(4,2), size=(self.width()-8,self.height()-4), superRootWidget=True)
self._ttk = SuperWidget(wid=ttk.TTkWidget(name = 'TTk'), weModified=self.weModified, thingSelected=self.thingSelected, pos=(4,2), size=(self.width()-8,self.height()-4), superRootWidget=True)
self.layout().addWidget(self._ttk)
def getTTk(self):

Loading…
Cancel
Save