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 [31/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/terra/TerraListViewSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraListViewSkin.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraListViewSkin.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraListViewSkin.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,713 @@
+/*
+ * 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.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+
+import pivot.collections.ArrayList;
+import pivot.collections.List;
+import pivot.collections.Sequence;
+import pivot.util.Vote;
+import pivot.wtk.Component;
+import pivot.wtk.Dimensions;
+import pivot.wtk.Keyboard;
+import pivot.wtk.ListView;
+import pivot.wtk.ListViewItemStateListener;
+import pivot.wtk.ListViewListener;
+import pivot.wtk.ListViewItemListener;
+import pivot.wtk.ListViewSelectionDetailListener;
+import pivot.wtk.Mouse;
+import pivot.wtk.Bounds;
+import pivot.wtk.Span;
+import pivot.wtk.Theme;
+import pivot.wtk.skin.ComponentSkin;
+
+/**
+ * List view skin.
+ * <p>
+ * NOTE This skin assumes a fixed renderer height.
+ * <p>
+ * TODO Support a "showToggleButtons" style.
+ *
+ * @author gbrown
+ */
+public class TerraListViewSkin extends ComponentSkin implements ListView.Skin,
+    ListViewListener, ListViewItemListener, ListViewItemStateListener,
+    ListViewSelectionDetailListener {
+    private Font font;
+    private Color color;
+    private Color disabledColor;
+    private Color backgroundColor;
+    private Color selectionColor;
+    private Color selectionBackgroundColor;
+    private Color inactiveSelectionColor;
+    private Color inactiveSelectionBackgroundColor;
+    private Color highlightColor;
+    private Color highlightBackgroundColor;
+    private boolean showHighlight;
+
+    private int highlightedIndex = -1;
+
+    public TerraListViewSkin() {
+        TerraTheme theme = (TerraTheme)Theme.getTheme();
+        font = theme.getFont();
+        color = theme.getColor(1);
+        disabledColor = theme.getColor(7);
+        backgroundColor = theme.getColor(4);
+        selectionColor = theme.getColor(4);
+        selectionBackgroundColor = theme.getColor(19);
+        inactiveSelectionColor = theme.getColor(1);
+        inactiveSelectionBackgroundColor = theme.getColor(9);
+        highlightColor = theme.getColor(1);
+        highlightBackgroundColor = theme.getColor(10);
+        showHighlight = true;
+    }
+
+    public void install(Component component) {
+        super.install(component);
+
+        ListView listView = (ListView)component;
+        listView.getListViewListeners().add(this);
+        listView.getListViewItemListeners().add(this);
+        listView.getListViewItemStateListeners().add(this);
+        listView.getListViewSelectionDetailListeners().add(this);
+    }
+
+    public void uninstall() {
+        ListView listView = (ListView)getComponent();
+        listView.getListViewListeners().remove(this);
+        listView.getListViewItemListeners().remove(this);
+        listView.getListViewItemStateListeners().remove(this);
+        listView.getListViewSelectionDetailListeners().remove(this);
+
+        super.uninstall();
+    }
+
+    @SuppressWarnings("unchecked")
+    public int getPreferredWidth(int height) {
+        int preferredWidth = 0;
+
+        ListView listView = (ListView)getComponent();
+        List<Object> listData = (List<Object>)listView.getListData();
+
+        ListView.ItemRenderer renderer = listView.getItemRenderer();
+
+        for (Object item : listData) {
+            renderer.render(item, listView, false, false, false);
+            preferredWidth = Math.max(preferredWidth, renderer.getPreferredWidth(-1));
+        }
+
+        return preferredWidth;
+    }
+
+    @SuppressWarnings("unchecked")
+    public int getPreferredHeight(int width) {
+        int preferredHeight = 0;
+
+        ListView listView = (ListView)getComponent();
+        List<Object> listData = (List<Object>)listView.getListData();
+
+        ListView.ItemRenderer renderer = listView.getItemRenderer();
+        preferredHeight = listData.getLength() * renderer.getPreferredHeight(-1);
+
+        return preferredHeight;
+    }
+
+    public Dimensions getPreferredSize() {
+        return new Dimensions(getPreferredWidth(-1), getPreferredHeight(-1));
+    }
+
+    public void layout() {
+        // No-op
+    }
+
+    @SuppressWarnings("unchecked")
+    public void paint(Graphics2D graphics) {
+        ListView listView = (ListView)getComponent();
+        List<Object> listData = (List<Object>)listView.getListData();
+        ListView.ItemRenderer renderer = listView.getItemRenderer();
+
+        int width = getWidth();
+        int height = getHeight();
+        int itemHeight = renderer.getPreferredHeight(-1);
+
+        // Paint the background
+        graphics.setPaint(backgroundColor);
+        graphics.fillRect(0, 0, width, height);
+
+        // Paint the list contents
+        int itemStart = 0;
+        int itemEnd = listData.getLength() - 1;
+
+        // Ensure that we only paint items that are visible
+        Rectangle clipBounds = graphics.getClipBounds();
+        if (clipBounds != null) {
+            itemStart = Math.max(itemStart, (int)Math.floor(clipBounds.y
+                / (double)itemHeight));
+            itemEnd = Math.min(itemEnd, (int)Math.ceil((clipBounds.y
+                + clipBounds.height) / (double)itemHeight) - 1);
+        }
+
+        for (int itemIndex = itemStart; itemIndex <= itemEnd; itemIndex++) {
+            Object item = listData.get(itemIndex);
+            boolean highlighted = (itemIndex == highlightedIndex
+                && Mouse.getButtons() == 0
+                && listView.getSelectMode() != ListView.SelectMode.NONE);
+            boolean selected = listView.isIndexSelected(itemIndex);
+            boolean disabled = listView.isItemDisabled(itemIndex);
+
+            Color itemBackgroundColor = null;
+
+            if (selected) {
+                itemBackgroundColor = (listView.isFocused())
+                    ? this.selectionBackgroundColor : inactiveSelectionBackgroundColor;
+            } else {
+                if (highlighted && showHighlight && !disabled) {
+                    itemBackgroundColor = highlightBackgroundColor;
+                }
+            }
+
+            if (itemBackgroundColor != null) {
+                graphics.setPaint(itemBackgroundColor);
+                graphics.fillRect(0, itemIndex * itemHeight, width, itemHeight);
+            }
+
+            // Paint the data
+            Graphics2D rendererGraphics = (Graphics2D)graphics.create(0, itemIndex * itemHeight,
+                width, itemHeight);
+
+            renderer.render(item, listView, selected, highlighted, disabled);
+            renderer.setSize(width, itemHeight);
+            renderer.paint(rendererGraphics);
+            rendererGraphics.dispose();
+        }
+    }
+
+    // List view skin methods
+    @SuppressWarnings("unchecked")
+    public int getItemAt(int y) {
+        if (y < 0) {
+            throw new IllegalArgumentException("y is negative");
+        }
+
+        ListView listView = (ListView)getComponent();
+        List<Object> listData = (List<Object>)listView.getListData();
+
+        ListView.ItemRenderer renderer = listView.getItemRenderer();
+
+        int index = (y / renderer.getPreferredHeight(-1));
+
+        if (index >= listData.getLength()) {
+            index = -1;
+        }
+
+        return index;
+    }
+
+    public Bounds getItemBounds(int index) {
+        ListView listView = (ListView)getComponent();
+        ListView.ItemRenderer renderer = listView.getItemRenderer();
+
+        int itemHeight = renderer.getPreferredHeight(-1);
+        return new Bounds(0, index * itemHeight, getWidth(), itemHeight);
+    }
+
+    @Override
+    public boolean isFocusable() {
+        ListView listView = (ListView)getComponent();
+        return (listView.getSelectMode() != ListView.SelectMode.NONE);
+    }
+
+    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 Color getBackgroundColor() {
+        return backgroundColor;
+    }
+
+    public void setBackgroundColor(Color backgroundColor) {
+        if (backgroundColor == null) {
+            throw new IllegalArgumentException("backgroundColor is null.");
+        }
+
+        this.backgroundColor = backgroundColor;
+        repaintComponent();
+    }
+
+    public final void setBackgroundColor(String backgroundColor) {
+        if (backgroundColor == null) {
+            throw new IllegalArgumentException("backgroundColor is null.");
+        }
+
+        setBackgroundColor(decodeColor(backgroundColor));
+    }
+
+
+    public Color getSelectionColor() {
+        return selectionColor;
+    }
+
+    public void setSelectionColor(Color selectionColor) {
+        if (selectionColor == null) {
+            throw new IllegalArgumentException("selectionColor is null.");
+        }
+
+        this.selectionColor = selectionColor;
+        repaintComponent();
+    }
+
+    public final void setSelectionColor(String selectionColor) {
+        if (selectionColor == null) {
+            throw new IllegalArgumentException("selectionColor is null.");
+        }
+
+        setSelectionColor(decodeColor(selectionColor));
+    }
+
+    public Color getSelectionBackgroundColor() {
+        return selectionBackgroundColor;
+    }
+
+    public void setSelectionBackgroundColor(Color selectionBackgroundColor) {
+        if (selectionBackgroundColor == null) {
+            throw new IllegalArgumentException("selectionBackgroundColor is null.");
+        }
+
+        this.selectionBackgroundColor = selectionBackgroundColor;
+        repaintComponent();
+    }
+
+    public final void setSelectionBackgroundColor(String selectionBackgroundColor) {
+        if (selectionBackgroundColor == null) {
+            throw new IllegalArgumentException("selectionBackgroundColor is null.");
+        }
+
+        setSelectionBackgroundColor(decodeColor(selectionBackgroundColor));
+    }
+
+    public Color getInactiveSelectionColor() {
+        return inactiveSelectionColor;
+    }
+
+    public void setInactiveSelectionColor(Color inactiveSelectionColor) {
+        if (inactiveSelectionColor == null) {
+            throw new IllegalArgumentException("inactiveSelectionColor is null.");
+        }
+
+        this.inactiveSelectionColor = inactiveSelectionColor;
+        repaintComponent();
+    }
+
+    public final void setInactiveSelectionColor(String inactiveSelectionColor) {
+        if (inactiveSelectionColor == null) {
+            throw new IllegalArgumentException("inactiveSelectionColor is null.");
+        }
+
+        setInactiveSelectionColor(decodeColor(inactiveSelectionColor));
+    }
+
+    public Color getInactiveSelectionBackgroundColor() {
+        return inactiveSelectionBackgroundColor;
+    }
+
+    public void setInactiveSelectionBackgroundColor(Color inactiveSelectionBackgroundColor) {
+        if (inactiveSelectionBackgroundColor == null) {
+            throw new IllegalArgumentException("inactiveSelectionBackgroundColor is null.");
+        }
+
+        this.inactiveSelectionBackgroundColor = inactiveSelectionBackgroundColor;
+        repaintComponent();
+    }
+
+    public final void setInactiveSelectionBackgroundColor(String inactiveSelectionBackgroundColor) {
+        if (inactiveSelectionBackgroundColor == null) {
+            throw new IllegalArgumentException("inactiveSelectionBackgroundColor is null.");
+        }
+
+        setInactiveSelectionBackgroundColor(decodeColor(inactiveSelectionBackgroundColor));
+    }
+
+    public Color getHighlightColor() {
+        return highlightColor;
+    }
+
+    public void setHighlightColor(Color highlightColor) {
+        if (highlightColor == null) {
+            throw new IllegalArgumentException("highlightColor is null.");
+        }
+
+        this.highlightColor = highlightColor;
+        repaintComponent();
+    }
+
+    public final void setHighlightColor(String highlightColor) {
+        if (highlightColor == null) {
+            throw new IllegalArgumentException("highlightColor is null.");
+        }
+
+        setHighlightColor(decodeColor(highlightColor));
+    }
+
+    public Color getHighlightBackgroundColor() {
+        return highlightBackgroundColor;
+    }
+
+    public void setHighlightBackgroundColor(Color highlightBackgroundColor) {
+        if (highlightBackgroundColor == null) {
+            throw new IllegalArgumentException("highlightBackgroundColor is null.");
+        }
+
+        this.highlightBackgroundColor = highlightBackgroundColor;
+        repaintComponent();
+    }
+
+    public final void setHighlightBackgroundColor(String highlightBackgroundColor) {
+        if (highlightBackgroundColor == null) {
+            throw new IllegalArgumentException("highlightBackgroundColor is null.");
+        }
+
+        setHighlightBackgroundColor(decodeColor(highlightBackgroundColor));
+    }
+
+    public boolean getShowHighlight() {
+        return showHighlight;
+    }
+
+    public void setShowHighlight(boolean showHighlight) {
+        this.showHighlight = showHighlight;
+        repaintComponent();
+    }
+
+    @Override
+    public boolean mouseMove(Component component, int x, int y) {
+        boolean consumed = super.mouseMove(component, x, y);
+
+        int previousHighlightedIndex = this.highlightedIndex;
+        highlightedIndex = getItemAt(y);
+
+        if (previousHighlightedIndex != highlightedIndex) {
+            if (previousHighlightedIndex != -1) {
+                repaintComponent(getItemBounds(previousHighlightedIndex));
+            }
+
+            if (highlightedIndex != -1) {
+                repaintComponent(getItemBounds(highlightedIndex));
+            }
+        }
+
+        return consumed;
+    }
+
+    @Override
+    public void mouseOut(Component component) {
+        super.mouseOut(component);
+
+        if (highlightedIndex != -1) {
+            Bounds itemBounds = getItemBounds(highlightedIndex);
+            repaintComponent(itemBounds.x, itemBounds.y, itemBounds.width, itemBounds.height);
+        }
+
+        highlightedIndex = -1;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public void mouseClick(Component component, Mouse.Button button, int x, int y, int count) {
+        ListView listView = (ListView)getComponent();
+
+        if (isFocusable()) {
+            listView.requestFocus();
+        }
+
+        List<Object> listData = (List<Object>)listView.getListData();
+        ListView.ItemRenderer renderer = listView.getItemRenderer();
+
+        int itemHeight = renderer.getPreferredHeight(-1);
+        int itemIndex = y / itemHeight;
+
+        if (itemIndex < listData.getLength()
+            && !listView.isItemDisabled(itemIndex)) {
+            ListView.SelectMode selectMode = listView.getSelectMode();
+            if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)
+                && selectMode == ListView.SelectMode.MULTI) {
+                // Select the range
+                int startIndex = listView.getFirstSelectedIndex();
+                int endIndex = listView.getLastSelectedIndex();
+                Span selectedRange = (itemIndex > startIndex) ?
+                    new Span(startIndex, itemIndex) : new Span(itemIndex, endIndex);
+
+                ArrayList<Span> selectedRanges = new ArrayList<Span>();
+                Sequence<Integer> disabledIndexes = listView.getDisabledIndexes();
+                if (disabledIndexes.getLength() == 0) {
+                    selectedRanges.add(selectedRange);
+                } else {
+                    // TODO Split the range by the disabled indexes; for now,
+                    // just return
+                    return;
+                }
+
+                listView.setSelectedRanges(selectedRanges);
+            } else if (Keyboard.isPressed(Keyboard.Modifier.CTRL)
+                && selectMode == ListView.SelectMode.MULTI) {
+                // Toggle the item's selection state
+                if (listView.isIndexSelected(itemIndex)) {
+                    listView.removeSelectedIndex(itemIndex);
+                } else {
+                    listView.addSelectedIndex(itemIndex);
+                }
+            } else {
+                // Select the item
+                if ((selectMode == ListView.SelectMode.SINGLE
+                        && listView.getSelectedIndex() != itemIndex)
+                    || selectMode == ListView.SelectMode.MULTI) {
+                    listView.setSelectedIndex(itemIndex);
+                }
+            }
+        }
+    }
+
+    @Override
+    public boolean mouseWheel(Component component, Mouse.ScrollType scrollType, int scrollAmount,
+        int wheelRotation, int x, int y) {
+        if (highlightedIndex != -1) {
+            Bounds itemBounds = getItemBounds(highlightedIndex);
+            repaintComponent(itemBounds.x, itemBounds.y, itemBounds.width, itemBounds.height);
+        }
+
+        highlightedIndex = -1;
+
+        return super.mouseWheel(component, scrollType, scrollAmount, wheelRotation, x, y);
+    }
+
+    @Override
+    public boolean keyPressed(Component component, int keyCode, Keyboard.KeyLocation keyLocation) {
+        boolean consumed = super.keyPressed(component, keyCode, keyLocation);
+
+        ListView listView = (ListView)getComponent();
+
+        switch (keyCode) {
+            case Keyboard.KeyCode.UP: {
+                int index = listView.getFirstSelectedIndex();
+
+                do {
+                    index--;
+                } while (index >= 0
+                    && listView.isItemDisabled(index));
+
+                if (index >= 0) {
+                    if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)
+                        && listView.getSelectMode() == ListView.SelectMode.MULTI) {
+                        listView.addSelectedIndex(index);
+                    } else {
+                        listView.setSelectedIndex(index);
+                    }
+
+                    listView.scrollAreaToVisible(getItemBounds(index));
+                }
+
+                consumed = true;
+                break;
+            }
+
+            case Keyboard.KeyCode.DOWN: {
+                int index = listView.getLastSelectedIndex();
+                int count = listView.getListData().getLength();
+
+                do {
+                    index++;
+                } while (index < count
+                    && listView.isItemDisabled(index));
+
+                if (index < count) {
+                    if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)
+                        && listView.getSelectMode() == ListView.SelectMode.MULTI) {
+                        listView.addSelectedIndex(index);
+                    } else {
+                        listView.setSelectedIndex(index);
+                    }
+
+                    listView.scrollAreaToVisible(getItemBounds(index));
+                }
+
+                consumed = true;
+                break;
+            }
+        }
+
+        // Clear the highlight
+        if (highlightedIndex != -1) {
+            highlightedIndex = -1;
+            repaintComponent(getItemBounds(highlightedIndex));
+        }
+
+        return consumed;
+    }
+
+    // Component state events
+    @Override
+    public void enabledChanged(Component component) {
+        super.enabledChanged(component);
+
+        repaintComponent();
+    }
+
+    @Override
+    public void focusedChanged(Component component, boolean temporary) {
+        super.focusedChanged(component, temporary);
+
+        repaintComponent();
+    }
+
+    // List view events
+    public void listDataChanged(ListView listView, List<?> previousListData) {
+        invalidateComponent();
+    }
+
+    public void itemRendererChanged(ListView listView, ListView.ItemRenderer previousItemRenderer) {
+        invalidateComponent();
+    }
+
+    public void selectModeChanged(ListView listView, ListView.SelectMode previousSelectMode) {
+        // No-op
+    }
+
+    public void selectedValueKeyChanged(ListView listView, String previousSelectedIndexKey) {
+        // No-op
+    }
+
+    public void selectedValuesKeyChanged(ListView listView, String previousSelectedValuesKey) {
+        // No-op
+    }
+
+    // List view item events
+    public void itemInserted(ListView listView, int index) {
+        invalidateComponent();
+    }
+
+    public void itemsRemoved(ListView listView, int index, int count) {
+        invalidateComponent();
+    }
+
+    public void itemUpdated(ListView listView, int index) {
+        invalidateComponent();
+    }
+
+    public void itemsSorted(ListView listView) {
+        repaintComponent();
+    }
+
+    // List view item state events
+
+    public Vote previewItemDisabledChange(ListView listView, int index) {
+        return Vote.APPROVE;
+    }
+
+    public void itemDisabledChangeVetoed(ListView listView, int index, Vote reason) {
+        // No-op
+    }
+
+    public void itemDisabledChanged(ListView listView, int index) {
+        repaintComponent(getItemBounds(index));
+    }
+
+    // List view selection detail events
+    public void selectedRangeAdded(ListView listView, int rangeStart, int rangeEnd) {
+        // Repaint the area containing the added selection
+        ListView.ItemRenderer renderer = listView.getItemRenderer();
+
+        int itemHeight = renderer.getPreferredHeight(-1);
+        repaintComponent(0, rangeStart * itemHeight,
+            getWidth(), (rangeEnd - rangeStart + 1) * itemHeight);
+    }
+
+    public void selectedRangeRemoved(ListView listView, int rangeStart, int rangeEnd) {
+        // Repaint the area containing the removed selection
+        ListView.ItemRenderer renderer = listView.getItemRenderer();
+
+        int itemHeight = renderer.getPreferredHeight(-1);
+        repaintComponent(0, rangeStart * itemHeight,
+            getWidth(), (rangeEnd - rangeStart + 1) * itemHeight);
+    }
+
+    public void selectionReset(ListView listView, Sequence<Span> previousSelectedRanges) {
+        // TODO Repaint only the area that changed (intersection of previous
+        // and new selection)
+        repaintComponent();
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMenuBarItemSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMenuBarItemSkin.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMenuBarItemSkin.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMenuBarItemSkin.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,112 @@
+/*
+ * 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.Color;
+import java.awt.Graphics2D;
+
+import pivot.wtk.Button;
+import pivot.wtk.Component;
+import pivot.wtk.Cursor;
+import pivot.wtk.Dimensions;
+import pivot.wtk.MenuBar;
+import pivot.wtk.skin.MenuBarItemSkin;
+
+/**
+ * Terra menu bar item skin.
+ *
+ * @author gbrown
+ */
+public class TerraMenuBarItemSkin extends MenuBarItemSkin {
+    @Override
+    public void install(Component component) {
+        super.install(component);
+
+        MenuBar.Item menuBarItem = (MenuBar.Item)component;
+        menuBarItem.setCursor(Cursor.DEFAULT);
+    }
+
+    public int getPreferredWidth(int height) {
+        MenuBar.Item menuBarItem = (MenuBar.Item)getComponent();
+
+        Button.DataRenderer dataRenderer = menuBarItem.getDataRenderer();
+        dataRenderer.render(menuBarItem.getButtonData(), menuBarItem, false);
+
+        return dataRenderer.getPreferredWidth(height);
+    }
+
+    public int getPreferredHeight(int width) {
+        MenuBar.Item menuBarItem = (MenuBar.Item)getComponent();
+
+        Button.DataRenderer dataRenderer = menuBarItem.getDataRenderer();
+        dataRenderer.render(menuBarItem.getButtonData(), menuBarItem, false);
+
+        return dataRenderer.getPreferredHeight(width);
+    }
+
+    public Dimensions getPreferredSize() {
+        MenuBar.Item menuBarItem = (MenuBar.Item)getComponent();
+
+        Button.DataRenderer dataRenderer = menuBarItem.getDataRenderer();
+        dataRenderer.render(menuBarItem.getButtonData(), menuBarItem, false);
+
+        return dataRenderer.getPreferredSize();
+    }
+
+    public void layout() {
+        // No-op
+    }
+
+    public void paint(Graphics2D graphics) {
+        MenuBar.Item menuBarItem = (MenuBar.Item)getComponent();
+        MenuBar menuBar = menuBarItem.getMenuBar();
+
+        int width = getWidth();
+        int height = getHeight();
+
+        boolean highlight = menuPopup.isOpen();
+
+        // Paint highlight state
+        if (highlight) {
+            Color highlightBackgroundColor = (Color)menuBar.getStyles().get("highlightBackgroundColor");
+            graphics.setColor(highlightBackgroundColor);
+            graphics.fillRect(0, 0, width, height);
+        }
+
+        // Paint the content
+        Button.DataRenderer dataRenderer = menuBarItem.getDataRenderer();
+        dataRenderer.render(menuBarItem.getButtonData(), menuBarItem, highlight);
+        dataRenderer.setSize(width, height);
+
+        dataRenderer.paint(graphics);
+    }
+
+    public Color getPopupBorderColor() {
+        return (Color)menuPopup.getStyles().get("borderColor");
+    }
+
+    public void setPopupBorderColor(Color popupBorderColor) {
+        menuPopup.getStyles().put("borderColor", popupBorderColor);
+    }
+
+    public void setPopupBorderColor(String popupBorderColor) {
+        if (popupBorderColor == null) {
+            throw new IllegalArgumentException("popupBorderColor is null.");
+        }
+
+        menuPopup.getStyles().put("borderColor", popupBorderColor);
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMenuBarSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMenuBarSkin.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMenuBarSkin.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMenuBarSkin.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,281 @@
+/*
+ * 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.Color;
+import java.awt.Font;
+
+import pivot.collections.Sequence;
+import pivot.wtk.Component;
+import pivot.wtk.Dimensions;
+import pivot.wtk.MenuBar;
+import pivot.wtk.MenuBarListener;
+import pivot.wtk.Theme;
+import pivot.wtk.skin.ContainerSkin;
+
+/**
+ * Menu bar skin.
+ *
+ * @author gbrown
+ */
+public class TerraMenuBarSkin extends ContainerSkin implements MenuBarListener {
+    private Font font;
+    private Color color;
+    private Color disabledColor;
+    private Color highlightColor;
+    private Color highlightBackgroundColor;
+    private int spacing;
+
+    public TerraMenuBarSkin() {
+        TerraTheme theme = (TerraTheme)Theme.getTheme();
+        setBackgroundColor(theme.getColor(4));
+
+        font = theme.getFont().deriveFont(Font.BOLD);
+        color = theme.getColor(1);
+        disabledColor = theme.getColor(7);
+        highlightColor = theme.getColor(4);
+        highlightBackgroundColor = theme.getColor(19);
+        spacing = 2;
+    }
+
+    public void install(Component component) {
+        super.install(component);
+
+        MenuBar menuBar = (MenuBar)component;
+        menuBar.getMenuBarListeners().add(this);
+
+        menuBar.setFocusTraversalPolicy(new IndexFocusTraversalPolicy(true));
+    }
+
+    public void uninstall() {
+        MenuBar menuBar = (MenuBar)getComponent();
+        menuBar.getMenuBarListeners().remove(this);
+
+        menuBar.setFocusTraversalPolicy(null);
+
+        super.uninstall();
+    }
+
+    public int getPreferredWidth(int height) {
+        int preferredWidth = 0;
+
+        MenuBar menuBar = (MenuBar)getComponent();
+        MenuBar.ItemSequence items = menuBar.getItems();
+
+        int j = 0;
+        for (int i = 0, n = items.getLength(); i < n; i++) {
+            if (j > 0) {
+                preferredWidth += spacing;
+            }
+
+            MenuBar.Item item = items.get(i);
+            if (item.isDisplayable()) {
+                preferredWidth += item.getPreferredWidth(height);
+                j++;
+            }
+        }
+
+        return preferredWidth;
+    }
+
+    public int getPreferredHeight(int width) {
+        int preferredHeight = 0;
+
+        MenuBar menuBar = (MenuBar)getComponent();
+        MenuBar.ItemSequence items = menuBar.getItems();
+
+        for (int i = 0, n = items.getLength(); i < n; i++) {
+            MenuBar.Item item = items.get(i);
+            if (item.isDisplayable()) {
+                preferredHeight = Math.max(item.getPreferredHeight(width), preferredHeight);
+            }
+        }
+
+        return preferredHeight;
+    }
+
+    public Dimensions getPreferredSize() {
+        int preferredWidth = 0;
+        int preferredHeight = 0;
+
+        MenuBar menuBar = (MenuBar)getComponent();
+        MenuBar.ItemSequence items = menuBar.getItems();
+
+        int j = 0;
+        for (int i = 0, n = items.getLength(); i < n; i++) {
+            if (j > 0) {
+                preferredWidth += spacing;
+            }
+
+            MenuBar.Item item = items.get(i);
+            if (item.isDisplayable()) {
+                preferredWidth += item.getPreferredWidth(-1);
+                preferredHeight = Math.max(item.getPreferredHeight(-1), preferredHeight);
+            }
+        }
+
+        return new Dimensions(preferredWidth, preferredHeight);
+    }
+
+    public void layout() {
+        MenuBar menuBar = (MenuBar)getComponent();
+
+        int height = getHeight();
+        int itemX = 0;
+
+        for (MenuBar.Item item : menuBar.getItems()) {
+            if (item.isDisplayable()) {
+                item.setVisible(true);
+                item.setSize(item.getPreferredWidth(height), height);
+                item.setLocation(itemX, 0);
+
+                itemX += item.getWidth() + spacing;
+            } else {
+                item.setVisible(false);
+            }
+        }
+    }
+
+    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 Color getHighlightColor() {
+        return highlightColor;
+    }
+
+    public void setHighlightColor(Color highlightColor) {
+        if (highlightColor == null) {
+            throw new IllegalArgumentException("highlightColor is null.");
+        }
+
+        this.highlightColor = highlightColor;
+        repaintComponent();
+    }
+
+    public final void setHighlightColor(String highlightColor) {
+        if (highlightColor == null) {
+            throw new IllegalArgumentException("highlightColor is null.");
+        }
+
+        setHighlightColor(decodeColor(highlightColor));
+    }
+
+    public Color getHighlightBackgroundColor() {
+        return highlightBackgroundColor;
+    }
+
+    public void setHighlightBackgroundColor(Color highlightBackgroundColor) {
+        if (highlightBackgroundColor == null) {
+            throw new IllegalArgumentException("highlightBackgroundColor is null.");
+        }
+
+        this.highlightBackgroundColor = highlightBackgroundColor;
+        repaintComponent();
+    }
+
+    public final void setHighlightBackgroundColor(String highlightBackgroundColor) {
+        if (highlightBackgroundColor == null) {
+            throw new IllegalArgumentException("highlightBackgroundColor is null.");
+        }
+
+        setHighlightBackgroundColor(decodeColor(highlightBackgroundColor));
+    }
+
+    public int getSpacing() {
+        return spacing;
+    }
+
+    public void setSpacing(int spacing) {
+        if (spacing < 0) {
+            throw new IllegalArgumentException("Spacing is negative.");
+        }
+
+        this.spacing = spacing;
+        invalidateComponent();
+    }
+
+    public void itemInserted(MenuBar menuBar, int index) {
+        invalidateComponent();
+    }
+
+    public void itemsRemoved(MenuBar menuBar, int index, Sequence<MenuBar.Item> removed) {
+        invalidateComponent();
+    }
+
+    public void activeChanged(MenuBar menuBar) {
+        // No-op
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMenuButtonSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMenuButtonSkin.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMenuButtonSkin.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMenuButtonSkin.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,438 @@
+/*
+ * 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.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.geom.GeneralPath;
+
+import pivot.collections.Dictionary;
+import pivot.wtk.Bounds;
+import pivot.wtk.Button;
+import pivot.wtk.Component;
+import pivot.wtk.Dimensions;
+import pivot.wtk.Insets;
+import pivot.wtk.MenuButton;
+import pivot.wtk.Theme;
+import pivot.wtk.skin.MenuButtonSkin;
+
+/**
+ * Terra menu button skin.
+ *
+ * @author gbrown
+ */
+public class TerraMenuButtonSkin extends MenuButtonSkin {
+    private Font font;
+    private Color color;
+    private Color disabledColor;
+    private Color backgroundColor;
+    private Color disabledBackgroundColor;
+    private Color borderColor;
+    private Color disabledBorderColor;
+    private Insets padding;
+    private int spacing;
+    private boolean toolbar;
+
+    // Derived colors
+    private Color bevelColor;
+    private Color pressedBevelColor;
+    private Color disabledBevelColor;
+
+    private static final int TRIGGER_WIDTH = 10;
+
+    public TerraMenuButtonSkin() {
+        TerraTheme theme = (TerraTheme)Theme.getTheme();
+
+        font = theme.getFont();
+        color = theme.getColor(1);
+        disabledColor = theme.getColor(7);
+        backgroundColor = theme.getColor(10);
+        disabledBackgroundColor = theme.getColor(10);
+        borderColor = theme.getColor(7);
+        disabledBorderColor = theme.getColor(7);
+        padding = new Insets(3);
+        spacing = 0;
+        toolbar = false;
+
+        // Set the derived colors
+        bevelColor = TerraTheme.brighten(backgroundColor);
+        pressedBevelColor = TerraTheme.darken(backgroundColor);
+        disabledBevelColor = disabledBackgroundColor;
+    }
+
+    public int getPreferredWidth(int height) {
+        MenuButton menuButton = (MenuButton)getComponent();
+        Button.DataRenderer dataRenderer = menuButton.getDataRenderer();
+
+        if (height != -1) {
+            height = Math.max(height - (padding.top + padding.bottom + 2), 0);
+        }
+
+        dataRenderer.render(menuButton.getButtonData(), menuButton, false);
+
+        int preferredWidth = dataRenderer.getPreferredWidth(-1) + TRIGGER_WIDTH
+            + padding.left + padding.right + spacing + 2;
+
+        return preferredWidth;
+    }
+
+    public int getPreferredHeight(int width) {
+        MenuButton menuButton = (MenuButton)getComponent();
+        Button.DataRenderer dataRenderer = menuButton.getDataRenderer();
+
+        dataRenderer.render(menuButton.getButtonData(), menuButton, false);
+
+        int preferredHeight = dataRenderer.getPreferredHeight(-1)
+            + padding.top + padding.bottom + 2;
+
+        return preferredHeight;
+    }
+
+    public Dimensions getPreferredSize() {
+        // TODO Optimize by performing calcuations locally
+        return new Dimensions(getPreferredWidth(-1), getPreferredHeight(-1));
+    }
+
+    public void layout() {
+        // No-op
+    }
+
+    public void paint(Graphics2D graphics) {
+        MenuButton menuButton = (MenuButton)getComponent();
+
+        int width = getWidth();
+        int height = getHeight();
+
+        Color backgroundColor = null;
+        Color bevelColor = null;
+        Color borderColor = null;
+
+        if (!toolbar
+            || highlighted
+            || menuPopup.isOpen()) {
+            if (menuButton.isEnabled()) {
+                backgroundColor = this.backgroundColor;
+                bevelColor = (pressed) ? pressedBevelColor : this.bevelColor;
+                borderColor = this.borderColor;
+            } else {
+                backgroundColor = disabledBackgroundColor;
+                bevelColor = disabledBevelColor;
+                borderColor = disabledBorderColor;
+            }
+        }
+
+        // Paint the background
+        if (backgroundColor != null) {
+            graphics.setPaint(backgroundColor);
+            graphics.fillRect(0, 0, width, height);
+        }
+
+        // Draw all lines with a 1px solid stroke
+        graphics.setStroke(new BasicStroke());
+
+        // Paint the bevel
+        if (bevelColor != null) {
+            graphics.setPaint(bevelColor);
+            graphics.drawLine(1, 1, width - 2, 1);
+        }
+
+        // Paint the border
+        if (borderColor != null) {
+            graphics.setPaint(borderColor);
+            graphics.drawRect(0, 0, width - 1, height - 1);
+        }
+
+        Bounds contentBounds = new Bounds(padding.left + 1, padding.top + 1,
+            Math.max(width - (padding.left + padding.right + spacing + TRIGGER_WIDTH + 2), 0),
+            Math.max(height - (padding.top + padding.bottom + 2), 0));
+
+        // Paint the content
+        Button.DataRenderer dataRenderer = menuButton.getDataRenderer();
+        dataRenderer.render(menuButton.getButtonData(), menuButton, highlighted);
+        dataRenderer.setSize(contentBounds.width, contentBounds.height);
+
+        Graphics2D contentGraphics = (Graphics2D)graphics.create();
+        contentGraphics.translate(contentBounds.x, contentBounds.y);
+        contentGraphics.clipRect(0, 0, contentBounds.width, contentBounds.height);
+        dataRenderer.paint(contentGraphics);
+        contentGraphics.dispose();
+
+        // Paint the trigger
+        Bounds triggerBounds = new Bounds(Math.max(width - (padding.right + TRIGGER_WIDTH), 0),
+            0, TRIGGER_WIDTH, Math.max(height - (padding.top - padding.bottom), 0));
+
+        GeneralPath triggerIconShape = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
+        triggerIconShape.moveTo(0, 0);
+        triggerIconShape.lineTo(3, 3);
+        triggerIconShape.lineTo(6, 0);
+        triggerIconShape.closePath();
+
+        Graphics2D triggerGraphics = (Graphics2D)graphics.create();
+        triggerGraphics.setStroke(new BasicStroke(0));
+        triggerGraphics.setPaint(color);
+
+        int tx = triggerBounds.x + Math.round((triggerBounds.width - triggerIconShape.getBounds().width) / 2);
+        int ty = triggerBounds.y + Math.round((triggerBounds.height - triggerIconShape.getBounds().height) / 2f);
+        triggerGraphics.translate(tx, ty);
+
+        triggerGraphics.draw(triggerIconShape);
+        triggerGraphics.fill(triggerIconShape);
+
+        triggerGraphics.dispose();
+
+        // Paint the focus state
+        if (menuButton.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(2, 2, Math.max(width - 5, 0),
+                Math.max(height - 5, 0));
+
+            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+                RenderingHints.VALUE_ANTIALIAS_OFF);
+        }
+    }
+
+    @Override
+    public boolean isFocusable() {
+        return !toolbar;
+    }
+
+    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 Color getBackgroundColor() {
+        return backgroundColor;
+    }
+
+    public void setBackgroundColor(Color backgroundColor) {
+        if (backgroundColor == null) {
+            throw new IllegalArgumentException("backgroundColor is null.");
+        }
+
+        this.backgroundColor = backgroundColor;
+        bevelColor = TerraTheme.brighten(backgroundColor);
+        pressedBevelColor = TerraTheme.darken(backgroundColor);
+        repaintComponent();
+    }
+
+    public final void setBackgroundColor(String backgroundColor) {
+        if (backgroundColor == null) {
+            throw new IllegalArgumentException("backgroundColor is null.");
+        }
+
+        setBackgroundColor(decodeColor(backgroundColor));
+    }
+
+    public Color getDisabledBackgroundColor() {
+        return disabledBackgroundColor;
+    }
+
+    public void setDisabledBackgroundColor(Color disabledBackgroundColor) {
+        if (disabledBackgroundColor == null) {
+            throw new IllegalArgumentException("disabledBackgroundColor is null.");
+        }
+
+        this.disabledBackgroundColor = disabledBackgroundColor;
+        disabledBevelColor = disabledBackgroundColor;
+        repaintComponent();
+    }
+
+    public final void setDisabledBackgroundColor(String disabledBackgroundColor) {
+        if (disabledBackgroundColor == null) {
+            throw new IllegalArgumentException("disabledBackgroundColor is null.");
+        }
+
+        setDisabledBackgroundColor(decodeColor(disabledBackgroundColor));
+    }
+
+    public Color getBorderColor() {
+        return borderColor;
+    }
+
+    public void setBorderColor(Color borderColor) {
+        if (borderColor == null) {
+            throw new IllegalArgumentException("borderColor is null.");
+        }
+
+        this.borderColor = borderColor;
+        menuPopup.getStyles().put("borderColor", borderColor);
+        repaintComponent();
+    }
+
+    public final void setBorderColor(String borderColor) {
+        if (borderColor == null) {
+            throw new IllegalArgumentException("borderColor is null.");
+        }
+
+        setBorderColor(decodeColor(borderColor));
+    }
+
+    public Color getDisabledBorderColor() {
+        return disabledBorderColor;
+    }
+
+    public void setDisabledBorderColor(Color disabledBorderColor) {
+        if (disabledBorderColor == null) {
+            throw new IllegalArgumentException("disabledBorderColor is null.");
+        }
+
+        this.disabledBorderColor = disabledBorderColor;
+        repaintComponent();
+    }
+
+    public final void setDisabledBorderColor(String disabledBorderColor) {
+        if (disabledBorderColor == null) {
+            throw new IllegalArgumentException("disabledBorderColor is null.");
+        }
+
+        setDisabledBorderColor(decodeColor(disabledBorderColor));
+    }
+
+    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 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());
+    }
+
+    public boolean isToolbar() {
+        return toolbar;
+    }
+
+    public void setToolbar(boolean toolbar) {
+        this.toolbar = toolbar;
+
+        if (toolbar &&
+            getComponent().isFocused()) {
+            Component.clearFocus();
+        }
+
+        repaintComponent();
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMenuItemSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMenuItemSkin.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMenuItemSkin.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMenuItemSkin.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,185 @@
+/*
+ * 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 java.awt.RenderingHints;
+
+import pivot.wtk.Button;
+import pivot.wtk.Component;
+import pivot.wtk.Cursor;
+import pivot.wtk.Dimensions;
+import pivot.wtk.Menu;
+import pivot.wtk.media.Image;
+import pivot.wtk.skin.MenuItemSkin;
+
+/**
+ * Terra menu item skin.
+ *
+ * @author gbrown
+ */
+public class TerraMenuItemSkin extends MenuItemSkin {
+    public final class CheckmarkImage extends Image {
+        public static final int SIZE = 14;
+        public static final int CHECKMARK_SIZE = 10;
+
+        public int getWidth() {
+            return SIZE;
+        }
+
+        public int getHeight() {
+            return SIZE;
+        }
+
+        public void paint(Graphics2D graphics) {
+            Menu.Item menuItem = (Menu.Item)getComponent();
+            Menu menu = menuItem.getSection().getMenu();
+
+            Color color = (Color)menu.getStyles().get("color");
+            graphics.setColor(color);
+            graphics.setStroke(new BasicStroke(2.5f));
+
+            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+                RenderingHints.VALUE_ANTIALIAS_ON);
+
+            // Draw a checkmark
+            int n = CHECKMARK_SIZE / 2;
+            int m = CHECKMARK_SIZE / 4;
+            int offsetX = (SIZE - (n + m)) / 2;
+            int offsetY = (SIZE - n) / 2;
+
+            graphics.drawLine(offsetX, (n - m) + offsetY,
+                m + offsetX, n + offsetY);
+            graphics.drawLine(m + offsetX, n + offsetY,
+                (m + n) + offsetX, offsetY);
+        }
+    }
+
+    private Image checkmarkImage = new CheckmarkImage();
+
+    public static final int EXPANDER_SIZE = 11;
+    public static final int EXPANDER_ICON_SIZE = 5;
+
+    @Override
+    public void install(Component component) {
+        super.install(component);
+
+        Menu.Item menuItem = (Menu.Item)component;
+        menuItem.setCursor(Cursor.DEFAULT);
+    }
+
+    public int getPreferredWidth(int height) {
+        Menu.Item menuItem = (Menu.Item)getComponent();
+
+        Button.DataRenderer dataRenderer = menuItem.getDataRenderer();
+        dataRenderer.render(menuItem.getButtonData(), menuItem, false);
+
+        return dataRenderer.getPreferredWidth(height) + EXPANDER_SIZE;
+    }
+
+    public int getPreferredHeight(int width) {
+        Menu.Item menuItem = (Menu.Item)getComponent();
+
+        Button.DataRenderer dataRenderer = menuItem.getDataRenderer();
+        dataRenderer.render(menuItem.getButtonData(), menuItem, false);
+
+        return Math.max(dataRenderer.getPreferredHeight(width), EXPANDER_SIZE);
+    }
+
+    public Dimensions getPreferredSize() {
+        Menu.Item menuItem = (Menu.Item)getComponent();
+
+        Button.DataRenderer dataRenderer = menuItem.getDataRenderer();
+        dataRenderer.render(menuItem.getButtonData(), menuItem, false);
+
+        Dimensions preferredSize = dataRenderer.getPreferredSize();
+
+        preferredSize.width += EXPANDER_SIZE;
+        preferredSize.height = Math.max(preferredSize.height, EXPANDER_SIZE);
+
+        return preferredSize;
+    }
+
+    public void layout() {
+        // No-op
+    }
+
+    public void paint(Graphics2D graphics) {
+        Menu.Item menuItem = (Menu.Item)getComponent();
+        Menu menu = menuItem.getSection().getMenu();
+
+        int width = getWidth();
+        int height = getHeight();
+
+        boolean highlight = (menuItem.isFocused()
+            || menuPopup.isOpen());
+
+        // Paint highlight state
+        if (highlight) {
+            Color highlightBackgroundColor = (Color)menu.getStyles().get("highlightBackgroundColor");
+            graphics.setColor(highlightBackgroundColor);
+            graphics.fillRect(0, 0, width, height);
+        }
+
+        // Paint the content
+        Button.DataRenderer dataRenderer = menuItem.getDataRenderer();
+        dataRenderer.render(menuItem.getButtonData(), menuItem, highlight);
+        dataRenderer.setSize(Math.max(width - EXPANDER_SIZE, 0), height);
+
+        dataRenderer.paint(graphics);
+
+        // Paint the expander
+        if (menuItem.getMenu() != null) {
+            Color color = (Color)(highlight ?
+                menu.getStyles().get("highlightColor") : menu.getStyles().get("color"));
+            graphics.setColor(color);
+            graphics.setStroke(new BasicStroke(0));
+
+            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+                RenderingHints.VALUE_ANTIALIAS_ON);
+
+            graphics.translate(dataRenderer.getWidth() + (EXPANDER_SIZE - EXPANDER_ICON_SIZE) / 2,
+                (height - EXPANDER_ICON_SIZE) / 2);
+
+            int[] xPoints = {0, EXPANDER_ICON_SIZE, 0};
+            int[] yPoints = {0, EXPANDER_ICON_SIZE / 2, EXPANDER_ICON_SIZE};
+            graphics.fillPolygon(xPoints, yPoints, 3);
+            graphics.drawPolygon(xPoints, yPoints, 3);
+        }
+    }
+
+    public Image getCheckmarkImage() {
+        return checkmarkImage;
+    }
+
+    public Color getPopupBorderColor() {
+        return (Color)menuPopup.getStyles().get("borderColor");
+    }
+
+    public void setPopupBorderColor(Color popupBorderColor) {
+        menuPopup.getStyles().put("borderColor", popupBorderColor);
+    }
+
+    public void setPopupBorderColor(String popupBorderColor) {
+        if (popupBorderColor == null) {
+            throw new IllegalArgumentException("popupBorderColor is null.");
+        }
+
+        menuPopup.getStyles().put("borderColor", popupBorderColor);
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMenuPopupSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMenuPopupSkin.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMenuPopupSkin.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMenuPopupSkin.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,225 @@
+/*
+ * 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.Color;
+
+import pivot.util.Vote;
+import pivot.wtk.Border;
+import pivot.wtk.Component;
+import pivot.wtk.ComponentClassListener;
+import pivot.wtk.Display;
+import pivot.wtk.Keyboard;
+import pivot.wtk.Menu;
+import pivot.wtk.MenuItemSelectionListener;
+import pivot.wtk.MenuPopup;
+import pivot.wtk.MenuPopupListener;
+import pivot.wtk.Panorama;
+import pivot.wtk.Theme;
+import pivot.wtk.Window;
+import pivot.wtk.effects.DropShadowDecorator;
+import pivot.wtk.effects.Transition;
+import pivot.wtk.effects.TransitionListener;
+import pivot.wtk.skin.PopupSkin;
+
+/**
+ * Menu popup skin.
+ *
+ * @author gbrown
+ */
+public class TerraMenuPopupSkin extends PopupSkin
+    implements MenuPopupListener, ComponentClassListener {
+    private Panorama panorama;
+    private Border border;
+
+    private DropShadowDecorator dropShadowDecorator = null;
+    private Transition closeTransition = null;
+
+    private static final int CLOSE_TRANSITION_DURATION = 150;
+    private static final int CLOSE_TRANSITION_RATE = 30;
+
+    private MenuItemSelectionListener menuItemPressListener = new MenuItemSelectionListener() {
+        public void itemSelected(Menu.Item item) {
+            final MenuPopup menuPopup = (MenuPopup)getComponent();
+
+            closeTransition = new FadeTransition(menuPopup,
+                CLOSE_TRANSITION_DURATION, CLOSE_TRANSITION_RATE);
+
+            closeTransition.start(new TransitionListener() {
+                public void transitionCompleted(Transition transition) {
+                    menuPopup.close();
+                }
+            });
+
+            menuPopup.close();
+        }
+    };
+
+    public TerraMenuPopupSkin() {
+        TerraTheme theme = (TerraTheme)Theme.getTheme();
+        setBackgroundColor((Color)null);
+
+        panorama = new Panorama();
+        panorama.getStyles().put("buttonBackgroundColor", Color.WHITE);
+
+        border = new Border(panorama);
+
+        border.getStyles().put("color", theme.getColor(7));
+        border.getStyles().put("backgroundColor", null);
+        border.getStyles().put("padding", 0);
+    }
+
+    @Override
+    public void install(Component component) {
+        super.install(component);
+
+        MenuPopup menuPopup = (MenuPopup)component;
+        menuPopup.getMenuPopupListeners().add(this);
+
+        if (menuPopup.isOpen()) {
+            Component.getComponentClassListeners().add(this);
+        }
+
+        Menu menu = menuPopup.getMenu();
+        if (menu != null) {
+            menu.getMenuItemSelectionListeners().add(menuItemPressListener);
+        }
+
+        panorama.setView(menu);
+        menuPopup.setContent(border);
+
+        // Attach the drop-shadow decorator
+        dropShadowDecorator = new DropShadowDecorator(3, 3, 3);
+        menuPopup.getDecorators().add(dropShadowDecorator);
+    }
+
+    @Override
+    public void uninstall() {
+        MenuPopup menuPopup = (MenuPopup)getComponent();
+        menuPopup.getMenuPopupListeners().remove(this);
+
+        if (menuPopup.isOpen()) {
+            Component.getComponentClassListeners().remove(this);
+        }
+
+        Menu menu = menuPopup.getMenu();
+        if (menu != null) {
+            menu.getMenuItemSelectionListeners().remove(menuItemPressListener);
+        }
+
+        panorama.setView(null);
+        menuPopup.setContent(null);
+
+        // Detach the drop shadow decorator
+        menuPopup.getDecorators().remove(dropShadowDecorator);
+        dropShadowDecorator = null;
+
+        super.uninstall();
+    }
+
+    public Color getBorderColor() {
+        return (Color)border.getStyles().get("color");
+    }
+
+    public void setBorderColor(Color borderColor) {
+        border.getStyles().put("color", borderColor);
+    }
+
+    public void setBorderColor(String borderColor) {
+        if (borderColor == null) {
+            throw new IllegalArgumentException("borderColor is null.");
+        }
+
+        border.getStyles().put("color", borderColor);
+    }
+
+    @Override
+    public boolean keyPressed(Component component, int keyCode, Keyboard.KeyLocation keyLocation) {
+        boolean consumed = super.keyPressed(component, keyCode, keyLocation);
+
+        if (keyCode == Keyboard.KeyCode.ESCAPE) {
+            MenuPopup menuPopup = (MenuPopup)getComponent();
+            Component affiliate = menuPopup.getAffiliate();
+            if (affiliate != null
+                && affiliate.isFocusable()) {
+                affiliate.requestFocus();
+            }
+
+            menuPopup.close();
+        }
+
+        return consumed;
+    }
+
+    @Override
+    public void windowOpened(Window window) {
+        super.windowOpened(window);
+        Component.getComponentClassListeners().add(this);
+    }
+
+    @Override
+    public Vote previewWindowClose(Window window) {
+        return (closeTransition != null
+            && closeTransition.isRunning()) ? Vote.DEFER : Vote.APPROVE;
+    }
+
+    @Override
+    public void windowCloseVetoed(Window window, Vote reason) {
+        super.windowCloseVetoed(window, reason);
+
+        if (reason == Vote.DENY
+            && closeTransition != null) {
+            closeTransition.stop();
+            closeTransition = null;
+        }
+    }
+
+    @Override
+    public void windowClosed(Window window, Display display) {
+        super.windowClosed(window, display);
+        Component.getComponentClassListeners().remove(this);
+
+        closeTransition = null;
+    }
+
+    public void menuChanged(MenuPopup menuPopup, Menu previousMenu) {
+        if (previousMenu != null) {
+            previousMenu.getMenuItemSelectionListeners().remove(menuItemPressListener);
+        }
+
+        Menu menu = menuPopup.getMenu();
+        if (menu != null) {
+            menu.getMenuItemSelectionListeners().add(menuItemPressListener);
+        }
+
+        panorama.setView(menu);
+    }
+
+    public void focusedComponentChanged(Component previousFocusedComponent) {
+        MenuPopup menuPopup = (MenuPopup)getComponent();
+
+        if (!menuPopup.containsFocus()) {
+            Component affiliate = menuPopup.getAffiliate();
+            Component focusedComponent = Component.getFocusedComponent();
+
+            if (focusedComponent != null
+                && focusedComponent != affiliate
+                && !menuPopup.isOwningAncestorOf(focusedComponent.getWindow())) {
+                menuPopup.close();
+            }
+        }
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMenuSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMenuSkin.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMenuSkin.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMenuSkin.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,379 @@
+/*
+ * 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.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+
+import pivot.collections.Sequence;
+import pivot.wtk.Component;
+import pivot.wtk.Dimensions;
+import pivot.wtk.Menu;
+import pivot.wtk.MenuListener;
+import pivot.wtk.Theme;
+import pivot.wtk.skin.ContainerSkin;
+
+/**
+ * Menu skin.
+ *
+ * @author gbrown
+ */
+public class TerraMenuSkin extends ContainerSkin implements MenuListener {
+    private Font font;
+    private Color color;
+    private Color disabledColor;
+    private Color highlightColor;
+    private Color highlightBackgroundColor;
+    private Color marginColor;
+    private int margin;
+    private Color separatorColor;
+    private int sectionSpacing;
+    private boolean showKeyboardShortcuts;
+
+    public TerraMenuSkin() {
+        TerraTheme theme = (TerraTheme)Theme.getTheme();
+        setBackgroundColor(theme.getColor(4));
+
+        font = theme.getFont();
+        color = theme.getColor(1);
+        disabledColor = theme.getColor(7);
+        highlightColor = theme.getColor(4);
+        highlightBackgroundColor = theme.getColor(19);
+        marginColor = theme.getColor(10);
+        margin = 20;
+        separatorColor = theme.getColor(7);
+        sectionSpacing = 7;
+        showKeyboardShortcuts = true;
+    }
+
+    public void install(Component component) {
+        super.install(component);
+
+        Menu menu = (Menu)component;
+        menu.getMenuListeners().add(this);
+    }
+
+    public void uninstall() {
+        Menu menu = (Menu)getComponent();
+        menu.getMenuListeners().remove(this);
+
+        super.uninstall();
+    }
+
+    public int getPreferredWidth(int height) {
+        int preferredWidth = 0;
+
+        Menu menu = (Menu)getComponent();
+        Menu.SectionSequence sections = menu.getSections();
+
+        for (int i = 0, n = sections.getLength(); i < n; i++) {
+            Menu.Section section = sections.get(i);
+
+            for (Menu.Item item : section) {
+                if (item.isDisplayable()) {
+                    preferredWidth = Math.max(item.getPreferredWidth(-1),
+                        preferredWidth);
+                }
+            }
+        }
+
+        return preferredWidth;
+    }
+
+    public int getPreferredHeight(int width) {
+        int preferredHeight = 0;
+
+        Menu menu = (Menu)getComponent();
+        Menu.SectionSequence sections = menu.getSections();
+
+        for (int i = 0, n = sections.getLength(); i < n; i++) {
+            Menu.Section section = sections.get(i);
+
+            for (Menu.Item item : section) {
+                if (item.isDisplayable()) {
+                    preferredHeight += item.getPreferredHeight(width);
+                }
+            }
+
+            if (i > 0) {
+                preferredHeight += sectionSpacing;
+            }
+        }
+
+        return preferredHeight;
+    }
+
+    public Dimensions getPreferredSize() {
+        int preferredWidth = 0;
+        int preferredHeight = 0;
+
+        Menu menu = (Menu)getComponent();
+        Menu.SectionSequence sections = menu.getSections();
+
+        for (int i = 0, n = sections.getLength(); i < n; i++) {
+            Menu.Section section = sections.get(i);
+
+            for (Menu.Item item : section) {
+                if (item.isDisplayable()) {
+                    preferredWidth = Math.max(item.getPreferredWidth(),
+                        preferredWidth);
+                    preferredHeight += item.getPreferredHeight();
+                }
+            }
+
+            if (i > 0) {
+                preferredHeight += sectionSpacing;
+            }
+        }
+
+        return new Dimensions(preferredWidth, preferredHeight);
+    }
+
+    public void layout() {
+        Menu menu = (Menu)getComponent();
+        Menu.SectionSequence sections = menu.getSections();
+
+        int width = getWidth();
+        int itemY = 0;
+
+        for (int i = 0, n = sections.getLength(); i < n; i++) {
+            Menu.Section section = sections.get(i);
+
+            for (Menu.Item item : section) {
+                if (item.isDisplayable()) {
+                    item.setVisible(true);
+                    item.setSize(width, item.getPreferredHeight(width));
+                    item.setLocation(0, itemY);
+
+                    itemY += item.getHeight();
+                } else {
+                    item.setVisible(false);
+                }
+            }
+
+            itemY += sectionSpacing;
+        }
+    }
+
+    public void paint(Graphics2D graphics) {
+        super.paint(graphics);
+
+        Menu menu = (Menu)getComponent();
+
+        int width = getWidth();
+        int height = getHeight();
+
+        // Paint the margin
+        if (marginColor != null) {
+            graphics.setColor(marginColor);
+            graphics.fillRect(0, 0, margin, height);
+        }
+
+        Menu.SectionSequence sections = menu.getSections();
+
+        for (int i = 0, n = sections.getLength(); i < n; i++) {
+            Menu.Section section = sections.get(i);
+
+            if (section.getLength() > 0) {
+                Menu.Item item = section.get(section.getLength() - 1);
+                int separatorY = item.getY() + item.getHeight() + sectionSpacing / 2;
+
+                // Paint the line
+                graphics.setColor(separatorColor);
+                graphics.drawLine(1, separatorY, width - 2, separatorY);
+            }
+        }
+    }
+
+    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 Color getHighlightColor() {
+        return highlightColor;
+    }
+
+    public void setHighlightColor(Color highlightColor) {
+        if (highlightColor == null) {
+            throw new IllegalArgumentException("highlightColor is null.");
+        }
+
+        this.highlightColor = highlightColor;
+        repaintComponent();
+    }
+
+    public final void setHighlightColor(String highlightColor) {
+        if (highlightColor == null) {
+            throw new IllegalArgumentException("highlightColor is null.");
+        }
+
+        setHighlightColor(decodeColor(highlightColor));
+    }
+
+    public Color getHighlightBackgroundColor() {
+        return highlightBackgroundColor;
+    }
+
+    public void setHighlightBackgroundColor(Color highlightBackgroundColor) {
+        if (highlightBackgroundColor == null) {
+            throw new IllegalArgumentException("highlightBackgroundColor is null.");
+        }
+
+        this.highlightBackgroundColor = highlightBackgroundColor;
+        repaintComponent();
+    }
+
+    public final void setHighlightBackgroundColor(String highlightBackgroundColor) {
+        if (highlightBackgroundColor == null) {
+            throw new IllegalArgumentException("highlightBackgroundColor is null.");
+        }
+
+        setHighlightBackgroundColor(decodeColor(highlightBackgroundColor));
+    }
+
+    public Color getMarginColor() {
+        return marginColor;
+    }
+
+    public void setMarginColor(Color marginColor) {
+        this.marginColor = marginColor;
+        repaintComponent();
+    }
+
+    public int getMargin() {
+        return margin;
+    }
+
+    public void setMargin(int margin) {
+        if (margin < 0) {
+            throw new IllegalArgumentException("margin is negative.");
+        }
+
+        this.margin = margin;
+        invalidateComponent();
+    }
+
+    public Color getSeparatorColor() {
+        return separatorColor;
+    }
+
+    public void setSeparatorColor(Color separatorColor) {
+        if (separatorColor == null) {
+            throw new IllegalArgumentException("separatorColor is null.");
+        }
+
+        this.separatorColor = separatorColor;
+        repaintComponent();
+    }
+
+    public int getSectionSpacing() {
+        return sectionSpacing;
+    }
+
+    public void setSectionSpacing(int sectionSpacing) {
+        if (sectionSpacing < 0) {
+            throw new IllegalArgumentException("sectionSpacing is negative.");
+        }
+
+        this.sectionSpacing = sectionSpacing;
+        invalidateComponent();
+    }
+
+    public boolean getShowKeyboardShortcuts() {
+        return showKeyboardShortcuts;
+    }
+
+    public void setShowKeyboardShortcuts(boolean showKeyboardShortcuts) {
+        this.showKeyboardShortcuts = showKeyboardShortcuts;
+        invalidateComponent();
+    }
+
+    public void sectionInserted(Menu menu, int index) {
+        invalidateComponent();
+    }
+
+    public void sectionsRemoved(Menu menu, int index, Sequence<Menu.Section> removed) {
+        invalidateComponent();
+    }
+
+    public void itemInserted(Menu.Section section, int index) {
+        invalidateComponent();
+    }
+
+    public void itemsRemoved(Menu.Section section, int index, Sequence<Menu.Item> removed) {
+        invalidateComponent();
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMeterSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMeterSkin.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMeterSkin.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/terra/TerraMeterSkin.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,194 @@
+/*
+ * 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 java.awt.geom.Line2D;
+import java.awt.geom.Rectangle2D;
+
+import pivot.wtk.Component;
+import pivot.wtk.Dimensions;
+import pivot.wtk.Meter;
+import pivot.wtk.MeterListener;
+import pivot.wtk.Theme;
+import pivot.wtk.skin.ComponentSkin;
+
+/**
+ * Meter skin.
+ *
+ * @author tvolkert
+ */
+public class TerraMeterSkin extends ComponentSkin
+    implements MeterListener {
+    private Color color;
+    private Color gridColor;
+    private float gridFrequency;
+
+    private static final int DEFAULT_WIDTH = 100;
+    private static final int DEFAULT_HEIGHT = 12;
+
+    public TerraMeterSkin() {
+        TerraTheme theme = (TerraTheme)Theme.getTheme();
+        color = theme.getColor(16);
+        gridColor = theme.getColor(10);
+        gridFrequency = 0.25f;
+    }
+
+    @Override
+    public void install(Component component) {
+        super.install(component);
+
+        Meter meter = (Meter)component;
+        meter.getMeterListeners().add(this);
+    }
+
+    @Override
+    public void uninstall() {
+        Meter meter = (Meter)getComponent();
+        meter.getMeterListeners().remove(this);
+
+        super.uninstall();
+    }
+
+    @Override
+    public boolean isFocusable() {
+        return false;
+    }
+
+    public int getPreferredWidth(int height) {
+        // Meter has no content, so its preferred width is hard coded in the
+        // class and is not affected by the height constraint.
+        return DEFAULT_WIDTH;
+    }
+
+    public int getPreferredHeight(int width) {
+        // Meter has no content, so its preferred height is hard coded in the
+        // class and is not affected by the width constraint.
+        return DEFAULT_HEIGHT;
+    }
+
+    public Dimensions getPreferredSize() {
+        // Meter has no content, so its preferred size is hard coded in the class.
+        return new Dimensions(DEFAULT_WIDTH, DEFAULT_HEIGHT);
+    }
+
+    public void layout() {
+        // No-op
+    }
+
+    public void paint(Graphics2D graphics) {
+        Meter meter = (Meter)getComponent();
+
+        // TODO Paint text
+
+        double width = (double)getWidth();
+        double height = (double)getHeight();
+        double meterStop = meter.getPercentage() * width;
+
+        graphics.setStroke(new BasicStroke());
+        graphics.setPaint(color);
+        graphics.fill(new Rectangle2D.Double(0, 0, meterStop - 1.0, height - 1.0));
+
+        graphics.setPaint(gridColor);
+        graphics.draw(new Rectangle2D.Double(0, 0, width - 1.0, height - 1.0));
+
+        int nLines = (int)Math.ceil(1.0 / gridFrequency) - 1;
+        double gridSeparation = width * gridFrequency;
+        for (int i = 0; i < nLines; i++) {
+           double gridX = (double)(i + 1) * gridSeparation;
+            graphics.draw(new Line2D.Double(gridX, 0.0, gridX, height - 1.0));
+        }
+    }
+
+    public Color getColor() {
+        return color;
+    }
+
+    public void setColor(Color color) {
+        this.color = color;
+        repaintComponent();
+    }
+
+    public final void setColor(String color) {
+        if (color == null) {
+            throw new IllegalArgumentException("color is null.");
+        }
+
+        setColor(decodeColor(color));
+    }
+
+    public Color getGridColor() {
+        return gridColor;
+    }
+
+    public void setGridColor(Color gridColor) {
+        this.gridColor = gridColor;
+        repaintComponent();
+    }
+
+    public final void setGridColor(String gridColor) {
+        if (gridColor == null) {
+            throw new IllegalArgumentException("gridColor is null.");
+        }
+
+        setGridColor(decodeColor(gridColor));
+    }
+
+    public float getGridFrequency() {
+        return gridFrequency;
+    }
+
+    public void setGridFrequency(float gridFrequency) {
+        this.gridFrequency = gridFrequency;
+        repaintComponent();
+    }
+
+    public final void setGridFrequency(Number gridFrequency) {
+        if (gridFrequency == null) {
+            throw new IllegalArgumentException("gridFrequency is null.");
+        }
+
+        setGridFrequency(gridFrequency.floatValue());
+    }
+
+    /**
+     * Listener for meter percentage changes.
+     *
+     * @param meter
+     *     The source of the event.
+     *
+     * @param previousPercentage
+     *     The previous percentage value.
+     */
+    public void percentageChanged(Meter meter, double previousPercentage) {
+        repaintComponent();
+    }
+
+    /**
+     * Listener for meter text changes.
+     *
+     * @param meter
+     *     The source of the event.
+     *
+     * @param previousText
+     *    The previous text value.
+     */
+    public void textChanged(Meter meter, String previousText) {
+        invalidateComponent();
+    }
+}