Я открывающимися в TopComponent для DataObject с этим кодом после выполнения действия:Открывая программно TopComponent
TopComponent tc = MultiViews.createMultiView("text/experiment+xml", expDO);
tc.open();
tc.requestActive();
Это работает отлично, но если я дважды щелкните на узле DataObject, новый TopComponent является открыт, хотя TopComponent только открыт для него.
Однако, если я только открываю TopComponet с двойным щелчком, всегда открыт один и единственный TopComponent для DataObject.
Такое поведение наблюдается, когда я открываю TopComponent с кодом выше. Я подозреваю, что TopComponent не зарегистрирован в TopComponent.registry, но я не знаю, как этого добиться.
Любая помощь приветствуется.
Edit: Это реализация DataObject (я избегал аннотаций, которые регистрируют мим-типа и действия пользователя):
public class ExperimentDataObject extends MultiDataObject implements PropertyChangeListener {
private final Logger LOGGER = Logger.getLogger(this.getClass().getName());
private Lookup lookup;
private InstanceContent ic = new InstanceContent();
private final Project project;
private final Experiment experiment;
public ExperimentDataObject(FileObject expFO, MultiFileLoader loader) throws DataObjectExistsException, IOException {
super(expFO, loader);
registerEditor("text/experiment+xml", true);
this.project = FileOwnerQuery.getOwner(expFO);
this.experiment = getObject();
this.experiment.setConfigFile(expFO);
experiment.addPropertyChangeListener(this);
expFO.setAttribute(AwsItem.ITEM_TYPE, AwsItemType.EXPERIMENT);
expFO.setAttribute(AwsItem.PROP_PROJECT, this.project);
LOGGER.trace("ExperimentDataObject " + this.getName() + " created.");
}
@Override
protected int associateLookup() {
return 1;
}
private class MyOpenCookie implements OpenCookie {
public void open(){
TopComponent tc = MultiViews.createMultiView("text/experiment+xml", ExperimentDataObject.this);
tc.open();
tc.requestActive();
}
}
/**
* Lookup implementation.
* @return
*/
@Override
public Lookup getLookup() {
if (lookup == null) {
lookup = new AbstractLookup(ic);
ic.add(this);
ic.add(project);
ic.add(experiment);
ic.add(new MyOpenCookie());
}
LOGGER.trace("ExperimentDO.getLookup() called.");
return lookup;
}
/**
* Creates the ExperimentDataNode for this DataObject
* @return
*/
@Override
protected Node createNodeDelegate() {
return new ExperimentDataNode(this);
}
/**
* Generates the experiment java object.<br>
* It must be created when the DataObject is constructed, in this way, the instance object is in
* the lookup of the DataObject.
*
* @return Experiment instance object
*/
private Experiment getObject() throws IOException {
XStream xstream = new XStream(new PureJavaReflectionProvider());
xstream.processAnnotations(Experiment.class);
return (Experiment) xstream.fromXML(FileUtil.toFile(this.getPrimaryFile()));
}
/**
* Saves the experiment java object to the config FileObject.<br>Doesn't matter if the experiment object has charged dataConfig in its DataItem's, because the object Experiment.ChannelData.dataItems is transient and they are not serialized.
*/
public void saveConfig() throws IOException {
FileLock doFileLock = this.getPrimaryFile().lock();
String xmlStr;
XStream xstream = new XStream(new DomDriver());
xstream.processAnnotations(Experiment.class);
xmlStr = xstream.toXML(experiment);
byte[] bytes = xmlStr.getBytes(Charset.forName("UTF-8"));
OutputStream os = this.getPrimaryFile().getOutputStream(doFileLock);
os.write(bytes);
os.flush();
os.close();
doFileLock.releaseLock();
os = null;
}
/**
* Detects change events in the the AwsItem object.<br>
Свойства изменения могут быть уволены из AwsItem или из объектов ChannelData в AwsItem * * @param ЭВТ */ @Override общественного недействительными propertyChange (PropertyChangeEvent ЭВТ) {
if (evt.getPropertyName() == AwsItem.PROP_CONFIG) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
saveConfig();
} catch (IOException ex) {
LOGGER.warn("Problem saving changes in AwsItem.", ex);
}
}
});
}
}
}
И это код DataNode: общественный класс ExperimentDataNode расширяет DataNode {
public static final String EXPERIMENT_NODE_ICON = "com/aws/experiment/resources/experiment.png";
private final ExperimentDataObject expDO;
private final Logger LOGGER = Logger.getLogger(this.getClass().getName());
public ExperimentDataNode(ExperimentDataObject expDO) {
super(expDO, Children.LEAF);
this.expDO = expDO;
}
@Override
public Action[] getActions(boolean context) {
return new Action[]{
SystemAction.get(OpenAction.class),
SystemAction.get(RenameAction.class),
SystemAction.get(DeleteAction.class),
};
}
public String getHtmlDisplayName() {
String result = this.getDataObject().getName();
if (result != null) return result;
else return "Experiment";
}
@Override
public boolean canRename() {
return true;
}
/**
* Renames the DataNode and the DataObject.<br>
* Also renames the object Experiment that DataObject represents.
* @param name
* @param renameDO
*/
@Override
public void setName(String name, boolean renameDO) {
super.setName(name, true);
Experiment exp = this.expDO.getLookup().lookup(Experiment.class);
exp.setName(name);
}
@Override
public boolean canDestroy() {
return true;
}
/**
* Deletes the DataObject and the data file associated to it.
* @throws IOException
*/
@Override
public void destroy() throws IOException {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Mode editorMode = WindowManager.getDefault().findMode("editor");
TopComponent[] openTopComponentsInEditorMode = editorMode.getTopComponents();
for (TopComponent tc : openTopComponentsInEditorMode) {
if (tc.getLookup().lookup(DataObject.class) == expDO) {
tc.close();
}
}
try {
Experiment experiment = expDO.getLookup().lookup(Experiment.class);
experiment.deleteChannelData();
expDO.delete();
fireNodeDestroyed();
} catch (IOException ex) {
LOGGER.warn("Problem deleting item experiment.", ex);
}
}
});
}
}
Не создавайте свой собственный мульти-вид, но вместо того, чтобы иметь OpenCookie в DataObject Открывает TopComponent для вас. Это то, что выполняется при двойном щелчке по DataNode. – sproger
См .: http://wiki.netbeans.org/DevFaqDataObject – sproger
Но этот метод подразумевает реализацию в DataObject некоторого интерфейса или абстрактного класса, такого как OpenSupport или OpenCookie, не так ли? На самом деле мой класс DataObject расширяет MultiDataObject, и мне не нужно ничего внедрять, чтобы открывать поддержку для открытия при двойном щелчке.Если я сделаю то, что вы предлагаете, мне нужно будет реализовать метод open(). Как я могу разместить абстрактный OpenCookie или OpenSupport? – pacobm