Package alm

Source Code of alm.ALMLayout

package alm;

import java.awt.*;
import java.io.*;
import java.util.*;
import java.util.List;

import javax.swing.JComponent;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;

import jaxb.ALMSchema;
import jaxb.ProcessXML;
import linearProgramming.*;

/**
* A GUI layout engine using the ALM.
*/
public class ALMLayout implements LayoutManager {

  /**
   * The specification used for calculating the layout.
   */
  private LayoutSpec layoutSpec;
 
  /**
   * A list of all the components added to the ALM.
   * Will expand when addArea is called and be reduced when
   * layoutComponent is called.
   */
  private List<Component> componentsToAdd;

  /**
   * The manner in which the GUI is dynamically adjusted. The default is to
   * fit the child controls into their parent.
   */
  private LayoutStyleType LayoutStyle = LayoutStyleType.FIT_TO_SIZE;

  boolean recoverlayout = false;
  boolean activated = true;

  protected JComponent parent;

  /**
   * Creates a new layout engine with an empty specification.
   */
  public ALMLayout() throws ALMException {
    super();
    try {
        layoutSpec = new LayoutSpec();
    } catch (LinearProgrammingException e) {
        throw new ALMException("Could not construct ALM Specification.", e);
    }
        componentsToAdd = new ArrayList<Component>();
  }

  /**
   * Creates a new layout engine with the given specification.
   *
   * @param ls
   * the layout specification
   */
  public ALMLayout(LayoutSpec ls) throws ALMException {
      this();
    layoutSpec = ls;
  }

    /**
     * Creates a new layout engine to load a file.
     *
     * @param
     * file a reference to the file to load
     */
    public ALMLayout(File file) throws ALMException {
        this();
        load(file);
    }
   
    /**
     * Creates a new layout engine to load a file from a filename.
     *
     * @param filename
     * the filename of given file
     */
    public ALMLayout(String filename) throws ALMException {
        this();
        load(filename);
    }

  // public boolean layout(object container, LayoutEventArgs layoutEventArgs)
  // {
  // JComponent parent = container as JComponent;
  // layout(parent);
  // return false; // False means that container's parent should not perform
  // layout.
  // }

  /**
   * Calculate and set the layout. If no layout specification is given, a
   * specification is reverse engineered automatically.
   *
   * @param parent
   *            the parent control of the controls in the layout
   */
  public void layout(Container parent) throws LinearProgrammingException {
    // make sure that layout events occuring during layout are ignored
    // i.e. activated is set to false during layout caluclation
    if (!activated)
      return;
    activated = false;

    // reverse engineer a layout specification if requested
    if (recoverlayout) {
      recoverLayout(parent);
      recoverlayout = false;
    }

    // if the layout engine is set to fit the GUI to the given size,
    // then the given size is enforced by setting absolute positions for
    // Right and Bottom
    if (LayoutStyle == LayoutStyleType.FIT_TO_SIZE) {
      layoutSpec.getRight().setRange(parent.getBounds().getWidth(), parent
          .getBounds().getWidth());
      layoutSpec.getBottom().setRange(parent.getBounds().getHeight(), parent
          .getBounds().getHeight());
    }

    layoutSpec.solveLayout();

    // if new layout is infeasible, use previous layout
    if (layoutSpec.getResult() == ResultType.INFEASIBLE) {
      activated = true; // now layout calculation is allowed to run again
      return;
    }
    if (layoutSpec.getResult() != ResultType.OPTIMAL) {
      layoutSpec.save("failed-layout.txt");
      throw new LinearProgrammingException("Could not solve the layout specification ("
          + layoutSpec.getResult().toString()
          + "). Saved specification in file failed-layout.txt");
    }

    // layoutSpec.Save("last-feasible-layout.txt");

    // change the size of the GUI according to the calculated size
    // if the layout engine was configured to do so
    if (LayoutStyle == LayoutStyleType.ADJUST_SIZE) {
      parent.setSize(new Dimension((int) Math
          .round(layoutSpec.getRight().getValue() - layoutSpec.getLeft().getValue()),
          (int) Math.round(layoutSpec.getBottom().getValue()
              - layoutSpec.getTop().getValue())));
    }

    // set the calculated positions and sizes for every area
    for (Area a : layoutSpec.getAreas())
      a.doLayout();

    activated = true; // now layout calculation is allowed to run again
  }

  // #region Editing
  // / <summary>
  // / Indicates whether editing mode is on.
  // / </summary>
  boolean editing = false;

  // / <summary>
  // / List that stores original controls while in edit mode
  // / </summary>
  public List<JComponent> savedControls;

  // / <summary>
  // / Edit form used
  // / </summary>
  public PropertiesWindow editForm;

  public void edit(JComponent parent) throws ALMException {
    layoutContainer(parent);
    activated = false;
    editing = true;
    try {
        layoutSpec.solve();
    } catch (LinearProgrammingException e) {
        throw new ALMException("Could not solve layout.", e);
    }
    savedControls = new ArrayList<JComponent>();
    for (Component control : parent.getComponents()) {
      JComponent c = (JComponent) control;
      savedControls.add(c);
    }
    this.editForm = new PropertiesWindow(parent, this);
    activated = true;
    editForm.setVisible(true);
    editForm.update();
  }

  public void quitEdit(Container parent) {
    editing = false;
    parent.removeAll();
    for (JComponent control : savedControls) {
      parent.add(control);
    }
  }

  /**
   * Reverse engineers the current GUI and recovers an ALM specification.
   */
  public void recoverLayout() {
    recoverlayout = true;
  }
 
  /**
   * Reverse engineers a GUI and recovers an ALM specification.
   *
   * @param parent
   *            the parent container of the GUI
   */
  public void recoverLayout(Container parent) throws LinearProgrammingException {
      layoutSpec = new LayoutSpec();
    TreeMap<Integer, XTab> xtabs = new TreeMap<Integer, XTab>();
    TreeMap<Integer, YTab> ytabs = new TreeMap<Integer, YTab>();

    xtabs.put((int) parent.getBounds().getX(), layoutSpec.getLeft());
    xtabs.put((int) (parent.getBounds().getX() + parent.getBounds()
        .getWidth()), layoutSpec.getRight());
    ytabs.put((int) parent.getBounds().getY(), layoutSpec.getTop());
    ytabs.put((int) (parent.getBounds().getY() + parent.getBounds()
        .getHeight()), layoutSpec.getBottom());

    for (Component c : parent.getComponents()) {
      JComponent cJ = (JComponent) c;
      XTab x1, x2;
      YTab y1, y2;

      if (xtabs.containsKey((int) cJ.getVisibleRect().getX()))
        x1 = xtabs.get((int) cJ.getVisibleRect().getX());
      else
        xtabs.put((int) cJ.getVisibleRect().getX(), x1 = new XTab(
            layoutSpec));
      if (xtabs.containsKey((int) (cJ.getVisibleRect().getX() + cJ
          .getVisibleRect().getWidth())))
        x2 = xtabs.get((int) (cJ.getVisibleRect().getX() + cJ
            .getVisibleRect().getWidth()));
      else
        xtabs.put((int) (cJ.getVisibleRect().getX() + cJ
            .getVisibleRect().getWidth()),
            x2 = new XTab(layoutSpec));
      if (ytabs.containsKey((int) cJ.getVisibleRect().getY()))
        y1 = ytabs.get((int) cJ.getVisibleRect().getY());
      else
        ytabs.put((int) cJ.getVisibleRect().getY(), y1 = new YTab(
            layoutSpec));
      if (ytabs.containsKey((int) (cJ.getVisibleRect().getY() + cJ
          .getVisibleRect().getHeight())))
        y2 = ytabs.get((int) (cJ.getVisibleRect().getY() + cJ
            .getVisibleRect().getHeight()));
      else
        ytabs.put((int) (cJ.getVisibleRect().getY() + cJ
            .getVisibleRect().getHeight()), y2 = new YTab(
            layoutSpec));

      layoutSpec.addArea(x1, y1, x2, y2, cJ);

      x2.leftLink = true;
      y2.topLink = true;
    }

    // adding additional constraints (links in the PO) for margins between
    // areas
    XTab currentXTab = null;
    XTab previousXTab = null;
    int currentXKey = 0;
    int previousXKey = 0;
    Iterator xTabsIterator = xtabs.values().iterator();
    Iterator xKeyIterator = xtabs.keySet().iterator();
    while (xTabsIterator.hasNext()) {
      currentXTab = (XTab) xTabsIterator.next();
      currentXKey = Integer.parseInt(xKeyIterator.next().toString());
      if (!currentXTab.leftLink)
        layoutSpec.addConstraint(-1, previousXTab, 1, currentXTab,
            OperatorType.EQ, -previousXKey + currentXKey);
      previousXTab = currentXTab;
      previousXKey = currentXKey;
    }

    YTab currentYTab = null;
    YTab previousYTab = null;
    int currentYKey = 0;
    int previousYKey = 0;
    Iterator yTabsIterator = ytabs.values().iterator();
    Iterator yKeyIterator = ytabs.keySet().iterator();
    while (yTabsIterator.hasNext()) {
      currentYTab = (YTab) yTabsIterator.next();
      currentYKey = Integer.parseInt(yKeyIterator.next().toString());
      if (!currentYTab.topLink)
        layoutSpec.addConstraint(-1, previousYTab, 1, currentYTab,
            OperatorType.EQ, -previousYKey + currentYKey);
      previousYTab = currentYTab;
      previousYKey = currentYKey;
    }
  }

  // #endregion RE

  public void removeLayoutComponent(Component comp) {
  }

  public void layoutContainer(Container parent) {
    this.parent = (JComponent) parent;
    for (Component c : componentsToAdd) {
        parent.add(c);
    }
    componentsToAdd.clear();
    try {
      layout(parent);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  public void addLayoutComponent(String name, Component comp) {}
  public Dimension minimumLayoutSize(Container parent) {
    return parent.getSize();
  }
  public Dimension preferredLayoutSize(Container parent) {
    return parent.getSize();
  }
    public LayoutSpec getLayoutSpec() {
        return layoutSpec;
    }
    public void setLayoutSpec(LayoutSpec ls) {
        layoutSpec = ls;
    }
   

    public void load(File file) throws ALMException {
        try {
        ProcessXML pro = new ProcessXML(this);
        JAXBContext jc = JAXBContext.newInstance("jaxb");
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        ALMSchema almlayout = (ALMSchema) unmarshaller.unmarshal(file);
        List<ALMSchema.Area> areaList = almlayout.getArea();
        List<ALMSchema.Constraint> constraintList = almlayout.getConstraint();
        for (int i = 0; i < areaList.size(); i++) {
            pro.parseArea(areaList.get(i));
        }
        for (int i = 0; i < constraintList.size(); i++) {
            pro.parseConstraint(constraintList.get(i));
        }
        pro.getNewLayoutSpec().solve();
       } catch (Exception e) {
         throw new ALMException("Could not load "+file.getName()+".", e);
       }
    }
    public void load(String filename) throws ALMException {
        load(new File(filename));
    }
   
    /**
     * Saves the layout configuration to a file
     * @param file
     * the configuration file to save
     */
    public void save(File file) {
        try {
            OutputStream fout = new FileOutputStream(file);
            OutputStream bout = new BufferedOutputStream(fout);
            OutputStreamWriter out = new OutputStreamWriter(bout, "UTF8");

            out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
            out.write("<almlayout>\n");
            out.write("\t<version> 2 </version>\n");

            layoutSpec.writeXML(out);

            out.write("</almlayout>");
            out.flush();
            out.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void save(String filename) {
       save(new File(filename));
    }
   
   
    // Modified wrapper methods for LayoutSpec
    public Area addArea(XTab left, YTab top, XTab right, YTab bottom,
            JComponent content, Dimension minContentSize) {
            componentsToAdd.add(content);
            return layoutSpec.addArea(left, top, right, bottom, content, minContentSize);
    }
    public Area addArea(Row row, Column column, JComponent content,
            Dimension minContentSize) {
            componentsToAdd.add(content);
            return layoutSpec.addArea(row, column, content, minContentSize);
    }
    public Area addArea(XTab left, YTab top, XTab right, YTab bottom,
            JComponent content) throws ALMException {
        try {
            componentsToAdd.add(content);
            return layoutSpec.addArea(left, top, right, bottom, content);
        } catch (LinearProgrammingException e) {
            throw new ALMException("Could not add area to layout.", e);
        }
    }
    public Area addArea(Row row, Column column, JComponent content) throws ALMException {
        componentsToAdd.add(content);
        try {
            return layoutSpec.addArea(row, column, content);
        } catch (LinearProgrammingException e) {
            throw new ALMException("Could not add area to layout.", e);
        }
    }
   
    // Wrapper methods for LayoutSpec
    public XTab addXTab() {
        return layoutSpec.addXTab();
    }
    public YTab addYTab() {
        return layoutSpec.addYTab();
    }
    public Row addRow() {
        return layoutSpec.addRow();
    }
    public Row addRow(YTab top, YTab bottom) throws ALMException {
        try {
            return layoutSpec.addRow(top, bottom);
        } catch (LinearProgrammingException e) {
            throw new ALMException("Cannot add row to layout.", e);
        }
    }
    public Column addColumn() {
        return layoutSpec.addColumn();
    }
    public Column addColumn(XTab left, XTab right) throws ALMException {
        try {
        return layoutSpec.addColumn(left, right);
    } catch (LinearProgrammingException e) {
        throw new ALMException("Cannot add column to layout.", e);
    }
    }
    public Area areaOf(JComponent c) {
        return layoutSpec.areaOf(c);
    }
    public List<Area> getAreas() {
        return layoutSpec.getAreas();
    }
    public List<Row> getRows() {
        return layoutSpec.getRows();
    }
    public List<Column> getColumns() {
        return layoutSpec.getColumns();
    }
    public XTab getLeft() {
        return layoutSpec.getLeft();
    }
    public XTab getRight() {
        return layoutSpec.getRight();
    }
    public YTab getTop() {
        return layoutSpec.getTop();
    }
    public YTab getBottom() {
        return layoutSpec.getBottom();
    }
    public Dimension getMinSize() throws LinearProgrammingException {
        return layoutSpec.getMinSize();
    }
    public Dimension getMaxSize() throws LinearProgrammingException {
        return layoutSpec.getMaxSize();
    }
    public Dimension getPreferredSize() throws LinearProgrammingException {
        return layoutSpec.getPreferredSize();
    }
    public void setMinSize(Dimension minSize) {
        layoutSpec.setMinSize(minSize);
    }
    public void setMaxSize(Dimension maxSize) {
        layoutSpec.setMaxSize(maxSize);
    }
    public void setPreferredSize(Dimension preferredSize) {
        layoutSpec.setPreferredSize(preferredSize);
    }
   
    // Wrapper methods for LinearSpec
    public Constraint addConstraint(Summand[] summands, OperatorType op, double rightSide) throws ALMException {
        try {
            return layoutSpec.addConstraint(summands, op, rightSide);
        } catch (LinearProgrammingException e) {
            throw new ALMException("Could not add constraint to linear specification.", e);
        }
    }
    public Constraint addConstraint(double coeff1, Variable var1, OperatorType op, double rightSide) throws ALMException {
        try {
            return layoutSpec.addConstraint(coeff1, var1, op, rightSide);
        } catch (LinearProgrammingException e) {
            throw new ALMException("Could not add constraint to linear specification.", e);
        }
    }
    public Constraint addConstraint(double coeff1, Variable var1,
            double coeff2, Variable var2, OperatorType op, double rightSide) throws ALMException {
        try {
            return layoutSpec.addConstraint(coeff1, var1, coeff2, var2, op, rightSide);
        } catch (LinearProgrammingException e) {
            throw new ALMException("Could not add constraint to linear specification.", e);
        }
    }
    public Constraint addConstraint(double coeff1, Variable var1,
            double coeff2, Variable var2, double coeff3, Variable var3, OperatorType op, double rightSide) throws ALMException {
        try {
            return layoutSpec.addConstraint(coeff1, var1, coeff2, var2, coeff3, var3,  op, rightSide);
        } catch (LinearProgrammingException e) {
            throw new ALMException("Could not add constraint to linear specification.", e);
        }
    }
    public Constraint addConstraint(double coeff1, Variable var1,
            double coeff2, Variable var2, double coeff3, Variable var3,
            double coeff4, Variable var4, OperatorType op, double rightSide) throws ALMException {
        try {
            return layoutSpec.addConstraint(coeff1, var1, coeff2, var2, coeff3, var3, coeff4, var4, op, rightSide);
        } catch (LinearProgrammingException e) {
            throw new ALMException("Could not add constraint to linear specification.", e);
        }
    }
    public Constraint addConstraint(Summand[] summands, OperatorType op,
            double penaltyNeg, double penaltyPos, double rightSide) throws ALMException  {
        try {
            return layoutSpec.addConstraint(summands, op, penaltyNeg, penaltyPos, rightSide);
        } catch (LinearProgrammingException e) {
            throw new ALMException("Could not add constraint to linear specification.", e);
        }
    }
    public Constraint addConstraint(double coeff1, Variable var1,
            OperatorType op, double rightSide, double penaltyNeg, double penaltyPos) throws ALMException {
        try {
            return layoutSpec.addConstraint(coeff1, var1, op, rightSide, penaltyNeg, penaltyPos);
        } catch (LinearProgrammingException e) {
            throw new ALMException("Could not add constraint to linear specification.", e);
        }
    }
    public Constraint addConstraint(double coeff1, Variable var1, double coeff2, Variable var2,
            OperatorType op, double rightSide, double penaltyNeg, double penaltyPos) throws ALMException {
        try {
            return layoutSpec.addConstraint(coeff1, var1, coeff2, var2, op, rightSide, penaltyNeg, penaltyPos);
        } catch (LinearProgrammingException e) {
            throw new ALMException("Could not add constraint to linear specification.", e);
        }
    }
    public Constraint addConstraint(double coeff1, Variable var1, double coeff2, Variable var2,
            double coeff3, Variable var3, OperatorType op, double rightSide, double penaltyNeg,
            double penaltyPos) throws ALMException {
        try {
            return layoutSpec.addConstraint(coeff1, var1, coeff2, var2, coeff3, var3, op, rightSide, penaltyNeg, penaltyPos);
        } catch (LinearProgrammingException e) {
            throw new ALMException("Could not add constraint to linear specification.", e);
        }
    }
    public Constraint addConstraint(double coeff1, Variable var1, double coeff2, Variable var2,
            double coeff3, Variable var3, double coeff4, Variable var4, OperatorType op,
            double rightSide, double penaltyNeg, double penaltyPos) throws ALMException {
        try {
            return layoutSpec.addConstraint(coeff1, var1, coeff2, var2, coeff3, var3, coeff4, var4, op, rightSide, penaltyNeg, penaltyPos);
        } catch (LinearProgrammingException e) {
            throw new ALMException("Could not add constraint to linear specification.", e);
        }
    }

}

TOP

Related Classes of alm.ALMLayout

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.