Creating MultiViewElements on the Fly

Following from the above, here's how to add a new tab in the Java Editor, on the fly (as described here, possible from 8.0 onwards), i.e., when the "Design Custom Component" menu item (which is only available when you right-click a subclass of com.vaadin.ui.CustomComponent, as described yesterday) is clicked:

@Override
public void actionPerformed(ActionEvent ev) {
    dobj.getLookup().lookup(Openable.class).open();
    TopComponent activated = WindowManager.getDefault().getRegistry().getActivated();
    MultiViewHandler mvh = MultiViews.findMultiViewHandler(activated);
    mvh.addMultiViewDescription(new DesignerMVD(), 1);
}

In short, the above gets you this:


DesignerMVD, referenced above, is as follows:

import java.awt.Image;
import org.netbeans.core.spi.multiview.MultiViewDescription;
import org.netbeans.core.spi.multiview.MultiViewElement;
import org.openide.util.HelpCtx;
import org.openide.util.Utilities;
import org.openide.windows.TopComponent;

public class DesignerMVD implements MultiViewDescription {
    @Override
    public int getPersistenceType() {
        return TopComponent.PERSISTENCE_NEVER;
    }
    @Override
    public String getDisplayName() {
        return "Designer";
    }
    @Override
    public Image getIcon() {
        return null;
    }
    @Override
    public HelpCtx getHelpCtx() {
        return HelpCtx.DEFAULT_HELP;
    }
    @Override
    public String preferredID() {
        return "Designer";
    }
    @Override
    public MultiViewElement createElement() {
        return new DesignMVE(Utilities.actionsGlobalContext());
    }
}
 

And DesignerMVE is like this, i.e., a JPanel, which will later contain a Visual Library Scene that visualizes the content of the CustomComponent in some way, so that it can be graphically edited:

import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import org.netbeans.core.spi.multiview.CloseOperationState;
import org.netbeans.core.spi.multiview.MultiViewElement;
import org.netbeans.core.spi.multiview.MultiViewElementCallback;
import org.openide.awt.UndoRedo;
import org.openide.loaders.DataObject;
import org.openide.util.Lookup;

public class DesignMVE extends JPanel implements MultiViewElement {
    private JToolBar toolbar = new JToolBar();
    private DataObject obj;
    public DesignMVE(Lookup lkp) {
        obj = lkp.lookup(DataObject.class);
        assert obj != null;
    }
    @Override
    public JComponent getVisualRepresentation() {
        return this;
    }
    @Override
    public JComponent getToolbarRepresentation() {
        toolbar.setFloatable(false);
        return toolbar;
    }
    @Override
    public Action[] getActions() {
        return new Action[0];
    }
    @Override
    public Lookup getLookup() {
        return obj.getLookup();
    }
    @Override public void componentOpened() {}
    @Override public void componentClosed() {}
    @Override public void componentShowing() {}
    @Override public void componentHidden() {}
    @Override public void componentActivated() {}
    @Override public void componentDeactivated() {}
    @Override
    public UndoRedo getUndoRedo() {
        return UndoRedo.NONE;
    }
    private transient MultiViewElementCallback callback;
    @Override
    public void setMultiViewCallback(MultiViewElementCallback mvec) {
        this.callback = mvec;
    }
    @Override
    public CloseOperationState canCloseElement() {
        return CloseOperationState.STATE_OK;
    }
}
 

Finally, the action for opening the DesignerMVD is slightly more complex because we don't want a new DesignerMVD whenever the Action is invoked. Specifically, we do not want a new DesignerMVD if the file is already open, since then a new DesignerMVD will already have been created. Hence (thanks to instructions here), we get this:

@Override
public void actionPerformed(ActionEvent ev) {
    //Need to make sure to add a designer
    //only if the file hasn't been opened yet,
    //otherwise we'll get a new designer
    //whenever the action is invoked:
    FileObject fileObject = dobj.getPrimaryFile();
    JavaSource javaSource = JavaSource.forFileObject(fileObject);
    if (javaSource != null) {
        try {
            javaSource.runUserActionTask(new Task<CompilationController>() {
                @Override
                public void run(CompilationController compilationController) throws Exception {
                    compilationController.toPhase(Phase.ELEMENTS_RESOLVED);
                    Document document = compilationController.getDocument();
                    if (document == null) {
                        dobj.getLookup().lookup(Openable.class).open();
                        TopComponent activated = WindowManager.getDefault().getRegistry().getActivated();
                        MultiViewHandler mvh = MultiViews.findMultiViewHandler(activated);
                        mvh.addMultiViewDescription(new DesignerMVD(), 1);
                    }
                }
            }, true);
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }
    }
}
 

A different approach might be to disable the Action when the file has been opened, so that it cannot be invoked again while the file is open, which means the above code would not be needed anymore.

The next step is to work on the Visual Library Scene, which will be contained within the JPanel above, together with a Palette (as described here) that contains all the relevant Vaadin components.

And then we'll have a Visual Designer for Vaadin!

Comments:

Post a Comment:
  • HTML Syntax: NOT allowed
About

Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.

Search

Archives
« September 2015
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today