Updating download.html page with Git information
[pythoncad.git] / PythonCAD / Interface / Gtk / gtkedit.py
blob04da54cffd226d44b5ed9783328e3d09386ec2d7
2 # Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 Art Haas
4 # This file is part of PythonCAD.
5 #
6 # PythonCAD is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # PythonCAD is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with PythonCAD; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 # handle cut, copy, paste, selections, etc
24 import pygtk
25 pygtk.require('2.0')
26 import gtk
28 from PythonCAD.Generic.point import Point
29 from PythonCAD.Generic.segment import Segment
30 from PythonCAD.Generic.circle import Circle
31 from PythonCAD.Generic.arc import Arc
32 from PythonCAD.Generic.hcline import HCLine
33 from PythonCAD.Generic.vcline import VCLine
34 from PythonCAD.Generic.acline import ACLine
35 from PythonCAD.Generic.cline import CLine
36 from PythonCAD.Generic.ccircle import CCircle
37 from PythonCAD.Generic.dimension import LinearDimension
38 from PythonCAD.Generic.dimension import HorizontalDimension
39 from PythonCAD.Generic.dimension import VerticalDimension
40 from PythonCAD.Generic.dimension import RadialDimension
41 from PythonCAD.Generic.dimension import AngularDimension
42 from PythonCAD.Generic import text
43 import PythonCAD.Generic.globals
45 def select_region_end_cb(gtkimage, widget, event, tool):
46 # print "called select_region_end_callback()"
47 _image = gtkimage.getImage()
48 _x2, _y2 = _image.getCurrentPoint()
49 _y1 = tool.popObject()
50 _x1 = tool.popObject()
51 _xmin = min(_x1, _x2)
52 _xmax = max(_x1, _x2)
53 _ymin = min(_y1, _y2)
54 _ymax = max(_y1, _y2)
55 tool.delHandler("motion_notify")
56 _active_layer = _image.getActiveLayer()
57 _objs = _active_layer.objsInRegion(_xmin, _ymin, _xmax, _ymax)
58 if len(_objs):
59 _image.sendMessage('group_action_started')
60 try:
61 for _obj in _objs:
62 _image.selectObject(_obj)
63 finally:
64 _image.sendMessage('group_action_ended')
65 gtkimage.setPrompt(_('Click on the items you want to select.'))
66 select_mode_init(gtkimage)
68 def select_motion_notify(gtkimage, widget, event, tool):
69 _tx, _ty = tool.getLocation()
70 _px, _py = gtkimage.coordToPixTransform(_tx, _ty)
71 _gc = gtkimage.getGC()
72 _x = int(event.x)
73 _y = int(event.y)
74 _cp = tool.getCurrentPoint()
75 if _cp is not None:
76 _xc, _yc = _cp
77 _xmin = min(_xc, _px)
78 _ymin = min(_yc, _py)
79 _rw = abs(_xc - _px)
80 _rh = abs(_yc - _py)
81 widget.window.draw_rectangle(_gc, False, _xmin, _ymin, _rw, _rh)
82 tool.setCurrentPoint(_x, _y)
83 _xmin = min(_x, _px)
84 _ymin = min(_y, _py)
85 _rw = abs(_x - _px)
86 _rh = abs(_y - _py)
87 widget.window.draw_rectangle(_gc, False, _xmin, _ymin, _rw, _rh)
88 return True
90 def select_button_press_cb(gtkimage, widget, event, tool):
91 _tol = gtkimage.getTolerance()
92 _image = gtkimage.getImage()
93 _x, _y = _image.getCurrentPoint()
94 # print "x: %g; y: %g" % (_x, _y)
95 _active_layer = _image.getActiveLayer()
96 _pts = _active_layer.find('point', _x, _y, _tol)
97 if len(_pts) > 0:
98 _image.sendMessage('group_action_started')
99 try:
100 for _pt in _pts:
101 _image.selectObject(_pt)
102 finally:
103 _image.sendMessage('group_action_ended')
104 else:
105 _objs = []
106 for _tb in _active_layer.getLayerEntities('text'):
107 # print "testing tb: " + `_tb`
108 _tx, _ty = _tb.getLocation()
109 # print "tx: %g; ty: %g" % (_tx, _ty)
110 _bounds = _tb.getBounds()
111 if _bounds is not None:
112 # print "has bounds ..."
113 _w, _h = _bounds
114 _align = _tb.getAlignment()
115 if _align == text.TextStyle.ALIGN_LEFT:
116 _txmin = _tx
117 _txmax = _tx + _w
118 elif _align == text.TextStyle.ALIGN_CENTER:
119 _off = _w/2.0
120 _txmin = _tx - _off
121 _txmax = _tx + _off
122 elif _align == text.TextStyle.ALIGN_RIGHT:
123 _txmin = _tx - _w
124 _txmax = _tx
125 else:
126 raise ValueError, "Unexpected alignment: %d" % _align
127 _tymin = _ty - _h
128 _tymax = _ty
129 # print "txmin: %g" % _txmin
130 # print "tymin: %g" % _tymin
131 # print "txmax: %g" % _txmax
132 # print "tymax: %g" % _tymax
133 if _txmin < _x < _txmax and _tymin < _y < _tymax:
134 _objs.append(_tb)
135 for _obj, _pt in _active_layer.mapPoint((_x, _y), _tol):
136 _objs.append(_obj)
137 if len(_objs):
138 _image.sendMessage('group_action_started')
139 try:
140 for _obj in _objs:
141 _image.selectObject(_obj)
142 finally:
143 _image.sendMessage('group_action_ended')
144 else:
145 # print "no objects ..."
146 gtkimage.setPrompt(_('Click on another point to select the region.'))
147 gc = gtkimage.getGC()
148 gc.set_line_attributes(1, gtk.gdk.LINE_SOLID,
149 gtk.gdk.CAP_BUTT, gtk.gdk.JOIN_MITER)
150 gc.set_function(gtk.gdk.INVERT)
151 tool.setLocation(_x, _y)
152 tool.pushObject(_x)
153 tool.pushObject(_y)
154 tool.setHandler("motion_notify", select_motion_notify)
155 tool.setHandler("button_press", select_region_end_cb)
157 def select_mode_init(gtkimage, tool=None):
158 gtkimage.setPrompt(_('Click on the items you want to select.'))
159 _tool = gtkimage.getImage().getTool()
160 _tool.initialize()
161 _tool.setHandler("button_press", select_button_press_cb)
163 def deselect_region_end_cb(gtkimage, widget, event, tool):
164 # print "called deselect_region_end_callback()"
165 _image = gtkimage.getImage()
166 _x2, _y2 = _image.getCurrentPoint()
167 _y1 = tool.popObject()
168 _x1 = tool.popObject()
169 _xmin = min(_x1, _x2)
170 _xmax = max(_x1, _x2)
171 _ymin = min(_y1, _y2)
172 _ymax = max(_y1, _y2)
173 tool.delHandler("motion_notify")
174 _active_layer = _image.getActiveLayer()
175 _objs = _active_layer.objsInRegion(_xmin, _ymin, _xmax, _ymax)
176 if len(_objs):
177 _sobjs = {}
178 for _obj in _image.getSelectedObjects(False):
179 if _obj.getParent() is _active_layer:
180 _sobjs[id(_obj)] = True
181 _image.sendMessage('group_action_started')
182 try:
183 for _obj in _objs:
184 if id(_obj) in _sobjs:
185 _image.deselectObject(_obj)
186 finally:
187 _image.sendMessage('group_action_ended')
188 gtkimage.setPrompt(_('Click on the items you want to deselect.'))
189 deselect_mode_init(gtkimage)
191 def deselect_button_press_cb(gtkimage, widget, event, tool):
192 _tol = gtkimage.getTolerance()
193 _image = gtkimage.getImage()
194 _x, _y = _image.getCurrentPoint()
195 # print "x: %g; y: %g" % (_x, _y)
196 _active_layer = _image.getActiveLayer()
197 _objs = []
198 for _obj in _image.getSelectedObjects(False):
199 if _obj.getParent() is _active_layer:
200 if isinstance(_obj, Point):
201 if abs(_obj.x - _x) < _tol and abs(_obj.y - _y) < _tol:
202 _objs.append(_obj)
203 elif isinstance(_obj, text.TextBlock):
204 _tx, _ty = _obj.getLocation()
205 _bounds = _obj.getBounds()
206 if _bounds is not None:
207 _w, _h = _bounds
208 _align = _obj.getAlignment()
209 if _align == text.TextStyle.ALIGN_LEFT:
210 _txmin = _tx
211 _txmax = _tx + _w
212 elif _align == text.TextStyle.ALIGN_CENTER:
213 _off = _w/2.0
214 _txmin = _tx - _off
215 _txmax = _tx + _off
216 elif _align == text.TextStyle.ALIGN_RIGHT:
217 _txmin = _tx - _w
218 _txmax = _tx
219 else:
220 raise ValueError, "Unexpected alignment: %d" % _align
221 _tymin = _ty - _h
222 _tymax = _ty
223 if _txmin < _x < _txmax and _tymin < _y < _tymax:
224 _objs.append(_obj)
225 elif _obj.mapCoords(_x, _y, _tol) is not None:
226 _objs.append(_obj)
227 else:
228 pass
229 if len(_objs):
230 _image.sendMessage('group_action_started')
231 try:
232 for _obj in _objs:
233 _image.deselectObject(_obj)
234 finally:
235 _image.sendMessage('group_action_ended')
236 else:
237 gtkimage.setPrompt(_('Click on another point to select the region.'))
238 gc = gtkimage.getGC()
239 gc.set_line_attributes(1, gtk.gdk.LINE_SOLID,
240 gtk.gdk.CAP_BUTT, gtk.gdk.JOIN_MITER)
241 gc.set_function(gtk.gdk.INVERT)
242 tool.setLocation(_x, _y)
243 tool.pushObject(_x)
244 tool.pushObject(_y)
245 tool.setHandler("motion_notify", select_motion_notify)
246 tool.setHandler("button_press", deselect_region_end_cb)
248 def deselect_mode_init(gtkimage, tool=None):
249 gtkimage.setPrompt(_('Click on the items you want to deselect.'))
250 _tool = gtkimage.getImage().getTool()
251 _tool.initialize()
252 _tool.setHandler("button_press", deselect_button_press_cb)
254 def paste_button_press_cb(gtkimage, widget, event, tool):
255 # print "called paste_button_press_cb()"
256 _image = gtkimage.getImage()
257 _x, _y = _image.getCurrentPoint()
258 # print "x: %g; y: %g" % (_x, _y)
259 _active_layer = _image.getActiveLayer()
260 _objs = PythonCAD.Generic.globals.selectobj.getObjects()
261 _objmap = {}
262 _image.startAction()
263 try:
264 for _obj in _objs:
265 if isinstance(_obj, Point):
266 if not _objmap.has_key('point'):
267 _objmap['point'] = {}
268 _pt = Point(_x, _y)
269 _ept = _active_layer.findObject(_pt)
270 if _ept is None:
271 _active_layer.addObject(_pt)
272 _objmap['point'][_obj] = _pt
273 else:
274 _objmap['point'][_obj] = _ept
275 elif isinstance(_obj, Segment):
276 if not _objmap.has_key('segment'):
277 _objmap['segment'] = {}
278 _cseg = _obj.clone()
279 _cseg.move(_x, _y)
280 _eseg = _active_layer.findObject(_cseg)
281 if _eseg is None:
282 _p1, _p2 = _cseg.getEndpoints()
283 _ep = _active_layer.findObject(_p1)
284 if _ep is None:
285 _active_layer.addObject(_p1)
286 else:
287 _cseg.setP1(_ep)
288 _ep = _active_layer.findObject(_p2)
289 if _ep is None:
290 _active_layer.addObject(_p2)
291 else:
292 _cseg.setP2(_ep)
293 _active_layer.addObject(_cseg)
294 else:
295 _objmap['segment'][_obj] = _eseg
296 elif isinstance(_obj, (Circle, Arc, CCircle)):
297 _cc = _obj.clone()
298 _cc.move(_x, _y)
299 _ec = _active_layer.findObject(_cc)
300 if _ec is None:
301 _cp = _cc.getCenter()
302 _ep = _active_layer.findObject(_cp)
303 if _ep is None:
304 _active_layer.addObject(_cp)
305 else:
306 _cc.setLocation(_ep)
307 _active_layer.addObject(_cc)
308 elif isinstance(_obj, (HCLine, VCLine, ACLine)):
309 _ccl = _obj.clone()
310 _ccl.move(_x, _y)
311 _ecl = _active_layer.findObject(_ccl)
312 if _ecl is None:
313 _lp = _ccl.getLocation()
314 _ep = _active_layer.findObject(_lp)
315 if _ep is None:
316 _active_layer.addObject(_lp)
317 else:
318 _ccl.setLocation(_ep)
319 _active_layer.addObject(_ccl)
320 elif isinstance(_obj, CLine):
321 _ccl = _obj.clone()
322 _ccl.move(_x, _y)
323 _ecl = _active_layer.findObject(_ccl)
324 if _ecl is None:
325 _p1, _p2 = _ccl.getKeypoints()
326 _ep = _active_layer.findObject(_p1)
327 if _ep is None:
328 _active_layer.addObject(_p1)
329 else:
330 _ccl.setP1(_ep)
331 _ep = _active_layer.findObject(_p2)
332 if _ep is None:
333 _active_layer.addObject(_p2)
334 else:
335 _ccl.setP2(_ep)
336 _active_layer.addObject(_ccl)
337 elif isinstance(_obj, LinearDimension):
338 if _active_layer.findObject(_obj) is None:
339 _l1, _l2 = _obj.getDimLayers()
340 if _image.hasLayer(_l1) and _image.hasLayer(_l2):
341 _p1, _p2 = _obj.getDimPoints()
342 _ds = _obj.getDimStyle()
343 if isinstance(_obj, HorizontalDimension):
344 _dtype = HorizontalDimension
345 elif isinstance(_obj, VerticalDimension):
346 _dtype = VerticalDimension
347 else:
348 _dtype = LinearDimension
349 _dim = _dtype(_l1, _p1, _l2, _p2, _x, _y, _ds)
350 _active_layer.addObject(_dim)
351 elif isinstance(_obj, RadialDimension):
352 if _active_layer.findObject(_obj) is None:
353 _lyr = _obj.getDimLayer()
354 if _image.hasLayer(_lyr):
355 _dc = _obj.getDimCircle()
356 _ds = _obj.getDimStyle()
357 _dim = RadialDimension(_lyr, _dc, _x, _y, _ds)
358 _active_layer.addObject(_dim)
359 elif isinstance(_obj, AngularDimension):
360 if _active_layer.findObject(_obj) is None:
361 _cl, _l1, _l2 = _obj.getDimLayers()
362 if (_image.hasLayer(_cl) and
363 _image.hasLayer(_l1) and
364 _image.hasLayer(_l2)):
365 _cp, _p1, _p2 = _obj.getDimPoints()
366 _ds = _obj.getDimStyle()
367 _dim = AngularDimension(_cl, _cp, _l1, _p1, _l2, _p2, _x, _y, _ds)
368 _active_layer.addObject(_dim)
369 elif isinstance(_obj, text.TextBlock):
370 _ntb = _obj.clone()
371 _ntb.setLocation(_x, _y)
372 _active_layer.addObject(_ntb)
373 else:
374 print "Unexpected type for pasting: " + `type(_obj)`
375 finally:
376 _image.endAction()
378 def paste_mode_init(gtkimage, tool=None):
379 gtkimage.setPrompt(_('Click where you want to paste the objects'))
380 _tool = gtkimage.getImage().getTool()
381 _tool.initialize()
382 _tool.setHandler("button_press", paste_button_press_cb)