The question of the day comes from Vadim, who asks on the NetBeans Platform mailing list: "Looking for example showing how to add Widget to Scene, e.g. by toolbar button click."
Well, the solution is very similar to this blog entry, where you see a solution provided by Jesse Glick for VisiTrend in Boston: https://blogs.oracle.com/geertjan/entry/zoom_capability
Other relevant articles to read are as follows:
http://netbeans.dzone.com/news/which-netbeans-platform-action
http://netbeans.dzone.com/how-to-make-context-sensitive-actions
Let's go through it step by step, with this result in the end, a solution involving 4 classes split (optionally, since a central feature of the NetBeans Platform is modularity) across multiple modules:
The Customer object has a "name" String and the Droppable capability has a method "doDrop" which takes a Customer object:
public interface Droppable { void doDrop(Customer c);}
In the TopComponent, we use "TopComponent.associateLookup" to publish an instance of "Droppable", which creates a new LabelWidget and adds it to the Scene in the TopComponent. Here's the TopComponent constructor:
public CustomerCanvasTopComponent() { initComponents(); setName(Bundle.CTL_CustomerCanvasTopComponent()); setToolTipText(Bundle.HINT_CustomerCanvasTopComponent()); final Scene scene = new Scene(); final LayerWidget layerWidget = new LayerWidget(scene); Droppable d = new Droppable(){ @Override public void doDrop(Customer c) { LabelWidget customerWidget = new LabelWidget(scene, c.getTitle()); customerWidget.getActions().addAction(ActionFactory.createMoveAction()); layerWidget.addChild(customerWidget); scene.validate(); } }; scene.addChild(layerWidget); jScrollPane1.setViewportView(scene.createView()); associateLookup(Lookups.singleton(d));}
The Action is displayed in the toolbar and is enabled only if a Droppable is currently in the Lookup:
@ActionID( category = "Tools", id = "org.customer.controler.AddCustomerAction")@ActionRegistration( iconBase = "org/customer/controler/icon.png", displayName = "#AddCustomerAction")@ActionReferences({ @ActionReference(path = "Toolbars/File", position = 300)})@NbBundle.Messages("AddCustomerAction=Add Customer")public final class AddCustomerAction implements ActionListener { private final Droppable context; public AddCustomerAction(Droppable droppable) { this.context = droppable; } @Override public void actionPerformed(ActionEvent ev) { NotifyDescriptor.InputLine inputLine = new NotifyDescriptor.InputLine("Name:", "Data Entry"); Object result = DialogDisplayer.getDefault().notify(inputLine); if (result == NotifyDescriptor.OK_OPTION) { Customer customer = new Customer(inputLine.getInputText()); context.doDrop(customer); } }}
Therefore, when the Properties window, for example, is selected, the Action will be disabled. (See the Zoomable example referred to in the link above for another example of this.) As you can see above, when the Action is invoked, a Droppable must be available (otherwise the Action would not have been enabled). The Droppable is obtained in the Action and a new Customer object is passed to its "doDrop" method.
The above in pictures, take note of the enablement of the toolbar button with the red dot, on the extreme left of the toolbar in the screenshots below:
The above shows the JButton is only enabled if the relevant TopComponent is active and, when the Action is invoked, the user can enter a name, after which a new LabelWidget is created in the Scene.
The source code of the above is here:
http://java.net/projects/nb-api-samples/sources/api-samples/show/versions/7.3/misc/WidgetCreationFromAction
Note: Showing this as an MVC example is slightly misleading because, depending on which model object ("Customer" and "Droppable") you're looking at, the V and the C are different. From the point of view of "Customer", the TopComponent is the View, while the Action is the Controler, since it determines when the M is displayed. However, from the point of view of "Droppable", the TopComponent is the Controler, since it determines when the Action, i.e., which is in this case the View, displays the presence of the M.