plus de décalage entre exécution des noteon/off et leur log.
[minwii.git] / src / pgu / gui / select.py
1 """
2 """
3
4 import traceback
5
6 from const import *
7 from button import Button
8 from basic import Label, Image
9 from table import Table
10
11 class Select(Table):
12 """A select input.
13
14 <pre>Select(value=None)</pre>
15
16 <dl>
17 <dt>value<dd>initial value
18 </dl>
19
20 <strong>Example</strong>
21 <code>
22 w = Select(value="goats")
23 w.add("Cats","cats")
24 w.add("Goats","goats")
25 w.add("Dogs","Dogs")
26
27 w.value = 'dogs' #changes the value from goats to dogs
28 </code>
29
30 """
31
32 # The drop-down arrow button for the selection widget
33 top_arrow = None
34 # A button displaying the currently selected item
35 top_selection = None
36 # The first option added to the selector
37 firstOption = None
38 # The PGU table of options
39 options = None
40
41 def __init__(self,value=None,**params):
42 params.setdefault('cls','select')
43 Table.__init__(self,**params)
44
45 label = Label(" ",cls=self.cls+".option.label")
46 self.top_selected = Button(label, cls=self.cls+".selected")
47 Table.add(self,self.top_selected) #,hexpand=1,vexpand=1)#,0,0)
48
49 self.top_arrow = Button(Image(self.style.arrow), cls=self.cls+".arrow")
50 Table.add(self,self.top_arrow) #,hexpand=1,vexpand=1) #,1,0)
51
52 self.options = Table(cls=self.cls+".options")
53 self.options.connect(BLUR,self._close,None)
54 self.options.name = "pulldown-table"
55
56 self.values = []
57 self.value = value
58
59 def resize(self,width=None,height=None):
60 max_w,max_h = 0,0
61 for w in self.options.widgets:
62 w.rect.w,w.rect.h = w.resize()
63 max_w,max_h = max(max_w,w.rect.w),max(max_h,w.rect.h)
64
65 #xt,xr,xb,xl = self.top_selected.getspacing()
66 self.top_selected.style.width = max_w #+ xl + xr
67 self.top_selected.style.height = max_h #+ xt + xb
68
69 self.top_arrow.connect(CLICK,self._open,None)
70 self.top_selected.connect(CLICK,self._open,None)
71
72 w,h = Table.resize(self,width,height)
73
74 self.options.style.width = w
75 #HACK: sort of, but not a big one..
76 self.options.resize()
77
78 return w,h
79
80 def _open(self,value):
81 opts = self.options
82
83 opts.rect.w, opts.rect.h = opts.resize()
84
85 # y = self.rect.y
86 # c = self.container
87 # while hasattr(c, 'container'):
88 # y += c.rect.y
89 # if (not c.container):
90 # break
91 # c = c.container
92
93 # if y + self.rect.h + opts.rect.h <= c.rect.h: #down
94 # dy = self.rect.y + self.rect.h
95 # else: #up
96 # dy = self.rect.y - self.rect.h
97
98 opts.rect.w, opts.rect.h = opts.resize()
99
100 # TODO - make sure there is enough space to open down
101 # ...
102 yp = self.rect.bottom-1
103
104 self.container.open(opts, self.rect.x, yp)
105 self.firstOption.focus()
106
107 # TODO - this is a hack
108 for opt in self.options.widgets:
109 opt.repaint()
110
111 def _close(self,value):
112 self.options.close()
113 self.top_selected.focus()
114
115 def _setvalue(self,value):
116 self.value = value._value
117 if hasattr(self,'container'):
118 #self.chsize()
119 #HACK: improper use of resize()
120 #self.resize() #to recenter the new value, etc.
121 pass
122 # #self._resize()
123
124 self._close(None)
125 #self.repaint() #this will happen anyways
126
127
128
129 def __setattr__(self,k,v):
130 mywidget = None
131 if k == 'value':
132 for w in self.values:
133 if w._value == v:
134 mywidget = w
135 _v = self.__dict__.get(k,NOATTR)
136 self.__dict__[k]=v
137 if k == 'value' and _v != NOATTR and _v != v:
138 self.send(CHANGE)
139 self.repaint()
140 if k == 'value':
141 if not mywidget:
142 mywidget = Label(" ",cls=self.cls+".option.label")
143 self.top_selected.value = mywidget
144
145 def add(self,w,value=None):
146 """Add a widget, value item to the Select.
147
148 <pre>Select.add(widget,value=None)</pre>
149
150 <dl>
151 <dt>widget<dd>Widget or string to represent the item
152 <dt>value<dd>value for this item
153 </dl>
154
155 <strong>Example</strong>
156 <code>
157 w = Select()
158 w.add("Goat") #adds a Label
159 w.add("Goat","goat") #adds a Label with the value goat
160 w.add(gui.Label("Cuzco"),"goat") #adds a Label with value goat
161 </code>
162 """
163
164 if type(w) == str: w = Label(w,cls=self.cls+".option.label")
165
166 w.style.align = -1
167 btn = Button(w,cls=self.cls+".option")
168 btn.connect(CLICK,self._setvalue,w)
169
170 self.options.tr()
171 self.options.add(btn)
172
173 if (not self.firstOption):
174 self.firstOption = btn
175
176 if value != None: w._value = value
177 else: w._value = w
178 if self.value == w._value:
179 self.top_selected.value = w
180 self.values.append(w)