Revert "Change program name to 'tabletconfig'."
[GnomeTabletApps.git] / code / tablet-capplet
blobabfce0068eda2554a4c307c85ee8ef42b9573dc3
1 #!/usr/bin/env python
2 ############################################################################
3 ##
4 ## Copyright (C), all rights reserved:
5 ## 2007-2009 Alexander Macdonald
6 ## 2008 Juho Vepsalainen
7 ## 2009 Thomas Iorns <yobbobandana@yahoo.co.nz>
8 ##
9 ## This program is free software; you can redistribute it and/or
10 ## modify it under the terms of the GNU General Public License version 2
12 ## Graphics Tablet Applet
14 ############################################################################
16 import pygtk
17 pygtk.require('2.0')
18 import gtk
19 import gtk.glade
20 import gobject
21 import cairo
22 import sys
23 import os
24 import subprocess
25 import math
27 bool_options = [
28 "TPCButton",
31 int_options = [
32 "Mode",
33 "ToolID",
34 "ClickForce",
37 def xswGetDefault(devicename, propertyname, *args):
38 ''' Get the default value for some option using xsetwacom.
39 '''
40 try:
41 cmd = ['xsetwacom']
42 cmd.extend(args)
43 cmd.extend(['getdefault', devicename, propertyname])
44 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
45 output = p.communicate()[0]
46 return output.strip()
47 except:
48 return None
50 def xswGet(devicename, propertyname, *args):
51 ''' Get the current value for some option using xsetwacom.
52 '''
53 try:
54 cmd = ['xsetwacom']
55 cmd.extend(args)
56 cmd.extend(['get', devicename, propertyname])
57 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
58 output = p.communicate()[0].strip()
59 if not output:
60 return None
61 if propertyname in bool_options:
62 return bool(int(output))
63 elif propertyname in int_options:
64 return int(output)
65 return output
66 except:
67 return None
69 def xswSet(devicename, propertyname, value, *args):
70 ''' Set an option using xsetwacom.
71 '''
72 try:
73 if value is True:
74 value = "on"
75 elif value is False:
76 value = "off"
77 elif value is None:
78 value = xswGetDefault(devicename, propertyname)
79 cmd = ['xsetwacom']
80 cmd.extend(args)
81 cmd.extend(['set', devicename, propertyname, str(value)])
82 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
83 output = p.communicate()[0]
84 return output.strip()
85 except:
86 return None
88 def GetPressCurve(devicename):
89 ''' Get the pressure curve of a device using xsetwacom
90 '''
91 try:
92 output = subprocess.Popen(["xsetwacom", "-x", "get", devicename, "PressCurve"], stdout=subprocess.PIPE).communicate()[0]
93 bits = output.split()
94 if bits[1] == "\"PressCurve\"":
95 return [float(x) for x in bits[2].strip("\"").split(",")]
96 except:
97 return None
99 def SetPressCurve(devicename, points):
100 ''' Set the pressure curve of a device using xsetwacom
102 try:
103 output = subprocess.Popen(["xsetwacom", "set", devicename, "PressCurve", str(points[0]), str(points[1]), str(points[2]), str(points[3])])
104 except:
105 return None
107 def GetClickForce(devicename):
108 ''' Get the ClickForce of a device using xsetwacom.
109 Values are in the range 1 - 21.
111 return xswGet(devicename, "ClickForce")
113 def SetClickForce(devicename, force):
114 ''' Set the ClickForce of a device using xsetwacom.
115 Values are in the range 1 - 21.
117 if force == None:
118 force = xswGetDefault(devicename, "ClickForce")
119 elif force > 21:
120 force = 21
121 elif force < 1:
122 force = 1
124 return xswSet(devicename, "ClickForce", force)
126 def GetMode(devicename):
127 ''' Get the device Mode using xsetwacom.
129 try:
130 output = subprocess.Popen(["xsetwacom", "get", devicename, "Mode"], stdout=subprocess.PIPE).communicate()[0]
131 return int(output.strip())
132 except:
133 return None
135 def SetMode(devicename, m):
136 ''' Set the device Mode using xsetwacom.
138 try:
139 output = subprocess.Popen(["xsetwacom", "set", devicename, "Mode", str(m)])
140 return int(output.strip())
141 except:
142 return None
144 class PressureCurveWidget(gtk.DrawingArea):
145 ''' A widget for displaying and modifying the pressure curve (PressCurve)
146 for a wacom-compatible drawing tablet. The curve may be
147 modified by dragging the control point.
149 def __init__(self):
151 gtk.DrawingArea.__init__(self)
153 self.Pressure = 0.0
154 self.CP = None
155 self.ClickForceLine = None
157 self.Radius = 5.0
158 self.ControlPointStroke = 2.0
159 self.ControlPointDiameter = (self.Radius * 2) + self.ControlPointStroke
160 self.WindowSize = None
161 self.Scale = None
163 self.DeviceName = ""
165 self.DraggingCP = False
166 self.DraggingCF = False
168 self.set_events(gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.BUTTON_MOTION_MASK | gtk.gdk.BUTTON1_MOTION_MASK | gtk.gdk.BUTTON2_MOTION_MASK | gtk.gdk.BUTTON3_MOTION_MASK | gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK)
170 self.connect("configure-event", self.ConfigureEvent)
171 self.connect("expose-event", self.ExposeEvent)
172 self.connect("motion-notify-event", self.MotionEvent)
173 self.connect("button-press-event", self.ButtonPress)
174 self.connect("button-release-event", self.ButtonRelease)
175 self.set_size_request(100,100)
177 def GetPoints(self):
178 ''' Return the control points as xsetwacom would like them.
180 if not self.CP:
181 return None
182 points = []
183 points.append(int(self.ClampValue(self.CP[0]) * 100.0))
184 points.append(int(self.ClampValue(1.0 - self.CP[1]) * 100.0))
185 points.append(100 - points[1])
186 points.append(100 - points[0])
187 return points
189 def SetDevice(self, name):
190 ''' Change or refresh the current device.
192 self.DeviceName = name
193 cf = GetClickForce(name)
195 if cf == None:
196 self.ClickForceLine = None
197 else:
198 self.ClickForceLine = self.ClampValue((cf - 1) / 20.0)
200 points = GetPressCurve(name)
201 if points == None:
202 self.CP = None
203 else:
204 self.CP = [points[0] / 100.0, 1.0 - (points[1] / 100.0)]
205 self.Pressure = 0.0
207 self.Update()
209 def Update(self):
210 self.queue_draw()
212 def ClampValue(self, v):
213 ''' Make sure v is between 0.0 and 1.0 inclusive.
215 if v < 0.0:
216 return 0.0
217 elif v > 1.0:
218 return 1.0
219 else:
220 return v
222 def ConfigureEvent(self, widget, event):
223 ''' Handle widget resize.
225 self.WindowSize = self.window.get_size()
226 xscale = self.WindowSize[0] - self.ControlPointDiameter
227 yscale = self.WindowSize[1] - self.ControlPointDiameter
228 self.Scale = (xscale, yscale)
230 def MotionEvent(self, widget, event):
231 ''' Handle motion notify events.
233 pos = event.get_coords()
234 pos = (pos[0] / self.Scale[0], pos[1] / self.Scale[1])
236 if self.CP == None:
237 return
239 if self.DraggingCP:
240 self.CP[0] = self.ClampValue(pos[0])
241 self.CP[1] = self.ClampValue(pos[1])
242 self.Update()
244 elif self.DraggingCF:
245 cf = int(pos[0] * 20)
246 self.ClickForceLine = self.ClampValue(cf / 20.0)
248 def ButtonPress(self, widget, event):
249 ''' Handle button press events.
251 if self.CP == None:
252 return
254 if self.DraggingCP or self.DraggingCF:
255 self.DragFinished()
256 else:
257 pos = event.get_coords()
258 pos = (pos[0] / self.Scale[0], pos[1] / self.Scale[1])
260 dx = abs(pos[0] - self.CP[0]) * self.Scale[0]
261 dy = abs(pos[1] - self.CP[1]) * self.Scale[1]
263 if dx < self.ControlPointDiameter and dy < self.ControlPointDiameter:
264 self.DraggingCP = True
265 return
267 if self.ClickForceLine == None:
268 return
270 dx = abs(pos[0] - self.ClickForceLine) * self.Scale[0]
272 if dx < self.ControlPointDiameter:
273 self.DraggingCF = True
274 return
276 def ButtonRelease(self, widget, event):
277 ''' Handle button release events.
279 self.DragFinished()
280 self.Update()
282 def DragFinished(self):
283 ''' Clean up after finished drag.
285 self.DraggingCP = False
286 self.DraggingCF = False
288 if self.ClickForceLine != None:
289 SetClickForce(self.DeviceName, int(self.ClickForceLine * 20.0) + 1)
291 points = self.GetPoints()
292 if points != None:
293 SetPressCurve(self.DeviceName, points)
295 def DrawGrid(self, cr):
296 ''' Draw a 10 by 10 grid.
298 cr.set_line_width(0.5)
299 cr.set_source_rgba(0.0, 0.0, 0.0, 0.25)
300 cr.save()
301 cr.scale(self.Scale[0], self.Scale[1])
302 cr.new_path()
303 for x in range(11):
304 cr.move_to(x * 0.1, 0.0)
305 cr.line_to(x * 0.1, 1.0)
306 for y in range(11):
307 cr.move_to(0.0, y * 0.1)
308 cr.line_to(1.0, y * 0.1)
309 cr.restore()
310 cr.stroke()
312 def DrawLinear(self, cr):
313 ''' Draw a line to indicate the default (linear) pressure curve.
315 cr.set_line_width(1.0)
316 cr.save()
317 cr.scale(self.Scale[0], self.Scale[1])
318 cr.new_path()
319 cr.move_to(0.0, 1.0)
320 cr.line_to(1.0, 0.0)
321 cr.restore()
322 cr.stroke()
324 def DrawClickForce(self, cr):
325 ''' Draw a vertical line indicating the current click force.
327 if self.ClickForceLine == None:
328 return
329 cr.set_line_width(1.0)
330 cr.set_source_rgba(1.0, 0.0, 0.0, 0.25)
331 cr.save()
332 cr.scale(self.Scale[0], self.Scale[1])
333 cr.new_path()
334 cr.move_to(self.ClickForceLine, 0.0)
335 cr.line_to(self.ClickForceLine, 1.0)
336 cr.restore()
337 cr.stroke()
339 def DrawPressure(self, cr, x0, y0, x1, y1, click=True):
340 ''' Draw the current pressure.
342 if not self.Pressure:
343 return
344 pmin = 0.0
345 if self.ClickForceLine != None:
346 pmin = self.ClickForceLine * 20 / 100.0
348 cr.save()
349 cr.scale(self.Scale[0], self.Scale[1])
350 cr.rectangle(0.0, 0.0, self.Pressure, 1.0)
351 cr.clip()
352 cr.new_path()
353 if self.Pressure >= pmin:
354 cr.set_source_rgba(114.0 / 255.0, 159.0 / 255.0, 207.0 / 255.0, 0.5)
355 else:
356 cr.set_source_rgba(207.0 / 255.0, 114.0 / 255.0, 114.0 / 255.0, 0.5)
357 cr.move_to(0.0,1.0)
358 cr.curve_to(x0, y0, x1, y1, 1.0, 0.0)
359 cr.line_to(1.0, 1.0)
360 cr.fill()
361 cr.restore()
363 def DrawPressureCurve(self, cr, x0, y0, x1, y1):
364 ''' Draw the active pressure curve.
366 cr.set_line_width(2.0)
367 cr.set_source_rgba(32.0 / 255.0, 74.0 / 255.0, 135.0 / 255.0, 1.0)
368 cr.save()
369 cr.scale(self.Scale[0], self.Scale[1])
370 cr.new_path()
371 cr.move_to(0.0, 1.0)
372 cr.curve_to(x0, y0, x1, y1, 1.0, 0.0)
373 cr.restore()
374 cr.stroke()
376 def ExposeEvent(self, widget, event):
377 ''' Draw the widget.
379 cr = widget.window.cairo_create()
380 cr.set_line_cap(cairo.LINE_CAP_ROUND);
382 cr.save()
383 cr.translate(self.ControlPointDiameter / 2.0, self.ControlPointDiameter / 2.0)
385 self.DrawGrid(cr)
387 if self.Pressure == None:
388 cr.restore()
389 return
391 self.DrawLinear(cr)
393 x0 = 0.0
394 y0 = 1.0
395 x1 = 1.0
396 y1 = 0.0
398 if self.CP:
399 x0 = self.CP[0]
400 y0 = self.CP[1]
401 x1 = self.CP[1]
402 y1 = self.CP[0]
404 self.DrawPressure(cr, x0, y0, x1, y1)
405 self.DrawPressureCurve(cr, x0, y0, x1, y1)
408 if self.CP == None:
409 cr.restore()
410 return
412 cr.set_line_width(2.0)
413 cr.set_source_rgba(0.0, 0.0, 0.0, 0.5)
415 cr.save()
416 cr.scale(self.Scale[0], self.Scale[1])
417 cr.move_to(0.0, 1.0)
418 cr.line_to(x0, y0)
419 cr.restore()
421 cr.stroke()
423 # Control Points
424 cr.set_line_width(2.0)
426 cr.save()
427 cr.arc(x0 * self.Scale[0], y0 * self.Scale[1], self.Radius, 0.0, 2.0 * math.pi);
428 cr.set_source_rgba(237.0 / 255.0, 212.0 / 255.0, 0.0, 0.5)
429 cr.fill_preserve()
430 cr.set_source_rgba(239.0 / 255.0, 41.0 / 255.0, 41.0 / 255.0, 1.0)
431 cr.stroke()
432 cr.restore()
434 cr.restore()
436 class DrawingTestWidget(gtk.DrawingArea):
437 ''' A widget for testing the pressure sensitivity of an input device.
439 def __init__(self):
441 gtk.DrawingArea.__init__(self)
443 self.Device = 0
444 self.Radius = 5.0
445 self.Drawing = False
446 self.WindowSize = None
447 self.Raster = None
448 self.RasterCr = None
450 self.set_events(gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.BUTTON_MOTION_MASK | gtk.gdk.BUTTON1_MOTION_MASK | gtk.gdk.BUTTON2_MOTION_MASK | gtk.gdk.BUTTON3_MOTION_MASK | gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK)
451 self.set_extension_events(gtk.gdk.EXTENSION_EVENTS_ALL)
453 self.connect("configure-event", self.ConfigureEvent)
454 self.connect("expose-event", self.ExposeEvent)
455 self.connect("motion-notify-event", self.MotionEvent)
456 self.connect("button-press-event", self.ButtonPress)
457 self.connect("button-release-event", self.ButtonRelease)
458 self.set_size_request(100,100)
460 def ConfigureEvent(self, widget, event):
461 ''' Handle widget resize.
463 self.WindowSize = self.window.get_size()
464 self.Raster = self.window.cairo_create().get_target().create_similar(cairo.CONTENT_COLOR, self.WindowSize[0], self.WindowSize[1])
465 self.RasterCr = cairo.Context(self.Raster)
466 self.RasterCr.set_source_rgba(1.0, 1.0, 1.0, 1.0)
467 self.RasterCr.rectangle(0.0, 0.0, self.WindowSize[0], self.WindowSize[1])
468 self.RasterCr.fill()
470 def GetPressure(self):
471 ''' Return the current device pressure.
473 dev = gtk.gdk.devices_list()[self.Device]
474 state = dev.get_state(self.window)
475 return dev.get_axis(state[0], gtk.gdk.AXIS_PRESSURE)
477 def MotionEvent(self, widget, event):
478 ''' Handle motion events.
480 if self.Drawing:
481 pos = event.get_coords()
482 p = self.GetPressure()
483 if p == None:
484 p = 0.0
485 r = p * 50 + 5
486 self.RasterCr.set_line_width(2)
487 self.RasterCr.set_source_rgba(p, 1.0, 0.0, 0.5)
488 if p:
489 self.RasterCr.arc(pos[0], pos[1],r, 0.0, 2 * math.pi);
490 else:
491 # draw something to indicate no pressure
492 self.RasterCr.move_to(pos[0] - 4, pos[1] - 4)
493 self.RasterCr.line_to(pos[0] + 4, pos[1] + 4)
494 self.RasterCr.move_to(pos[0] - 4, pos[1] + 4)
495 self.RasterCr.line_to(pos[0] + 4, pos[1] - 4)
497 self.RasterCr.fill_preserve()
498 self.RasterCr.set_source_rgba(0.5, 0.2, p, 0.5)
499 self.RasterCr.stroke()
500 reg = gtk.gdk.Region()
501 reg.union_with_rect((int(pos[0] - r - 2), int(pos[1] - r - 2), int(2 * (r + 2)), int(2 * (r + 2))))
502 self.window.invalidate_region(reg, False)
504 def ButtonPress(self, widget, event):
505 ''' Handle button press events.
507 self.Drawing = True
509 def ButtonRelease(self, widget, event):
510 ''' Handle button release events.
512 self.Drawing = False
514 def ExposeEvent(self, widget, event):
515 ''' Draw the widget.
517 cr = widget.window.cairo_create()
518 cr.set_source_surface(self.Raster, 0.0, 0.0)
519 cr.paint()
520 cr.set_line_width(2)
521 cr.set_source_rgba(0.0, 0.0, 0.0, 0.25)
522 cr.rectangle(0.0, 0.0, self.WindowSize[0], self.WindowSize[1])
523 cr.stroke()
525 class GraphicsTabletApplet:
526 ''' GUI for configuring wacom-compatible drawing tablets.
528 def __init__(self, gladefile, statusicon):
530 self.WidgetTree = gtk.glade.XML(gladefile)
531 self.StatusIcon = statusicon
533 self.MainWindow = self.WidgetTree.get_widget("MainWindow")
534 self.DeviceCombo = self.WidgetTree.get_widget("DeviceCombo")
535 self.ModeCombo = self.WidgetTree.get_widget("ModeCombo")
536 self.XTilt = self.WidgetTree.get_widget("xtilt")
537 self.YTilt = self.WidgetTree.get_widget("ytilt")
538 self.Wheel = self.WidgetTree.get_widget("wheel")
539 self.ToolID = self.WidgetTree.get_widget("ToolID")
540 self.TPCRadioButton = self.WidgetTree.get_widget("tpcbutton")
541 self.ClickForceScale = self.WidgetTree.get_widget("ClickForceScale")
542 self.ClickForceFrame = self.WidgetTree.get_widget("ClickForceFrame")
543 self.SideSwitchFrame = self.WidgetTree.get_widget("SideSwitchFrame")
544 self.TiltFrame = self.WidgetTree.get_widget("TiltFrame")
545 self.WheelFrame = self.WidgetTree.get_widget("WheelFrame")
547 self.Curve = PressureCurveWidget()
548 self.Curve.show()
549 self.WidgetTree.get_widget("PressureVBox").add(self.Curve)
551 self.DrawingArea = DrawingTestWidget()
552 self.DrawingArea.show()
553 self.WidgetTree.get_widget("DrawingAlignment").add(self.DrawingArea)
555 self.Device = 0
556 self.DeviceMode = None
557 self.DeviceName = None
559 self.DeviceCombo.connect("changed", self.DeviceSelected)
560 self.ModeCombo.connect("changed", self.ModeChanged)
561 self.ClickForceScale.connect("value-changed", self.ClickForceChanged)
562 self.TPCRadioButton.connect("toggled", self.TPCButtonToggled)
564 self.DeviceList = gtk.ListStore(str)
565 self.DeviceCell = gtk.CellRendererText()
566 self.DeviceCombo.pack_start(self.DeviceCell, True)
567 self.DeviceCombo.add_attribute(self.DeviceCell, 'text', 0)
568 self.DeviceCombo.set_model(self.DeviceList)
570 self.ClickForce = None
571 self.TPCButton = None
573 def Run(self):
574 ''' Set up device list and start main window app.
576 for d in gtk.gdk.devices_list():
577 devicename = str(d.name)
578 self.DeviceList.append([devicename])
579 toolID = xswGet(devicename, "ToolID")
580 if toolID >= 0: # valid wacom device
581 self.Device = max(len(self.DeviceList) - 1, 0)
582 else:
583 pass
585 self.DeviceCombo.set_active(self.Device)
586 self.DeviceName = gtk.gdk.devices_list()[self.Device].name
587 self.UpdateChildren()
588 gobject.idle_add(self.Update)
590 self.MainWindow.run()
591 self.MainWindow.hide()
593 def GetPressure(self):
594 ''' Return current device pressure.
596 dev = gtk.gdk.devices_list()[self.Device]
597 state = dev.get_state(self.DrawingArea.window)
598 return dev.get_axis(state[0], gtk.gdk.AXIS_PRESSURE)
600 def GetTilt(self):
601 ''' Return current device tilt as (xtilt, ytilt).
603 dev = gtk.gdk.devices_list()[self.Device]
604 state = dev.get_state(self.DrawingArea.window)
605 try:
606 x = float(dev.get_axis(state[0], gtk.gdk.AXIS_XTILT))
607 y = float(dev.get_axis(state[0], gtk.gdk.AXIS_YTILT))
608 if x != x or y != y:
609 return None
610 else:
611 return (x, y)
612 except:
613 return None
615 def GetWheel(self):
616 ''' Return current device wheel state.
618 dev = gtk.gdk.devices_list()[self.Device]
619 state = dev.get_state(self.DrawingArea.window)
620 try:
621 wheel = dev.get_axis(state[0], gtk.gdk.AXIS_WHEEL)
622 if wheel != wheel:
623 return None
624 else:
625 return wheel
626 except:
627 return None
629 def ModeChanged(self, widget):
630 ''' Set changed mode using xsetwacom.
632 xswSet(self.DeviceName, "Mode", widget.get_active())
634 def ClickForceChanged(self, widget):
635 ''' Do callback for ClickForce slider "value-changed" event.
637 cf = widget.get_value()
638 self.Curve.ClickForceLine = (cf - 1) / 20.0
639 SetClickForce(self.DeviceName, cf)
641 def TPCButtonToggled(self, widget):
642 ''' Handle "toggled" event from the TPCButton radio button.
644 if self.TPCButton == widget.get_active():
645 return
646 self.TPCButton = widget.get_active()
647 xswSet(self.DeviceName, "TPCButton", self.TPCButton)
649 def UpdateDeviceMode(self):
650 ''' Update the device mode combo box.
652 self.DeviceMode = xswGet(self.DeviceName, "Mode")
653 if self.DeviceMode == None:
654 self.ModeCombo.set_sensitive(False)
655 else:
656 self.ModeCombo.set_sensitive(True)
657 self.ModeCombo.set_active(self.DeviceMode)
659 def UpdateClickForce(self):
660 ''' Update the click force slider.
662 self.ClickForce = GetClickForce(self.DeviceName)
663 if self.ClickForce == None:
664 self.ClickForceFrame.hide()
665 else:
666 self.ClickForceFrame.show()
667 self.ClickForceScale.set_value(self.ClickForce)
669 def UpdateTPCButton(self):
670 ''' Update the TPCButton radio button group.
672 self.TPCButton = xswGet(self.DeviceName, "TPCButton")
674 if self.TPCButton == None:
675 self.SideSwitchFrame.hide()
676 return
678 self.SideSwitchFrame.show()
679 self.TPCButton = bool(self.TPCButton)
681 if self.TPCButton == self.TPCRadioButton.get_active():
682 return
684 if self.TPCButton:
685 self.TPCRadioButton.set_active(True)
686 return
688 for button in self.TPCRadioButton.get_group():
689 if button != TPCRadioButton: # there's only one other
690 button.set_active(True)
691 return
693 def UpdateChildren(self):
694 ''' Update the child widgets to reflect current settings.
696 self.UpdateDeviceMode()
697 self.UpdateClickForce()
698 self.UpdateTPCButton()
700 def DeviceSelected(self, widget):
701 ''' Update the various parts of the applet for a new device.
703 self.Device = widget.get_active()
704 self.DrawingArea.Device = self.Device
705 self.DeviceName = gtk.gdk.devices_list()[self.Device].name
706 self.Curve.SetDevice(self.DeviceName)
707 self.UpdateChildren()
709 def Update(self):
710 p = self.GetPressure()
712 if p == None:
713 self.Curve.Pressure = None
714 self.Curve.Update()
715 else:
716 self.Curve.Pressure = p
717 self.Curve.Update()
719 t = self.GetTilt()
721 if t == None:
722 self.TiltFrame.hide()
723 else:
724 self.TiltFrame.show()
725 self.XTilt.set_adjustment(gtk.Adjustment(t[0], -1.0, 1.0))
726 self.YTilt.set_adjustment(gtk.Adjustment(t[1], -1.0, 1.0))
728 w = self.GetWheel()
730 if w == None:
731 self.WheelFrame.hide()
732 else:
733 self.WheelFrame.show()
734 self.Wheel.set_adjustment(gtk.Adjustment(w, -1.0, 1.0))
736 id = xswGet(self.DeviceName, "ToolID")
738 if id == None:
739 id = ""
741 self.ToolID.set_label(str(id))
743 return True
745 ################################################################################
748 if __name__ == '__main__':
750 import optparse
751 parser = optparse.OptionParser()
752 parser.add_option("-l", "--local", action="store_true", dest="runlocal",
753 default=False, help="Run from current directory.")
754 parser.add_option("-f", "--file", dest="filename",
755 help="write config to FILE", metavar="FILE")
756 parser.add_option("-s", "--set", action="store_true", dest="setandexit",
757 default=False, help="set options and exit (don't run GUI)")
758 parser.add_option("-g", "--get", action="store_true", dest="getandexit",
759 default=False, help="get options and exit (don't run GUI)")
760 (options, args) = parser.parse_args()
762 if options.runlocal:
763 statusicon = gtk.status_icon_new_from_file("./tabletconfig.svg")
764 gladefile = "./tabletconfig.glade"
765 else:
766 statusicon = gtk.status_icon_new_from_file("/usr/share/icons/tabletconfig.svg")
767 gladefile = "/usr/share/tablet-apps/tabletconfig.glade"
769 a = GraphicsTabletApplet(gladefile, statusicon)
770 a.Run()