org.eclipse.che.ide.part.editor.multipart.SplitEditorPartViewImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.che.ide.part.editor.multipart.SplitEditorPartViewImpl.java

Source

/*******************************************************************************
 * Copyright (c) 2012-2017 Codenvy, S.A.
 * 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:
 *   Codenvy, S.A. - initial API and implementation
 *******************************************************************************/
package org.eclipse.che.ide.part.editor.multipart;

import com.google.common.collect.BiMap;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Node;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.SimpleLayoutPanel;
import com.google.gwt.user.client.ui.SplitLayoutPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;

import org.eclipse.che.ide.api.constraints.Direction;
import org.eclipse.che.ide.api.parts.EditorMultiPartStackState;
import org.eclipse.che.ide.api.parts.EditorPartStack;
import org.eclipse.che.ide.api.theme.Style;

import static org.eclipse.che.ide.api.constraints.Direction.HORIZONTALLY;
import static org.eclipse.che.ide.api.constraints.Direction.VERTICALLY;

/**
 * @author Roman Nikitenko
 */
public class SplitEditorPartViewImpl implements SplitEditorPartView {
    private final static int SPLITTER_SIZE = 5;
    private final static String VERTICAL_DRAGGER_CLASS = "gwt-SplitLayoutPanel-VDragger";
    private final static String HORIZONTAL_DRAGGER_CLASS = "gwt-SplitLayoutPanel-HDragger";

    private SplitEditorPartView parent;
    private SplitEditorPartView specimenView;
    private SplitEditorPartView replicaView;
    private final IsWidget specimenWidget;
    private final SimpleLayoutPanel rootPanel;
    private SplitLayoutPanel splitLayoutPanel;
    private Direction direction;

    @AssistedInject
    public SplitEditorPartViewImpl(@Assisted IsWidget specimenWidget) {
        this.specimenWidget = specimenWidget;
        rootPanel = new SimpleLayoutPanel();
        rootPanel.add(specimenWidget);
    }

    @AssistedInject
    public SplitEditorPartViewImpl(@Assisted IsWidget specimen, @Assisted SplitEditorPartView parent) {
        this(specimen);
        this.parent = parent;
    }

    @Override
    public SplitEditorPartView getSpecimen() {
        return specimenView;
    }

    @Override
    public SplitEditorPartView getReplica() {
        return replicaView;
    }

    @Override
    public void split(IsWidget replicaWidget, Direction direction, double size) {
        this.direction = direction;
        splitLayoutPanel = new SplitLayoutPanel(SPLITTER_SIZE);
        specimenView = new SplitEditorPartViewImpl(specimenWidget, this);
        replicaView = new SplitEditorPartViewImpl(replicaWidget, this);

        if (direction == VERTICALLY) {
            splitVertically(size);
        } else if (direction == HORIZONTALLY) {
            splitHorizontally(size);
        }

        splitLayoutPanel.add(replicaView);
        rootPanel.remove(specimenWidget);
        rootPanel.add(splitLayoutPanel);

        tuneSplitter(splitLayoutPanel);
    }

    private void splitVertically(double size) {
        double newSize = size == -1 ? rootPanel.getOffsetWidth() / 2 : size;
        splitLayoutPanel.addWest(specimenView, newSize);
    }

    private void splitHorizontally(double size) {
        double newSize = size == -1 ? rootPanel.getOffsetHeight() / 2 : size;
        splitLayoutPanel.addNorth(specimenView, newSize);
    }

    @Override
    public void removeChild(SplitEditorPartView child) {
        splitLayoutPanel.remove(child);
        if (child == replicaView && specimenView != null) {
            splitLayoutPanel.add(specimenView);
        }

        if (child == specimenView) {
            specimenView = null;
        } else if (child == replicaView) {
            replicaView = null;
        }

        if (parent != null && isEmpty()) {
            parent.removeChild(this);
        }

        if (isEmpty()) {
            rootPanel.removeFromParent();
        }
        splitLayoutPanel.forceLayout();
    }

    @Override
    public void removeFromParent() {
        if (parent != null) {
            parent.removeChild(this);
        } else {
            rootPanel.removeFromParent();
        }
    }

    @Override
    public EditorMultiPartStackState getState(BiMap<SplitEditorPartView, EditorPartStack> splitEditorParts) {
        if (splitLayoutPanel == null) {
            return new EditorMultiPartStackState(splitEditorParts.get(this));

        } else if (specimenView == null && replicaView != null) {
            return replicaView.getState(splitEditorParts);
        } else if (replicaView == null && specimenView != null) {
            return specimenView.getState(splitEditorParts);
        }
        if (specimenView != null) {
            return new EditorMultiPartStackState(direction, splitLayoutPanel.getWidgetSize(specimenView.asWidget()),
                    specimenView.getState(splitEditorParts), replicaView.getState(splitEditorParts));
        }
        throw new IllegalStateException("Can't create state, specimenView and replicaView are both null.");
    }

    private boolean isEmpty() {
        return specimenView == null && replicaView == null;
    }

    /**
     * Improves splitter visibility.
     */
    private void tuneSplitter(SplitLayoutPanel splitLayoutPanel) {
        NodeList<Node> nodes = splitLayoutPanel.getElement().getChildNodes();
        for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.getItem(i);
            if (node.hasChildNodes()) {
                Element el = node.getFirstChild().cast();
                String className = el.getClassName();
                if (HORIZONTAL_DRAGGER_CLASS.equals(className)) {
                    tuneVerticalSplitter(el);
                } else if (VERTICAL_DRAGGER_CLASS.equals(className)) {
                    tuneHorizontalSplitter(el);
                }
            }
        }
    }

    /**
     * Tunes splitter. Makes it wider and adds double border to seem rich.
     *
     * @param el
     *         element to tune
     */
    private void tuneVerticalSplitter(Element el) {
        /** Add Z-Index to move the splitter on the top and make content visible */
        el.getParentElement().getStyle().setProperty("zIndex", "1000");
        el.getParentElement().getStyle().setProperty("overflow", "visible");

        /** Tune splitter catch panel */
        el.getStyle().setProperty("boxSizing", "border-box");
        el.getStyle().setProperty("width", "5px");
        el.getStyle().setProperty("overflow", "hidden");
        el.getStyle().setProperty("marginLeft", "-3px");
        el.getStyle().setProperty("backgroundColor", "transparent");

        /** Add small border */
        DivElement smallBorder = Document.get().createDivElement();
        smallBorder.getStyle().setProperty("position", "absolute");
        smallBorder.getStyle().setProperty("width", "1px");
        smallBorder.getStyle().setProperty("height", "100%");
        smallBorder.getStyle().setProperty("left", "3px");
        smallBorder.getStyle().setProperty("top", "0px");
        smallBorder.getStyle().setProperty("backgroundColor", Style.getSplitterSmallBorderColor());
        el.appendChild(smallBorder);
    }

    /**
     * Tunes bottom splitter. Makes it tiny but with a transparent area for easy resizing.
     *
     * @param el
     *         element to tune
     */
    private void tuneHorizontalSplitter(Element el) {
        /** Add Z-Index to move the splitter on the top and make content visible */
        el.getParentElement().getStyle().setProperty("zIndex", "1000");
        el.getParentElement().getStyle().setProperty("overflow", "visible");

        el.getStyle().setProperty("height", "3px");
        el.getStyle().setProperty("marginTop", "-2px");
        el.getStyle().setProperty("backgroundColor", "transparent");

        /** Add small border */
        DivElement delimiter = Document.get().createDivElement();
        delimiter.getStyle().setProperty("position", "absolute");
        delimiter.getStyle().setProperty("width", "100%");
        delimiter.getStyle().setProperty("height", "1px");
        delimiter.getStyle().setProperty("left", "0px");
        delimiter.getStyle().setProperty("backgroundColor", Style.getSplitterSmallBorderColor());
        delimiter.getStyle().setProperty("top", "2px");
        el.appendChild(delimiter);
    }

    @Override
    public Widget asWidget() {
        return rootPanel;
    }
}