diff options
Diffstat (limited to 'src/com/vaadin/ui/GridLayout.java')
-rw-r--r-- | src/com/vaadin/ui/GridLayout.java | 1415 |
1 files changed, 0 insertions, 1415 deletions
diff --git a/src/com/vaadin/ui/GridLayout.java b/src/com/vaadin/ui/GridLayout.java deleted file mode 100644 index 2391a9cd3a..0000000000 --- a/src/com/vaadin/ui/GridLayout.java +++ /dev/null @@ -1,1415 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.io.Serializable; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.Map; -import java.util.Map.Entry; - -import com.vaadin.event.LayoutEvents.LayoutClickEvent; -import com.vaadin.event.LayoutEvents.LayoutClickListener; -import com.vaadin.event.LayoutEvents.LayoutClickNotifier; -import com.vaadin.shared.Connector; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.gridlayout.GridLayoutServerRpc; -import com.vaadin.shared.ui.gridlayout.GridLayoutState; -import com.vaadin.terminal.LegacyPaint; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Vaadin6Component; -import com.vaadin.terminal.gwt.client.ui.LayoutClickEventHandler; - -/** - * A layout where the components are laid out on a grid using cell coordinates. - * - * <p> - * The GridLayout also maintains a cursor for adding components in - * left-to-right, top-to-bottom order. - * </p> - * - * <p> - * Each component in a <code>GridLayout</code> uses a defined - * {@link GridLayout.Area area} (column1,row1,column2,row2) from the grid. The - * components may not overlap with the existing components - if you try to do so - * you will get an {@link OverlapsException}. Adding a component with cursor - * automatically extends the grid by increasing the grid height. - * </p> - * - * <p> - * The grid coordinates, which are specified by a row and column index, always - * start from 0 for the topmost row and the leftmost column. - * </p> - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ -@SuppressWarnings("serial") -public class GridLayout extends AbstractLayout implements - Layout.AlignmentHandler, Layout.SpacingHandler, LayoutClickNotifier, - Vaadin6Component { - - private GridLayoutServerRpc rpc = new GridLayoutServerRpc() { - - @Override - public void layoutClick(MouseEventDetails mouseDetails, - Connector clickedConnector) { - fireEvent(LayoutClickEvent.createEvent(GridLayout.this, - mouseDetails, clickedConnector)); - - } - }; - /** - * Cursor X position: this is where the next component with unspecified x,y - * is inserted - */ - private int cursorX = 0; - - /** - * Cursor Y position: this is where the next component with unspecified x,y - * is inserted - */ - private int cursorY = 0; - - /** - * Contains all items that are placed on the grid. These are components with - * grid area definition. - */ - private final LinkedList<Area> areas = new LinkedList<Area>(); - - /** - * Mapping from components to their respective areas. - */ - private final LinkedList<Component> components = new LinkedList<Component>(); - - /** - * Mapping from components to alignments (horizontal + vertical). - */ - private Map<Component, Alignment> componentToAlignment = new HashMap<Component, Alignment>(); - - private static final Alignment ALIGNMENT_DEFAULT = Alignment.TOP_LEFT; - - /** - * Has there been rows inserted or deleted in the middle of the layout since - * the last paint operation. - */ - private boolean structuralChange = false; - - private Map<Integer, Float> columnExpandRatio = new HashMap<Integer, Float>(); - private Map<Integer, Float> rowExpandRatio = new HashMap<Integer, Float>(); - - /** - * Constructor for a grid of given size (number of columns and rows). - * - * The grid may grow or shrink later. Grid grows automatically if you add - * components outside its area. - * - * @param columns - * Number of columns in the grid. - * @param rows - * Number of rows in the grid. - */ - public GridLayout(int columns, int rows) { - setColumns(columns); - setRows(rows); - registerRpc(rpc); - } - - /** - * Constructs an empty (1x1) grid layout that is extended as needed. - */ - public GridLayout() { - this(1, 1); - } - - @Override - public GridLayoutState getState() { - return (GridLayoutState) super.getState(); - } - - /** - * <p> - * Adds a component to the grid in the specified area. The area is defined - * by specifying the upper left corner (column1, row1) and the lower right - * corner (column2, row2) of the area. The coordinates are zero-based. - * </p> - * - * <p> - * If the area overlaps with any of the existing components already present - * in the grid, the operation will fail and an {@link OverlapsException} is - * thrown. - * </p> - * - * @param component - * the component to be added. - * @param column1 - * the column of the upper left corner of the area <code>c</code> - * is supposed to occupy. The leftmost column has index 0. - * @param row1 - * the row of the upper left corner of the area <code>c</code> is - * supposed to occupy. The topmost row has index 0. - * @param column2 - * the column of the lower right corner of the area - * <code>c</code> is supposed to occupy. - * @param row2 - * the row of the lower right corner of the area <code>c</code> - * is supposed to occupy. - * @throws OverlapsException - * if the new component overlaps with any of the components - * already in the grid. - * @throws OutOfBoundsException - * if the cells are outside the grid area. - */ - public void addComponent(Component component, int column1, int row1, - int column2, int row2) throws OverlapsException, - OutOfBoundsException { - - if (component == null) { - throw new NullPointerException("Component must not be null"); - } - - // Checks that the component does not already exist in the container - if (components.contains(component)) { - throw new IllegalArgumentException( - "Component is already in the container"); - } - - // Creates the area - final Area area = new Area(component, column1, row1, column2, row2); - - // Checks the validity of the coordinates - if (column2 < column1 || row2 < row1) { - throw new IllegalArgumentException( - "Illegal coordinates for the component"); - } - if (column1 < 0 || row1 < 0 || column2 >= getColumns() - || row2 >= getRows()) { - throw new OutOfBoundsException(area); - } - - // Checks that newItem does not overlap with existing items - checkExistingOverlaps(area); - - // Inserts the component to right place at the list - // Respect top-down, left-right ordering - // component.setParent(this); - final Iterator<Area> i = areas.iterator(); - int index = 0; - boolean done = false; - while (!done && i.hasNext()) { - final Area existingArea = i.next(); - if ((existingArea.row1 >= row1 && existingArea.column1 > column1) - || existingArea.row1 > row1) { - areas.add(index, area); - components.add(index, component); - done = true; - } - index++; - } - if (!done) { - areas.addLast(area); - components.addLast(component); - } - - // Attempt to add to super - try { - super.addComponent(component); - } catch (IllegalArgumentException e) { - areas.remove(area); - components.remove(component); - throw e; - } - - // update cursor position, if it's within this area; use first position - // outside this area, even if it's occupied - if (cursorX >= column1 && cursorX <= column2 && cursorY >= row1 - && cursorY <= row2) { - // cursor within area - cursorX = column2 + 1; // one right of area - if (cursorX >= getColumns()) { - // overflowed columns - cursorX = 0; // first col - // move one row down, or one row under the area - cursorY = (column1 == 0 ? row2 : row1) + 1; - } else { - cursorY = row1; - } - } - - requestRepaint(); - } - - /** - * Tests if the given area overlaps with any of the items already on the - * grid. - * - * @param area - * the Area to be checked for overlapping. - * @throws OverlapsException - * if <code>area</code> overlaps with any existing area. - */ - private void checkExistingOverlaps(Area area) throws OverlapsException { - for (final Iterator<Area> i = areas.iterator(); i.hasNext();) { - final Area existingArea = i.next(); - if (existingArea.overlaps(area)) { - // Component not added, overlaps with existing component - throw new OverlapsException(existingArea); - } - } - } - - /** - * Adds the component to the grid in cells column1,row1 (NortWest corner of - * the area.) End coordinates (SouthEast corner of the area) are the same as - * column1,row1. The coordinates are zero-based. Component width and height - * is 1. - * - * @param component - * the component to be added. - * @param column - * the column index, starting from 0. - * @param row - * the row index, starting from 0. - * @throws OverlapsException - * if the new component overlaps with any of the components - * already in the grid. - * @throws OutOfBoundsException - * if the cell is outside the grid area. - */ - public void addComponent(Component component, int column, int row) - throws OverlapsException, OutOfBoundsException { - this.addComponent(component, column, row, column, row); - } - - /** - * Forces the next component to be added at the beginning of the next line. - * - * <p> - * Sets the cursor column to 0 and increments the cursor row by one. - * </p> - * - * <p> - * By calling this function you can ensure that no more components are added - * right of the previous component. - * </p> - * - * @see #space() - */ - public void newLine() { - cursorX = 0; - cursorY++; - } - - /** - * Moves the cursor forward by one. If the cursor goes out of the right grid - * border, it is moved to the first column of the next row. - * - * @see #newLine() - */ - public void space() { - cursorX++; - if (cursorX >= getColumns()) { - cursorX = 0; - cursorY++; - } - } - - /** - * Adds the component into this container to the cursor position. If the - * cursor position is already occupied, the cursor is moved forwards to find - * free position. If the cursor goes out from the bottom of the grid, the - * grid is automatically extended. - * - * @param component - * the component to be added. - */ - @Override - public void addComponent(Component component) { - - // Finds first available place from the grid - Area area; - boolean done = false; - while (!done) { - try { - area = new Area(component, cursorX, cursorY, cursorX, cursorY); - checkExistingOverlaps(area); - done = true; - } catch (final OverlapsException e) { - space(); - } - } - - // Extends the grid if needed - if (cursorX >= getColumns()) { - setColumns(cursorX + 1); - } - if (cursorY >= getRows()) { - setRows(cursorY + 1); - } - - addComponent(component, cursorX, cursorY); - } - - /** - * Removes the specified component from the layout. - * - * @param component - * the component to be removed. - */ - @Override - public void removeComponent(Component component) { - - // Check that the component is contained in the container - if (component == null || !components.contains(component)) { - return; - } - - Area area = null; - for (final Iterator<Area> i = areas.iterator(); area == null - && i.hasNext();) { - final Area a = i.next(); - if (a.getComponent() == component) { - area = a; - } - } - - components.remove(component); - if (area != null) { - areas.remove(area); - } - - componentToAlignment.remove(component); - - super.removeComponent(component); - - requestRepaint(); - } - - /** - * Removes the component specified by its cell coordinates. - * - * @param column - * the component's column, starting from 0. - * @param row - * the component's row, starting from 0. - */ - public void removeComponent(int column, int row) { - - // Finds the area - for (final Iterator<Area> i = areas.iterator(); i.hasNext();) { - final Area area = i.next(); - if (area.getColumn1() == column && area.getRow1() == row) { - removeComponent(area.getComponent()); - return; - } - } - } - - /** - * Gets an Iterator for the components contained in the layout. By using the - * Iterator it is possible to step through the contents of the layout. - * - * @return the Iterator of the components inside the layout. - */ - @Override - public Iterator<Component> getComponentIterator() { - return Collections.unmodifiableCollection(components).iterator(); - } - - /** - * Gets the number of components contained in the layout. Consistent with - * the iterator returned by {@link #getComponentIterator()}. - * - * @return the number of contained components - */ - @Override - public int getComponentCount() { - return components.size(); - } - - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - // TODO Remove once Vaadin6Component is no longer implemented - } - - /** - * Paints the contents of this component. - * - * @param target - * the Paint Event. - * @throws PaintException - * if the paint operation failed. - */ - @Override - public void paintContent(PaintTarget target) throws PaintException { - // TODO refactor attribute names in future release. - target.addAttribute("structuralChange", structuralChange); - structuralChange = false; - - // Area iterator - final Iterator<Area> areaiterator = areas.iterator(); - - // Current item to be processed (fetch first item) - Area area = areaiterator.hasNext() ? (Area) areaiterator.next() : null; - - // Collects rowspan related information here - final HashMap<Integer, Integer> cellUsed = new HashMap<Integer, Integer>(); - - // Empty cell collector - int emptyCells = 0; - - final String[] alignmentsArray = new String[components.size()]; - final Integer[] columnExpandRatioArray = new Integer[getColumns()]; - final Integer[] rowExpandRatioArray = new Integer[getRows()]; - - int realColExpandRatioSum = 0; - float colSum = getExpandRatioSum(columnExpandRatio); - if (colSum == 0) { - // no columns has been expanded, all cols have same expand - // rate - float equalSize = 1 / (float) getColumns(); - int myRatio = Math.round(equalSize * 1000); - for (int i = 0; i < getColumns(); i++) { - columnExpandRatioArray[i] = myRatio; - } - realColExpandRatioSum = myRatio * getColumns(); - } else { - for (int i = 0; i < getColumns(); i++) { - int myRatio = Math - .round((getColumnExpandRatio(i) / colSum) * 1000); - columnExpandRatioArray[i] = myRatio; - realColExpandRatioSum += myRatio; - } - } - - boolean equallyDividedRows = false; - int realRowExpandRatioSum = 0; - float rowSum = getExpandRatioSum(rowExpandRatio); - if (rowSum == 0) { - // no rows have been expanded - equallyDividedRows = true; - float equalSize = 1 / (float) getRows(); - int myRatio = Math.round(equalSize * 1000); - for (int i = 0; i < getRows(); i++) { - rowExpandRatioArray[i] = myRatio; - } - realRowExpandRatioSum = myRatio * getRows(); - } - - int index = 0; - - // Iterates every applicable row - for (int cury = 0; cury < getRows(); cury++) { - target.startTag("gr"); - - if (!equallyDividedRows) { - int myRatio = Math - .round((getRowExpandRatio(cury) / rowSum) * 1000); - rowExpandRatioArray[cury] = myRatio; - realRowExpandRatioSum += myRatio; - - } - // Iterates every applicable column - for (int curx = 0; curx < getColumns(); curx++) { - - // Checks if current item is located at curx,cury - if (area != null && (area.row1 == cury) - && (area.column1 == curx)) { - - // First check if empty cell needs to be rendered - if (emptyCells > 0) { - target.startTag("gc"); - target.addAttribute("x", curx - emptyCells); - target.addAttribute("y", cury); - if (emptyCells > 1) { - target.addAttribute("w", emptyCells); - } - target.endTag("gc"); - emptyCells = 0; - } - - // Now proceed rendering current item - final int cols = (area.column2 - area.column1) + 1; - final int rows = (area.row2 - area.row1) + 1; - target.startTag("gc"); - - target.addAttribute("x", curx); - target.addAttribute("y", cury); - - if (cols > 1) { - target.addAttribute("w", cols); - } - if (rows > 1) { - target.addAttribute("h", rows); - } - LegacyPaint.paint(area.getComponent(), target); - - alignmentsArray[index++] = String - .valueOf(getComponentAlignment(area.getComponent()) - .getBitMask()); - - target.endTag("gc"); - - // Fetch next item - if (areaiterator.hasNext()) { - area = areaiterator.next(); - } else { - area = null; - } - - // Updates the cellUsed if rowspan needed - if (rows > 1) { - int spannedx = curx; - for (int j = 1; j <= cols; j++) { - cellUsed.put(new Integer(spannedx), new Integer( - cury + rows - 1)); - spannedx++; - } - } - - // Skips the current item's spanned columns - if (cols > 1) { - curx += cols - 1; - } - - } else { - - // Checks against cellUsed, render space or ignore cell - if (cellUsed.containsKey(new Integer(curx))) { - - // Current column contains already an item, - // check if rowspan affects at current x,y position - final int rowspanDepth = cellUsed - .get(new Integer(curx)).intValue(); - - if (rowspanDepth >= cury) { - - // ignore cell - // Check if empty cell needs to be rendered - if (emptyCells > 0) { - target.startTag("gc"); - target.addAttribute("x", curx - emptyCells); - target.addAttribute("y", cury); - if (emptyCells > 1) { - target.addAttribute("w", emptyCells); - } - target.endTag("gc"); - - emptyCells = 0; - } - } else { - - // empty cell is needed - emptyCells++; - - // Removes the cellUsed key as it has become - // obsolete - cellUsed.remove(Integer.valueOf(curx)); - } - } else { - - // empty cell is needed - emptyCells++; - } - } - - } // iterates every column - - // Last column handled of current row - - // Checks if empty cell needs to be rendered - if (emptyCells > 0) { - target.startTag("gc"); - target.addAttribute("x", getColumns() - emptyCells); - target.addAttribute("y", cury); - if (emptyCells > 1) { - target.addAttribute("w", emptyCells); - } - target.endTag("gc"); - - emptyCells = 0; - } - - target.endTag("gr"); - } // iterates every row - - // Last row handled - - // correct possible rounding error - if (rowExpandRatioArray.length > 0) { - rowExpandRatioArray[0] -= realRowExpandRatioSum - 1000; - } - if (columnExpandRatioArray.length > 0) { - columnExpandRatioArray[0] -= realColExpandRatioSum - 1000; - } - - target.addAttribute("colExpand", columnExpandRatioArray); - target.addAttribute("rowExpand", rowExpandRatioArray); - - // Add child component alignment info to layout tag - target.addAttribute("alignments", alignmentsArray); - - } - - private float getExpandRatioSum(Map<Integer, Float> ratioMap) { - float sum = 0; - for (Iterator<Entry<Integer, Float>> iterator = ratioMap.entrySet() - .iterator(); iterator.hasNext();) { - sum += iterator.next().getValue(); - } - return sum; - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Layout.AlignmentHandler#getComponentAlignment(com - * .vaadin.ui.Component) - */ - @Override - public Alignment getComponentAlignment(Component childComponent) { - Alignment alignment = componentToAlignment.get(childComponent); - if (alignment == null) { - return ALIGNMENT_DEFAULT; - } else { - return alignment; - } - } - - /** - * Defines a rectangular area of cells in a GridLayout. - * - * <p> - * Also maintains a reference to the component contained in the area. - * </p> - * - * <p> - * The area is specified by the cell coordinates of its upper left corner - * (column1,row1) and lower right corner (column2,row2). As otherwise with - * GridLayout, the column and row coordinates start from zero. - * </p> - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class Area implements Serializable { - - /** - * The column of the upper left corner cell of the area. - */ - private final int column1; - - /** - * The row of the upper left corner cell of the area. - */ - private int row1; - - /** - * The column of the lower right corner cell of the area. - */ - private final int column2; - - /** - * The row of the lower right corner cell of the area. - */ - private int row2; - - /** - * Component painted in the area. - */ - private Component component; - - /** - * <p> - * Construct a new area on a grid. - * </p> - * - * @param component - * the component connected to the area. - * @param column1 - * The column of the upper left corner cell of the area. The - * leftmost column has index 0. - * @param row1 - * The row of the upper left corner cell of the area. The - * topmost row has index 0. - * @param column2 - * The column of the lower right corner cell of the area. The - * leftmost column has index 0. - * @param row2 - * The row of the lower right corner cell of the area. The - * topmost row has index 0. - */ - public Area(Component component, int column1, int row1, int column2, - int row2) { - this.column1 = column1; - this.row1 = row1; - this.column2 = column2; - this.row2 = row2; - this.component = component; - } - - /** - * Tests if this Area overlaps with another Area. - * - * @param other - * the other Area that is to be tested for overlap with this - * area - * @return <code>true</code> if <code>other</code> area overlaps with - * this on, <code>false</code> if it does not. - */ - public boolean overlaps(Area other) { - return column1 <= other.getColumn2() && row1 <= other.getRow2() - && column2 >= other.getColumn1() && row2 >= other.getRow1(); - - } - - /** - * Gets the component connected to the area. - * - * @return the Component. - */ - public Component getComponent() { - return component; - } - - /** - * Sets the component connected to the area. - * - * <p> - * This function only sets the value in the data structure and does not - * send any events or set parents. - * </p> - * - * @param newComponent - * the new connected overriding the existing one. - */ - protected void setComponent(Component newComponent) { - component = newComponent; - } - - /** - * @deprecated Use {@link #getColumn1()} instead. - */ - @Deprecated - public int getX1() { - return getColumn1(); - } - - /** - * Gets the column of the top-left corner cell. - * - * @return the column of the top-left corner cell. - */ - public int getColumn1() { - return column1; - } - - /** - * @deprecated Use {@link #getColumn2()} instead. - */ - @Deprecated - public int getX2() { - return getColumn2(); - } - - /** - * Gets the column of the bottom-right corner cell. - * - * @return the column of the bottom-right corner cell. - */ - public int getColumn2() { - return column2; - } - - /** - * @deprecated Use {@link #getRow1()} instead. - */ - @Deprecated - public int getY1() { - return getRow1(); - } - - /** - * Gets the row of the top-left corner cell. - * - * @return the row of the top-left corner cell. - */ - public int getRow1() { - return row1; - } - - /** - * @deprecated Use {@link #getRow2()} instead. - */ - @Deprecated - public int getY2() { - return getRow2(); - } - - /** - * Gets the row of the bottom-right corner cell. - * - * @return the row of the bottom-right corner cell. - */ - public int getRow2() { - return row2; - } - - } - - /** - * Gridlayout does not support laying components on top of each other. An - * <code>OverlapsException</code> is thrown when a component already exists - * (even partly) at the same space on a grid with the new component. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class OverlapsException extends java.lang.RuntimeException { - - private final Area existingArea; - - /** - * Constructs an <code>OverlapsException</code>. - * - * @param existingArea - */ - public OverlapsException(Area existingArea) { - this.existingArea = existingArea; - } - - @Override - public String getMessage() { - StringBuilder sb = new StringBuilder(); - Component component = existingArea.getComponent(); - sb.append(component); - sb.append("( type = "); - sb.append(component.getClass().getName()); - if (component.getCaption() != null) { - sb.append(", caption = \""); - sb.append(component.getCaption()); - sb.append("\""); - } - sb.append(")"); - sb.append(" is already added to "); - sb.append(existingArea.column1); - sb.append(","); - sb.append(existingArea.column1); - sb.append(","); - sb.append(existingArea.row1); - sb.append(","); - sb.append(existingArea.row2); - sb.append("(column1, column2, row1, row2)."); - - return sb.toString(); - } - - /** - * Gets the area . - * - * @return the existing area. - */ - public Area getArea() { - return existingArea; - } - } - - /** - * An <code>Exception</code> object which is thrown when an area exceeds the - * bounds of the grid. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class OutOfBoundsException extends java.lang.RuntimeException { - - private final Area areaOutOfBounds; - - /** - * Constructs an <code>OoutOfBoundsException</code> with the specified - * detail message. - * - * @param areaOutOfBounds - */ - public OutOfBoundsException(Area areaOutOfBounds) { - this.areaOutOfBounds = areaOutOfBounds; - } - - /** - * Gets the area that is out of bounds. - * - * @return the area out of Bound. - */ - public Area getArea() { - return areaOutOfBounds; - } - } - - /** - * Sets the number of columns in the grid. The column count can not be - * reduced if there are any areas that would be outside of the shrunk grid. - * - * @param columns - * the new number of columns in the grid. - */ - public void setColumns(int columns) { - - // The the param - if (columns < 1) { - throw new IllegalArgumentException( - "The number of columns and rows in the grid must be at least 1"); - } - - // In case of no change - if (getColumns() == columns) { - return; - } - - // Checks for overlaps - if (getColumns() > columns) { - for (final Iterator<Area> i = areas.iterator(); i.hasNext();) { - final Area area = i.next(); - if (area.column2 >= columns) { - throw new OutOfBoundsException(area); - } - } - } - - getState().setColumns(columns); - - requestRepaint(); - } - - /** - * Get the number of columns in the grid. - * - * @return the number of columns in the grid. - */ - public int getColumns() { - return getState().getColumns(); - } - - /** - * Sets the number of rows in the grid. The number of rows can not be - * reduced if there are any areas that would be outside of the shrunk grid. - * - * @param rows - * the new number of rows in the grid. - */ - public void setRows(int rows) { - - // The the param - if (rows < 1) { - throw new IllegalArgumentException( - "The number of columns and rows in the grid must be at least 1"); - } - - // In case of no change - if (getRows() == rows) { - return; - } - - // Checks for overlaps - if (getRows() > rows) { - for (final Iterator<Area> i = areas.iterator(); i.hasNext();) { - final Area area = i.next(); - if (area.row2 >= rows) { - throw new OutOfBoundsException(area); - } - } - } - - getState().setRows(rows); - - requestRepaint(); - } - - /** - * Get the number of rows in the grid. - * - * @return the number of rows in the grid. - */ - public int getRows() { - return getState().getRows(); - } - - /** - * Gets the current x-position (column) of the cursor. - * - * <p> - * The cursor position points the position for the next component that is - * added without specifying its coordinates (grid cell). When the cursor - * position is occupied, the next component will be added to first free - * position after the cursor. - * </p> - * - * @return the grid column the cursor is on, starting from 0. - */ - public int getCursorX() { - return cursorX; - } - - /** - * Sets the current cursor x-position. This is usually handled automatically - * by GridLayout. - * - * @param cursorX - */ - public void setCursorX(int cursorX) { - this.cursorX = cursorX; - } - - /** - * Gets the current y-position (row) of the cursor. - * - * <p> - * The cursor position points the position for the next component that is - * added without specifying its coordinates (grid cell). When the cursor - * position is occupied, the next component will be added to the first free - * position after the cursor. - * </p> - * - * @return the grid row the Cursor is on. - */ - public int getCursorY() { - return cursorY; - } - - /** - * Sets the current y-coordinate (row) of the cursor. This is usually - * handled automatically by GridLayout. - * - * @param cursorY - * the row number, starting from 0 for the topmost row. - */ - public void setCursorY(int cursorY) { - this.cursorY = cursorY; - } - - /* Documented in superclass */ - @Override - public void replaceComponent(Component oldComponent, Component newComponent) { - - // Gets the locations - Area oldLocation = null; - Area newLocation = null; - for (final Iterator<Area> i = areas.iterator(); i.hasNext();) { - final Area location = i.next(); - final Component component = location.getComponent(); - if (component == oldComponent) { - oldLocation = location; - } - if (component == newComponent) { - newLocation = location; - } - } - - if (oldLocation == null) { - addComponent(newComponent); - } else if (newLocation == null) { - removeComponent(oldComponent); - addComponent(newComponent, oldLocation.getColumn1(), - oldLocation.getRow1(), oldLocation.getColumn2(), - oldLocation.getRow2()); - } else { - oldLocation.setComponent(newComponent); - newLocation.setComponent(oldComponent); - requestRepaint(); - } - } - - /* - * Removes all components from this container. - * - * @see com.vaadin.ui.ComponentContainer#removeAllComponents() - */ - @Override - public void removeAllComponents() { - super.removeAllComponents(); - componentToAlignment = new HashMap<Component, Alignment>(); - cursorX = 0; - cursorY = 0; - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Layout.AlignmentHandler#setComponentAlignment(com - * .vaadin.ui.Component, int, int) - */ - @Override - public void setComponentAlignment(Component childComponent, - int horizontalAlignment, int verticalAlignment) { - componentToAlignment.put(childComponent, new Alignment( - horizontalAlignment + verticalAlignment)); - requestRepaint(); - } - - @Override - public void setComponentAlignment(Component childComponent, - Alignment alignment) { - componentToAlignment.put(childComponent, alignment); - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Layout.SpacingHandler#setSpacing(boolean) - */ - @Override - public void setSpacing(boolean spacing) { - getState().setSpacing(spacing); - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Layout.SpacingHandler#isSpacing() - */ - @Override - public boolean isSpacing() { - return getState().isSpacing(); - } - - /** - * Inserts an empty row at the specified position in the grid. - * - * @param row - * Index of the row before which the new row will be inserted. - * The leftmost row has index 0. - */ - public void insertRow(int row) { - if (row > getRows()) { - throw new IllegalArgumentException("Cannot insert row at " + row - + " in a gridlayout with height " + getRows()); - } - - for (Iterator<Area> i = areas.iterator(); i.hasNext();) { - Area existingArea = i.next(); - // Areas ending below the row needs to be moved down or stretched - if (existingArea.row2 >= row) { - existingArea.row2++; - - // Stretch areas that span over the selected row - if (existingArea.row1 >= row) { - existingArea.row1++; - } - - } - } - - if (cursorY >= row) { - cursorY++; - } - - setRows(getRows() + 1); - structuralChange = true; - requestRepaint(); - } - - /** - * Removes a row and all the components in the row. - * - * <p> - * Components which span over several rows are removed if the selected row - * is on the first row of such a component. - * </p> - * - * <p> - * If the last row is removed then all remaining components will be removed - * and the grid will be reduced to one row. The cursor will be moved to the - * upper left cell of the grid. - * </p> - * - * @param row - * Index of the row to remove. The leftmost row has index 0. - */ - public void removeRow(int row) { - if (row >= getRows()) { - throw new IllegalArgumentException("Cannot delete row " + row - + " from a gridlayout with height " + getRows()); - } - - // Remove all components in row - for (int col = 0; col < getColumns(); col++) { - removeComponent(col, row); - } - - // Shrink or remove areas in the selected row - for (Iterator<Area> i = areas.iterator(); i.hasNext();) { - Area existingArea = i.next(); - if (existingArea.row2 >= row) { - existingArea.row2--; - - if (existingArea.row1 > row) { - existingArea.row1--; - } - } - } - - if (getRows() == 1) { - /* - * Removing the last row means that the dimensions of the Grid - * layout will be truncated to 1 empty row and the cursor is moved - * to the first cell - */ - cursorX = 0; - cursorY = 0; - } else { - setRows(getRows() - 1); - if (cursorY > row) { - cursorY--; - } - } - - structuralChange = true; - requestRepaint(); - - } - - /** - * Sets the expand ratio of given column. - * - * <p> - * The expand ratio defines how excess space is distributed among columns. - * Excess space means space that is left over from components that are not - * sized relatively. By default, the excess space is distributed evenly. - * </p> - * - * <p> - * Note that the component width of the GridLayout must be defined (fixed or - * relative, as opposed to undefined) for this method to have any effect. - * </p> - * - * @see #setWidth(float, int) - * - * @param columnIndex - * @param ratio - */ - public void setColumnExpandRatio(int columnIndex, float ratio) { - columnExpandRatio.put(columnIndex, ratio); - requestRepaint(); - } - - /** - * Returns the expand ratio of given column - * - * @see #setColumnExpandRatio(int, float) - * - * @param columnIndex - * @return the expand ratio, 0.0f by default - */ - public float getColumnExpandRatio(int columnIndex) { - Float r = columnExpandRatio.get(columnIndex); - return r == null ? 0 : r.floatValue(); - } - - /** - * Sets the expand ratio of given row. - * - * <p> - * Expand ratio defines how excess space is distributed among rows. Excess - * space means the space left over from components that are not sized - * relatively. By default, the excess space is distributed evenly. - * </p> - * - * <p> - * Note, that height needs to be defined (fixed or relative, as opposed to - * undefined height) for this method to have any effect. - * </p> - * - * @see #setHeight(float, int) - * - * @param rowIndex - * The row index, starting from 0 for the topmost row. - * @param ratio - */ - public void setRowExpandRatio(int rowIndex, float ratio) { - rowExpandRatio.put(rowIndex, ratio); - requestRepaint(); - } - - /** - * Returns the expand ratio of given row. - * - * @see #setRowExpandRatio(int, float) - * - * @param rowIndex - * The row index, starting from 0 for the topmost row. - * @return the expand ratio, 0.0f by default - */ - public float getRowExpandRatio(int rowIndex) { - Float r = rowExpandRatio.get(rowIndex); - return r == null ? 0 : r.floatValue(); - } - - /** - * Gets the Component at given index. - * - * @param x - * The column index, starting from 0 for the leftmost column. - * @param y - * The row index, starting from 0 for the topmost row. - * @return Component in given cell or null if empty - */ - public Component getComponent(int x, int y) { - for (final Iterator<Area> iterator = areas.iterator(); iterator - .hasNext();) { - final Area area = iterator.next(); - if (area.getColumn1() <= x && x <= area.getColumn2() - && area.getRow1() <= y && y <= area.getRow2()) { - return area.getComponent(); - } - } - return null; - } - - /** - * Returns information about the area where given component is laid in the - * GridLayout. - * - * @param component - * the component whose area information is requested. - * @return an Area object that contains information how component is laid in - * the grid - */ - public Area getComponentArea(Component component) { - for (final Iterator<Area> iterator = areas.iterator(); iterator - .hasNext();) { - final Area area = iterator.next(); - if (area.getComponent() == component) { - return area; - } - } - return null; - } - - @Override - public void addListener(LayoutClickListener listener) { - addListener(LayoutClickEventHandler.LAYOUT_CLICK_EVENT_IDENTIFIER, - LayoutClickEvent.class, listener, - LayoutClickListener.clickMethod); - } - - @Override - public void removeListener(LayoutClickListener listener) { - removeListener(LayoutClickEventHandler.LAYOUT_CLICK_EVENT_IDENTIFIER, - LayoutClickEvent.class, listener); - } - -} |