@Override public boolean addEdit(UndoableEdit anEdit) { if (super.addEdit(anEdit)) { if (mergeEditIndex >= MERGE_INDEX_NOT_INITIALIZED) { // Valid or not inited if (anEdit instanceof BaseDocumentEvent) { mergeEditIndex = size() - 1; } else if (anEdit.getClass() != BaseDocument.AtomicCompoundEdit.class && !CaretUndo.isCaretUndoEdit(anEdit) ) { mergeEditIndex = MERGE_PROHIBITED; // Do not allow merging if there are unknown undoable edits } } return true; } return false; }
/** Try to determine whether this event can replace the old one. * This is used to batch the one-letter modifications into larger * parts (words) and undoing/redoing them at once. * This method returns true whether */ public @Override boolean replaceEdit(UndoableEdit anEdit) { BaseDocument doc = (BaseDocument)getDocument(); if (anEdit instanceof BaseDocument.AtomicCompoundEdit) { BaseDocument.AtomicCompoundEdit compEdit = (BaseDocument.AtomicCompoundEdit)anEdit; BaseDocumentEvent aMergeEdit = compEdit.getMergeEdit(); if (!doc.undoMergeReset && aMergeEdit != null) { if (canMerge(aMergeEdit)) { previous = anEdit; return true; } } } else if (anEdit instanceof BaseDocumentEvent) { BaseDocumentEvent evt = (BaseDocumentEvent)anEdit; if (!doc.undoMergeReset && canMerge(evt)) { previous = anEdit; return true; } } doc.undoMergeReset = false; return false; }
public @Override void die() { // Super of die() int size = edits.size(); for (int i = size-1; i >= 0; i--) { UndoableEdit e = (UndoableEdit)edits.elementAt(i); e.die(); } alive2 = false; // End super of die() if (previous != null) { previous.die(); previous = null; } }
public void testWrapping() throws Exception { MimePath mimePath = MimePath.EMPTY; MockMimeLookup.setInstances(mimePath, new TestingUndoableEditWrapper(), new TestingUndoableEditWrapper2()); CESEnv env = new CESEnv(); Document doc = env.support.openDocument(); // doc.addUndoableEditListener(new UndoableEditListener() { // @Override // public void undoableEditHappened(UndoableEditEvent e) { // UndoableEdit edit = e.getEdit(); // } // }); doc.insertString(0, "Test", null); Class wrapEditClass = TestingUndoableEditWrapper.WrapCompoundEdit.class; assertNotNull(NbDocument.getEditToBeUndoneOfType(env.support, wrapEditClass)); Class wrapEditClass2 = TestingUndoableEditWrapper2.WrapCompoundEdit2.class; assertNotNull(NbDocument.getEditToBeUndoneOfType(env.support, wrapEditClass2)); // A trick to get whole edit UndoableEdit wholeEdit = NbDocument.getEditToBeUndoneOfType(env.support, UndoableEdit.class); assertTrue(wholeEdit instanceof List); @SuppressWarnings("unchecked") List<? extends UndoableEdit> listEdit = (List<? extends UndoableEdit>) wholeEdit; assertEquals(3, listEdit.size()); assertEquals(wrapEditClass, listEdit.get(1).getClass()); assertEquals(wrapEditClass2, listEdit.get(2).getClass()); }
@Test public void testAddCaretUndoableEdit() throws Exception { final JEditorPane pane = new JEditorPane("text/plain", "Haf"); //final CompoundEdit compoundEdit = new CompoundEdit(); final boolean[] editAdded = { false }; final Document doc = pane.getDocument(); doc.putProperty(CustomUndoDocument.class, new CustomUndoDocument() { @Override public void addUndoableEdit(UndoableEdit edit) { editAdded[0] = true; } }); final EditorCaret editorCaret = new EditorCaret(); SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { pane.setCaret(editorCaret); EditorUtilities.addCaretUndoableEdit(doc, editorCaret); } }); assertTrue(editAdded[0]); }
@Override public String getUndoPresentationName() { UndoableEdit last = lastEdit(); if (last != null) { return last.getUndoPresentationName(); } else { String name = getPresentationName(); if (!"".equals(name)) { name = UIManager.getString("AbstractUndoableEdit.undoText") + " " + name; } else { name = UIManager.getString("AbstractUndoableEdit.undoText"); } return name; } }
@Override public String getRedoPresentationName() { UndoableEdit last = lastEdit(); if (last != null) { return last.getRedoPresentationName(); } else { String name = getPresentationName(); if (!"".equals(name)) { name = UIManager.getString("AbstractUndoableEdit.redoText") + " " + name; } else { name = UIManager.getString("AbstractUndoableEdit.redoText"); } return name; } }
private static <T extends UndoableEdit> T getEditToBeUndoneRedoneOfType(EditorCookie ec, Class<T> type, boolean redone) { UndoRedo ur; if (ec instanceof CloneableEditorSupport && ((ur = ((CloneableEditorSupport)ec).getUndoRedo()) instanceof UndoRedoManager)) { UndoRedoManager urManager = (UndoRedoManager) ur; UndoableEdit edit = urManager.editToBeUndoneRedone(redone); if (type.isInstance(edit)) { return type.cast(edit); } else if (edit instanceof List) { @SuppressWarnings("unchecked") List<UndoableEdit> listEdit = (List<UndoableEdit>) edit; for (int i = listEdit.size() -1; i >= 0; i--) { // Go from most wrapped back edit = listEdit.get(i); if (type.isInstance(edit)) { @SuppressWarnings("unchecked") T inst = (T) edit; return inst; } } } } return null; }
@Override public UndoableEdit wrap(UndoableEdit ed, Document doc) { if (!active.get()) { return ed; } if (doc.getProperty(BaseDocument.StreamDescriptionProperty) == null) { //no dataobject return ed; } UndoableEditDelegate current = new UndoableEditDelegate(ed, (BaseDocument) doc, performer); UndoableEditDelegate first = docToFirst.get(doc); if (first == null) { docToFirst.put((BaseDocument) doc, current); } return current; }
@Override public boolean addEdit(UndoableEdit anEdit) { if (!isInProgress()) { return false; } else { UndoableEdit last = lastEdit(); // If this is the first subedit received, just add it. // Otherwise, give the last one a chance to absorb the new // one. If it won't, give the new one a chance to absorb // the last one. if (last == null) { edits.add(anEdit); } else if (!last.addEdit(anEdit)) { if (anEdit.replaceEdit(last)) { edits.remove(edits.size()-1); } edits.add(anEdit); } return true; } }
@Override public String getUndoPresentationName() { UndoableEdit last = lastEdit(); if (last != null) { return last.getUndoPresentationName(); } else { String name = getPresentationName(); if (!"".equals(name)) { name = NbBundle.getMessage(ContentEdit.class, "AbstractUndoableEdit.undoText.param", name); // NOI18N } else { name = NbBundle.getMessage(ContentEdit.class, "AbstractUndoableEdit.undoText"); // NOI18N } return name; } }
@Override public String getRedoPresentationName() { UndoableEdit last = lastEdit(); if (last != null) { return last.getRedoPresentationName(); } else { String name = getPresentationName(); if (!"".equals(name)) { name = NbBundle.getMessage(ContentEdit.class, "AbstractUndoableEdit.redoText.param", name); // NOI18N } else { name = NbBundle.getMessage(ContentEdit.class, "AbstractUndoableEdit.redoText"); // NOI18N } return name; } }
@Override public boolean addEdit(UndoableEdit edit) { if ((lastEdit() != null) && lastEdit().equals(edit)) { return false; } else { return super.addEdit(edit); } }
private void addEdit(UndoableEdit edit) { if (compoundEdits.isEmpty()) { UndoableEditEvent editEvent = new UndoableEditEvent(getMainList(), edit); for (UndoableEditListener l : editListeners) { l.undoableEditHappened(editEvent); } } else { compoundEdits.peek().addEdit(edit); } }
public static void main(String[] args) { final LinkedList<UndoableEdit> edits = new LinkedList<UndoableEdit>(); UndoableEditListener editListener = new UndoableEditListener() { @Override public void undoableEditHappened(UndoableEditEvent e) { System.out.println(e.getEdit()); edits.addFirst(e.getEdit()); } }; UndoableList<Integer> list = new UndoableList<Integer>(new LinkedList<Integer>()); list.addUndoableEditListener(editListener); for (int i = 1; i < 10; i++) { list.add(2*i); } System.out.println(list); list.add(6, 13); System.out.println(list); list.set(3, 7); System.out.println(list); List<Integer> subList = list.subList(3, 6); System.out.println(subList); subList.set(0, 8); System.out.println(list); System.out.println(subList); subList.remove(1); System.out.println("----------------------------------"); for (UndoableEdit edit : edits) { System.out.println("Undo " + edit); edit.undo(); System.out.println(list); } }
private void startNewEdit (JTextComponent component, UndoableEdit atomicEdit) { if (edit != null) { // finish the last edit edit.end(); } edit = new MyCompoundEdit(); edit.addEdit(atomicEdit); super.undoableEditHappened(new UndoableEditEvent(component, edit)); lastOffset = component.getCaretPosition(); lastLength = component.getDocument().getLength(); }
private static void duplicate(Node[] nodes, int dimension, int direction) { List<RADComponent> comps = FormUtils.getSelectedLayoutComponents(nodes); RADVisualContainer parent = (comps != null) ? getParent(comps) : null; if (parent != null) { FormModel formModel = parent.getFormModel(); LayoutModel layoutModel = formModel.getLayoutModel(); Object layoutUndoMark = layoutModel.getChangeMark(); UndoableEdit layoutEdit = layoutModel.getUndoableEdit(); boolean autoUndo = true; // in case of unexpected error, for robustness String[] sourceIds = new String[comps.size()]; String[] targetIds = new String[comps.size()]; int i = 0; MetaComponentCreator creator = formModel.getComponentCreator(); try { for (RADComponent comp : comps) { RADComponent copiedComp = creator.copyComponent(comp, parent); if (copiedComp == null) { return; // copy failed... } sourceIds[i] = comp.getId(); targetIds[i] = copiedComp.getId(); i++; } FormEditor.getFormDesigner(formModel).getLayoutDesigner() .duplicateLayout(sourceIds, targetIds, dimension, direction); autoUndo = false; } finally { if (layoutUndoMark != null && !layoutUndoMark.equals(layoutModel.getChangeMark())) { formModel.addUndoableEdit(layoutEdit); } if (autoUndo) { formModel.forceUndoOfCompoundEdit(); } } } }
@Override public void run() { if (wheelerBlocked) { wheelerBlocked = false; if (wheeler != null) { EventQueue.invokeLater(wheeler); } return; } wheeler = null; RADVisualComponent comp = getMouseWheelComponent(formDesigner, true); if (comp == component) { FormModel formModel = getFormModel(); LayoutModel layoutModel = getLayoutModel(); Object layoutUndoMark = layoutModel.getChangeMark(); javax.swing.undo.UndoableEdit ue = layoutModel.getUndoableEdit(); boolean autoUndo = true; try { mouseHint = formDesigner.getLayoutDesigner().mouseWheelMoved(coalesced, units); autoUndo = false; showToolTip(lastEvent); } finally { formModel.fireContainerLayoutChanged((RADVisualContainer)comp, null, null, null); if (!layoutUndoMark.equals(layoutModel.getChangeMark())) { formModel.addUndoableEdit(ue); } if (autoUndo) { formModel.forceUndoOfCompoundEdit(); } else { // successfully applied wheelerBlocked = true; // don't allow next changes until the current one is built in the designer EventQueue.invokeLater(this); } } } }
private void updateComponentLayer(final boolean fireChange) { if (formModel == null) { // the form can be closed just after opened, before this gets called (#70439) return; } if (getLayoutDesigner() == null) { return; } // Ensure that the components are laid out componentLayer.revalidate(); // Add componentLayer among components to validate RepaintManager.currentManager(componentLayer).validateInvalidComponents(); LayoutModel layoutModel = formModel.getLayoutModel(); // If after a change (FormModel has a compound edit started, i.e. it's not // just after form loaded) that was not primarily in layout, start undo // edit in LayoutModel as well: some changes can be done when updating to // actual visual state that was affected by changes elsewhere. UndoableEdit layoutUndoEdit = formModel.isCompoundEditInProgress() && !layoutModel.isUndoableEditInProgress() ? layoutModel.getUndoableEdit() : null; if (getLayoutDesigner().updateCurrentState() && fireChange) { formModel.fireFormChanged(true); // hack: to regenerate code once again } if (layoutModel.endUndoableEdit() && layoutUndoEdit != null) { formModel.addUndoableEdit(layoutUndoEdit); } updateResizabilityActions(); componentLayer.repaint(); }
/** * Aligns selected components in the specified direction. * * @param closed determines if closed group should be created. * @param dimension dimension to align in. * @param alignment requested alignment. */ void align(boolean closed, int dimension, int alignment) { // Check that the action is enabled Action action = null; Iterator iter = getDesignerActions(true).iterator(); while (iter.hasNext()) { Action candidate = (Action)iter.next(); if (candidate instanceof AlignAction) { AlignAction alignCandidate = (AlignAction)candidate; if ((alignCandidate.getAlignment() == alignment) && (alignCandidate.getDimension() == dimension)) { action = alignCandidate; break; } } } if ((action == null) || (!action.isEnabled())) { return; } Collection selectedIds = selectedLayoutComponentIds(); RADComponent parent = commonParent(selectedIds); LayoutModel layoutModel = formModel.getLayoutModel(); Object layoutUndoMark = layoutModel.getChangeMark(); javax.swing.undo.UndoableEdit ue = layoutModel.getUndoableEdit(); boolean autoUndo = true; try { getLayoutDesigner().align(selectedIds, closed, dimension, alignment); autoUndo = false; } finally { formModel.fireContainerLayoutChanged((RADVisualContainer)parent, null, null, null); if (!layoutUndoMark.equals(layoutModel.getChangeMark())) { formModel.addUndoableEdit(ue); } if (autoUndo) { formModel.forceUndoOfCompoundEdit(); } } }
UndoableEdit startOnSaveTasks() { assert (atomicDepth > 0); // Should only be called under atomic lock // If there would be any pending edits // fire them so that they don't clash with on-save tasks in undo manager. // Pending edits could occur due to an outer atomic lock // around CES.saveDocument(). Anyway it would generally be an undesirable situation // due to possibly invalid lock order (doc's atomic lock would then precede on-save tasks' locks). checkAndFireAtomicEdits(); ensureAtomicEditsInited(); return atomicEdits; }
public @Override boolean replaceEdit(UndoableEdit anEdit) { if (nonSignificant) { // Non-significant edit must be replacing previousEdit = anEdit; // Becomes significant nonSignificant = false; return true; } if (!undoMergeReset && mergeEditIndex >= 0) { // Only merge if this edit contains BaseDocumentEvent child item List<UndoableEdit> thisEdits = getEdits(); BaseDocumentEvent thisMergeEdit = (BaseDocumentEvent) thisEdits.get(mergeEditIndex); if (anEdit instanceof BaseDocument.AtomicCompoundEdit) { BaseDocument.AtomicCompoundEdit anAtomicEdit = (BaseDocument.AtomicCompoundEdit)anEdit; List<UndoableEdit> anAtomicEditChildren = anAtomicEdit.getEdits(); for (int i = 0; i < anAtomicEditChildren.size(); i++) { UndoableEdit child = (UndoableEdit)anAtomicEditChildren.get(i); if (child instanceof BaseDocumentEvent && thisMergeEdit.canMerge((BaseDocumentEvent)child)) { previousEdit = anEdit; return true; } } } else if (anEdit instanceof BaseDocumentEvent) { BaseDocumentEvent evt = (BaseDocumentEvent)anEdit; if (thisMergeEdit.canMerge(evt)) { previousEdit = anEdit; return true; } } } return false; }
private static void sendUndoableEdit(Document d, UndoableEdit ue) { if(d instanceof AbstractDocument) { UndoableEditListener[] uels = ((AbstractDocument)d).getUndoableEditListeners(); UndoableEditEvent ev = new UndoableEditEvent(d, ue); for(UndoableEditListener uel : uels) { uel.undoableEditHappened(ev); } } }
/** * Removes part of the content. * * @param where the starting position >= 0, where + nitems < length() * @param nitems the number of characters to remove >= 0 * @return an UndoableEdit object for undoing * @exception BadLocationException if the specified position is invalid * @see AbstractDocument.Content#remove */ public UndoableEdit remove(int where, int nitems) throws BadLocationException { if (where + nitems >= length()) { throw new BadLocationException("Invalid remove", length() + 1); } String removedString = getString(where, nitems); UndoableEdit edit = new RemoveUndo(where, removedString); replace(where, nitems, empty, 0); return edit; }
@Override public boolean addEdit(UndoableEdit anEdit) { if (anEdit instanceof MyEdit && ((MyEdit)anEdit).ignore) { return true; } return false; }
UndoableEdit removeUpdate(int removeOffset, int removeLength) { // The algorithm here is similar to the one in PlainDocument.removeUpdate(). // Unfortunately in case exactly a line element (or multiple line elements) // the algorithm removes extra line that follows the end of removed area. // That could be improved but compatibility with PlainDocument would be lost. Edit edit = null; int removeEndOffset = removeOffset + removeLength; int line0 = getElementIndex(removeOffset); int line1 = getElementIndex(removeEndOffset); if (line0 != line1) { // at least one line was removed line1++; // will remove the line where remove ends as well Element[] removeElements = new Element[line1 - line0]; copyElements(line0, line1, removeElements, 0); Element[] addElements = new Element[] { new LineElement(this, ((LineElement)removeElements[0]).getStartPosition(), ((LineElement)removeElements[removeElements.length - 1]).getEndPosition() ) }; replace(line0, removeElements.length, addElements); edit = new Edit(line0, removeElements, addElements); } // checkConsistency(); return edit; }
@Override public UndoableEdit wrap(UndoableEdit edit, Document doc) { WrapCompoundEdit2 wrapEdit = new WrapCompoundEdit2(); wrapEdit.addEdit(edit); wrapEdit.end(); return wrapEdit; }
private UndoableEditDelegate(UndoableEdit ed, DataObject dob, RefactoringSession session) { undoManager = UndoManager.getDefault(); ces = dob.getLookup().lookup(CloneableEditorSupport.class); //this.delegate = ed; this.inner = new CompoundEdit(); inner.addEdit(ed); delegate = ed; this.session = session; }
@Override public boolean addEdit(UndoableEdit ue) { if (ue instanceof List) { List<UndoableEdit> listEdit = (List<UndoableEdit>) ue; UndoableEdit topEdit = listEdit.get(listEdit.size() - 1); // Check that there's only original document's edit and the wrapping refactoring edit boolean refatoringEditOnly = listEdit.size() == 2; if (refatoringEditOnly && topEdit instanceof UndoableEditDelegate) { inner.addEdit(listEdit.get(0)); return true; } return false; } return false; }
private ModElement addModElement(UndoableEdit compoundEdit, int startOffset, int endOffset) { ModElement modElement = new ModElement(this, startOffset, endOffset); lastModElementIndex = findModElementIndex(startOffset, true); AddModElementEdit edit = new AddModElementEdit(lastModElementIndex, modElement); edit.run(); compoundEdit.addEdit(edit); return modElement; }
@Override public UndoableEdit insertString(int offset, String str) throws BadLocationException { checkOffsetInDoc(offset); UndoEdit edit = new UndoEdit(false, offset, str); insertEdit(edit); return edit; }
protected UndoableEdit lastEdit() { int count = edits.size(); if (count > 0) return edits.get(count-1); else return null; }
@Override public void undoableEditHappened(UndoableEditEvent e) { UndoableEdit edit = e.getEdit(); if (edit instanceof AbstractDocument.DefaultDocumentEvent) { try { AbstractDocument.DefaultDocumentEvent event = (AbstractDocument.DefaultDocumentEvent) edit; int start = event.getOffset(); int len = event.getLength(); String text = ""; if ("addition".equals(edit.getPresentationName())) { text = event.getDocument().getText(start, len); } boolean isNeedStart = false; if (current == null || lastEditName == null || !lastEditName.equals(edit.getPresentationName()) || text.contains("\n") && !"deletion".equals(edit.getPresentationName()) || Math.abs(lastOffset - start) > 1) { isNeedStart = true; } while (pointer < edits.size() - 1) { edits.remove(edits.size() - 1); isNeedStart = true; } if (isNeedStart) { createCompoundEdit(); } current.addEdit(edit); lastEditName = edit.getPresentationName(); lastOffset = start; } catch (BadLocationException e1) { if (logger.isDebugEnabled()) { logger.debug(e1, e1); } } } }
@Override public boolean replaceEdit(UndoableEdit anEdit) { if (undoRedoManager.isAtSavepoint()) { // Prohibit replacing at savepoint return false; } WrapUndoEdit wrapEdit = (WrapUndoEdit) anEdit; boolean replaced = delegate.replaceEdit(wrapEdit.delegate); undoRedoManager.checkLogOp("WrapUndoEdit.replaceEdit=" + replaced, anEdit); if (replaced) { undoRedoManager.checkReplaceSavepointEdit(wrapEdit, this); } return replaced; }
void sendUndoableEdit(Document d, UndoableEdit ue) { if(d instanceof AbstractDocument) { UndoableEditListener[] uels = ((AbstractDocument)d).getUndoableEditListeners(); UndoableEditEvent ev = new UndoableEditEvent(d, ue); for(UndoableEditListener uel : uels) { uel.undoableEditHappened(ev); } } }
private UndoableEditDelegate(UndoableEdit ed, BaseDocument doc, InstantRefactoringPerformer performer) { DataObject dob = (DataObject) doc.getProperty(BaseDocument.StreamDescriptionProperty); this.ces = dob.getLookup().lookup(CloneableEditorSupport.class); this.inner = new CompoundEdit(); this.inner.addEdit(ed); this.delegate = ed; this.performer = performer; }