add Mode, LineMode, and CircleMode classes
This commit is contained in:
parent
701b7db7ba
commit
05c8627395
298
SketchWidget.py
298
SketchWidget.py
@ -1,4 +1,5 @@
|
|||||||
|
|
||||||
|
import sys
|
||||||
import math
|
import math
|
||||||
import gtk
|
import gtk
|
||||||
import gtk.gtkgl
|
import gtk.gtkgl
|
||||||
@ -20,12 +21,19 @@ class SketchWidget(object):
|
|||||||
self.panning = False
|
self.panning = False
|
||||||
self.drawingShape = None
|
self.drawingShape = None
|
||||||
self.drawingConstraints = {}
|
self.drawingConstraints = {}
|
||||||
self.mode = ''
|
self.modes = {
|
||||||
|
'select': SelectMode(),
|
||||||
|
'line': LineMode(),
|
||||||
|
'circle': CircleMode(),
|
||||||
|
}
|
||||||
|
self.mode_name = 'select'
|
||||||
|
self.mode = self.modes[self.mode_name]
|
||||||
self.snap_ptrefs = {} # keyed on PointRef
|
self.snap_ptrefs = {} # keyed on PointRef
|
||||||
self.cursors = {
|
self.cursors = {
|
||||||
'arrow': gtk.gdk.Cursor(gtk.gdk.ARROW),
|
'arrow': gtk.gdk.Cursor(gtk.gdk.ARROW),
|
||||||
'crosshair': gtk.gdk.Cursor(gtk.gdk.CROSSHAIR),
|
'crosshair': gtk.gdk.Cursor(gtk.gdk.CROSSHAIR),
|
||||||
}
|
}
|
||||||
|
self.cursor = 'arrow'
|
||||||
self.hover_snap_ptref = None
|
self.hover_snap_ptref = None
|
||||||
self.solved = False
|
self.solved = False
|
||||||
|
|
||||||
@ -238,18 +246,12 @@ class SketchWidget(object):
|
|||||||
|
|
||||||
def button_press_event(self, widget, event, data = None):
|
def button_press_event(self, widget, event, data = None):
|
||||||
if event.button == 1:
|
if event.button == 1:
|
||||||
if self.mode == 'line':
|
self.mode.do_left_click(self, event.x, event.y)
|
||||||
self.do_line_left_click(event.x, event.y)
|
|
||||||
elif self.mode == 'circle':
|
|
||||||
self.do_circle_left_click(event.x, event.y)
|
|
||||||
elif event.button == 2:
|
elif event.button == 2:
|
||||||
self.panning = True
|
self.panning = True
|
||||||
self.panning_start = (event.x, self.size[1] - event.y)
|
self.panning_start = (event.x, self.size[1] - event.y)
|
||||||
elif event.button == 3:
|
elif event.button == 3:
|
||||||
if self.mode == 'line':
|
self.mode.do_right_click(self, event.x, event.y)
|
||||||
self.do_line_right_click(event.x, event.y)
|
|
||||||
elif self.mode == 'circle':
|
|
||||||
self.do_circle_right_click(event.x, event.y)
|
|
||||||
|
|
||||||
def button_release_event(self, widget, event, data = None):
|
def button_release_event(self, widget, event, data = None):
|
||||||
if event.button == 2:
|
if event.button == 2:
|
||||||
@ -265,10 +267,7 @@ class SketchWidget(object):
|
|||||||
self.panning_start = (event.x, self.size[1] - event.y)
|
self.panning_start = (event.x, self.size[1] - event.y)
|
||||||
self.queue_redraw()
|
self.queue_redraw()
|
||||||
else:
|
else:
|
||||||
if self.mode == 'line':
|
self.mode.do_motion(self, event.x, event.y)
|
||||||
self.do_line_motion(event.x, event.y)
|
|
||||||
elif self.mode == 'circle':
|
|
||||||
self.do_circle_motion(event.x, event.y)
|
|
||||||
|
|
||||||
def scroll_event(self, widget, event, data = None):
|
def scroll_event(self, widget, event, data = None):
|
||||||
if event.direction == gtk.gdk.SCROLL_UP:
|
if event.direction == gtk.gdk.SCROLL_UP:
|
||||||
@ -363,133 +362,24 @@ class SketchWidget(object):
|
|||||||
glEnd()
|
glEnd()
|
||||||
glPopAttrib()
|
glPopAttrib()
|
||||||
|
|
||||||
def set_mode(self, mode):
|
def set_mode(self, mode_name):
|
||||||
if mode != self.mode:
|
if mode_name not in self.modes:
|
||||||
if self.mode == 'line':
|
sys.stderr.write(__name__ +
|
||||||
self.drawingShape = None
|
':set_mode(): Unknown mode %s\n' % mode_name)
|
||||||
self.queue_redraw()
|
elif mode_name != self.mode_name:
|
||||||
elif self.mode == 'circle':
|
self.mode.end_mode(self)
|
||||||
self.drawingShape = None
|
self.mode_name = mode_name
|
||||||
self.queue_redraw()
|
self.mode = self.modes[mode_name]
|
||||||
if self.widget.window is not None:
|
|
||||||
if mode in ('line', 'circle'):
|
|
||||||
self.widget.window.set_cursor(self.cursors['crosshair'])
|
|
||||||
else:
|
|
||||||
self.widget.window.set_cursor(self.cursors['arrow'])
|
|
||||||
self.mode = mode
|
|
||||||
self.cancel_drawing_shape()
|
self.cancel_drawing_shape()
|
||||||
|
c = self.mode.get_cursor()
|
||||||
def do_line_left_click(self, x, y):
|
if c in self.cursors and c != self.cursor:
|
||||||
click_pt = self.screenPtToPt((x, self.size[1] - y))
|
self.cursor = c
|
||||||
start = click_pt
|
self.widget.window.set_cursor(self.cursors[c])
|
||||||
start_pt_ref = None
|
|
||||||
if self.hover_snap_ptref is not None:
|
|
||||||
start = self.hover_snap_ptref.getPt()
|
|
||||||
start_pt_ref = self.hover_snap_ptref
|
|
||||||
if self.drawingShape is not None:
|
|
||||||
# end a currently drawing line
|
|
||||||
# add snap points for newly drawn line
|
|
||||||
self.add_snap_ptrefs_from_shape(self.drawingShape)
|
|
||||||
start = self.drawingShape.getPt(1) # start at last snap point
|
|
||||||
prev_line = self.drawingShape
|
|
||||||
if self.hover_snap_ptref is not None:
|
|
||||||
c = Connect(self.hover_snap_ptref.shape,
|
|
||||||
self.hover_snap_ptref.ptNum,
|
|
||||||
self.drawingShape, 1)
|
|
||||||
self.drawingConstraints['c2'] = c
|
|
||||||
pt = self.hover_snap_ptref.getPt()
|
|
||||||
self.drawingShape.setPt(1, pt)
|
|
||||||
# don't do a horizontal/vertical when snapping
|
|
||||||
self.drawingConstraints['hv'] = None
|
|
||||||
self.merge_in_drawing_shape()
|
|
||||||
start = prev_line.getPt(1)
|
|
||||||
start_pt_ref = PointRef(prev_line, 1)
|
|
||||||
# begin a new line
|
|
||||||
self.drawingShape = Line(
|
|
||||||
start[0], start[1], click_pt[0], click_pt[1])
|
|
||||||
if start_pt_ref is not None:
|
|
||||||
c = Connect(start_pt_ref.shape, start_pt_ref.ptNum,
|
|
||||||
self.drawingShape, 0)
|
|
||||||
self.drawingConstraints['c1'] = c
|
|
||||||
self.queue_redraw()
|
|
||||||
|
|
||||||
def do_line_right_click(self, x, y):
|
|
||||||
if self.drawingShape is not None:
|
|
||||||
self.cancel_drawing_shape()
|
|
||||||
self.queue_redraw()
|
|
||||||
else:
|
|
||||||
self.window.set_mode('')
|
|
||||||
|
|
||||||
def do_line_motion(self, x, y):
|
|
||||||
self.update_hover_snap_point(x, y)
|
|
||||||
if self.drawingShape is not None:
|
|
||||||
this_pt = self.screenPtToPt((x, self.size[1] - y))
|
|
||||||
if self.hover_snap_ptref is not None:
|
|
||||||
this_pt = self.hover_snap_ptref.getPt()
|
|
||||||
self.drawingConstraints['hv'] = None
|
|
||||||
else:
|
|
||||||
start = self.drawingShape.getPt(0)
|
|
||||||
angle = math.atan2(this_pt[1] - start[1], this_pt[0] - start[0])
|
|
||||||
angle *= 180.0 / math.pi
|
|
||||||
def within(a, b, d): return abs(a - b) < d
|
|
||||||
def snaps_to(q): return within(angle, q, self.snap_angle)
|
|
||||||
hv_snap_dist = self.screenDistToDist(self.hv_snap_dist)
|
|
||||||
if ((snaps_to(-180) or snaps_to(180) or snaps_to(0))
|
|
||||||
and within(start[1], this_pt[1], hv_snap_dist)):
|
|
||||||
this_pt = (this_pt[0], start[1])
|
|
||||||
if not ('hv' in self.drawingConstraints
|
|
||||||
and isinstance(self.drawingConstraints['hv'],
|
|
||||||
Horizontal)):
|
|
||||||
c = Horizontal(
|
|
||||||
self.drawingShape, 0, self.drawingShape, 1)
|
|
||||||
self.drawingConstraints['hv'] = c
|
|
||||||
elif ((snaps_to(-90) or snaps_to(90))
|
|
||||||
and within(start[0], this_pt[0], hv_snap_dist)):
|
|
||||||
this_pt = (start[0], this_pt[1])
|
|
||||||
if not ('hv' in self.drawingConstraints
|
|
||||||
and isinstance(self.drawingConstraints['hv'],
|
|
||||||
Vertical)):
|
|
||||||
c = Vertical(self.drawingShape, 0, self.drawingShape, 1)
|
|
||||||
self.drawingConstraints['hv'] = c
|
|
||||||
else:
|
|
||||||
self.drawingConstraints['hv'] = None
|
|
||||||
self.drawingShape.setPt(1, this_pt)
|
|
||||||
self.queue_redraw()
|
|
||||||
|
|
||||||
def do_circle_left_click(self, x, y):
|
|
||||||
pt = self.screenPtToPt((x, self.size[1] - y))
|
|
||||||
if self.drawingShape is None:
|
|
||||||
hsp = self.hover_snap_ptref
|
|
||||||
if hsp is not None:
|
|
||||||
pt = hsp.getPt()
|
|
||||||
self.drawingShape = Circle(pt[0], pt[1], 0)
|
|
||||||
if hsp is not None:
|
|
||||||
c = Connect(hsp.shape, hsp.ptNum, self.drawingShape, 0)
|
|
||||||
self.drawingConstraints['c'] = c
|
|
||||||
else:
|
|
||||||
self.add_snap_ptrefs_from_shape(self.drawingShape)
|
|
||||||
self.merge_in_drawing_shape()
|
|
||||||
self.queue_redraw()
|
|
||||||
|
|
||||||
def do_circle_right_click(self, x, y):
|
|
||||||
if self.drawingShape is not None:
|
|
||||||
self.cancel_drawing_shape()
|
|
||||||
self.queue_redraw()
|
|
||||||
else:
|
|
||||||
self.window.set_mode('')
|
|
||||||
|
|
||||||
def do_circle_motion(self, x, y):
|
|
||||||
if self.drawingShape is not None:
|
|
||||||
pt = self.screenPtToPt((x, self.size[1] - y))
|
|
||||||
r = self.dist_bw(self.drawingShape.getPt(0), pt)
|
|
||||||
self.drawingShape.setRadius(r)
|
|
||||||
self.queue_redraw()
|
|
||||||
self.set_hover_snap_point(None)
|
|
||||||
else:
|
|
||||||
self.update_hover_snap_point(x, y)
|
|
||||||
|
|
||||||
def cancel_drawing_shape(self):
|
def cancel_drawing_shape(self):
|
||||||
self.drawingShape = None
|
if self.drawingShape is not None:
|
||||||
|
self.drawingShape = None
|
||||||
|
self.queue_redraw()
|
||||||
self.drawingConstraints = {}
|
self.drawingConstraints = {}
|
||||||
self.hover_snap_ptref = None
|
self.hover_snap_ptref = None
|
||||||
|
|
||||||
@ -581,3 +471,137 @@ class SketchWidget(object):
|
|||||||
sys.stderr.write(__name__ +
|
sys.stderr.write(__name__ +
|
||||||
':solve(): Unknown Sketch.solve() result\n')
|
':solve(): Unknown Sketch.solve() result\n')
|
||||||
self.window.update_sketch_status(valid, text)
|
self.window.update_sketch_status(valid, text)
|
||||||
|
|
||||||
|
class Mode(object):
|
||||||
|
def do_left_click(self, sw, x, y):
|
||||||
|
pass
|
||||||
|
def do_right_click(self, sw, x, y):
|
||||||
|
pass
|
||||||
|
def do_motion(self, sw, x, y):
|
||||||
|
pass
|
||||||
|
def begin_mode(self, sw):
|
||||||
|
pass
|
||||||
|
def end_mode(self, sw):
|
||||||
|
pass
|
||||||
|
def get_cursor(self):
|
||||||
|
return 'arrow'
|
||||||
|
|
||||||
|
class SelectMode(Mode):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class LineMode(Mode):
|
||||||
|
def do_left_click(self, sw, x, y):
|
||||||
|
click_pt = sw.screenPtToPt((x, sw.size[1] - y))
|
||||||
|
start = click_pt
|
||||||
|
start_pt_ref = None
|
||||||
|
if sw.hover_snap_ptref is not None:
|
||||||
|
start = sw.hover_snap_ptref.getPt()
|
||||||
|
start_pt_ref = sw.hover_snap_ptref
|
||||||
|
if sw.drawingShape is not None:
|
||||||
|
# end a currently drawing line
|
||||||
|
# add snap points for newly drawn line
|
||||||
|
sw.add_snap_ptrefs_from_shape(sw.drawingShape)
|
||||||
|
start = sw.drawingShape.getPt(1) # start at last snap point
|
||||||
|
prev_line = sw.drawingShape
|
||||||
|
if sw.hover_snap_ptref is not None:
|
||||||
|
c = Connect(sw.hover_snap_ptref.shape,
|
||||||
|
sw.hover_snap_ptref.ptNum,
|
||||||
|
sw.drawingShape, 1)
|
||||||
|
sw.drawingConstraints['c2'] = c
|
||||||
|
pt = sw.hover_snap_ptref.getPt()
|
||||||
|
sw.drawingShape.setPt(1, pt)
|
||||||
|
# don't do a horizontal/vertical when snapping
|
||||||
|
sw.drawingConstraints['hv'] = None
|
||||||
|
sw.merge_in_drawing_shape()
|
||||||
|
start = prev_line.getPt(1)
|
||||||
|
start_pt_ref = PointRef(prev_line, 1)
|
||||||
|
# begin a new line
|
||||||
|
sw.drawingShape = Line(
|
||||||
|
start[0], start[1], click_pt[0], click_pt[1])
|
||||||
|
if start_pt_ref is not None:
|
||||||
|
c = Connect(start_pt_ref.shape, start_pt_ref.ptNum,
|
||||||
|
sw.drawingShape, 0)
|
||||||
|
sw.drawingConstraints['c1'] = c
|
||||||
|
sw.queue_redraw()
|
||||||
|
|
||||||
|
def do_right_click(self, sw, x, y):
|
||||||
|
if sw.drawingShape is not None:
|
||||||
|
sw.cancel_drawing_shape()
|
||||||
|
sw.queue_redraw()
|
||||||
|
else:
|
||||||
|
sw.window.set_mode('')
|
||||||
|
|
||||||
|
def do_motion(self, sw, x, y):
|
||||||
|
sw.update_hover_snap_point(x, y)
|
||||||
|
if sw.drawingShape is not None:
|
||||||
|
this_pt = sw.screenPtToPt((x, sw.size[1] - y))
|
||||||
|
if sw.hover_snap_ptref is not None:
|
||||||
|
this_pt = sw.hover_snap_ptref.getPt()
|
||||||
|
sw.drawingConstraints['hv'] = None
|
||||||
|
else:
|
||||||
|
start = sw.drawingShape.getPt(0)
|
||||||
|
angle = math.atan2(this_pt[1] - start[1], this_pt[0] - start[0])
|
||||||
|
angle *= 180.0 / math.pi
|
||||||
|
def within(a, b, d): return abs(a - b) < d
|
||||||
|
def snaps_to(q): return within(angle, q, sw.snap_angle)
|
||||||
|
hv_snap_dist = sw.screenDistToDist(sw.hv_snap_dist)
|
||||||
|
if ((snaps_to(-180) or snaps_to(180) or snaps_to(0))
|
||||||
|
and within(start[1], this_pt[1], hv_snap_dist)):
|
||||||
|
this_pt = (this_pt[0], start[1])
|
||||||
|
if not ('hv' in sw.drawingConstraints
|
||||||
|
and isinstance(sw.drawingConstraints['hv'],
|
||||||
|
Horizontal)):
|
||||||
|
c = Horizontal(
|
||||||
|
sw.drawingShape, 0, sw.drawingShape, 1)
|
||||||
|
sw.drawingConstraints['hv'] = c
|
||||||
|
elif ((snaps_to(-90) or snaps_to(90))
|
||||||
|
and within(start[0], this_pt[0], hv_snap_dist)):
|
||||||
|
this_pt = (start[0], this_pt[1])
|
||||||
|
if not ('hv' in sw.drawingConstraints
|
||||||
|
and isinstance(sw.drawingConstraints['hv'],
|
||||||
|
Vertical)):
|
||||||
|
c = Vertical(sw.drawingShape, 0, sw.drawingShape, 1)
|
||||||
|
sw.drawingConstraints['hv'] = c
|
||||||
|
else:
|
||||||
|
sw.drawingConstraints['hv'] = None
|
||||||
|
sw.drawingShape.setPt(1, this_pt)
|
||||||
|
sw.queue_redraw()
|
||||||
|
|
||||||
|
def get_cursor(self):
|
||||||
|
return 'crosshair'
|
||||||
|
|
||||||
|
class CircleMode(Mode):
|
||||||
|
def do_left_click(self, sw, x, y):
|
||||||
|
pt = sw.screenPtToPt((x, sw.size[1] - y))
|
||||||
|
if sw.drawingShape is None:
|
||||||
|
hsp = sw.hover_snap_ptref
|
||||||
|
if hsp is not None:
|
||||||
|
pt = hsp.getPt()
|
||||||
|
sw.drawingShape = Circle(pt[0], pt[1], 0)
|
||||||
|
if hsp is not None:
|
||||||
|
c = Connect(hsp.shape, hsp.ptNum, sw.drawingShape, 0)
|
||||||
|
sw.drawingConstraints['c'] = c
|
||||||
|
else:
|
||||||
|
sw.add_snap_ptrefs_from_shape(sw.drawingShape)
|
||||||
|
sw.merge_in_drawing_shape()
|
||||||
|
sw.queue_redraw()
|
||||||
|
|
||||||
|
def do_right_click(self, sw, x, y):
|
||||||
|
if sw.drawingShape is not None:
|
||||||
|
sw.cancel_drawing_shape()
|
||||||
|
sw.queue_redraw()
|
||||||
|
else:
|
||||||
|
sw.window.set_mode('')
|
||||||
|
|
||||||
|
def do_motion(self, sw, x, y):
|
||||||
|
if sw.drawingShape is not None:
|
||||||
|
pt = sw.screenPtToPt((x, sw.size[1] - y))
|
||||||
|
r = sw.dist_bw(sw.drawingShape.getPt(0), pt)
|
||||||
|
sw.drawingShape.setRadius(r)
|
||||||
|
sw.queue_redraw()
|
||||||
|
sw.set_hover_snap_point(None)
|
||||||
|
else:
|
||||||
|
sw.update_hover_snap_point(x, y)
|
||||||
|
|
||||||
|
def get_cursor(self):
|
||||||
|
return 'crosshair'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user