def RemoveObjects(self, infolist): if not infolist: return NullUndo sliced = selinfo.list_to_tree_sliced(infolist) sliced.reverse() undo = [self.begin_change_children()] try: for start, end in sliced: if type(end) == IntType: # > 1 adjacent children of self. XXX implement this raise SketchInternalError('Deletion of multiple objects' ' of BlendGroups not yet' ' implemented') elif type(end) == ListType: # remove grandchildren (children of child of self) if start % 2 == 0: # control object changes. This should result in # a recompute() automatically. undo.append(self.objects[start].RemoveObjects(end)) else: pass else: # a single child. If it's one of our control # objects, remove self undo.append(self.do_remove_child(start)) undo.append(self.end_change_children()) return CreateListUndo(undo) except: Undo(CreateListUndo(undo)) raise
def DuplicateObjects(self, infolist, offset): infolist = list_to_tree2(infolist) objects = self.objects undo = [self.begin_change_children()] selection = [] added = 0 try: for idx, obj in infolist: idx = idx + added if type(obj) == ListType: # duplicate in subobj sel, undoinfo = objects[idx].DuplicateObjects(obj, offset) undo.append(undoinfo) selection = selection + prepend_idx(idx, sel) else: obj = obj.Duplicate() obj.Translate(offset) sel, undoinfo = self.Insert(obj, idx + 1) undo.append(undoinfo) selection.append(sel) added = added + 1 undo.append(self.end_change_children()) return (selection, CreateListUndo(undo)) except: Undo(CreateListUndo(undo)) raise
def do_remove_child(self, idx): undo = [] try: if idx % 2 == 0: # a control object if self.document is not None: undo.append(self.document.AddClearRect(self.bounding_rect)) if len(self.objects) > 3: if idx == 0: undo.append(self.remove(1)) undo.append(self.remove(0)) elif idx == len(self.objects) - 1: undo.append(self.remove(idx)) undo.append(self.remove(idx - 1)) else: steps = self.objects[idx + 1].Steps() \ + self.objects[idx - 1].Steps() u = (UndoAfter, CreateMultiUndo(self.remove(idx + 1), self.remove(idx)), self.objects[idx - 1].SetParameters(steps)) undo.append(u) else: # remove one of only two control objects -> Remove self undo.append(self.parent.Remove(self)) return CreateListUndo(undo) else: # XXX implement this case raise ValueError, 'BlendGroup: cannot remove non control child' except: Undo(CreateListUndo(undo)) raise
def MoveObjectsUp(self, infolist): sliced = list_to_tree_sliced(infolist) sliced.reverse() undo = [self.begin_change_children()] selection = [] permutation = range(len(self.objects)) objects = self.objects max = len(objects) try: for start, end in sliced: if type(end) == IntType: if end < max: temp = permutation[start:end] del permutation[start:end] permutation[start + 1:start + 1] = temp selection = selection + select_range( start + 1, objects[start:end]) else: selection = selection + select_range( start, objects[start:end]) elif type(end) == ListType: sel, undo_info = objects[start].MoveObjectsUp(end) if undo_info is not NullUndo: undo.append(undo_info) selection = selection + prepend_idx(start, sel) else: if start < max - 1: del permutation[start] permutation.insert(start + 1, start) selection.append(build_info(start + 1, objects[start])) else: selection.append(build_info(start, objects[start])) undo_info = self.permute_objects(permutation) if undo_info is not NullUndo: undo.append(undo_info) undo.append(self.end_change_children()) if len(undo) <= 2: undo = NullUndo selection = infolist else: undo = CreateListUndo(undo) return (selection, undo) except: Undo(CreateListUndo(undo)) raise
def ForAllUndo(self, func): # XXX: should we just change start and end and recompute? self.begin_change_children() undo = map(func, self.objects) self.end_change_children(ignore_child_changes=1) idx = range(0, len(self.objects), 2) undo = map(operator.getitem, [undo] * len(idx), idx) return CreateListUndo(undo)
def ForAllUndo(self, func): if self.objects: undo = [self.begin_change_children()] undo = undo + map(func, self.objects) undo.append(self.end_change_children()) return CreateListUndo(undo) else: return NullUndo
def ForAllUndo(self, func): undoinfo = self.for_all(func) self.del_lazy_attrs() if len(undoinfo) == 1: undoinfo = undoinfo[0] if type(undoinfo) == ListType: return CreateListUndo(undoinfo) return undoinfo
def RemoveObjects(self, infolist): if not infolist: return NullUndo sliced = list_to_tree_sliced(infolist) sliced.reverse() # important! undo = [self.begin_change_children()] try: for start, end in sliced: if type(end) == IntType: undo.append(self.RemoveSlice(start, end)) elif type(end) == ListType: undo.append(self.objects[start].RemoveObjects(end)) else: undo.append(self.Remove(end, start)) undo.append(self.end_change_children()) return CreateListUndo(undo) except: Undo(CreateListUndo(undo)) raise
def Transform(self, trafo): undo = [self.begin_change_children()] try: undo.append(PluginCompound.Transform(self, trafo)) undo.append(self.set_transformation(trafo(self.trafo))) undo.append(self.end_change_children()) except: undo.reverse() map(Undo, undo) raise return CreateListUndo(undo)
def ForAllUndo2(self, method, *args): t = time.clock() methods = map(getattr, self.GetObjects(), [method] * len(self.objects)) #print time.clock() - t, #undoinfo = self.for_all(func) undoinfo = map(apply, methods, [args] * len(methods)) #print time.clock() - t self.del_lazy_attrs() if len(undoinfo) == 1: undoinfo = undoinfo[0] if type(undoinfo) == ListType: return CreateListUndo(undoinfo) return undoinfo
def SetProperty(self, **kw): stack = self.stack undo = [] append = undo.append if len(stack) == 1 and not stack[0].is_dynamic: set = stack[0].SetProperty for prop, value in kw.items(): append(set(prop, value)) else: set = self.set_property for prop, value in kw.items(): append(set(prop, value)) if len(self.stack) > 1: undo_stack = (self.set_stack, self.stack[:]) if self.delete_shadowed_layers(): undo.append(undo_stack) undo = CreateListUndo(undo) undo = (UndoAfter, undo, self._clear_cache()) return undo
def undo_changes(self): Undo(CreateListUndo(self.undo))
def move_objects_to_top(self, infolist, to_bottom=0): # Implement the public methods MoveToTop (if to_bottom is false) # and MoveToBottom (if to_bottom is true). sliced = list_to_tree_sliced(infolist) sliced.reverse() undo = [self.begin_change_children()] selection = [] idxs = [] permutation = range(len(self.objects)) try: for start, end in sliced: if type(end) == IntType: # a contiguous range of self's children (start:end) idxs[:0] = permutation[start:end] del permutation[start:end] elif type(end) == ListType: # children of self.objects[start] child = self.objects[start] sel, undo_info = child.move_objects_to_top(end, to_bottom) if undo_info is not NullUndo: undo.append(undo_info) selection = selection + prepend_idx(start, sel) else: # a single object (self.object[start]) idxs.insert(0, start) del permutation[start] if idxs: # direct children of self are involved: apply the # permutation if to_bottom: permutation = idxs + permutation else: permutation = permutation + idxs undo_info = self.permute_objects(permutation) if undo_info is not NullUndo: undo.append(undo_info) # finished: undo.append(self.end_change_children()) if len(undo) <= 2: # We haven't really done anything (undo has length 2), # so we just pass the selection info back unchanged selection = infolist undo = NullUndo else: # We have done something, so figure out the new # selection info undo = CreateListUndo(undo) if to_bottom: selection = selection \ + select_range(0, self.objects[:len(idxs)]) else: min = len(self.objects) - len(idxs) selection = selection \ + select_range(min, self.objects[min:]) return (selection, undo) except: # Ooops, something's gone wrong. Undo everything we've done # so far... (hmm, this currently fails to undo everything if # undo.append(undo_info) fails... (the undo_info involved # would be lost)) Undo(CreateListUndo(undo)) raise