3 # Display a table, with per-item actions:
5 # A1 | A2 | A3 | .... | AN
6 # B1 | B2 | B3 | .... | BN
7 # C1 | C2 | C3 | .... | CN
8 # .. | .. | .. | .... | ..
9 # Z1 | Z2 | Z3 | .... | ZN
11 # Not all columns need to have the same length.
12 # The data structure is a list of columns;
13 # each column is a list of items.
14 # Each item is a pair of a string and an action procedure.
15 # The first item may be a column title.
19 from stdwinevents
import *
21 def open(title
, data
): # Public function to open a table window
23 # Set geometry parameters (one day, these may be changeable)
25 margin
= stdwin
.textwidth(' ')
26 lineheight
= stdwin
.lineheight()
28 # Geometry calculations
36 if rows
> maxrows
: maxrows
= rows
38 width
= colwidth(coldata
) + margin
39 totwidth
= totwidth
+ width
40 colstarts
.append(totwidth
)
42 # Calculate document and window height
44 docwidth
, docheight
= totwidth
, maxrows
*lineheight
45 winwidth
, winheight
= docwidth
, docheight
46 if winwidth
> stdwin
.textwidth('n')*100: winwidth
= 0
47 if winheight
> stdwin
.lineheight()*30: winheight
= 0
51 stdwin
.setdefwinsize(winwidth
, winheight
)
54 # Set properties and override methods
58 w
.lineheight
= lineheight
59 w
.colstarts
= colstarts
62 w
.selection
= (-1, -1)
63 w
.lastselection
= (-1, -1)
65 w
.setdocsize(docwidth
, docheight
)
74 def update(w
, data
): # Change the data
78 hidesel(w
, w
.begindrawing())
80 # Get old geometry parameters
83 lineheight
= w
.lineheight
85 # Geometry calculations
93 if rows
> maxrows
: maxrows
= rows
95 width
= colwidth(coldata
) + margin
96 totwidth
= totwidth
+ width
97 colstarts
.append(totwidth
)
99 # Calculate document and window height
101 docwidth
, docheight
= totwidth
, maxrows
*lineheight
103 # Set changed properties and change window size
106 w
.colstarts
= colstarts
107 w
.totwidth
= totwidth
109 w
.change((0, 0), (10000, 10000))
110 w
.setdocsize(docwidth
, docheight
)
111 w
.change((0, 0), (docwidth
, docheight
))
113 # Show selection, or forget it if out of range
115 showsel(w
, w
.begindrawing())
116 if not w
.selshown
: w
.selection
= (-1, -1)
118 def colwidth(coldata
): # Subroutine to calculate column width
120 for string
, action
in coldata
:
121 width
= stdwin
.textwidth(string
)
122 if width
> maxwidth
: maxwidth
= width
125 def draw(w
, ((left
, top
), (right
, bottom
))): # Draw method
126 ileft
= whichcol(w
, left
)
127 iright
= whichcol(w
, right
-1) + 1
128 if iright
> len(w
.data
): iright
= len(w
.data
)
129 itop
= divmod(top
, w
.lineheight
)[0]
130 if itop
< 0: itop
= 0
131 ibottom
, remainder
= divmod(bottom
, w
.lineheight
)
132 if remainder
: ibottom
= ibottom
+ 1
134 if ileft
<= w
.selection
[0] < iright
:
135 if itop
<= w
.selection
[1] < ibottom
:
137 d
.erase((left
, top
), (right
, bottom
))
138 for i
in range(ileft
, iright
):
141 if ibottom
< jbottom
: jbottom
= ibottom
143 v
= itop
* w
.lineheight
144 for j
in range(itop
, jbottom
):
145 string
, action
= col
[j
]
146 d
.text((h
, v
), string
)
150 def mup(w
, detail
): # Mouse up method
151 (h
, v
), nclicks
, button
, mask
= detail
152 icol
= whichcol(w
, h
)
153 if 0 <= icol
< len(w
.data
):
154 irow
= divmod(v
, w
.lineheight
)[0]
156 if 0 <= irow
< len(col
):
157 string
, action
= col
[irow
]
158 action(w
, string
, (icol
, irow
), detail
)
160 def whichcol(w
, h
): # Return column number (may be >= len(w.data))
161 for icol
in range(0, len(w
.data
)):
162 if h
< w
.colstarts
[icol
+1]:
171 elif type == WC_RIGHT
:
173 elif type == WC_DOWN
:
177 icol
, irow
= w
.lastselection
178 icol
= icol
+ incr
[0]
179 if icol
< 0: icol
= len(w
.data
)-1
180 if icol
>= len(w
.data
): icol
= 0
181 if 0 <= icol
< len(w
.data
):
182 irow
= irow
+ incr
[1]
183 if irow
< 0: irow
= len(w
.data
[icol
]) - 1
184 if irow
>= len(w
.data
[icol
]): irow
= 0
187 if 0 <= icol
< len(w
.data
) and 0 <= irow
< len(w
.data
[icol
]):
188 w
.lastselection
= icol
, irow
189 string
, action
= w
.data
[icol
][irow
]
190 detail
= (0, 0), 1, 1, 1
191 action(w
, string
, (icol
, irow
), detail
)
194 # Selection management
195 # TO DO: allow multiple selected entries
197 def select(w
, selection
): # Public function to set the item selection
200 w
.selection
= selection
202 if w
.selshown
: lastselection
= selection
204 def hidesel(w
, d
): # Hide the selection, if shown
205 if w
.selshown
: invertsel(w
, d
)
207 def showsel(w
, d
): # Show the selection, if hidden
208 if not w
.selshown
: invertsel(w
, d
)
210 def invertsel(w
, d
): # Invert the selection, if valid
211 icol
, irow
= w
.selection
212 if 0 <= icol
< len(w
.data
) and 0 <= irow
< len(w
.data
[icol
]):
213 left
= w
.colstarts
[icol
]
214 right
= w
.colstarts
[icol
+1]
215 top
= irow
* w
.lineheight
216 bottom
= (irow
+1) * w
.lineheight
217 d
.invert((left
, top
), (right
, bottom
))
218 w
.selshown
= (not w
.selshown
)
223 def demo_action(w
, string
, (icol
, irow
), detail
): # Action function for demo
224 select(w
, (irow
, icol
))
226 def demo(): # Demonstration
227 da
= demo_action
# shorthand
228 col0
= [('a1', da
), ('bbb1', da
), ('c1', da
)]
229 col1
= [('a2', da
), ('bbb2', da
)]
230 col2
= [('a3', da
), ('b3', da
), ('c3', da
), ('d4', da
), ('d5', da
)]
232 for i
in range(1, 31): col3
.append(('xxx' + `i`
, da
))
233 data
= [col0
, col1
, col2
, col3
]
234 w
= open('tablewin.demo', data
)