Я хотел бы использовать функцию launcher.openfile в eclipse. Поэтому я прочитал несколько документов (например, https://help.eclipse.org/2020-03/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Fguide%2Fproduct_open_file.htm). Я правильно реализовал настраиваемый класс Application, но в содержимом этого класса что-то не хватает, я думаю, потому что в моем классе LifeCycle главное окно больше не может быть найдено, который обычно можно найти, когда я использую стандартное приложение E4Application.
Как я могу использовать общие функции класса E4Application, добавляя только SWT Listener SWT.OpenDocument.
Здесь мой код приложения:
package de.port.dsntool.ui.services;
import org.eclipse.core.runtime.IProduct;
import org.eclipse.core.runtime.Platform;
import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
public class MyE4Application implements IApplication{
//Application with Listener to SWT.OpenDocument
private Display display = null;
public Display getApplicationDisplay() {
if (display == null) {
display = Display.getDefault();
}
return display;
}
@Override
public Object start(IApplicationContext context) throws Exception {
System.out.println("START My Application");
OpenDocumentEventProcessor openDocProcessor =
new OpenDocumentEventProcessor();
IProduct product = Platform.getProduct();
if (product != null && product.getName() != null) {
Display.setAppName(product.getName());
}
Display display = getApplicationDisplay();
display.addListener(SWT.OpenDocument, openDocProcessor);
try {
int returnCode = PlatformUI.createAndRunWorkbench(display, new
ApplicationWorkbenchAdvisor(openDocProcessor));
if (returnCode == PlatformUI.RETURN_RESTART) {
return IApplication.EXIT_RESTART;
}
return IApplication.EXIT_OK;
} finally {
if (display != null)
display.dispose();
}
}
@Override
public void stop() {
// TODO Auto-generated method stub
}
}
ApplicationWorkbenchAdvisor. java:
package my.package;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.application.WorkbenchAdvisor;
public class ApplicationWorkbenchAdvisor extends WorkbenchAdvisor {
private OpenDocumentEventProcessor openDocProcessor;
public ApplicationWorkbenchAdvisor(
OpenDocumentEventProcessor openDocProcessor) {
this.openDocProcessor = openDocProcessor;
}
@Override
public void eventLoopIdle(Display display) {
openDocProcessor.openFiles();
super.eventLoopIdle(display);
}
@Override
public String getInitialWindowPerspectiveId() {
// TODO Auto-generated method stub
return null;
}
}
OpenDocumentEventProcessor. java:
package my.package;
import java.util.ArrayList;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
public class OpenDocumentEventProcessor implements Listener {
private ArrayList<String> filesToOpen = new ArrayList<String>(1);
@Override
public void handleEvent(Event event) {
if (event.text != null)
filesToOpen.add(event.text);
}
public void openFiles() {
if (filesToOpen.isEmpty())
return;
String[] filePaths = filesToOpen.toArray(
new String[filesToOpen.size()]);
filesToOpen.clear();
for (String path : filePaths) {
// open the file path
}
}
}
LifeCycle. java Фрагмент ProcessAdditions:
/**
* Method to be invoked on ProcessAdditions life-cycle moment.
*
* @param context Eclipse context.
*/
@ProcessAdditions
public void processAdditons(MApplication app, EModelService modelService,
final IEclipseContext context,
final IBrandingInfo branding) {
/*obtain logger from context and publish it
* to objects that require it*/
final Logger logger = context.get(Logger.class);
if (logger != null) {
ProblemRegistry.INSTANCE.setLogger(logger);
}
/*obtain extension registry from context and publish
* it to objects that require it*/
final IExtensionRegistry registry = context
.get(IExtensionRegistry.class);
if (registry != null) {
ProjectRegistry.INSTANCE.setExtensionRegistry(registry);
}
/* Push help service into context. */
context.set(HelpService.class, new HelpServiceImpl(registry));
MWindow window = (MWindow)modelService.find("my.package2.app.trimmedwindow.0", app);
System.out.println("app: " + app);
System.out.println("modelService: " + modelService);
System.out.println("window: " + window);
//ERROR: window is null here which is normally not when using standard E4Application
window.setLabel(branding.getWindowTitle());
...
}
EDIT
Я реализовал ваше решение @ greg-449 с помощью функции PostContextCreate в моем жизненном цикле и EventloopAdvisor. Но я обнаружил странную ошибку: это решение работает ТОЛЬКО при открытии диалогового окна до или после реализации слушателя в PostContextCreate:
Это мой настоящий фрагмент кода из моего жизненного цикла:
@PostContextCreate
public void postContextCreate(final IEclipseContext context) {
final Shell shell = new Shell(Display.getCurrent());
new LicenseAgreementDialog(shell).open();
if(!shell.isDisposed())
shell.dispose();
OpenDocumentEventProcessor openDocProcessor = new OpenDocumentEventProcessor();
Display display = Display.getCurrent();
display.addListener(SWT.OpenDocument, openDocProcessor);
IEventLoopAdvisor eventLoopAdvisor = new EventLoopAdvisor(openDocProcessor);
context.set(IEventLoopAdvisor.class, eventLoopAdvisor);
}
Класс LicenseAgreementDialog
открывает диалоговое окно только один раз перед запуском приложения RCP (открывается во время загрузки экрана-заставки), а после запуска приложения событие SWT.OpenDocument должным образом запускается другими файлами проекта с двойным щелчком. Но когда я закрываю приложение rcp и снова запускаю его, LicenseAgreementDialog
снова не открывается правильно, а затем больше нет событий SWT.OpenDocument, которые запускаются. Я протестировал эту ошибку и пришел к решению, что мне всегда нужно открывать диалог в @PostContextCreateFunction
, иначе событие SWT.OpenDocument не запускается. Я тестировал его также с обычным MessageDialog
(-> MessageDialog.openInformation(new Shell(Display.getCurrent()), "Opening", "Now");
) вместо LicenseAgreementDialog
, который открывается каждый раз при запуске, который работает, но без какого-либо диалога, прежде чем он не будет.
Есть ли есть ли шанс избежать открытия фиктивного диалога для запуска события?
ОКОНЧАТЕЛЬНОЕ редактирование
После множества проб и ошибок я наконец нашел приемлемое решение, чтобы избежать этот фиктивный диалог в начале: я использовал подсказку с добавлением al oop readAndDispatch до его false, но только этот l oop не имеет значения. Мне пришлось добавить второй l oop, который ждет, пока readAndDispatch вернет true. Я тестировал два цикла в разном порядке и так далее, но это единственное рабочее решение:
@PostContextCreate
public void postContextCreate(final IEclipseContext context,
final IEventBroker eventBroker) {
final Shell shell = new Shell(Display.getCurrent());
new LicenseAgreementDialog(shell).open();
/*check for clicked project file or only launcher.exe
* when only launcher.exe is clicked there are no cmd arguments
* when project file is double clicked and gets opened by file handler
* the one and only cmd arg is the filepath from the clicked project file */
if(Platform.getCommandLineArgs().length != 0) {
while(Display.getCurrent().readAndDispatch()) { /* wait for false */ }
while(!Display.getCurrent().readAndDispatch()) { /* wait for true */ }
}
if(!shell.isDisposed())
shell.dispose();
OpenDocumentEventProcessor openDocProcessor = new OpenDocumentEventProcessor(eventBroker);
Display display = Display.getCurrent();
display.addListener(SWT.OpenDocument, openDocProcessor);
IEventLoopAdvisor eventLoopAdvisor = new EventLoopAdvisor(openDocProcessor);
context.set(IEventLoopAdvisor.class, eventLoopAdvisor);
}
С этими двумя циклами событие SWT.OpenDocument всегда запускается правильно, даже если я этого не сделаю. показывать диалог раньше. Спасибо за помощь @ greg-449.
И вот небольшая подсказка, которую я уже имел: файл .ini должен иметь атрибут -name, который должен соответствовать метке главного окна автономного приложения RCP, когда вы используйте функцию openfile с событием SWT.OpenDocument (для меня я использую название продукта в качестве метки окна):
, когда метка вашего главного окна, например: My Rcp App
тогда ваш файл launcher.ini должен иметь свойство -name с той же строкой:
--launcher.defaultAction
openFile
-name
My Rcp App
или вы используете переменную для имени продукта вашего приложения rcp:
--launcher.defaultAction
openFile
-name
%product.name