diff -r 687656888bfe core.multiview/nbproject/project.xml --- a/core.multiview/nbproject/project.xml Tue Feb 02 16:33:18 2010 +0300 +++ b/core.multiview/nbproject/project.xml Wed Feb 03 20:04:18 2010 +0100 @@ -134,6 +134,11 @@ + org.openide.loaders + + + + org.openide.windows diff -r 687656888bfe core.multiview/test/unit/src/org/netbeans/core/multiview/issue180221/Bundle.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core.multiview/test/unit/src/org/netbeans/core/multiview/issue180221/Bundle.properties Wed Feb 03 20:04:18 2010 +0100 @@ -0,0 +1,5 @@ +CTL_SomeAction=XYZ +LBL_XYZ_loader_name=XYZ Files +OpenIDE-Module-Name=LineSetIssue +Services/MIMEResolver/XYZResolver.xml=XYZ Files +Templates/Other/XYZTemplate.xyz=Empty XYZ file diff -r 687656888bfe core.multiview/test/unit/src/org/netbeans/core/multiview/issue180221/DesignViewDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core.multiview/test/unit/src/org/netbeans/core/multiview/issue180221/DesignViewDescription.java Wed Feb 03 20:04:18 2010 +0100 @@ -0,0 +1,48 @@ +package org.netbeans.core.multiview.issue180221; + +import org.netbeans.core.spi.multiview.MultiViewDescription; +import org.netbeans.core.spi.multiview.MultiViewElement; +import org.openide.util.HelpCtx; +import org.openide.windows.TopComponent; + +import java.awt.*; +import java.io.Serializable; + +/** + * @author David Kaspar + */ +public final class DesignViewDescription implements MultiViewDescription, Serializable { + + private static final long serialVersionUID = -1l; + + private XYZDataObject designDataObject; + + public DesignViewDescription (XYZDataObject designDataObject) { + this.designDataObject = designDataObject; + } + + public int getPersistenceType () { + return TopComponent.PERSISTENCE_ONLY_OPENED; + } + + public String getDisplayName () { + return "Design"; + } + + public Image getIcon () { + return null; + } + + public HelpCtx getHelpCtx () { + return null; + } + + public String preferredID () { + return null; + } + + public MultiViewElement createElement () { + return new DesignViewElement (designDataObject); + } + +} diff -r 687656888bfe core.multiview/test/unit/src/org/netbeans/core/multiview/issue180221/DesignViewElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core.multiview/test/unit/src/org/netbeans/core/multiview/issue180221/DesignViewElement.java Wed Feb 03 20:04:18 2010 +0100 @@ -0,0 +1,96 @@ +package org.netbeans.core.multiview.issue180221; + +import org.netbeans.core.spi.multiview.CloseOperationState; +import org.netbeans.core.spi.multiview.MultiViewElement; +import org.netbeans.core.spi.multiview.MultiViewElementCallback; +import org.netbeans.core.spi.multiview.MultiViewFactory; +import org.openide.awt.UndoRedo; +import org.openide.util.Lookup; + +import javax.swing.*; +import java.io.IOException; +import java.io.Serializable; +import org.openide.windows.TopComponent; + +/** + * @author David Kaspar + */ +public final class DesignViewElement implements MultiViewElement, Serializable { + + public static volatile int COUNTER = 0; + + private static final long serialVersionUID = -1; + + private XYZDataObject designDataObject; + private transient MultiViewElementCallback multiViewElementCallback; + + DesignViewElement (XYZDataObject designDataObject) { + this.designDataObject = designDataObject; + COUNTER ++; + init (); + } + + private void init () { + } + + public JComponent getVisualRepresentation () { + return new TopComponent (); + } + + public JComponent getToolbarRepresentation () { + return new JPanel (); + } + + public Action[] getActions () { + return new Action[0]; + } + + public Lookup getLookup () { + return designDataObject.getLookup (); + } + + public void setMultiViewCallback(MultiViewElementCallback multiViewElementCallback) { + this.multiViewElementCallback = multiViewElementCallback; + } + + public CloseOperationState canCloseElement () { + if (! designDataObject.getEditorSupport ().isLastView (multiViewElementCallback.getTopComponent ())) + return CloseOperationState.STATE_OK; + return MultiViewFactory.createUnsafeCloseState(SourceViewElement.CLOSING_ID, null, null); + } + + private void writeObject (java.io.ObjectOutputStream out) throws IOException { + out.writeObject (designDataObject); + } + + private void readObject (java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + Object object = in.readObject (); + if (! (object instanceof XYZDataObject)) + throw new ClassNotFoundException ("DataObject expected but not found"); // NOI18N + designDataObject = (XYZDataObject) object; + init (); + } + + public void componentOpened() { + } + + public void componentClosed() { + } + + public void componentShowing() { + } + + public void componentHidden() { + } + + public void componentActivated() { + } + + public void componentDeactivated() { + } + + public UndoRedo getUndoRedo() { + return UndoRedo.NONE; + } + +} diff -r 687656888bfe core.multiview/test/unit/src/org/netbeans/core/multiview/issue180221/Issue180221Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core.multiview/test/unit/src/org/netbeans/core/multiview/issue180221/Issue180221Test.java Wed Feb 03 20:04:18 2010 +0100 @@ -0,0 +1,65 @@ +package org.netbeans.core.multiview.issue180221; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import junit.framework.Test; +import org.netbeans.core.api.multiview.MultiViewPerspective; +import org.netbeans.junit.NbModuleSuite; +import org.netbeans.junit.NbTestCase; +import org.openide.cookies.OpenCookie; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileSystem; +import org.openide.filesystems.FileUtil; +import org.openide.loaders.DataLoaderPool; +import org.openide.loaders.DataObject; + +/** + * @author David Kaspar + */ +public class Issue180221Test extends NbTestCase { + + public Issue180221Test(String name) { + super(name); + } + + public static Test suite () { + return NbModuleSuite.create(NbModuleSuite.emptyConfiguration().addTest(Issue180221Test.class).gui(false)); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + FileObject fo = FileUtil.createData(FileUtil.getConfigRoot(), "Services/MIMEResolver/XYZResolver.xml"); + InputStream is = Issue180221Test.class.getResourceAsStream("XYZResolver.xml"); + OutputStream os = fo.getOutputStream(); + FileUtil.copy(is, os); + is.close (); + os.close (); + + FileObject fo2 = FileUtil.createData(FileUtil.getConfigRoot(), "Loaders/text/x-xyz/Factories/XYZDataLoader.instance"); + fo2.setAttribute("instanceCreate", DataLoaderPool.factory(XYZDataObject.class, "test/x-xyz", null)); + } + + @Override + protected boolean runInEQ() { + return true; + } + + public void testOpenAt () throws IOException { + clearWorkDir(); + FileObject workDir = FileUtil.toFileObject(getWorkDir()); + FileObject xyz = workDir.createData("a", "xyz"); + DataObject d = DataObject.find (xyz); + assertTrue ("The DataObject should be XYZDataObject but is: " + d + ".", d instanceof XYZDataObject); + + d.getLookup().lookup(OpenCookie.class).open (); + assertEquals("SourceView should NOT be opened.", 0, SourceViewElement.COUNTER); + assertEquals("DesignView should be opened.", 1, DesignViewElement.COUNTER); + + XYZDataEditorSupport c = d.getLookup().lookup(XYZDataEditorSupport.class); + c.openAt (); + assertEquals("SourceView should be opened.", 1, SourceViewElement.COUNTER); + } + +} diff -r 687656888bfe core.multiview/test/unit/src/org/netbeans/core/multiview/issue180221/SourceViewDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core.multiview/test/unit/src/org/netbeans/core/multiview/issue180221/SourceViewDescription.java Wed Feb 03 20:04:18 2010 +0100 @@ -0,0 +1,48 @@ +package org.netbeans.core.multiview.issue180221; + +import org.netbeans.core.spi.multiview.MultiViewDescription; +import org.netbeans.core.spi.multiview.MultiViewElement; +import org.openide.util.HelpCtx; +import org.openide.windows.TopComponent; + +import java.awt.*; +import java.io.Serializable; + +/** + * @author David Kaspar + */ +public final class SourceViewDescription implements MultiViewDescription, Serializable { + + private static final long serialVersionUID = -1l; + + private XYZDataObject designDataObject; + + public SourceViewDescription (XYZDataObject designDataObject) { + this.designDataObject = designDataObject; + } + + public int getPersistenceType () { + return TopComponent.PERSISTENCE_ONLY_OPENED; + } + + public String getDisplayName () { + return "Source"; + } + + public Image getIcon () { + return null; + } + + public HelpCtx getHelpCtx () { + return null; + } + + public String preferredID () { + return null; + } + + public MultiViewElement createElement () { + return new SourceViewElement (designDataObject); + } + +} diff -r 687656888bfe core.multiview/test/unit/src/org/netbeans/core/multiview/issue180221/SourceViewElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core.multiview/test/unit/src/org/netbeans/core/multiview/issue180221/SourceViewElement.java Wed Feb 03 20:04:18 2010 +0100 @@ -0,0 +1,163 @@ +package org.netbeans.core.multiview.issue180221; + +import org.netbeans.core.spi.multiview.CloseOperationState; +import org.netbeans.core.spi.multiview.MultiViewElement; +import org.netbeans.core.spi.multiview.MultiViewElementCallback; +import org.netbeans.core.spi.multiview.MultiViewFactory; +import org.openide.awt.UndoRedo; +import org.openide.text.CloneableEditor; +import org.openide.text.NbDocument; +import org.openide.util.Lookup; + +import javax.swing.*; +import javax.swing.text.Document; +import java.io.IOException; +import java.io.Serializable; + +/** + * @author David Kaspar + */ +public final class SourceViewElement implements MultiViewElement, Serializable { + + public static volatile int COUNTER = 0; + + private static final long serialVersionUID = -1; + + static final String CLOSING_ID = "ID_JAVA_CLOSING"; // NOI18N + + private XYZDataObject designDataObject; + private transient DesignCloneableEditor editor; + private transient JComponent toolbar; + private transient MultiViewElementCallback multiViewElementCallback; + + SourceViewElement (XYZDataObject designDataObject) { + COUNTER ++; + this.designDataObject = designDataObject; + init (); + } + + private void init () { + XYZDataEditorSupport editorSupport = designDataObject.getEditorSupport (); + editor = new DesignCloneableEditor (editorSupport); + editorSupport.initializeCloneableEditor (editor); + } + + public JComponent getVisualRepresentation () { + return editor; + } + + public JComponent getToolbarRepresentation () { + if (toolbar == null) { + JEditorPane pane = editor.getEditorPane (); + if (pane != null) { + Document doc = pane.getDocument (); + if (doc instanceof NbDocument.CustomToolbar) + toolbar = ((NbDocument.CustomToolbar) doc).createToolbar (pane); + } + if (toolbar == null) + toolbar = new JPanel (); + } + return toolbar; + } + + public Action[] getActions () { + return editor.getActions (); + } + + public Lookup getLookup () { + return editor.getLookup (); + } + + public void componentOpened () { + editor.componentOpened (); + } + + public void componentClosed () { +// editor.componentClosed (); + } + + public void componentShowing () { + editor.componentShowing (); + } + + public void componentHidden () { + editor.componentOpened (); + } + + public void componentActivated () { + editor.componentActivated (); + } + + public void componentDeactivated () { + editor.componentDeactivated (); + } + + public UndoRedo getUndoRedo () { + return editor.getUndoRedo (); + } + + public void setMultiViewCallback (MultiViewElementCallback multiViewElementCallback) { + this.multiViewElementCallback = multiViewElementCallback; +// designDataObject.getEditorSupport ().setMVTC (multiViewElementCallback.getTopComponent ()); + } + + public CloseOperationState canCloseElement () { + if (! designDataObject.getEditorSupport ().isLastView (multiViewElementCallback.getTopComponent ())) + return CloseOperationState.STATE_OK; + return MultiViewFactory.createUnsafeCloseState(CLOSING_ID, null, null); + } + + private void writeObject (java.io.ObjectOutputStream out) throws IOException { + out.writeObject (designDataObject); + } + + private void readObject (java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + Object object = in.readObject (); + if (! (object instanceof XYZDataObject)) + throw new ClassNotFoundException ("DataObject expected but not found"); // NOI18N + designDataObject = (XYZDataObject) object; + init (); + } + + private static final class DesignCloneableEditor extends CloneableEditor { + + public DesignCloneableEditor () { + } + + public DesignCloneableEditor(XYZDataEditorSupport editorSupport) { + super(editorSupport); + } + + @Override + protected void componentActivated () { + super.componentActivated(); + } + + @Override + protected void componentDeactivated () { + super.componentDeactivated(); + } + + @Override + protected void componentShowing() { + super.componentShowing(); + } + + @Override + protected void componentHidden () { + super.componentHidden (); + } + + @Override + protected void componentOpened() { + super.componentOpened(); + } + + @Override + protected void componentClosed() { + super.componentClosed(); + } + + } + +} diff -r 687656888bfe core.multiview/test/unit/src/org/netbeans/core/multiview/issue180221/XYZDataEditorSupport.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core.multiview/test/unit/src/org/netbeans/core/multiview/issue180221/XYZDataEditorSupport.java Wed Feb 03 20:04:18 2010 +0100 @@ -0,0 +1,155 @@ +package org.netbeans.core.multiview.issue180221; + +import java.io.IOException; +import java.io.Serializable; +import java.util.Enumeration; +import javax.swing.text.Position.Bias; +import org.netbeans.core.api.multiview.MultiViewHandler; +import org.netbeans.core.api.multiview.MultiViewPerspective; +import org.netbeans.core.api.multiview.MultiViews; +import org.netbeans.core.spi.multiview.CloseOperationHandler; +import org.netbeans.core.spi.multiview.CloseOperationState; +import org.netbeans.core.spi.multiview.MultiViewDescription; +import org.netbeans.core.spi.multiview.MultiViewFactory; +import org.openide.cookies.EditCookie; +import org.openide.cookies.EditorCookie; +import org.openide.cookies.OpenCookie; +import org.openide.cookies.PrintCookie; +import org.openide.filesystems.FileLock; +import org.openide.filesystems.FileObject; +import org.openide.text.CloneableEditor; +import org.openide.text.CloneableEditorSupport; +import org.openide.text.DataEditorSupport; +import org.openide.text.PositionRef; +import org.openide.windows.CloneableOpenSupport; +import org.openide.windows.CloneableTopComponent; +import org.openide.windows.TopComponent; + +/** + * @author David Kaspar + */ +public class XYZDataEditorSupport extends DataEditorSupport implements OpenCookie, EditCookie, EditorCookie, PrintCookie, EditorCookie.Observable { + + private final CloseOperationHandler closeHandler; + + private ViewIndex viewIndex = ViewIndex.SOURCE; + + public XYZDataEditorSupport(XYZDataObject dataObject) { + super(dataObject, new Environment (dataObject)); + + closeHandler = new CloseHandler (dataObject); + } + + @Override + public void open() { + viewIndex = ViewIndex.DESIGN; + super.open(); + + showTopComponent (viewIndex); + viewIndex = ViewIndex.SOURCE; + } + + @Override + public void edit() { + viewIndex = ViewIndex.SOURCE; + super.edit(); + + showTopComponent (viewIndex); + } + + public void showTopComponent (ViewIndex tabIndex) { + TopComponent topComponent = allEditors.getArbitraryComponent (); + if (topComponent == null) { + final Enumeration enumeration = allEditors.getComponents (); + while (topComponent == null && enumeration.hasMoreElements ()) + topComponent = enumeration.nextElement (); + } + + if (topComponent != null) { + MultiViewHandler handler = MultiViews.findMultiViewHandler (topComponent); + MultiViewPerspective perspective = handler.getPerspectives ()[tabIndex.ordinal ()]; + handler.requestActive (perspective); + handler.requestVisible (perspective); + } + } + + @Override + public void initializeCloneableEditor (CloneableEditor editor) { + super.initializeCloneableEditor (editor); + } + + @Override + protected Pane createPane() { + MultiViewDescription[] descriptions = new MultiViewDescription[] { + new SourceViewDescription ((XYZDataObject) getDataObject ()), + new DesignViewDescription ((XYZDataObject) getDataObject ()) + }; + return (CloneableEditorSupport.Pane) MultiViewFactory.createCloneableMultiView (descriptions, descriptions[viewIndex.ordinal ()], closeHandler); + } + + public boolean isLastView (TopComponent topComponent) { + final Enumeration enumeration = allEditors.getComponents (); + while (enumeration.hasMoreElements ()) { + TopComponent tc = enumeration.nextElement (); + if (topComponent == tc) + continue; + return false; + } + return true; + } + + public void openAt() { + openAt (createPositionRef(0, Bias.Forward), 0); + } + + private static class CloseHandler implements CloseOperationHandler, Serializable { + + private static final long serialVersionUID = -1; + private XYZDataObject dataObject; + + public CloseHandler (XYZDataObject dataObject) { + this.dataObject = dataObject; + } + + public boolean resolveCloseOperation(CloseOperationState[] elements) { + XYZDataEditorSupport editorSupport = dataObject.getEditorSupport (); + boolean can = editorSupport.canClose(); + if (can) + editorSupport.notifyClosed(); + return can; + } + + } + + private static final class Environment extends Env { + + private static final long serialVersionUID = -1l; + + public Environment (XYZDataObject dataObject) { + super (dataObject); + } + + @Override + protected FileObject getFile () { + return ((XYZDataObject) getDataObject ()).getPrimaryFile (); + } + + @Override + protected FileLock takeLock () throws IOException { + return ((XYZDataObject) getDataObject ()).getPrimaryEntry().takeLock (); + } + + @Override + public CloneableOpenSupport findCloneableOpenSupport() { + return (CloneableEditorSupport) getDataObject().getCookie (EditorCookie.class); + } + + } + + public static enum ViewIndex { + + SOURCE, DESIGN + + } + +} diff -r 687656888bfe core.multiview/test/unit/src/org/netbeans/core/multiview/issue180221/XYZDataObject.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core.multiview/test/unit/src/org/netbeans/core/multiview/issue180221/XYZDataObject.java Wed Feb 03 20:04:18 2010 +0100 @@ -0,0 +1,43 @@ +package org.netbeans.core.multiview.issue180221; + +import java.io.IOException; +import org.openide.filesystems.FileObject; +import org.openide.loaders.DataNode; +import org.openide.loaders.DataObjectExistsException; +import org.openide.loaders.MultiDataObject; +import org.openide.loaders.MultiFileLoader; +import org.openide.nodes.CookieSet; +import org.openide.nodes.Node; +import org.openide.nodes.Children; +import org.openide.nodes.Node.Cookie; +import org.openide.util.Lookup; + +/** + * @author David Kaspar + */ +public class XYZDataObject extends MultiDataObject { + + private final XYZDataEditorSupport editorSupport; + + public XYZDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException { + super(pf, loader); + CookieSet cookies = getCookieSet(); + editorSupport = new XYZDataEditorSupport (this); + cookies.add((Cookie) editorSupport); + } + + @Override + protected Node createNodeDelegate() { + return new DataNode(this, Children.LEAF, getLookup()); + } + + @Override + public Lookup getLookup() { + return getCookieSet().getLookup(); + } + + XYZDataEditorSupport getEditorSupport() { + return editorSupport; + } + +} diff -r 687656888bfe core.multiview/test/unit/src/org/netbeans/core/multiview/issue180221/XYZResolver.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core.multiview/test/unit/src/org/netbeans/core/multiview/issue180221/XYZResolver.xml Wed Feb 03 20:04:18 2010 +0100 @@ -0,0 +1,8 @@ + + + + + + + +