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 gtk
|
||||
import gtk.gtkgl
|
||||
@ -20,12 +21,19 @@ class SketchWidget(object):
|
||||
self.panning = False
|
||||
self.drawingShape = None
|
||||
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.cursors = {
|
||||
'arrow': gtk.gdk.Cursor(gtk.gdk.ARROW),
|
||||
'crosshair': gtk.gdk.Cursor(gtk.gdk.CROSSHAIR),
|
||||
}
|
||||
self.cursor = 'arrow'
|
||||
self.hover_snap_ptref = None
|
||||
self.solved = False
|
||||
|
||||
@ -238,18 +246,12 @@ class SketchWidget(object):
|
||||
|
||||
def button_press_event(self, widget, event, data = None):
|
||||
if event.button == 1:
|
||||
if self.mode == 'line':
|
||||
self.do_line_left_click(event.x, event.y)
|
||||
elif self.mode == 'circle':
|
||||
self.do_circle_left_click(event.x, event.y)
|
||||
self.mode.do_left_click(self, event.x, event.y)
|
||||
elif event.button == 2:
|
||||
self.panning = True
|
||||
self.panning_start = (event.x, self.size[1] - event.y)
|
||||
elif event.button == 3:
|
||||
if self.mode == 'line':
|
||||
self.do_line_right_click(event.x, event.y)
|
||||
elif self.mode == 'circle':
|
||||
self.do_circle_right_click(event.x, event.y)
|
||||
self.mode.do_right_click(self, event.x, event.y)
|
||||
|
||||
def button_release_event(self, widget, event, data = None):
|
||||
if event.button == 2:
|
||||
@ -265,10 +267,7 @@ class SketchWidget(object):
|
||||
self.panning_start = (event.x, self.size[1] - event.y)
|
||||
self.queue_redraw()
|
||||
else:
|
||||
if self.mode == 'line':
|
||||
self.do_line_motion(event.x, event.y)
|
||||
elif self.mode == 'circle':
|
||||
self.do_circle_motion(event.x, event.y)
|
||||
self.mode.do_motion(self, event.x, event.y)
|
||||
|
||||
def scroll_event(self, widget, event, data = None):
|
||||
if event.direction == gtk.gdk.SCROLL_UP:
|
||||
@ -363,133 +362,24 @@ class SketchWidget(object):
|
||||
glEnd()
|
||||
glPopAttrib()
|
||||
|
||||
def set_mode(self, mode):
|
||||
if mode != self.mode:
|
||||
if self.mode == 'line':
|
||||
self.drawingShape = None
|
||||
self.queue_redraw()
|
||||
elif self.mode == 'circle':
|
||||
self.drawingShape = None
|
||||
self.queue_redraw()
|
||||
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
|
||||
def set_mode(self, mode_name):
|
||||
if mode_name not in self.modes:
|
||||
sys.stderr.write(__name__ +
|
||||
':set_mode(): Unknown mode %s\n' % mode_name)
|
||||
elif mode_name != self.mode_name:
|
||||
self.mode.end_mode(self)
|
||||
self.mode_name = mode_name
|
||||
self.mode = self.modes[mode_name]
|
||||
self.cancel_drawing_shape()
|
||||
|
||||
def do_line_left_click(self, x, y):
|
||||
click_pt = self.screenPtToPt((x, self.size[1] - y))
|
||||
start = click_pt
|
||||
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)
|
||||
c = self.mode.get_cursor()
|
||||
if c in self.cursors and c != self.cursor:
|
||||
self.cursor = c
|
||||
self.widget.window.set_cursor(self.cursors[c])
|
||||
|
||||
def cancel_drawing_shape(self):
|
||||
self.drawingShape = None
|
||||
if self.drawingShape is not None:
|
||||
self.drawingShape = None
|
||||
self.queue_redraw()
|
||||
self.drawingConstraints = {}
|
||||
self.hover_snap_ptref = None
|
||||
|
||||
@ -581,3 +471,137 @@ class SketchWidget(object):
|
||||
sys.stderr.write(__name__ +
|
||||
':solve(): Unknown Sketch.solve() result\n')
|
||||
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