Skip to content
Newer
Older
100644 404 lines (333 sloc) 16.9 KB
c365d21 more gchart update
lkcl authored Aug 30, 2009
1
28cb27e more gchart update
lkcl authored Aug 30, 2009
2 from pyjamas import DOM
3 from pyjamas import Window
4
c365d21 more gchart update
lkcl authored Aug 30, 2009
5 from pyjamas.ui import Event
6 from pyjamas.ui.Button import Button
7 from pyjamas.ui.DialogBox import DialogBox
8 from pyjamas.ui.DockPanel import DockPanel
9 from pyjamas.ui.FlexTable import FlexTable
b0bca3c more gchart update
lkcl authored Aug 30, 2009
10 from pyjamas.ui import HasHorizontalAlignment
c365d21 more gchart update
lkcl authored Aug 30, 2009
11 from pyjamas.ui.HorizontalPanel import HorizontalPanel
12 from pyjamas.ui.ListBox import ListBox
13 from pyjamas.ui.VerticalPanel import VerticalPanel
14 from pyjamas.chart.GChart import GChart
15 from pyjamas.chart import AnnotationLocation
16 from pyjamas.chart import SymbolType
17 from pyjamas.chart import TouchedPointUpdateOption
18
19 LABEL_COL = 0; # for the label/object pairs
20 OBJECT_COL = 1; # associated with the property
21 N_COLS = 2; # editing form
22
23 N_SLICES = 5
24
25 """*
26 * This example displays a pie chart that, when you click on any slice,
27 * opens a dialog that lets you modify the color, shading pattern, and
28 * size of of that slice. That dialog also contains "Prev Slice" and "Next
29 * Slice" buttons that, by invoking GChart's <tt>touch</tt> method,
30 * programmatically emulate the user sequentially "touching" (selecting)
31 * slices with their mouse.
32 *
33 * <p>
34 *
35 * The slice properties dialog in this example is an ordinary GWT modal
36 * dialog (a <tt>DialogBox</tt> with modal=True, autoHide=True). It self.gets
37 * GChart to inform it of click events on the chart by implementing the
38 * standard GWT <tt>ClickHandler</tt> interface, and then passing
39 * itself to GChart's <tt>addClickHandler</tt> method. The dialog's
40 * <tt>onClick</tt> method shows itself (via <tt>DialogBox.show</tt>)
41 * and then uses GChart's <tt>getTouchedPoint</tt> method to self.get a
42 * reference to the clicked-on slice that it uses to load that slice's
43 * properties into the form. As the user makes changes via the form,
44 * they are copied back into the chart and the chart's <tt>update</tt>
45 * method is invoked to immediately show the changes on the chart.
46 * <p>
47 *
48 * GChart's "currently touched point" (available via
49 * <tt>getTouchedPoint</tt>) ordinarily moves in lock-step with current
50 * mouse location, and thus falls short of a True point selection
51 * capability. This example works around this limitation by exploiting
52 * the fact that a GWT modal dialog "eats" all mouse events while it is
53 * open. So, when the modal dialog is opened, the mouse location seen by
54 * GChart, and hence the "currently touched" point is frozen. This lets
55 * us use GChart's currently touched point as if it were the "selected"
56 * point in this example.
57 *
58 """
59
60 """
61 * A helper class to facilitate property editing via drop-down
62 * lists in this example (there's nothing GChart-specific here):
63 """
64 class ObjectSelectorDropdownList(ListBox):
65
66 def __init__(self, labelObjectPairs):
67 ListBox.__init__(self)
68 self.labelObjectPairs = labelObjectPairs
69 self.setVisibleItemCount(1); # makes it a drop-down list
70 # add each label as an item on the drop-down list
71 for i in range(len(labelObjectPairs)):
72 self.addItem( labelObjectPairs[i][LABEL_COL])
73
74 # returns object at given index
75 def getObject(self, index):
76 result = self.labelObjectPairs[index][OBJECT_COL]
77 return result
78
79
80 # returns the currently selected object in the drop-down list
81 def getSelectedObject(self):
5c2808e more gchart update
lkcl authored Aug 30, 2009
82 result = self.getObject(self.getSelectedIndex())
c365d21 more gchart update
lkcl authored Aug 30, 2009
83 return result
84
85
86 # makes given object the selected one (assumes it's on list--once)
87 def setSelectedObject(self, selectedObject):
88 for i in range(len(self.labelObjectPairs)):
5c2808e more gchart update
lkcl authored Aug 30, 2009
89 if selectedObject == self.labelObjectPairs[i][OBJECT_COL]:
c365d21 more gchart update
lkcl authored Aug 30, 2009
90 self.setSelectedIndex(i)
91 return
92
93
94 raise IllegalArgumentException(
95 "selectedObject specified was not found on the labelObjectPairs list.")
96
97
98
99 # number of label, object pairs
100 def getNObjects(self):
101 return len(self.labelObjectPairs)
102
103
104 # class ObjectSelectorDropdownList
105 #
106 # holds color information associated with color selection drop-down
107 class ColorSpec:
108 def __init__(self, backgroundColor, borderColor):
109 self.backgroundColor = backgroundColor
110 self.borderColor =borderColor
111
112
113
114 # the modal dialog that pops up when they click on a slice to edit it
f1b48a5 more gchart update
lkcl authored Aug 30, 2009
115 class SliceEditor(DialogBox):
c365d21 more gchart update
lkcl authored Aug 30, 2009
116 def __init__(self, chart):
117 """ DialogBox CSS Style self.settings used with this example for reference:
118
119 Note: These simplified CSS styles make the dialog's title bar behave a
120 little quirkily in IE6 when dragging. For more sophisticated CSS that
121 fixes this problem (and also provides a more professional look) see the
122 CSS tab of the DialogBox example in the GWT <a href="xxx"> Showcase of
123 Features</a> (I just didn't want to copy 5 pages of obscure DialogBox
124 CSS into what is after all a Client-side GChart example).
125
126 .gwt-DialogBox .Caption {
127 font-size: 18
128 color: #eef
129 background: #00f repeat-x 0px -2003px
130 padding: 4px 4px 4px 8px
131 cursor: default
132 border-bottom: 2px solid #008
133 border-top: 3px solid #448
134
135
136 .gwt-DialogBox .dialogContent {
137 border: 1px solid #008
138 background: #ddd
139 padding: 3px
140
141
142 """
143 DialogBox.__init__(self, autoHide=True, modal=True)
144 self.chart = chart
145 self.isFirstTime = True
146 mainPanel = VerticalPanel()
147 propertyForm = FlexTable()
148 commandBar = DockPanel()
149 sliceSwitcher = HorizontalPanel()
f1b48a5 more gchart update
lkcl authored Aug 30, 2009
150 self.prevSlice = Button("&lt;Prev Slice", self)
151 self.nextSlice = Button("Next Slice&gt;", self)
152 self.closeButton = Button("Close", self)
c365d21 more gchart update
lkcl authored Aug 30, 2009
153
154 self.chart.colorSelector.addChangeListener(self)
155 self.chart.sliceSizeSelector.addChangeListener(self)
156 self.chart.shadingSelector.addChangeListener(self)
157
f1b48a5 more gchart update
lkcl authored Aug 30, 2009
158 #self.prevSlice.addClickListener(self)
159 #self.nextSlice.addClickListener(self)
160 #self.closeButton.addClickListener(self)
161
c365d21 more gchart update
lkcl authored Aug 30, 2009
162 # slice properties table (slice color, shading and size)
5c2808e more gchart update
lkcl authored Aug 30, 2009
163 propertyForm.setSize(3, 2)
c365d21 more gchart update
lkcl authored Aug 30, 2009
164 propertyForm.setText( 0, 0, "Color:")
b7f11a0 more gchart update
lkcl authored Aug 30, 2009
165 propertyForm.setWidget(0, 1, self.chart.colorSelector)
c365d21 more gchart update
lkcl authored Aug 30, 2009
166 propertyForm.setText( 1, 0, "Shading Pattern:")
b7f11a0 more gchart update
lkcl authored Aug 30, 2009
167 propertyForm.setWidget(1, 1, self.chart.shadingSelector)
c365d21 more gchart update
lkcl authored Aug 30, 2009
168 propertyForm.setText( 2, 0, "Slice Size:")
b7f11a0 more gchart update
lkcl authored Aug 30, 2009
169 propertyForm.setWidget(2, 1, self.chart.sliceSizeSelector)
c365d21 more gchart update
lkcl authored Aug 30, 2009
170 # add additional properties here, if desired
171
172 # buttons for changing the selected slice from the form
b7f11a0 more gchart update
lkcl authored Aug 30, 2009
173 sliceSwitcher.add(self.prevSlice)
174 sliceSwitcher.add(self.nextSlice)
c365d21 more gchart update
lkcl authored Aug 30, 2009
175
176 commandBar.add(sliceSwitcher, DockPanel.WEST)
e028da3 more gchart update
lkcl authored Aug 30, 2009
177 commandBar.add(self.closeButton, DockPanel.EAST)
b7f11a0 more gchart update
lkcl authored Aug 30, 2009
178 commandBar.setCellHorizontalAlignment(self.closeButton,
c365d21 more gchart update
lkcl authored Aug 30, 2009
179 HasHorizontalAlignment.ALIGN_RIGHT)
180 commandBar.setWidth("100%"); # pushes close button to right edge
181
182 # create main form and place it in DialogBox
183 mainPanel.add(propertyForm)
184 mainPanel.add(commandBar)
5c2808e more gchart update
lkcl authored Aug 30, 2009
185 self.setWidget(mainPanel); # add the DialogBox' single, defining, widget
c365d21 more gchart update
lkcl authored Aug 30, 2009
186
c4e7f66 more gchart update
lkcl authored Aug 30, 2009
187 def onChange(self, sender):
8286de3 more gchart update
lkcl authored Aug 30, 2009
188 self.copyFormPropertiesIntoChart(self.chart.getTouchedPoint())
c4e7f66 more gchart update
lkcl authored Aug 30, 2009
189 # Changes in slice size can place a different, or no, slice under
190 # GChart's "current mouse position". Such chart changes "underneath the
191 # mouse" would normally result in a change in the touched point; the
192 # TOUCHED_POINT_LOCKED update option keeps that from happening.
193 self.chart.update(TouchedPointUpdateOption.TOUCHED_POINT_LOCKED)
194
c365d21 more gchart update
lkcl authored Aug 30, 2009
195 # loads properties associated with point/slice into form
196 def copyChartPropertiesIntoForm(self, p):
197 # dialog title bar caption:
5c2808e more gchart update
lkcl authored Aug 30, 2009
198 self.setText("Slice %d Properties " % \
199 self.chart.getCurveIndex(p.getParent()))
2ac1ab6 more gchart update
lkcl authored Aug 30, 2009
200 self.chart.colorSelector.setSelectedObject(
201 self.getColorSpec( p.getParent().getSymbol().getBackgroundColor(),
202 p.getParent().getSymbol().getBorderColor()))
203 self.chart.shadingSelector.setSelectedObject(
c365d21 more gchart update
lkcl authored Aug 30, 2009
204 p.getParent().getSymbol().getSymbolType())
5c2808e more gchart update
lkcl authored Aug 30, 2009
205 sliceSize = round(100*p.getParent().getSymbol().getPieSliceSize())
2ac1ab6 more gchart update
lkcl authored Aug 30, 2009
206 self.chart.sliceSizeSelector.setSelectedObject( int(sliceSize) )
c365d21 more gchart update
lkcl authored Aug 30, 2009
207
208 # saves current form self.settings into associated point/slice of chart
209 def copyFormPropertiesIntoChart(self, p):
210 p.getParent().getSymbol().setBackgroundColor(
2ac1ab6 more gchart update
lkcl authored Aug 30, 2009
211 self.chart.colorSelector.getSelectedObject().backgroundColor)
c365d21 more gchart update
lkcl authored Aug 30, 2009
212 p.getParent().getSymbol().setBorderColor(
2ac1ab6 more gchart update
lkcl authored Aug 30, 2009
213 self.chart.colorSelector.getSelectedObject().borderColor)
c365d21 more gchart update
lkcl authored Aug 30, 2009
214
215 # selection flips border and background colors
216 p.getParent().getSymbol().setHoverSelectionBorderColor(
2ac1ab6 more gchart update
lkcl authored Aug 30, 2009
217 self.chart.colorSelector.getSelectedObject().backgroundColor)
c365d21 more gchart update
lkcl authored Aug 30, 2009
218 p.getParent().getSymbol().setHoverSelectionBackgroundColor(
2ac1ab6 more gchart update
lkcl authored Aug 30, 2009
219 self.chart.colorSelector.getSelectedObject().borderColor)
c365d21 more gchart update
lkcl authored Aug 30, 2009
220 p.getParent().getSymbol().setSymbolType(
c153ec6 more gchart update
lkcl authored Aug 30, 2009
221 self.chart.shadingSelector.getSelectedObject())
2ac1ab6 more gchart update
lkcl authored Aug 30, 2009
222 sliceSize = int(self.chart.sliceSizeSelector.getSelectedObject())
c365d21 more gchart update
lkcl authored Aug 30, 2009
223 p.getParent().getSymbol().setPieSliceSize(sliceSize/100.)
224
225
226 # Retrieves an existing ColorSpec object reference, given its colors
227 def getColorSpec(self, backgroundColor, borderColor):
5c2808e more gchart update
lkcl authored Aug 30, 2009
228 for i in range(self.chart.colorSelector.getNObjects()):
c365d21 more gchart update
lkcl authored Aug 30, 2009
229 cs = self.chart.colorSelector.getObject(i)
64eff55 find * -name '*.py' | xargs sed -i -r 's,\s+$,,'
C Anthony Risinger authored May 14, 2012
230 if (backgroundColor == cs.backgroundColor and
5c2808e more gchart update
lkcl authored Aug 30, 2009
231 borderColor == cs.borderColor):
c365d21 more gchart update
lkcl authored Aug 30, 2009
232 return cs
233
234
235 raise IllegalArgumentException(
236 "Attempt to retrieve a non-existing color combination.")
237
238
28cb27e more gchart update
lkcl authored Aug 30, 2009
239 def onClick(self, sender):
a0fbe72 more gchart update
lkcl authored Aug 30, 2009
240 print "onClick", sender
241 if sender == self.prevSlice:
242 self.chart.onClickPrevSlice(sender)
243 elif sender == self.nextSlice:
244 self.chart.onClickNextSlice(sender)
245 elif sender == self.closeButton:
246 self.onClickClose(sender)
247 else:
248 self.onClickDefault(sender)
249
250 def onClickClose(self, event):
251 self.hide()
252 self.chart.touch(None); # clears any selected slice
253 self.chart.update(TouchedPointUpdateOption.TOUCHED_POINT_LOCKED)
254
255
256 def onClickDefault(self, sender):
c365d21 more gchart update
lkcl authored Aug 30, 2009
257 # don't shown property editor if they clicked on nothing
28cb27e more gchart update
lkcl authored Aug 30, 2009
258 if None == self.chart.getTouchedPoint():
c365d21 more gchart update
lkcl authored Aug 30, 2009
259 return
260
28cb27e more gchart update
lkcl authored Aug 30, 2009
261 event = DOM.eventGetCurrentEvent()
c365d21 more gchart update
lkcl authored Aug 30, 2009
262
263 # load properties of clicked-on slice into form
28cb27e more gchart update
lkcl authored Aug 30, 2009
264 self.copyChartPropertiesIntoForm(self.chart.getTouchedPoint())
265 if self.isFirstTime:
c365d21 more gchart update
lkcl authored Aug 30, 2009
266 # initially put upper left corner wherever they clicked...
267 self.setPopupPosition(
28cb27e more gchart update
lkcl authored Aug 30, 2009
268 Window.getScrollLeft()+ DOM.eventGetClientX(event),
269 Window.getScrollTop() + DOM.eventGetClientX(event))
c365d21 more gchart update
lkcl authored Aug 30, 2009
270 self.show()
28cb27e more gchart update
lkcl authored Aug 30, 2009
271 self.isFirstTime = False
c365d21 more gchart update
lkcl authored Aug 30, 2009
272
273 else:
274 # ...thereafter, just stay whereever they dragged it to
275 self.show()
276
277
278
279
280 class GChartExample20 (GChart):
281
282
283
284
285 # the single dialog box that self.gets used to edit any slice
286 def __init__(self):
1354dcc more gchart update
lkcl authored Aug 30, 2009
287 GChart.__init__(self)
c365d21 more gchart update
lkcl authored Aug 30, 2009
288
289 # labels/values for color selection drop-down list:
290 self.colorSelector = ObjectSelectorDropdownList( \
291 [["Red", ColorSpec("red", "#F88")],
292 ["Fuchsia", ColorSpec("#F0F", "#F8F")],
293 ["Lime", ColorSpec("#0F0", "#8F8")],
294 ["Blue", ColorSpec("#00F", "#88F")],
295 ["Aqua", ColorSpec("#0FF", "#8FF")],
296 ["Maroon", ColorSpec("#800", "#C88")],
297 ["Purple", ColorSpec("#808", "#C8C")],
298 ["Green", ColorSpec("#080", "#8C8")],
299 ["Olive", ColorSpec("#880", "#CC8")],
300 ["Navy", ColorSpec("#008", "#88C")],
301 ["Teal", ColorSpec("#088", "#8CC")]])
302
303 # labels/values for slice shading pattern drop-down list
304 self.shadingSelector = ObjectSelectorDropdownList( \
305 [["Vertical shading", SymbolType.PIE_SLICE_VERTICAL_SHADING],
306 ["Horizontal shading", SymbolType.PIE_SLICE_HORIZONTAL_SHADING],
307 ["Optimal shading", SymbolType.PIE_SLICE_OPTIMAL_SHADING]])
308
309 # labels/values for pie slice size (as percentage) drop-down list
310 self.sliceSizeSelector = ObjectSelectorDropdownList([
9b5adf1 more gchart update
lkcl authored Aug 30, 2009
311 ["0%", int(0)],
312 ["5%", int(5)],
313 ["10%", int(10)],
314 ["15%", int(15)],
315 ["20%", int(20)],
316 ["25%", int(25)],
317 ["30%", int(30)],
318 ["35%", int(35)],
319 ["40%", int(40)],
320 ["45%", int(45)],
321 ["50%", int(50)],
322 ["55%", int(55)],
323 ["60%", int(60)],
324 ["65%", int(65)],
325 ["70%", int(70)],
326 ["75%", int(75)],
327 ["80%", int(80)],
328 ["85%", int(85)],
329 ["90%", int(90)],
330 ["95%", int(95)],
331 ["100%", int(100)]])
c365d21 more gchart update
lkcl authored Aug 30, 2009
332
29e54a1 more gchart update
lkcl authored Aug 30, 2009
333 self.theSliceEditor = SliceEditor(self)
334
335 SOURCE_CODE_LINK = \
336 "<a href='GChartExample20.txt' target='_blank'>Source code</a>"
337 self.setChartSize(100, 100)
338 self.setBorderStyle("none")
339 self.setChartTitle("<big>Click pie to edit!</big>")
340 self.setChartTitleThickness(20)
341 self.setChartFootnotes(SOURCE_CODE_LINK)
342 self.setChartFootnotesThickness(20)
343 # initial slice sizes
344 initSliceSize = [0.3, 0.2, 0.1, 0.2, 0.2]
345
346 self.addClickListener(self.theSliceEditor)
347
c365d21 more gchart update
lkcl authored Aug 30, 2009
348 for iCurve in range(N_SLICES):
349 self.addCurve()
350 self.getCurve().getSymbol().setBorderWidth(1)
351 self.getCurve().getSymbol().setFillThickness(4)
352 self.getCurve().getSymbol().setFillSpacing(4)
353 self.getCurve().getSymbol().setHoverLocation(
354 AnnotationLocation.ON_PIE_ARC)
355 self.getCurve().getSymbol().setBorderColor(
356 self.colorSelector.getObject(iCurve).borderColor)
357 self.getCurve().getSymbol().setBackgroundColor(
358 self.colorSelector.getObject(iCurve).backgroundColor)
359 # selection flips border and background colors
360 self.getCurve().getSymbol().setHoverSelectionBackgroundColor(
361 self.colorSelector.getObject(iCurve).borderColor)
362 self.getCurve().getSymbol().setHoverSelectionBorderColor(
363 self.colorSelector.getObject(iCurve).backgroundColor)
364 self.getCurve().getSymbol().setSymbolType(
97a4763 more gchart update
lkcl authored Aug 31, 2009
365 SymbolType.PIE_SLICE_HORIZONTAL_SHADING)
c365d21 more gchart update
lkcl authored Aug 30, 2009
366 self.getCurve().getSymbol().setPieSliceSize(initSliceSize[iCurve])
367 self.getCurve().getSymbol().setModelHeight(1.0); #diameter = yMax-yMin
368 self.getCurve().getSymbol().setModelWidth(0)
369 self.getCurve().addPoint(0.5, 0.5); # pie centered in world units
370
371 self.getXAxis().setAxisMin(0); # so 0.5,0.5 (see above) centers pie
372 self.getXAxis().setAxisMax(1)
373 self.getYAxis().setAxisMin(0)
374 self.getYAxis().setAxisMax(1)
375 self.getXAxis().setHasGridlines(False); # hides axes, ticks, etc.
376 self.getXAxis().setAxisVisible(False); # (not needed for the pie)
377 self.getXAxis().setTickCount(0)
378 self.getYAxis().setHasGridlines(False)
379 self.getYAxis().setAxisVisible(False)
380 self.getYAxis().setTickCount(0)
381 self.update()
382
383
384 def onClickPrevSlice(self, event):
385 iCurve = self.getCurveIndex(self.getTouchedCurve())
386 if (iCurve == 0) :
387 iPrev = self.getNCurves()-1
388 else:
389 iPrev = (iCurve-1)
390 self.touch(self.getCurve(iPrev).getPoint(0))
923e40b more gchart update
lkcl authored Aug 30, 2009
391 self.theSliceEditor.copyChartPropertiesIntoForm(self.getTouchedPoint())
c365d21 more gchart update
lkcl authored Aug 30, 2009
392 self.update(TouchedPointUpdateOption.TOUCHED_POINT_LOCKED)
393
394 def onClickNextSlice(self, event):
395 iCurve = self.getCurveIndex(self.getTouchedCurve())
396 if (iCurve+1 == self.getNCurves()) :
397 iNext = 0
398 else:
399 iNext = (iCurve+1)
400 self.touch(self.getCurve(iNext).getPoint(0))
923e40b more gchart update
lkcl authored Aug 30, 2009
401 self.theSliceEditor.copyChartPropertiesIntoForm(self.getTouchedPoint())
c365d21 more gchart update
lkcl authored Aug 30, 2009
402 self.update(TouchedPointUpdateOption.TOUCHED_POINT_LOCKED)
403
Something went wrong with that request. Please try again.