You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pivot.apache.org by tv...@apache.org on 2009/03/16 17:16:58 UTC
svn commit: r754926 [28/38] - in /incubator/pivot/tags/v1.0: ./ charts-test/
charts-test/src/ charts-test/src/pivot/ charts-test/src/pivot/charts/
charts-test/src/pivot/charts/test/ charts/ charts/lib/ charts/src/
charts/src/pivot/ charts/src/pivot/cha...
Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/TablePaneSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/TablePaneSkin.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/TablePaneSkin.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/TablePaneSkin.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,1384 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * 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 pivot.wtk.skin;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.geom.Area;
+import java.awt.geom.Rectangle2D;
+
+import pivot.collections.Dictionary;
+import pivot.collections.Sequence;
+import pivot.wtk.Component;
+import pivot.wtk.Dimensions;
+import pivot.wtk.Insets;
+import pivot.wtk.Bounds;
+import pivot.wtk.TablePane;
+import pivot.wtk.TablePaneListener;
+import pivot.wtk.TablePaneAttributeListener;
+
+/**
+ * Table pane skin.
+ *
+ * @author tvolkert
+ */
+public class TablePaneSkin extends ContainerSkin implements TablePane.Skin,
+ TablePaneListener, TablePaneAttributeListener {
+ private Insets padding = DEFAULT_PADDING;
+ private int horizontalSpacing = 0;
+ private int verticalSpacing = 0;
+ private boolean showHorizontalGridLines = false;
+ private boolean showVerticalGridLines = false;
+ private Color gridColor = Color.BLACK;
+ private Color selectionBackgroundColor = Color.GRAY;
+
+ private static final Insets DEFAULT_PADDING = new Insets(0);
+
+ private int[] columnWidths = null;
+ private int[] rowHeights = null;
+
+ @Override
+ public void install(Component component) {
+ super.install(component);
+
+ TablePane tablePane = (TablePane)component;
+ tablePane.getTablePaneListeners().add(this);
+ tablePane.getTablePaneAttributeListeners().add(this);
+ }
+
+ @Override
+ public void uninstall() {
+ TablePane tablePane = (TablePane)getComponent();
+ tablePane.getTablePaneListeners().remove(this);
+ tablePane.getTablePaneAttributeListeners().remove(this);
+
+ super.uninstall();
+ }
+
+ @Override
+ public int getPreferredWidth(int height) {
+ TablePane tablePane = (TablePane)getComponent();
+ TablePane.RowSequence rows = tablePane.getRows();
+ TablePane.ColumnSequence columns = tablePane.getColumns();
+
+ int rowCount = rows.getLength();
+ int columnCount = columns.getLength();
+
+ int[] columnWidths = new int[columnCount];
+ int[] relativeWeights = new int[columnCount];
+ boolean[] defaultWidthColumns = new boolean[columnCount];
+
+ int totalRelativeWeight = 0;
+
+ // First, we calculate the base widths of the columns, giving relative
+ // columns their preferred width
+
+ for (int i = 0; i < columnCount; i++) {
+ TablePane.Column column = columns.get(i);
+ int columnWidth = column.getWidth();
+ boolean isRelative = column.isRelative();
+
+ if (isRelative) {
+ relativeWeights[i] = columnWidth;
+ totalRelativeWeight += columnWidth;
+ }
+
+ if (columnWidth < 0 || isRelative) {
+ columnWidth = getPreferredColumnWidth(tablePane, i, null);
+ }
+
+ columnWidths[i] = columnWidth;
+ defaultWidthColumns[i] = (columnWidth < 0);
+ }
+
+ // Next, we adjust the widths of the relative columns upwards where
+ // necessary to reconcile their widths relative to one another while
+ // ensuring that they still get at least their preferred width
+
+ if (totalRelativeWeight > 0) {
+ int totalRelativeWidth = 0;
+
+ // Calculate the total relative width after the required upward
+ // adjustments
+
+ for (int i = 0; i < columnCount; i++) {
+ int columnWidth = columnWidths[i];
+ int relativeWeight = relativeWeights[i];
+
+ if (relativeWeight > 0) {
+ float weightPercentage = relativeWeight / (float)totalRelativeWeight;
+ totalRelativeWidth = Math.max(totalRelativeWidth,
+ (int)(columnWidth / weightPercentage));
+ }
+ }
+
+ // Perform the upward adjustments using the total relative width
+
+ for (int i = 0; i < columnCount; i++) {
+ int relativeWeight = relativeWeights[i];
+
+ if (relativeWeight > 0) {
+ float weightPercentage = relativeWeight / (float)totalRelativeWeight;
+ columnWidths[i] = (int)(weightPercentage * totalRelativeWidth);
+ }
+ }
+ }
+
+ // Finally, we account for spanning cells, which have been ignored thus
+ // far. If any spanned cell is default-width (including relative width
+ // columns), then we ensure that the sum of the widths of the spanned
+ // cells is enough to satisfy the preferred width of the spanning
+ // content
+
+ for (int i = 0; i < rowCount; i++) {
+ TablePane.Row row = rows.get(i);
+
+ for (int j = 0, n = row.getLength(); j < n && j < columnCount; j++) {
+ Component component = row.get(j);
+
+ if (component != null
+ && component.isDisplayable()) {
+ int columnSpan = TablePane.getColumnSpan(component);
+
+ if (columnSpan > 1) {
+ // We might need to adjust column widths to accomodate
+ // this spanning cell. First, we find out if any of the
+ // spanned cells are default width and how much space
+ // we've allocated thus far for those cells
+
+ int spannedDefaultWidthCellCount = 0;
+ int spannedRelativeWeight = 0;
+ int spannedWidth = 0;
+
+ for (int k = 0; k < columnSpan && j + k < columnCount; k++) {
+ if (defaultWidthColumns[j + k]) {
+ spannedDefaultWidthCellCount++;
+ }
+
+ spannedRelativeWeight += relativeWeights[j + k];
+ spannedWidth += columnWidths[j + k];
+ }
+
+ if (spannedRelativeWeight > 0
+ || spannedDefaultWidthCellCount > 0) {
+ int rowHeight = row.isRelative() ? -1 : row.getHeight();
+ int componentPreferredWidth = component.getPreferredWidth(rowHeight);
+
+ if (componentPreferredWidth > spannedWidth) {
+ // The component's preferred width is larger
+ // than the width we've allocated thus far, so
+ // an adjustment is necessary
+ int adjustment = componentPreferredWidth - spannedWidth;
+
+ if (spannedRelativeWeight > 0) {
+ // We'll distribute the adjustment across
+ // the spanned relative columns and adjust
+ // other relative column widths to keep all
+ // relative column widths reconciled
+ float unitAdjustment = adjustment /
+ (float)spannedRelativeWeight;
+
+ for (int k = 0; k < columnCount; k++) {
+ int relativeWeight = relativeWeights[k];
+
+ if (relativeWeight > 0) {
+ int columnAdjustment =
+ Math.round(unitAdjustment * relativeWeight);
+
+ columnWidths[k] += columnAdjustment;
+ }
+ }
+ } else {
+ // We'll distribute the adjustment evenly
+ // among the default-width columns
+ for (int k = 0; k < columnSpan && j + k < columnCount; k++) {
+ if (defaultWidthColumns[j + k]) {
+ int columnAdjustment = adjustment /
+ spannedDefaultWidthCellCount;
+
+ columnWidths[j + k] += columnAdjustment;
+
+ // Adjust these to avoid rounding errors
+ adjustment -= columnAdjustment;
+ spannedDefaultWidthCellCount--;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // The preferred width of the table pane is the sum of the column
+ // widths, plus padding and spacing
+
+ int preferredWidth = padding.left + padding.right + (columnCount - 1) * horizontalSpacing;
+
+ for (int i = 0; i < columnCount; i++) {
+ preferredWidth += columnWidths[i];
+ }
+
+ return preferredWidth;
+ }
+
+ @Override
+ public int getPreferredHeight(int width) {
+ TablePane tablePane = (TablePane)getComponent();
+ TablePane.RowSequence rows = tablePane.getRows();
+ TablePane.ColumnSequence columns = tablePane.getColumns();
+
+ int rowCount = rows.getLength();
+ int columnCount = columns.getLength();
+
+ int[] rowHeights = new int[rowCount];
+ int[] relativeWeights = new int[rowCount];
+ boolean[] defaultHeightRows = new boolean[rowCount];
+
+ int totalRelativeWeight = 0;
+
+ if (width < 0) {
+ width = getPreferredWidth(-1);
+ }
+
+ int[] columnWidths = getColumnWidths(tablePane, width, null);
+
+ // First, we calculate the base heights of the rows, giving relative
+ // rows their preferred height
+
+ for (int i = 0; i < rowCount; i++) {
+ TablePane.Row row = rows.get(i);
+ int rowHeight = row.getHeight();
+ boolean isRelative = row.isRelative();
+
+ if (isRelative) {
+ relativeWeights[i] = rowHeight;
+ totalRelativeWeight += rowHeight;
+ }
+
+ if (rowHeight < 0 || isRelative) {
+ rowHeight = getPreferredRowHeight(tablePane, i, columnWidths);
+ }
+
+ rowHeights[i] = rowHeight;
+ defaultHeightRows[i] = (rowHeight < 0);
+ }
+
+ // Next, we adjust the heights of the relative rows upwards where
+ // necessary to reconcile their heights relative to one another while
+ // ensuring that they still get at least their preferred height
+
+ if (totalRelativeWeight > 0) {
+ int totalRelativeHeight = 0;
+
+ // Calculate the total relative height after the required upward
+ // adjustments
+
+ for (int i = 0; i < rowCount; i++) {
+ int rowHeight = rowHeights[i];
+ int relativeWeight = relativeWeights[i];
+
+ if (relativeWeight > 0) {
+ float weightPercentage = relativeWeight / (float)totalRelativeWeight;
+ totalRelativeHeight = Math.max(totalRelativeHeight,
+ (int)(rowHeight / weightPercentage));
+ }
+ }
+
+ // Perform the upward adjustments using the total relative height
+
+ for (int i = 0; i < rowCount; i++) {
+ int relativeWeight = relativeWeights[i];
+
+ if (relativeWeight > 0) {
+ float weightPercentage = relativeWeight / (float)totalRelativeWeight;
+ rowHeights[i] = (int)(weightPercentage * totalRelativeHeight);
+ }
+ }
+ }
+
+ // Finally, we account for spanning cells, which have been ignored thus
+ // far. If any spanned cell is default-height (including relative height
+ // rows), then we ensure that the sum of the heights of the spanned
+ // cells is enough to satisfy the preferred height of the spanning
+ // content
+
+ for (int i = 0; i < rowCount; i++) {
+ TablePane.Row row = rows.get(i);
+
+ for (int j = 0, n = row.getLength(); j < n && j < columnCount; j++) {
+ Component component = row.get(j);
+
+ if (component != null
+ && component.isDisplayable()) {
+ int rowSpan = TablePane.getRowSpan(component);
+
+ if (rowSpan > 1) {
+ // We might need to adjust row heights to accomodate
+ // this spanning cell. First, we find out if any of the
+ // spanned cells are default height and how much space
+ // we've allocated thus far for those cells
+
+ int spannedDefaultHeightCellCount = 0;
+ int spannedRelativeWeight = 0;
+ int spannedHeight = 0;
+
+ for (int k = 0; k < rowSpan && i + k < rowCount; k++) {
+ if (defaultHeightRows[i + k]) {
+ spannedDefaultHeightCellCount++;
+ }
+
+ spannedRelativeWeight += relativeWeights[i + k];
+ spannedHeight += rowHeights[i + k];
+ }
+
+ if (spannedRelativeWeight > 0
+ || spannedDefaultHeightCellCount > 0) {
+ int componentPreferredHeight =
+ component.getPreferredHeight(columnWidths[j]);
+
+ if (componentPreferredHeight > spannedHeight) {
+ // The component's preferred height is larger
+ // than the height we've allocated thus far, so
+ // an adjustment is necessary
+ int adjustment = componentPreferredHeight - spannedHeight;
+
+ if (spannedRelativeWeight > 0) {
+ // We'll distribute the adjustment across
+ // the spanned relative rows and adjust
+ // other relative row heights to keep all
+ // relative row heights reconciled
+ float unitAdjustment = adjustment /
+ (float)spannedRelativeWeight;
+
+ for (int k = 0; k < rowCount; k++) {
+ int relativeWeight = relativeWeights[k];
+
+ if (relativeWeight > 0) {
+ int rowAdjustment =
+ Math.round(unitAdjustment * relativeWeight);
+
+ rowHeights[k] += rowAdjustment;
+ }
+ }
+ } else {
+ // We'll distribute the adjustment evenly
+ // among the default-height rows
+ for (int k = 0; k < rowSpan && i + k < rowCount; k++) {
+ if (defaultHeightRows[i + k]) {
+ int rowAdjustment = adjustment /
+ spannedDefaultHeightCellCount;
+
+ rowHeights[i + k] += rowAdjustment;
+
+ // Adjust these to avoid rounding errors
+ adjustment -= rowAdjustment;
+ spannedDefaultHeightCellCount--;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // The preferred height of the table pane is the sum of the row
+ // heights, plus padding and spacing
+
+ int preferredHeight = padding.top + padding.bottom + (rowCount - 1) * verticalSpacing;
+
+ for (int i = 0; i < rowCount; i++) {
+ preferredHeight += rowHeights[i];
+ }
+
+ return preferredHeight;
+ }
+
+ @Override
+ public Dimensions getPreferredSize() {
+ // TODO Optimize by performing calculations here
+ int preferredWidth = getPreferredWidth(-1);
+ int preferredHeight = getPreferredHeight(preferredWidth);
+ return new Dimensions(preferredWidth, preferredHeight);
+ }
+
+ public void layout() {
+ TablePane tablePane = (TablePane)getComponent();
+
+ TablePane.RowSequence rows = tablePane.getRows();
+ TablePane.ColumnSequence columns = tablePane.getColumns();
+
+ int rowCount = rows.getLength();
+ int columnCount = columns.getLength();
+
+ int width = getWidth();
+ int height = getHeight();
+
+ // NOTE We cache column widths and row heights to make getColumnAt()
+ // and getRowAt() more efficient
+ columnWidths = getColumnWidths(tablePane, width, null);
+ rowHeights = getRowHeights(tablePane, height, columnWidths);
+
+ int componentY = padding.top;
+ for (int i = 0; i < rowCount; i++) {
+ TablePane.Row row = rows.get(i);
+
+ int componentX = padding.left;
+ for (int j = 0, n = row.getLength(); j < n && j < columnCount; j++) {
+ Component child = row.get(j);
+
+ if (child != null) {
+ if (child.isDisplayable()) {
+ child.setLocation(componentX, componentY);
+
+ int columnSpan = TablePane.getColumnSpan(child);
+ int childWidth = (columnSpan - 1) * horizontalSpacing;
+ for (int k = 0; k < columnSpan && j + k < columnCount; k++) {
+ childWidth += columnWidths[j + k];
+ }
+
+ int rowSpan = TablePane.getRowSpan(child);
+ int childHeight = (rowSpan - 1) * verticalSpacing;
+ for (int k = 0; k < rowSpan && i + k < rowCount; k++) {
+ childHeight += rowHeights[i + k];
+ }
+
+ // Set the component's size
+ child.setSize(Math.max(childWidth, 0), Math.max(childHeight, 0));
+
+ // Show the component
+ child.setVisible(true);
+ } else {
+ // Hide the component
+ child.setVisible(false);
+ }
+ }
+
+ componentX += (columnWidths[j] + horizontalSpacing);
+ }
+
+ componentY += (rowHeights[i] + verticalSpacing);
+ }
+ }
+
+ @Override
+ public void paint(Graphics2D graphics) {
+ super.paint(graphics);
+
+ TablePane tablePane = (TablePane)getComponent();
+
+ TablePane.RowSequence rows = tablePane.getRows();
+ TablePane.ColumnSequence columns = tablePane.getColumns();
+
+ int rowCount = rows.getLength();
+ int columnCount = columns.getLength();
+
+ int width = getWidth();
+ int height = getHeight();
+
+ graphics.setPaint(selectionBackgroundColor);
+
+ // Paint the selected rows
+ for (int i = 0, rowY = padding.top; i < rowCount; i++) {
+ TablePane.Row row = rows.get(i);
+
+ if (row.isSelected()) {
+ graphics.fillRect(0, rowY, width, rowHeights[i]);
+ }
+
+ rowY += rowHeights[i] + verticalSpacing;
+ }
+
+ // Paint the selected columns
+ for (int j = 0, columnX = padding.left; j < columnCount; j++) {
+ TablePane.Column column = columns.get(j);
+
+ if (column.isSelected()) {
+ graphics.fillRect(columnX, 0, columnWidths[j], height);
+ }
+
+ columnX += columnWidths[j] + horizontalSpacing;
+ }
+
+ // Paint the grid lines
+ if ((showHorizontalGridLines && verticalSpacing > 0)
+ || (showVerticalGridLines && horizontalSpacing > 0)) {
+ Graphics2D gridGraphics = (Graphics2D)graphics.create();
+
+ gridGraphics.setStroke(new BasicStroke());
+ gridGraphics.setPaint(gridColor);
+
+ // Find any components that span multiple rows or columns, and
+ // ensure that the grid lines don't get painted through their
+ // cells. We'll only instantiate gridClip if we find such cells
+ Area gridClip = null;
+
+ for (int i = 0, componentY = padding.top; i < rowCount; i++) {
+ for (int j = 0, componentX = padding.left; j < columnCount; j++) {
+ Component component = tablePane.getCellComponent(i, j);
+
+ if (component != null) {
+ int rowSpan = TablePane.getRowSpan(component);
+ int columnSpan = TablePane.getColumnSpan(component);
+
+ if (rowSpan > 1
+ || columnSpan > 1) {
+ int rowY = componentY;
+ int columnX = componentX;
+
+ int rowHeight = rowHeights[i];
+ int columnWidth = columnWidths[j];
+
+ for (int k = i + 1; k < i + rowSpan; k++) {
+ rowHeight += rowHeights[k] + verticalSpacing;
+ }
+
+ for (int k = j + 1; k < j + columnSpan; k++) {
+ columnWidth += columnWidths[k] + horizontalSpacing;
+ }
+
+ if (gridClip == null) {
+ gridClip = new Area(graphics.getClip());
+ }
+
+ if (horizontalSpacing > 1) {
+ columnWidth += horizontalSpacing - 1;
+ columnX -= (int)(((float)horizontalSpacing * 0.5f) - 0.5f);
+ }
+
+ if (verticalSpacing > 1) {
+ rowHeight += verticalSpacing - 1;
+ rowY -= (int)(((float)verticalSpacing * 0.5f) - 0.5f);
+ }
+
+ Rectangle2D.Float bounds = new Rectangle2D.Float(columnX, rowY,
+ columnWidth, rowHeight);
+ gridClip.subtract(new Area(bounds));
+ }
+ }
+
+ componentX += columnWidths[j] + horizontalSpacing;
+ }
+
+ componentY += rowHeights[i] + verticalSpacing;
+ }
+
+ if (gridClip != null) {
+ gridGraphics.clip(gridClip);
+ }
+
+ if (showHorizontalGridLines
+ && verticalSpacing > 0) {
+ int rowY = padding.top + (rowHeights[0] + verticalSpacing);
+
+ for (int i = 1; i < rowCount; i++) {
+ int gridY = Math.max(rowY - (int)Math.ceil(verticalSpacing * 0.5f), 0);
+ int gridWidth = Math.max(width - (padding.left + padding.right), 0);
+ gridGraphics.drawLine(padding.left, gridY, gridWidth - 1, gridY);
+
+ rowY += (rowHeights[i] + verticalSpacing);
+ }
+ }
+
+ if (showVerticalGridLines
+ && horizontalSpacing > 0) {
+ int columnX = padding.left + (columnWidths[0] + horizontalSpacing);
+
+ for (int j = 1; j < columnCount; j++) {
+ int gridX = Math.max(columnX - (int)Math.ceil(horizontalSpacing * 0.5), 0);
+ int gridHeight = Math.max(height - (padding.top + padding.bottom), 0);
+ gridGraphics.drawLine(gridX, padding.top, gridX, gridHeight - 1);
+
+ columnX += (columnWidths[j] + horizontalSpacing);
+ }
+ }
+
+ gridGraphics.dispose();
+ }
+ }
+
+ /**
+ * Gets the padding that will be reserved around the table pane during
+ * layout.
+ */
+ public Insets getPadding() {
+ return padding;
+ }
+
+ /**
+ * Sets the padding that will be reserved around the table pane during
+ * layout.
+ */
+ public void setPadding(Insets padding) {
+ if (padding == null) {
+ throw new IllegalArgumentException("padding is null.");
+ }
+
+ this.padding = padding;
+ invalidateComponent();
+ }
+
+ /**
+ * Sets the padding that will be reserved around the table pane during
+ * layout.
+ */
+ public final void setPadding(int padding) {
+ setPadding(new Insets(padding));
+ }
+
+ /**
+ * Sets the padding that will be reserved around the table pane during
+ * layout.
+ */
+ public final void setPadding(Dictionary<String, ?> padding) {
+ if (padding == null) {
+ throw new IllegalArgumentException("padding is null.");
+ }
+
+ setPadding(new Insets(padding));
+ }
+
+ /**
+ * Gets the spacing that will be applied in between the table pane's
+ * columns during layout.
+ */
+ public int getHorizontalSpacing() {
+ return horizontalSpacing;
+ }
+
+ /**
+ * Sets the spacing that will be applied in between the table pane's
+ * columns during layout.
+ */
+ public void setHorizontalSpacing(int horizontalSpacing) {
+ if (horizontalSpacing < 0) {
+ throw new IllegalArgumentException("horizontalSpacing is negative");
+ }
+
+ this.horizontalSpacing = horizontalSpacing;
+ invalidateComponent();
+ }
+
+ /**
+ * Gets the spacing that will be applied in between the table pane's rows
+ * during layout.
+ */
+ public int getVerticalSpacing() {
+ return verticalSpacing;
+ }
+
+ /**
+ * Sets the spacing that will be applied in between the table pane's rows
+ * during layout.
+ */
+ public void setVerticalSpacing(int verticalSpacing) {
+ if (verticalSpacing < 0) {
+ throw new IllegalArgumentException("verticalSpacing is negative");
+ }
+
+ this.verticalSpacing = verticalSpacing;
+ invalidateComponent();
+ }
+
+ /**
+ * Tells whether or not horizontal grid lines will be painted in between
+ * the table pane's rows.
+ */
+ public boolean getShowHorizontalGridLines() {
+ return showHorizontalGridLines;
+ }
+
+ /**
+ * Sets whether or not horizontal grid lines will be painted in between
+ * the table pane's rows.
+ */
+ public void setShowHorizontalGridLines(boolean showHorizontalGridLines) {
+ this.showHorizontalGridLines = showHorizontalGridLines;
+ repaintComponent();
+ }
+
+ /**
+ * Tells whether or not vertical grid lines will be painted in between
+ * the table pane's columns.
+ */
+ public boolean getShowVerticalGridLines() {
+ return showVerticalGridLines;
+ }
+
+ /**
+ * Sets whether or not vertical grid lines will be painted in between
+ * the table pane's columns.
+ */
+ public void setShowVerticalGridLines(boolean showVerticalGridLines) {
+ this.showVerticalGridLines = showVerticalGridLines;
+ repaintComponent();
+ }
+
+ /**
+ * Gets the color used to paint the table pane's grid lines.
+ */
+ public Color getGridColor() {
+ return gridColor;
+ }
+
+ /**
+ * Sets the color used to paint the table pane's grid lines.
+ */
+ public void setGridColor(Color gridColor) {
+ if (gridColor == null) {
+ throw new IllegalArgumentException("gridColor is null.");
+ }
+
+ this.gridColor = gridColor;
+
+ if (showHorizontalGridLines || showVerticalGridLines) {
+ repaintComponent();
+ }
+ }
+
+ /**
+ * Sets the color used to paint the table pane's grid lines.
+ */
+ public final void setGridColor(String gridColor) {
+ if (gridColor == null) {
+ throw new IllegalArgumentException("gridColor is null.");
+ }
+
+ setGridColor(decodeColor(gridColor));
+ }
+
+ /**
+ * Gets the background color used to paint the selected rows and columns.
+ */
+ public Color getSelectionBackgroundColor() {
+ return selectionBackgroundColor;
+ }
+
+ /**
+ * Sets the background color used to paint the selected rows and columns.
+ */
+ public void setSelectionBackgroundColor(Color selectionBackgroundColor) {
+ if (selectionBackgroundColor == null) {
+ throw new IllegalArgumentException("selectionBackgroundColor is null.");
+ }
+
+ this.selectionBackgroundColor = selectionBackgroundColor;
+ repaintComponent();
+ }
+
+ /**
+ * Sets the background color used to paint the selected rows and columns.
+ */
+ public final void setSelectionBackgroundColor(String selectionBackgroundColor) {
+ if (selectionBackgroundColor == null) {
+ throw new IllegalArgumentException("selectionBackgroundColor is null.");
+ }
+
+ setSelectionBackgroundColor(decodeColor(selectionBackgroundColor));
+ }
+
+ /**
+ * Gets the preferred width of a table pane column, which is defined as the
+ * maximum preferred width of the column's displayable components. The
+ * preferred width of each constituent component will be constrained by the
+ * height of the row that the component occupies (as specified in the array
+ * of row heights).
+ * <p>
+ * Components that span multiple columns will not be considered in the
+ * calculation. It is up to the caller to factor such components into the
+ * column widths calculation.
+ *
+ * @param tablePane
+ * The table pane
+ *
+ * @param columnIndex
+ * The index of the column whose preferred width we're calculating
+ *
+ * @param rowHeights
+ * An array of row height values corresponding to the rows of the table
+ * pane, or <tt>null</tt> if these heights are not yet known
+ */
+ private static int getPreferredColumnWidth(TablePane tablePane, int columnIndex,
+ int[] rowHeights) {
+ TablePane.RowSequence rows = tablePane.getRows();
+
+ int preferredWidth = 0;
+
+ for (int i = 0, n = rows.getLength(); i < n; i++) {
+ TablePane.Row row = rows.get(i);
+
+ if (row.getLength() > columnIndex) {
+ Component component = row.get(columnIndex);
+
+ if (component != null
+ && component.isDisplayable()
+ && TablePane.getColumnSpan(component) == 1) {
+ int rowHeight = -1;
+
+ if (rowHeights != null) {
+ rowHeight = rowHeights[i];
+ } else if (!row.isRelative()) {
+ rowHeight = row.getHeight();
+ }
+
+ preferredWidth = Math.max(preferredWidth,
+ component.getPreferredWidth(rowHeight));
+ }
+ }
+ }
+
+ return preferredWidth;
+ }
+
+ /**
+ * Gets the preferred height of a table pane row, which is defined as the
+ * maximum preferred height of the row's displayable components. The
+ * preferred height of each constituent component will be constrained by
+ * the width of the column that the component occupies (as specified in the
+ * array of column widths).
+ * <p>
+ * Components that span multiple rows will not be considered in the
+ * calculation. It is up to the caller to factor such components into the
+ * row heights calculation.
+ *
+ * @param tablePane
+ * The table pane
+ *
+ * @param rowIndex
+ * The index of the row whose preferred height we're calculating
+ *
+ * @param columnWidths
+ * An array of column width values corresponding to the columns of the
+ * table pane, or <tt>null</tt> if these widths are not yet known
+ */
+ private static int getPreferredRowHeight(TablePane tablePane, int rowIndex,
+ int[] columnWidths) {
+ TablePane.ColumnSequence columns = tablePane.getColumns();
+ TablePane.Row row = tablePane.getRows().get(rowIndex);
+
+ int preferredHeight = 0;
+
+ for (int i = 0, n = row.getLength(), m = columns.getLength(); i < n && i < m; i++) {
+ Component component = row.get(i);
+
+ if (component != null
+ && component.isDisplayable()
+ && TablePane.getRowSpan(component) == 1) {
+ TablePane.Column column = columns.get(i);
+ int columnWidth = -1;
+
+ if (columnWidths != null) {
+ columnWidth = columnWidths[i];
+ } else if (!column.isRelative()) {
+ columnWidth = column.getWidth();
+ }
+
+ preferredHeight = Math.max(preferredHeight,
+ component.getPreferredHeight(columnWidth));
+ }
+ }
+
+ return preferredHeight;
+ }
+
+ /**
+ * Gets the width of each column of a table pane given the specified
+ * constraints. This method is static to allow other skins (such as
+ * <tt>TablePaneHeaderSkin</tt>) to hook into it.
+ *
+ * @param tablePane
+ * The table pane
+ *
+ * @param width
+ * The width constraint of the table pane
+ *
+ * @param rowHeights
+ * The heights of the table pane's rows, which will be used as height
+ * constraints to the column widths when necessary, or <tt>null</tt> if the
+ * row heights are not yet known (the column widths will be unconstrained)
+ *
+ * @return
+ * An array containing the width of each column in the table pane given the
+ * specified constraints
+ */
+ public static int[] getColumnWidths(TablePane tablePane, int width, int[] rowHeights) {
+ assert(width >= 0) : "Width must be greater than or equal to zero.";
+
+ TablePane.RowSequence rows = tablePane.getRows();
+ TablePane.ColumnSequence columns = tablePane.getColumns();
+
+ int rowCount = rows.getLength();
+ int columnCount = columns.getLength();
+
+ int[] columnWidths = new int[columnCount];
+ boolean[] defaultWidthColumns = new boolean[columnCount];
+
+ Insets padding = (Insets)tablePane.getStyles().get("padding");
+ int horizontalSpacing = (Integer)tablePane.getStyles().get("horizontalSpacing");
+
+ int reservedWidth = padding.left + padding.right +
+ Math.max(columnCount - 1, 0) * horizontalSpacing;
+ int totalRelativeWeight = 0;
+
+ // First, we allocate the widths of non-relative columns. We store the
+ // widths of relative columns as negative values for later processing
+
+ for (int i = 0; i < columnCount; i++) {
+ TablePane.Column column = columns.get(i);
+ int columnWidth = column.getWidth();
+
+ if (column.isRelative()) {
+ columnWidths[i] = -columnWidth;
+ totalRelativeWeight += columnWidth;
+ } else {
+ if (columnWidth < 0) {
+ // Default width column; we must calculate the width
+ columnWidth = getPreferredColumnWidth(tablePane, i, rowHeights);
+ defaultWidthColumns[i] = true;
+ }
+
+ columnWidths[i] = columnWidth;
+ reservedWidth += columnWidth;
+ }
+ }
+
+ // Next, we we account for default-width columns containing spanning
+ // cells, which have been ignored thus far. We ensure that the sum of
+ // the widths of the spanned cells is enough to satisfy the preferred
+ // width of the spanning content.
+
+ for (int i = 0; i < rowCount; i++) {
+ TablePane.Row row = rows.get(i);
+
+ for (int j = 0, n = row.getLength(); j < n && j < columnCount; j++) {
+ Component component = row.get(j);
+
+ if (component != null
+ && component.isDisplayable()) {
+ int columnSpan = TablePane.getColumnSpan(component);
+
+ if (columnSpan > 1) {
+ // We might need to adjust column widths to accomodate
+ // this spanning cell. First, we find out if any of the
+ // spanned cells are default width and how much space
+ // we've allocated thus far for those cells
+
+ int spannedDefaultWidthCellCount = 0;
+ int spannedRelativeWeight = 0;
+ int spannedWidth = 0;
+
+ for (int k = 0; k < columnSpan && j + k < columnCount; k++) {
+ if (defaultWidthColumns[j + k]) {
+ spannedDefaultWidthCellCount++;
+ }
+
+ if (columnWidths[j + k] < 0) {
+ spannedRelativeWeight += -columnWidths[j + k];
+ } else {
+ spannedWidth += columnWidths[j + k];
+ }
+ }
+
+ // If we span any relative-width columns, we assume
+ // that we'll achieve the desired spanning width when
+ // we divvy up the remaining space, so there's no need
+ // to make an adjustment here. This assumption is safe
+ // because our preferred width policy is to *either*
+ // divide the adjustment among the relative-width
+ // columns *or* among the default-width columns if we
+ // don't span any relative-width columns
+
+ if (spannedRelativeWeight == 0
+ && spannedDefaultWidthCellCount > 0) {
+ int rowHeight = -1;
+
+ if (rowHeights != null) {
+ rowHeight = rowHeights[i];
+ } else if (!row.isRelative()) {
+ rowHeight = row.getHeight();
+ }
+
+ int componentPreferredWidth = component.getPreferredWidth(rowHeight);
+
+ if (componentPreferredWidth > spannedWidth) {
+ // The component's preferred width is larger
+ // than the width we've allocated thus far, so
+ // an adjustment is necessary
+ int adjustment = componentPreferredWidth - spannedWidth;
+ reservedWidth -= adjustment;
+
+ // We'll distribute the adjustment evenly
+ // among the default-width columns
+ for (int k = 0; k < columnSpan && j + k < columnCount; k++) {
+ if (defaultWidthColumns[j + k]) {
+ int columnAdjustment = adjustment /
+ spannedDefaultWidthCellCount;
+
+ columnWidths[j + k] += columnAdjustment;
+
+ // Adjust these to avoid rounding errors
+ adjustment -= columnAdjustment;
+ spannedDefaultWidthCellCount--;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Finally, we allocate the widths of the relative columns by divvying
+ // up the remaining width
+
+ int remainingWidth = Math.max(width - reservedWidth, 0);
+ if (totalRelativeWeight > 0 && remainingWidth > 0) {
+ for (int i = 0; i < columnCount; i++) {
+ if (columnWidths[i] < 0) {
+ int relativeWeight = -columnWidths[i];
+ float weightPercentage = relativeWeight / (float)totalRelativeWeight;
+ int columnWidth = (int)(remainingWidth * weightPercentage);
+
+ columnWidths[i] = columnWidth;
+
+ // NOTE we adjust remainingWidth and totalRelativeWeight as we go
+ // to avoid potential rounding errors in the columnWidth
+ // calculation
+ remainingWidth -= columnWidth;
+ totalRelativeWeight -= relativeWeight;
+ }
+ }
+ }
+
+ return columnWidths;
+ }
+
+ /**
+ * Gets the height of each row of a table pane given the specified
+ * constraints. This method is static to allow other skins (such as
+ * <tt>TablePaneHeaderSkin</tt>) to hook into it.
+ *
+ * @param tablePane
+ * The table pane
+ *
+ * @param height
+ * The height constraint of the table pane
+ *
+ * @param columnWidths
+ * The widths of the table pane's columns, which will be used as width
+ * constraints to the row heights when necessary, or <tt>null</tt> if the
+ * column widths are not yet known (the row heights will be unconstrained)
+ *
+ * @return
+ * An array containing the height of each row in the table pane given the
+ * specified constraints
+ */
+ public static int[] getRowHeights(TablePane tablePane, int height, int[] columnWidths) {
+ assert(height >= 0) : "Height must be greater than or equal to zero.";
+
+ TablePane.RowSequence rows = tablePane.getRows();
+ TablePane.ColumnSequence columns = tablePane.getColumns();
+
+ int rowCount = tablePane.getRows().getLength();
+ int columnCount = tablePane.getColumns().getLength();
+
+ int rowHeights[] = new int[rowCount];
+ boolean[] defaultHeightRows = new boolean[rowCount];
+
+ Insets padding = (Insets)tablePane.getStyles().get("padding");
+ int verticalSpacing = (Integer)tablePane.getStyles().get("verticalSpacing");
+
+ int reservedHeight = padding.top + padding.bottom +
+ Math.max(rowCount - 1, 0) * verticalSpacing;
+ int totalRelativeWeight = 0;
+
+ // First, we allocate the heights of non-relative rows. We store the
+ // heights of relative rows as negative values for later processing
+
+ for (int i = 0; i < rowCount; i++) {
+ TablePane.Row row = rows.get(i);
+ int rowHeight = row.getHeight();
+
+ if (row.isRelative()) {
+ rowHeights[i] = -rowHeight;
+ totalRelativeWeight += rowHeight;
+ } else {
+ if (rowHeight < 0) {
+ // Default height row; we must calculate the height
+ rowHeight = getPreferredRowHeight(tablePane, i, columnWidths);
+ defaultHeightRows[i] = true;
+ }
+
+ rowHeights[i] = rowHeight;
+ reservedHeight += rowHeight;
+ }
+ }
+
+ // Next, we we account for default-width columns containing spanning
+ // cells, which have been ignored thus far. We ensure that the sum of
+ // the widths of the spanned cells is enough to satisfy the preferred
+ // width of the spanning content.
+
+ for (int i = 0; i < rowCount; i++) {
+ TablePane.Row row = rows.get(i);
+
+ for (int j = 0, n = row.getLength(); j < n && j < columnCount; j++) {
+ Component component = row.get(j);
+
+ if (component != null
+ && component.isDisplayable()) {
+ int rowSpan = TablePane.getRowSpan(component);
+
+ if (rowSpan > 1) {
+ // We might need to adjust row heights to accomodate
+ // this spanning cell. First, we find out if any of the
+ // spanned cells are default height and how much space
+ // we've allocated thus far for those cells
+
+ int spannedDefaultHeightCellCount = 0;
+ int spannedRelativeWeight = 0;
+ int spannedHeight = 0;
+
+ for (int k = 0; k < rowSpan && i + k < rowCount; k++) {
+ if (defaultHeightRows[i + k]) {
+ spannedDefaultHeightCellCount++;
+ }
+
+ if (rowHeights[i + k] < 0) {
+ spannedRelativeWeight += -rowHeights[i + k];
+ } else {
+ spannedHeight += rowHeights[i + k];
+ }
+ }
+
+ // If we span any relative-height rows, we assume
+ // that we'll achieve the desired spanning height when
+ // we divvy up the remaining space, so there's no need
+ // to make an adjustment here. This assumption is safe
+ // because our preferred height policy is to *either*
+ // divide the adjustment among the relative-height
+ // rows *or* among the default-height rows if we
+ // don't span any relative-height rows
+
+ if (spannedRelativeWeight == 0
+ && spannedDefaultHeightCellCount > 0) {
+ TablePane.Column column = columns.get(j);
+ int columnWidth = -1;
+
+ if (columnWidths != null) {
+ columnWidth = columnWidths[j];
+ } else if (!column.isRelative()) {
+ columnWidth = column.getWidth();
+ }
+
+ int componentPreferredHeight =
+ component.getPreferredHeight(columnWidth);
+
+ if (componentPreferredHeight > spannedHeight) {
+ // The component's preferred height is larger
+ // than the height we've allocated thus far, so
+ // an adjustment is necessary
+ int adjustment = componentPreferredHeight - spannedHeight;
+ reservedHeight -= adjustment;
+
+ // We'll distribute the adjustment evenly
+ // among the default-height rows
+ for (int k = 0; k < rowSpan && i + k < rowCount; k++) {
+ if (defaultHeightRows[i + k]) {
+ int rowAdjustment = adjustment /
+ spannedDefaultHeightCellCount;
+
+ rowHeights[i + k] += rowAdjustment;
+
+ // Adjust these to avoid rounding errors
+ adjustment -= rowAdjustment;
+ spannedDefaultHeightCellCount--;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Finally, we allocate the heights of the relative rows by divvying
+ // up the remaining height
+
+ int remainingHeight = Math.max(height - reservedHeight, 0);
+ if (totalRelativeWeight > 0
+ && remainingHeight > 0) {
+ for (int i = 0; i < rowCount; i++) {
+ if (rowHeights[i] < 0) {
+ int relativeWeight = -rowHeights[i];
+ float weightPercentage = relativeWeight / (float)totalRelativeWeight;
+ int rowHeight = (int)(remainingHeight * weightPercentage);
+
+ rowHeights[i] = rowHeight;
+
+ // NOTE we adjust remainingHeight and totalRelativeWeight as we
+ // go to avoid potential rounding errors in the rowHeight
+ // calculation
+ remainingHeight -= rowHeight;
+ totalRelativeWeight -= relativeWeight;
+ }
+ }
+ }
+
+ return rowHeights;
+ }
+
+ // TablePane.Skin methods
+
+ public int getRowAt(int y) {
+ if (rowHeights == null) {
+ return -1;
+ }
+
+ int rowIndex = -1;
+
+ for (int i = 0, rowY = padding.top; rowY <= y && i < rowHeights.length; i++) {
+ int rowHeight = rowHeights[i];
+
+ if (y < rowY + rowHeight) {
+ rowIndex = i;
+ break;
+ }
+
+ rowY += rowHeight + verticalSpacing;
+ }
+
+ return rowIndex;
+ }
+
+ public Bounds getRowBounds(int row) {
+ if (rowHeights == null) {
+ return new Bounds(0, 0, 0, 0);
+ }
+
+ int rowY = padding.top;
+
+ for (int i = 0; i < row; i++) {
+ rowY += rowHeights[i] + verticalSpacing;
+ }
+
+ return new Bounds(0, rowY, getWidth(), rowHeights[row]);
+ }
+
+ public int getColumnAt(int x) {
+ if (columnWidths == null) {
+ return -1;
+ }
+
+ int columnIndex = -1;
+
+ for (int j = 0, columnX = padding.left; columnX <= x && j < columnWidths.length; j++) {
+ int columnWidth = columnWidths[j];
+
+ if (x < columnX + columnWidth) {
+ columnIndex = j;
+ break;
+ }
+
+ columnX += columnWidth + horizontalSpacing;
+ }
+
+ return columnIndex;
+ }
+
+ public Bounds getColumnBounds(int column) {
+ if (columnWidths == null) {
+ return new Bounds(0, 0, 0, 0);
+ }
+
+ int columnX = padding.left;
+
+ for (int j = 0; j < column; j++) {
+ columnX += columnWidths[j] + horizontalSpacing;
+ }
+
+ return new Bounds(columnX, 0, columnWidths[column], getHeight());
+ }
+
+ // TablePaneListener methods
+
+ public void rowInserted(TablePane tablePane, int index) {
+ invalidateComponent();
+ }
+
+ public void rowsRemoved(TablePane tablePane, int index, Sequence<TablePane.Row> rows) {
+ invalidateComponent();
+ }
+
+ public void rowHeightChanged(TablePane.Row row, int previousHeight,
+ boolean previousRelative) {
+ invalidateComponent();
+ }
+
+ public void rowSelectedChanged(TablePane.Row row) {
+ TablePane tablePane = row.getTablePane();
+ repaintComponent(getRowBounds(tablePane.getRows().indexOf(row)));
+ }
+
+ public void columnInserted(TablePane tablePane, int index) {
+ invalidateComponent();
+ }
+
+ public void columnsRemoved(TablePane tablePane, int index,
+ Sequence<TablePane.Column> columns) {
+ invalidateComponent();
+ }
+
+ public void columnWidthChanged(TablePane.Column column, int previousWidth,
+ boolean previousRelative) {
+ invalidateComponent();
+ }
+
+ public void columnSelectedChanged(TablePane.Column column) {
+ TablePane tablePane = column.getTablePane();
+ repaintComponent(getColumnBounds(tablePane.getColumns().indexOf(column)));
+ }
+
+ public void cellInserted(TablePane.Row row, int column) {
+ invalidateComponent();
+ }
+
+ public void cellsRemoved(TablePane.Row row, int column,
+ Sequence<Component> removed) {
+ invalidateComponent();
+ }
+
+ public void cellUpdated(TablePane.Row row, int column,
+ Component previousComponent) {
+ invalidateComponent();
+ }
+
+ // TablePaneAttribute events
+
+ public void rowSpanChanged(TablePane tablePane, Component component,
+ int previousRowSpan) {
+ invalidateComponent();
+ }
+
+ public void columnSpanChanged(TablePane tablePane, Component component,
+ int previousColumnSpan) {
+ invalidateComponent();
+ }
+}
Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/WindowSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/WindowSkin.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/WindowSkin.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/WindowSkin.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * 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 pivot.wtk.skin;
+
+import java.awt.Color;
+
+import pivot.util.Vote;
+import pivot.wtk.Action;
+import pivot.wtk.Component;
+import pivot.wtk.Container;
+import pivot.wtk.Dimensions;
+import pivot.wtk.Direction;
+import pivot.wtk.Display;
+import pivot.wtk.FocusTraversalPolicy;
+import pivot.wtk.Keyboard;
+import pivot.wtk.Window;
+import pivot.wtk.WindowListener;
+import pivot.wtk.WindowStateListener;
+import pivot.wtk.media.Image;
+
+/**
+ * Window skin.
+ *
+ * @author gbrown
+ */
+public class WindowSkin extends ContainerSkin
+ implements WindowListener, WindowStateListener {
+ /**
+ * Focus traversal policy that always returns the window's content. This
+ * ensures that focus does not traverse out of the window.
+ *
+ * @author gbrown
+ */
+ public static class WindowFocusTraversalPolicy implements FocusTraversalPolicy {
+ public Component getNextComponent(Container container, Component component, Direction direction) {
+ assert (container instanceof Window) : "container is not a Window";
+
+ if (container == null) {
+ throw new IllegalArgumentException("container is null.");
+ }
+
+ if (direction == null) {
+ throw new IllegalArgumentException("direction is null.");
+ }
+
+ Window window = (Window)container;
+
+ return window.getContent();
+ }
+ }
+
+ public WindowSkin() {
+ setBackgroundColor(Color.WHITE);
+ }
+
+ @Override
+ public void install(Component component) {
+ super.install(component);
+
+ Window window = (Window)component;
+ window.getWindowListeners().add(this);
+ window.getWindowStateListeners().add(this);
+
+ window.setFocusTraversalPolicy(new WindowFocusTraversalPolicy());
+ }
+
+ @Override
+ public void uninstall() {
+ Window window = (Window)getComponent();
+ window.getWindowListeners().remove(this);
+ window.getWindowStateListeners().remove(this);
+
+ window.setFocusTraversalPolicy(null);
+
+ super.uninstall();
+ }
+
+ public int getPreferredWidth(int height) {
+ Window window = (Window)getComponent();
+ Component content = window.getContent();
+
+ return (content != null
+ && content.isDisplayable()) ?
+ content.getPreferredWidth(height) : 0;
+ }
+
+ public int getPreferredHeight(int width) {
+ Window window = (Window)getComponent();
+ Component content = window.getContent();
+
+ return (content != null
+ && content.isDisplayable()) ?
+ content.getPreferredHeight(width) : 0;
+ }
+
+ public Dimensions getPreferredSize() {
+ Window window = (Window)getComponent();
+ Component content = window.getContent();
+
+ return (content != null
+ && content.isDisplayable()) ?
+ content.getPreferredSize() : new Dimensions(0, 0);
+ }
+
+ public void layout() {
+ Window window = (Window)getComponent();
+ Component content = window.getContent();
+
+ if (content != null) {
+ if (content.isDisplayable()) {
+ content.setVisible(true);
+ content.setSize(window.getSize());
+ } else {
+ content.setVisible(false);
+ }
+ }
+ }
+
+ // Component key events
+ @Override
+ public boolean keyReleased(Component component, int keyCode, Keyboard.KeyLocation keyLocation) {
+ boolean consumed = super.keyReleased(component, keyCode, keyLocation);
+
+ // Perform any action defined for this keystroke
+ // in the active window's action dictionary
+ Window window = (Window)getComponent();
+ Keyboard.KeyStroke keyStroke = new Keyboard.KeyStroke(keyCode,
+ Keyboard.getModifiers());
+
+ Action action = window.getActions().get(keyStroke);
+ if (action != null) {
+ action.perform();
+ }
+
+ return consumed;
+ }
+
+ // Window events
+ public void titleChanged(Window window, String previousTitle) {
+ // No-op
+ }
+
+ public void iconChanged(Window window, Image previousIcon) {
+ // No-op
+ }
+
+ public void contentChanged(Window window, Component previousContent) {
+ invalidateComponent();
+ }
+
+ public void ownerChanged(Window window, Window previousOwner) {
+ // No-op
+ }
+
+ public void activeChanged(Window window) {
+ // No-op
+ }
+
+ public void maximizedChanged(Window window) {
+ // No-op
+ }
+
+ // Window state events
+ public Vote previewWindowOpen(Window window, Display display) {
+ return Vote.APPROVE;
+ }
+
+ public void windowOpenVetoed(Window window, Vote reason) {
+ // No-op
+ }
+
+ public void windowOpened(Window window) {
+ }
+
+ public Vote previewWindowClose(Window window) {
+ return Vote.APPROVE;
+ }
+
+ public void windowCloseVetoed(Window window, Vote reason) {
+ // No-op
+ }
+
+ public void windowClosed(Window window, Display display) {
+ }
+}
Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/obsidian/ObsidianPushButtonSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/obsidian/ObsidianPushButtonSkin.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/obsidian/ObsidianPushButtonSkin.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/obsidian/ObsidianPushButtonSkin.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * 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 pivot.wtk.skin.obsidian;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.GradientPaint;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.geom.RoundRectangle2D;
+
+import pivot.wtk.Button;
+import pivot.wtk.Dimensions;
+import pivot.wtk.Insets;
+import pivot.wtk.PushButton;
+import pivot.wtk.skin.PushButtonSkin;
+
+/**
+ * Obsidian push button skin.
+ *
+ * @author gbrown
+ */
+public class ObsidianPushButtonSkin extends PushButtonSkin {
+ // Style properties
+ private Font font = new Font("Verdana", Font.PLAIN, 11);
+ private Color color = Color.WHITE;
+ private Color disabledColor = new Color(0x66, 0x66, 0x66);
+ private Insets padding = new Insets(4, 8, 4, 8);
+
+ private Color borderColor = new Color(0x4c, 0x4c, 0x4c);
+ private Color gradientStartColor = new Color(0x66, 0x66, 0x66);
+ private Color gradientEndColor = new Color(0x00, 0x00, 0x00);
+
+ private Color highlightedBorderColor = new Color(0x4c, 0x4c, 0x4c);
+ private Color highlightedGradientStartColor = new Color(0x99, 0x99, 0x99);
+ private Color highlightedGradientEndColor = new Color(0x00, 0x00, 0x00);
+
+ private Color pressedBorderColor = new Color(0x80, 0x80, 0x80);
+ private Color pressedGradientStartColor = new Color(0x00, 0x00, 0x00);
+ private Color pressedGradientEndColor = new Color(0x66, 0x66, 0x66);
+
+ private Color disabledBorderColor = new Color(0x80, 0x80, 0x80);
+ private Color disabledGradientStartColor = new Color(0x4c, 0x4c, 0x4c);
+ private Color disabledGradientEndColor = new Color(0x4c, 0x4c, 0x4c);
+
+ private int cornerRadius = 6;
+
+ public int getPreferredWidth(int height) {
+ PushButton pushButton = (PushButton)getComponent();
+ Button.DataRenderer dataRenderer = pushButton.getDataRenderer();
+
+ dataRenderer.render(pushButton.getButtonData(), pushButton, false);
+
+ // Include padding in constraint
+ if (height != -1) {
+ height = Math.max(height - (padding.top + padding.bottom + 2), 0);
+ }
+
+ int preferredWidth = dataRenderer.getPreferredWidth(height)
+ + padding.left + padding.right + 2;
+
+ return preferredWidth;
+ }
+
+ public int getPreferredHeight(int width) {
+ PushButton pushButton = (PushButton)getComponent();
+ Button.DataRenderer dataRenderer = pushButton.getDataRenderer();
+
+ dataRenderer.render(pushButton.getButtonData(), pushButton, false);
+
+ // Include padding in constraint
+ if (width != -1) {
+ width = Math.max(width - (padding.left + padding.right + 2), 0);
+ }
+
+ int preferredHeight = dataRenderer.getPreferredHeight(width)
+ + padding.top + padding.bottom + 2;
+
+ return preferredHeight;
+ }
+
+ public Dimensions getPreferredSize() {
+ PushButton pushButton = (PushButton)getComponent();
+ Button.DataRenderer dataRenderer = pushButton.getDataRenderer();
+
+ dataRenderer.render(pushButton.getButtonData(), pushButton, false);
+
+ Dimensions preferredContentSize = dataRenderer.getPreferredSize();
+
+ int preferredWidth = preferredContentSize.width
+ + padding.left + padding.right + 2;
+
+ int preferredHeight = preferredContentSize.height
+ + padding.top + padding.bottom + 2;
+
+ return new Dimensions(preferredWidth, preferredHeight);
+ }
+
+ public void paint(Graphics2D graphics) {
+ PushButton pushButton = (PushButton)getComponent();
+
+ Color borderColor = null;
+ Color gradientStartColor = null;
+ Color gradientEndColor = null;
+
+ if (pushButton.isEnabled()) {
+ if (pressed
+ || pushButton.isSelected()) {
+ borderColor = pressedBorderColor;
+ gradientStartColor = pressedGradientStartColor;
+ gradientEndColor = pressedGradientEndColor;
+ } else {
+ if (highlighted) {
+ borderColor = highlightedBorderColor;
+ gradientStartColor = highlightedGradientStartColor;
+ gradientEndColor = highlightedGradientEndColor;
+ } else {
+ borderColor = this.borderColor;
+ gradientStartColor = this.gradientStartColor;
+ gradientEndColor = this.gradientEndColor;
+ }
+ }
+ }
+ else {
+ borderColor = disabledBorderColor;
+ gradientStartColor = disabledGradientStartColor;
+ gradientEndColor = disabledGradientEndColor;
+ }
+
+ int width = getWidth();
+ int height = getHeight();
+
+ Graphics2D contentGraphics = (Graphics2D)graphics.create();
+
+ // Paint the background
+ RoundRectangle2D buttonRectangle = new RoundRectangle2D.Double(0, 0,
+ width - 1, height - 1, cornerRadius, cornerRadius);
+
+ graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+
+ graphics.setPaint(new GradientPaint(width / 2, 0, gradientStartColor,
+ width / 2, height, gradientEndColor));
+ graphics.fill(buttonRectangle);
+
+ // Paint the border
+ graphics.setPaint(borderColor);
+ graphics.setStroke(new BasicStroke());
+ graphics.draw(buttonRectangle);
+
+ // Paint the content
+ Button.DataRenderer dataRenderer = pushButton.getDataRenderer();
+ dataRenderer.render(pushButton.getButtonData(), pushButton, false);
+ dataRenderer.setSize(Math.max(width - (padding.left + padding.right + 2), 0),
+ Math.max(getHeight() - (padding.top + padding.bottom + 2), 0));
+
+ contentGraphics.translate(padding.left + 1, padding.top + 1);
+ contentGraphics.clipRect(0, 0, dataRenderer.getWidth(), dataRenderer.getHeight());
+ dataRenderer.paint(contentGraphics);
+
+ // Paint the focus state
+ if (pushButton.isFocused()) {
+ BasicStroke dashStroke = new BasicStroke(1.0f, BasicStroke.CAP_ROUND,
+ BasicStroke.JOIN_ROUND, 1.0f, new float[] {0.0f, 2.0f}, 0.0f);
+
+ graphics.setColor(highlightedGradientStartColor);
+ graphics.setStroke(dashStroke);
+
+ graphics.draw(new RoundRectangle2D.Double(2, 2, Math.max(width - 5, 0),
+ Math.max(height - 5, 0), cornerRadius - 2, cornerRadius - 2));
+ }
+ }
+
+ public Font getFont() {
+ return font;
+ }
+
+ public Color getColor() {
+ return color;
+ }
+
+ public Color getDisabledColor() {
+ return disabledColor;
+ }
+}
Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/obsidian/ObsidianRadioButtonSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/obsidian/ObsidianRadioButtonSkin.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/obsidian/ObsidianRadioButtonSkin.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/obsidian/ObsidianRadioButtonSkin.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * 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 pivot.wtk.skin.obsidian;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.geom.Ellipse2D;
+
+import pivot.wtk.Button;
+import pivot.wtk.Dimensions;
+import pivot.wtk.RadioButton;
+import pivot.wtk.skin.RadioButtonSkin;
+
+/**
+ * Obsidian radio button skin.
+ * <p>
+ * TODO Button alignment style (vertical only).
+ *
+ * @author gbrown
+ */
+public class ObsidianRadioButtonSkin extends RadioButtonSkin {
+ private Font font = new Font("Verdana", Font.PLAIN, 11);
+ private Color color = Color.BLACK;
+ private Color disabledColor = new Color(0x99, 0x99, 0x99);
+ private int spacing = 3;
+
+ private static final Color BUTTON_COLOR = Color.WHITE;
+ private static final Color BUTTON_BORDER_COLOR = new Color(0x99, 0x99, 0x99);
+ private static final Color BUTTON_SELECTION_COLOR = Color.BLACK;
+ private static final Color DISABLED_BUTTON_COLOR = Color.WHITE;
+ private static final Color DISABLED_BUTTON_BORDER_COLOR = new Color(0xcc, 0xcc, 0xcc);
+ private static final Color DISABLED_BUTTON_SELECTION_COLOR = new Color(0x99, 0x99, 0x99);
+
+ private static final int BUTTON_DIAMETER = 14;
+ private static final int BUTTON_SELECTION_DIAMETER = 6;
+
+ public int getPreferredWidth(int height) {
+ RadioButton radioButton = (RadioButton)getComponent();
+ Button.DataRenderer dataRenderer = radioButton.getDataRenderer();
+
+ dataRenderer.render(radioButton.getButtonData(), radioButton, false);
+
+ int preferredWidth = BUTTON_DIAMETER
+ + dataRenderer.getPreferredWidth(height)
+ + spacing * 2;
+
+ return preferredWidth;
+ }
+
+ public int getPreferredHeight(int width) {
+ RadioButton radioButton = (RadioButton)getComponent();
+ Button.DataRenderer dataRenderer = radioButton.getDataRenderer();
+
+ dataRenderer.render(radioButton.getButtonData(), radioButton, false);
+
+ if (width != -1) {
+ width = Math.max(width - (BUTTON_DIAMETER + spacing), 0);
+ }
+
+ int preferredHeight = Math.max(BUTTON_DIAMETER,
+ dataRenderer.getPreferredHeight(width));
+
+ return preferredHeight;
+ }
+
+ public Dimensions getPreferredSize() {
+ RadioButton radioButton = (RadioButton)getComponent();
+ Button.DataRenderer dataRenderer = radioButton.getDataRenderer();
+
+ dataRenderer.render(radioButton.getButtonData(), radioButton, false);
+
+ int preferredWidth = BUTTON_DIAMETER
+ + dataRenderer.getPreferredWidth(-1)
+ + spacing * 2;
+
+ int preferredHeight = Math.max(BUTTON_DIAMETER,
+ dataRenderer.getPreferredHeight(-1));
+
+ return new Dimensions(preferredWidth, preferredHeight);
+ }
+
+ public void paint(Graphics2D graphics) {
+ RadioButton radioButton = (RadioButton)getComponent();
+ int width = getWidth();
+ int height = getHeight();
+
+ // Paint the button
+ Graphics2D buttonGraphics = (Graphics2D)graphics.create();
+ paintButton(buttonGraphics, radioButton, height);
+ buttonGraphics.dispose();
+
+ // Paint the content
+ Button.DataRenderer dataRenderer = radioButton.getDataRenderer();
+ dataRenderer.render(radioButton.getButtonData(), radioButton, false);
+ dataRenderer.setSize(Math.max(width - (BUTTON_DIAMETER + spacing * 2), 0), height);
+
+ Graphics2D contentGraphics = (Graphics2D)graphics.create();
+ contentGraphics.translate(BUTTON_DIAMETER + spacing, 0);
+ contentGraphics.clipRect(0, 0, dataRenderer.getWidth(), dataRenderer.getHeight());
+ dataRenderer.paint(contentGraphics);
+ contentGraphics.dispose();
+
+ // Paint the focus state
+ if (radioButton.isFocused()) {
+ BasicStroke dashStroke = new BasicStroke(1.0f, BasicStroke.CAP_ROUND,
+ BasicStroke.JOIN_ROUND, 1.0f, new float[] {0.0f, 2.0f}, 0.0f);
+
+ graphics.setStroke(dashStroke);
+ graphics.setColor(BUTTON_BORDER_COLOR);
+
+ graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+
+ graphics.drawRect(BUTTON_DIAMETER + 1, 0,
+ dataRenderer.getWidth() + spacing * 2 - 2,
+ dataRenderer.getHeight() - 1);
+ }
+ }
+
+ private void paintButton(Graphics2D graphics, RadioButton radioButton, int height) {
+ Color buttonColor = null;
+ Color buttonBorderColor = null;
+ Color buttonSelectionColor = null;
+
+ if (radioButton.isEnabled()) {
+ buttonColor = BUTTON_COLOR;
+ buttonBorderColor = BUTTON_BORDER_COLOR;
+ buttonSelectionColor = BUTTON_SELECTION_COLOR;
+ }
+ else {
+ buttonColor = DISABLED_BUTTON_COLOR;
+ buttonBorderColor = DISABLED_BUTTON_BORDER_COLOR;
+ buttonSelectionColor = DISABLED_BUTTON_SELECTION_COLOR;
+ }
+
+ // Center the button vertically
+ graphics.translate(0, (height - BUTTON_DIAMETER) / 2);
+
+ // Paint the border
+ graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+
+ Ellipse2D buttonCircle = new Ellipse2D.Double(0, 0,
+ BUTTON_DIAMETER - 1, BUTTON_DIAMETER - 1);
+ graphics.setColor(buttonBorderColor);
+ graphics.fill(buttonCircle);
+
+ Ellipse2D innerButtonCircle = new Ellipse2D.Double(1, 1,
+ BUTTON_DIAMETER - 3, BUTTON_DIAMETER - 3);
+ graphics.setColor(buttonBorderColor);
+ graphics.fill(buttonCircle);
+
+ graphics.setColor(buttonColor);
+ graphics.fill(innerButtonCircle);
+
+ if (radioButton.isSelected()) {
+ Ellipse2D buttonSelectionCircle = new Ellipse2D.Double((BUTTON_DIAMETER
+ - (BUTTON_SELECTION_DIAMETER - 1)) / 2,
+ (BUTTON_DIAMETER - (BUTTON_SELECTION_DIAMETER - 1)) / 2,
+ BUTTON_SELECTION_DIAMETER - 1, BUTTON_SELECTION_DIAMETER - 1);
+ graphics.setColor(buttonSelectionColor);
+ graphics.fill(buttonSelectionCircle);
+ }
+ }
+
+ public Font getFont() {
+ return font;
+ }
+
+ public void setFont(Font font) {
+ if (font == null) {
+ throw new IllegalArgumentException("font is null.");
+ }
+
+ this.font = font;
+ invalidateComponent();
+ }
+
+ public final void setFont(String font) {
+ if (font == null) {
+ throw new IllegalArgumentException("font is null.");
+ }
+
+ setFont(Font.decode(font));
+ }
+
+ public Color getColor() {
+ return color;
+ }
+
+ public void setColor(Color color) {
+ if (color == null) {
+ throw new IllegalArgumentException("color is null.");
+ }
+
+ this.color = color;
+ repaintComponent();
+ }
+
+ public final void setColor(String color) {
+ if (color == null) {
+ throw new IllegalArgumentException("color is null.");
+ }
+
+ setColor(decodeColor(color));
+ }
+
+ public Color getDisabledColor() {
+ return disabledColor;
+ }
+
+ public void setDisabledColor(Color disabledColor) {
+ if (disabledColor == null) {
+ throw new IllegalArgumentException("disabledColor is null.");
+ }
+
+ this.disabledColor = disabledColor;
+ repaintComponent();
+ }
+
+ public final void setDisabledColor(String disabledColor) {
+ if (disabledColor == null) {
+ throw new IllegalArgumentException("disabledColor is null.");
+ }
+
+ setDisabledColor(decodeColor(disabledColor));
+ }
+
+ public int getSpacing() {
+ return spacing;
+ }
+
+ public void setSpacing(int spacing) {
+ this.spacing = spacing;
+ invalidateComponent();
+ }
+
+ public final void setSpacing(Number spacing) {
+ if (spacing == null) {
+ throw new IllegalArgumentException("spacing is null.");
+ }
+
+ setSpacing(spacing.intValue());
+ }
+}
Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/obsidian/ObsidianTheme.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/obsidian/ObsidianTheme.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/obsidian/ObsidianTheme.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/obsidian/ObsidianTheme.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,31 @@
+package pivot.wtk.skin.obsidian;
+
+import java.awt.Font;
+
+import pivot.wtk.PushButton;
+import pivot.wtk.RadioButton;
+import pivot.wtk.Theme;
+
+/**
+ * Obsidian theme.
+ *
+ * @author gbrown
+ */
+public final class ObsidianTheme extends Theme {
+ private Font font = new Font("Verdana", Font.PLAIN, 11);
+
+ public ObsidianTheme() {
+ componentSkinMap.put(PushButton.class, ObsidianPushButtonSkin.class);
+ componentSkinMap.put(RadioButton.class, ObsidianRadioButtonSkin.class);
+ }
+
+ public void install() {
+ }
+
+ public void uninstall() {
+ }
+
+ public Font getFont() {
+ return font;
+ }
+}
Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/obsidian/package.html
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/obsidian/package.html?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/obsidian/package.html (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/obsidian/package.html Mon Mar 16 16:16:40 2009
@@ -0,0 +1,6 @@
+<html>
+<head></head>
+<body>
+<p>Defines skin classes for the experimental "Obsidian" theme.</p>
+</body>
+</html>
Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/package.html
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/package.html?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/package.html (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/package.html Mon Mar 16 16:16:40 2009
@@ -0,0 +1,6 @@
+<html>
+<head></head>
+<body>
+<p>Contains common skins and abstract base classes for theme-specific skins.</p>
+</body>
+</html>
Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/FadeTransition.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/FadeTransition.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/FadeTransition.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/FadeTransition.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * 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 pivot.wtk.skin.terra;
+
+import pivot.wtk.Component;
+import pivot.wtk.effects.FadeDecorator;
+import pivot.wtk.effects.Transition;
+import pivot.wtk.effects.TransitionListener;
+
+/**
+ * Fade transition class.
+ *
+ * @author gbrown
+ */
+public class FadeTransition extends Transition {
+ private Component component;
+ private FadeDecorator fadeDecorator = new FadeDecorator();
+
+ public FadeTransition(Component component, int duration, int rate) {
+ super(duration, rate, false);
+ this.component = component;
+ }
+
+ @Override
+ public void start(TransitionListener transitionListener) {
+ component.getDecorators().add(fadeDecorator);
+
+ super.start(transitionListener);
+ }
+
+ @Override
+ public void stop() {
+ component.getDecorators().remove(fadeDecorator);
+
+ super.stop();
+ }
+
+ @Override
+ protected void update() {
+ fadeDecorator.setOpacity(1.0f - getPercentComplete());
+ component.repaint();
+ }
+}
Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/SlideTransition.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/SlideTransition.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/SlideTransition.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/SlideTransition.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * 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 pivot.wtk.skin.terra;
+
+import pivot.wtk.Component;
+import pivot.wtk.effects.Transition;
+import pivot.wtk.effects.TransitionListener;
+import pivot.wtk.effects.TranslationDecorator;
+import pivot.wtk.effects.easing.Easing;
+import pivot.wtk.effects.easing.Quadratic;
+
+/**
+ * Slide transition class.
+ *
+ * @author gbrown
+ */
+public class SlideTransition extends Transition {
+ private Component component;
+ private int x0;
+ private int x1;
+ private int y0;
+ private int y1;
+ private boolean reverse;
+
+ private int x;
+ private int y;
+
+ private Easing easing = new Quadratic();
+ private TranslationDecorator translationDecorator = new TranslationDecorator(true);
+
+ public SlideTransition(Component component, int x0, int x1, int y0, int y1,
+ boolean reverse, int duration, int rate) {
+ super(duration, rate, false);
+ this.component = component;
+ this.x0 = x0;
+ this.x1 = x1;
+ this.y0 = y0;
+ this.y1 = y1;
+ this.reverse = reverse;
+ }
+
+ public int getX() {
+ return x;
+ }
+
+ public int getY() {
+ return y;
+ }
+
+ @Override
+ public void start(TransitionListener transitionListener) {
+ component.getDecorators().add(translationDecorator);
+ super.start(transitionListener);
+ }
+
+ @Override
+ public void stop() {
+ super.stop();
+ component.getDecorators().remove(translationDecorator);
+ }
+
+ @Override
+ protected void update() {
+ int elapsedTime = getElapsedTime();
+ int duration = getDuration();
+
+ x = (int)(reverse ? easing.easeIn(elapsedTime, x0, x1 - x0, duration)
+ : easing.easeOut(elapsedTime, x0, x1 - x0, duration));
+
+ y = (int)(reverse ? easing.easeOut(elapsedTime, y0, y1 - y0, duration)
+ : easing.easeOut(elapsedTime, y0, y1 - y0, duration));
+
+ translationDecorator.setOffset(x, y);
+ component.repaint();
+ }
+}