Friday, June 22, 2012

Branding Support for TopComponents

By: Geertjan Wielenga | Product Manager

In yesterday's blog entry, you saw how a menu item can be created, in this case with the label "Brand", especially for Java classes that extend TopComponent:

And, as you can see here, it's not about the name of the class, i.e., not because the class above is named "BlaTopComponent" because below the "Brand" men item is also available for the class named "Bla":

Both the files BlaTopComponent.java and Bla.java have the "Brand" menu item available, because both extend the "org.openide.windows.TopComponent"  class, as shown yesterday.

Now we continue by creating a new JPanel, with checkboxes for each part of a TopComponent that we consider to be brandable. In my case, this is the end result, at deployment, when the Brand menu item is clicked for the Bla class:


When the user (who, in this case, is a developer) clicks OK, a constructor is created and the related client properties are added, depending on which of the checkboxes are clicked:

public Bla() {
    putClientProperty(TopComponent.PROP_SLIDING_DISABLED, false);
    putClientProperty(TopComponent.PROP_UNDOCKING_DISABLED, true);
    putClientProperty(TopComponent.PROP_MAXIMIZATION_DISABLED, false);
    putClientProperty(TopComponent.PROP_CLOSING_DISABLED, true);
    putClientProperty(TopComponent.PROP_DRAGGING_DISABLED, false);
}

At this point, no check is done to see whether a constructor already exists, nor whether the client properties are already available. That's for an upcoming blog entry! Right now, the constructor is always created, regardless of whether it already exists, and the client properties are always added.

The key to all this is the 'actionPeformed' of the TopComponent, which was left empty yesterday. We start by creating a JDialog from the JPanel and we retrieve the selected state of the checkboxes defined in the JPanel:

@Override
public void actionPerformed(ActionEvent ev) {
    String msg = dobj.getName() + " Branding";
    final BrandTopComponentPanel brandTopComponentPanel = new BrandTopComponentPanel();
    dd = new DialogDescriptor(brandTopComponentPanel, msg, true, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            Object result = dd.getValue();
            if (DialogDescriptor.OK_OPTION == result) {
                isClosing = brandTopComponentPanel.getClosingCheckBox().isSelected();
                isDragging = brandTopComponentPanel.getDraggingCheckBox().isSelected();
                isMaximization = brandTopComponentPanel.getMaximizationCheckBox().isSelected();
                isSliding = brandTopComponentPanel.getSlidingCheckBox().isSelected();
                isUndocking = brandTopComponentPanel.getUndockingCheckBox().isSelected();
                JavaSource javaSource = JavaSource.forFileObject(dobj.getPrimaryFile());
                try {
                    javaSource.runUserActionTask(new ScanTask(javaSource), true);
                } catch (IOException ex) {
                    Exceptions.printStackTrace(ex);
                }
            }
        }
    });
    DialogDisplayer.getDefault().createDialog(dd).setVisible(true);
}

Then we start a scan process, which introduces the branding. We're already doing a scan process for identifying whether a class is a TopComponent. So, let's combine those two scans, branching out based on which one we're doing:

private class ScanTask implements Task<CompilationController> {
    private BrandTopComponentAction action = null;
    private JavaSource js = null;
    private ScanTask(JavaSource js) {
        this.js = js;
    }
    private ScanTask(BrandTopComponentAction action) {
        this.action = action;
    }
    @Override
    public void run(final CompilationController info) throws Exception {
        info.toPhase(Phase.ELEMENTS_RESOLVED);
        if (action != null) {
            new EnableIfTopComponentScanner(info, action).scan(
                    info.getCompilationUnit(), null);
        } else {
            introduceBranding();
        }
    }
    private void introduceBranding() throws IOException {
        CancellableTask task = new CancellableTask<WorkingCopy>() {
            @Override
            public void run(WorkingCopy workingCopy) throws IOException {
                workingCopy.toPhase(Phase.RESOLVED);
                CompilationUnitTree cut = workingCopy.getCompilationUnit();
                TreeMaker treeMaker = workingCopy.getTreeMaker();
                for (Tree typeDecl : cut.getTypeDecls()) {
                    if (Tree.Kind.CLASS == typeDecl.getKind()) {
                        ClassTree clazz = (ClassTree) typeDecl;
                        ModifiersTree methodModifiers = treeMaker.Modifiers(Collections.<Modifier>singleton(Modifier.PUBLIC));
                        MethodTree newMethod =
                                treeMaker.Method(methodModifiers,
                                "<init>",
                                treeMaker.PrimitiveType(TypeKind.VOID),
                                Collections.<TypeParameterTree>emptyList(),
                                Collections.EMPTY_LIST,
                                Collections.<ExpressionTree>emptyList(),
                                "{ putClientProperty(TopComponent.PROP_SLIDING_DISABLED, " + isSliding + ");\n"+
                                "  putClientProperty(TopComponent.PROP_UNDOCKING_DISABLED, " + isUndocking + ");\n"+
                                "  putClientProperty(TopComponent.PROP_MAXIMIZATION_DISABLED, " + isMaximization + ");\n"+
                                "  putClientProperty(TopComponent.PROP_CLOSING_DISABLED, " + isClosing + ");\n"+
                                "  putClientProperty(TopComponent.PROP_DRAGGING_DISABLED, " + isDragging + "); }\n",
                                null);
                        ClassTree modifiedClazz = treeMaker.addClassMember(clazz, newMethod);
                        workingCopy.rewrite(clazz, modifiedClazz);
                    }
                }
            }
            @Override
            public void cancel() {
            }
        };
        ModificationResult result = js.runModificationTask(task);
        result.commit();
    }
}
private static class EnableIfTopComponentScanner extends TreePathScanner<Void, Void> {
    private CompilationInfo info;
    private final AbstractAction action;
    public EnableIfTopComponentScanner(CompilationInfo info, AbstractAction action) {
        this.info = info;
        this.action = action;
    }
    @Override
    public Void visitClass(ClassTree t, Void v) {
        Element el = info.getTrees().getElement(getCurrentPath());
        if (el != null) {
            TypeElement te = (TypeElement) el;
            if (te.getSuperclass().toString().equals("org.openide.windows.TopComponent")) {
                action.setEnabled(true);
            } else {
                action.setEnabled(false);
            }
        }
        return null;
    }
}

Join the discussion

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha
 

Visit the Oracle Blog

 

Contact Us

Oracle

Integrated Cloud Applications & Platform Services