org.eclipse.wb.internal.rcp.model.widgets.SashFormInfo.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.wb.internal.rcp.model.widgets.SashFormInfo.java

Source

/*******************************************************************************
 * Copyright (c) 2011 Google, Inc.
 * 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:
 *    Google, Inc. - initial API and implementation
 *******************************************************************************/
package org.eclipse.wb.internal.rcp.model.widgets;

import org.eclipse.wb.core.eval.AstEvaluationEngine;
import org.eclipse.wb.core.eval.EvaluationContext;
import org.eclipse.wb.core.model.JavaInfo;
import org.eclipse.wb.core.model.ObjectInfo;
import org.eclipse.wb.core.model.broadcast.JavaEventListener;
import org.eclipse.wb.core.model.broadcast.ObjectInfoDelete;
import org.eclipse.wb.draw2d.geometry.Rectangle;
import org.eclipse.wb.internal.core.model.JavaInfoUtils;
import org.eclipse.wb.internal.core.model.creation.CreationSupport;
import org.eclipse.wb.internal.core.model.description.ComponentDescription;
import org.eclipse.wb.internal.core.model.property.converter.IntegerConverter;
import org.eclipse.wb.internal.core.utils.ast.AstEditor;
import org.eclipse.wb.internal.core.utils.ast.DomGenerics;
import org.eclipse.wb.internal.core.utils.state.EditorState;
import org.eclipse.wb.internal.swt.model.widgets.CompositeInfo;
import org.eclipse.wb.internal.swt.model.widgets.ControlInfo;
import org.eclipse.wb.internal.swt.support.ControlSupport;

import org.eclipse.jdt.core.dom.ArrayCreation;
import org.eclipse.jdt.core.dom.ArrayInitializer;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;

import org.apache.commons.lang.StringUtils;

import java.util.List;

/**
 * Model for {@link SashForm}.
 * 
 * @author scheglov_ke
 * @coverage rcp.model.widgets
 */
public final class SashFormInfo extends CompositeInfo implements ISashFormInfo<ControlInfo> {
    private final SashFormInfo m_this = this;

    ////////////////////////////////////////////////////////////////////////////
    //
    // Constructor
    //
    ////////////////////////////////////////////////////////////////////////////
    public SashFormInfo(AstEditor editor, ComponentDescription description, CreationSupport creationSupport)
            throws Exception {
        super(editor, description, creationSupport);
        // when remove ControlInfo: remove weight
        addBroadcastListener(new ObjectInfoDelete() {
            @Override
            public void before(ObjectInfo parent, ObjectInfo child) throws Exception {
                if (child instanceof ControlInfo && parent == m_this) {
                    removeWeight((ControlInfo) child);
                }
            }
        });
        addBroadcastListener(new JavaEventListener() {
            @Override
            public void moveBefore(JavaInfo child, ObjectInfo oldParent, JavaInfo newParent) throws Exception {
                if (child instanceof ControlInfo && oldParent == m_this && oldParent != newParent) {
                    removeWeight((ControlInfo) child);
                }
            }
        });
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Access
    //
    ////////////////////////////////////////////////////////////////////////////
    public boolean isHorizontal() {
        return ControlSupport.isStyle(getObject(), SWT.HORIZONTAL);
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Commands
    //
    ////////////////////////////////////////////////////////////////////////////
    public void command_CREATE(ControlInfo control, ControlInfo nextControl) throws Exception {
        ensureWeights();
        JavaInfoUtils.add(control, null, this, nextControl);
        addWeight(control);
    }

    public void command_MOVE(ControlInfo control, ControlInfo nextControl) throws Exception {
        ensureWeights();
        int oldIndex = getChildrenControls().indexOf(control);
        JavaInfoUtils.move(control, null, this, nextControl);
        // update weights
        if (oldIndex == -1) {
            addWeight(control);
        } else {
            moveWeight(control, oldIndex);
        }
    }

    public void command_RESIZE(ControlInfo control, int size) throws Exception {
        ensureWeights();
        List<ControlInfo> children = getChildrenControls();
        // prepare weights as current sizes
        int[] weights = new int[children.size()];
        for (int i = 0; i < children.size(); i++) {
            ControlInfo child = children.get(i);
            Rectangle bounds = child.getModelBounds();
            weights[i] = isHorizontal() ? bounds.width : bounds.height;
        }
        // update adjacent weights
        int index = children.indexOf(control);
        int sumWeight = weights[index] + weights[index + 1];
        weights[index + 1] = Math.max(0, sumWeight - size);
        weights[index] = sumWeight - weights[index + 1];
        // set weights
        setWeights(weights);
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Weights operations
    //
    ////////////////////////////////////////////////////////////////////////////
    /**
     * Adds weight for {@link ControlInfo} that is already in children.
     */
    private void addWeight(ControlInfo newControl) throws Exception {
        ArrayInitializer weightsExpression = ensureWeights();
        int[] weights = getWeights(weightsExpression);
        // prepare weight for "newControl"
        int newWeight;
        if (weights.length == 0) {
            newWeight = 1;
        } else {
            newWeight = 0;
            for (int i = 0; i < weights.length; i++) {
                newWeight += weights[i];
            }
            newWeight /= weights.length;
        }
        // add weight
        int newIndex = getChildrenControls().indexOf(newControl);
        getEditor().addArrayElement(weightsExpression, newIndex,
                IntegerConverter.INSTANCE.toJavaSource(this, newWeight));
    }

    /**
     * Moves weight for {@link ControlInfo} that is already moved in children.
     */
    private void moveWeight(ControlInfo newControl, int oldIndex) throws Exception {
        ArrayInitializer weightsExpression = ensureWeights();
        int newIndex = getChildrenControls().indexOf(newControl);
        getEditor().moveArrayElement(weightsExpression, weightsExpression, oldIndex, newIndex);
    }

    /**
     * Removes weight for {@link ControlInfo} that is still in children.
     */
    private void removeWeight(ControlInfo control) throws Exception {
        MethodInvocation invocation = getMethodInvocation("setWeights(int[])");
        if (invocation != null) {
            ArrayInitializer weightsExpression = ((ArrayCreation) DomGenerics.arguments(invocation).get(0))
                    .getInitializer();
            int index = getChildrenControls().indexOf(control);
            getEditor().removeArrayElement(weightsExpression, index);
        }
    }

    /**
     * Ensures that this {@link SashFormInfo} has "setWeights()" invocation.
     * 
     * @return the {@link ArrayInitializer} for weights.
     */
    private ArrayInitializer ensureWeights() throws Exception {
        MethodInvocation invocation = getMethodInvocation("setWeights(int[])");
        if (invocation == null) {
            String elementsSource;
            {
                elementsSource = StringUtils.repeat("1, ", getChildrenControls().size());
                elementsSource = StringUtils.removeEnd(elementsSource, ", ");
            }
            // add invocation
            String arraySource = "new int[] {" + elementsSource + "}";
            invocation = addMethodInvocation("setWeights(int[])", arraySource);
        }
        return ((ArrayCreation) DomGenerics.arguments(invocation).get(0)).getInitializer();
    }

    /**
     * @param weightsExpression
     *          the argument of {@link SashForm#setWeights(int[])} argument.
     * 
     * @return the current weights.
     */
    private int[] getWeights(ArrayInitializer weightsExpression) throws Exception {
        EvaluationContext context;
        {
            AstEditor editor = getEditor();
            EditorState state = EditorState.get(editor);
            ClassLoader editorLoader = state.getEditorLoader();
            context = new EvaluationContext(editorLoader, state.getFlowDescription());
        }
        // evaluate
        return (int[]) AstEvaluationEngine.evaluate(context, weightsExpression);
    }

    /**
     * Sets the weights for {@link SashForm#setWeights(int[])}.
     */
    private void setWeights(int[] weights) throws Exception {
        String arraySource;
        {
            arraySource = "new int[] {";
            for (int i = 0; i < weights.length; i++) {
                if (i > 0) {
                    arraySource += ", ";
                }
                arraySource += weights[i];
            }
            arraySource += "}";
        }
        // replace "setWeight()" invocation
        removeMethodInvocations("setWeights(int[])");
        addMethodInvocation("setWeights(int[])", arraySource);
    }
}