This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 48427
Collapse All | Expand All

(-)diff/src/org/netbeans/api/diff/Difference.java (+6 lines)
Lines 62-67 Link Here
62
    /** Change type of difference - a portion of a file was changed in the other */
62
    /** Change type of difference - a portion of a file was changed in the other */
63
    public static final int CHANGE = 2;
63
    public static final int CHANGE = 2;
64
    
64
    
65
    public static class Kind {
66
67
        public Kind() {
68
        }
69
    }
70
    
65
    private int type = 0;
71
    private int type = 0;
66
    private int firstStart = 0;
72
    private int firstStart = 0;
67
    private int firstEnd = 0;
73
    private int firstEnd = 0;
(-)editor.lib/nbproject/project.xml (+5 lines)
Lines 202-207 Link Here
202
                        <recursive/>
202
                        <recursive/>
203
                    </test-dependency>
203
                    </test-dependency>
204
                    <test-dependency>
204
                    <test-dependency>
205
                        <code-name-base>org.netbeans.modules.editor.mimelookup</code-name-base>
206
                        <compile-dependency/>
207
                        <test/>
208
                    </test-dependency>
209
                    <test-dependency>
205
                        <code-name-base>org.netbeans.modules.editor.settings.storage</code-name-base>
210
                        <code-name-base>org.netbeans.modules.editor.settings.storage</code-name-base>
206
                        <recursive/>
211
                        <recursive/>
207
                        <compile-dependency/>
212
                        <compile-dependency/>
(-)editor.lib/src/org/netbeans/editor/BaseDocument.java (-3 / +18 lines)
Lines 45-51 Link Here
45
package org.netbeans.editor;
45
package org.netbeans.editor;
46
46
47
import java.awt.Font;
47
import java.awt.Font;
48
import java.beans.PropertyVetoException;
49
import java.beans.VetoableChangeListener;
48
import java.beans.VetoableChangeListener;
50
import java.util.Hashtable;
49
import java.util.Hashtable;
51
import java.util.Dictionary;
50
import java.util.Dictionary;
Lines 56-61 Link Here
56
import java.beans.PropertyChangeListener;
55
import java.beans.PropertyChangeListener;
57
import java.beans.PropertyChangeEvent;
56
import java.beans.PropertyChangeEvent;
58
import java.beans.PropertyChangeSupport;
57
import java.beans.PropertyChangeSupport;
58
import java.util.Collection;
59
import java.util.EventListener;
59
import java.util.EventListener;
60
import java.util.HashSet;
60
import java.util.HashSet;
61
import java.util.Set;
61
import java.util.Set;
Lines 112-122 Link Here
112
import org.netbeans.modules.editor.lib2.document.ReadWriteBuffer;
112
import org.netbeans.modules.editor.lib2.document.ReadWriteBuffer;
113
import org.netbeans.modules.editor.lib2.document.ReadWriteUtils;
113
import org.netbeans.modules.editor.lib2.document.ReadWriteUtils;
114
import org.netbeans.modules.editor.lib2.document.StableCompoundEdit;
114
import org.netbeans.modules.editor.lib2.document.StableCompoundEdit;
115
import org.netbeans.spi.editor.document.UndoableEditWrapper;
115
import org.netbeans.spi.lexer.MutableTextInput;
116
import org.netbeans.spi.lexer.MutableTextInput;
116
import org.netbeans.spi.lexer.TokenHierarchyControl;
117
import org.netbeans.spi.lexer.TokenHierarchyControl;
117
import org.openide.filesystems.FileObject;
118
import org.openide.filesystems.FileObject;
118
import org.openide.util.RequestProcessor;
119
import org.openide.util.RequestProcessor.Task;
120
import org.openide.util.WeakListeners;
119
import org.openide.util.WeakListeners;
121
120
122
/**
121
/**
Lines 346-351 Link Here
346
    
345
    
347
    private UndoableEdit removeUpdateLineUndo;
346
    private UndoableEdit removeUpdateLineUndo;
348
347
348
    private Collection<? extends UndoableEditWrapper> undoEditWrappers;
349
349
    private DocumentFilter.FilterBypass filterBypass;
350
    private DocumentFilter.FilterBypass filterBypass;
350
351
351
    private Preferences prefs;
352
    private Preferences prefs;
Lines 565-570 Link Here
565
566
566
        TrailingWhitespaceRemove.install(this);
567
        TrailingWhitespaceRemove.install(this);
567
568
569
        undoEditWrappers = MimeLookup.getLookup(mimeType).lookupAll(UndoableEditWrapper.class);
570
568
        if (weakPrefsListener == null) {
571
        if (weakPrefsListener == null) {
569
            // the listening could have already been initialized from setMimeType(), which
572
            // the listening could have already been initialized from setMimeType(), which
570
            // is called by some kits from initDocument()
573
            // is called by some kits from initDocument()
Lines 1571-1576 Link Here
1571
    }
1574
    }
1572
1575
1573
    protected @Override void fireUndoableEditUpdate(UndoableEditEvent e) {
1576
    protected @Override void fireUndoableEditUpdate(UndoableEditEvent e) {
1577
        // Possibly wrap contained edit
1578
        if (undoEditWrappers != null) {
1579
            UndoableEdit origEdit = e.getEdit();
1580
            UndoableEdit edit = origEdit;
1581
            for (UndoableEditWrapper wrapper : undoEditWrappers) {
1582
                edit = wrapper.wrap(edit, this);
1583
            }
1584
            if (edit != origEdit) {
1585
                e = new UndoableEditEvent(this, edit);
1586
            }
1587
        }
1588
        
1574
	// Fire to the list of listeners that was used before the atomic lock started
1589
	// Fire to the list of listeners that was used before the atomic lock started
1575
        // This fixes issue #47881 and appears to be somewhat more logical
1590
        // This fixes issue #47881 and appears to be somewhat more logical
1576
        // than the default approach to fire all the current listeners
1591
        // than the default approach to fire all the current listeners
(-)editor.lib/test/unit/src/org/netbeans/editor/TestingUndoableEditWrapper.java (+72 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.editor;
43
44
import javax.swing.text.Document;
45
import javax.swing.undo.CompoundEdit;
46
import javax.swing.undo.UndoableEdit;
47
import org.netbeans.spi.editor.document.UndoableEditWrapper;
48
49
/**
50
 *
51
 * @author mmetelka
52
 */
53
//@MimeRegistration(mimeType="", service=UndoableEditWrapper.class)
54
public class TestingUndoableEditWrapper implements UndoableEditWrapper {
55
56
    @Override
57
    public UndoableEdit wrap(UndoableEdit edit, Document doc) {
58
        WrapCompoundEdit wrapEdit = new WrapCompoundEdit();
59
        wrapEdit.addEdit(edit);
60
        wrapEdit.end();
61
        return wrapEdit;
62
    }
63
    
64
    static final class WrapCompoundEdit extends CompoundEdit {
65
        
66
        WrapCompoundEdit() {
67
        }
68
        
69
    }
70
71
    
72
}
(-)editor.lib/test/unit/src/org/netbeans/editor/UndoableEditWrapperTest.java (+80 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * Contributor(s):
28
 *
29
 * The Original Software is NetBeans. The Initial Developer of the Original
30
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
31
 * Microsystems, Inc. All Rights Reserved.
32
 *
33
 * If you wish your version of this file to be governed by only the CDDL
34
 * or only the GPL Version 2, indicate your decision by adding
35
 * "[Contributor] elects to include this software in this distribution
36
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
37
 * single choice of license, a recipient has the option to distribute
38
 * your version of this file under either the CDDL, the GPL Version 2 or
39
 * to extend the choice of license to its licensees as provided above.
40
 * However, if you add GPL Version 2 code and therefore, elected the GPL
41
 * Version 2 license, then the option applies only if the new code is
42
 * made subject to such option by the copyright holder.
43
 */
44
45
package org.netbeans.editor;
46
47
import javax.swing.event.UndoableEditEvent;
48
import javax.swing.event.UndoableEditListener;
49
import javax.swing.undo.UndoableEdit;
50
import org.netbeans.api.editor.mimelookup.MimePath;
51
import org.netbeans.api.editor.mimelookup.test.MockMimeLookup;
52
import org.netbeans.junit.NbTestCase;
53
54
/**
55
 *
56
 * @author Miloslav Metelka
57
 */
58
public class UndoableEditWrapperTest extends NbTestCase {
59
    
60
    /** Creates a new instance of ZOrderTest */
61
    public UndoableEditWrapperTest(String name) {
62
        super(name);
63
    }
64
    
65
    public void testWrapping() throws Exception {
66
        MimePath mimePath = MimePath.EMPTY;
67
        MockMimeLookup.setInstances(mimePath, new TestingUndoableEditWrapper());
68
        BaseDocument bDoc = new BaseDocument(false, "");
69
        bDoc.addUndoableEditListener(new UndoableEditListener() {
70
            @Override
71
            public void undoableEditHappened(UndoableEditEvent e) {
72
                UndoableEdit edit = e.getEdit();
73
                assertEquals("Expected WrapCompoundEdit.class",
74
                        TestingUndoableEditWrapper.WrapCompoundEdit.class, edit.getClass());
75
            }
76
        });
77
        bDoc.insertString(0, "Test", null);
78
    }
79
80
}
(-)editor.lib2/manifest.mf (-1 / +1 lines)
Lines 1-6 Link Here
1
Manifest-Version: 1.0
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.netbeans.modules.editor.lib2/1
2
OpenIDE-Module: org.netbeans.modules.editor.lib2/1
3
OpenIDE-Module-Implementation-Version: 26
3
OpenIDE-Module-Implementation-Version: 27
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/editor/lib2/Bundle.properties
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/editor/lib2/Bundle.properties
5
OpenIDE-Module-Layer: org/netbeans/modules/editor/lib2/resources/layer.xml
5
OpenIDE-Module-Layer: org/netbeans/modules/editor/lib2/resources/layer.xml
6
OpenIDE-Module-Needs: org.netbeans.modules.editor.actions
6
OpenIDE-Module-Needs: org.netbeans.modules.editor.actions
(-)editor.lib2/nbproject/project.properties (-1 / +1 lines)
Lines 43-49 Link Here
43
is.autoload=true
43
is.autoload=true
44
javac.source=1.6
44
javac.source=1.6
45
javac.compilerargs=-Xlint:unchecked
45
javac.compilerargs=-Xlint:unchecked
46
spec.version.base=1.55.0
46
spec.version.base=1.56.0
47
47
48
javadoc.arch=${basedir}/arch.xml
48
javadoc.arch=${basedir}/arch.xml
49
javadoc.apichanges=${basedir}/apichanges.xml
49
javadoc.apichanges=${basedir}/apichanges.xml
(-)editor.lib2/nbproject/project.xml (+1 lines)
Lines 188-193 Link Here
188
            <public-packages>
188
            <public-packages>
189
                <package>org.netbeans.api.editor</package>
189
                <package>org.netbeans.api.editor</package>
190
                <package>org.netbeans.spi.editor.codegen</package>
190
                <package>org.netbeans.spi.editor.codegen</package>
191
                <package>org.netbeans.spi.editor.document</package>
191
                <package>org.netbeans.spi.editor.highlighting</package>
192
                <package>org.netbeans.spi.editor.highlighting</package>
192
                <package>org.netbeans.spi.editor.highlighting.support</package>
193
                <package>org.netbeans.spi.editor.highlighting.support</package>
193
                <package>org.netbeans.spi.editor.typinghooks</package>
194
                <package>org.netbeans.spi.editor.typinghooks</package>
(-)editor.lib2/src/org/netbeans/spi/editor/document/UndoableEditWrapper.java (+68 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.spi.editor.document;
43
44
import javax.swing.text.Document;
45
import javax.swing.undo.UndoableEdit;
46
import org.netbeans.api.annotations.common.NonNull;
47
48
/**
49
 * Wrap undoable edits generated by document implementation into a custom undoable edit.
50
 * <br/>
51
 * Instances should be registered by using @MimeRegistration.
52
 *
53
 * @author Miloslav Metelka
54
 */
55
public interface UndoableEditWrapper {
56
    
57
    /**
58
     * Wrap given undoable edit by a custom undoable edit implementation
59
     * (or leave it as it is).
60
     *
61
     * @param edit original undoable edit generated by document (or previous wrapper).
62
     * @param doc document which generated the original undoable edit.
63
     * @return wrap edit or original edit.
64
     * @since 1.56
65
     */
66
    @NonNull UndoableEdit wrap(@NonNull UndoableEdit edit, @NonNull Document doc);
67
    
68
}
(-)java.navigation/src/org/netbeans/modules/java/navigation/ClassMemberPanel.java (-1 / +9 lines)
Lines 48-56 Link Here
48
import javax.swing.JComponent;
48
import javax.swing.JComponent;
49
import org.netbeans.api.java.source.ElementHandle;
49
import org.netbeans.api.java.source.ElementHandle;
50
import org.netbeans.spi.navigator.NavigatorPanel;
50
import org.netbeans.spi.navigator.NavigatorPanel;
51
import org.netbeans.spi.navigator.NavigatorPanelWithUndo;
52
import org.openide.awt.UndoRedo;
51
import org.openide.util.Lookup;
53
import org.openide.util.Lookup;
52
import org.openide.util.NbBundle;
54
import org.openide.util.NbBundle;
53
import org.openide.util.RequestProcessor;
55
import org.openide.util.RequestProcessor;
56
import org.openide.util.lookup.Lookups;
54
57
55
/**
58
/**
56
 *
59
 *
Lines 60-66 Link Here
60
    @NavigatorPanel.Registration(mimeType="text/x-java", position=100, displayName="#LBL_members"),
63
    @NavigatorPanel.Registration(mimeType="text/x-java", position=100, displayName="#LBL_members"),
61
    @NavigatorPanel.Registration(mimeType="application/x-class-file", displayName="#LBL_members")
64
    @NavigatorPanel.Registration(mimeType="application/x-class-file", displayName="#LBL_members")
62
})
65
})
63
public class ClassMemberPanel implements NavigatorPanel {
66
public class ClassMemberPanel implements NavigatorPanelWithUndo {
64
67
65
    private ClassMemberPanelUI component;
68
    private ClassMemberPanelUI component;
66
69
Lines 135-138 Link Here
135
    public static ClassMemberPanel getInstance() {
138
    public static ClassMemberPanel getInstance() {
136
        return INSTANCE;
139
        return INSTANCE;
137
    }    
140
    }    
141
142
    @Override
143
    public UndoRedo getUndoRedo() {
144
        return Lookups.forPath("org/netbeans/modules/refactoring").lookup(UndoRedo.class);
138
}
145
}
146
}
(-)openide.actions/src/org/openide/actions/Bundle.properties (+4 lines)
Lines 151-153 Link Here
151
MSG_GC=GC...
151
MSG_GC=GC...
152
CTL_GC=Click to force garbage collection
152
CTL_GC=Click to force garbage collection
153
153
154
LBL_CannotUndo=Cannot Undo
155
LBL_CannotRedo=Cannot Redo
156
157
(-)openide.actions/src/org/openide/actions/RedoAction.java (-7 / +8 lines)
Lines 43-49 Link Here
43
 */
43
 */
44
package org.openide.actions;
44
package org.openide.actions;
45
45
46
import java.awt.HeadlessException;
47
import java.util.MissingResourceException;
46
import javax.swing.Action;
48
import javax.swing.Action;
49
import javax.swing.JOptionPane;
47
import org.openide.awt.UndoRedo;
50
import org.openide.awt.UndoRedo;
48
import org.openide.util.HelpCtx;
51
import org.openide.util.HelpCtx;
49
import org.openide.util.Lookup;
52
import org.openide.util.Lookup;
Lines 52-67 Link Here
52
55
53
import javax.swing.UIManager;
56
import javax.swing.UIManager;
54
import javax.swing.undo.CannotRedoException;
57
import javax.swing.undo.CannotRedoException;
58
import javax.swing.undo.CannotUndoException;
55
import org.openide.util.ContextAwareAction;
59
import org.openide.util.ContextAwareAction;
56
import org.openide.util.Exceptions;
60
import org.openide.util.Exceptions;
61
import org.openide.windows.TopComponent;
62
import org.openide.windows.WindowManager;
57
63
58
64
59
/** Redo an edit. Since version 6.18 this class
65
60
* implements {@link ContextAwareAction}.
61
*
62
* @see UndoAction
63
* @author   Ian Formanek, Jaroslav Tulach
64
*/
65
public class RedoAction extends CallableSystemAction implements ContextAwareAction {
66
public class RedoAction extends CallableSystemAction implements ContextAwareAction {
66
    private static String SWING_DEFAULT_LABEL = UIManager.getString("AbstractUndoableEdit.redoText"); //NOI18N
67
    private static String SWING_DEFAULT_LABEL = UIManager.getString("AbstractUndoableEdit.redoText"); //NOI18N
67
68
Lines 106-112 Link Here
106
                undoRedo.redo();
107
                undoRedo.redo();
107
            }
108
            }
108
        } catch (CannotRedoException ex) {
109
        } catch (CannotRedoException ex) {
109
            Exceptions.printStackTrace(ex);
110
            UndoRedoAction.cannotUndoRedo(ex);
110
        }
111
        }
111
112
112
        UndoAction.updateStatus();
113
        UndoAction.updateStatus();
(-)openide.actions/src/org/openide/actions/UndoAction.java (-1 / +2 lines)
Lines 56-61 Link Here
56
import java.beans.*;
56
import java.beans.*;
57
import java.util.logging.Logger;
57
import java.util.logging.Logger;
58
import java.util.logging.Level;
58
import java.util.logging.Level;
59
import javax.swing.JOptionPane;
59
60
60
import javax.swing.SwingUtilities;
61
import javax.swing.SwingUtilities;
61
import javax.swing.UIManager;
62
import javax.swing.UIManager;
Lines 185-191 Link Here
185
                undoRedo.undo();
186
                undoRedo.undo();
186
            }
187
            }
187
        } catch (CannotUndoException ex) {
188
        } catch (CannotUndoException ex) {
188
            Exceptions.printStackTrace(ex);
189
            UndoRedoAction.cannotUndoRedo(ex);
189
        }
190
        }
190
191
191
        updateStatus();
192
        updateStatus();
(-)openide.actions/src/org/openide/actions/UndoRedoAction.java (-2 / +16 lines)
Lines 41-46 Link Here
41
package org.openide.actions;
41
package org.openide.actions;
42
42
43
import java.awt.EventQueue;
43
import java.awt.EventQueue;
44
import java.awt.HeadlessException;
44
import java.awt.event.ActionEvent;
45
import java.awt.event.ActionEvent;
45
import javax.swing.Action;
46
import javax.swing.Action;
46
import org.openide.awt.UndoRedo;
47
import org.openide.awt.UndoRedo;
Lines 53-61 Link Here
53
54
54
import java.beans.*;
55
import java.beans.*;
55
import java.util.Map;
56
import java.util.Map;
57
import java.util.MissingResourceException;
56
import java.util.logging.Logger;
58
import java.util.logging.Logger;
57
import java.util.logging.Level;
59
import java.util.logging.Level;
58
import javax.swing.AbstractAction;
60
import javax.swing.AbstractAction;
61
import javax.swing.JOptionPane;
59
62
60
import javax.swing.UIManager;
63
import javax.swing.UIManager;
61
import javax.swing.event.*;
64
import javax.swing.event.*;
Lines 221-237 Link Here
221
                undoRedo.undo();
224
                undoRedo.undo();
222
            }
225
            }
223
        } catch (CannotUndoException ex) {
226
        } catch (CannotUndoException ex) {
224
            Exceptions.printStackTrace(ex);
227
            cannotUndoRedo(ex);
225
        } else try {
228
        } else try {
226
            if (undoRedo.canRedo()) {
229
            if (undoRedo.canRedo()) {
227
                undoRedo.redo();
230
                undoRedo.redo();
228
            }
231
            }
229
        } catch (CannotRedoException ex) {
232
        } catch (CannotRedoException ex) {
230
            Exceptions.printStackTrace(ex);
233
            cannotUndoRedo(ex);
231
        }
234
        }
232
        run();
235
        run();
233
    }
236
    }
234
237
238
    static void cannotUndoRedo(RuntimeException ex) throws MissingResourceException, HeadlessException {
239
        if (ex.getMessage() != null) {
240
            JOptionPane.showMessageDialog(
241
                    WindowManager.getDefault().getMainWindow(),
242
                    ex.getMessage(),
243
                    NbBundle.getMessage(UndoRedoAction.class, ex instanceof CannotUndoException ? "LBL_CannotUndo" : "LBL_CannotRedo"),
244
                    JOptionPane.ERROR_MESSAGE);
245
        }
246
    }
247
248
235
    @Override
249
    @Override
236
    public void propertyChange(PropertyChangeEvent ev) {
250
    public void propertyChange(PropertyChangeEvent ev) {
237
        if (TopComponent.Registry.PROP_ACTIVATED.equals(ev.getPropertyName())) {
251
        if (TopComponent.Registry.PROP_ACTIVATED.equals(ev.getPropertyName())) {
(-)openide.text/src/org/openide/text/NbDocument.java (+25 lines)
Lines 51-56 Link Here
51
import javax.swing.JToolBar;
51
import javax.swing.JToolBar;
52
import javax.swing.SwingUtilities;
52
import javax.swing.SwingUtilities;
53
import javax.swing.text.*;
53
import javax.swing.text.*;
54
import javax.swing.undo.UndoableEdit;
55
import org.openide.awt.UndoRedo;
54
import org.openide.cookies.EditorCookie;
56
import org.openide.cookies.EditorCookie;
55
57
56
58
Lines 519-524 Link Here
519
        ((Annotatable) doc).removeAnnotation(annotation);
521
        ((Annotatable) doc).removeAnnotation(annotation);
520
    }
522
    }
521
523
524
    public static <T> T getEditToBeUndoneOfType(EditorCookie ec, Class<T> type) {
525
        return getEditToBeUndoneRedoneOfType(ec, type, false);
526
    }
527
    
528
    public static <T> T getEditToBeRedoneOfType(EditorCookie ec, Class<T> type) {
529
        return getEditToBeUndoneRedoneOfType(ec, type, true);
530
    }
531
    
532
    private static <T> T getEditToBeUndoneRedoneOfType(EditorCookie ec, Class<T> type, boolean redone) {
533
        UndoRedo ur;
534
        if (ec instanceof CloneableEditorSupport &&
535
                ((ur = ((CloneableEditorSupport)ec).getUndoRedo()) instanceof UndoRedoManager))
536
        {
537
            UndoRedoManager urManager = (UndoRedoManager) ur;
538
            UndoableEdit edit = urManager.editToBeUndoneRedone(redone);
539
            if (type.isInstance(edit)) {
540
                @SuppressWarnings("unchecked") T inst = (T) edit;
541
                return inst;
542
            }
543
        }
544
        return null;
545
    }
546
522
    /** Specialized version of document that knows how to lock the document
547
    /** Specialized version of document that knows how to lock the document
523
    * for complex modifications.
548
    * for complex modifications.
524
    */
549
    */
(-)openide.text/src/org/openide/text/UndoRedoManager.java (+5 lines)
Lines 564-569 Link Here
564
        undoGroup = null;
564
        undoGroup = null;
565
    }
565
    }
566
566
567
    UndoableEdit editToBeUndoneRedone(boolean redone) { // Access for NbDocument
568
        WrapUndoEdit wrapEdit = (WrapUndoEdit) (redone ? editToBeRedone() : editToBeUndone());
569
        return wrapEdit.delegate();
570
    }
571
567
    static String editToString(UndoableEdit edit) {
572
    static String editToString(UndoableEdit edit) {
568
        if (edit instanceof WrapUndoEdit) {
573
        if (edit instanceof WrapUndoEdit) {
569
            return toStringTerse(edit) + "->" + toStringTerse(((WrapUndoEdit)edit).delegate()); // NOI18N
574
            return toStringTerse(edit) + "->" + toStringTerse(((WrapUndoEdit)edit).delegate()); // NOI18N
(-)openide.text/test/unit/src/org/openide/text/EditToBeUndoneRedoneTest.java (+285 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * Contributor(s):
28
 *
29
 * The Original Software is NetBeans. The Initial Developer of the Original
30
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
31
 * Microsystems, Inc. All Rights Reserved.
32
 *
33
 * If you wish your version of this file to be governed by only the CDDL
34
 * or only the GPL Version 2, indicate your decision by adding
35
 * "[Contributor] elects to include this software in this distribution
36
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
37
 * single choice of license, a recipient has the option to distribute
38
 * your version of this file under either the CDDL, the GPL Version 2 or
39
 * to extend the choice of license to its licensees as provided above.
40
 * However, if you add GPL Version 2 code and therefore, elected the GPL
41
 * Version 2 license, then the option applies only if the new code is
42
 * made subject to such option by the copyright holder.
43
 */
44
45
package org.openide.text;
46
47
import java.beans.PropertyChangeListener;
48
import java.beans.PropertyChangeSupport;
49
import java.beans.VetoableChangeListener;
50
import java.io.ByteArrayInputStream;
51
import java.io.ByteArrayOutputStream;
52
import java.io.IOException;
53
import java.io.InputStream;
54
import java.io.OutputStream;
55
import java.io.Serializable;
56
import java.util.Date;
57
import javax.swing.event.UndoableEditEvent;
58
import javax.swing.text.AttributeSet;
59
import javax.swing.text.BadLocationException;
60
import javax.swing.text.Document;
61
import javax.swing.text.EditorKit;
62
import javax.swing.text.Position;
63
import javax.swing.text.StyledDocument;
64
import javax.swing.undo.AbstractUndoableEdit;
65
import javax.swing.undo.CannotRedoException;
66
import javax.swing.undo.CannotUndoException;
67
import javax.swing.undo.CompoundEdit;
68
import javax.swing.undo.UndoableEdit;
69
import org.netbeans.junit.NbTestCase;
70
import org.openide.awt.UndoRedo;
71
import org.openide.cookies.EditorCookie;
72
import org.openide.text.CloneableEditorSupport.Env;
73
import org.openide.util.Exceptions;
74
import org.openide.util.Lookup;
75
import org.openide.util.RequestProcessor;
76
import org.openide.util.RequestProcessor.Task;
77
import org.openide.windows.CloneableOpenSupport;
78
import org.openide.windows.CloneableTopComponent;
79
80
/**
81
 * Deadlock of a thread simulating reloading of document and another thread trying to close the file.
82
 * 
83
 * @author Miloslav Metelka
84
 */
85
public class EditToBeUndoneRedoneTest extends NbTestCase
86
implements CloneableEditorSupport.Env {
87
    static {
88
        System.setProperty("org.openide.windows.DummyWindowManager.VISIBLE", "false");
89
    }
90
    /** the support to work with */
91
    private transient CES support;
92
93
    // Env variables
94
    private transient String content = "";
95
    private transient boolean valid = true;
96
    private transient boolean modified = false;
97
    /** if not null contains message why this document cannot be modified */
98
    private transient String cannotBeModified;
99
    private transient Date date = new Date ();
100
    private transient final PropertyChangeSupport pcl;
101
    private transient VetoableChangeListener vetoL;
102
    
103
    private transient volatile boolean inReloadBeforeSupportLock;
104
    private transient volatile boolean closing;
105
    
106
    private static EditToBeUndoneRedoneTest RUNNING;
107
    
108
    public EditToBeUndoneRedoneTest(String s) {
109
        super(s);
110
        pcl = new PropertyChangeSupport(this);
111
    }
112
    
113
    protected void setUp () {
114
        support = new CES (this, Lookup.EMPTY);
115
        RUNNING = this;
116
    }
117
    
118
    protected boolean runInEQ() {
119
        return false;
120
    }
121
122
    @Override
123
    protected int timeOut() {
124
        return 15000;
125
    }
126
    
127
    private Object writeReplace () {
128
        return new Replace ();
129
    }
130
    
131
    public void testUndoRedoEdits() throws Exception {
132
        Document doc = support.openDocument();
133
        doc.insertString(0, "a", null);
134
        UndoRedo.Manager ur = support.getUndoRedo();
135
        MyEdit myEdit = NbDocument.getEditToBeUndoneOfType(support, MyEdit.class);
136
        assertNotNull("Expected valid myEdit", myEdit);
137
        ur.undo();
138
        myEdit = NbDocument.getEditToBeRedoneOfType(support, MyEdit.class);
139
        assertNotNull("Expected valid myEdit", myEdit);
140
    }
141
    
142
    //
143
    // Implementation of the CloneableEditorSupport.Env
144
    //
145
    
146
    public synchronized void addPropertyChangeListener(PropertyChangeListener l) {
147
        pcl.addPropertyChangeListener(l);
148
    }    
149
    public synchronized void removePropertyChangeListener(PropertyChangeListener l) {
150
        pcl.removePropertyChangeListener(l);
151
    }
152
    
153
    public synchronized void addVetoableChangeListener(VetoableChangeListener l) {
154
        assertNull ("This is the first veto listener", vetoL);
155
        vetoL = l;
156
    }
157
    public void removeVetoableChangeListener(VetoableChangeListener l) {
158
        assertEquals ("Removing the right veto one", vetoL, l);
159
        vetoL = null;
160
    }
161
    
162
    public CloneableOpenSupport findCloneableOpenSupport() {
163
        return RUNNING.support;
164
    }
165
    
166
    public String getMimeType() {
167
        return "text/plain";
168
    }
169
    
170
    public Date getTime() {
171
        return date;
172
    }
173
    
174
    public InputStream inputStream() throws IOException {
175
        return new ByteArrayInputStream (content.getBytes ());
176
    }
177
    public OutputStream outputStream() throws IOException {
178
        class ContentStream extends ByteArrayOutputStream {
179
            public void close () throws IOException {
180
                super.close ();
181
                content = new String (toByteArray ());
182
            }
183
        }
184
        
185
        return new ContentStream ();
186
    }
187
    
188
    public boolean isValid() {
189
        return valid;
190
    }
191
    
192
    public boolean isModified() {
193
        return modified;
194
    }
195
196
    public void markModified() throws IOException {
197
        if (cannotBeModified != null) {
198
            final String notify = cannotBeModified;
199
            IOException e = new IOException () {
200
                public String getLocalizedMessage () {
201
                    return notify;
202
                }
203
            };
204
            Exceptions.attachLocalizedMessage(e, cannotBeModified);
205
            throw e;
206
        }
207
        
208
        modified = true;
209
    }
210
    
211
    public void unmarkModified() {
212
        modified = false;
213
    }
214
    
215
    /** Implementation of the CES */
216
    private static final class CES extends CloneableEditorSupport implements EditorCookie {
217
        public CES (Env env, Lookup l) {
218
            super (env, l);
219
        }
220
        
221
        @Override
222
        protected EditorKit createEditorKit () {
223
            // Important to use NbLikeEditorKit since otherwise FilterDocument
224
            // would be created with improper runAtomic()
225
            return new MyKit ();
226
        }
227
        public CloneableTopComponent.Ref getRef () {
228
            return allEditors;
229
        }
230
        
231
        protected String messageName() {
232
            return "Name";
233
        }
234
        
235
        protected String messageOpened() {
236
            return "Opened";
237
        }
238
        
239
        protected String messageOpening() {
240
            return "Opening";
241
        }
242
        
243
        protected String messageSave() {
244
            return "Save";
245
        }
246
        
247
        protected String messageToolTip() {
248
            return "ToolTip";
249
        }
250
        
251
    }
252
253
    private static final class Replace implements Serializable {
254
        public Object readResolve () {
255
            return RUNNING;
256
        }
257
    }
258
259
    private static final class MyEdit extends CompoundEdit { // Marker custom undo edit
260
        
261
    }
262
    
263
    private static final class MyKit extends NbLikeEditorKit {
264
265
        @Override
266
        public Document createDefaultDocument() {
267
            return new Doc() {
268
269
                @Override
270
                protected void fireUndoableEditUpdate(UndoableEditEvent e) {
271
                    UndoableEdit edit = e.getEdit();
272
                    MyEdit wrapEdit = new MyEdit();
273
                    wrapEdit.addEdit(edit);
274
                    wrapEdit.end();
275
                    e = new UndoableEditEvent(e.getSource(), wrapEdit);
276
277
                    super.fireUndoableEditUpdate(e);
278
                }
279
280
            };
281
        }
282
        
283
        
284
    }
285
}
(-)projectui/src/org/netbeans/modules/project/ui/ProjectTab.java (-1 / +8 lines)
Lines 101-106 Link Here
101
import org.openide.awt.ActionReferences;
101
import org.openide.awt.ActionReferences;
102
import org.openide.awt.ActionRegistration;
102
import org.openide.awt.ActionRegistration;
103
import org.openide.awt.StatusDisplayer;
103
import org.openide.awt.StatusDisplayer;
104
import org.openide.awt.UndoRedo;
104
import org.openide.explorer.ExplorerManager;
105
import org.openide.explorer.ExplorerManager;
105
import org.openide.explorer.ExplorerUtils;
106
import org.openide.explorer.ExplorerUtils;
106
import org.openide.explorer.view.BeanTreeView;
107
import org.openide.explorer.view.BeanTreeView;
Lines 125-130 Link Here
125
import org.openide.util.RequestProcessor.Task;
126
import org.openide.util.RequestProcessor.Task;
126
import org.openide.util.Utilities;
127
import org.openide.util.Utilities;
127
import org.openide.util.WeakListeners;
128
import org.openide.util.WeakListeners;
129
import org.openide.util.lookup.Lookups;
128
import org.openide.windows.TopComponent;
130
import org.openide.windows.TopComponent;
129
import org.openide.windows.WindowManager;
131
import org.openide.windows.WindowManager;
130
132
Lines 135-141 Link Here
135
 * @author Petr Hrebejk
137
 * @author Petr Hrebejk
136
 */
138
 */
137
public class ProjectTab extends TopComponent 
139
public class ProjectTab extends TopComponent 
138
                        implements ExplorerManager.Provider, PropertyChangeListener {
140
                        implements ExplorerManager.Provider, PropertyChangeListener, UndoRedo.Provider {
139
                
141
                
140
    public static final String ID_LOGICAL = "projectTabLogical_tc"; // NOI18N                            
142
    public static final String ID_LOGICAL = "projectTabLogical_tc"; // NOI18N                            
141
    public static final String ID_PHYSICAL = "projectTab_tc"; // NOI18N                        
143
    public static final String ID_PHYSICAL = "projectTab_tc"; // NOI18N                        
Lines 248-253 Link Here
248
        return manager;
250
        return manager;
249
    }
251
    }
250
    
252
    
253
    @Override
254
    public UndoRedo getUndoRedo() {
255
        return Lookups.forPath("org/netbeans/modules/refactoring").lookup(UndoRedo.class);
256
    }    
257
    
251
    /* Singleton accessor. As ProjectTab is persistent singleton this
258
    /* Singleton accessor. As ProjectTab is persistent singleton this
252
     * accessor makes sure that ProjectTab is deserialized by window system.
259
     * accessor makes sure that ProjectTab is deserialized by window system.
253
     * Uses known unique TopComponent ID TC_ID = "projectTab_tc" to get ProjectTab instance
260
     * Uses known unique TopComponent ID TC_ID = "projectTab_tc" to get ProjectTab instance
(-)refactoring.api/apichanges.xml (+16 lines)
Lines 49-54 Link Here
49
    <apidef name="refactoring">Refactoring API</apidef>
49
    <apidef name="refactoring">Refactoring API</apidef>
50
</apidefs>
50
</apidefs>
51
<changes>
51
<changes>
52
    <change id="RefactoringCommit">
53
        <api name="refactoring"/>
54
        <summary>Added RefactoringCommit and ModificationResult SPI classes.</summary>
55
        <version major="1" minor="23"/>
56
        <date day="2" month="3" year="2011"/>
57
        <author login="jbecicka"/>
58
        <compatibility addition="yes"/>
59
        <description>
60
            <p>
61
                Added RefactoringCommit and ModificationResult SPI classes.
62
            </p>    
63
        </description>
64
        <class package="org.netbeans.modules.refactoring.spi" name="ModificationResult"/>
65
        <class package="org.netbeans.modules.refactoring.spi" name="RefactoringCommit"/>
66
        <issue number="209110"/>
67
    </change>
52
    <change id="CopyRefactoring">
68
    <change id="CopyRefactoring">
53
        <api name="refactoring"/>
69
        <api name="refactoring"/>
54
        <summary>Added CopyRefactoring to support Copy of multiple files.</summary>
70
        <summary>Added CopyRefactoring to support Copy of multiple files.</summary>
(-)refactoring.api/nbproject/project.xml (-10 / +19 lines)
Lines 46-55 Link Here
46
                    <compile-dependency/>
46
                    <compile-dependency/>
47
                    <run-dependency>
47
                    <run-dependency>
48
                        <release-version>3</release-version>
48
                        <release-version>3</release-version>
49
                        <specification-version>3.1</specification-version>
49
                        <specification-version>3.20.1</specification-version>
50
                    </run-dependency>
50
                    </run-dependency>
51
                </dependency>
51
                </dependency>
52
                <dependency>
52
                <dependency>
53
                    <code-name-base>org.netbeans.modules.editor.lib2</code-name-base>
54
                    <build-prerequisite/>
55
                    <compile-dependency/>
56
                    <run-dependency>
57
                        <release-version>1</release-version>
58
                        <specification-version>1.56</specification-version>
59
                    </run-dependency>
60
                </dependency>
61
                <dependency>
53
                    <code-name-base>org.netbeans.modules.editor.mimelookup</code-name-base>
62
                    <code-name-base>org.netbeans.modules.editor.mimelookup</code-name-base>
54
                    <build-prerequisite/>
63
                    <build-prerequisite/>
55
                    <compile-dependency/>
64
                    <compile-dependency/>
Lines 59-64 Link Here
59
                    </run-dependency>
68
                    </run-dependency>
60
                </dependency>
69
                </dependency>
61
                <dependency>
70
                <dependency>
71
                    <code-name-base>org.netbeans.modules.parsing.api</code-name-base>
72
                    <build-prerequisite/>
73
                    <compile-dependency/>
74
                    <run-dependency>
75
                        <release-version>1</release-version>
76
                        <specification-version>1.51</specification-version>
77
                    </run-dependency>
78
                </dependency>
79
                <dependency>
62
                    <code-name-base>org.netbeans.modules.projectapi</code-name-base>
80
                    <code-name-base>org.netbeans.modules.projectapi</code-name-base>
63
                    <build-prerequisite/>
81
                    <build-prerequisite/>
64
                    <compile-dependency/>
82
                    <compile-dependency/>
Lines 175-189 Link Here
175
                        <specification-version>6.6</specification-version>
193
                        <specification-version>6.6</specification-version>
176
                    </run-dependency>
194
                    </run-dependency>
177
                </dependency>
195
                </dependency>
178
                <dependency>
179
                    <code-name-base>org.netbeans.modules.parsing.api</code-name-base>
180
                    <build-prerequisite/>
181
                    <compile-dependency/>
182
                    <run-dependency>
183
                        <release-version>1</release-version>
184
                        <specification-version>1.51</specification-version>
185
                    </run-dependency>
186
                </dependency>
187
            </module-dependencies>
196
            </module-dependencies>
188
            <test-dependencies>
197
            <test-dependencies>
189
                <test-type>
198
                <test-type>
(-)refactoring.api/src/org/netbeans/modules/refactoring/api/RefactoringSession.java (-2 / +51 lines)
Lines 53-67 Link Here
53
import java.util.concurrent.atomic.AtomicBoolean;
53
import java.util.concurrent.atomic.AtomicBoolean;
54
import java.util.logging.Level;
54
import java.util.logging.Level;
55
import java.util.logging.Logger;
55
import java.util.logging.Logger;
56
import javax.swing.text.Document;
56
import org.netbeans.api.annotations.common.CheckForNull;
57
import org.netbeans.api.annotations.common.CheckForNull;
57
import org.netbeans.api.annotations.common.NonNull;
58
import org.netbeans.api.annotations.common.NonNull;
59
import org.netbeans.api.editor.mimelookup.MimeLookup;
60
import org.netbeans.editor.BaseDocument;
58
import org.netbeans.modules.refactoring.api.impl.ProgressSupport;
61
import org.netbeans.modules.refactoring.api.impl.ProgressSupport;
59
import org.netbeans.modules.refactoring.api.impl.SPIAccessor;
62
import org.netbeans.modules.refactoring.api.impl.SPIAccessor;
60
import org.netbeans.modules.refactoring.spi.RefactoringElementImplementation;
63
import org.netbeans.modules.refactoring.spi.RefactoringElementImplementation;
61
import org.netbeans.modules.refactoring.spi.RefactoringElementsBag;
64
import org.netbeans.modules.refactoring.spi.RefactoringElementsBag;
65
import org.netbeans.modules.refactoring.spi.RefactoringCommit;
62
import org.netbeans.modules.refactoring.spi.Transaction;
66
import org.netbeans.modules.refactoring.spi.Transaction;
63
import org.netbeans.modules.refactoring.spi.impl.UndoManager;
67
import org.netbeans.modules.refactoring.spi.impl.UndoManager;
68
import org.netbeans.modules.refactoring.spi.impl.UndoableWrapper;
69
import org.netbeans.spi.editor.document.UndoableEditWrapper;
64
import org.openide.LifecycleManager;
70
import org.openide.LifecycleManager;
71
import org.openide.cookies.EditorCookie;
72
import org.openide.filesystems.FileObject;
73
import org.openide.loaders.DataObject;
74
import org.openide.loaders.DataObjectNotFoundException;
65
import org.openide.util.Exceptions;
75
import org.openide.util.Exceptions;
66
import org.openide.util.Parameters;
76
import org.openide.util.Parameters;
67
77
Lines 128-136 Link Here
128
                    }
138
                    }
129
                }
139
                }
130
            } finally {
140
            } finally {
141
                UndoableWrapper wrapper = MimeLookup.getLookup("").lookup(UndoableWrapper.class);
131
                for (Transaction commit:SPIAccessor.DEFAULT.getCommits(bag)) {
142
                for (Transaction commit:SPIAccessor.DEFAULT.getCommits(bag)) {
143
                    setWrappers(commit, wrapper);
132
                    commit.commit();
144
                    commit.commit();
145
                    unsetWrappers(commit, wrapper);
133
                }
146
                }
147
                wrapper.close();
134
            }
148
            }
135
            if (saveAfterDone) {
149
            if (saveAfterDone) {
136
                LifecycleManager.getDefault().saveAll();
150
                LifecycleManager.getDefault().saveAll();
Lines 175-184 Link Here
175
                    f.undoChange();
189
                    f.undoChange();
176
                }
190
                }
177
            }
191
            }
192
            UndoableWrapper wrapper = MimeLookup.getLookup("").lookup(UndoableWrapper.class);
178
            for (ListIterator<Transaction> commitIterator = commits.listIterator(commits.size()); commitIterator.hasPrevious();) {
193
            for (ListIterator<Transaction> commitIterator = commits.listIterator(commits.size()); commitIterator.hasPrevious();) {
179
                commitIterator.previous().rollback();
194
                final Transaction commit = commitIterator.previous();
195
                setWrappers(commit, wrapper);
196
                commit.rollback();
197
                unsetWrappers(commit, wrapper);
180
            }
198
            }
181
            
199
            wrapper.close();
182
            while (it.hasPrevious()) {
200
            while (it.hasPrevious()) {
183
                fireProgressListenerStep();
201
                fireProgressListenerStep();
184
                RefactoringElementImplementation element = (RefactoringElementImplementation) it.previous();
202
                RefactoringElementImplementation element = (RefactoringElementImplementation) it.previous();
Lines 254-259 Link Here
254
        }
272
        }
255
    }
273
    }
256
    
274
    
275
    private void setWrappers(Transaction commit, UndoableWrapper wrap) {
276
        wrap.setActive(true);
277
        
278
        //        if (!(commit instanceof RefactoringCommit))
279
        //            return;
280
        //        for (FileObject f:((RefactoringCommit) commit).getModifiedFiles()) {
281
        //            Document doc = getDocument(f);
282
        //            if (doc!=null)
283
        //                doc.putProperty(BaseDocument.UndoableEditWrapper.class, wrap);
284
        //        }
285
    }
286
287
    private void unsetWrappers(Transaction commit, UndoableWrapper wrap) {
288
        wrap.setActive(false);
289
290
        //        setWrappers(commit, null);
291
    }
292
293
    private Document getDocument(FileObject f) {
294
        try {
295
            DataObject dob = DataObject.find(f);
296
            EditorCookie cookie = dob.getLookup().lookup(EditorCookie.class);
297
            if (cookie == null)
298
                return null;
299
            return cookie.getDocument();
300
        } catch (DataObjectNotFoundException ex) {
301
            return null;
302
        }
303
    }
304
305
    
257
    private class ElementsCollection extends AbstractCollection<RefactoringElement> {
306
    private class ElementsCollection extends AbstractCollection<RefactoringElement> {
258
        @Override
307
        @Override
259
        public Iterator<RefactoringElement> iterator() {
308
        public Iterator<RefactoringElement> iterator() {
(-)refactoring.api/src/org/netbeans/modules/refactoring/api/resources/layer.xml (-5 / +2 lines)
Lines 54-64 Link Here
54
                <attr name="position" intvalue="400"/>
54
                <attr name="position" intvalue="400"/>
55
                <attr name="misplaced.action.allowed" boolvalue="true"/>
55
                <attr name="misplaced.action.allowed" boolvalue="true"/>
56
            </file>
56
            </file>
57
            <file name="UndoSeparator.instance">
58
                <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
59
                <attr name="position" intvalue="1900"/>
60
            </file>
61
            
62
        </folder>
57
        </folder>
63
        
58
        
64
        <folder name="Window">
59
        <folder name="Window">
Lines 82-87 Link Here
82
        <file name="RefactoringAll.instance">
77
        <file name="RefactoringAll.instance">
83
            <attr name="instanceCreate" methodvalue="org.netbeans.modules.refactoring.api.ui.RefactoringActionsFactory.popupSubmenuAction"/>
78
            <attr name="instanceCreate" methodvalue="org.netbeans.modules.refactoring.api.ui.RefactoringActionsFactory.popupSubmenuAction"/>
84
        </file>
79
        </file>
80
        <file name="org-netbeans-modules-refactoring-spi-impl-RedoAction.instance_hidden"/>
81
            <file name="org-netbeans-modules-refactoring-spi-impl-UndoAction.instance_hidden"/>
85
    </folder>
82
    </folder>
86
83
87
  <folder name="Window">
84
  <folder name="Window">
(-)refactoring.api/src/org/netbeans/modules/refactoring/spi/BackupFacility.java (+2 lines)
Lines 96-102 Link Here
96
 * @see RefactoringElementsBag#addFileChange
96
 * @see RefactoringElementsBag#addFileChange
97
 * @see BackupFacility.Handle
97
 * @see BackupFacility.Handle
98
 * @author Jan Becicka
98
 * @author Jan Becicka
99
 * @deprecated 
99
 */
100
 */
101
@Deprecated
100
public abstract class BackupFacility {
102
public abstract class BackupFacility {
101
    
103
    
102
    private BackupFacility() {
104
    private BackupFacility() {
(-)refactoring.api/src/org/netbeans/modules/refactoring/spi/BackupFacility2.java (-51 / +267 lines)
Lines 41-76 Link Here
41
 * Version 2 license, then the option applies only if the new code is
41
 * Version 2 license, then the option applies only if the new code is
42
 * made subject to such option by the copyright holder.
42
 * made subject to such option by the copyright holder.
43
 */
43
 */
44
45
package org.netbeans.modules.refactoring.spi;
44
package org.netbeans.modules.refactoring.spi;
46
45
47
import java.io.File;
46
import java.io.*;
48
import java.io.FileInputStream;
47
import java.net.MalformedURLException;
49
import java.io.FileOutputStream;
50
import java.io.IOException;
51
import java.io.InputStream;
52
import java.io.OutputStream;
53
import java.net.URI;
48
import java.net.URI;
54
import java.net.URISyntaxException;
49
import java.net.URISyntaxException;
55
import java.util.ArrayList;
50
import java.security.DigestInputStream;
56
import java.util.Collection;
51
import java.security.MessageDigest;
57
import java.util.HashMap;
52
import java.security.NoSuchAlgorithmException;
58
import java.util.List;
53
import java.util.*;
59
import java.util.Map;
54
import java.util.logging.Logger;
55
import org.netbeans.editor.BaseDocument;
56
import org.netbeans.modules.refactoring.spi.impl.UndoableWrapper;
57
import org.netbeans.modules.refactoring.spi.impl.UndoableWrapper.UndoableEditDelegate;
58
import org.openide.cookies.EditorCookie;
60
import org.openide.filesystems.FileObject;
59
import org.openide.filesystems.FileObject;
61
import org.openide.filesystems.FileUtil;
60
import org.openide.filesystems.FileUtil;
61
import org.openide.loaders.DataObject;
62
import org.openide.loaders.DataObjectNotFoundException;
63
import org.openide.text.CloneableEditorSupport;
64
import org.openide.text.NbDocument;
65
import org.openide.util.Exceptions;
62
import org.openide.util.Lookup;
66
import org.openide.util.Lookup;
67
import sun.misc.IOUtils;
63
68
64
/**
69
/**
65
 * Simple backup facility
70
 * Simple backup facility can be used to backup files and implement undo For
66
 * can be used to backup files and implement undo
71
 * instance Java Refactoring module implements undo this way:
67
 * For instance Java Refactoring module implements undo this way:
68
 *
72
 *
69
 * public Problem prepare(RefactoringElementsBag elements) {
73
 * public Problem prepare(RefactoringElementsBag elements) { . .
70
 * .
74
 * elements.registerTransaction(new RetoucheCommit(results)); }
71
 * .
72
 *   elements.registerTransaction(new RetoucheCommit(results));
73
 * }
74
 * 
75
 * 
75
 * where RetoucheCommit is Transaction:
76
 * where RetoucheCommit is Transaction:
76
 * <pre>
77
 * <pre>
Lines 89-94 Link Here
89
 * </pre>
90
 * </pre>
90
 * 
91
 * 
91
 * You can register your own implementation via META-INF services.
92
 * You can register your own implementation via META-INF services.
93
 *
92
 * @see Transaction
94
 * @see Transaction
93
 * @see RefactoringElementImplementation#performChange
95
 * @see RefactoringElementImplementation#performChange
94
 * @see RefactoringElementImplementation#undoChange
96
 * @see RefactoringElementImplementation#undoChange
Lines 97-111 Link Here
97
 * @see BackupFacility.Handle
99
 * @see BackupFacility.Handle
98
 * @author Jan Becicka
100
 * @author Jan Becicka
99
 */
101
 */
100
public abstract class BackupFacility {
102
abstract class BackupFacility2 {
101
    
103
    
102
    private BackupFacility() {
104
    private static final Logger LOG = Logger.getLogger("org.netbeans.modules.refactoring.Undo");
105
106
    private BackupFacility2() {
103
    }
107
    }
108
    private static BackupFacility2 defaultInstance;
104
    
109
    
105
    private static BackupFacility defaultInstance;
106
    
107
    /**
110
    /**
108
     * does beckup
111
     * does backup
112
     *
109
     * @param file file(s) to backup
113
     * @param file file(s) to backup
110
     * @return handle which can be used to restore files
114
     * @return handle which can be used to restore files
111
     * @throws java.io.IOException if backup failed
115
     * @throws java.io.IOException if backup failed
Lines 114-119 Link Here
114
    
118
    
115
    /**
119
    /**
116
     * does backup
120
     * does backup
121
     *
117
     * @param fileObjects FileObjects to backup
122
     * @param fileObjects FileObjects to backup
118
     * @return handle which can be used to restore files
123
     * @return handle which can be used to restore files
119
     * @throws java.io.IOException 
124
     * @throws java.io.IOException 
Lines 123-132 Link Here
123
    }
128
    }
124
    
129
    
125
    /**
130
    /**
126
     * do cleanup
131
     * do cleanup all backup files are deleted all internal structures cleared
127
     * all backup files are deleted
132
     * default implemntation
128
     * all internal structures cleared
129
     * default implementa
130
     */
133
     */
131
    public abstract void clear();
134
    public abstract void clear();
132
    
135
    
Lines 135-146 Link Here
135
     * class in META-INF services -> this class is returned. Otherwise default 
138
     * class in META-INF services -> this class is returned. Otherwise default 
136
     * implementation is used.
139
     * implementation is used.
137
     */
140
     */
138
    public static BackupFacility getDefault() {
141
    public static BackupFacility2 getDefault() {
139
        BackupFacility instance = Lookup.getDefault().lookup(BackupFacility.class);
142
        BackupFacility2 instance = Lookup.getDefault().lookup(BackupFacility2.class);
140
        return (instance != null) ? instance : getDefaultInstance();
143
        return (instance != null) ? instance : getDefaultInstance();
141
    }
144
    }
142
    
145
    
143
    private static synchronized BackupFacility getDefaultInstance() {
146
    private static synchronized BackupFacility2 getDefaultInstance() {
144
        if (defaultInstance == null) {
147
        if (defaultInstance == null) {
145
            defaultInstance = new DefaultImpl();
148
            defaultInstance = new DefaultImpl();
146
        }
149
        }
Lines 149-205 Link Here
149
    }
152
    }
150
    
153
    
151
    /**
154
    /**
152
     * Handle class representing handle to file(s), which were backuped
155
     * Handle class representing handle to file(s), which were backuped by {@link  org.netbeans.modules.refactoring.spi.BackupFacility#backup()}
153
     * by
154
     * {@link  org.netbeans.modules.refactoring.spi.BackupFacility#backup()}
155
     */
156
     */
156
    public interface Handle {
157
    public interface Handle {
158
157
        /**
159
        /**
158
         * restore file(s), which was stored by  {@link  org.netbeans.modules.refactoring.spi.BackupFacility#backup()}
160
         * restore file(s), which was stored by {@link  org.netbeans.modules.refactoring.spi.BackupFacility#backup()}
161
         *
159
         * @throws java.io.IOException if restore failed.
162
         * @throws java.io.IOException if restore failed.
160
         */
163
         */
161
        void restore() throws IOException;
164
        public abstract void restore() throws java.io.IOException;
165
166
        void storeChecksum() throws IOException;
167
168
        public Collection<String> checkChecksum(boolean undo) throws IOException;
162
    }
169
    }
163
    
170
    
164
    private static class DefaultHandle implements Handle {
171
    private static class DefaultHandle implements Handle {
165
        List<Long> handle;
172
166
        DefaultImpl instance;
173
        private List<Long> handle;
174
        private DefaultImpl instance;
175
167
        private DefaultHandle(DefaultImpl instance, List<Long> handles) {
176
        private DefaultHandle(DefaultImpl instance, List<Long> handles) {
168
            this.handle = handles;
177
            this.handle = handles;
169
            this.instance = instance;
178
            this.instance = instance;
170
        }
179
        }
180
171
        @Override
181
        @Override
172
        public void restore() throws IOException {
182
        public void restore() throws IOException {
173
            for (long l:handle) {
183
            for (long l : handle) {
174
                instance.restore(l);
184
                instance.restore(l);
175
            }
185
            }
176
        }
186
        }
187
188
        @Override
189
        public void storeChecksum() throws IOException {
190
            for (long l : handle) {
191
                instance.storeChecksum(l);
177
    }
192
    }
193
        }
178
    
194
    
179
    private static class DefaultImpl extends BackupFacility {
195
        @Override
196
        public Collection<String> checkChecksum(boolean undo) throws IOException {
197
            Collection<String> result = new LinkedList<String>();
198
            for (long l : handle) {
199
                String checkChecksum = instance.checkChecksum(l, undo);
200
                if (checkChecksum !=null) {
201
                    result.add(checkChecksum);
202
                }
203
            }
204
            return result;
180
        
205
        
206
        }
207
    }
208
209
    private static class DefaultImpl extends BackupFacility2 {
210
181
        private long currentId = 0;
211
        private long currentId = 0;
182
        private Map<Long, BackupEntry> map = new HashMap<Long, BackupEntry>();
212
        private Map<Long, BackupEntry> map = new HashMap<Long, BackupEntry>();
183
        
213
        
214
        private String MD5toString(byte[] digest) {
215
            StringBuilder b = new StringBuilder();
216
            for (int i = 0; i < digest.length; i++) {
217
                b.append(Integer.toHexString(0xFF & digest[i]));
218
            }
219
            return b.toString();
220
        }
221
222
        private void storeChecksum(long l) throws IOException {
223
            BackupEntry backup = map.get(l);
224
            File f = new File(backup.path);
225
            FileObject fo = FileUtil.toFileObject(f);
226
            DataObject dob = DataObject.find(fo);
227
            if (dob != null) {
228
                CloneableEditorSupport ces = dob.getLookup().lookup(CloneableEditorSupport.class);
229
                final BaseDocument doc = (BaseDocument) ces.getDocument();
230
                if (doc !=null && doc.isAtomicLock()) {
231
                    //workaround to avoid deadlock
232
                    return;
233
                }
234
            }
235
            LOG.fine("Storing MD5 for " + backup.path);
236
            backup.checkSum = getMD5(getInputStream(backup.path));
237
            LOG.fine("MD5 is: " + MD5toString(backup.checkSum));
238
        }
239
240
        private String checkChecksum(long l, boolean undo) {
241
242
            try {
243
                BackupEntry backup = map.get(l);
244
                File f = new File(backup.path);
245
                FileObject fo = FileUtil.toFileObject(f);
246
                DataObject dob = DataObject.find(fo);
247
                if (dob != null) {
248
                    CloneableEditorSupport ces = dob.getLookup().lookup(CloneableEditorSupport.class);
249
250
                    final BaseDocument doc = (BaseDocument) ces.getDocument();
251
                    if (doc != null && doc.isAtomicLock()) {
252
                        //workaround to avoid deadlock
253
                        return null;
254
                    } else {
255
                        EditorCookie editor = dob.getLookup().lookup(EditorCookie.class);
256
                        if (editor != null  && doc!=null && editor.isModified()) {
257
                            UndoableEditDelegate edit = undo?NbDocument.getEditToBeUndoneOfType(editor, UndoableWrapper.UndoableEditDelegate.class):NbDocument.getEditToBeRedoneOfType(editor, UndoableWrapper.UndoableEditDelegate.class);
258
                            if (edit == null) {
259
                                try {
260
                                    LOG.fine("Editor Undo Different");
261
                                    return backup.path.toURL().getPath();
262
                                } catch (MalformedURLException ex) {
263
                                    Exceptions.printStackTrace(ex);
264
                                }
265
                            }
266
                        }
267
268
                    }
269
                }
270
271
                try {
272
                    LOG.fine("Checking MD5 for " + backup.path);
273
                    byte[] ts = getMD5(getInputStream(backup.path));
274
                    if (!Arrays.equals(backup.checkSum, ts)) {
275
                        LOG.fine("MD5 check failed");
276
                        return backup.path.toURL().getPath();
277
                    }
278
                } catch (IOException ex) {
279
                    Exceptions.printStackTrace(ex);
280
                }
281
            } catch (DataObjectNotFoundException ex) {
282
                Exceptions.printStackTrace(ex);
283
            }
284
            return null;
285
        }
286
287
        private InputStream getInputStream(URI path) throws IOException {
288
            File f = new File(path);
289
            FileObject fo = FileUtil.toFileObject(f);
290
            DataObject dob = DataObject.find(fo);
291
            CloneableEditorSupport ces = dob.getLookup().lookup(CloneableEditorSupport.class);
292
            if (ces != null && ces.isModified()) {
293
                LOG.fine("Editor Input Stream");
294
                return ces.getInputStream();
295
            }
296
            LOG.fine("File Input Stream");
297
            return fo.getInputStream();
298
        }
299
184
        private class BackupEntry {
300
        private class BackupEntry {
301
185
            private File file;
302
            private File file;
186
            private URI path;
303
            private URI path;
304
            private byte[] checkSum;
305
            private boolean undo = true;
306
307
            public BackupEntry() {
187
        }
308
        }
188
        
309
        
189
        /** Creates a new instance of BackupFacility */
310
            public boolean isUndo() {
311
                return undo;
312
            }
313
314
            public void setUndo(boolean undo) {
315
                this.undo = undo;
316
            }
317
        }
318
319
        /**
320
         * Creates a new instance of BackupFacility
321
         */
190
        private DefaultImpl() {
322
        private DefaultImpl() {
191
        }
323
        }
192
        
324
        
193
        @Override
325
        @Override
194
        public Handle backup(FileObject ... file) throws IOException {
326
        public Handle backup(FileObject... file) throws IOException {
195
            ArrayList<Long> list = new ArrayList<Long>();
327
            ArrayList<Long> list = new ArrayList<Long>();
196
            for (FileObject f:file) {
328
            for (FileObject f : file) {
197
                list.add(backup(f));
329
                list.add(backup(f));
198
            }
330
            }
199
            return new DefaultHandle(this, list);
331
            return new DefaultHandle(this, list);
200
        }
332
        }
333
201
        /**
334
        /**
202
         * does beckup
335
         * does backup
336
         *
203
         * @param file to backup
337
         * @param file to backup
204
         * @return id of backup file
338
         * @return id of backup file
205
         * @throws java.io.IOException if backup failed
339
         * @throws java.io.IOException if backup failed
Lines 217-230 Link Here
217
                throw (IOException) new IOException(file.toString()).initCause(ex);
351
                throw (IOException) new IOException(file.toString()).initCause(ex);
218
            }
352
            }
219
        }
353
        }
354
355
        private byte[] getMD5(InputStream is) throws IOException {
356
            try {
357
                MessageDigest md = MessageDigest.getInstance("MD5");
358
                try {
359
                    is = new DigestInputStream(is, md);
360
                    IOUtils.readFully(is, -1, true);
361
                } finally {
362
                    is.close();
363
                }
364
                return md.digest();
365
            } catch (NoSuchAlgorithmException ex) {
366
                throw new IOException(ex);
367
            }
368
        }
369
370
        private static java.lang.reflect.Field undoRedo;
371
372
        static {
373
            try {
374
                //obviously hack. See 108616 and 48427
375
                undoRedo = org.openide.text.CloneableEditorSupport.class.getDeclaredField("undoRedo"); //NOI18N
376
                undoRedo.setAccessible(true);
377
            } catch (NoSuchFieldException ex) {
378
                Exceptions.printStackTrace(ex);
379
            } catch (SecurityException ex) {
380
                Exceptions.printStackTrace(ex);
381
            }
382
        }
383
220
        /**
384
        /**
221
         * restore file, which was stored by backup(file)
385
         * restore file, which was stored by backup(file)
386
         *
222
         * @param id identification of backup transaction
387
         * @param id identification of backup transaction
223
         * @throws java.io.IOException if restore failed.
388
         * @throws java.io.IOException if restore failed.
224
         */
389
         */
225
        void restore(long id) throws IOException {
390
        void restore(long id) throws IOException {
226
            BackupEntry entry = map.get(id);
391
            BackupEntry entry = map.get(id);
227
            if(entry==null) {
392
            if (entry == null) {
228
                throw new IllegalArgumentException("Backup with id " + id + "does not exist"); // NOI18N
393
                throw new IllegalArgumentException("Backup with id " + id + "does not exist"); // NOI18N
229
            }
394
            }
230
            File backup = File.createTempFile("nbbackup", null); //NOI18N
395
            File backup = File.createTempFile("nbbackup", null); //NOI18N
Lines 232-241 Link Here
232
            File f = new File(entry.path);
397
            File f = new File(entry.path);
233
            if (createNewFile(f)) {
398
            if (createNewFile(f)) {
234
                backup.createNewFile();
399
                backup.createNewFile();
235
                copy(f,backup);
400
                copy(f, backup);
236
            }
401
            }
237
            FileObject fileObj = FileUtil.toFileObject(f);
402
            FileObject fileObj = FileUtil.toFileObject(f);
238
            copy(entry.file,fileObj);
403
404
            if (!tryUndoOrRedo(fileObj, entry)) {
405
                copy(entry.file, fileObj);
406
            }
239
            entry.file.delete();
407
            entry.file.delete();
240
            if (backup.exists()) {
408
            if (backup.exists()) {
241
                entry.file = backup;
409
                entry.file = backup;
Lines 244-257 Link Here
244
            }
412
            }
245
        }
413
        }
246
        
414
        
415
        private boolean tryUndoOrRedo(final FileObject fileObj, final BackupEntry entry) throws DataObjectNotFoundException {
416
            DataObject dob = DataObject.find(fileObj);
417
            if (dob != null) {
418
                CloneableEditorSupport ces = dob.getLookup().lookup(CloneableEditorSupport.class);
419
                final org.openide.awt.UndoRedo.Manager manager;
420
                try {
421
                    manager = (org.openide.awt.UndoRedo.Manager) undoRedo.get(ces);
422
                    final BaseDocument doc = (BaseDocument) ces.getDocument();
423
                    if (doc==null) {
424
                        return false;
425
                    }
426
                    if (doc.isAtomicLock()) {
427
                        //undo already performed
428
                        if (entry.isUndo()) {
429
                            entry.setUndo(false);
430
                        } else {
431
                            entry.setUndo(true);
432
                        }
433
                    } else {
434
                        if ((entry.isUndo() && manager.canUndo()) || (!entry.isUndo() && manager.canRedo())) {
435
                            doc.runAtomic(new Runnable() {
436
437
                                @Override
438
                                public void run() {
439
                                    if (entry.isUndo()) {
440
                                        manager.undo();
441
                                        entry.setUndo(false);
442
                                    } else {
443
                                        manager.redo();
444
                                        entry.setUndo(true);
445
                                    }
446
                                }
447
                            });
448
                        } else {
449
                            return false;
450
                        }
451
                    }
452
                    return true;
453
                } catch (IllegalArgumentException ex) {
454
                    Exceptions.printStackTrace(ex);
455
                } catch (IllegalAccessException ex) {
456
                    Exceptions.printStackTrace(ex);
457
                }
458
            }
459
            return false;
460
        }
461
247
        /**
462
        /**
248
         * workaround for #93390
463
         * workaround for #93390
249
         */
464
         */
250
        private boolean createNewFile(File f) throws IOException {
465
        private boolean createNewFile(File f) throws IOException {
251
            if (f.exists())
466
            if (f.exists()) {
252
                return true;
467
                return true;
468
            }
253
            File parent = f.getParentFile();
469
            File parent = f.getParentFile();
254
            if (parent!=null) {
470
            if (parent != null) {
255
                createNewFolder(parent);
471
                createNewFolder(parent);
256
            }
472
            }
257
            FileUtil.createData(f);
473
            FileUtil.createData(f);
Lines 297-303 Link Here
297
        
513
        
298
        @Override
514
        @Override
299
        public void clear() {
515
        public void clear() {
300
            for(BackupEntry entry: map.values()) {
516
            for (BackupEntry entry : map.values()) {
301
                entry.file.delete();
517
                entry.file.delete();
302
            }
518
            }
303
            map.clear();
519
            map.clear();
(-)refactoring.api/src/org/netbeans/modules/refactoring/spi/ModificationResult.java (+84 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.refactoring.spi;
43
44
import java.io.File;
45
import java.io.IOException;
46
import java.util.Collection;
47
import org.openide.filesystems.FileObject;
48
49
/**
50
 * Result of changes performed by refactoring plugin.
51
 * @author Jan Becicka
52
 * @since 1.23
53
 */
54
public interface ModificationResult {
55
56
    /**
57
     * New source text for given file. 
58
     * 
59
     * @param file
60
     * @return new source text
61
     * @throws IOException
62
     * @throws IllegalArgumentException
63
     */
64
    public String getResultingSource(FileObject file) throws IOException, IllegalArgumentException;
65
    
66
    /**
67
     * FileObjects modified by this ModificationResult.
68
     * @return
69
     */
70
    public Collection<? extends FileObject> getModifiedFileObjects();
71
72
    /**
73
     * New files generated by this ModificationResult.
74
     * @return 
75
     */
76
    public Collection<? extends File> getNewFiles();
77
78
    /**
79
     * Performs commit of changes into files.
80
     * @throws IOException 
81
     */
82
    public void commit() throws IOException;
83
    
84
}
(-)refactoring.api/src/org/netbeans/modules/refactoring/spi/RefactoringCommit.java (-20 / +118 lines)
Lines 41-55 Link Here
41
 * Version 2 license, then the option applies only if the new code is
41
 * Version 2 license, then the option applies only if the new code is
42
 * made subject to such option by the copyright holder.
42
 * made subject to such option by the copyright holder.
43
 */
43
 */
44
package org.netbeans.modules.refactoring.java.plugins;
44
package org.netbeans.modules.refactoring.spi;
45
45
46
import java.io.File;
46
import java.io.File;
47
import java.io.IOException;
47
import java.io.IOException;
48
import java.util.*;
48
import java.util.ArrayList;
49
import java.util.Collection;
50
import java.util.HashSet;
51
import java.util.List;
52
import java.util.Set;
49
import java.util.logging.Level;
53
import java.util.logging.Level;
50
import java.util.logging.Logger;
54
import java.util.logging.Logger;
51
import org.netbeans.api.java.source.ModificationResult;
55
import javax.swing.undo.CannotRedoException;
52
import org.netbeans.modules.refactoring.spi.BackupFacility;
56
import javax.swing.undo.CannotUndoException;
57
import org.netbeans.api.annotations.common.NonNull;
58
import org.netbeans.modules.refactoring.spi.BackupFacility2;
59
import org.netbeans.modules.refactoring.spi.BackupFacility2.Handle;
53
import org.netbeans.modules.refactoring.spi.Transaction;
60
import org.netbeans.modules.refactoring.spi.Transaction;
54
import org.openide.cookies.EditorCookie;
61
import org.openide.cookies.EditorCookie;
55
import org.openide.filesystems.FileObject;
62
import org.openide.filesystems.FileObject;
Lines 59-103 Link Here
59
import org.openide.util.Exceptions;
66
import org.openide.util.Exceptions;
60
67
61
/**
68
/**
62
 *
69
 * Default implementation of {@link Transaction}
63
 * @author Jan Becicka
70
 * @author Jan Becicka
71
 * @since 1.23
64
 */
72
 */
65
73
66
public class RetoucheCommit implements Transaction {
74
 public final class RefactoringCommit implements Transaction {
67
    private static final Logger LOG = Logger.getLogger(RetoucheCommit.class.getName());
75
 
68
    List<BackupFacility.Handle> ids = new ArrayList<BackupFacility.Handle>();
76
     private static final Logger LOG = Logger.getLogger(RefactoringCommit.class.getName());
77
 
78
     /**
79
      * FileObjects modified by this Transaction
80
      *
81
      * @return collection of FileObjects
82
      */
83
     @NonNull Collection<? extends FileObject> getModifiedFiles() {
84
         ArrayList<FileObject> result = new ArrayList();
85
         for (ModificationResult modification:results) {
86
             result.addAll(modification.getModifiedFileObjects());
87
         }
88
         return result;
89
     }
90
 
91
     private static class CannotUndoRefactoring extends CannotUndoException {
92
93
         private Collection<String> files;
94
95
         private CannotUndoRefactoring(Collection<String> checkChecksum) {
96
             super();
97
             this.files = checkChecksum;
98
         }
99
100
        @Override
101
        public String getMessage() {
102
            StringBuilder b = new StringBuilder("Cannot Undo.\nFollowing files were modified:\n");
103
            for (String f:files) {
104
                b.append(f);
105
                b.append('\n');
106
            }
107
            return b.toString();
108
        }
109
         
110
         
111
112
         public Collection<String> getFiles() {
113
             return files;
114
         }
115
     }
116
117
     private static class CannotRedoRefactoring extends CannotRedoException {
118
119
         private Collection<String> files;
120
121
         private CannotRedoRefactoring(Collection<String> checkChecksum) {
122
             this.files = checkChecksum;
123
         }
124
125
         public Collection<String> getFiles() {
126
             return files;
127
         }
128
129
         @Override
130
         public String getMessage() {
131
            StringBuilder b = new StringBuilder("Cannot Redo.\nFollowing files were modified:\n");
132
            for (String f:files) {
133
                b.append(f);
134
                b.append('\n');
135
            }
136
            return b.toString();
137
        }
138
         
139
     }
140
     
141
 
142
    List<BackupFacility2.Handle> ids = new ArrayList<BackupFacility2.Handle>();
69
    private boolean commited = false;
143
    private boolean commited = false;
70
    Collection<ModificationResult> results;
144
    Collection<? extends ModificationResult> results;
71
    private Set<File> newFiles;
145
    private Set<File> newFiles;
72
    
146
    
73
    public RetoucheCommit(Collection<ModificationResult> results) {
147
    /**
148
     * RefactoringCommit is just collection of ModificationResults
149
     * @param results 
150
     */
151
    public RefactoringCommit(Collection<? extends ModificationResult> results) {
74
        this.results = results;
152
        this.results = results;
75
    }
153
    }
76
    
154
    
77
    @Override
78
    public void commit() {
155
    public void commit() {
79
        try {
156
        try {
80
            if (commited) {
157
            if (commited) {
81
                for (BackupFacility.Handle id:ids) {
158
                 for (BackupFacility2.Handle id : ids) {
159
                    Collection<String> checkChecksum = id.checkChecksum(false);
160
                    if (!checkChecksum.isEmpty()) {
161
                        throw new CannotRedoRefactoring(checkChecksum);
162
                    }
163
                 }
164
                
165
                for (BackupFacility2.Handle id:ids) {
82
                    try {
166
                    try {
83
                        id.restore();
167
                        id.restore();
168
                        id.storeChecksum();
84
                    } catch (IOException ex) {
169
                    } catch (IOException ex) {
85
                        throw new RuntimeException(ex);
170
                        throw new RuntimeException(ex);
86
                    }
171
                    }
87
                }
172
                }
88
            } else {
173
            } else {
89
                commited = true;
174
                commited = true;
90
                for (ModificationResult result:results) {
175
                 for (ModificationResult result : results) {
91
                    ids.add(BackupFacility.getDefault().backup(result.getModifiedFileObjects()));
176
                     Handle backupid = BackupFacility2.getDefault().backup(result.getModifiedFileObjects());
177
                     ids.add(backupid);
92
                    if (newFiles == null) {
178
                    if (newFiles == null) {
93
                        newFiles = new HashSet<File>();
179
                        newFiles = new HashSet<File>();
94
                    }
180
                    }
95
                    newFiles.addAll(result.getNewFiles());
181
                    newFiles.addAll(result.getNewFiles());
96
                    result.commit();
182
                    result.commit();
97
                }
183
                    backupid.storeChecksum();
98
184
99
                openNewFiles(newFiles);
185
                openNewFiles(newFiles);
100
            }
186
            }
187
            }
101
            
188
            
102
        } catch (IOException ex) {
189
        } catch (IOException ex) {
103
            throw new RuntimeException(ex);
190
            throw new RuntimeException(ex);
Lines 105-126 Link Here
105
    }
192
    }
106
    
193
    
107
    private boolean newFilesStored = false;
194
    private boolean newFilesStored = false;
108
    @Override
195
109
    public void rollback() {
196
    public void rollback() {
110
        for (BackupFacility.Handle id:ids) {
111
            try {
197
            try {
198
             for (BackupFacility2.Handle id : ids) {
199
                 Collection<String> checkChecksum = id.checkChecksum(true);
200
                 if (!checkChecksum.isEmpty()) {
201
                     throw new CannotUndoRefactoring(checkChecksum);
202
                 }
203
204
                 try {
112
                id.restore();
205
                id.restore();
206
                     id.storeChecksum();
113
            } catch (IOException ex) {
207
            } catch (IOException ex) {
114
                throw new RuntimeException(ex);
208
                throw new RuntimeException(ex);
115
            }
209
            }
116
        }
210
        }
117
        boolean localStored = false;
211
        boolean localStored = false;
118
        if (newFiles!=null) {
212
             if (newFiles != null) {
119
            for (File f:newFiles) {
213
                 for (File f : newFiles) {
120
                try {
214
                try {
121
                    FileObject fo = FileUtil.toFileObject(f);
215
                    FileObject fo = FileUtil.toFileObject(f);
122
                    if (!newFilesStored) {
216
                    if (!newFilesStored) {
123
                        ids.add(BackupFacility.getDefault().backup(fo));
217
                             ids.add(BackupFacility2.getDefault().backup(fo));
124
                        localStored = true;
218
                        localStored = true;
125
                    }
219
                    }
126
                    fo.delete();
220
                    fo.delete();
Lines 130-137 Link Here
130
            }
224
            }
131
            newFilesStored |= localStored;
225
            newFilesStored |= localStored;
132
        }
226
        }
227
         } catch (IOException ex) {
228
             Exceptions.printStackTrace(ex);
133
    }
229
    }
134
230
231
     }
232
135
    private static void openNewFiles(Set<File> newFiles) {
233
    private static void openNewFiles(Set<File> newFiles) {
136
        if (newFiles == null) {
234
        if (newFiles == null) {
137
            return;
235
            return;
(-)refactoring.api/src/org/netbeans/modules/refactoring/spi/impl/Bundle.properties (+6 lines)
Lines 51-56 Link Here
51
LBL_MoveAction=&Move...
51
LBL_MoveAction=&Move...
52
LBL_Undo=U&ndo
52
LBL_Undo=U&ndo
53
LBL_Redo=Red&o
53
LBL_Redo=Red&o
54
MSG_ReallyUndo=Really undo {0}
55
MSG_ConfirmUndo=Confirm undo
56
MSG_ReallyRedo=Really redo {0}
57
MSG_ConfirmRedo=Confirm redo
58
MSG_ConfirmRefresh=Do you want to refresh refactoring?
59
MSG_FileModified=Some files were modified
54
60
55
#Refactoring Preview Window
61
#Refactoring Preview Window
56
LBL_CloseWindow=Close Tab
62
LBL_CloseWindow=Close Tab
(-)refactoring.api/src/org/netbeans/modules/refactoring/spi/impl/InvalidationListener.java (-55 lines)
Lines 1-55 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * Contributor(s):
28
 *
29
 * The Original Software is NetBeans. The Initial Developer of the Original
30
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
31
 * Microsystems, Inc. All Rights Reserved.
32
 *
33
 * If you wish your version of this file to be governed by only the CDDL
34
 * or only the GPL Version 2, indicate your decision by adding
35
 * "[Contributor] elects to include this software in this distribution
36
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
37
 * single choice of license, a recipient has the option to distribute
38
 * your version of this file under either the CDDL, the GPL Version 2 or
39
 * to extend the choice of license to its licensees as provided above.
40
 * However, if you add GPL Version 2 code and therefore, elected the GPL
41
 * Version 2 license, then the option applies only if the new code is
42
 * made subject to such option by the copyright holder.
43
 */
44
45
package org.netbeans.modules.refactoring.spi.impl;
46
47
import java.util.EventListener;
48
49
/**
50
 *
51
 * @author Jan Becicka
52
 */
53
public interface InvalidationListener extends EventListener {
54
    void invalidateObject();
55
}
(-)refactoring.api/src/org/netbeans/modules/refactoring/spi/impl/ParametersPanel.java (-7 / +3 lines)
Lines 86-92 Link Here
86
 *
86
 *
87
 * @author Martin Matula, Jan Becicka
87
 * @author Martin Matula, Jan Becicka
88
 */
88
 */
89
public class ParametersPanel extends JPanel implements ProgressListener, ChangeListener, InvalidationListener {
89
public class ParametersPanel extends JPanel implements ProgressListener, ChangeListener {
90
    
90
    
91
    public static final String JUMP_TO_FIRST_OCCURENCE = "JUMP_TO_FIRST_OCCURENCE"; //NOI18N
91
    public static final String JUMP_TO_FIRST_OCCURENCE = "JUMP_TO_FIRST_OCCURENCE"; //NOI18N
92
92
Lines 478-487 Link Here
478
                                        null);
478
                                        null);
479
                                DialogDisplayer.getDefault().notifyLater(nd);
479
                                DialogDisplayer.getDefault().notifyLater(nd);
480
                            } else {
480
                            } else {
481
                                UndoWatcher.watch(session, ParametersPanel.this);
481
                                //UndoWatcher.watch(session, ParametersPanel.this);
482
                                session.addProgressListener(ParametersPanel.this);
482
                                session.addProgressListener(ParametersPanel.this);
483
                                session.doRefactoring(true);
483
                                session.doRefactoring(true);
484
                                UndoWatcher.stopWatching(ParametersPanel.this);
484
                                //UndoWatcher.stopWatching(ParametersPanel.this);
485
                            }
485
                            }
486
                        }
486
                        }
487
                    } finally {
487
                    } finally {
Lines 1031-1040 Link Here
1031
        return rui.getHelpCtx();
1031
        return rui.getHelpCtx();
1032
    }
1032
    }
1033
    
1033
    
1034
    @Override
1035
    public void invalidateObject() {
1036
    }
1037
1038
    private RefactoringSession getResult() {
1034
    private RefactoringSession getResult() {
1039
        synchronized (RESULT_LOCK) {
1035
        synchronized (RESULT_LOCK) {
1040
            return result;
1036
            return result;
(-)refactoring.api/src/org/netbeans/modules/refactoring/spi/impl/RedoAction.java (-126 lines)
Lines 1-126 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * Contributor(s):
28
 *
29
 * The Original Software is NetBeans. The Initial Developer of the Original
30
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
31
 * Microsystems, Inc. All Rights Reserved.
32
 *
33
 * If you wish your version of this file to be governed by only the CDDL
34
 * or only the GPL Version 2, indicate your decision by adding
35
 * "[Contributor] elects to include this software in this distribution
36
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
37
 * single choice of license, a recipient has the option to distribute
38
 * your version of this file under either the CDDL, the GPL Version 2 or
39
 * to extend the choice of license to its licensees as provided above.
40
 * However, if you add GPL Version 2 code and therefore, elected the GPL
41
 * Version 2 license, then the option applies only if the new code is
42
 * made subject to such option by the copyright holder.
43
 */
44
45
package org.netbeans.modules.refactoring.spi.impl;
46
47
import java.beans.PropertyChangeEvent;
48
import java.beans.PropertyChangeListener;
49
import javax.swing.Action;
50
import javax.swing.SwingUtilities;
51
import org.openide.awt.ActionID;
52
import org.openide.awt.ActionReference;
53
import org.openide.awt.ActionRegistration;
54
import org.openide.util.HelpCtx;
55
import org.openide.util.NbBundle;
56
import org.openide.util.actions.CallableSystemAction;
57
58
@ActionID(id = "org.netbeans.modules.refactoring.spi.impl.RedoAction", category = "Refactoring")
59
@ActionRegistration(displayName = "#LBL_Redo")
60
@ActionReference(path = "Menu/Refactoring" , name = "RedoAction", position = 2100)
61
public class RedoAction extends CallableSystemAction implements PropertyChangeListener {
62
63
    private UndoManager undoManager;
64
65
    public RedoAction() {
66
        putValue(Action.NAME, getString("LBL_Redo")); //NOI18N
67
        putValue("noIconInMenu", Boolean.TRUE); // NOI18N
68
        undoManager = UndoManager.getDefault();
69
        undoManager.addPropertyChangeListener(this);
70
        updateState();
71
    }
72
    
73
    @Override
74
    public void propertyChange (PropertyChangeEvent event) {
75
        updateState();
76
    }
77
    
78
    private void updateState() {
79
        String desc = undoManager.getRedoDescription();
80
        String name = getString("LBL_Redo");
81
        if (desc != null) {
82
            name += " [" + desc + "]"; //NOI18N
83
        }
84
        
85
        final String n = name;
86
        final boolean b = undoManager.isRedoAvailable();
87
        Runnable r = new Runnable() {
88
            @Override
89
            public void run() {
90
                setEnabled(b);
91
                putValue(Action.NAME, n);
92
            }
93
        };
94
95
        if (SwingUtilities.isEventDispatchThread()) {
96
            r.run();
97
        } else {
98
            SwingUtilities.invokeLater(r);
99
        }
100
    }
101
    
102
    private static final String getString(String key) {
103
        return NbBundle.getMessage(RedoAction.class, key);
104
    }
105
    
106
    @Override
107
    public void performAction() {
108
        undoManager.redo();
109
        undoManager.saveAll();
110
    }
111
    
112
    @Override
113
    public org.openide.util.HelpCtx getHelpCtx() {
114
        return HelpCtx.DEFAULT_HELP;
115
    }
116
    
117
    @Override
118
    public String getName() {
119
        return (String) getValue(Action.NAME);
120
    }
121
    
122
    @Override
123
    protected boolean asynchronous() {
124
        return true;
125
    }
126
}
(-)refactoring.api/src/org/netbeans/modules/refactoring/spi/impl/RefactoringPanel.java (-9 / +67 lines)
Lines 58-63 Link Here
58
import java.lang.reflect.InvocationTargetException;
58
import java.lang.reflect.InvocationTargetException;
59
import java.util.*;
59
import java.util.*;
60
import java.util.Collection;
60
import java.util.Collection;
61
import java.util.Map.Entry;
61
import java.util.prefs.Preferences;
62
import java.util.prefs.Preferences;
62
import javax.swing.*;
63
import javax.swing.*;
63
import javax.swing.border.EmptyBorder;
64
import javax.swing.border.EmptyBorder;
Lines 81-86 Link Here
81
import org.openide.DialogDisplayer;
82
import org.openide.DialogDisplayer;
82
import org.openide.ErrorManager;
83
import org.openide.ErrorManager;
83
import org.openide.awt.Mnemonics;
84
import org.openide.awt.Mnemonics;
85
import org.openide.filesystems.FileObject;
86
import org.openide.loaders.DataObject;
84
import org.openide.text.CloneableEditorSupport;
87
import org.openide.text.CloneableEditorSupport;
85
import org.openide.text.PositionBounds;
88
import org.openide.text.PositionBounds;
86
import org.openide.util.*;
89
import org.openide.util.*;
Lines 91-97 Link Here
91
 *
94
 *
92
 * @author  Pavel Flaska, Martin Matula
95
 * @author  Pavel Flaska, Martin Matula
93
 */
96
 */
94
public class RefactoringPanel extends JPanel implements InvalidationListener {
97
public class RefactoringPanel extends JPanel {
95
    private static final RequestProcessor RP = new RequestProcessor(RefactoringPanel.class.getName(), 1, false, false);
98
    private static final RequestProcessor RP = new RequestProcessor(RefactoringPanel.class.getName(), 1, false, false);
96
    
99
    
97
    // PRIVATE FIELDS
100
    // PRIVATE FIELDS
Lines 502-507 Link Here
502
     */
505
     */
503
    private void refactor() {
506
    private void refactor() {
504
        checkEventThread();
507
        checkEventThread();
508
        if (!checkTimeStamps()) {
509
            if (JOptionPane.showConfirmDialog(
510
                    this,
511
                    NbBundle.getMessage(RefactoringPanel.class, "MSG_ConfirmRefresh"),
512
                    NbBundle.getMessage(RefactoringPanel.class, "MSG_FileModified"),
513
                    JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) {
514
                refresh(true);
515
                return;
516
            }   else {
517
            return;
518
            }
519
        }
505
        disableComponents(RefactoringPanel.this);
520
        disableComponents(RefactoringPanel.this);
506
        progressListener = new ProgressL();
521
        progressListener = new ProgressL();
507
        RP.post(new Runnable() {
522
        RP.post(new Runnable() {
Lines 603-609 Link Here
603
        requestFocus();
618
        requestFocus();
604
    }
619
    }
605
    
620
    
606
    @Override
621
    /**
622
     * TODO: probably useless
623
     * remove
624
     */
607
    public void invalidateObject() {
625
    public void invalidateObject() {
608
        if (isQuery) {
626
        if (isQuery) {
609
            return;
627
            return;
Lines 681-687 Link Here
681
            RP.post(new Runnable() {
699
            RP.post(new Runnable() {
682
                @Override
700
                @Override
683
                public void run() {
701
                public void run() {
684
                    Set<CloneableEditorSupport> editorSupports = new HashSet<CloneableEditorSupport>();
702
                    Set<FileObject> fileObjects = new HashSet<FileObject>();
685
                    int errorsNum = 0;
703
                    int errorsNum = 0;
686
                    if (!isQuery) {
704
                    if (!isQuery) {
687
                        for (Iterator iter = elements.iterator(); iter.hasNext(); ) {
705
                        for (Iterator iter = elements.iterator(); iter.hasNext(); ) {
Lines 748-757 Link Here
748
                                    }
766
                                    }
749
                                }
767
                                }
750
                                PositionBounds pb = e.getPosition();
768
                                PositionBounds pb = e.getPosition();
751
                                if (pb != null) {
769
                                fileObjects.add(e.getParentFile());
752
                                    CloneableEditorSupport ces = pb.getBegin().getCloneableEditorSupport();
753
                                    editorSupports.add(ces);
754
                                }
755
                                
770
                                
756
                                if (i % 10 == 0)
771
                                if (i % 10 == 0)
757
                                    progressHandle.progress(i/10);
772
                                    progressHandle.progress(i/10);
Lines 760-766 Link Here
760
                            //[retouche]                        JavaModel.getJavaRepository().endTrans();
775
                            //[retouche]                        JavaModel.getJavaRepository().endTrans();
761
                        }
776
                        }
762
                       
777
                       
763
                        UndoManager.getDefault().watch(editorSupports, RefactoringPanel.this);
778
                        //UndoManager.getDefault().watch(editorSupports, RefactoringPanel.this);
779
                        storeTimeStamps(fileObjects);
764
                    } catch (RuntimeException t) {
780
                    } catch (RuntimeException t) {
765
                        cleanupTreeElements();
781
                        cleanupTreeElements();
766
                        throw t;
782
                        throw t;
Lines 857-862 Link Here
857
        });
873
        });
858
    }
874
    }
859
    
875
    
876
     private Map<FileObject, Long> timeStamps = new HashMap<FileObject, Long>();
877
     
878
     private void storeTimeStamps(Set<FileObject> fileObjects) {
879
         timeStamps.clear();
880
         for (FileObject fo:fileObjects) {
881
             timeStamps.put(fo, fo.lastModified().getTime());
882
         }
883
     }
884
     
885
     /**
886
      * @return true if timestamps are OK
887
      */
888
     private boolean checkTimeStamps() {
889
         Set<FileObject> modified = getModifiedFileObjects();
890
         for (Entry<FileObject, Long> entry: timeStamps.entrySet()) {
891
             if (modified.contains(entry.getKey()))
892
                 return false;
893
             if (!entry.getKey().isValid())
894
                 return false;
895
             if (entry.getKey().lastModified().getTime() != entry.getValue())
896
                 return false;
897
         }
898
         return true;
899
     }
900
     
901
     private Set<FileObject> getModifiedFileObjects() {
902
         Set<FileObject> result = new HashSet();
903
         for (DataObject dob: DataObject.getRegistry().getModified()) {
904
             result.add(dob.getPrimaryFile());
905
         }
906
         return result;
907
     }
908
     
909
     private void clearTimeStamps() {
910
         timeStamps.clear();
911
     }
912
 
913
 
914
     
915
    
860
    private void createTree(TreeNode root) throws MissingResourceException {
916
    private void createTree(TreeNode root) throws MissingResourceException {
861
        if (tree == null) {
917
        if (tree == null) {
862
            // add panel with appropriate content
918
            // add panel with appropriate content
Lines 1069-1075 Link Here
1069
    } */
1125
    } */
1070
    
1126
    
1071
    protected void closeNotify() {
1127
    protected void closeNotify() {
1072
        UndoWatcher.stopWatching(this);
1128
        clearTimeStamps();
1129
        //UndoWatcher.stopWatching(this);
1073
        if (tree!=null) {
1130
        if (tree!=null) {
1074
            ToolTipManager.sharedInstance().unregisterComponent(tree);
1131
            ToolTipManager.sharedInstance().unregisterComponent(tree);
1075
            scrollPane.getViewport().remove(tree);
1132
            scrollPane.getViewport().remove(tree);
Lines 1126-1131 Link Here
1126
                    handle.start(event.getCount());
1183
                    handle.start(event.getCount());
1127
                    d.setVisible(true);
1184
                    d.setVisible(true);
1128
                }
1185
                }
1186
1129
            });
1187
            });
1130
        }
1188
        }
1131
        
1189
        
(-)refactoring.api/src/org/netbeans/modules/refactoring/spi/impl/RefactoringUndoRedo.java (+117 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.refactoring.spi.impl;
43
44
import java.beans.PropertyChangeEvent;
45
import java.beans.PropertyChangeListener;
46
import javax.swing.event.ChangeEvent;
47
import javax.swing.event.ChangeListener;
48
import javax.swing.undo.CannotRedoException;
49
import javax.swing.undo.CannotUndoException;
50
import org.openide.awt.UndoRedo;
51
import org.openide.util.ChangeSupport;
52
import org.openide.util.lookup.ServiceProvider;
53
54
/**
55
 *
56
 * @author Jan Becicka
57
 */
58
@ServiceProvider(service=UndoRedo.class, path="org/netbeans/modules/refactoring")
59
public class RefactoringUndoRedo implements UndoRedo {
60
    
61
    private UndoManager manager = UndoManager.getDefault();
62
    
63
    private ChangeSupport pcs = new ChangeSupport(this);
64
    
65
    public RefactoringUndoRedo() {
66
        manager.addChangeListener(new ChangeListener() {
67
68
            @Override
69
            public void stateChanged(ChangeEvent e) {
70
                pcs.fireChange();
71
            }
72
73
        });
74
    }
75
76
    @Override
77
    public boolean canUndo() {
78
        return manager.isUndoAvailable();
79
    }
80
81
    @Override
82
    public boolean canRedo() {
83
        return manager.isRedoAvailable();
84
    }
85
86
    @Override
87
    public void undo() throws CannotUndoException {
88
        manager.undo();
89
    }
90
91
    @Override
92
    public void redo() throws CannotRedoException {
93
        manager.redo();
94
    }
95
96
    @Override
97
    public void addChangeListener(final ChangeListener l) {
98
        pcs.addChangeListener(l);
99
        
100
    }
101
102
    @Override
103
    public void removeChangeListener(ChangeListener l) {
104
        pcs.removeChangeListener(l);
105
    }
106
107
    @Override
108
    public String getUndoPresentationName() {
109
        return manager.getUndoDescription();
110
    }
111
112
    @Override
113
    public String getRedoPresentationName() {
114
        return manager.getRedoDescription();
115
    }
116
    
117
}
(-)refactoring.api/src/org/netbeans/modules/refactoring/spi/impl/UndoAction.java (-126 lines)
Lines 1-126 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * Contributor(s):
28
 *
29
 * The Original Software is NetBeans. The Initial Developer of the Original
30
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
31
 * Microsystems, Inc. All Rights Reserved.
32
 *
33
 * If you wish your version of this file to be governed by only the CDDL
34
 * or only the GPL Version 2, indicate your decision by adding
35
 * "[Contributor] elects to include this software in this distribution
36
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
37
 * single choice of license, a recipient has the option to distribute
38
 * your version of this file under either the CDDL, the GPL Version 2 or
39
 * to extend the choice of license to its licensees as provided above.
40
 * However, if you add GPL Version 2 code and therefore, elected the GPL
41
 * Version 2 license, then the option applies only if the new code is
42
 * made subject to such option by the copyright holder.
43
 */
44
45
package org.netbeans.modules.refactoring.spi.impl;
46
47
import java.beans.PropertyChangeEvent;
48
import java.beans.PropertyChangeListener;
49
import javax.swing.Action;
50
import javax.swing.SwingUtilities;
51
import org.openide.awt.ActionID;
52
import org.openide.awt.ActionReference;
53
import org.openide.awt.ActionRegistration;
54
import org.openide.util.HelpCtx;
55
import org.openide.util.NbBundle;
56
import org.openide.util.actions.CallableSystemAction;
57
58
@ActionID(id = "org.netbeans.modules.refactoring.spi.impl.UndoAction", category = "Refactoring")
59
@ActionRegistration(displayName = "#LBL_Undo")
60
@ActionReference(path = "Menu/Refactoring" , name = "UndoAction", position = 2000)
61
public class UndoAction extends CallableSystemAction implements PropertyChangeListener {
62
63
    private UndoManager undoManager;
64
65
    public UndoAction() {
66
        putValue(Action.NAME, getString("LBL_Undo")); //NOI18N
67
        putValue("noIconInMenu", Boolean.TRUE); // NOI18N
68
        undoManager = UndoManager.getDefault();
69
        undoManager.addPropertyChangeListener(this);
70
        updateState();
71
    }
72
    
73
    @Override
74
    public void propertyChange (PropertyChangeEvent event) {
75
        updateState();
76
    }
77
    
78
    private void updateState() {
79
        String desc = undoManager.getUndoDescription();
80
        String name = getString("LBL_Undo"); //NOI18N
81
        if (desc != null) {
82
            name += " [" + desc + "]"; //NOI18N
83
        }
84
85
        final String n = name;
86
        final boolean b = undoManager.isUndoAvailable();
87
        Runnable r = new Runnable() {
88
            @Override
89
            public void run() {
90
                setEnabled(b);
91
                putValue(Action.NAME, n);
92
            }
93
        };
94
95
        if (SwingUtilities.isEventDispatchThread()) {
96
            r.run();
97
        } else {
98
            SwingUtilities.invokeLater(r);
99
        }
100
    }
101
    
102
    private static final String getString(String key) {
103
        return NbBundle.getMessage(UndoAction.class, key);
104
    }
105
    
106
    @Override
107
    public void performAction() {
108
        undoManager.undo();
109
        undoManager.saveAll();
110
    }
111
    
112
    @Override
113
    public org.openide.util.HelpCtx getHelpCtx() {
114
        return HelpCtx.DEFAULT_HELP;
115
    }
116
    
117
    @Override
118
    public String getName() {
119
        return (String) getValue(Action.NAME);
120
    }
121
122
    @Override
123
    protected boolean asynchronous() {
124
        return true;
125
    }
126
}
(-)refactoring.api/src/org/netbeans/modules/refactoring/spi/impl/UndoManager.java (-368 / +134 lines)
Lines 41-139 Link Here
41
 * Version 2 license, then the option applies only if the new code is
41
 * Version 2 license, then the option applies only if the new code is
42
 * made subject to such option by the copyright holder.
42
 * made subject to such option by the copyright holder.
43
 */
43
 */
44
45
package org.netbeans.modules.refactoring.spi.impl;
44
package org.netbeans.modules.refactoring.spi.impl;
46
45
47
import java.beans.PropertyChangeEvent;
48
import java.beans.PropertyChangeListener;
49
import java.beans.PropertyChangeSupport;
50
import java.lang.reflect.InvocationTargetException;
51
import java.util.Arrays;
52
import java.util.Collection;
53
import java.util.HashMap;
54
import java.util.HashSet;
55
import java.util.IdentityHashMap;
46
import java.util.IdentityHashMap;
56
import java.util.Iterator;
47
import java.util.Iterator;
57
import java.util.LinkedList;
48
import java.util.LinkedList;
58
import java.util.Map;
49
import javax.swing.JOptionPane;
59
import java.util.Set;
50
import javax.swing.event.ChangeListener;
60
import javax.swing.SwingUtilities;
51
import javax.swing.undo.CannotRedoException;
61
import javax.swing.event.DocumentEvent;
52
import javax.swing.undo.CannotUndoException;
62
import javax.swing.event.DocumentListener;
63
import javax.swing.text.AbstractDocument;
64
import javax.swing.text.Document;
65
import javax.swing.text.StyledDocument;
66
import org.netbeans.api.project.FileOwnerQuery;
67
import org.netbeans.api.project.Project;
68
import org.netbeans.api.project.ui.OpenProjects;
69
import org.netbeans.modules.refactoring.spi.BackupFacility;
70
import org.netbeans.modules.refactoring.api.ProgressEvent;
53
import org.netbeans.modules.refactoring.api.ProgressEvent;
71
import org.netbeans.modules.refactoring.api.ProgressListener;
54
import org.netbeans.modules.refactoring.api.ProgressListener;
72
import org.netbeans.modules.refactoring.api.RefactoringSession;
55
import org.netbeans.modules.refactoring.api.RefactoringSession;
73
import org.openide.LifecycleManager;
56
import org.netbeans.modules.refactoring.spi.BackupFacility;
74
import org.openide.cookies.EditorCookie;
57
import org.openide.util.ChangeSupport;
75
import org.openide.filesystems.FileChangeAdapter;
58
import org.openide.util.NbBundle;
76
import org.openide.filesystems.FileEvent;
59
import org.openide.windows.WindowManager;
77
import org.openide.filesystems.FileObject;
78
import org.openide.filesystems.FileRenameEvent;
79
import org.openide.loaders.DataObject;
80
import org.openide.text.CloneableEditorSupport;
81
import org.openide.text.NbDocument;
82
import org.openide.util.Exceptions;
83
60
84
/**
61
/**
85
 *
62
 *
86
 * @author Jan Becicka
63
 * @author Jan Becicka
87
 */
64
 */
88
public final class UndoManager extends FileChangeAdapter implements DocumentListener, PropertyChangeListener /*, GlobalPathRegistryListener */{
65
public final class UndoManager {
89
    
66
    
90
    /** stack of undo items */
67
    /**
68
     * stack of undo items
69
     */
91
    private LinkedList<LinkedList<UndoItem>> undoList;
70
    private LinkedList<LinkedList<UndoItem>> undoList;
92
    
71
    /**
93
    /** stack of redo items */
72
     * stack of redo items
73
     */
94
    private LinkedList<LinkedList<UndoItem>> redoList;
74
    private LinkedList<LinkedList<UndoItem>> redoList;
95
75
96
    /** set of all CloneableEditorSupports */
76
    private final ChangeSupport changeSupport = new ChangeSupport(this);
97
    private final Set<CloneableEditorSupport> allCES = new HashSet<CloneableEditorSupport>();
98
    
99
    private final Map<FileObject, CloneableEditorSupport> fileObjectToCES = new HashMap<FileObject, CloneableEditorSupport>();
100
    
101
    /** map document -> CloneableEditorSupport */
102
    private final Map<Document, CloneableEditorSupport> documentToCES = new HashMap<Document, CloneableEditorSupport>();
103
    
104
    /** map listener -> CloneableEditorSupport */ 
105
    private final Map<InvalidationListener, Collection<? extends CloneableEditorSupport>> listenerToCES = new HashMap<InvalidationListener, Collection<? extends CloneableEditorSupport>>();
106
    private boolean listenersRegistered = false;
107
    
108
    public static final String PROP_STATE = "state"; //NOI18N
109
    
110
    private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
111
    
112
    private boolean wasUndo = false;
77
    private boolean wasUndo = false;
113
    private boolean wasRedo = false;
78
    private boolean wasRedo = false;
114
    private boolean transactionStart;
79
    private boolean transactionStart;
115
    private boolean dontDeleteUndo = false;
116
    
117
    private IdentityHashMap<LinkedList, String> descriptionMap;
80
    private IdentityHashMap<LinkedList, String> descriptionMap;
118
    private String description;
81
    private String description;
119
    private ProgressListener progress;
82
    private ProgressListener progress;
120
    
121
    private static UndoManager instance;
83
    private static UndoManager instance;
122
    private Set<Project> projects;
123
84
124
85
    /**
125
    public static UndoManager getDefault() {
86
     * Singleton instance
126
        if (instance==null) {
87
     * @return
88
     */
89
    public static synchronized UndoManager getDefault() {
90
        if (instance == null) {
127
            instance = new UndoManager();
91
            instance = new UndoManager();
128
        }
92
        }
129
        return instance;
93
        return instance;
130
    }
94
    }
131
    /** Creates a new instance of UndoManager */
95
96
    /**
97
     * Creates a new instance of UndoManager
98
     */
132
    private UndoManager() {
99
    private UndoManager() {
133
        undoList = new LinkedList<LinkedList<UndoItem>>();
100
        undoList = new LinkedList<LinkedList<UndoItem>>();
134
        redoList = new LinkedList<LinkedList<UndoItem>>();
101
        redoList = new LinkedList<LinkedList<UndoItem>>();
135
        descriptionMap = new IdentityHashMap<LinkedList, String>();
102
        descriptionMap = new IdentityHashMap<LinkedList, String>();
136
        projects = new HashSet<Project>();
137
    }
103
    }
138
    
104
    
139
    private UndoManager(ProgressListener progress) {
105
    private UndoManager(ProgressListener progress) {
Lines 141-221 Link Here
141
        this.progress = progress;
107
        this.progress = progress;
142
    }
108
    }
143
    
109
    
110
    /**
111
     * Setter for undo description. For instance "Rename"
112
     * @param desc 
113
     */
144
    public void setUndoDescription(String desc) { 
114
    public void setUndoDescription(String desc) { 
145
        description = desc;
115
        description = desc;
146
    }
116
    }
147
    
117
    
118
    /**
119
     * Getter for undo description.
120
     * @return
121
     */
148
    public String getUndoDescription() {
122
    public String getUndoDescription() {
149
        if (undoList.isEmpty()) return null;
123
        if (undoList.isEmpty()) {
124
            return null;
125
        }
150
        return descriptionMap.get(undoList.getFirst());
126
        return descriptionMap.get(undoList.getFirst());
151
    }
127
    }
152
    
128
    
129
    /**
130
     * Getter for Redo description.
131
     * @return
132
     */
153
    public String getRedoDescription() { 
133
    public String getRedoDescription() { 
154
        if (redoList.isEmpty()) return null;
134
        if (redoList.isEmpty()) {
135
            return null;
136
        }
155
        return descriptionMap.get(redoList.getFirst());
137
        return descriptionMap.get(redoList.getFirst());
156
    }
138
    }
157
    
139
    
158
    /** called to mark transaction start
140
    /**
141
     * called to mark transaction start
159
     */
142
     */
160
    public void transactionStarted() {
143
    public void transactionStarted() {
161
        transactionStart = true;
144
        transactionStart = true;
162
        unregisterListeners();
163
        //RepositoryUpdater.getDefault().setListenOnChanges(false);
164
    }
145
    }
165
    
146
    
166
    /**
147
    /**
167
     * called to mark end of transaction
148
     * called to mark end of transaction
168
     */
149
     */
169
    public void transactionEnded(boolean fail) {
150
    public void transactionEnded(boolean fail) {
170
        try {
171
            description = null;
151
            description = null;
172
            dontDeleteUndo = true;
152
        if (fail && !undoList.isEmpty()) {
173
            if (fail && !undoList.isEmpty())
153
            //XXX todo 
174
                undoList.removeFirst();
154
            //undoList.removeFirst();
175
            else {
155
        } else {
176
                // [TODO] (jb) this code disables undos for changes using org.openide.src
156
                // [TODO] (jb) this code disables undos for changes using org.openide.src
177
                if (isUndoAvailable() && getUndoDescription() == null) {
157
                if (isUndoAvailable() && getUndoDescription() == null) {
178
                    descriptionMap.remove(undoList.removeFirst());
158
                    descriptionMap.remove(undoList.removeFirst());
179
                    dontDeleteUndo = false;
180
                }
159
                }
181
                
182
            }
160
            }
183
            
161
        fireChange();
184
            invalidate(null);
185
            dontDeleteUndo = false;
186
        } finally {
187
            if (SwingUtilities.isEventDispatchThread()) {
188
                registerListeners();
189
            } else {
190
                try {
191
                    SwingUtilities.invokeAndWait(new Runnable() {
192
193
                        @Override
194
                        public void run() {
195
                            registerListeners();
196
                        }
162
                        }
197
                    });
198
                } catch (InterruptedException ex) {
199
                    Exceptions.printStackTrace(ex);
200
                } catch (InvocationTargetException ex) {
201
                    Exceptions.printStackTrace(ex);
202
                }
203
            }
204
            fireStateChange();
205
        }
206
    }
207
    
163
    
208
    /** undo last transaction */
164
    /**
165
     * undo last transaction
166
     */
209
    public void undo() {
167
    public void undo() {
210
        //System.out.println("************* Starting UNDO");
168
        //System.out.println("************* Starting UNDO");
211
        if (isUndoAvailable()) {
169
        if (isUndoAvailable()) {
170
            if (JOptionPane.showConfirmDialog(
171
                    WindowManager.getDefault().getMainWindow(),
172
                    NbBundle.getMessage(UndoManager.class, "MSG_ReallyUndo", getUndoDescription()),
173
                    NbBundle.getMessage(UndoManager.class, "MSG_ConfirmUndo"),
174
                    JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) {
175
                throw new CannotUndoException();
176
            }
177
178
            Runnable run = new Runnable() {
179
180
                public void run() {
212
            boolean fail = true;
181
            boolean fail = true;
213
            try {
182
            try {
214
                transactionStarted();
183
                transactionStarted();
215
                wasUndo = true;
184
                wasUndo = true;
216
                LinkedList undo =  (LinkedList) undoList.getFirst();
185
                        LinkedList undo = (LinkedList) undoList.getFirst();
217
                fireProgressListenerStart(0, undo.size());
186
                fireProgressListenerStart(0, undo.size());
218
                undoList.removeFirst();
219
                Iterator undoIterator = undo.iterator();
187
                Iterator undoIterator = undo.iterator();
220
                UndoItem item;
188
                UndoItem item;
221
                redoList.addFirst(new LinkedList<UndoItem>());
189
                redoList.addFirst(new LinkedList<UndoItem>());
Lines 228-233 Link Here
228
                        addItem(item);
196
                        addItem(item);
229
                    }
197
                    }
230
                }
198
                }
199
                        undoList.removeFirst();
231
                fail = false;
200
                fail = false;
232
            } finally {
201
            } finally {
233
                try {
202
                try {
Lines 235-258 Link Here
235
                    transactionEnded(fail);
204
                    transactionEnded(fail);
236
                } finally {
205
                } finally {
237
                    fireProgressListenerStop();
206
                    fireProgressListenerStop();
238
                    fireStateChange();
207
                            fireChange();
239
                }
208
                }
240
            }
209
            }
210
241
        }
211
        }
212
            };
213
214
//            if (SwingUtilities.isEventDispatchThread()) {
215
//                ProgressUtils.runOffEventDispatchThread(run,
216
//                        "Undoing... ",
217
//                        new AtomicBoolean(),
218
//                        false);
219
//            } else {
220
            run.run();
221
//            }
242
    }
222
    }
223
    }
243
    
224
    
244
    /** redo last undo
225
    /**
226
     * redo last undo
245
     */
227
     */
246
    public void redo() {
228
    public void redo() {
247
        //System.out.println("************* Starting REDO");
229
        //System.out.println("************* Starting REDO");
248
        if (isRedoAvailable()) {
230
        if (isRedoAvailable()) {
231
            if (JOptionPane.showConfirmDialog(
232
                    WindowManager.getDefault().getMainWindow(),
233
                    NbBundle.getMessage(UndoManager.class, "MSG_ReallyRedo", getRedoDescription()),
234
                    NbBundle.getMessage(UndoManager.class, "MSG_ConfirmRedo"),
235
                    JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) {
236
                throw new CannotRedoException();
237
            }
238
            Runnable run = new Runnable() {
239
240
                public void run() {
249
            boolean fail = true;
241
            boolean fail = true;
250
            try {
242
            try {
251
                transactionStarted();
243
                transactionStarted();
252
                wasRedo = true;
244
                wasRedo = true;
253
                LinkedList<UndoItem> redo = redoList.getFirst();
245
                LinkedList<UndoItem> redo = redoList.getFirst();
254
                fireProgressListenerStart(1, redo.size());
246
                fireProgressListenerStart(1, redo.size());
255
                redoList.removeFirst();
256
                Iterator<UndoItem> redoIterator = redo.iterator();
247
                Iterator<UndoItem> redoIterator = redo.iterator();
257
                UndoItem item;
248
                UndoItem item;
258
                description = descriptionMap.remove(redo);
249
                description = descriptionMap.remove(redo);
Lines 264-269 Link Here
264
                        addItem(item);
255
                        addItem(item);
265
                    }
256
                    }
266
                }
257
                }
258
                        redoList.removeFirst();
267
                fail = false;
259
                fail = false;
268
            } finally {
260
            } finally {
269
                try {
261
                try {
Lines 271-296 Link Here
271
                    transactionEnded(fail);
263
                    transactionEnded(fail);
272
                } finally {
264
                } finally {
273
                    fireProgressListenerStop();
265
                    fireProgressListenerStop();
274
                    fireStateChange();
266
                            fireChange();
275
                }
267
                }
276
            }
268
            }
277
        }
269
        }
270
            };
271
272
//            if (SwingUtilities.isEventDispatchThread()) {
273
//                ProgressUtils.runOffEventDispatchThread(run,
274
//                        "Redoing... ",
275
//                        new AtomicBoolean(),
276
//                        false);
277
//            } else {
278
            run.run();
279
//            }
278
    }
280
    }
281
    }
279
    
282
    
280
    /** clean undo/redo stacks */
283
    /**
284
     * clean undo/redo stacks
285
     */
281
    public void clear() {
286
    public void clear() {
282
        undoList.clear();
287
        undoList.clear();
283
        redoList.clear();
288
        redoList.clear();
284
        descriptionMap.clear();
289
        descriptionMap.clear();
285
        BackupFacility.getDefault().clear();
290
        BackupFacility.getDefault().clear();
286
        fireStateChange();
291
        fireChange();
287
    }
292
    }
288
    
293
    
289
    public void addItem(RefactoringSession session) {
294
    public void addItem(RefactoringSession session) {
290
        addItem(new SessionUndoItem(session));
295
        addItem(new SessionUndoItem(session));
291
    }
296
    }
292
    
297
    
293
    /** add new item to undo/redo list */
298
    /**
299
     * add new item to undo/redo list
300
     */
294
    private void addItem(UndoItem item) {
301
    private void addItem(UndoItem item) {
295
        if (wasUndo) {
302
        if (wasUndo) {
296
            LinkedList<UndoItem> redo = this.redoList.getFirst();
303
            LinkedList<UndoItem> redo = this.redoList.getFirst();
Lines 304-312 Link Here
304
            LinkedList<UndoItem> undo = this.undoList.getFirst();
311
            LinkedList<UndoItem> undo = this.undoList.getFirst();
305
            undo.addFirst(item);
312
            undo.addFirst(item);
306
        }
313
        }
307
        if (! (wasUndo || wasRedo)) 
314
        if (!(wasUndo || wasRedo)) {
308
            redoList.clear();
315
            redoList.clear();
309
    }
316
    }
317
    }
310
     
318
     
311
    public boolean isUndoAvailable() {
319
    public boolean isUndoAvailable() {
312
        return !undoList.isEmpty();
320
        return !undoList.isEmpty();
Lines 316-596 Link Here
316
        return !redoList.isEmpty();
324
        return !redoList.isEmpty();
317
    }
325
    }
318
    
326
    
319
    public void addPropertyChangeListener(PropertyChangeListener pcl) {
327
    public void addChangeListener(ChangeListener cl) {
320
        pcs.addPropertyChangeListener(pcl);
328
        changeSupport.addChangeListener(cl);
321
    }
329
    }
322
    
330
    
323
    public void removePropertyChangeListener(PropertyChangeListener pcl) {
331
    public void removeChangeListener(ChangeListener cl) {
324
        pcs.removePropertyChangeListener(pcl);
332
        changeSupport.removeChangeListener(cl);
325
    }
333
    }
326
334
327
    private void fireStateChange() {
335
    private void fireChange() {
328
        pcs.firePropertyChange(PROP_STATE, null, null);
336
        changeSupport.fireChange();
329
    }
337
    }
330
    
338
    
331
    public void watch(Collection<? extends CloneableEditorSupport> ceSupports, InvalidationListener l) {
332
        synchronized (allCES) {
333
            registerListeners();
334
        }
335
        for (final CloneableEditorSupport ces : ceSupports) {
336
            final Document d = ces.getDocument();
337
            if (d!=null) {
338
                d.render(new Runnable() {
339
                    @Override
340
                    public void run() {
341
                        synchronized(allCES) {
342
                            if (allCES.add(ces)) {
343
                                ces.addPropertyChangeListener(UndoManager.this);
344
                                d.addDocumentListener(UndoManager.this);
345
                                documentToCES.put(d, ces);
346
                                Object o = d.getProperty(Document.StreamDescriptionProperty);
347
                                if (o instanceof DataObject) {
348
                                    FileObject file = ((DataObject)o).getPrimaryFile();
349
                                    fileObjectToCES.put(file, ces);
350
                                    Project p = FileOwnerQuery.getOwner(file);
351
                                    if (p!= null) 
352
                                        projects.add(p);
353
                                }
354
                            }
355
                        }
356
                    }
357
                });
358
            } else {
359
                synchronized(allCES) {
360
                    if (allCES.add(ces)) {
361
                        ces.addPropertyChangeListener(UndoManager.this);
362
                    }
363
                }
364
            }
365
        }
366
        synchronized(allCES) {
367
            if (l != null) {
368
                listenerToCES.put(l, ceSupports);
369
            }
370
        }
371
    }
372
    
373
    public void stopWatching(InvalidationListener l) {
374
        //synchronized (undoStack) {
375
            synchronized (allCES) {
376
                listenerToCES.remove(l);
377
                clearIfPossible();
378
            }
379
        //}
380
    }
381
    
382
    private static java.lang.reflect.Field undoRedo;
383
    
384
    static{
385
        try {
386
            //obviously hack. See 108616 and 48427
387
            undoRedo = org.openide.text.CloneableEditorSupport.class.getDeclaredField("undoRedo"); //NOI18N
388
            undoRedo.setAccessible(true);
389
        } catch (NoSuchFieldException ex) {
390
            Exceptions.printStackTrace(ex);
391
        } catch (SecurityException ex) {
392
            Exceptions.printStackTrace(ex);
393
        }
394
    }
395
396
    private void discardAllEdits(InvalidationListener l) {
397
        for (CloneableEditorSupport s:listenerToCES==null||l==null?allCES:listenerToCES.get(l)) {
398
            try {
399
                org.openide.awt.UndoRedo.Manager manager = (org.openide.awt.UndoRedo.Manager) undoRedo.get(s);
400
                if (manager!=null) {
401
                    //if manager not initialized - there is nothing to discard
402
                    //#114485
403
                    manager.discardAllEdits();
404
                }
405
            } catch (SecurityException ex) {
406
                Exceptions.printStackTrace(ex);
407
            } catch (IllegalArgumentException ex) {
408
                Exceptions.printStackTrace(ex);
409
            } catch (IllegalAccessException ex) {
410
                Exceptions.printStackTrace(ex);
411
            }
412
        }
413
    }
414
    
415
//    TODO: 
416
//    public void pathsAdded(GlobalPathRegistryEvent event) {
417
//    }
418
//
419
//    public void pathsRemoved(GlobalPathRegistryEvent event) {
420
//        assert event != null : "event == null"; // NOI18N
421
//        if (event.getId().equals(ClassPath.SOURCE)) {
422
//            clear();
423
//        }
424
//    }
425
426
    private void registerListeners() {
427
        if (listenersRegistered) return;
428
        // TODO: 
429
        // GlobalPathRegistry.getDefault().addGlobalPathRegistryListener(this);
430
        Util.addFileSystemsListener(this);
431
        for (CloneableEditorSupport ces:allCES) {
432
            ces.addPropertyChangeListener(this);
433
        }
434
        for (Document doc:documentToCES.keySet()) {
435
            doc.addDocumentListener(this);
436
        }
437
        OpenProjects.getDefault().addPropertyChangeListener(this);
438
        listenersRegistered = true;
439
    }
440
    
441
    private void unregisterListeners() {
442
        if (!listenersRegistered) return;
443
        OpenProjects.getDefault().removePropertyChangeListener(this);
444
        Util.removeFileSystemsListener(this);
445
        //TODO: 
446
        //GlobalPathRegistry.getDefault().removeGlobalPathRegistryListener(this);
447
        for (CloneableEditorSupport ces:allCES) {
448
            ces.removePropertyChangeListener(this);
449
        }
450
        for (Document doc:documentToCES.keySet()) {
451
            doc.removeDocumentListener(this);
452
        }
453
        listenersRegistered = false;
454
    }
455
    
456
    private void invalidate(CloneableEditorSupport ces) {
457
        synchronized (undoList) {
458
            if (!(wasRedo || wasUndo) && !dontDeleteUndo) {
459
                clear();
460
            } 
461
            synchronized (allCES) {
462
                if (ces == null) {
463
                    // invalidate all
464
                    for (InvalidationListener lis:listenerToCES.keySet()) {
465
                        lis.invalidateObject();
466
                        discardAllEdits(lis);
467
                    }
468
                    listenerToCES.clear();
469
                } else {
470
                    for (Iterator<Map.Entry<InvalidationListener, Collection<? extends CloneableEditorSupport>>> it = listenerToCES.entrySet().iterator(); it.hasNext();) {
471
                        Map.Entry<InvalidationListener, Collection<? extends CloneableEditorSupport>> e = it.next();
472
                        if ((e.getValue()).contains(ces)) {
473
                            e.getKey().invalidateObject();
474
                            it.remove();
475
                        }
476
                    }
477
                    /*ces.removeChangeListener(this);
478
                    allCES.remove(ces);
479
                    Document d = ces.getDocument();
480
                    if (d != null) {
481
                        d.removeDocumentListener(this);
482
                        documentToCES.remove(d);
483
                    }
484
                     */
485
                }
486
                clearIfPossible();
487
            }
488
        }
489
    }
490
    
491
    private void clearIfPossible() {
492
        if (listenerToCES.isEmpty() && undoList.isEmpty() && redoList.isEmpty()) {
493
            unregisterListeners();
494
            allCES.clear();
495
            documentToCES.clear();
496
            fileObjectToCES.clear();
497
            projects.clear();
498
        }
499
    }        
500
    
501
    // FileChangeAdapter ........................................................
502
    
503
    @Override
504
    public void fileChanged(FileEvent fe) {   
505
        CloneableEditorSupport ces = fileObjectToCES.get(fe.getFile());
506
        if (ces!=null) {
507
            invalidate(ces);
508
        }
509
    }
510
    
511
    @Override
512
    public void fileDeleted(FileEvent fe) {
513
        fileChanged(fe);
514
    }
515
516
    @Override
517
    public void fileRenamed(FileRenameEvent fe) {
518
        fileChanged(fe);
519
    }
520
    
521
    // DocumentListener .........................................................
522
    
523
    @Override
524
    public void changedUpdate(DocumentEvent e) {
525
    }
526
527
    @Override
528
    public void insertUpdate(DocumentEvent e) {        
529
        invalidate(documentToCES.get(e.getDocument()));
530
    }
531
532
    @Override
533
    public void removeUpdate(DocumentEvent e) {
534
        invalidate(documentToCES.get(e.getDocument()));
535
    }
536
        
537
    private void documentStateChanged(CloneableEditorSupport ces) {
538
        synchronized (allCES) {
539
            Document d = ces.getDocument();
540
            for (Iterator it = documentToCES.entrySet().iterator(); it.hasNext();) {
541
                Map.Entry en = (Map.Entry) it.next();
542
                if (en.getValue() == ces) {
543
                    ((Document) en.getKey()).removeDocumentListener(this);
544
                    it.remove();
545
                    break;
546
                }
547
            }
548
            if (d != null) {
549
                documentToCES.put(d, ces);
550
                d.addDocumentListener(this);
551
            }
552
        }
553
    }
554
    
555
    public void saveAll() {
556
        synchronized (allCES) {
557
            unregisterListeners();
558
        }
559
        try {
560
            LifecycleManager.getDefault().saveAll();
561
        } finally {
562
            synchronized (allCES) {
563
                registerListeners();
564
            }
565
        }
566
    }
567
568
    private void fireProgressListenerStart(int type, int count) {
339
    private void fireProgressListenerStart(int type, int count) {
569
        stepCounter = 0;
340
        stepCounter = 0;
570
        if (progress == null)
341
        if (progress == null) {
571
            return;
342
            return;
343
        }
572
        progress.start(new ProgressEvent(this, ProgressEvent.START, type, count));
344
        progress.start(new ProgressEvent(this, ProgressEvent.START, type, count));
573
    }
345
    }
574
    
575
    private int stepCounter = 0;
346
    private int stepCounter = 0;
576
    /** Notifies all registered listeners about the event.
347
348
    /**
349
     * Notifies all registered listeners about the event.
577
     */
350
     */
578
    private void fireProgressListenerStep() {
351
    private void fireProgressListenerStep() {
579
        if (progress == null)
352
        if (progress == null) {
580
            return;
353
            return;
354
        }
581
        progress.step(new ProgressEvent(this, ProgressEvent.STEP, 0, ++stepCounter));
355
        progress.step(new ProgressEvent(this, ProgressEvent.STEP, 0, ++stepCounter));
582
    }
356
    }
583
357
584
    /** Notifies all registered listeners about the event.
358
    /**
359
     * Notifies all registered listeners about the event.
585
     */
360
     */
586
    private void fireProgressListenerStop() {
361
    private void fireProgressListenerStop() {
587
        if (progress == null)
362
        if (progress == null) {
588
            return;
363
            return;
364
        }
589
        progress.stop(new ProgressEvent(this, ProgressEvent.STOP));
365
        progress.stop(new ProgressEvent(this, ProgressEvent.STOP));
590
    }
366
    }
591
    
367
    
592
    private interface UndoItem {
368
    private interface UndoItem {
369
593
        void undo();
370
        void undo();
371
594
        void redo();
372
        void redo();
595
    }
373
    }
596
    
374
    
Lines 598-604 Link Here
598
        
376
        
599
         private RefactoringSession change;
377
         private RefactoringSession change;
600
        
378
        
601
        public SessionUndoItem (RefactoringSession change) {
379
        public SessionUndoItem(RefactoringSession change) {
602
            this.change = change;
380
            this.change = change;
603
        }
381
        }
604
        
382
        
Lines 612-627 Link Here
612
            change.doRefactoring(false);
390
            change.doRefactoring(false);
613
        }
391
        }
614
    }
392
    }
615
616
    @Override
617
    public void propertyChange(PropertyChangeEvent evt) {
618
        if (OpenProjects.PROPERTY_OPEN_PROJECTS.equals(evt.getPropertyName())) {
619
            Set<Project> p = new HashSet<Project>(projects);
620
            p.removeAll(Arrays.asList((Project[])evt.getNewValue()));
621
            if (!p.isEmpty())
622
                invalidate(null);
623
        } else if (EditorCookie.Observable.PROP_DOCUMENT.equals(evt.getPropertyName())) {
624
            documentStateChanged((CloneableEditorSupport) evt.getSource());
625
        }
393
        }
626
    }
627
}
(-)refactoring.api/src/org/netbeans/modules/refactoring/spi/impl/UndoWatcher.java (-90 lines)
Lines 1-90 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * Contributor(s):
28
 *
29
 * The Original Software is NetBeans. The Initial Developer of the Original
30
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
31
 * Microsystems, Inc. All Rights Reserved.
32
 *
33
 * If you wish your version of this file to be governed by only the CDDL
34
 * or only the GPL Version 2, indicate your decision by adding
35
 * "[Contributor] elects to include this software in this distribution
36
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
37
 * single choice of license, a recipient has the option to distribute
38
 * your version of this file under either the CDDL, the GPL Version 2 or
39
 * to extend the choice of license to its licensees as provided above.
40
 * However, if you add GPL Version 2 code and therefore, elected the GPL
41
 * Version 2 license, then the option applies only if the new code is
42
 * made subject to such option by the copyright holder.
43
 */
44
package org.netbeans.modules.refactoring.spi.impl;
45
46
import java.util.Collection;
47
import java.util.Collections;
48
import java.util.HashSet;
49
import java.util.Iterator;
50
import org.netbeans.modules.refactoring.api.RefactoringElement;
51
import org.netbeans.modules.refactoring.api.RefactoringSession;
52
import org.netbeans.modules.refactoring.spi.impl.UndoManager;
53
import org.openide.cookies.EditorCookie;
54
import org.openide.loaders.DataObject;
55
import org.openide.text.CloneableEditorSupport;
56
import org.openide.text.PositionBounds;
57
58
/** 
59
 *
60
 * @author Martin Matula, Daniel Prusa
61
 */
62
public class UndoWatcher {
63
64
     private static Collection extractCES(Collection elements) {
65
        HashSet result = new HashSet();
66
        for (Iterator it = elements.iterator(); it.hasNext();) {
67
            RefactoringElement e = (RefactoringElement) it.next();
68
            PositionBounds pb = e.getPosition();
69
            if (pb != null) {
70
                CloneableEditorSupport ces = pb.getBegin().getCloneableEditorSupport();
71
                result.add(ces);
72
            }
73
        }
74
        return result;
75
    }
76
77
    public static void watch(RefactoringSession session, InvalidationListener l) {
78
        UndoManager.getDefault().watch(extractCES(session.getRefactoringElements()), l);
79
    }
80
81
    public static void stopWatching(InvalidationListener l) {
82
        UndoManager.getDefault().stopWatching(l);
83
    }
84
    
85
    public static void watch(DataObject o) {
86
        EditorCookie ces = o.getCookie(EditorCookie.class);
87
        assert ces instanceof CloneableEditorSupport;
88
        UndoManager.getDefault().watch(Collections.singleton((CloneableEditorSupport)ces), null);
89
    }
90
}
(-)refactoring.api/src/org/netbeans/modules/refactoring/spi/impl/UndoableWrapper.java (+206 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.refactoring.spi.impl;
43
44
import java.util.HashMap;
45
import java.util.Map;
46
import java.util.concurrent.atomic.AtomicBoolean;
47
import javax.swing.text.Document;
48
import javax.swing.text.JTextComponent;
49
import javax.swing.undo.CannotRedoException;
50
import javax.swing.undo.CannotUndoException;
51
import javax.swing.undo.CompoundEdit;
52
import javax.swing.undo.UndoableEdit;
53
import org.netbeans.api.editor.EditorRegistry;
54
import org.netbeans.api.editor.mimelookup.MimeRegistration;
55
import org.netbeans.editor.BaseDocument;
56
import org.netbeans.spi.editor.document.UndoableEditWrapper;
57
import org.openide.loaders.DataObject;
58
import org.openide.text.CloneableEditorSupport;
59
60
/**
61
 *
62
 * @author Jan Becicka
63
 */
64
@MimeRegistration(mimeType="", service=UndoableEditWrapper.class)
65
public class UndoableWrapper implements UndoableEditWrapper {
66
67
    private AtomicBoolean active = new AtomicBoolean();
68
    private Map<BaseDocument, UndoableEditDelegate> docToFirst = new HashMap();
69
70
    public UndoableWrapper() {
71
    }
72
    
73
74
    @Override
75
    public UndoableEdit wrap(UndoableEdit ed, Document doc) {
76
        if (!active.get())
77
            return ed;
78
        if (doc.getProperty(BaseDocument.StreamDescriptionProperty) == null) {
79
            //no dataobject
80
            return ed;
81
        } 
82
        UndoableEditDelegate current = new UndoableEditDelegate(ed, (BaseDocument) doc);
83
        UndoableEditDelegate first = docToFirst.get(doc);
84
        if (first == null) {
85
            docToFirst.put((BaseDocument) doc, current);
86
        }
87
        return current;
88
    }
89
90
    public void close() {
91
        for (UndoableEditDelegate first: docToFirst.values()) {
92
            first.end();
93
        }
94
        docToFirst.clear();
95
    }
96
97
    public void setActive(boolean b) {
98
        active.set(b);
99
    }
100
101
    public class UndoableEditDelegate implements UndoableEdit {
102
103
        private UndoManager undoManager;
104
        private CloneableEditorSupport ces;
105
        private UndoableEdit delegate;
106
        private CompoundEdit inner;
107
108
        private UndoableEditDelegate(UndoableEdit ed, BaseDocument doc) {
109
            undoManager = UndoManager.getDefault();
110
            DataObject dob = (DataObject) doc.getProperty(BaseDocument.StreamDescriptionProperty);
111
            ces = dob.getLookup().lookup(CloneableEditorSupport.class);
112
            //this.delegate = ed;
113
            this.inner = new CompoundEdit();
114
            inner.addEdit(ed);
115
            delegate = ed;
116
        }
117
118
        @Override
119
        public void undo() throws CannotUndoException {
120
            JTextComponent focusedComponent = EditorRegistry.focusedComponent();
121
            if (focusedComponent != null) {
122
                if (focusedComponent.getDocument() == ces.getDocument()) {
123
                    //call global undo only for focused component
124
                    undoManager.undo();
125
                }
126
            }
127
            //delegate.undo();
128
            inner.undo();
129
        }
130
131
        @Override
132
        public boolean canUndo() {
133
            //return delegate.canUndo();
134
            return inner.canUndo();
135
        }
136
137
        @Override
138
        public void redo() throws CannotRedoException {
139
            JTextComponent focusedComponent = EditorRegistry.focusedComponent();
140
            if (focusedComponent != null) {
141
                if (focusedComponent.getDocument() == ces.getDocument()) {
142
                    //call global undo only for focused component
143
                    undoManager.redo();
144
                }
145
            }
146
            //delegate.redo();
147
            inner.redo();
148
        }
149
150
        @Override
151
        public boolean canRedo() {
152
            //return delegate.canRedo();
153
            return inner.canRedo();
154
        }
155
156
        @Override
157
        public void die() {
158
            //delegate.die();
159
            inner.die();
160
        }
161
162
        @Override
163
        public boolean addEdit(UndoableEdit ue) {
164
            if (ue instanceof UndoableEditDelegate) {
165
                return inner.addEdit(((UndoableEditDelegate) ue).unwrap());
166
            }
167
            return false;
168
            //return delegate.addEdit(ue);
169
        }
170
        
171
        public UndoableEdit unwrap() {
172
            return delegate;
173
        }
174
175
        @Override
176
        public boolean replaceEdit(UndoableEdit ue) {
177
            return inner.replaceEdit(ue);
178
            //return delegate.replaceEdit(ue);
179
        }
180
181
        @Override
182
        public boolean isSignificant() {
183
            return inner.isSignificant();
184
            //return delegate.isSignificant();
185
        }
186
187
        @Override
188
        public String getPresentationName() {
189
            return undoManager.getUndoDescription();
190
        }
191
192
        @Override
193
        public String getUndoPresentationName() {
194
            return undoManager.getUndoDescription();
195
        }
196
197
        @Override
198
        public String getRedoPresentationName() {
199
            return undoManager.getRedoDescription();
200
        }
201
202
        private void end() {
203
            inner.end();
204
        }
205
    }
206
}
(-)refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/RetoucheCommit.java (-156 lines)
Lines 1-156 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * Contributor(s):
28
 *
29
 * The Original Software is NetBeans. The Initial Developer of the Original
30
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
31
 * Microsystems, Inc. All Rights Reserved.
32
 *
33
 * If you wish your version of this file to be governed by only the CDDL
34
 * or only the GPL Version 2, indicate your decision by adding
35
 * "[Contributor] elects to include this software in this distribution
36
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
37
 * single choice of license, a recipient has the option to distribute
38
 * your version of this file under either the CDDL, the GPL Version 2 or
39
 * to extend the choice of license to its licensees as provided above.
40
 * However, if you add GPL Version 2 code and therefore, elected the GPL
41
 * Version 2 license, then the option applies only if the new code is
42
 * made subject to such option by the copyright holder.
43
 */
44
package org.netbeans.modules.refactoring.java.plugins;
45
46
import java.io.File;
47
import java.io.IOException;
48
import java.util.*;
49
import java.util.logging.Level;
50
import java.util.logging.Logger;
51
import org.netbeans.api.java.source.ModificationResult;
52
import org.netbeans.modules.refactoring.spi.BackupFacility;
53
import org.netbeans.modules.refactoring.spi.Transaction;
54
import org.openide.cookies.EditorCookie;
55
import org.openide.filesystems.FileObject;
56
import org.openide.filesystems.FileUtil;
57
import org.openide.loaders.DataObject;
58
import org.openide.loaders.DataObjectNotFoundException;
59
import org.openide.util.Exceptions;
60
61
/**
62
 *
63
 * @author Jan Becicka
64
 */
65
66
public class RetoucheCommit implements Transaction {
67
    private static final Logger LOG = Logger.getLogger(RetoucheCommit.class.getName());
68
    List<BackupFacility.Handle> ids = new ArrayList<BackupFacility.Handle>();
69
    private boolean commited = false;
70
    Collection<ModificationResult> results;
71
    private Set<File> newFiles;
72
    
73
    public RetoucheCommit(Collection<ModificationResult> results) {
74
        this.results = results;
75
    }
76
    
77
    @Override
78
    public void commit() {
79
        try {
80
            if (commited) {
81
                for (BackupFacility.Handle id:ids) {
82
                    try {
83
                        id.restore();
84
                    } catch (IOException ex) {
85
                        throw new RuntimeException(ex);
86
                    }
87
                }
88
            } else {
89
                commited = true;
90
                for (ModificationResult result:results) {
91
                    ids.add(BackupFacility.getDefault().backup(result.getModifiedFileObjects()));
92
                    if (newFiles == null) {
93
                        newFiles = new HashSet<File>();
94
                    }
95
                    newFiles.addAll(result.getNewFiles());
96
                    result.commit();
97
                }
98
99
                openNewFiles(newFiles);
100
            }
101
            
102
        } catch (IOException ex) {
103
            throw new RuntimeException(ex);
104
        }
105
    }
106
    
107
    private boolean newFilesStored = false;
108
    @Override
109
    public void rollback() {
110
        for (BackupFacility.Handle id:ids) {
111
            try {
112
                id.restore();
113
            } catch (IOException ex) {
114
                throw new RuntimeException(ex);
115
            }
116
        }
117
        boolean localStored = false;
118
        if (newFiles!=null) {
119
            for (File f:newFiles) {
120
                try {
121
                    FileObject fo = FileUtil.toFileObject(f);
122
                    if (!newFilesStored) {
123
                        ids.add(BackupFacility.getDefault().backup(fo));
124
                        localStored = true;
125
                    }
126
                    fo.delete();
127
                } catch (IOException ex) {
128
                    Exceptions.printStackTrace(ex);
129
                }
130
            }
131
            newFilesStored |= localStored;
132
        }
133
    }
134
135
    private static void openNewFiles(Set<File> newFiles) {
136
        if (newFiles == null) {
137
            return;
138
        }
139
        for (File file : newFiles) {
140
            FileObject fo = FileUtil.toFileObject(file);
141
            if (fo != null) {
142
                try {
143
                    DataObject dobj = DataObject.find(fo);
144
                    EditorCookie editor = dobj.getLookup().lookup(EditorCookie.class);
145
                    if (editor != null) {
146
                        editor.open();
147
                    }
148
                } catch (DataObjectNotFoundException ex) {
149
                    // not harmful
150
                    LOG.log(Level.INFO, ex.getMessage(), ex);
151
                }
152
            }
153
        }
154
    }
155
}
156
            
(-)refactoring.java/src/org/netbeans/modules/refactoring/java/spi/JavaModificationResult.java (+81 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.refactoring.java.spi;
43
44
import java.io.File;
45
import java.io.IOException;
46
import java.util.Collection;
47
import org.netbeans.modules.refactoring.spi.ModificationResult;
48
import org.openide.filesystems.FileObject;
49
50
/**
51
 *
52
 * @author Jan Becicka
53
 */
54
class JavaModificationResult implements ModificationResult {
55
56
    private org.netbeans.api.java.source.ModificationResult delegate;
57
    
58
    JavaModificationResult(org.netbeans.api.java.source.ModificationResult r) {
59
        this.delegate = r;
60
    }
61
62
    @Override
63
    public Collection<? extends FileObject> getModifiedFileObjects() {
64
        return delegate.getModifiedFileObjects();
65
    }
66
67
    @Override
68
    public Collection<? extends File> getNewFiles() {
69
        return delegate.getNewFiles();
70
    }
71
72
    @Override
73
    public void commit() throws IOException {
74
        delegate.commit();
75
    }
76
77
    @Override
78
    public String getResultingSource(FileObject file) throws IOException, IllegalArgumentException {
79
        return delegate.getResultingSource(file);
80
    }
81
}
(-)refactoring.java/src/org/netbeans/modules/refactoring/java/spi/JavaRefactoringPlugin.java (-2 / +10 lines)
Lines 59-65 Link Here
59
import org.netbeans.modules.refactoring.java.api.JavaRefactoringUtils;
59
import org.netbeans.modules.refactoring.java.api.JavaRefactoringUtils;
60
import org.netbeans.modules.refactoring.java.plugins.FindVisitor;
60
import org.netbeans.modules.refactoring.java.plugins.FindVisitor;
61
import org.netbeans.modules.refactoring.java.plugins.JavaPluginUtils;
61
import org.netbeans.modules.refactoring.java.plugins.JavaPluginUtils;
62
import org.netbeans.modules.refactoring.java.plugins.RetoucheCommit;
62
import org.netbeans.modules.refactoring.spi.RefactoringCommit;
63
import org.netbeans.modules.refactoring.spi.ProgressProviderAdapter;
63
import org.netbeans.modules.refactoring.spi.ProgressProviderAdapter;
64
import org.netbeans.modules.refactoring.spi.RefactoringElementsBag;
64
import org.netbeans.modules.refactoring.spi.RefactoringElementsBag;
65
import org.netbeans.modules.refactoring.spi.RefactoringPlugin;
65
import org.netbeans.modules.refactoring.spi.RefactoringPlugin;
Lines 104-113 Link Here
104
     * @author Jan Becicka
104
     * @author Jan Becicka
105
     */
105
     */
106
    public static Transaction createTransaction(@NonNull Collection<ModificationResult> modifications) {
106
    public static Transaction createTransaction(@NonNull Collection<ModificationResult> modifications) {
107
        return new RetoucheCommit(modifications);
107
        return new RefactoringCommit(createJavaModifications(modifications));
108
    }
108
    }
109
109
110
    private static Collection<org.netbeans.modules.refactoring.spi.ModificationResult> createJavaModifications(Collection<ModificationResult> modifications) {
111
        LinkedList<org.netbeans.modules.refactoring.spi.ModificationResult> result = new LinkedList();
112
        for (ModificationResult r:modifications) {
113
            result.add(new JavaModificationResult(r));
114
        }
115
        return result;
116
    }
110
    
117
    
118
    
111
    protected Problem preCheck(CompilationController javac) throws IOException {
119
    protected Problem preCheck(CompilationController javac) throws IOException {
112
        return null;
120
        return null;
113
    }
121
    }

Return to bug 48427