Branding Support for TopComponents
Posted
by Geertjan
on Oracle Blogs
See other posts from Oracle Blogs
or by Geertjan
Published on Fri, 22 Jun 2012 09:35:48 +0000
Indexed on
2012/06/23
15:20 UTC
Read the original article
Hit count: 180
/NetBeans IDE
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; } }
© Oracle Blogs or respective owner