All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.intellij.uiDesigner.radComponents.RadBorderLayoutManager Maven / Gradle / Ivy

Go to download

A packaging of the IntelliJ Community Edition ui-designer library. This is release number 1 of trunk branch 142.

The newest version!
/*
 * Copyright 2000-2009 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.intellij.uiDesigner.radComponents;

import com.intellij.openapi.project.Project;
import com.intellij.uiDesigner.UIFormXmlConstants;
import com.intellij.uiDesigner.XmlWriter;
import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.uiDesigner.designSurface.ComponentDragObject;
import com.intellij.uiDesigner.designSurface.ComponentDropLocation;
import com.intellij.uiDesigner.designSurface.FeedbackLayer;
import com.intellij.uiDesigner.designSurface.GuiEditor;
import com.intellij.uiDesigner.propertyInspector.Property;
import com.intellij.uiDesigner.propertyInspector.PropertyRenderer;
import com.intellij.uiDesigner.propertyInspector.PropertyEditor;
import com.intellij.uiDesigner.propertyInspector.InplaceContext;
import com.intellij.uiDesigner.propertyInspector.editors.ComboBoxPropertyEditor;
import com.intellij.uiDesigner.propertyInspector.renderers.LabelPropertyRenderer;
import com.intellij.uiDesigner.propertyInspector.properties.HGapProperty;
import com.intellij.uiDesigner.propertyInspector.properties.VGapProperty;
import com.intellij.uiDesigner.snapShooter.SnapshotContext;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;

/**
 * @author yole
 */
public class RadBorderLayoutManager extends RadLayoutManager {
  public String getName() {
    return UIFormXmlConstants.LAYOUT_BORDER;
  }

  public LayoutManager createLayout() {
    return new BorderLayout();
  }

  public void writeLayout(final XmlWriter writer, final RadContainer radContainer) {
    BorderLayout layout = (BorderLayout) radContainer.getLayout();
    writer.addAttribute(UIFormXmlConstants.ATTRIBUTE_HGAP, layout.getHgap());
    writer.addAttribute(UIFormXmlConstants.ATTRIBUTE_VGAP, layout.getVgap());
  }

  public void addComponentToContainer(final RadContainer container, final RadComponent component, final int index) {
    if (component.getCustomLayoutConstraints() == null) {
      if (container.getDelegee().getComponentCount() == 0) {
        component.setCustomLayoutConstraints(BorderLayout.CENTER);
      }
      else {
        throw new RuntimeException("can't add component without constraints to container with BorderLayout");
      }
    }
    container.getDelegee().add(component.getDelegee(), component.getCustomLayoutConstraints(), index);
  }

  public void writeChildConstraints(final XmlWriter writer, final RadComponent child) {
    writer.addAttribute(UIFormXmlConstants.ATTRIBUTE_BORDER_CONSTRAINT, (String) child.getCustomLayoutConstraints());
  }

  @NotNull @Override
  public ComponentDropLocation getDropLocation(RadContainer container, final Point location) {
    return new MyDropLocation(container, getQuadrantAt(container, location));
  }

  private static String getQuadrantAt(final RadContainer container, final Point location) {
    if (location == null) {
      return BorderLayout.CENTER;
    }

    Dimension size = container.getDelegee().getSize();
    if (location.x < size.width / 3) {
      return BorderLayout.WEST;
    }
    if (location.y < size.height / 3) {
      return BorderLayout.NORTH;
    }
    if (location.x > size.width * 2 / 3) {
      return BorderLayout.EAST;
    }
    if (location.y > size.height * 2 / 3) {
      return BorderLayout.SOUTH;
    }

    return BorderLayout.CENTER;
  }


  @Override public void changeContainerLayout(RadContainer container) throws IncorrectOperationException {
    ArrayList componentsInBorder = new ArrayList();

    boolean borderHorz = true;
    if (container.getComponentCount() == 1) {
      componentsInBorder.add(container.getComponent(0));
    }
    else if (container.getLayoutManager().isIndexed()) {
      for(RadComponent c: container.getComponents()) {
        if (!(c instanceof RadHSpacer) && !(c instanceof RadVSpacer)) {
          componentsInBorder.add(c);
        }
      }
    }
    else if (container.getLayoutManager().isGrid()) {
      if (container.getGridRowCount() == 1) {
        copyGridLine(container, componentsInBorder, true);
      }
      else if (container.getGridColumnCount() == 1) {
        copyGridLine(container, componentsInBorder, false);
        borderHorz = false;
      }
    }

    if ((container.getComponentCount() > 0 && componentsInBorder.size() == 0) || componentsInBorder.size() > 3) {
      throw new IncorrectOperationException("Component layout is too complex to convert to BorderLayout");
    }

    for(int i=container.getComponentCount()-1; i >= 0; i--) {
      container.removeComponent(container.getComponent(i));
    }

    super.changeContainerLayout(container);

    if (componentsInBorder.size() == 1) {
      componentsInBorder.get(0).setCustomLayoutConstraints(BorderLayout.CENTER);
    }
    else if (componentsInBorder.size() > 1) {
      componentsInBorder.get(0).setCustomLayoutConstraints(borderHorz ? BorderLayout.WEST : BorderLayout.NORTH);
      componentsInBorder.get(1).setCustomLayoutConstraints(BorderLayout.CENTER);
      if (componentsInBorder.size() > 2) {
        componentsInBorder.get(2).setCustomLayoutConstraints(borderHorz ? BorderLayout.EAST : BorderLayout.SOUTH);
      }
    }

    for(RadComponent c: componentsInBorder) {
      container.addComponent(c);
    }
  }

  private static void copyGridLine(final RadContainer container, final ArrayList componentsInBorder, boolean isRow) {
    int cell = 0;
    while(cell < container.getGridCellCount(!isRow)) {
      RadComponent c = container.getComponentAtGrid(isRow, 0, cell);
      if (c == null)
        cell++;
      else {
        if (!(c instanceof RadHSpacer) && !(c instanceof RadVSpacer)) {
          componentsInBorder.add(c);
        }
        cell += c.getConstraints().getSpan(!isRow);
      }
    }
  }

  @Override public Property[] getContainerProperties(final Project project) {
    return new Property[] {
      HGapProperty.getInstance(project),
      VGapProperty.getInstance(project)
    };
  }

  public Property[] getComponentProperties(final Project project, final RadComponent component) {
    return new Property[] {
      BorderSideProperty.INSTANCE
    };
  }

  public boolean canMoveComponent(final RadComponent c, final int rowDelta, final int colDelta, final int rowSpanDelta, final int colSpanDelta) {
    if (rowSpanDelta != 0 || colSpanDelta != 0) {
      return false;
    }
    String side = (String) c.getCustomLayoutConstraints();
    String adjSide = getAdjacentSide(side, rowDelta, colDelta);
    return adjSide != null && c.getParent().findComponentWithConstraints(adjSide) == null;
  }

  public void moveComponent(final RadComponent c, final int rowDelta, final int colDelta, final int rowSpanDelta, final int colSpanDelta) {
    String side = (String) c.getCustomLayoutConstraints();
    String adjSide = getAdjacentSide(side, rowDelta, colDelta);
    if (adjSide != null) {
      c.changeCustomLayoutConstraints(adjSide);
    }
  }

  @Nullable
  private static String getAdjacentSide(final String side, final int rowDelta, final int colDelta) {
    if (rowDelta == -1 && colDelta == 0) {
      return getAdjacentSide(side, BorderLayout.NORTH, BorderLayout.SOUTH);
    }
    if (rowDelta == 1 && colDelta == 0) {
      return getAdjacentSide(side, BorderLayout.SOUTH, BorderLayout.NORTH);
    }
    if (rowDelta == 0 && colDelta == -1) {
      return getAdjacentSide(side, BorderLayout.WEST, BorderLayout.EAST);
    }
    if (rowDelta == 0 && colDelta == 1) {
      return getAdjacentSide(side, BorderLayout.EAST, BorderLayout.WEST);
    }
    return null;
  }

  @Nullable
  private static String getAdjacentSide(final String side, final String toEdge, final String fromEdge) {
    if (side.equals(toEdge)) {
      return null;
    }
    if (side.equals(fromEdge)) {
      return BorderLayout.CENTER;
    }
    return toEdge;
  }

  @Override public void createSnapshotLayout(final SnapshotContext context,
                                             final JComponent parent,
                                             final RadContainer container,
                                             final LayoutManager layout) {
    BorderLayout borderLayout = (BorderLayout) layout;
    container.setLayout(new BorderLayout(borderLayout.getHgap(), borderLayout.getVgap()));
  }

  @Override public void addSnapshotComponent(final JComponent parent,
                                             final JComponent child,
                                             final RadContainer container,
                                             final RadComponent component) {
    BorderLayout borderLayout = (BorderLayout) parent.getLayout();
    final Object constraints = borderLayout.getConstraints(child);
    if (constraints != null) {
      // sometimes the container sets the layout manager to BorderLayout but
      // overrides the layout() method so that the component constraints are not used
      component.setCustomLayoutConstraints(constraints);
      container.addComponent(component);
    }
  }

  private static class MyDropLocation implements ComponentDropLocation {
    private final RadContainer myContainer;
    private final String myQuadrant;

    public MyDropLocation(final RadContainer container, final String quadrant) {
      myQuadrant = quadrant;
      myContainer = container;
    }

    public RadContainer getContainer() {
      return myContainer;
    }

    public boolean canDrop(ComponentDragObject dragObject) {
      return dragObject.getComponentCount() == 1 &&
             ((BorderLayout) myContainer.getLayout()).getLayoutComponent(myQuadrant) == null;
    }

    public void placeFeedback(FeedbackLayer feedbackLayer, ComponentDragObject dragObject) {
      Dimension initialSize = dragObject.getInitialSize(myContainer);
      feedbackLayer.putFeedback(myContainer.getDelegee(), getFeedbackRect(myQuadrant, initialSize),
                                myContainer.getDisplayName() + " (" + myQuadrant.toLowerCase() + ")");
    }

    private Rectangle getFeedbackRect(final String quadrant, final Dimension initialSize) {
      Dimension size = myContainer.getDelegee().getSize();
      int initialWidth = (initialSize.width > 0 && initialSize.width < size.width) ? initialSize.width : size.width/3;
      int initialHeight = (initialSize.height > 0 && initialSize.height < size.height) ? initialSize.height: size.height/3;
      if (quadrant.equals(BorderLayout.WEST)) {
        int deltaN = getHeightAtConstraint(BorderLayout.NORTH);
        int deltaS = getHeightAtConstraint(BorderLayout.SOUTH);
        return new Rectangle(0, deltaN, initialWidth, size.height - deltaN - deltaS);
      }
      if (quadrant.equals(BorderLayout.NORTH)) {
        return new Rectangle(0, 0, size.width, initialHeight);
      }
      if (quadrant.equals(BorderLayout.EAST)) {
        int deltaN = getHeightAtConstraint(BorderLayout.NORTH);
        int deltaS = getHeightAtConstraint(BorderLayout.SOUTH);
        return new Rectangle(size.width - initialWidth, deltaN, initialWidth, size.height - deltaN - deltaS);
      }
      if (quadrant.equals(BorderLayout.SOUTH)) {
        return new Rectangle(0, size.height - initialHeight, size.width, initialHeight);
      }
      return new Rectangle(size.width/3, size.height/3, size.width/3, size.height/3);
    }

    private int getHeightAtConstraint(final String constraint) {
      BorderLayout layout = (BorderLayout) myContainer.getLayout();
      Component c = layout.getLayoutComponent(myContainer.getDelegee(), constraint);
      if (c == null) {
        return 0;
      }
      return c.getBounds().height;
    }

    public void processDrop(GuiEditor editor,
                            RadComponent[] components,
                            GridConstraints[] constraintsToAdjust,
                            ComponentDragObject dragObject) {
      components [0].setCustomLayoutConstraints(myQuadrant);
      myContainer.addComponent(components [0]);
    }

    @Nullable
    public ComponentDropLocation getAdjacentLocation(Direction direction) {
      String side = null;
      switch (direction) {
        case LEFT:
          side = getAdjacentSide(myQuadrant, 0, -1);
          break;
        case UP:
          side = getAdjacentSide(myQuadrant, -1, 0);
          break;
        case RIGHT:
          side = getAdjacentSide(myQuadrant, 0, 1);
          break;
        case DOWN:
          side = getAdjacentSide(myQuadrant, 1, 0);
          break;
      }
      if (side != null) {
        return new MyDropLocation(myContainer, side);
      }
      return null;
    }
  }

  private static class BorderSideProperty extends Property {
    private LabelPropertyRenderer myRenderer = null;
    private BorderSideEditor myEditor = null;

    public static BorderSideProperty INSTANCE = new BorderSideProperty();

    public BorderSideProperty() {
      super(null, "Border Side");
    }

    public String getValue(RadComponent component) {
      return (String) component.getCustomLayoutConstraints();
    }

    protected void setValueImpl(RadComponent component, String value) throws Exception {
      if (!value.equals(component.getCustomLayoutConstraints())) {
        if (component.getParent().findComponentWithConstraints(value) != null) {
          throw new Exception("There is already another component at location " + value);
        }
        component.changeCustomLayoutConstraints(value);
      }
    }

    @NotNull
    public PropertyRenderer getRenderer() {
      if (myRenderer == null) {
        myRenderer = new LabelPropertyRenderer();
      }
      return myRenderer;
    }

    public PropertyEditor getEditor() {
      if (myEditor == null) {
        myEditor = new BorderSideEditor();
      }
      return myEditor;
    }
  }

  private static class BorderSideEditor extends ComboBoxPropertyEditor {
    public BorderSideEditor() {
      String[] sides = new String[] {
        BorderLayout.CENTER, BorderLayout.NORTH, BorderLayout.SOUTH, BorderLayout.WEST, BorderLayout.EAST,
        BorderLayout.PAGE_START, BorderLayout.PAGE_END, BorderLayout.LINE_START, BorderLayout.LINE_END
      };
      myCbx.setModel(new DefaultComboBoxModel(sides));
    }

    public JComponent getComponent(RadComponent component, String value, InplaceContext inplaceContext) {
      myCbx.setSelectedItem(value);
      return myCbx;
    }
  }
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy