org.semanticsoft.vaaclipse.presentation.renderers.TrimBarRenderer.java Source code

Java tutorial

Introduction

Here is the source code for org.semanticsoft.vaaclipse.presentation.renderers.TrimBarRenderer.java

Source

/*******************************************************************************
 * 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 v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Rushan R. Gilmullin - initial API and implementation
 *******************************************************************************/

package org.semanticsoft.vaaclipse.presentation.renderers;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;

import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.contexts.RunAndTrack;
import org.eclipse.e4.ui.internal.workbench.ContributionsAnalyzer;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.MCoreExpression;
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.SideValue;
import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
import org.eclipse.e4.ui.model.application.ui.basic.MTrimElement;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
import org.eclipse.e4.ui.model.application.ui.menu.MTrimContribution;
import org.eclipse.e4.ui.services.internal.events.EventBroker;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.e4.ui.workbench.modeling.ExpressionContext;
import org.semanticsoft.vaaclipse.api.VaadinExecutorService;
import org.semanticsoft.vaaclipse.presentation.widgets.TrimmedWindowContent;

import com.vaadin.server.Sizeable.Unit;
import com.vaadin.ui.AbstractLayout;
import com.vaadin.ui.AbstractOrderedLayout;
import com.vaadin.ui.Component;
import com.vaadin.ui.ComponentContainer;
import com.vaadin.ui.CssLayout;
import com.vaadin.ui.Panel;
import com.vaadin.ui.VerticalLayout;

@SuppressWarnings("restriction")
public class TrimBarRenderer extends VaadinRenderer {

    @Inject
    MApplication app;

    @Inject
    EventBroker eventBroker;

    @Inject
    EModelService modelService;

    @Inject
    VaadinExecutorService execService;

    private HashMap<MTrimBar, ArrayList<ArrayList<MTrimElement>>> pendingCleanup = new HashMap<MTrimBar, ArrayList<ArrayList<MTrimElement>>>();

    @PostConstruct
    public void subsrcribe() {

    }

    @PreDestroy
    public void unsubscribe() {

    }

    @Override
    public void createWidget(MUIElement element, MElementContainer<MUIElement> parent) {
        if (!(element instanceof MTrimBar)) {
            return;
        }

        MTrimBar mTrimBar = (MTrimBar) element;
        int orientation = mTrimBar.getSide().getValue();

        AbstractLayout trimBar = null;

        if (orientation == SideValue.BOTTOM_VALUE) {
            trimBar = new CssLayout();
            trimBar.addStyleName("horizontaltrimbar");
        } else if (orientation == SideValue.TOP_VALUE) {
            trimBar = new CssLayout();
            trimBar.addStyleName("toptrimbar");
        } else if (orientation == SideValue.LEFT_VALUE || orientation == SideValue.RIGHT_VALUE) {
            trimBar = new VerticalLayout();
            trimBar.addStyleName("verticaltrimbar");
        }

        trimBar.setSizeUndefined();

        if (orientation == SideValue.BOTTOM_VALUE || orientation == SideValue.TOP_VALUE) {
            trimBar.setWidth("100%");
        }

        element.setWidget(trimBar);
    }

    @Override
    public void processContents(MElementContainer<MUIElement> container) {
        final MTrimBar trimBar = (MTrimBar) ((MElementContainer<?>) container);
        int orientation = trimBar.getSide().getValue();
        AbstractLayout trimBarWidget = (AbstractLayout) container.getWidget();
        if (orientation == SideValue.TOP_VALUE || orientation == SideValue.BOTTOM_VALUE)
            trimBarWidget.setHeight(-1, Unit.PIXELS);
        else
            trimBarWidget.setWidth(-1, Unit.PIXELS);

        boolean isFirst = true;
        trimBarWidget.removeAllComponents();
        for (MUIElement element : container.getChildren()) {
            if (element.isToBeRendered()) {
                ComponentContainer subToolbar = (ComponentContainer) element.getWidget();
                subToolbar.setVisible(element.isVisible());
                if (subToolbar != null) {
                    if (orientation == SideValue.TOP_VALUE || orientation == SideValue.BOTTOM_VALUE)
                        subToolbar.addStyleName("horizontaltrimelement");
                    else
                        subToolbar.addStyleName("verticaltrimelement");

                    subToolbar.setSizeUndefined();

                    trimBarWidget.addComponent(subToolbar);
                    isFirst = false;
                }
            }
        }

        //---
        IEclipseContext ctx = getContext(container);
        final ExpressionContext eContext = new ExpressionContext(ctx);

        //visible when support for original trimbar elements (without contributed)
        for (final MTrimElement child : trimBar.getChildren()) {
            if (child.getVisibleWhen() != null) {
                ctx.runAndTrack(new RunAndTrack() {
                    @Override
                    public boolean changed(IEclipseContext context) {

                        if (!trimBar.isToBeRendered() || !trimBar.isVisible() || trimBar.getWidget() == null) {
                            return false;
                        }

                        final boolean rc = ContributionsAnalyzer.isVisible((MCoreExpression) child.getVisibleWhen(),
                                eContext);
                        execService.invokeLater(new Runnable() {

                            @Override
                            public void run() {
                                child.setToBeRendered(rc);
                            }
                        });

                        return true;
                    }
                });
            }
        }

        //contributions
        ArrayList<MTrimContribution> toContribute = new ArrayList<MTrimContribution>();
        ContributionsAnalyzer.gatherTrimContributions(trimBar, app.getTrimContributions(), trimBar.getElementId(),
                toContribute, eContext);
        addTrimContributions(trimBar, toContribute, ctx, eContext);

        refreshVisibility(trimBar);
    }

    private void refreshVisibility(MTrimBar trimBar) {

        AbstractLayout trimBarWidget = (AbstractLayout) trimBar.getWidget();
        int orientation = trimBar.getSide().getValue();

        trimBarWidget.setVisible(trimBarWidget.getComponentCount() != 0);

        if (orientation == SideValue.TOP_VALUE) {
            MWindow window = modelService.getTopLevelWindowFor(trimBar);
            TrimmedWindowContent windowContent = (TrimmedWindowContent) ((Panel) window.getWidget()).getContent();

            Component topbar = windowContent.getTopbar();
            if (topbar != null)
                topbar.setVisible(trimBarWidget.getComponentCount() != 0);
        }
    }

    private void addTrimContributions(final MTrimBar trimModel, ArrayList<MTrimContribution> toContribute,
            IEclipseContext ctx, final ExpressionContext eContext) {
        HashSet<String> existingToolbarIds = new HashSet<String>();
        for (MTrimElement item : trimModel.getChildren()) {
            String id = item.getElementId();
            if (item instanceof MToolBar && id != null) {
                existingToolbarIds.add(id);
            }
        }

        boolean done = toContribute.size() == 0;
        while (!done) {
            ArrayList<MTrimContribution> curList = new ArrayList<MTrimContribution>(toContribute);
            int retryCount = toContribute.size();
            toContribute.clear();

            for (final MTrimContribution contribution : curList) {
                final ArrayList<MTrimElement> toRemove = new ArrayList<MTrimElement>();
                if (!ContributionsAnalyzer.processAddition(trimModel, contribution, toRemove, existingToolbarIds)) {
                    toContribute.add(contribution);
                } else {
                    if (contribution.getVisibleWhen() != null) {
                        ctx.runAndTrack(new RunAndTrack() {
                            @Override
                            public boolean changed(IEclipseContext context) {
                                if (!trimModel.isToBeRendered() || !trimModel.isVisible()
                                        || trimModel.getWidget() == null) {
                                    return false;
                                }
                                final boolean rc = ContributionsAnalyzer.isVisible(contribution, eContext);

                                execService.invokeLater(new Runnable() {

                                    @Override
                                    public void run() {
                                        for (MTrimElement child : toRemove) {
                                            child.setToBeRendered(rc);
                                        }
                                    }
                                });

                                return true;
                            }
                        });
                    }
                    ArrayList<ArrayList<MTrimElement>> lists = pendingCleanup.get(trimModel);
                    if (lists == null) {
                        lists = new ArrayList<ArrayList<MTrimElement>>();
                        pendingCleanup.put(trimModel, lists);
                    }
                    lists.add(toRemove);
                }
            }
            // We're done if the retryList is now empty (everything done) or
            // if the list hasn't changed at all (no hope)
            done = (toContribute.size() == 0) || (toContribute.size() == retryCount);
        }
    }

    @Override
    public void addChildGui(MUIElement child, MElementContainer<MUIElement> element) {
        if (!(child instanceof MTrimElement && (MElementContainer<?>) element instanceof MTrimBar))
            return;

        MTrimBar trimBar = (MTrimBar) (MElementContainer<?>) element;

        final Component childWidget = (Component) child.getWidget();
        childWidget.setVisible(child.isVisible());
        childWidget.setSizeUndefined();
        int orientation = trimBar.getSide().getValue();
        if (orientation == SideValue.TOP_VALUE || orientation == SideValue.BOTTOM_VALUE)
            childWidget.addStyleName("horizontaltrimelement");
        else
            childWidget.addStyleName("verticaltrimelement");

        int index = indexOf(child, element);
        if (element.getWidget() instanceof CssLayout) {
            CssLayout trimWidget = (CssLayout) element.getWidget();
            trimWidget.addComponent(childWidget, index);
            trimWidget.markAsDirty();
        } else if (element.getWidget() instanceof AbstractOrderedLayout) {
            AbstractOrderedLayout trimWidget = (AbstractOrderedLayout) element.getWidget();
            trimWidget.addComponent(childWidget, index);
            trimWidget.markAsDirty();
        }

        refreshVisibility(trimBar);
    }

    @Override
    public void removeChildGui(MUIElement child, MElementContainer<MUIElement> element) {
        if (!(child instanceof MTrimElement && (MElementContainer<?>) element instanceof MTrimBar))
            return;

        super.removeChildGui(child, element);

        Component trimWidget = (Component) element.getWidget();

        MTrimBar trimBar = (MTrimBar) (MElementContainer<?>) element;
        refreshVisibility(trimBar);

        trimWidget.markAsDirty();
    }
}