|
Re: Presenting an MPart in a dialog [message #1727161 is a reply to message #1726484] |
Sun, 20 March 2016 14:48 |
Peter Kullmann Messages: 240 Registered: July 2009 |
Senior Member |
|
|
I found a way to do this. It's not so elegant but at least it works and I can re-use most of my dialogs in e4 with little changes. The idea is to use a MDialog model element to represent the dialog and use a special renderer for this. The renderer doesn't do a lot because the dialog was created before the renderer is called. The main pieces are the following:
First, the jface dialog:
@Override
protected Control createDialogArea(Composite parent) {
Composite comp = (Composite) super.createDialogArea(parent);
Composite partHolder = new Composite(comp, SWT.NONE);
GridDataFactory.fillDefaults().grab(true, true).applyTo(partHolder);
partHolder.setLayout(new FillLayout());
EModelService modelService = parentContext.get(EModelService.class);
MDialog dialog = modelService.createModelElement(MDialog.class);
dialog.getPersistedState().put(IPresentationEngine.CUSTOM_RENDERER_KEY,
"bundleclass://testdialog/testdialog.DialogRenderer");
dialog.getTransientData().put("jface-dialog", this);
dialog.getTransientData().put("part-holder", partHolder);
MWindow window = parentContext.get(MWindow.class);
window.getWindows().add(dialog);
EPartService partService = parentContext.get(EPartService.class);
MPart part = partService.createPart("my.partdescriptor.id");
dialog.getChildren().add(part);
return comp;
}
So, during creation of the dialog controls the MDialog element is added to the application model and connected to the dialog (using transient data). And: A custom renderer is required for the MDialog element. Here comes the renderer:
public class DialogRenderer extends SWTPartRenderer {
@Override
public Object createWidget(MUIElement element, Object parent) {
if (!(element instanceof MDialog)) {
return null;
}
Dialog dialog = element.getTransientData().get("jface-dialog");
bindWidget(element, dialog.getShell());
IEclipseContext localContext = getContext(element);
localContext.set(Shell.class, dialog.getShell());
localContext.set(E4Workbench.LOCAL_ACTIVE_SHELL, dialog.getShell());
dialog.getShell().addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
element.setRenderer(false);
MWindow container = (MWindow) ((EObject) element).eContainer();
if (container != null) {
container.getWindows().remove(element);
}
}
});
return dialog.getShell();
}
@Override
public Object getUIContainer(MUIElement element) {
MUIElement parent = element.getParent();
if (parent == null) {
// might be a detached window
parent = (MUIElement) ((EObject) element).eContainer();
return parent == null ? null : parent.getWidget();
}
if (!(parent instanceof MDialog))
throw new RuntimeException(
"Expected a MDialog as parent in " + element
+ "\nActually got: " + parent);
return ((MDialog)parent).getTransientData().get("part-holder");
}
@Override
@PostConstruct
public void init(IEclipseContext context) {
super.init(context);
}
}
The renderer returns the dialog shell as widget for the dialog and removes the MDialog element from the model as soon as the shell is disposed. The dialog's children (ie the part I would like to show inside the dialog) will be rendered inside the partHolder composite. This is the purpose of the getUIContainer method.
With this, everything inside the dialog works as if it was another workbench window: Popup menus, key bindings etc.
Peter
|
|
|
Re: Presenting an MPart in a dialog [message #1727170 is a reply to message #1727161] |
Sun, 20 March 2016 18:31 |
Thomas Schindl Messages: 6651 Registered: July 2009 |
Senior Member |
|
|
I would discourage anyone to use the MDialog stuff! It is provisional
and IMHO completely broken in its current design!
Tom
On 20.03.16 15:48, Peter Kullmann wrote:
> I found a way to do this. It's not so elegant but at least it works and
> I can re-use most of my dialogs in e4 with little changes. The idea is
> to use a MDialog model element to represent the dialog and use a special
> renderer for this. The renderer doesn't do a lot because the dialog was
> created before the renderer is called. The main pieces are the following:
>
> First, the jface dialog:
>
>
> @Override
> protected Control createDialogArea(Composite parent) {
> Composite comp = (Composite) super.createDialogArea(parent);
>
> Composite partHolder = new Composite(comp, SWT.NONE);
> GridDataFactory.fillDefaults().grab(true, true).applyTo(partHolder);
> partHolder.setLayout(new FillLayout());
>
> EModelService modelService = parentContext.get(EModelService.class);
> MDialog dialog = modelService.createModelElement(MDialog.class);
>
> dialog.getPersistedState().put(IPresentationEngine.CUSTOM_RENDERER_KEY,
> "bundleclass://testdialog/testdialog.DialogRenderer");
> dialog.getTransientData().put("jface-dialog", this);
> dialog.getTransientData().put("part-holder", partHolder);
> MWindow window = parentContext.get(MWindow.class);
> window.getWindows().add(dialog);
>
> EPartService partService = parentContext.get(EPartService.class);
> MPart part = partService.createPart("my.partdescriptor.id");
> dialog.getChildren().add(part);
>
> return comp;
> }
>
>
> So, during creation of the dialog controls the MDialog element is added
> to the application model and connected to the dialog (using transient
> data). And: A custom renderer is required for the MDialog element. Here
> comes the renderer:
>
>
> public class DialogRenderer extends SWTPartRenderer {
>
> @Override
> public Object createWidget(MUIElement element, Object parent) {
> if (!(element instanceof MDialog)) {
> return null;
> }
> Dialog dialog = element.getTransientData().get("jface-dialog");
> bindWidget(element, dialog.getShell());
>
> IEclipseContext localContext = getContext(element);
> localContext.set(Shell.class, dialog.getShell());
> localContext.set(E4Workbench.LOCAL_ACTIVE_SHELL, dialog.getShell());
>
> dialog.getShell().addDisposeListener(new DisposeListener() {
> @Override
> public void widgetDisposed(DisposeEvent e) {
> element.setRenderer(false);
> MWindow container = (MWindow) ((EObject)
> element).eContainer();
> if (container != null) {
> container.getWindows().remove(element);
> }
> }
> });
>
> return dialog.getShell();
> }
>
> @Override
> public Object getUIContainer(MUIElement element) {
> MUIElement parent = element.getParent();
> if (parent == null) {
> // might be a detached window
> parent = (MUIElement) ((EObject) element).eContainer();
> return parent == null ? null : parent.getWidget();
> }
>
> if (!(parent instanceof MDialog))
> throw new RuntimeException(
> "Expected a MDialog as parent in " + element
> + "\nActually got: " + parent);
> return ((MDialog)parent).getTransientData().get("part-holder");
> }
>
> @Override
> @PostConstruct
> public void init(IEclipseContext context) {
> super.init(context);
> }
> }
>
>
> The renderer returns the dialog shell as widget for the dialog and
> removes the MDialog element from the model as soon as the shell is
> disposed. The dialog's children (ie the part I would like to show inside
> the dialog) will be rendered inside the partHolder composite. This is
> the purpose of the getUIContainer method.
>
> With this, everything inside the dialog works as if it was another
> workbench window: Popup menus, key bindings etc.
>
> Peter
>
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.03205 seconds