forked from BBN-Q/PyQLab
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEnamlHelpers.enaml
More file actions
140 lines (127 loc) · 4.41 KB
/
EnamlHelpers.enaml
File metadata and controls
140 lines (127 loc) · 4.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
"""
Reusable widgets for handling lists and dictionaries
"""
from traits.api import HasTraits, Dict, TraitDictObject, List, Any, on_trait_change, WeakRef, Instance, Str, Function
from enaml.widgets.api import Window, Container, Stack, StackItem, ListControl, ListItem, PushButton, Form, Label, Field, ComboBox
from enaml.stdlib.mapped_view import MappedView
from enaml.core.api import Looper, Include
from enaml.layout.api import hbox, vbox, spacer
class DictManager(HasTraits):
"""
Helper to manage a list next to a set of stack items
"""
listItems = List
itemDict = Instance(TraitDictObject)
displayFilter = Function(lambda x : True)
def __init__(self, **kwargs):
super(DictManager, self).__init__(**kwargs)
dictName = self.itemDict.object().get().keys()[[self.itemDict==item for item in self.itemDict.object().get().values()].index(True)]
self.itemDict.object().on_trait_change(self.update_lists, dictName+'_items')
self.itemDict.object().on_trait_change(self.name_change, dictName+'.name')
for item in self.itemDict.values():
if self.displayFilter(item):
self.listItems.append(MyListItem(myItem=item))
def name_change(self, obj, name, old, new):
"""
Since the dictionary is keyed off item names we need to change the dictionary
"""
self.itemDict[new] = self.itemDict.pop(old)
def update_lists(self, obj, name, new):
#We do this to also catch name changes where the item name is different to new.removed.keys()
if new.removed:
#List current dictionary names
goodNames = self.itemDict.keys()
#Find all items in list that are no longer there
for ct, item in enumerate(reversed(self.listItems)):
if item.text not in goodNames:
del self.listItems[-(ct+1)]
for item in new.added.values():
if self.displayFilter(item):
self.listItems.append(MyListItem(myItem=item))
enamldef MyListItem(ListItem):
attr myItem
text := myItem.name
editable = True
checked := myItem.enabled
checkable = True
enamldef DictManagerView(Container):
attr dictManager = DictManager(itemDict=myDict, displayFilter=displayFilter)
attr displayFilter = lambda x : True
attr myDict
attr addDialog
attr modelName
attr viewMap
attr viewkwargs = {}
constraints = [
hbox(vbox(myList, hbox(addButton, deleteButton, debugButton, spacer)), mapViewCont),
myList.width <= 300]
ListControl: myList:
hug_width = 'medium'
Include: listInc:
objects << sorted([item for item in dictManager.listItems], key=lambda x : x.text.lower())
Container: mapViewCont:
hug_width = 'medium'
MappedView:
#Hacky thing to catch deletions
model << dictManager.itemDict[myList.list_items[myList.current_row].text] \
if (myList.current_row < len(myList.list_items) and len(myList.list_items) > 0) else None
modelkey = modelName
typemap = viewMap
kwargs = viewkwargs
PushButton: addButton:
text = 'Add'
clicked ::
addDialog(root_object(), dictManager.itemDict)
PushButton: deleteButton:
text = 'Delete'
clicked ::
myDict.pop(myList.list_items[myList.current_row].text)
PushButton: debugButton:
text = 'Debug'
clicked ::
import pdb; pdb.set_trace()
enamldef AddDialog(Window):
attr itemDict
attr newClassList
attr objText
attr kwargs : dict = {}
title = 'Add a new {}...'.format(objText)
modality = 'window_modal'
Container:
constraints = [vbox(myForm, hbox(spacer, okButton, cancelButton))]
Form: myForm:
Label:
text = 'New Name'
Field: newName:
text = 'New'+objText
Label: modelChoiceLabel:
text = 'New {} Model'.format(objText)
ComboBox: modelChoice:
index = 0
items = [f.__name__ for f in newClassList]
PushButton: okButton:
text = 'OK'
clicked ::
itemDict.update({newName.text:newClassList[modelChoice.index](name=newName.text, **kwargs)})
close()
PushButton: cancelButton:
text = 'Cancel'
clicked ::
close()
#A combo box connected to a Enum trait
enamldef EnumComboBox(ComboBox):
attr myObj
attr traitName
attr itemList = list(myObj.trait(traitName).handler.values)
items = itemList
index << itemList.index(getattr(myObj, traitName))
index :: setattr(myObj, traitName, itemList[index])
tool_tip = myObj.trait(traitName).desc
enamldef EnumFloatComboBox(ComboBox):
attr myObj
attr traitName
attr itemList = [str(item) for item in myObj.trait(traitName).handler.values]
items = itemList
index << itemList.index(str(getattr(myObj, traitName)))
index :: setattr(myObj, traitName, float(itemList[index]))
tool_tip = myObj.trait(traitName).desc