问题
I am creating a custom toolbar for my RCP application.
As shown in figure I want to have a drop down box with three other text boxes. These are basically the input box and are interdependent. Right now each of these boxes are in separate classes. I want to bring them together in one class so it is easier to create listeners for each other.
protected void fillCoolBar(ICoolBarManager coolBar) { IToolBarManager toolbar = new ToolBarManager(coolBar.getStyle()); coolBar.add(toolbar); Toolbar extraToolBar = new Toolbar("Toolbar"); toolbar.add(extraToolBar); toolbar.add(new Separator()); toolbar.add(new MyCombo("Demo Combo box")); toolbar.add(new Separator()); toolbar.add(new IPaddress("Ip")); toolbar.add(new Separator()); toolbar.add(new Mask("Mask")); toolbar.add(new Separator()); toolbar.add(new Count("Count")); } public class IPaddress extends ControlContribution { Text textBox; public IPaddress(String id) { super(id); // TODO Auto-generated constructor stub } @Override protected Control createControl(Composite parent) { textBox = new Text(parent, SWT.MULTI | SWT.BORDER | SWT.WRAP); textBox.setLayoutData(new GridData(GridData.FILL_BOTH)); textBox.addModifyListener(new ModifyListener(){ public void modifyText(ModifyEvent event) { Text text = (Text) event.widget; System.out.println(text.getText()); } }); return textBox; } }
Thus I want to create a new custom Toolbar will all the functionalities that I want and then stick it to the original. But somehow it only shows an empty bar on the left.
protected Control createControl(Composite parent) { toolBar = new ToolBar(parent, SWT.FLAT |SWT.BORDER); Device dev = toolBar.getDisplay(); try { newi = new Image(dev, "C:\\Users\\RahmanAs\\ChipcoachWorkspace\\ChipCoach\\icons\\FileClose.png"); opei = new Image(dev, "C:\\Users\\RahmanAs\\ChipcoachWorkspace\\ChipCoach\\icons\\FileOpen.png"); } catch (Exception e) { System.out.println("Cannot load images"); System.out.println(e.getMessage()); System.exit(1); } ToolItem item0 = new ToolItem (toolBar, SWT.PUSH); item0.setImage(newi); item0.setText("Hello"); ToolItem item1 = new ToolItem(toolBar, SWT.PUSH); item1.setText("Push"); ToolItem item2 = new ToolItem(toolBar, SWT.PUSH); item2.setText("Pull"); return toolBar; }
I also have run buttons, which I created in the plugin using Vogella's tutorial. But I cannot program their placements in this way. (For example if I want them in the beginning.) Is there a way to create them programmatically?
回答1:
I think the reason your leftmost ToolBar
is empty is a layout issue. In my code below, I had a similar "empty" ToolBar
problem when I did not have any buttons located outside the custom ToolBar
but still in the main ToolBar
. Adding in the "foo" and "bar" buttons fixed the layout issue, but I could not figure out the right calls to layout()
or pack()
to fix it. I think this may be related to the bug here.
I took a swing at creating a similar ToolBar
and built around the "RCP Mail Template" plugin-project that you can create from the "New Plug-in Project" wizard.
To address your first two concerns, I created 3 packages in the example RCP bundle (I called my project "com.bar.foo"):
- com.bar.foo.actions - Contains classes that extend
ContributionControl
and wrapCombo
andText
widgets. These have nothing to do with the data model and just worry about creating widgets. - com.bar.foo.model - Contains the data model. I just made up a simple model here with an IP, mask, gateway, and one or two helpful methods.
- com.bar.foo.toolBar - These classes are plugged up to the main UI
ToolBar
via theorg.eclipse.ui.menus
extension point. They link the data model to theContributionControls
in the first package. The most important class here isToolBarContribution
, which effectively centralizes all of your listeners. This makes it easier for you to link the listeners for the widgets to the same model.
Here's the source for the ToolBarContribution
(note that it addresses your first two concerns because it hooks up the listeners to the model and provides its own ToolBar
to the UI):
package com.bar.foo.toolBar;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.ui.menus.WorkbenchWindowControlContribution;
import com.bar.foo.actions.ComboContributionItem;
import com.bar.foo.actions.TextContributionItem;
import com.bar.foo.model.NetworkConfig;
public class ToolBarContribution extends WorkbenchWindowControlContribution {
// Our data model.
private NetworkConfig configuration = new NetworkConfig();
// Each of these corresponds to a widget in the ToolBar.
private Action scanAction;
private ComboContributionItem sourceCombo;
private TextContributionItem ipText;
private TextContributionItem maskText;
private TextContributionItem gatewayText;
@Override
protected Control createControl(Composite parent) {
setupContributionItems();
// Let's not get our hands messy with SWT... add IActions or
// IContributionItems to a ToolBarManager and let the ToolBarManager
// create the SWT ToolBar.
ToolBarManager manager = new ToolBarManager();
manager.add(scanAction);
manager.add(sourceCombo);
manager.add(ipText);
manager.add(maskText);
manager.add(gatewayText);
ToolBar toolBar = manager.createControl(parent);
// Highlight the ToolBar in red.
toolBar.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_RED));
return toolBar;
}
private void setupContributionItems() {
scanAction = new Action("Scan Host") {
@Override
public void run() {
System.out.println("Scanning...");
String host = sourceCombo.getComboControl().getText();
configuration.scanHost(host);
System.out.println("Scanned!");
refreshTexts();
}
};
scanAction.setToolTipText("Scans the host for a configuration.");
final SelectionListener comboListener = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
ipText.getTextControl().setText("");
maskText.getTextControl().setText("");
gatewayText.getTextControl().setText("");
}
};
sourceCombo = new ComboContributionItem("sourceCombo") {
@Override
public Control createControl(Composite parent) {
// Let ComboContributionItem create the initial control.
Control control = super.createControl(parent);
// Now customize the Combo widget.
Combo combo = getComboControl();
combo.setItems(configuration.getAvailableHosts());
combo.addSelectionListener(comboListener);
// Return the default control.
return control;
}
};
ipText = new TextContributionItem("ipText", SWT.BORDER | SWT.SINGLE
| SWT.READ_ONLY);
maskText = new TextContributionItem("maskText");
gatewayText = new TextContributionItem("gatewayText");
}
private void refreshTexts() {
ipText.getTextControl().setText(configuration.getIP());
maskText.getTextControl().setText(configuration.getMask());
gatewayText.getTextControl().setText(configuration.getGateway());
}
}
In addition to this ToolBar
, I have two separate buttons in the main UI ToolBar
, one before, and one after the custom ToolBar
. Their sources are in the package com.bar.foo.toolBar. Here is the first command:
package com.bar.foo.toolBar;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
public class FooHandler extends AbstractHandler {
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
System.out.println("foo");
return null;
}
}
And here is the second one:
package com.bar.foo.toolBar;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
public class BarHandler extends AbstractHandler {
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
System.out.println("bar");
return null;
}
}
Since I didn't know too much about your data, I had to create my own model. The model in the package com.bar.foo.model is just one class:
package com.bar.foo.model;
public class NetworkConfig {
private String ip = "";
private String mask = "";
private String gateway = "";
public String[] getAvailableHosts() {
return new String[] { "fooHost" };
}
public void scanHost(String host) {
if ("fooHost".equals(host)) {
ip = "192.168.1.2";
mask = "255.255.255.0";
gateway = "192.168.1.1";
} else {
ip = "";
mask = "";
gateway = "";
}
}
public String getIP() {
return ip;
}
public String getMask() {
return mask;
}
public String getGateway() {
return gateway;
}
}
Now for the com.bar.foo.actions package that contains the ControlContributions
that go in the custom ToolBar
. Note that neither of these two classes have anything to do with the model, and they can be re-used elsewhere in your product.
The first class just wraps a Combo
widget. The widget can be initially customized by overriding the controlCreated(Combo)
method. I use that in the ToolBarContribution
class to add a SelectionListener
and set the Combo
's items. Here's the class:
package com.bar.foo.actions;
import org.eclipse.jface.action.ControlContribution;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
public class ComboContributionItem extends ControlContribution {
private Combo combo;
public ComboContributionItem(String id) {
super(id);
}
@Override
protected Control createControl(Composite parent) {
combo = new Combo(parent, SWT.READ_ONLY | SWT.V_SCROLL | SWT.H_SCROLL);
return combo;
}
@Override
public int computeWidth(Control control) {
// The widget is now 100 pixels. You can new GC gc = new GC(control) and
// use the gc.stringExtent(String) method to help compute a more dynamic
// width.
return 100;
}
public Combo getComboControl() {
return combo;
}
}
The other class in this package wraps a Text
widget:
package com.bar.foo.actions;
import org.eclipse.jface.action.ControlContribution;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Text;
public class TextContributionItem extends ControlContribution {
private final int style;
private Text text;
public TextContributionItem(String id) {
this(id, SWT.BORDER | SWT.SINGLE);
}
public TextContributionItem(String id, int style) {
super(id);
this.style = style;
}
@Override
protected Control createControl(Composite parent) {
text = new Text(parent, style);
return text;
}
@Override
public int computeWidth(Control control) {
return 100;
}
public Text getTextControl() {
return text;
}
}
I didn't do this, but if you need to further customize the Text
widget for your ToolBar
, you can override the createControl(Composite)
method just like I did when initializing the ComboContributionItem
.
Now one last thing: I used extensions to customize the ToolBar
. However, the same logic used by ToolBarContribution
applies to your fillCoolBar(ICoolBarManager)
method or your createControl(Composite)
method, depending on which ToolBar
you ultimately wish to modify.
In my case, here's what I added to the end of the plugin's plugin.xml
:
<extension
point="org.eclipse.ui.menus">
<menuContribution
locationURI="toolbar:org.eclipse.ui.main.toolbar">
<toolbar
id="com.bar.foo.toolbar">
<command
commandId="com.bar.foo.commands.foo"
label="Foo"
style="push">
</command>
<control
class="com.bar.foo.toolBar.ToolBarContribution">
</control>
<command
commandId="com.bar.foo.commands.bar"
label="Bar"
style="push">
</command>
</toolbar>
</menuContribution>
</extension>
<extension
point="org.eclipse.ui.commands">
<command
id="com.bar.foo.commands.foo"
name="Foo">
</command>
<command
id="com.bar.foo.commands.bar"
name="Bar">
</command>
</extension>
<extension
point="org.eclipse.ui.handlers">
<handler
class="com.bar.foo.toolBar.FooHandler"
commandId="com.bar.foo.commands.foo">
</handler>
<handler
class="com.bar.foo.toolBar.BarHandler"
commandId="com.bar.foo.commands.bar">
</handler>
</extension>
The commands are hooked up so that there's a button for FooHandler
before the custom ToolBar
and a button for BarHandler
after the custom ToolBar
. The order in which these commands are specified in the xml will be reflected in the application. Likewise, the order in which the items are added to the custom ToolBar
will reflect in your product.
Another note on placement: You can make the menuContributions appear in different places by setting a placement in the locationURI's query, e.g., toolbar:org.eclipse.ui.main.toolbar?after=additions
. "before" is another placement keyword like "after". More examples of this can be found in this Eclipse help doc.
来源:https://stackoverflow.com/questions/26097895/eclipse-rcp-application-custom-toolbar