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:36:28 UTC
svn commit: r754936 [34/38] - in /incubator/pivot/tags/v1.0.1: ./
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/c...
Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/skin/terra/TerraSpinnerSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/skin/terra/TerraSpinnerSkin.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/skin/terra/TerraSpinnerSkin.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/skin/terra/TerraSpinnerSkin.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,813 @@
+/*
+ * 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 java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.GradientPaint;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+
+import pivot.collections.List;
+import pivot.wtk.ApplicationContext;
+import pivot.wtk.Component;
+import pivot.wtk.Dimensions;
+import pivot.wtk.Keyboard;
+import pivot.wtk.Mouse;
+import pivot.wtk.Bounds;
+import pivot.wtk.Spinner;
+import pivot.wtk.SpinnerListener;
+import pivot.wtk.SpinnerSelectionListener;
+import pivot.wtk.Theme;
+import pivot.wtk.media.Image;
+import pivot.wtk.skin.ComponentSkin;
+import pivot.wtk.skin.ContainerSkin;
+
+/**
+ * Spinner skin.
+ *
+ * @author tvolkert
+ */
+public class TerraSpinnerSkin extends ContainerSkin implements Spinner.Skin,
+ SpinnerListener, SpinnerSelectionListener {
+ /**
+ * Encapsulates the code needed to perform timer-controlled spinning.
+ */
+ private static class AutomaticSpinner {
+ public Spinner spinner;
+ public int direction;
+
+ private int timeoutID = -1;
+ private int intervalID = -1;
+
+ /**
+ * Starts spinning the specified spinner.
+ *
+ * @param spinner
+ * The spinner to spin
+ *
+ * @param direction
+ * <tt>1</tt> to adjust the spinner's selected index larger;
+ * <tt>-1</tt> to adjust it smaller
+ *
+ * @exception IllegalStateException
+ * If automatic spinner of any spinner is already in progress.
+ * Only one spinner may be automatically spun at one time
+ */
+ public void start(Spinner spinner, int direction) {
+ assert(direction != 0) : "Direction must be positive or negative";
+
+ if (timeoutID != -1
+ || intervalID != -1) {
+ throw new IllegalStateException("Already running");
+ }
+
+ this.spinner = spinner;
+ this.direction = direction;
+
+ // Wait a timeout period, then begin repidly spinning
+ timeoutID = ApplicationContext.setTimeout(new Runnable() {
+ public void run() {
+ intervalID = ApplicationContext.setInterval(new Runnable() {
+ public void run() {
+ spin();
+ }
+ }, 30);
+
+ timeoutID = -1;
+ }
+ }, 400);
+
+ // We initially spin once to register that we've started
+ spin();
+ }
+
+ private void spin() {
+ boolean circular = spinner.isCircular();
+ int selectedIndex = spinner.getSelectedIndex();
+ int count = spinner.getSpinnerData().getLength();
+
+ if (direction > 0) {
+ if (selectedIndex < count - 1) {
+ spinner.setSelectedIndex(selectedIndex + 1);
+ } else if (circular) {
+ spinner.setSelectedIndex(0);
+ } else {
+ stop();
+ }
+ } else {
+ if (selectedIndex > 0) {
+ spinner.setSelectedIndex(selectedIndex - 1);
+ } else if (circular) {
+ spinner.setSelectedIndex(count - 1);
+ } else {
+ stop();
+ }
+ }
+ }
+
+ /**
+ * Stops any automatic spinning in progress.
+ */
+ public void stop() {
+ if (timeoutID != -1) {
+ ApplicationContext.clearTimeout(timeoutID);
+ timeoutID = -1;
+ }
+
+ if (intervalID != -1) {
+ ApplicationContext.clearInterval(intervalID);
+ intervalID = -1;
+ }
+ }
+ }
+
+ /**
+ * Component that holds the content of a spinner. It is the focusable part
+ * of a spinner.
+ *
+ * @author tvolkert
+ */
+ protected class SpinnerContent extends Component {
+ public SpinnerContent() {
+ setSkin(new SpinnerContentSkin());
+ }
+ }
+
+ /**
+ * SpinnerContent skin.
+ *
+ * @author tvolkert
+ */
+ protected class SpinnerContentSkin extends ComponentSkin {
+ public int getPreferredWidth(int height) {
+ Spinner spinner = (Spinner)TerraSpinnerSkin.this.getComponent();
+ Spinner.ItemRenderer itemRenderer = spinner.getItemRenderer();
+
+ itemRenderer.render(spinner.getSelectedValue(), spinner);
+ return itemRenderer.getPreferredWidth(height);
+ }
+
+ public int getPreferredHeight(int width) {
+ Spinner spinner = (Spinner)TerraSpinnerSkin.this.getComponent();
+ Spinner.ItemRenderer itemRenderer = spinner.getItemRenderer();
+
+ itemRenderer.render(spinner.getSelectedValue(), spinner);
+ return itemRenderer.getPreferredHeight(width);
+ }
+
+ public Dimensions getPreferredSize() {
+ Spinner spinner = (Spinner)TerraSpinnerSkin.this.getComponent();
+ Spinner.ItemRenderer itemRenderer = spinner.getItemRenderer();
+
+ itemRenderer.render(spinner.getSelectedValue(), spinner);
+ return itemRenderer.getPreferredSize();
+ }
+
+ public void layout() {
+ // No-op
+ }
+
+ public void paint(Graphics2D graphics) {
+ SpinnerContent spinnerContent = (SpinnerContent)getComponent();
+ Spinner spinner = (Spinner)TerraSpinnerSkin.this.getComponent();
+
+ int width = getWidth();
+ int height = getHeight();
+
+ // Paint the content
+ Spinner.ItemRenderer itemRenderer = spinner.getItemRenderer();
+ itemRenderer.render(spinner.getSelectedValue(), spinner);
+
+ Graphics2D contentGraphics = (Graphics2D)graphics.create();
+ Dimensions rendererSize = itemRenderer.getPreferredSize();
+ itemRenderer.setSize(rendererSize.width, rendererSize.height);
+ itemRenderer.paint(contentGraphics);
+ contentGraphics.dispose();
+
+ // Paint the focus state
+ if (spinnerContent.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(borderColor);
+
+ graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+
+ graphics.drawRect(1, 1, Math.max(width - 3, 0),
+ Math.max(height - 3, 0));
+ }
+ }
+
+ @Override
+ public void enabledChanged(Component component) {
+ super.enabledChanged(component);
+
+ repaintComponent();
+ }
+
+ @Override
+ public void focusedChanged(Component component, boolean temporary) {
+ super.focusedChanged(component, temporary);
+
+ repaintComponent();
+ }
+
+ @Override
+ public boolean keyPressed(Component component, int keyCode, Keyboard.KeyLocation keyLocation) {
+ boolean consumed = false;
+
+ Spinner spinner = (Spinner)TerraSpinnerSkin.this.getComponent();
+
+ boolean circular = spinner.isCircular();
+ int count = spinner.getSpinnerData().getLength();
+
+ int selectedIndex = spinner.getSelectedIndex();
+ int newSelectedIndex = selectedIndex;
+
+ if (keyCode == Keyboard.KeyCode.UP) {
+ if (selectedIndex < count - 1) {
+ newSelectedIndex++;
+ } else if (circular) {
+ newSelectedIndex = 0;
+ }
+ } else if (keyCode == Keyboard.KeyCode.DOWN) {
+ if (selectedIndex > 0) {
+ newSelectedIndex--;
+ } else if (circular) {
+ newSelectedIndex = count - 1;
+ }
+ } else {
+ consumed = super.keyPressed(component, keyCode, keyLocation);
+ }
+
+ if (newSelectedIndex != selectedIndex) {
+ spinner.setSelectedIndex(newSelectedIndex);
+ consumed = true;
+ }
+
+ return consumed;
+ }
+ }
+
+ /**
+ * Spinner button.
+ *
+ * @author tvolkert
+ */
+ protected class SpinButton extends Component {
+ private int direction;
+ private Image buttonImage;
+
+ public SpinButton(int direction, Image buttonImage) {
+ this.direction = direction;
+ this.buttonImage = buttonImage;
+
+ setSkin(new SpinButtonSkin());
+ }
+
+ public int getDirection() {
+ return direction;
+ }
+
+ public Image getButtonImage() {
+ return buttonImage;
+ }
+ }
+
+ /**
+ * Spinner button skin.
+ *
+ * @author tvolkert
+ */
+ protected class SpinButtonSkin extends ComponentSkin {
+ private boolean highlighted = false;
+ private boolean pressed = false;
+
+ @Override
+ public boolean isFocusable() {
+ return false;
+ }
+
+ public int getPreferredWidth(int height) {
+ return BUTTON_IMAGE_SIZE + 6;
+ }
+
+ public int getPreferredHeight(int width) {
+ return BUTTON_IMAGE_SIZE + 2;
+ }
+
+ public Dimensions getPreferredSize() {
+ return new Dimensions(getPreferredWidth(-1), getPreferredHeight(-1));
+ }
+
+ public void layout() {
+ // No-op
+ }
+
+ public void paint(Graphics2D graphics) {
+ // Apply spinner styles to the button
+ SpinButton spinButton = (SpinButton)getComponent();
+
+ int width = getWidth();
+ int height = getHeight();
+
+ // Paint the background
+ float alpha = pressed ? 0.5f : highlighted ? 0.25f : 0.0f;
+ graphics.setPaint(new Color(0, 0, 0, alpha));
+ graphics.fillRect(0, 0, width, height);
+
+ // Paint the image
+ SpinButtonImage buttonImage = (SpinButtonImage)spinButton.getButtonImage();
+ graphics.translate((width - BUTTON_IMAGE_SIZE) / 2,
+ (height - BUTTON_IMAGE_SIZE) / 2);
+ buttonImage.paint(graphics);
+ }
+
+ @Override
+ public void enabledChanged(Component component) {
+ super.enabledChanged(component);
+
+ automaticSpinner.stop();
+
+ pressed = false;
+ highlighted = false;
+ repaintComponent();
+ }
+
+ @Override
+ public void mouseOver(Component component) {
+ super.mouseOver(component);
+
+ highlighted = true;
+ repaintComponent();
+ }
+
+ @Override
+ public void mouseOut(Component component) {
+ super.mouseOut(component);
+
+ automaticSpinner.stop();
+
+ pressed = false;
+ highlighted = false;
+ repaintComponent();
+ }
+
+ @Override
+ public boolean mouseDown(Component component, Mouse.Button button, int x, int y) {
+ boolean consumed = super.mouseDown(component, button, x, y);
+
+ if (button == Mouse.Button.LEFT) {
+ SpinButton spinButton = (SpinButton)getComponent();
+ Spinner spinner = (Spinner)TerraSpinnerSkin.this.getComponent();
+
+ // Start the automatic spinner. It'll be stopped when we
+ // mouse up or mouse out
+ automaticSpinner.start(spinner, spinButton.getDirection());
+
+ pressed = true;
+ repaintComponent();
+
+ consumed = true;
+ }
+
+ return consumed;
+ }
+
+ @Override
+ public boolean mouseUp(Component component, Mouse.Button button, int x, int y) {
+ boolean consumed = super.mouseUp(component, button, x, y);
+
+ if (button == Mouse.Button.LEFT) {
+ automaticSpinner.stop();
+
+ pressed = false;
+ repaintComponent();
+ }
+
+ return consumed;
+ }
+ }
+
+ /**
+ * Abstract base class for button images.
+ */
+ protected abstract class SpinButtonImage extends Image {
+ public int getWidth() {
+ return BUTTON_IMAGE_SIZE;
+ }
+
+ public int getHeight() {
+ return BUTTON_IMAGE_SIZE;
+ }
+
+ public void paint(Graphics2D graphics) {
+ graphics.setStroke(new BasicStroke(0));
+ graphics.setPaint(buttonImageColor);
+ }
+ }
+
+ protected class SpinUpImage extends SpinButtonImage {
+ public void paint(Graphics2D graphics) {
+ super.paint(graphics);
+
+ int[] xPoints = {0, 2, 4};
+ int[] yPoints = {3, 1, 3};
+ graphics.fillPolygon(xPoints, yPoints, 3);
+ graphics.drawPolygon(xPoints, yPoints, 3);
+ }
+ }
+
+ protected class SpinDownImage extends SpinButtonImage {
+ public void paint(Graphics2D graphics) {
+ super.paint(graphics);
+
+ int[] xPoints = {0, 2, 4};
+ int[] yPoints = {1, 3, 1};
+ graphics.fillPolygon(xPoints, yPoints, 3);
+ graphics.drawPolygon(xPoints, yPoints, 3);
+ }
+ }
+
+ private SpinnerContent spinnerContent = new SpinnerContent();
+ private SpinButton upButton = new SpinButton(1, new SpinUpImage());
+ private SpinButton downButton = new SpinButton(-1, new SpinDownImage());
+
+ private Font font;
+ private Color color;
+ private Color disabledColor;
+ private Color borderColor;
+ private Color buttonImageColor;
+ private Color buttonBackgroundColor;
+ private Color buttonDisabledBackgroundColor;
+ private Color buttonHighlightedBackgroundColor;
+
+ private static AutomaticSpinner automaticSpinner = new AutomaticSpinner();
+
+ public static final int BUTTON_IMAGE_SIZE = 5;
+
+ public TerraSpinnerSkin() {
+ TerraTheme theme = (TerraTheme)Theme.getTheme();
+ setBackgroundColor(theme.getColor(4));
+
+ font = theme.getFont();
+ color = theme.getColor(1);
+ disabledColor = theme.getColor(7);
+ borderColor = theme.getColor(7);
+ buttonImageColor = theme.getColor(1);
+ buttonBackgroundColor = theme.getColor(10);
+ buttonDisabledBackgroundColor = theme.getColor(10);
+ buttonHighlightedBackgroundColor = theme.getColor(11);
+ }
+
+ @Override
+ public void setSize(int width, int height) {
+ int previousWidth = getWidth();
+ int previousHeight = getHeight();
+
+ super.setSize(width, height);
+
+ if (previousWidth != width
+ || previousHeight != height) {
+ automaticSpinner.stop();
+ }
+ }
+
+ @Override
+ public void install(Component component) {
+ super.install(component);
+
+ Spinner spinner = (Spinner)component;
+ spinner.getSpinnerListeners().add(this);
+ spinner.getSpinnerSelectionListeners().add(this);
+
+ spinner.add(spinnerContent);
+ spinner.add(upButton);
+ spinner.add(downButton);
+ }
+
+ @Override
+ public void uninstall() {
+ Spinner spinner = (Spinner)getComponent();
+ spinner.getSpinnerListeners().remove(this);
+ spinner.getSpinnerSelectionListeners().remove(this);
+
+ spinner.remove(spinnerContent);
+ spinner.remove(upButton);
+ spinner.remove(downButton);
+
+ super.uninstall();
+ }
+
+ @Override
+ public int getPreferredWidth(int height) {
+ // Preferred width is the sum of our maximum button width plus the
+ // content width, plus the border
+
+ // Border thickness
+ int preferredWidth = 2;
+
+ int buttonHeight = (height < 0 ? -1 : height / 2);
+ preferredWidth += Math.max(upButton.getPreferredWidth(buttonHeight),
+ downButton.getPreferredWidth(buttonHeight));
+
+ if (height >= 0) {
+ // Subtract border thickness from height constraint
+ height = Math.max(height - 2, 0);
+ }
+
+ preferredWidth += spinnerContent.getPreferredWidth(height);
+
+ return preferredWidth;
+ }
+
+ @Override
+ public int getPreferredHeight(int width) {
+ // Preferred height is the maximum of the button height and the
+ // renderer's preferred height (plus the border), where button
+ // height is defined as the larger of the two buttons' preferred
+ // height, doubled.
+
+ Dimensions upButtonPreferredSize = upButton.getPreferredSize();
+ Dimensions downButtonPreferredSize = downButton.getPreferredSize();
+
+ int preferredHeight = Math.max(upButtonPreferredSize.height,
+ downButtonPreferredSize.height) * 2;
+
+ if (width >= 0) {
+ // Subtract the button and border width from width constraint
+ int buttonWidth = Math.max(upButtonPreferredSize.width,
+ downButtonPreferredSize.width);
+
+ width = Math.max(width - buttonWidth - 2, 0);
+ }
+
+ preferredHeight = Math.max(preferredHeight,
+ spinnerContent.getPreferredHeight(width)) + 1;
+
+ return preferredHeight;
+ }
+
+ @Override
+ public Dimensions getPreferredSize() {
+ // TODO Optimize
+ return new Dimensions(getPreferredWidth(-1), getPreferredHeight(-1));
+ }
+
+ public void layout() {
+ int width = getWidth();
+ int height = getHeight();
+
+ int buttonHeight = (height - 2) / 2;
+ int buttonWidth = Math.max(upButton.getPreferredWidth(buttonHeight),
+ downButton.getPreferredWidth(buttonHeight));
+
+ spinnerContent.setSize(width - buttonWidth - 3, height - 2);
+ spinnerContent.setLocation(1, 1);
+
+ upButton.setSize(buttonWidth, buttonHeight);
+ upButton.setLocation(width - buttonWidth - 1, 1);
+
+ downButton.setSize(buttonWidth, buttonHeight);
+ downButton.setLocation(width - buttonWidth - 1, height - buttonHeight - 1);
+ }
+
+ @Override
+ public void paint(Graphics2D graphics) {
+ super.paint(graphics);
+
+ int width = getWidth();
+ int height = getHeight();
+
+ int buttonX = upButton.getX();
+ int buttonWidth = upButton.getWidth();
+ int buttonHeight = upButton.getHeight();
+
+ graphics.setPaint(new GradientPaint(buttonX + buttonWidth / 2, 0, buttonHighlightedBackgroundColor,
+ buttonX + buttonWidth / 2, buttonHeight, buttonBackgroundColor));
+ graphics.fillRect(buttonX, 0, buttonWidth, height);
+
+ graphics.setStroke(new BasicStroke(0));
+ graphics.setPaint(borderColor);
+ graphics.drawRect(0, 0, width - 1, height - 1);
+ graphics.drawLine(width - buttonWidth - 2, 0,
+ width - buttonWidth - 2, height - 1);
+ graphics.drawLine(width - buttonWidth - 2, buttonHeight + 1,
+ width - 1, buttonHeight + 1);
+ }
+
+ @Override
+ public void mouseClick(Component component, Mouse.Button button, int x, int y, int count) {
+ spinnerContent.requestFocus();
+ }
+
+ protected void invalidateContent() {
+ spinnerContent.invalidate();
+ spinnerContent.repaint();
+ }
+
+ 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 Color getBorderColor() {
+ return borderColor;
+ }
+
+ public void setBorderColor(Color borderColor) {
+ if (borderColor == null) {
+ throw new IllegalArgumentException("borderColor is null.");
+ }
+
+ this.borderColor = borderColor;
+
+ repaintComponent();
+ }
+
+ public final void setBorderColor(String borderColor) {
+ if (borderColor == null) {
+ throw new IllegalArgumentException("borderColor is null.");
+ }
+
+ setBorderColor(decodeColor(borderColor));
+ }
+
+ public Color getButtonImageColor() {
+ return buttonImageColor;
+ }
+
+ public void setButtonImageColor(Color buttonImageColor) {
+ this.buttonImageColor = buttonImageColor;
+ repaintComponent();
+ }
+
+ public final void setButtonImageColor(String buttonImageColor) {
+ if (buttonImageColor == null) {
+ throw new IllegalArgumentException("buttonImageColor is null");
+ }
+
+ setButtonImageColor(decodeColor(buttonImageColor));
+ }
+
+ public Color getButtonBackgroundColor() {
+ return buttonBackgroundColor;
+ }
+
+ public void setButtonBackgroundColor(Color buttonBackgroundColor) {
+ this.buttonBackgroundColor = buttonBackgroundColor;
+ repaintComponent();
+ }
+
+ public final void setButtonBackgroundColor(String buttonBackgroundColor) {
+ if (buttonBackgroundColor == null) {
+ throw new IllegalArgumentException("buttonBackgroundColor is null");
+ }
+
+ setButtonBackgroundColor(decodeColor(buttonBackgroundColor));
+ }
+
+ public Color getButtonDisabledBackgroundColor() {
+ return buttonDisabledBackgroundColor;
+ }
+
+ public void setButtonDisabledBackgroundColor(Color buttonDisabledBackgroundColor) {
+ this.buttonDisabledBackgroundColor = buttonDisabledBackgroundColor;
+ repaintComponent();
+ }
+
+ public final void setButtonDisabledBackgroundColor(String buttonDisabledBackgroundColor) {
+ if (buttonDisabledBackgroundColor == null) {
+ throw new IllegalArgumentException("buttonDisabledBackgroundColor is null");
+ }
+
+ setButtonDisabledBackgroundColor(decodeColor(buttonDisabledBackgroundColor));
+ }
+
+ public Color getButtonHighlightedBackgroundColor() {
+ return buttonHighlightedBackgroundColor;
+ }
+
+ public void setButtonHighlightedBackgroundColor(Color buttonHighlightedBackgroundColor) {
+ this.buttonHighlightedBackgroundColor = buttonHighlightedBackgroundColor;
+ repaintComponent();
+ }
+
+ public final void setButtonHighlightedBackgroundColor(String buttonHighlightedBackgroundColor) {
+ if (buttonHighlightedBackgroundColor == null) {
+ throw new IllegalArgumentException("buttonHighlightedBackgroundColor is null");
+ }
+
+ setButtonHighlightedBackgroundColor(decodeColor(buttonHighlightedBackgroundColor));
+ }
+
+ public Font getFont() {
+ return font;
+ }
+
+ public void setFont(Font font) {
+ if (font == null) {
+ throw new IllegalArgumentException("font is null.");
+ }
+
+ this.font = font;
+
+ invalidateContent();
+ }
+
+ public final void setFont(String font) {
+ if (font == null) {
+ throw new IllegalArgumentException("font is null.");
+ }
+
+ setFont(Font.decode(font));
+ }
+
+ // Spinner.Skin methods
+
+ public Bounds getContentBounds() {
+ return spinnerContent.getBounds();
+ }
+
+ // SpinnerListener methods
+
+ public void spinnerDataChanged(Spinner spinner, List<?> previousSpinnerData) {
+ invalidateContent();
+ }
+
+ public void itemRendererChanged(Spinner spinner,
+ Spinner.ItemRenderer previousItemRenderer) {
+ invalidateContent();
+ }
+
+ public void circularChanged(Spinner spinner) {
+ // No-op
+ }
+
+ public void selectedValueKeyChanged(Spinner spinner,
+ String previousSelectedValueKey) {
+ // No-op
+ }
+
+ // SpinnerSelectionListener methods
+
+ public void selectedIndexChanged(Spinner spinner, int previousSelectedIndex) {
+ invalidateContent();
+ }
+}
Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/skin/terra/TerraSplitPaneSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/skin/terra/TerraSplitPaneSkin.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/skin/terra/TerraSplitPaneSkin.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/skin/terra/TerraSplitPaneSkin.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,540 @@
+/*
+ * 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 java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Graphics2D;
+
+import pivot.wtk.Component;
+import pivot.wtk.ComponentMouseListener;
+import pivot.wtk.ComponentMouseButtonListener;
+import pivot.wtk.Cursor;
+import pivot.wtk.Dimensions;
+import pivot.wtk.Display;
+import pivot.wtk.Mouse;
+import pivot.wtk.Orientation;
+import pivot.wtk.Point;
+import pivot.wtk.Span;
+import pivot.wtk.SplitPane;
+import pivot.wtk.SplitPaneListener;
+import pivot.wtk.Theme;
+import pivot.wtk.skin.ComponentSkin;
+import pivot.wtk.skin.ContainerSkin;
+
+/**
+ * Split pane skin.
+ *
+ * @author tvolkert
+ */
+public class TerraSplitPaneSkin extends ContainerSkin
+ implements SplitPaneListener {
+
+ /**
+ * Split pane splitter component.
+ *
+ * @author tvolkert
+ */
+ protected class Splitter extends Component {
+ public Splitter() {
+ super();
+ setSkin(new SplitterSkin());
+ }
+
+ public void updateCursor() {
+ Cursor cursor = Cursor.DEFAULT;
+ SplitPane splitPane = (SplitPane)TerraSplitPaneSkin.this.getComponent();
+
+ if (!splitPane.isLocked()) {
+ switch (splitPane.getOrientation()) {
+ case HORIZONTAL:
+ switch (splitPane.getPrimaryRegion()) {
+ case TOP_LEFT:
+ cursor = Cursor.RESIZE_EAST;
+ break;
+ case BOTTOM_RIGHT:
+ cursor = Cursor.RESIZE_WEST;
+ break;
+ }
+ break;
+
+ case VERTICAL:
+ switch (splitPane.getPrimaryRegion()) {
+ case TOP_LEFT:
+ cursor = Cursor.RESIZE_SOUTH;
+ break;
+ case BOTTOM_RIGHT:
+ cursor = Cursor.RESIZE_NORTH;
+ break;
+ }
+ break;
+ }
+ }
+
+ setCursor(cursor);
+ }
+ }
+
+ /**
+ * Split pane splitter component skin.
+ *
+ * @author tvolkert
+ */
+ protected class SplitterSkin extends ComponentSkin {
+ private class DragHandler
+ implements ComponentMouseListener, ComponentMouseButtonListener {
+ public boolean mouseMove(Component component, int x, int y) {
+ SplitPane splitPane = (SplitPane)TerraSplitPaneSkin.this.getComponent();
+
+ Orientation orientation = splitPane.getOrientation();
+
+ // Calculate the would-be new split location
+ int splitLocation;
+ if (orientation == Orientation.HORIZONTAL) {
+ splitLocation = x - dragOffset;
+ } else {
+ splitLocation = y - dragOffset;
+ }
+
+ splitLocation = boundSplitLocation(splitLocation);
+
+ if (shadow == null) {
+ // Update the split location immediately
+ splitPane.setSplitLocation(splitLocation);
+ } else {
+ // Move the shadow
+ if (orientation == Orientation.HORIZONTAL) {
+ shadow.setLocation(splitLocation, 0);
+ } else {
+ shadow.setLocation(0, splitLocation);
+ }
+ }
+
+ return false;
+ }
+
+ public void mouseOver(Component component) {
+ }
+
+ public void mouseOut(Component component) {
+ }
+
+ public boolean mouseDown(Component component, Mouse.Button button, int x, int y) {
+ return false;
+ }
+
+ public boolean mouseUp(Component component, Mouse.Button button, int x, int y) {
+ if (shadow != null) {
+ SplitPane splitPane = (SplitPane)TerraSplitPaneSkin.this.getComponent();
+
+ // Update the split location and remove the shadow
+ int splitLocation;
+ if (splitPane.getOrientation() == Orientation.HORIZONTAL) {
+ splitLocation = shadow.getX();
+ } else {
+ splitLocation = shadow.getY();
+ }
+
+ splitPane.setSplitLocation(splitLocation);
+
+ splitPane.remove(shadow);
+ shadow = null;
+ }
+
+ assert (component instanceof Display);
+ component.getComponentMouseListeners().remove(this);
+ component.getComponentMouseButtonListeners().remove(this);
+
+ return false;
+ }
+
+ public void mouseClick(Component component, Mouse.Button button, int x, int y, int count) {
+ }
+ }
+
+ private int dragOffset;
+ private SplitterShadow shadow = null;
+ private DragHandler dragHandler = new DragHandler();
+
+ @Override
+ public boolean isFocusable() {
+ return false;
+ }
+
+ public int getPreferredWidth(int height) {
+ // This will never get called since the size of the splitter is set
+ // automatically by SplitPaneSkin using the the size of the
+ // SplitPane and the split thickness
+ return 0;
+ }
+
+ public int getPreferredHeight(int width) {
+ // This will never get called since the size of the splitter is set
+ // automatically by SplitPaneSkin using the the size of the
+ // SplitPane and the split thickness
+ return 0;
+ }
+
+ public void layout() {
+ // No-op
+ }
+
+ public void paint(Graphics2D graphics) {
+ SplitPane splitPane = (SplitPane)TerraSplitPaneSkin.this.getComponent();
+
+ Orientation orientation = splitPane.getOrientation();
+
+ int width = getWidth();
+ int height = getHeight();
+
+ int imageWidth, imageHeight;
+ if (orientation == Orientation.HORIZONTAL) {
+ imageWidth = width - 4;
+ imageHeight = Math.min(height - 4, 8);
+ } else {
+ imageWidth = Math.min(width - 4, 8);
+ imageHeight = height - 4;
+ }
+
+ if (imageWidth > 0 && imageHeight > 0) {
+ int translateX = (width - imageWidth) / 2;
+ int translateY = (height - imageHeight) / 2;
+ graphics.translate(translateX, translateY);
+
+ Color dark = splitterHandlePrimaryColor;
+ Color light = splitterHandleSecondaryColor;
+
+ if (orientation == Orientation.HORIZONTAL) {
+ graphics.setStroke(new BasicStroke());
+
+ graphics.setPaint(dark);
+ graphics.drawLine(0, 0, imageWidth - 1, 0);
+ graphics.drawLine(0, 3, imageWidth - 1, 3);
+ graphics.drawLine(0, 6, imageWidth - 1, 6);
+
+ graphics.setPaint(light);
+ graphics.drawLine(0, 1, imageWidth - 1, 1);
+ graphics.drawLine(0, 4, imageWidth - 1, 4);
+ graphics.drawLine(0, 7, imageWidth - 1, 7);
+ } else {
+ int half = imageHeight / 2;
+
+ graphics.setPaint(dark);
+ graphics.fillRect(0, 0, 2, half);
+ graphics.fillRect(3, 0, 2, half);
+ graphics.fillRect(6, 0, 2, half);
+
+ graphics.setPaint(light);
+ graphics.fillRect(0, half, 2, half);
+ graphics.fillRect(3, half, 2, half);
+ graphics.fillRect(6, half, 2, half);
+ }
+ }
+ }
+
+ @Override
+ public boolean mouseDown(Component component, Mouse.Button button, int x, int y) {
+ Splitter splitter = (Splitter)getComponent();
+ SplitPane splitPane = (SplitPane)TerraSplitPaneSkin.this.getComponent();
+
+ Orientation orientation = splitPane.getOrientation();
+
+ if (!splitPane.isLocked()) {
+ int splitLocation = splitPane.getSplitLocation();
+
+ Display display = splitPane.getDisplay();
+ Point displayCoordinates = splitter.mapPointToAncestor(display, x, y);
+
+ if (orientation == Orientation.HORIZONTAL) {
+ dragOffset = displayCoordinates.x - splitLocation;
+ } else {
+ dragOffset = displayCoordinates.y - splitLocation;
+ }
+
+ if (useShadow) {
+ shadow = new SplitterShadow();
+ splitPane.add(shadow);
+
+ if (orientation == Orientation.HORIZONTAL) {
+ shadow.setLocation(splitter.getX(), 0);
+ } else {
+ shadow.setLocation(0, splitter.getY());
+ }
+ shadow.setSize(getWidth(), getHeight());
+ }
+
+ display.getComponentMouseListeners().add(dragHandler);
+ display.getComponentMouseButtonListeners().add(dragHandler);
+ }
+
+ return false;
+ }
+
+ private int boundSplitLocation(int splitLocation) {
+ SplitPane splitPane = (SplitPane)TerraSplitPaneSkin.this.getComponent();
+
+ int lower = 0;
+ int upper;
+ if (splitPane.getOrientation() == Orientation.HORIZONTAL) {
+ upper = splitPane.getWidth() - splitterThickness;
+ } else {
+ upper = splitPane.getHeight() - splitterThickness;
+ }
+
+ Span bounds = splitPane.getSplitBounds();
+ if (bounds != null) {
+ lower = Math.max(lower, bounds.getStart());
+ upper = Math.min(upper, bounds.getEnd());
+ }
+
+ if (splitLocation < lower) {
+ splitLocation = lower;
+ } else if (splitLocation > upper) {
+ splitLocation = upper;
+ }
+
+ return splitLocation;
+ }
+ }
+
+ /**
+ * Split pane splitter shadow component.
+ *
+ * @author tvolkert
+ */
+ protected class SplitterShadow extends Component {
+ public SplitterShadow() {
+ super();
+ setSkin(new SplitterShadowSkin());
+ }
+ }
+
+ /**
+ * Split pane splitter shadow component skin.
+ *
+ * @author tvolkert
+ */
+ protected class SplitterShadowSkin extends ComponentSkin {
+ public int getPreferredWidth(int height) {
+ // This will never get called since the splitter will always just
+ // set the size of its shadow to match its own size
+ return 0;
+ }
+
+ public int getPreferredHeight(int width) {
+ // This will never get called since the splitter will always just
+ // set the size of its shadow to match its own size
+ return 0;
+ }
+
+ public void layout() {
+ // No-op
+ }
+
+ public void paint(Graphics2D graphics) {
+ graphics.setStroke(new BasicStroke());
+ graphics.setPaint(new Color(0, 0, 0, 64));
+ graphics.fillRect(0, 0, getWidth(), getHeight());
+ }
+ }
+
+ private Splitter splitter = new Splitter();
+
+ private Color splitterHandlePrimaryColor;
+ private Color splitterHandleSecondaryColor;
+ private int splitterThickness;
+ private boolean useShadow;
+
+ public TerraSplitPaneSkin() {
+ TerraTheme theme = (TerraTheme)Theme.getTheme();
+ splitterHandlePrimaryColor = theme.getColor(9);
+ splitterHandleSecondaryColor = theme.getColor(10);
+ splitterThickness = 6;
+ useShadow = false;
+ }
+
+ @Override
+ public void install(Component component) {
+ super.install(component);
+
+ SplitPane splitPane = (SplitPane)component;
+ splitPane.getSplitPaneListeners().add(this);
+
+ splitPane.add(splitter);
+ splitter.updateCursor();
+ }
+
+ @Override
+ public void uninstall() {
+ SplitPane splitPane = (SplitPane)getComponent();
+ splitPane.getSplitPaneListeners().remove(this);
+
+ splitPane.remove(splitter);
+
+ super.uninstall();
+ }
+
+ @Override
+ public int getPreferredWidth(int height) {
+ return 0;
+ }
+
+ @Override
+ public int getPreferredHeight(int width) {
+ return 0;
+ }
+
+ @Override
+ public Dimensions getPreferredSize() {
+ return new Dimensions(0, 0);
+ }
+
+ public void layout() {
+ int width = getWidth();
+ int height = getHeight();
+
+ SplitPane splitPane = (SplitPane)getComponent();
+ int splitLocation = splitPane.getSplitLocation();
+ Component leftComponent = splitPane.getTopLeftComponent();
+ Component rightComponent = splitPane.getBottomRightComponent();
+
+ int rightStart = splitLocation + splitterThickness;
+
+ if (splitPane.getOrientation() == Orientation.HORIZONTAL) {
+ splitter.setLocation(splitLocation, 0);
+ splitter.setSize(splitterThickness, height);
+
+ if (leftComponent != null) {
+ leftComponent.setLocation(0, 0);
+ leftComponent.setSize(splitLocation, height);
+ }
+
+ if (rightComponent != null) {
+ rightComponent.setLocation(rightStart, 0);
+ rightComponent.setSize(Math.max(width - rightStart, 0), height);
+ }
+ } else {
+ splitter.setLocation(0, splitLocation);
+ splitter.setSize(width, splitterThickness);
+
+ if (leftComponent != null) {
+ leftComponent.setLocation(0, 0);
+ leftComponent.setSize(width, splitLocation);
+ }
+
+ if (rightComponent != null) {
+ rightComponent.setLocation(0, rightStart);
+ rightComponent.setSize(width, Math.max(height - rightStart, 0));
+ }
+ }
+ }
+
+ public Color getSplitterHandlePrimaryColor() {
+ return splitterHandlePrimaryColor;
+ }
+
+ public void setSplitterHandlePrimaryColor(Color splitterHandlePrimaryColor) {
+ if (splitterHandlePrimaryColor == null) {
+ throw new IllegalArgumentException("splitterHandlePrimaryColor is null.");
+ }
+
+ this.splitterHandlePrimaryColor = splitterHandlePrimaryColor;
+ splitter.repaint();
+ }
+
+ public final void setSplitterHandlePrimaryColor(String splitterHandlePrimaryColor) {
+ if (splitterHandlePrimaryColor == null) {
+ throw new IllegalArgumentException("splitterHandlePrimaryColor is null.");
+ }
+
+ setSplitterHandlePrimaryColor(decodeColor(splitterHandlePrimaryColor));
+ }
+
+ public Color getSplitterHandleSecondaryColor() {
+ return splitterHandleSecondaryColor;
+ }
+
+ public void setSplitterHandleSecondaryColor(Color splitterHandleSecondaryColor) {
+ if (splitterHandleSecondaryColor == null) {
+ throw new IllegalArgumentException("splitterHandleSecondaryColor is null.");
+ }
+
+ this.splitterHandleSecondaryColor = splitterHandleSecondaryColor;
+ splitter.repaint();
+ }
+
+ public final void setSplitterHandleSecondaryColor(String splitterHandleSecondaryColor) {
+ if (splitterHandleSecondaryColor == null) {
+ throw new IllegalArgumentException("splitterHandleSecondaryColor is null.");
+ }
+
+ setSplitterHandleSecondaryColor(decodeColor(splitterHandleSecondaryColor));
+ }
+
+ public int getSplitterThickness() {
+ return splitterThickness;
+ }
+
+ public void setSplitterThickness(int splitterThickness) {
+ this.splitterThickness = splitterThickness;
+ invalidateComponent();
+ }
+
+ public final void setSplitterThickness(String splitterThickness) {
+ if (splitterThickness == null) {
+ throw new IllegalArgumentException("splitterThickness is null.");
+ }
+
+ setSplitterThickness(Integer.parseInt(splitterThickness));
+ }
+
+ public boolean getUseShadow() {
+ return useShadow;
+ }
+
+ public void setUseShadow(boolean useShadow) {
+ this.useShadow = useShadow;
+ }
+
+ public void topLeftComponentChanged(SplitPane splitPane, Component previousTopLeftComponent) {
+ // No-op
+ }
+
+ public void bottomRightComponentChanged(SplitPane splitPane, Component previousBottomRightComponent) {
+ // No-op
+ }
+
+ public void orientationChanged(SplitPane splitPane) {
+ splitter.updateCursor();
+ invalidateComponent();
+ }
+
+ public void primaryRegionChanged(SplitPane splitPane) {
+ splitter.updateCursor();
+ }
+
+ public void splitLocationChanged(SplitPane splitPane, int previousSplitLocation) {
+ invalidateComponent();
+ }
+
+ public void splitBoundsChanged(SplitPane splitPane, Span previousSplitBounds) {
+ invalidateComponent();
+ }
+
+ public void lockedChanged(SplitPane splitPane) {
+ splitter.updateCursor();
+ }
+}
Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/skin/terra/TerraTabPaneSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/skin/terra/TerraTabPaneSkin.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/skin/terra/TerraTabPaneSkin.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/skin/terra/TerraTabPaneSkin.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,990 @@
+/*
+ * 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 java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.GradientPaint;
+import java.awt.Graphics2D;
+
+import pivot.collections.Dictionary;
+import pivot.collections.Sequence;
+import pivot.wtk.Button;
+import pivot.wtk.Component;
+import pivot.wtk.Dimensions;
+import pivot.wtk.FlowPane;
+import pivot.wtk.HorizontalAlignment;
+import pivot.wtk.Insets;
+import pivot.wtk.Mouse;
+import pivot.wtk.Orientation;
+import pivot.wtk.Panorama;
+import pivot.wtk.Bounds;
+import pivot.wtk.TabPane;
+import pivot.wtk.TabPaneListener;
+import pivot.wtk.TabPaneSelectionListener;
+import pivot.wtk.TabPaneAttributeListener;
+import pivot.wtk.Theme;
+import pivot.wtk.VerticalAlignment;
+import pivot.wtk.Button.Group;
+import pivot.wtk.content.ButtonData;
+import pivot.wtk.content.ButtonDataRenderer;
+import pivot.wtk.media.Image;
+import pivot.wtk.skin.ButtonSkin;
+import pivot.wtk.skin.ContainerSkin;
+
+/**
+ * Tab pane skin.
+ * <p>
+ * TODO Make tab buttons focusable?
+ * <p>
+ * TODO Disable the tab button when the component is disabled? We'd need
+ * style properties to present a disabled tab button state. We'd also need
+ * to manage button enabled state independently of tab pane enabled state.
+ * <p>
+ * TODO Support the displayable flag to show/hide tabs.
+ * <p>
+ * TODO Add showCloseButton style.
+ *
+ * @author gbrown
+ */
+public class TerraTabPaneSkin extends ContainerSkin
+ implements TabPaneListener, TabPaneSelectionListener, TabPaneAttributeListener,
+ Button.GroupListener {
+ protected class TabButton extends Button {
+ public TabButton() {
+ this(null);
+ }
+
+ public TabButton(Object buttonData) {
+ super(buttonData);
+
+ super.setToggleButton(true);
+ setDataRenderer(DEFAULT_DATA_RENDERER);
+
+ setSkin(new TabButtonSkin());
+ }
+
+ @Override
+ public boolean isEnabled() {
+ TabPane tabPane = (TabPane)TerraTabPaneSkin.this.getComponent();
+ return tabPane.isEnabled();
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setToggleButton(boolean toggleButton) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setTriState(boolean triState) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void press() {
+ // If the tab pane is collapsible, toggle the button selection;
+ // otherwise, select it
+ TabPane tabPane = (TabPane)TerraTabPaneSkin.this.getComponent();
+ setSelected(tabPane.isCollapsible() ? !isSelected() : true);
+
+ super.press();
+ }
+ }
+
+ protected class TabButtonSkin extends ButtonSkin {
+ public int getPreferredWidth(int height) {
+ TabButton tabButton = (TabButton)getComponent();
+ TabPane tabPane = (TabPane)TerraTabPaneSkin.this.getComponent();
+
+ Button.DataRenderer dataRenderer = tabButton.getDataRenderer();
+ dataRenderer.render(tabButton.getButtonData(), tabButton, false);
+
+ // Include padding in constraint
+ if (height != -1) {
+ height = Math.max(height - (buttonPadding.top + buttonPadding.bottom + 2), 0);
+ }
+
+ int preferredWidth = 0;
+ switch (tabPane.getTabOrientation()) {
+ case HORIZONTAL: {
+ preferredWidth = dataRenderer.getPreferredWidth(height)
+ + buttonPadding.left + buttonPadding.right + 2;
+ break;
+ }
+
+ case VERTICAL: {
+ preferredWidth = dataRenderer.getPreferredHeight(height)
+ + buttonPadding.top + buttonPadding.bottom + 2;
+ break;
+ }
+ }
+
+ return preferredWidth;
+ }
+
+ public int getPreferredHeight(int width) {
+ TabButton tabButton = (TabButton)getComponent();
+ TabPane tabPane = (TabPane)TerraTabPaneSkin.this.getComponent();
+
+ Button.DataRenderer dataRenderer = tabButton.getDataRenderer();
+ dataRenderer.render(tabButton.getButtonData(), tabButton, false);
+
+ // Include padding in constraint
+ if (width != -1) {
+ width = Math.max(width - (buttonPadding.left + buttonPadding.right + 2), 0);
+ }
+
+ int preferredHeight = 0;
+ switch (tabPane.getTabOrientation()) {
+ case HORIZONTAL: {
+ preferredHeight = dataRenderer.getPreferredHeight(width)
+ + buttonPadding.top + buttonPadding.bottom + 2;
+ break;
+ }
+
+ case VERTICAL: {
+ preferredHeight = dataRenderer.getPreferredWidth(width)
+ + buttonPadding.left + buttonPadding.right + 2;
+ break;
+ }
+ }
+
+ return preferredHeight;
+ }
+
+ public Dimensions getPreferredSize() {
+ TabButton tabButton = (TabButton)getComponent();
+ TabPane tabPane = (TabPane)TerraTabPaneSkin.this.getComponent();
+
+ Button.DataRenderer dataRenderer = tabButton.getDataRenderer();
+ dataRenderer.render(tabButton.getButtonData(), tabButton, false);
+
+ Dimensions preferredContentSize = dataRenderer.getPreferredSize();
+
+ int preferredWidth = 0;
+ int preferredHeight = 0;
+ switch (tabPane.getTabOrientation()) {
+ case HORIZONTAL: {
+ preferredWidth = preferredContentSize.width
+ + buttonPadding.left + buttonPadding.right + 2;
+
+ preferredHeight = preferredContentSize.height
+ + buttonPadding.top + buttonPadding.bottom + 2;
+
+ break;
+ }
+
+ case VERTICAL: {
+ preferredWidth = preferredContentSize.height
+ + buttonPadding.top + buttonPadding.bottom + 2;
+
+ preferredHeight = preferredContentSize.width
+ + buttonPadding.left + buttonPadding.right + 2;
+
+ break;
+ }
+ }
+
+ return new Dimensions(preferredWidth, preferredHeight);
+ }
+
+ public void paint(Graphics2D graphics) {
+ TabButton tabButton = (TabButton)getComponent();
+ TabPane tabPane = (TabPane)TerraTabPaneSkin.this.getComponent();
+ Orientation tabOrientation = tabPane.getTabOrientation();
+
+ Color backgroundColor = (tabButton.isSelected()) ?
+ activeTabColor : inactiveTabColor;
+
+ int width = getWidth();
+ int height = getHeight();
+
+ graphics.setStroke(new BasicStroke());
+
+ // Draw the background
+ graphics.setPaint(backgroundColor);
+ graphics.fillRect(0, 0, width, height);
+
+ // Draw the bevel
+ graphics.setPaint(new GradientPaint(width / 2, 1, buttonBevelColor,
+ width / 2, GRADIENT_BEVEL_THICKNESS, backgroundColor));
+
+ switch(tabOrientation) {
+ case HORIZONTAL: {
+ graphics.fillRect(1, 1, width - 2, GRADIENT_BEVEL_THICKNESS);
+ break;
+ }
+
+ case VERTICAL: {
+ graphics.fillRect(1, 1, width - 1, GRADIENT_BEVEL_THICKNESS);
+ break;
+ }
+ }
+
+ // Draw the border
+ graphics.setPaint(borderColor);
+
+ if (tabButton.isSelected()) {
+ switch(tabOrientation) {
+ case HORIZONTAL: {
+ graphics.drawLine(0, height - 1, 0, 0);
+ graphics.drawLine(0, 0, width - 1, 0);
+ graphics.drawLine(width - 1, 0, width - 1, height - 1);
+ break;
+ }
+
+ case VERTICAL: {
+ graphics.drawLine(width, 0, 0, 0);
+ graphics.drawLine(0, 0, 0, height - 1);
+ graphics.drawLine(0, height - 1, width - 1, height - 1);
+ break;
+ }
+ }
+ } else {
+ graphics.drawRect(0, 0, width - 1, height - 1);
+ }
+
+ // Paint the content
+ Button.DataRenderer dataRenderer = tabButton.getDataRenderer();
+ dataRenderer.render(tabButton.getButtonData(), tabButton, false);
+
+ Graphics2D contentGraphics = (Graphics2D)graphics.create();
+
+ switch (tabOrientation) {
+ case HORIZONTAL: {
+ dataRenderer.setSize(Math.max(getWidth() - (buttonPadding.left + buttonPadding.right + 2), 0),
+ Math.max(getHeight() - (buttonPadding.top + buttonPadding.bottom + 2), 0));
+
+ contentGraphics.translate(buttonPadding.left + 1, buttonPadding.top + 1);
+ break;
+ }
+
+ case VERTICAL: {
+ dataRenderer.setSize(Math.max(getHeight() - (buttonPadding.top + buttonPadding.bottom + 2), 0),
+ Math.max(getWidth() - (buttonPadding.left + buttonPadding.right + 2), 0));
+
+ contentGraphics.translate(buttonPadding.top + 1, buttonPadding.left + 1);
+ contentGraphics.rotate(-Math.PI / 2d);
+ contentGraphics.translate(-dataRenderer.getWidth(), 0);
+ break;
+ }
+ }
+
+ contentGraphics.clipRect(0, 0, dataRenderer.getWidth(), dataRenderer.getHeight());
+ dataRenderer.paint(contentGraphics);
+
+ contentGraphics.dispose();
+ }
+
+ @Override
+ public boolean isFocusable() {
+ return false;
+ }
+
+ @Override
+ public void mouseClick(Component component, Mouse.Button button, int x, int y, int count) {
+ TabButton tabButton = (TabButton)getComponent();
+ tabButton.press();
+ }
+
+ public Font getFont() {
+ return buttonFont;
+ }
+
+ public Color getColor() {
+ return buttonColor;
+ }
+
+ public Color getDisabledColor() {
+ return buttonColor;
+ }
+ }
+
+ protected Panorama buttonPanorama = new Panorama();
+ protected FlowPane buttonFlowPane = new FlowPane();
+ private Button.Group tabButtonGroup = new Button.Group();
+
+ private Color activeTabColor;
+ private Color inactiveTabColor;
+ private Color borderColor;
+ private Insets padding;
+ private Font buttonFont;
+ private Color buttonColor;
+ private Insets buttonPadding;
+
+ // Derived colors
+ private Color buttonBevelColor;
+
+ public static final int GRADIENT_BEVEL_THICKNESS = 4;
+ private static final Button.DataRenderer DEFAULT_DATA_RENDERER = new ButtonDataRenderer();
+
+ public TerraTabPaneSkin() {
+ TerraTheme theme = (TerraTheme)Theme.getTheme();
+ activeTabColor = theme.getColor(11);
+ inactiveTabColor = theme.getColor(9);
+ borderColor = theme.getColor(7);
+ padding = new Insets(6);
+ buttonFont = theme.getFont();
+ buttonColor = theme.getColor(1);
+ buttonPadding = new Insets(3, 4, 3, 4);
+
+ // Set the derived colors
+ buttonBevelColor = TerraTheme.brighten(inactiveTabColor);
+
+ tabButtonGroup.getGroupListeners().add(this);
+
+ buttonFlowPane.getStyles().put("spacing", 2);
+ }
+
+ public void install(Component component) {
+ super.install(component);
+
+ TabPane tabPane = (TabPane)component;
+
+ // Add this as a listener on the tab pane
+ tabPane.getTabPaneListeners().add(this);
+ tabPane.getTabPaneSelectionListeners().add(this);
+ tabPane.getTabPaneAttributeListeners().add(this);
+
+ // Add the button panorama and flow pane
+ buttonPanorama.getStyles().put("buttonBackgroundColor", borderColor);
+ buttonPanorama.getStyles().put("buttonPadding", 6);
+ buttonPanorama.setView(buttonFlowPane);
+ tabPane.add(buttonPanorama);
+
+ // Apply the current tab orientation
+ tabOrientationChanged(tabPane);
+
+ // Add buttons for all existing tabs
+ for (Component tab : tabPane.getTabs()) {
+ TabButton tabButton = new TabButton(new ButtonData(TabPane.getIcon(tab),
+ TabPane.getName(tab)));
+ tabButton.setGroup(tabButtonGroup);
+
+ buttonFlowPane.add(tabButton);
+ }
+
+ selectedIndexChanged(tabPane, -1);
+ }
+
+ public void uninstall() {
+ TabPane tabPane = (TabPane)getComponent();
+
+ // Remove this as a listener on the tab pane
+ tabPane.getTabPaneListeners().remove(this);
+ tabPane.getTabPaneSelectionListeners().remove(this);
+ tabPane.getTabPaneAttributeListeners().remove(this);
+
+ // Remove the button panorama
+ tabPane.remove(buttonPanorama);
+
+ super.uninstall();
+ }
+
+ public int getPreferredWidth(int height) {
+ int preferredWidth = 0;
+
+ TabPane tabPane = (TabPane)getComponent();
+ Orientation tabOrientation = tabPane.getTabOrientation();
+ Component corner = tabPane.getCorner();
+
+ switch (tabOrientation) {
+ case HORIZONTAL: {
+ if (height != -1) {
+ if (corner != null
+ && corner.isDisplayable()) {
+ height = Math.max(height - Math.max(corner.getPreferredHeight(-1),
+ Math.max(buttonPanorama.getPreferredHeight(-1) - 1, 0)), 0);
+ } else {
+ height = Math.max(height - (buttonPanorama.getPreferredHeight(-1) - 1), 0);
+ }
+
+ height = Math.max(height - (padding.top + padding.bottom + 2), 0);
+ }
+
+ if (tabPane.getSelectedIndex() != -1) {
+ for (Component tab : tabPane.getTabs()) {
+ preferredWidth = Math.max(preferredWidth,
+ tab.getPreferredWidth(height));
+ }
+
+ preferredWidth += (padding.left + padding.right + 2);
+ }
+
+ int buttonAreaPreferredWidth = buttonPanorama.getPreferredWidth(-1);
+
+ if (corner != null
+ && corner.isDisplayable()) {
+ buttonAreaPreferredWidth += corner.getPreferredWidth(-1);
+ }
+
+ preferredWidth = Math.max(preferredWidth,
+ buttonAreaPreferredWidth);
+
+ break;
+ }
+
+ case VERTICAL: {
+ if (height != -1) {
+ height = Math.max(height - (padding.top + padding.bottom + 2), 0);
+ }
+
+ if (tabPane.getSelectedIndex() != -1) {
+ for (Component tab : tabPane.getTabs()) {
+ preferredWidth = Math.max(preferredWidth,
+ tab.getPreferredWidth(height));
+ }
+
+ preferredWidth += (padding.left + padding.right + 2);
+ } else {
+ preferredWidth += 1;
+ }
+
+ if (corner != null
+ && corner.isDisplayable()) {
+ preferredWidth += Math.max(corner.getPreferredWidth(-1),
+ Math.max(buttonPanorama.getPreferredWidth(-1) - 1, 0));
+ } else {
+ preferredWidth += Math.max(buttonPanorama.getPreferredWidth(-1) - 1, 0);
+ }
+
+ break;
+ }
+ }
+
+ return preferredWidth;
+ }
+
+ public int getPreferredHeight(int width) {
+ int preferredHeight = 0;
+
+ TabPane tabPane = (TabPane)getComponent();
+ Orientation tabOrientation = tabPane.getTabOrientation();
+ Component corner = tabPane.getCorner();
+
+ switch (tabOrientation) {
+ case HORIZONTAL: {
+ if (width != -1) {
+ width = Math.max(width - (padding.left + padding.right + 2), 0);
+ }
+
+ if (tabPane.getSelectedIndex() != -1) {
+ for (Component tab : tabPane.getTabs()) {
+ preferredHeight = Math.max(preferredHeight,
+ tab.getPreferredHeight(width));
+ }
+
+ preferredHeight += (padding.top + padding.bottom + 2);
+ } else {
+ preferredHeight += 1;
+ }
+
+ if (corner != null
+ && corner.isDisplayable()) {
+ preferredHeight += Math.max(corner.getPreferredHeight(-1),
+ Math.max(buttonPanorama.getPreferredHeight(-1) - 1, 0));
+ } else {
+ preferredHeight += Math.max(buttonPanorama.getPreferredHeight(-1) - 1, 0);
+ }
+
+ break;
+ }
+
+ case VERTICAL: {
+ if (width != -1) {
+ if (corner != null
+ && corner.isDisplayable()) {
+ width = Math.max(width - Math.max(corner.getPreferredWidth(-1),
+ Math.max(buttonPanorama.getPreferredWidth(-1) - 1, 0)), 0);
+ } else {
+ width = Math.max(width - (buttonPanorama.getPreferredWidth(-1) - 1), 0);
+ }
+
+ width = Math.max(width - (padding.left + padding.right + 2), 0);
+ }
+
+ if (tabPane.getSelectedIndex() != -1) {
+ for (Component tab : tabPane.getTabs()) {
+ preferredHeight = Math.max(preferredHeight,
+ tab.getPreferredHeight(width));
+ }
+
+ preferredHeight += (padding.top + padding.bottom + 2);
+ }
+
+ int buttonAreaPreferredHeight = buttonPanorama.getPreferredHeight(-1);
+
+ if (corner != null
+ && corner.isDisplayable()) {
+ buttonAreaPreferredHeight += corner.getPreferredHeight(-1);
+ }
+
+ preferredHeight = Math.max(preferredHeight,
+ buttonAreaPreferredHeight);
+
+ break;
+ }
+ }
+
+ return preferredHeight;
+ }
+
+ public Dimensions getPreferredSize() {
+ // TODO Optimize
+ return new Dimensions(getPreferredWidth(-1), getPreferredHeight(-1));
+ }
+
+ public void layout() {
+ TabPane tabPane = (TabPane)getComponent();
+ Component corner = tabPane.getCorner();
+
+ int width = getWidth();
+ int height = getHeight();
+
+ int tabX = 0;
+ int tabY = 0;
+ int tabWidth = 0;
+ int tabHeight = 0;
+
+ Dimensions buttonPanoramaPreferredSize = buttonPanorama.getPreferredSize();
+
+ switch (tabPane.getTabOrientation()) {
+ case HORIZONTAL: {
+ int buttonPanoramaWidth = Math.min(width,
+ buttonPanoramaPreferredSize.width);
+ int buttonPanoramaHeight = buttonPanoramaPreferredSize.height;
+ int buttonPanoramaX = 0;
+ int buttonPanoramaY = 0;
+
+ if (corner != null) {
+ if (corner.isDisplayable()) {
+ int cornerWidth = width - buttonPanoramaWidth;
+ int cornerHeight = Math.max(corner.getPreferredHeight(-1), buttonPanoramaPreferredSize.height - 1);
+ int cornerX = buttonPanoramaWidth;
+ int cornerY = Math.max(buttonPanoramaHeight - cornerHeight - 1, 0);
+
+ buttonPanoramaY = Math.max(cornerHeight - buttonPanoramaHeight + 1, 0);
+
+ corner.setVisible(true);
+ corner.setLocation(cornerX, cornerY);
+ corner.setSize(cornerWidth, cornerHeight);
+ } else {
+ corner.setVisible(false);
+ }
+ }
+
+ buttonPanorama.setLocation(buttonPanoramaX, buttonPanoramaY);
+ buttonPanorama.setSize(buttonPanoramaWidth, buttonPanoramaHeight);
+
+ tabX = padding.left + 1;
+ tabY = padding.top + buttonPanoramaY + buttonPanoramaHeight;
+ tabWidth = Math.max(width - (padding.left + padding.right + 2), 0);
+ tabHeight = Math.max(height - (padding.top + padding.bottom
+ + buttonPanoramaY + buttonPanoramaHeight + 1), 0);
+
+ break;
+ }
+
+ case VERTICAL: {
+ int buttonPanoramaWidth = buttonPanoramaPreferredSize.width;
+ int buttonPanoramaHeight = Math.min(height,
+ buttonPanoramaPreferredSize.height);
+ int buttonPanoramaX = 0;
+ int buttonPanoramaY = 0;
+
+ if (corner != null) {
+ if (corner.isDisplayable()) {
+ int cornerWidth = corner.getPreferredWidth(-1);
+ int cornerHeight = height - buttonPanoramaHeight;
+ int cornerX = Math.max(buttonPanoramaWidth - cornerWidth - 1, 0);
+ int cornerY = buttonPanoramaHeight;
+
+ buttonPanoramaX = Math.max(cornerWidth - buttonPanoramaWidth + 1, 0);
+
+ corner.setVisible(true);
+ corner.setLocation(cornerX, cornerY);
+ corner.setSize(cornerWidth, cornerHeight);
+ } else {
+ corner.setVisible(false);
+ }
+ }
+
+ buttonPanorama.setLocation(buttonPanoramaX, buttonPanoramaY);
+ buttonPanorama.setSize(buttonPanoramaWidth, buttonPanoramaHeight);
+
+ tabX = padding.left + buttonPanoramaX + buttonPanoramaWidth;
+ tabY = padding.top + 1;
+ tabWidth = Math.max(width - (padding.left + padding.right
+ + buttonPanoramaX + buttonPanoramaWidth + 1), 0);
+ tabHeight = Math.max(height - (padding.top + padding.bottom + 2), 0);
+
+ break;
+ }
+ }
+
+ TabPane.TabSequence tabs = tabPane.getTabs();
+ int selectedIndex = tabPane.getSelectedIndex();
+
+ for (int i = 0, n = tabs.getLength(); i < n; i++) {
+ Component tab = tabs.get(i);
+ if (i == selectedIndex) {
+ // Show the selected tab
+ tab.setVisible(true);
+
+ // Set the tab's size and location
+ tab.setLocation(tabX, tabY);
+ tab.setSize(tabWidth, tabHeight);
+ } else {
+ tab.setVisible(false);
+ }
+ }
+ }
+
+ @Override
+ public void paint(Graphics2D graphics) {
+ TabPane tabPane = (TabPane)getComponent();
+
+ Bounds tabPaneBounds = tabPane.getBounds();
+
+ // Call the base class to paint the background
+ super.paint(graphics);
+
+ graphics.setStroke(new BasicStroke());
+
+ // Paint the content background and border
+ int x = 0;
+ int y = 0;
+ int width = 0;
+ int height = 0;
+
+ Orientation tabOrientation = tabPane.getTabOrientation();
+
+ switch (tabOrientation) {
+ case HORIZONTAL: {
+ x = 0;
+ y = Math.max(buttonPanorama.getY() + buttonPanorama.getHeight() - 1, 0);
+ width = tabPaneBounds.width;
+ height = Math.max(tabPaneBounds.height - (y + 1), 0);
+
+ break;
+ }
+
+ case VERTICAL: {
+ x = Math.max(buttonPanorama.getX() + buttonPanorama.getWidth() - 1, 0);
+ y = 0;
+ width = Math.max(tabPaneBounds.width - (x + 1), 0);
+ height = tabPaneBounds.height;
+
+ break;
+ }
+ }
+
+ Bounds contentBounds = new Bounds(x, y, width, height);
+
+ if (!contentBounds.isEmpty()) {
+ // If a tab is selected, paint the active background color; otherwise,
+ // paint the inactive background color
+ int selectedIndex = tabPane.getSelectedIndex();
+ graphics.setPaint((selectedIndex == -1) ? inactiveTabColor : activeTabColor);
+ graphics.fillRect(contentBounds.x, contentBounds.y,
+ contentBounds.width, contentBounds.height);
+
+ // Draw the border
+ graphics.setPaint(borderColor);
+ graphics.drawRect(contentBounds.x, contentBounds.y,
+ Math.max(contentBounds.width - 1, 0),
+ Math.max(contentBounds.height - 1, 0));
+
+ // Draw the bevel for vertical tabs
+ if (tabOrientation == Orientation.VERTICAL) {
+ graphics.setPaint(new GradientPaint(width / 2, contentBounds.y + 1, buttonBevelColor,
+ width / 2, contentBounds.y + 1 + GRADIENT_BEVEL_THICKNESS, activeTabColor));
+ graphics.fillRect(contentBounds.x + 1, contentBounds.y + 1,
+ contentBounds.width - 2, GRADIENT_BEVEL_THICKNESS);
+ }
+ }
+ }
+
+ public Color getActiveTabColor() {
+ return activeTabColor;
+ }
+
+ public void setActiveTabColor(Color activeTabColor) {
+ if (activeTabColor == null) {
+ throw new IllegalArgumentException("activeTabColor is null.");
+ }
+
+ this.activeTabColor = activeTabColor;
+ repaintComponent();
+ }
+
+ public final void setActiveTabColor(String activeTabColor) {
+ if (activeTabColor == null) {
+ throw new IllegalArgumentException("activeTabColor is null.");
+ }
+
+ setActiveTabColor(decodeColor(activeTabColor));
+ }
+
+ public Color getInactiveTabColor() {
+ return inactiveTabColor;
+ }
+
+ public void setInactiveTabColor(Color inactiveTabColor) {
+ if (inactiveTabColor == null) {
+ throw new IllegalArgumentException("inactiveTabColor is null.");
+ }
+
+ this.inactiveTabColor = inactiveTabColor;
+ buttonBevelColor = TerraTheme.brighten(inactiveTabColor);
+ repaintComponent();
+ }
+
+ public final void setInactiveTabColor(String inactiveTabColor) {
+ if (inactiveTabColor == null) {
+ throw new IllegalArgumentException("inactiveTabColor is null.");
+ }
+
+ setInactiveTabColor(decodeColor(inactiveTabColor));
+ }
+
+ public Color getBorderColor() {
+ return borderColor;
+ }
+
+ public void setBorderColor(Color borderColor) {
+ if (borderColor == null) {
+ throw new IllegalArgumentException("borderColor is null.");
+ }
+
+ this.borderColor = borderColor;
+ buttonPanorama.getStyles().put("buttonBackgroundColor", borderColor);
+ repaintComponent();
+ }
+
+ public final void setBorderColor(String borderColor) {
+ if (borderColor == null) {
+ throw new IllegalArgumentException("borderColor is null.");
+ }
+
+ setBorderColor(decodeColor(borderColor));
+ }
+
+ public Insets getPadding() {
+ return padding;
+ }
+
+ public void setPadding(Insets padding) {
+ if (padding == null) {
+ throw new IllegalArgumentException("padding is null.");
+ }
+
+ this.padding = padding;
+ invalidateComponent();
+ }
+
+ public final void setPadding(Dictionary<String, ?> padding) {
+ if (padding == null) {
+ throw new IllegalArgumentException("padding is null.");
+ }
+
+ setPadding(new Insets(padding));
+ }
+
+ public final void setPadding(int padding) {
+ setPadding(new Insets(padding));
+ }
+
+ public final void setPadding(Number padding) {
+ if (padding == null) {
+ throw new IllegalArgumentException("padding is null.");
+ }
+
+ setPadding(padding.intValue());
+ }
+
+ public Font getButtonFont() {
+ return buttonFont;
+ }
+
+ public void setButtonFont(Font buttonFont) {
+ if (buttonFont == null) {
+ throw new IllegalArgumentException("buttonFont is null.");
+ }
+
+ this.buttonFont = buttonFont;
+ invalidateComponent();
+ }
+
+ public final void setButtonFont(String buttonFont) {
+ if (buttonFont == null) {
+ throw new IllegalArgumentException("buttonFont is null.");
+ }
+
+ setButtonFont(Font.decode(buttonFont));
+ }
+
+ public Color getButtonColor() {
+ return buttonColor;
+ }
+
+ public void setButtonColor(Color buttonColor) {
+ if (buttonColor == null) {
+ throw new IllegalArgumentException("buttonColor is null.");
+ }
+
+ this.buttonColor = buttonColor;
+ repaintComponent();
+ }
+
+ public final void setButtonColor(String buttonColor) {
+ if (buttonColor == null) {
+ throw new IllegalArgumentException("buttonColor is null.");
+ }
+
+ setButtonColor(decodeColor(buttonColor));
+ }
+
+ public Insets getButtonPadding() {
+ return buttonPadding;
+ }
+
+ public void setButtonPadding(Insets buttonPadding) {
+ if (buttonPadding == null) {
+ throw new IllegalArgumentException("buttonPadding is null.");
+ }
+
+ this.buttonPadding = buttonPadding;
+ invalidateComponent();
+ }
+
+ public final void setButtonPadding(int buttonPadding) {
+ setButtonPadding(new Insets(buttonPadding));
+ }
+
+ public int getButtonSpacing() {
+ return (Integer)buttonFlowPane.getStyles().get("spacing");
+ }
+
+ public void setButtonSpacing(int buttonSpacing) {
+ buttonFlowPane.getStyles().put("spacing", buttonSpacing);
+ }
+
+ protected void updateButtonData(Component tab) {
+ TabPane tabPane = (TabPane)getComponent();
+ int tabIndex = tabPane.getTabs().indexOf(tab);
+
+ if (tabIndex != -1) {
+ TabButton tabButton =
+ (TabButton)buttonFlowPane.get(tabIndex);
+
+ tabButton.setButtonData(new ButtonData(TabPane.getIcon(tab),
+ TabPane.getName(tab)));
+ }
+ }
+
+ // TabPaneListener methods
+
+ public void tabOrientationChanged(TabPane tabPane) {
+ Orientation tabOrientation = tabPane.getTabOrientation();
+
+ buttonFlowPane.setOrientation(tabOrientation);
+
+ Component.StyleDictionary buttonFlowPaneStyles = buttonFlowPane.getStyles();
+ switch (tabOrientation) {
+ case HORIZONTAL: {
+ buttonFlowPaneStyles.put("horizontalAlignment", HorizontalAlignment.LEFT);
+ buttonFlowPaneStyles.put("verticalAlignment", VerticalAlignment.JUSTIFY);
+ break;
+ }
+
+ case VERTICAL: {
+ buttonFlowPaneStyles.put("horizontalAlignment", HorizontalAlignment.JUSTIFY);
+ buttonFlowPaneStyles.put("verticalAlignment", VerticalAlignment.TOP);
+ break;
+ }
+ }
+ }
+
+ public void collapsibleChanged(TabPane tabPane) {
+ // No-op
+ }
+
+ public void tabInserted(TabPane tabPane, int index) {
+ // Create a new button for the tab
+ Component tab = tabPane.getTabs().get(index);
+ TabButton tabButton = new TabButton(new ButtonData(TabPane.getIcon(tab),
+ TabPane.getName(tab)));
+ tabButton.setGroup(tabButtonGroup);
+
+ buttonFlowPane.insert(tabButton, index);
+ }
+
+ public void tabsRemoved(TabPane tabPane, int index, Sequence<Component> tabs) {
+ // Remove the buttons
+ Sequence<Component> removed = buttonFlowPane.remove(index, tabs.getLength());
+
+ for (int i = 0, n = removed.getLength(); i < n; i++) {
+ TabButton tabButton = (TabButton)removed.get(i);
+ tabButton.setGroup((Group)null);
+ }
+ }
+
+ public void cornerChanged(TabPane tabPane, Component previousCorner) {
+ invalidateComponent();
+ }
+
+ // Tab pane selection events
+ public void selectedIndexChanged(TabPane tabPane, int previousSelectedIndex) {
+ int selectedIndex = tabPane.getSelectedIndex();
+
+ if (selectedIndex == -1) {
+ Button button = tabButtonGroup.getSelection();
+ if (button != null) {
+ button.setSelected(false);
+ }
+ } else {
+ Button button = (Button)buttonFlowPane.get(selectedIndex);
+ button.setSelected(true);
+ }
+
+ invalidateComponent();
+ }
+
+ // Tab pane attribute events
+ public void nameChanged(TabPane tabPane, Component component, String previousName) {
+ updateButtonData(component);
+ }
+
+ public void iconChanged(TabPane tabPane, Component component, Image previousIcon) {
+ updateButtonData(component);
+ }
+
+ // Button group events
+ public void selectionChanged(Group group, Button previousSelection) {
+ Button button = tabButtonGroup.getSelection();
+ int index = (button == null) ? -1 : buttonFlowPane.indexOf(button);
+
+ TabPane tabPane = (TabPane)getComponent();
+ tabPane.setSelectedIndex(index);
+ }
+}
Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/skin/terra/TerraTablePaneSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/skin/terra/TerraTablePaneSkin.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/skin/terra/TerraTablePaneSkin.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/skin/terra/TerraTablePaneSkin.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,41 @@
+/*
+ * 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.Theme;
+import pivot.wtk.skin.TablePaneSkin;
+
+/**
+ * Terra table pane skin.
+ *
+ * @author tvolkert
+ */
+public class TerraTablePaneSkin extends TablePaneSkin {
+ public TerraTablePaneSkin() {
+ setGridColor(7);
+ setSelectionBackgroundColor(10);
+ }
+
+ public final void setGridColor(int gridColor) {
+ TerraTheme theme = (TerraTheme)Theme.getTheme();
+ setGridColor(theme.getColor(gridColor));
+ }
+
+ public final void setSelectionBackgroundColor(int selectionBackgroundColor) {
+ TerraTheme theme = (TerraTheme)Theme.getTheme();
+ setSelectionBackgroundColor(theme.getColor(selectionBackgroundColor));
+ }
+}