| /******************************************************************************* |
| * Copyright (c) 2012 Rushan R. Gilmullin and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Rushan R. Gilmullin - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.osbp.vaaclipse.presentation.renderers; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import javax.annotation.PostConstruct; |
| import javax.annotation.PreDestroy; |
| import javax.inject.Inject; |
| |
| import org.eclipse.e4.core.contexts.IEclipseContext; |
| import org.eclipse.e4.core.di.annotations.Optional; |
| import org.eclipse.e4.core.services.events.IEventBroker; |
| import org.eclipse.e4.ui.model.application.MApplication; |
| import org.eclipse.e4.ui.model.application.ui.MContext; |
| import org.eclipse.e4.ui.model.application.ui.MElementContainer; |
| import org.eclipse.e4.ui.model.application.ui.MUIElement; |
| import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective; |
| import org.eclipse.e4.ui.model.application.ui.advanced.MPerspectiveStack; |
| import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder; |
| import org.eclipse.e4.ui.model.application.ui.basic.MPartStack; |
| import org.eclipse.e4.ui.model.application.ui.basic.MWindow; |
| import org.eclipse.e4.ui.workbench.IPresentationEngine; |
| import org.eclipse.e4.ui.workbench.UIEvents; |
| import org.eclipse.e4.ui.workbench.UIEvents.EventTags; |
| import org.eclipse.e4.ui.workbench.modeling.EPartService; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.xmi.XMIResource; |
| import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl; |
| import org.eclipse.emf.edit.domain.EditingDomain; |
| import org.eclipse.osbp.runtime.designer.api.IDesignerService; |
| import org.eclipse.osbp.runtime.designer.api.IDesignerService.DesignEvent; |
| import org.eclipse.osbp.runtime.designer.api.IDesignerService.EventType; |
| import org.eclipse.osbp.runtime.designer.api.IWidgetDesignConfigurator; |
| import org.eclipse.osbp.vaaclipse.Activator; |
| import org.eclipse.osbp.vaaclipse.api.ResourceInfoProvider; |
| import org.eclipse.osbp.vaaclipse.presentation.engine.GenericPresentationEngine; |
| import org.eclipse.osbp.vaaclipse.presentation.utils.Commons; |
| import org.eclipse.osbp.vaaclipse.presentation.utils.HierarchyUtils; |
| import org.eclipse.osbp.vaaclipse.publicapi.authentication.AuthenticationConstants; |
| import org.eclipse.osbp.vaaclipse.publicapi.change.ChangeCommand; |
| import org.eclipse.osbp.vaaclipse.publicapi.change.SimpleCommand; |
| import org.eclipse.osbp.vaaclipse.publicapi.model.Tags; |
| import org.eclipse.osbp.vaaclipse.publicapi.perspective.IPerspectiveHandler; |
| import org.eclipse.osbp.vaaclipse.publicapi.resources.BundleResource; |
| import org.eclipse.osbp.vaaclipse.publicapi.resources.ResourceHelper; |
| import org.eclipse.osbp.vaaclipse.widgets.StackWidget; |
| import org.eclipse.osbp.vaaclipse.widgets.TwoStateToolbarButton; |
| import org.eclipse.osbp.vaadin.optiondialog.OptionDialog; |
| import org.eclipse.osbp.vaadin.optiondialog.OptionDialog.OptionsAlign; |
| import org.osgi.framework.ServiceReference; |
| import org.osgi.service.event.Event; |
| import org.osgi.service.event.EventHandler; |
| |
| import com.vaadin.addon.contextmenu.ContextMenu; |
| import com.vaadin.addon.contextmenu.MenuItem; |
| import com.vaadin.data.Item; |
| import com.vaadin.data.util.IndexedContainer; |
| import com.vaadin.event.dd.DragAndDropEvent; |
| import com.vaadin.event.dd.DropHandler; |
| import com.vaadin.event.dd.acceptcriteria.AcceptAll; |
| import com.vaadin.event.dd.acceptcriteria.AcceptCriterion; |
| import com.vaadin.server.Resource; |
| import com.vaadin.server.Sizeable.Unit; |
| import com.vaadin.server.StreamVariable; |
| import com.vaadin.server.ThemeResource; |
| import com.vaadin.ui.Button; |
| import com.vaadin.ui.Button.ClickEvent; |
| import com.vaadin.ui.Button.ClickListener; |
| import com.vaadin.ui.Component; |
| import com.vaadin.ui.ComponentContainer; |
| import com.vaadin.ui.DragAndDropWrapper; |
| import com.vaadin.ui.DragAndDropWrapper.WrapperTransferable; |
| import com.vaadin.ui.HorizontalLayout; |
| import com.vaadin.ui.Html5File; |
| import com.vaadin.ui.Label; |
| import com.vaadin.ui.Notification; |
| import com.vaadin.ui.Notification.Type; |
| import com.vaadin.ui.Panel; |
| import com.vaadin.ui.Table; |
| import com.vaadin.ui.UI; |
| import com.vaadin.ui.VerticalLayout; |
| |
| /** |
| * @author rushan |
| * |
| */ |
| public class PerspectiveStackRenderer extends VaadinRenderer implements IDesignerService.IDesignListener { |
| |
| /** |
| * Removes the perspective from stack if it is closed. |
| */ |
| private static final String TAG__REMOVE_ON_CLOSE = "remove_on_close"; |
| |
| /** |
| * The perspective is not visible in the open perspective dialog. |
| */ |
| private static final String TAG__NOT_IN_OPEN_PERSPECTIVE_DIALOG = "not_in_open_perspective_dialog"; |
| |
| private MPerspectiveStack perspectiveStackForSwitcher; |
| private HorizontalLayout perspectiveSwitcherPanel; |
| private Map<MPerspective, TwoStateToolbarButton> perspective_button = new HashMap<MPerspective, TwoStateToolbarButton>(); |
| private Map<Component, PerspectiveContextMenu> button2ContextMenu = new HashMap<Component, PerspectiveContextMenu>(); |
| |
| private MPerspective activePerspective; |
| @Inject |
| private UI vaadinUI; |
| |
| @Inject |
| @Optional |
| private IPerspectiveHandler perspectiveRegistry; |
| |
| @Inject |
| @Optional |
| private EditingDomain editingDomain; |
| |
| @Inject |
| @Optional |
| private IDesignerService designerService; |
| |
| @SuppressWarnings("serial") |
| private class PerspectiveContextMenu extends ContextMenu { |
| private static final String SHOW_TEXT = "Show Text"; |
| |
| private MenuItem showTextItem; |
| private MenuItem closeItem; |
| private final MPerspective perspective; |
| |
| // Resource checkIcon = new ThemeResource("../vaaclipse_default_theme/img/check.png"); |
| |
| public PerspectiveContextMenu(TwoStateToolbarButton button, boolean iconsOnly, MPerspective perspective) { |
| super(button, true); |
| this.perspective = perspective; |
| createItems(iconsOnly); |
| // setIconsOnly(iconsOnly); |
| } |
| |
| private void createItems(boolean iconsOnly) { |
| closeItem = addItem("Close", this::menuSelected); |
| showTextItem = addItem(SHOW_TEXT, this::menuSelected); |
| } |
| |
| public MenuItem getShowTextItem() { |
| return showTextItem; |
| } |
| |
| public MenuItem getCloseItem() { |
| return closeItem; |
| } |
| |
| // void setIconsOnly(boolean iconsOnly) { |
| // showTextItem.setIcon(!iconsOnly ? checkIcon : null); |
| // } |
| |
| void menuSelected(MenuItem clickedItem) { |
| |
| if (clickedItem == getCloseItem()) { |
| if (perspective.getTags().contains(TAG__REMOVE_ON_CLOSE)) { |
| // sends new messages |
| modelService.removePerspectiveModel(perspective, perspective.getContext().get(MWindow.class)); |
| |
| switchToPreviousPerspective(perspective); |
| |
| } else if (perspective == activePerspective) { |
| switchToPreviousPerspective(perspective); |
| } |
| |
| perspective.setToBeRendered(false); |
| |
| } else if (clickedItem == getShowTextItem()) { |
| if (perspectiveStackForSwitcher.getTags().contains(Tags.ICONS_ONLY)) |
| perspectiveStackForSwitcher.getTags().remove(Tags.ICONS_ONLY); |
| else |
| perspectiveStackForSwitcher.getTags().add(Tags.ICONS_ONLY); |
| } |
| |
| } |
| |
| } |
| |
| public HorizontalLayout getPerspectiveSwitcher() { |
| return perspectiveSwitcherPanel; |
| } |
| |
| public MPerspectiveStack getPerspectiveStackForSwitcher() { |
| return perspectiveStackForSwitcher; |
| } |
| |
| @Inject |
| IEventBroker eventBroker; |
| |
| @Inject |
| MApplication application; |
| |
| @Inject |
| EPartService partService; |
| |
| @Inject |
| GenericPresentationEngine engine; |
| |
| static final String PERSPECTIVE_LABEL = "PerspectiveLabel"; |
| static final String PERSPECTIVE_ICON = "PerspectiveIcon"; |
| |
| private final EventHandler tagListener = new EventHandler() { |
| @SuppressWarnings("unused") |
| @Override |
| public void handleEvent(Event event) { |
| Object changedObj = event.getProperty(EventTags.ELEMENT); |
| |
| if (!(changedObj instanceof MPerspectiveStack)) { |
| return; |
| } |
| |
| final MPerspectiveStack changedElement = (MPerspectiveStack) changedObj; |
| |
| String eventType = (String) event.getProperty(UIEvents.EventTags.TYPE); |
| String tag = (String) event.getProperty(UIEvents.EventTags.NEW_VALUE); |
| String oldVal = (String) event.getProperty(UIEvents.EventTags.OLD_VALUE); |
| |
| if (UIEvents.EventTypes.ADD.equals(eventType) && Tags.ICONS_ONLY.equals(tag)) { |
| for (Map.Entry<MPerspective, TwoStateToolbarButton> entry : perspective_button.entrySet()) { |
| MPerspective perspective = entry.getKey(); |
| TwoStateToolbarButton button = entry.getValue(); |
| button.setLabelAndIcon(null, Commons.trim(perspective.getIconURI())); |
| |
| PerspectiveContextMenu menu = button2ContextMenu.get(button); |
| // menu.setIconsOnly(true); |
| } |
| } else if (UIEvents.EventTypes.REMOVE.equals(eventType) && Tags.ICONS_ONLY.equals(oldVal)) { |
| for (Map.Entry<MPerspective, TwoStateToolbarButton> entry : perspective_button.entrySet()) { |
| MPerspective perspective = entry.getKey(); |
| TwoStateToolbarButton button = entry.getValue(); |
| button.setLabelAndIcon(Commons.trim(perspective.getLabel()), |
| Commons.trim(perspective.getIconURI())); |
| |
| PerspectiveContextMenu menu = button2ContextMenu.get(button); |
| // menu.setIconsOnly(false); |
| } |
| } |
| } |
| }; |
| |
| private EventHandler selectPerspectiveHandler = new EventHandler() { |
| @SuppressWarnings("unchecked") |
| public void handleEvent(Event event) { |
| Object element = event.getProperty(UIEvents.EventTags.ELEMENT); |
| |
| if (!(element instanceof MPerspectiveStack)) |
| return; |
| |
| MPerspectiveStack stack = (MPerspectiveStack) element; |
| if (stack.getRenderer() != PerspectiveStackRenderer.this) |
| return; |
| @SuppressWarnings("unused") |
| PerspectiveStackRenderer psr = (PerspectiveStackRenderer) stack.getRenderer(); |
| |
| // Gather up the elements that are being 'hidden' by this change |
| MUIElement oldSel = (MUIElement) event.getProperty(UIEvents.EventTags.OLD_VALUE); |
| if (oldSel != null) { |
| @SuppressWarnings("unused") |
| List<MUIElement> goingHidden = new ArrayList<MUIElement>(); |
| } |
| |
| if (oldSel != null) { |
| perspective_button.get(oldSel).setCheckedState(false); |
| perspective_button.get(oldSel).setSwitchStateByUserClickEnabled(true); |
| |
| hideElementRecursive(oldSel); |
| } |
| |
| ((VerticalLayout) stack.getWidget()).removeAllComponents(); |
| |
| if (stack.getSelectedElement() != null) { |
| showElementRecursive(stack.getSelectedElement()); |
| ((VerticalLayout) stack.getWidget()).addComponent((Component) stack.getSelectedElement().getWidget()); |
| perspective_button.get(stack.getSelectedElement()).setCheckedState(true); |
| perspective_button.get(stack.getSelectedElement()).setSwitchStateByUserClickEnabled(false); |
| |
| // mark the perspective as active |
| switchPerspective(stack.getSelectedElement()); |
| } else if (oldSel instanceof MElementContainer<?>) { |
| disconnectReferencedElementsFromPerspectiveWidgets((MElementContainer<? extends MUIElement>) oldSel); |
| } |
| |
| } |
| }; |
| |
| private EventHandler localizeLabel = new EventHandler() { |
| @Override |
| public void handleEvent(Event event) { |
| Object element = event.getProperty(UIEvents.EventTags.ELEMENT); |
| |
| if (!(element instanceof MPerspective)) |
| return; |
| |
| MPerspective perspective = (MPerspective) element; |
| |
| String newValue = (String) event.getProperty(UIEvents.EventTags.NEW_VALUE); |
| |
| boolean iconsOnly = perspectiveStackForSwitcher.getTags().contains(Tags.ICONS_ONLY); |
| String label = iconsOnly ? null : Commons.trim(newValue); |
| String iconURI = Commons.trim(perspective.getIconURI()); |
| |
| TwoStateToolbarButton button = perspective_button.get(perspective); |
| if (button != null) { |
| button.setLabelAndIcon(label, iconURI); |
| } |
| } |
| }; |
| |
| private EventHandler iconURI = new EventHandler() { |
| @Override |
| public void handleEvent(Event event) { |
| Object element = event.getProperty(UIEvents.EventTags.ELEMENT); |
| |
| if (!(element instanceof MPerspective)) |
| return; |
| |
| MPerspective perspective = (MPerspective) element; |
| |
| String newValue = (String) event.getProperty(UIEvents.EventTags.NEW_VALUE); |
| |
| TwoStateToolbarButton button = perspective_button.get(perspective); |
| if (button != null) { |
| button.setIconURI(newValue); |
| } |
| } |
| }; |
| |
| private EventHandler localizeTooltip = new EventHandler() { |
| @Override |
| public void handleEvent(Event event) { |
| Object element = event.getProperty(UIEvents.EventTags.ELEMENT); |
| |
| if (!(element instanceof MPerspective)) |
| return; |
| |
| MPerspective perspective = (MPerspective) element; |
| |
| if (perspective.getTooltip() != null) { |
| String newValue = (String) event.getProperty(UIEvents.EventTags.NEW_VALUE); |
| TwoStateToolbarButton button = perspective_button.get(perspective); |
| if (button != null) { |
| button.setDescription(newValue); |
| } |
| } |
| } |
| }; |
| |
| private void disconnectReferencedElementsFromPerspectiveWidgets(MElementContainer<? extends MUIElement> container) { |
| for (MUIElement e : container.getChildren()) { |
| if (e instanceof MPlaceholder) { |
| MPlaceholder ph = (MPlaceholder) e; |
| if (ph.isToBeRendered()) { |
| ComponentContainer phComponent = (ComponentContainer) ph.getWidget(); |
| Component refComponent = (Component) ph.getRef().getWidget(); |
| phComponent.removeComponent(refComponent); |
| } |
| } |
| } |
| } |
| |
| @PostConstruct |
| public void postConstruct() { |
| eventBroker.subscribe(UIEvents.ElementContainer.TOPIC_SELECTEDELEMENT, selectPerspectiveHandler); |
| eventBroker.subscribe(UIEvents.ApplicationElement.TOPIC_TAGS, tagListener); |
| eventBroker.subscribe(UIEvents.UILabel.TOPIC_LOCALIZED_LABEL, localizeLabel); |
| eventBroker.subscribe(UIEvents.UILabel.TOPIC_LOCALIZED_TOOLTIP, localizeTooltip); |
| eventBroker.subscribe(UIEvents.UILabel.TOPIC_LABEL, localizeLabel); |
| eventBroker.subscribe(UIEvents.UILabel.TOPIC_TOOLTIP, localizeTooltip); |
| eventBroker.subscribe(UIEvents.UILabel.TOPIC_ICONURI, iconURI); |
| eventBroker.subscribe(UIEvents.ElementContainer.TOPIC_CHILDREN, childrenMoveUpdater); |
| } |
| |
| @PreDestroy |
| public void preDestroy() { |
| |
| if (designerService != null) { |
| designerService.removeListener(this); |
| } |
| |
| eventBroker.unsubscribe(selectPerspectiveHandler); |
| eventBroker.unsubscribe(tagListener); |
| eventBroker.unsubscribe(localizeLabel); |
| eventBroker.unsubscribe(localizeTooltip); |
| eventBroker.unsubscribe(iconURI); |
| eventBroker.unsubscribe(childrenMoveUpdater); |
| } |
| |
| private EventHandler childrenMoveUpdater = new EventHandler() { |
| @SuppressWarnings("unchecked") |
| public void handleEvent(Event event) { |
| // Ensure that this event is for a MMenuItem |
| if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MPerspectiveStack)) |
| return; |
| |
| MElementContainer<MUIElement> stack = (MElementContainer<MUIElement>) event |
| .getProperty(UIEvents.EventTags.ELEMENT); |
| String type = (String) event.getProperty(UIEvents.EventTags.TYPE); |
| |
| // on move, we unrender an render the UI again |
| // |
| if (UIEvents.EventTypes.MOVE.equals(type)) { |
| MUIElement newValue = (MUIElement) event.getProperty(UIEvents.EventTags.NEW_VALUE); |
| removeChildGui(newValue, stack); |
| addChildGui(newValue, stack); |
| } |
| } |
| }; |
| private DragAndDropWrapper html5Drop; |
| |
| @Override |
| public boolean isLazy() { |
| return true; |
| } |
| |
| @Override |
| public void createWidget(MUIElement element, MElementContainer<MUIElement> parent) { |
| if (perspectiveSwitcherPanel == null) |
| initializePerspectiveSwticherPanel((MPerspectiveStack) element); |
| |
| VerticalLayout perspectiveStackContent = new VerticalLayout(); |
| perspectiveStackContent.setSizeFull(); |
| element.setWidget(perspectiveStackContent); |
| |
| if (designerService != null) { |
| designerService.addListener(this); |
| |
| if (designerService.isDesignMode()) { |
| updateDesigner(true); |
| } |
| } |
| } |
| |
| private void initializePerspectiveSwticherPanel(MPerspectiveStack perspectiveStack) { |
| if (perspectiveSwitcherPanel != null) |
| return; |
| // initialize perspective switcher panel |
| perspectiveStackForSwitcher = perspectiveStack; |
| |
| perspectiveSwitcherPanel = new HorizontalLayout(); |
| perspectiveSwitcherPanel.setStyleName("perspectivepanel"); |
| perspectiveSwitcherPanel.setSizeUndefined(); |
| |
| // add separator between openPerspectiveButton and perspective's buttons |
| Label separator = new Label(); |
| separator.setSizeUndefined(); |
| separator.addStyleName("horizontalseparator"); |
| separator.setHeight("100%"); |
| perspectiveSwitcherPanel.addComponent(separator); |
| |
| // add buttons to perspective switch panel |
| for (final MPerspective perspective : perspectiveStackForSwitcher.getChildren()) { |
| if (perspective.isToBeRendered()) { |
| Component button = createPerspectiveButton(perspective); |
| if (button != null) { |
| perspectiveSwitcherPanel.addComponent(button); |
| } |
| } |
| } |
| } |
| |
| @SuppressWarnings("serial") |
| private Component createPerspectiveButton(final MPerspective perspective) { |
| if (!perspective.isVisible()) |
| return null; |
| boolean iconsOnly = perspectiveStackForSwitcher.getTags().contains(Tags.ICONS_ONLY); |
| String label = iconsOnly ? null : Commons.trim(perspective.getLocalizedLabel()); |
| String iconURI = Commons.trim(perspective.getIconURI()); |
| |
| final TwoStateToolbarButton button = new TwoStateToolbarButton(label, iconURI); |
| |
| if (perspective.getTooltip() != null) { |
| button.setDescription(perspective.getLocalizedTooltip()); |
| } |
| |
| button.addListener(new ClickListener() { |
| public void buttonClick(ClickEvent event) { |
| if (editingDomain != null) { |
| SimpleCommand command = new SimpleCommand("Switch perspective: " |
| + activePerspective.getLocalizedLabel() + " <--> " + perspective.getLocalizedLabel()) { |
| final MPerspective oldPerspective = activePerspective; |
| final MPerspective newPerspective = perspective; |
| |
| @Override |
| protected void doExecute() { |
| switchPerspective(newPerspective); |
| } |
| |
| @Override |
| protected void doUndo() { |
| switchPerspective(oldPerspective); |
| } |
| }; |
| editingDomain.getCommandStack().execute(command); |
| |
| } else { |
| switchPerspective(perspective); |
| } |
| } |
| }); |
| |
| // Create context menu |
| final PerspectiveContextMenu menu = new PerspectiveContextMenu(button, iconsOnly, perspective); |
| |
| |
| menu.setAsContextMenuOf(button); |
| button2ContextMenu.put(button, menu); |
| perspective_button.put(perspective, button); |
| return button; |
| } |
| |
| @Override |
| public void notify(DesignEvent event) { |
| updateDesigner(event.getType() == EventType.ENABLED); |
| } |
| |
| private void updateDesigner(boolean enabled) { |
| IWidgetDesignConfigurator designConfigurator = context.get(IWidgetDesignConfigurator.class); |
| if (designConfigurator != null) { |
| for (Map.Entry<MPerspective, TwoStateToolbarButton> entry : perspective_button.entrySet()) { |
| designConfigurator.configure(entry.getValue(), (EObject) entry.getKey(), enabled); |
| } |
| } |
| } |
| |
| @Override |
| public void processContents(MElementContainer<MUIElement> element) { |
| if (element.getChildren().isEmpty()) |
| return; |
| |
| MPerspectiveStack perspectiveStack = (MPerspectiveStack) (MElementContainer<?>) element; |
| MPerspective selectedPerspective = perspectiveStack.getSelectedElement(); |
| if (selectedPerspective == null) { |
| // try to find by registry |
| if (perspectiveRegistry != null) { |
| String userId = (String) context.get(AuthenticationConstants.USER_ID); |
| String perspectiveId = perspectiveRegistry.getDefaultPerspective(userId); |
| if (perspectiveId != null) { |
| selectedPerspective = perspectiveRegistry.findPerspectiveWithId(perspectiveId); |
| } |
| if (selectedPerspective == null) { |
| selectedPerspective = (MPerspective) findFirstRenderableAndVisibleElement(perspectiveStack); |
| } |
| } else { |
| // use the first elemet |
| selectedPerspective = (MPerspective) findFirstRenderableAndVisibleElement(perspectiveStack); |
| } |
| } |
| |
| if (selectedPerspective != null) { |
| if (!selectedPerspective.isToBeRendered() || !selectedPerspective.isVisible()) { |
| selectedPerspective = (MPerspective) findFirstRenderableAndVisibleElement(perspectiveStack); |
| if (selectedPerspective != null) { |
| switchPerspective(selectedPerspective); |
| } else { |
| perspectiveStack.setSelectedElement(null); |
| } |
| } else { |
| // reset selected element (set selected element handler will |
| // work) |
| perspectiveStack.setSelectedElement(null); |
| switchPerspective(selectedPerspective); |
| } |
| } |
| |
| refreshPerspectiveStackVisibility(perspectiveStack); |
| } |
| |
| private void switchPerspective(MPerspective perspective) { |
| if (perspective.isToBeRendered() && perspective.getWidget() == null) |
| engine.createGui(perspective); |
| partService.switchPerspective(perspective); |
| this.activePerspective = perspective; |
| if (perspective.getElementId() != null) { |
| String perspectiveId = perspective.getElementId().trim(); |
| application.getContext().set("activePerspective", perspectiveId); |
| } |
| } |
| |
| private void refreshPerspectiveStackVisibility(MPerspectiveStack stack) { |
| perspectiveSwitcherPanel.setVisible(stack.getChildren().size() > 0); |
| } |
| |
| @Override |
| public void addChildGui(MUIElement child, MElementContainer<MUIElement> element) { |
| MPerspectiveStack stack = (MPerspectiveStack) (MElementContainer<?>) element; |
| MPerspective p = (MPerspective) child; |
| |
| Component button = createPerspectiveButton(p); |
| // shift on 2 - the first child - open perspective button, the second |
| // child - is separator |
| int index = indexOf(child, element) + 2; |
| perspectiveSwitcherPanel.addComponent(button, |
| Math.min(index, perspectiveSwitcherPanel.getComponentCount() - 1)); |
| |
| refreshPerspectiveStackVisibility(stack); |
| } |
| |
| @Override |
| public void removeChildGui(MUIElement child, MElementContainer<MUIElement> element) { |
| MPerspectiveStack stack = (MPerspectiveStack) (MElementContainer<?>) element; |
| MPerspective p = (MPerspective) child; |
| |
| Button button = perspective_button.remove(p); |
| if (button != null) { |
| perspectiveSwitcherPanel.removeComponent(button); |
| button2ContextMenu.remove(button); |
| } |
| |
| refreshPerspectiveStackVisibility(stack); |
| } |
| |
| private void openOpenPerspectiveWindow() { |
| OptionDialog dlg = new OptionDialog(); |
| dlg.setCaption("Open perspective"); |
| |
| ServiceReference<ResourceInfoProvider> resourceInfoProviderRef = Activator.getInstance().getContext() |
| .getServiceReference(ResourceInfoProvider.class); |
| if (resourceInfoProviderRef != null) { |
| ResourceInfoProvider resourceInfoProvider = Activator.getInstance().getContext() |
| .getService(resourceInfoProviderRef); |
| if (resourceInfoProvider.getApplicationHeaderIcon() != null) { |
| dlg.setIcon(BundleResource.valueOf(resourceInfoProvider.getApplicationHeaderIcon())); |
| } |
| } |
| |
| dlg.setModal(true); |
| dlg.setWidth(360, Unit.PIXELS); |
| dlg.setHeight(440, Unit.PIXELS); |
| dlg.addOption(0, "OK"); |
| dlg.addOption(1, "CANCEL"); |
| dlg.setOptionButtonsWidth(80, Unit.PIXELS); |
| dlg.setOptionButtonsAlignment(OptionsAlign.RIGHT); |
| |
| vaadinUI.addWindow(dlg); |
| |
| dlg.setComponentProvider(new OptionDialog.ComponentProvider() { |
| |
| Panel panel; |
| Table list; |
| IndexedContainer container; |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| public Component getComponent(OptionDialog optionDialog) { |
| if (panel == null) { |
| container = new IndexedContainer(); |
| container.addContainerProperty(PERSPECTIVE_ICON, Resource.class, null); |
| container.addContainerProperty(PERSPECTIVE_LABEL, String.class, null); |
| |
| for (MPerspective p : perspectiveStackForSwitcher.getChildren()) { |
| if (!p.isVisible()) { |
| continue; |
| } |
| |
| if (p.getTags().contains(TAG__NOT_IN_OPEN_PERSPECTIVE_DIALOG)) { |
| continue; |
| } |
| |
| Item item = container.addItem(p.getElementId()); |
| Resource icon = ResourceHelper.createResource(p.getIconURI()); |
| if (icon != null) { |
| item.getItemProperty(PERSPECTIVE_ICON).setValue(icon); |
| } |
| item.getItemProperty(PERSPECTIVE_LABEL).setValue(p.getLabel()); |
| } |
| |
| panel = new Panel(); |
| list = new Table(); |
| list.addStyleName("open_perspective_window"); |
| panel.setContent(list); |
| list.setSizeFull(); |
| list.setSelectable(true); |
| list.setMultiSelect(false); |
| list.setContainerDataSource(container); |
| list.setColumnHeaderMode(Table.COLUMN_HEADER_MODE_HIDDEN); |
| list.setVisibleColumns(new Object[] { PERSPECTIVE_LABEL }); |
| list.setRowHeaderMode(Table.ROW_HEADER_MODE_ICON_ONLY); |
| list.setItemIconPropertyId(PERSPECTIVE_ICON); |
| list.setColumnExpandRatio(PERSPECTIVE_LABEL, 1); |
| } |
| return panel; |
| } |
| |
| @Override |
| public void optionSelected(OptionDialog dlg, int optionId) { |
| if (optionId == 0) { |
| // selected perspective's elementId |
| String perspectiveId = (String) list.getValue(); |
| if (perspectiveId != null) { |
| MPerspective perspective = (MPerspective) modelService.find(perspectiveId, |
| perspectiveStackForSwitcher); |
| if (!perspective.isToBeRendered()) |
| perspective.setToBeRendered(true); |
| switchPerspective(perspective); |
| } |
| } |
| dlg.close(); |
| } |
| |
| @Override |
| public void setMessage(String message) { |
| } |
| }); |
| } |
| |
| // ------------------------------------------------------- |
| // ------------------------------------------------------- |
| private void hideElementRecursive(MUIElement element) { |
| if (element == null || element.getWidget() == null) |
| return; |
| |
| if (element instanceof MPlaceholder) { |
| MPlaceholder ph = (MPlaceholder) element; |
| element = ph.getRef(); |
| } |
| |
| // Hide any floating windows |
| if (element instanceof MWindow && element.getWidget() != null) { |
| element.setVisible(false); |
| } |
| |
| if (element instanceof MElementContainer<?>) { |
| MElementContainer<?> container = (MElementContainer<?>) element; |
| for (MUIElement childElement : container.getChildren()) { |
| hideElementRecursive(childElement); |
| } |
| |
| // OK, now process detached windows |
| if (element instanceof MWindow) { |
| for (MWindow w : ((MWindow) element).getWindows()) { |
| hideElementRecursive(w); |
| } |
| } else if (element instanceof MPerspective) { |
| for (MWindow w : ((MPerspective) element).getWindows()) { |
| hideElementRecursive(w); |
| } |
| } |
| } |
| } |
| |
| private void showElementRecursive(MUIElement element) { |
| if (!element.isToBeRendered()) |
| return; |
| |
| if (element instanceof MPlaceholder && element.getWidget() != null) { |
| MPlaceholder ph = (MPlaceholder) element; |
| MUIElement ref = ph.getRef(); |
| ref.setCurSharedRef(ph); |
| |
| ComponentContainer phComponent = (ComponentContainer) ph.getWidget(); |
| Component refComponent = (Component) ph.getRef().getWidget(); |
| phComponent.addComponent(refComponent); |
| |
| element = ref; |
| |
| // top right folder |
| MPartStack topLeftStack = HierarchyUtils.findTopLeftFolder(ph.getRef()); |
| if (topLeftStack != null) { |
| if (ph.getTags().contains(IPresentationEngine.MAXIMIZED)) |
| ((StackWidget) topLeftStack.getWidget()).setState(1); |
| else if (ph.getTags().contains(IPresentationEngine.MINIMIZED)) |
| ((StackWidget) topLeftStack.getWidget()).setState(-1); |
| else { |
| if (((StackWidget) topLeftStack.getWidget()) != null) { |
| ((StackWidget) topLeftStack.getWidget()).setState(0); |
| } |
| } |
| |
| } |
| } |
| |
| if (element instanceof MContext) { |
| IEclipseContext context = ((MContext) element).getContext(); |
| if (context != null) { |
| IEclipseContext newParentContext = modelService.getContainingContext(element); |
| if (context.getParent() != newParentContext) { |
| context.setParent(newParentContext); |
| } |
| } |
| } |
| |
| // Show any floating windows |
| if (element instanceof MWindow && element.getWidget() != null) { |
| int visCount = 0; |
| for (MUIElement kid : ((MWindow) element).getChildren()) { |
| if (kid.isToBeRendered() && kid.isVisible()) |
| visCount++; |
| } |
| if (visCount > 0) |
| element.setVisible(true); |
| } |
| |
| if (element instanceof MElementContainer<?>) { |
| MElementContainer<?> container = (MElementContainer<?>) element; |
| List<MUIElement> kids = new ArrayList<MUIElement>(container.getChildren()); |
| for (MUIElement childElement : kids) { |
| showElementRecursive(childElement); |
| } |
| |
| // OK, now process detached windows |
| if (element instanceof MWindow) { |
| for (MWindow w : ((MWindow) element).getWindows()) { |
| showElementRecursive(w); |
| } |
| } else if (element instanceof MPerspective) { |
| for (MWindow w : ((MPerspective) element).getWindows()) { |
| showElementRecursive(w); |
| } |
| } |
| } |
| } |
| |
| private void switchToPreviousPerspective(final MPerspective perspective) { |
| MPerspective prevRenderableAndVisiblePerspective = null, nextRenderableAndVisiblePerspective = null; |
| boolean startSearch = false; |
| for (MPerspective p : perspectiveStackForSwitcher.getChildren()) { |
| if (startSearch && p.isToBeRendered() && p.isVisible()) { |
| nextRenderableAndVisiblePerspective = p; |
| break; |
| } |
| |
| if (p == perspective) |
| startSearch = true; |
| |
| if (!startSearch && p.isToBeRendered() && p.isVisible()) { |
| prevRenderableAndVisiblePerspective = p; |
| } |
| } |
| |
| MPerspective newSelectedPerspective = nextRenderableAndVisiblePerspective != null |
| ? nextRenderableAndVisiblePerspective : prevRenderableAndVisiblePerspective; |
| |
| if (newSelectedPerspective != null) { |
| switchPerspective(newSelectedPerspective); |
| } |
| } |
| |
| private class PerspectiveDropHandler implements DropHandler { |
| private static final long FILE_SIZE_LIMIT = 2 * 1024 * 1024; // 2MB |
| |
| public PerspectiveDropHandler() { |
| } |
| |
| @Override |
| public void drop(final DragAndDropEvent dropEvent) { |
| // expecting this to be an html5 drag |
| final WrapperTransferable tr = (WrapperTransferable) dropEvent.getTransferable(); |
| final Html5File[] files = tr.getFiles(); |
| if (files != null) { |
| for (final Html5File html5File : files) { |
| final String fileName = html5File.getFileName(); |
| // if (!fileName.endsWith(".perspective")) { |
| // continue; |
| // } |
| if (html5File.getFileSize() > FILE_SIZE_LIMIT) { |
| Notification.show("File rejected. Max 2Mb files are accepted by Sampler", |
| Notification.Type.WARNING_MESSAGE); |
| } else { |
| final ByteArrayOutputStream bas = new ByteArrayOutputStream(); |
| final StreamVariable streamVariable = new StreamVariable() { |
| @Override |
| public OutputStream getOutputStream() { |
| return bas; |
| } |
| |
| @Override |
| public boolean listenProgress() { |
| return false; |
| } |
| |
| @Override |
| public void onProgress(final StreamingProgressEvent event) { |
| } |
| |
| @Override |
| public void streamingStarted(final StreamingStartEvent event) { |
| } |
| |
| @Override |
| public void streamingFinished(final StreamingEndEvent event) { |
| addPerspective(fileName, html5File.getType(), |
| new ByteArrayInputStream(bas.toByteArray())); |
| } |
| |
| @Override |
| public void streamingFailed(final StreamingErrorEvent event) { |
| } |
| |
| @Override |
| public boolean isInterrupted() { |
| return false; |
| } |
| }; |
| html5File.setStreamVariable(streamVariable); |
| } |
| } |
| } |
| } |
| |
| @SuppressWarnings("restriction") |
| private void addPerspective(final String name, final String type, final InputStream stream) { |
| XMIResource resource = new XMIResourceImpl(URI.createURI("perspective" + name)); |
| try { |
| resource.load(stream, null); |
| |
| final MPerspective perspective = (MPerspective) resource.getContents().get(0); |
| ChangeCommand command = new ChangeCommand("Drop perspective: " + perspective.getLocalizedLabel(), |
| ((EObject) getPerspectiveStackForSwitcher()).eResource()) { |
| @Override |
| protected void doExecute() { |
| // add the perspective |
| // |
| getPerspectiveStackForSwitcher().getChildren().add(perspective); |
| getPerspectiveStackForSwitcher().setSelectedElement(perspective); |
| } |
| }; |
| editingDomain.getCommandStack().execute(command); |
| |
| resource.unload(); |
| |
| } catch (IOException e) { |
| Notification.show(e.toString(), Type.ERROR_MESSAGE); |
| } |
| } |
| |
| @Override |
| public AcceptCriterion getAcceptCriterion() { |
| return AcceptAll.get(); |
| } |
| } |
| } |