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 [26/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/LabelSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/LabelSkin.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/LabelSkin.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/LabelSkin.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,486 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.skin;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.font.FontRenderContext;
+import java.awt.font.LineBreakMeasurer;
+import java.awt.font.LineMetrics;
+import java.awt.font.TextAttribute;
+import java.awt.font.TextLayout;
+import java.awt.geom.Line2D;
+import java.awt.geom.Rectangle2D;
+import java.text.AttributedCharacterIterator;
+import java.text.AttributedString;
+
+import pivot.collections.Dictionary;
+import pivot.wtk.Component;
+import pivot.wtk.Dimensions;
+import pivot.wtk.HorizontalAlignment;
+import pivot.wtk.Insets;
+import pivot.wtk.Label;
+import pivot.wtk.LabelListener;
+import pivot.wtk.TextDecoration;
+import pivot.wtk.Theme;
+import pivot.wtk.VerticalAlignment;
+
+/**
+ * Label skin.
+ * <p>
+ * TODO showEllipsis style
+ *
+ * @author gbrown
+ */
+public class LabelSkin extends ComponentSkin implements LabelListener {
+ private FontRenderContext fontRenderContext = new FontRenderContext(null, true, true);
+
+ private Font font;
+ private Color color;
+ private TextDecoration textDecoration;
+ private HorizontalAlignment horizontalAlignment;
+ private VerticalAlignment verticalAlignment;
+ private Insets padding;
+ private boolean wrapText;
+
+ public LabelSkin() {
+ Theme theme = Theme.getTheme();
+ color = Color.BLACK;
+ font = theme.getFont();
+ textDecoration = null;
+ horizontalAlignment = HorizontalAlignment.LEFT;
+ verticalAlignment = VerticalAlignment.TOP;
+ padding = new Insets(0);
+ wrapText = false;
+ }
+
+ @Override
+ public void install(Component component) {
+ super.install(component);
+
+ Label label = (Label)getComponent();
+ label.getLabelListeners().add(this);
+ }
+
+ @Override
+ public void uninstall() {
+ Label label = (Label)getComponent();
+ label.getLabelListeners().remove(this);
+
+ super.uninstall();
+ }
+
+ public int getPreferredWidth(int height) {
+ int preferredWidth = 0;
+
+ Label label = (Label)getComponent();
+ String text = label.getText();
+
+ if (text != null
+ && text.length() > 0) {
+ Rectangle2D stringBounds = font.getStringBounds(text, fontRenderContext);
+ preferredWidth = (int)Math.ceil(stringBounds.getWidth());
+ }
+
+ preferredWidth += (padding.left + padding.right);
+
+ return preferredWidth;
+ }
+
+ public int getPreferredHeight(int width) {
+ int preferredHeight = 0;
+
+ Label label = (Label)getComponent();
+ String text = label.getText();
+
+ if (text == null) {
+ text = "";
+ }
+
+ if (wrapText
+ && width != -1
+ && text.length() > 0) {
+ int contentWidth = width - (padding.left + padding.right);
+
+ AttributedString attributedText = new AttributedString(text);
+ attributedText.addAttribute(TextAttribute.FONT, font);
+
+ AttributedCharacterIterator aci = attributedText.getIterator();
+ LineBreakMeasurer lbm = new LineBreakMeasurer(aci, fontRenderContext);
+
+ float lineHeights = 0;
+ while (lbm.getPosition() < aci.getEndIndex()) {
+ int offset = lbm.nextOffset(contentWidth);
+
+ LineMetrics lm = font.getLineMetrics(aci,
+ lbm.getPosition(), offset, fontRenderContext);
+
+ float lineHeight = lm.getAscent() + lm.getDescent()
+ + lm.getLeading();
+ lineHeights += lineHeight;
+
+ lbm.setPosition(offset);
+ }
+
+ preferredHeight = (int)Math.ceil(lineHeights);
+ } else {
+ LineMetrics lm = font.getLineMetrics(text, fontRenderContext);
+ preferredHeight = (int)Math.ceil(lm.getAscent() + lm.getDescent()
+ + lm.getLeading());
+ }
+
+ preferredHeight += (padding.top + padding.bottom);
+
+ return preferredHeight;
+ }
+
+ public Dimensions getPreferredSize() {
+ int preferredWidth = 0;
+ int preferredHeight = 0;
+
+ Label label = (Label)getComponent();
+ String text = label.getText();
+
+ if (text != null
+ && text.length() > 0) {
+ Rectangle2D stringBounds = font.getStringBounds(text, fontRenderContext);
+ preferredWidth = (int)Math.ceil(stringBounds.getWidth());
+ preferredHeight = (int)Math.ceil(stringBounds.getHeight());
+ }
+
+ preferredWidth += (padding.left + padding.right);
+ preferredHeight += (padding.top + padding.bottom);
+
+ return new Dimensions(preferredWidth, preferredHeight);
+ }
+
+ public void layout() {
+ // No-op
+ }
+
+ public void paint(Graphics2D graphics) {
+ int width = getWidth();
+ int height = getHeight();
+
+ Label label = (Label)getComponent();
+ String text = label.getText();
+
+ if (text != null
+ && text.length() > 0) {
+ if (fontRenderContext.isAntiAliased()) {
+ // TODO Use VALUE_TEXT_ANTIALIAS_LCD_HRGB when JDK 1.6 is
+ // available on OSX?
+ graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
+ RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ }
+
+ if (fontRenderContext.usesFractionalMetrics()) {
+ graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
+ RenderingHints.VALUE_FRACTIONALMETRICS_ON);
+ }
+
+ graphics.setFont(font);
+ graphics.setPaint(color);
+
+ float y = 0;
+ switch (verticalAlignment) {
+ case TOP: {
+ y = padding.top;
+ break;
+ }
+
+ case BOTTOM: {
+ y = height - getPreferredHeight(wrapText ? width : -1) + padding.top;
+ break;
+ }
+
+ case CENTER: {
+ y = (height - getPreferredHeight(wrapText ? width : -1)) / 2 + padding.top;
+ break;
+ }
+ }
+
+ if (wrapText) {
+ AttributedString attributedText = new AttributedString(text);
+ attributedText.addAttribute(TextAttribute.FONT, font);
+
+ AttributedCharacterIterator aci = attributedText.getIterator();
+ LineBreakMeasurer lbm = new LineBreakMeasurer(aci, fontRenderContext);
+
+ int contentWidth = width - (padding.left + padding.right);
+
+ while (lbm.getPosition() < aci.getEndIndex()) {
+ TextLayout textLayout = lbm.nextLayout(contentWidth);
+ y += textLayout.getAscent();
+ drawText(graphics, textLayout, y);
+ y += textLayout.getDescent() + textLayout.getLeading();
+ }
+ } else {
+ TextLayout textLayout = new TextLayout(text, font, fontRenderContext);
+ drawText(graphics, textLayout, y + textLayout.getAscent());
+ }
+ }
+ }
+
+ private void drawText(Graphics2D graphics, TextLayout textLayout, float y) {
+ float width = getWidth();
+ Rectangle2D textBounds = textLayout.getBounds();
+
+ float x = 0;
+ switch (horizontalAlignment) {
+ case LEFT: {
+ x = padding.left;
+ break;
+ }
+
+ case RIGHT: {
+ x = width - (float)(textBounds.getX() + textBounds.getWidth()) -
+ padding.right;
+ break;
+ }
+
+ case CENTER: {
+ x = (width - (padding.left + padding.right) -
+ (float)(textBounds.getX() + textBounds.getWidth())) / 2f +
+ padding.left;
+ break;
+ }
+ }
+
+ textLayout.draw(graphics, x, y);
+
+ if (textDecoration != null) {
+ graphics.setStroke(new BasicStroke());
+
+ float offset = 0;
+
+ switch (textDecoration) {
+ case UNDERLINE: {
+ offset = y + 2;
+ break;
+ }
+
+ case STRIKETHROUGH: {
+ offset = y - textLayout.getAscent() / 3f + 1;
+ break;
+ }
+ }
+
+ Line2D line = new Line2D.Float(x, offset, x + (float)textBounds.getWidth(), offset);
+ graphics.draw(line);
+ }
+ }
+
+ /**
+ * @return
+ * <tt>false</tt>; labels are not focusable.
+ */
+ @Override
+ public boolean isFocusable() {
+ return 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 int getFontSize() {
+ return font.getSize();
+ }
+
+ public void setFontSize(int fontSize) {
+ font = font.deriveFont((float)fontSize);
+ }
+
+ public boolean isFontBold() {
+ return ((font.getStyle() & Font.BOLD) == Font.BOLD);
+ }
+
+ public void setFontBold(boolean fontBold) {
+ if (isFontBold() != fontBold) {
+ if (fontBold) {
+ font = font.deriveFont(Font.BOLD);
+ } else {
+ font = font.deriveFont(font.getStyle() & (~Font.BOLD));
+ }
+ }
+ }
+
+ public boolean isFontItalic() {
+ return ((font.getStyle() & Font.ITALIC) == Font.ITALIC);
+ }
+
+ public void setFontItalic(boolean fontItalic) {
+ if (isFontItalic() != fontItalic) {
+ if (fontItalic) {
+ font = font.deriveFont(Font.ITALIC);
+ } else {
+ font = font.deriveFont(font.getStyle() & (~Font.ITALIC));
+ }
+ }
+ }
+
+ 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 TextDecoration getTextDecoration() {
+ return textDecoration;
+ }
+
+ public void setTextDecoration(TextDecoration textDecoration) {
+ this.textDecoration = textDecoration;
+ invalidateComponent();
+ }
+
+ public final void setTextDecoration(String textDecoration) {
+ if (textDecoration == null) {
+ throw new IllegalArgumentException("textDecoration is null.");
+ }
+
+ setTextDecoration(TextDecoration.decode(textDecoration));
+ }
+
+ public HorizontalAlignment getHorizontalAlignment() {
+ return horizontalAlignment;
+ }
+
+ public void setHorizontalAlignment(HorizontalAlignment horizontalAlignment) {
+ if (horizontalAlignment == null) {
+ throw new IllegalArgumentException("horizontalAlignment is null.");
+ }
+
+ this.horizontalAlignment = horizontalAlignment;
+ repaintComponent();
+ }
+
+ public final void setHorizontalAlignment(String horizontalAlignment) {
+ if (horizontalAlignment == null) {
+ throw new IllegalArgumentException("horizontalAlignment is null.");
+ }
+
+ setHorizontalAlignment(HorizontalAlignment.decode(horizontalAlignment));
+ }
+
+ public VerticalAlignment getVerticalAlignment() {
+ return verticalAlignment;
+ }
+
+ public void setVerticalAlignment(VerticalAlignment verticalAlignment) {
+ if (verticalAlignment == null) {
+ throw new IllegalArgumentException("verticalAlignment is null.");
+ }
+
+ this.verticalAlignment = verticalAlignment;
+ repaintComponent();
+ }
+
+ public final void setVerticalAlignment(String verticalAlignment) {
+ if (verticalAlignment == null) {
+ throw new IllegalArgumentException("verticalAlignment is null.");
+ }
+
+ setVerticalAlignment(VerticalAlignment.decode(verticalAlignment));
+ }
+
+ 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 boolean getWrapText() {
+ return wrapText;
+ }
+
+ public void setWrapText(boolean wrapText) {
+ this.wrapText = wrapText;
+ invalidateComponent();
+ }
+
+ // Label events
+ public void textChanged(Label label, String previousText) {
+ invalidateComponent();
+ }
+
+ public void textKeyChanged(Label label, String previousTextKey) {
+ // No-op
+ }
+}
Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/LinkButtonSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/LinkButtonSkin.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/LinkButtonSkin.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/LinkButtonSkin.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.skin;
+
+import pivot.wtk.Component;
+import pivot.wtk.LinkButton;
+import pivot.wtk.Mouse;
+
+/**
+ * Abstract base class for link button skins.
+ *
+ * @author gbrown
+ */
+public abstract class LinkButtonSkin extends ButtonSkin {
+ @Override
+ public void mouseClick(Component component, Mouse.Button button, int x, int y, int count) {
+ LinkButton linkButton = (LinkButton)getComponent();
+ linkButton.press();
+ }
+}
Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/ListButtonSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/ListButtonSkin.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/ListButtonSkin.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/ListButtonSkin.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.skin;
+
+import pivot.collections.ArrayList;
+import pivot.collections.List;
+import pivot.wtk.Button;
+import pivot.wtk.Component;
+import pivot.wtk.ComponentKeyListener;
+import pivot.wtk.ComponentMouseButtonListener;
+import pivot.wtk.Dimensions;
+import pivot.wtk.Direction;
+import pivot.wtk.Display;
+import pivot.wtk.Keyboard;
+import pivot.wtk.ListButton;
+import pivot.wtk.ListButtonListener;
+import pivot.wtk.ListButtonSelectionListener;
+import pivot.wtk.ListView;
+import pivot.wtk.Mouse;
+import pivot.wtk.Point;
+import pivot.wtk.Popup;
+import pivot.wtk.Window;
+
+/**
+ * Abstract base class for list button skins.
+ * <p>
+ * TODO Extend Popup instead of adding event listeners? May slightly simplify
+ * implementation.
+ * <p>
+ * TODO Rather than blindly closing when a mouse down is received, we could
+ * instead cache the selection state in the popup's container mouse down event
+ * and compare it to the current state in component mouse down. If different,
+ * we close the popup. This would also tie this base class less tightly to its
+ * concrete subclasses.
+ *
+ * @author gbrown
+ */
+public abstract class ListButtonSkin extends ButtonSkin
+ implements ListButtonListener, ListButtonSelectionListener {
+ protected ListView listView;
+ protected Popup listViewPopup;
+
+ private ComponentKeyListener listViewPopupKeyListener = new ComponentKeyListener() {
+ public void keyTyped(Component component, char character) {
+ // No-op
+ }
+
+ public boolean keyPressed(Component component, int keyCode, Keyboard.KeyLocation keyLocation) {
+ switch (keyCode) {
+ case Keyboard.KeyCode.ESCAPE: {
+ listViewPopup.close();
+ getComponent().requestFocus();
+ break;
+ }
+
+ case Keyboard.KeyCode.TAB:
+ case Keyboard.KeyCode.ENTER: {
+ ListButton listButton = (ListButton)getComponent();
+
+ int index = listView.getSelectedIndex();
+
+ listView.clearSelection();
+ listButton.setSelectedIndex(index);
+
+ listViewPopup.close();
+
+ if (keyCode == Keyboard.KeyCode.TAB) {
+ Direction direction = (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) ?
+ Direction.BACKWARD : Direction.FORWARD;
+ listButton.transferFocus(direction);
+ } else {
+ listButton.requestFocus();
+ }
+
+ break;
+ }
+ }
+
+ return false;
+ }
+
+ public boolean keyReleased(Component component, int keyCode, Keyboard.KeyLocation keyLocation) {
+ return false;
+ }
+ };
+
+ private ComponentMouseButtonListener listViewPopupMouseListener = new ComponentMouseButtonListener() {
+ 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) {
+ return false;
+ }
+
+ public void mouseClick(Component component, Mouse.Button button, int x, int y, int count) {
+ ListButton listButton = (ListButton)getComponent();
+
+ int index = listView.getSelectedIndex();
+
+ listView.clearSelection();
+ listButton.setSelectedIndex(index);
+
+ listViewPopup.close();
+ getComponent().requestFocus();
+ }
+ };
+
+ protected boolean pressed = false;
+
+ public ListButtonSkin() {
+ listView = new ListView();
+
+ listViewPopup = new Popup();
+ listViewPopup.getComponentMouseButtonListeners().add(listViewPopupMouseListener);
+ listViewPopup.getComponentKeyListeners().add(listViewPopupKeyListener);
+ }
+
+ @Override
+ public void install(Component component) {
+ super.install(component);
+
+ ListButton listButton = (ListButton)component;
+ listButton.getListButtonListeners().add(this);
+ listButton.getListButtonSelectionListeners().add(this);
+
+ listView.setListData(listButton.getListData());
+ listView.setItemRenderer(listButton.getItemRenderer());
+ }
+
+ @Override
+ public void uninstall() {
+ listViewPopup.close();
+
+ ListButton listButton = (ListButton)getComponent();
+ listButton.getListButtonListeners().remove(this);
+ listButton.getListButtonSelectionListeners().remove(this);
+
+ listView.setListData(new ArrayList<Object>());
+
+ super.uninstall();
+ }
+
+ // Component state events
+ @Override
+ public void enabledChanged(Component component) {
+ super.enabledChanged(component);
+
+ listViewPopup.close();
+ pressed = false;
+ }
+
+ @Override
+ public void focusedChanged(Component component, boolean temporary) {
+ super.focusedChanged(component, temporary);
+
+ // Close the popup if focus was transferred to a component whose
+ // window is not the popup
+ if (!component.isFocused()
+ && !listViewPopup.containsFocus()) {
+ listViewPopup.close();
+ }
+
+ pressed = false;
+ }
+
+ // Component mouse events
+ @Override
+ public void mouseOut(Component component) {
+ super.mouseOut(component);
+
+ pressed = false;
+ }
+
+ @Override
+ public boolean mouseDown(Component component, Mouse.Button button, int x, int y) {
+ boolean consumed = super.mouseDown(component, button, x, y);
+
+ pressed = true;
+ repaintComponent();
+
+ return consumed;
+ }
+
+ @Override
+ public boolean mouseUp(Component component, Mouse.Button button, int x, int y) {
+ boolean consumed = super.mouseUp(component, button, x, y);
+
+ pressed = false;
+ repaintComponent();
+
+ return consumed;
+ }
+
+ @Override
+ public void mouseClick(Component component, Mouse.Button button, int x, int y, int count) {
+ ListButton listButton = (ListButton)getComponent();
+
+ listButton.requestFocus();
+ listButton.press();
+
+ if (listView.isShowing()) {
+ listView.requestFocus();
+ }
+ }
+
+ @Override
+ public boolean keyPressed(Component component, int keyCode, Keyboard.KeyLocation keyLocation) {
+ boolean consumed = false;
+
+ if (keyCode == Keyboard.KeyCode.SPACE) {
+ pressed = true;
+ repaintComponent();
+ consumed = true;
+ } else if (keyCode == Keyboard.KeyCode.UP) {
+ ListButton listButton = (ListButton)getComponent();
+ int selectedIndex = listButton.getSelectedIndex();
+
+ if (selectedIndex > 0) {
+ listButton.setSelectedIndex(selectedIndex - 1);
+ consumed = true;
+ }
+ } else if (keyCode == Keyboard.KeyCode.DOWN) {
+ ListButton listButton = (ListButton)getComponent();
+ int selectedIndex = listButton.getSelectedIndex();
+
+ if (selectedIndex < listButton.getListData().getLength() - 1) {
+ listButton.setSelectedIndex(selectedIndex + 1);
+ consumed = true;
+ }
+ } else {
+ consumed = super.keyPressed(component, keyCode, keyLocation);
+ }
+
+ return consumed;
+ }
+
+ @Override
+ public boolean keyReleased(Component component, int keyCode, Keyboard.KeyLocation keyLocation) {
+ boolean consumed = false;
+
+ ListButton listButton = (ListButton)getComponent();
+
+ if (keyCode == Keyboard.KeyCode.SPACE) {
+ pressed = false;
+ repaintComponent();
+
+ listButton.press();
+ } else {
+ consumed = super.keyReleased(component, keyCode, keyLocation);
+ }
+
+ return consumed;
+ }
+
+ // Button events
+ @Override
+ public void buttonPressed(Button button) {
+ if (listViewPopup.isOpen()) {
+ listViewPopup.close();
+ } else {
+ ListButton listButton = (ListButton)button;
+
+ Component content = listViewPopup.getContent();
+
+ if (listButton.getListData().getLength() > 0) {
+ // Determine the popup's location and preferred size, relative
+ // to the button
+ Window window = listButton.getWindow();
+
+ if (window != null) {
+ int width = getWidth();
+ int height = getHeight();
+
+ Display display = listButton.getDisplay();
+
+ // Ensure that the popup remains within the bounds of the display
+ Point buttonLocation = listButton.mapPointToAncestor(display, 0, 0);
+
+ Dimensions displaySize = display.getSize();
+ Dimensions popupSize = content.getPreferredSize();
+
+ int x = buttonLocation.x;
+ if (popupSize.width > width
+ && x + popupSize.width > displaySize.width) {
+ x = buttonLocation.x + width - popupSize.width;
+ }
+
+ int y = buttonLocation.y + height - 1;
+ if (y + popupSize.height > displaySize.height) {
+ if (buttonLocation.y - popupSize.height > 0) {
+ y = buttonLocation.y - popupSize.height + 1;
+ } else {
+ popupSize.height = displaySize.height - y;
+ }
+ } else {
+ popupSize.height = -1;
+ }
+
+ listViewPopup.setLocation(x, y);
+ listViewPopup.setPreferredSize(popupSize);
+ listViewPopup.open(listButton);
+
+ if (listView.getFirstSelectedIndex() == -1
+ && listView.getListData().getLength() > 0) {
+ listView.setSelectedIndex(0);
+ }
+
+ listView.requestFocus();
+ }
+ }
+ }
+ }
+
+ // List button events
+ public void listDataChanged(ListButton listButton, List<?> previousListData) {
+ listView.setListData(listButton.getListData());
+ }
+
+ public void itemRendererChanged(ListButton listButton, ListView.ItemRenderer previousItemRenderer) {
+ listView.setItemRenderer(listButton.getItemRenderer());
+ }
+
+ public void selectedValueKeyChanged(ListButton listButton, String previousSelectedValueKey) {
+ // No-op
+ }
+
+ // List button selection events
+ public void selectedIndexChanged(ListButton listButton, int previousSelectedIndex) {
+ // Set the selected item as the button data
+ int selectedIndex = listButton.getSelectedIndex();
+
+ Object buttonData = (selectedIndex == -1) ? null : listButton.getListData().get(selectedIndex);
+ listButton.setButtonData(buttonData);
+
+ listView.setSelectedIndex(listButton.getSelectedIndex());
+ }
+}
Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/MenuBarItemSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/MenuBarItemSkin.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/MenuBarItemSkin.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/MenuBarItemSkin.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.skin;
+
+import pivot.util.Vote;
+import pivot.wtk.Button;
+import pivot.wtk.Component;
+import pivot.wtk.ComponentKeyListener;
+import pivot.wtk.Direction;
+import pivot.wtk.Display;
+import pivot.wtk.Keyboard;
+import pivot.wtk.Menu;
+import pivot.wtk.MenuBar;
+import pivot.wtk.MenuPopup;
+import pivot.wtk.Mouse;
+import pivot.wtk.Point;
+import pivot.wtk.Window;
+import pivot.wtk.WindowStateListener;
+
+/**
+ * Abstract base class for menu bar item skins.
+ *
+ * @author gbrown
+ */
+public abstract class MenuBarItemSkin extends ButtonSkin implements MenuBar.ItemListener {
+ protected MenuPopup menuPopup = new MenuPopup();
+
+ public MenuBarItemSkin() {
+ menuPopup.getWindowStateListeners().add(new WindowStateListener() {
+ public Vote previewWindowOpen(Window window, Display display) {
+ return Vote.APPROVE;
+ }
+
+ public void windowOpenVetoed(Window window, Vote reason) {
+ // No-op
+ }
+
+ public void windowOpened(Window window) {
+ // No-op
+ }
+
+ public Vote previewWindowClose(Window window) {
+ return Vote.APPROVE;
+ }
+
+ public void windowCloseVetoed(Window window, Vote reason) {
+ // No-op
+ }
+
+ public void windowClosed(Window window, Display display) {
+ MenuBar.Item menuBarItem = (MenuBar.Item)getComponent();
+ if (menuBarItem.isFocused()) {
+ Component.clearFocus();
+ } else {
+ repaintComponent();
+ }
+
+ MenuBar menuBar = menuBarItem.getMenuBar();
+ if (!menuBar.containsFocus()) {
+ menuBar.setActive(false);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void install(Component component) {
+ super.install(component);
+
+ MenuBar.Item menuBarItem = (MenuBar.Item)component;
+ menuBarItem.getItemListeners().add(this);
+
+ menuPopup.setMenu(menuBarItem.getMenu());
+ }
+
+ @Override
+ public void uninstall() {
+ MenuBar.Item menuBarItem = (MenuBar.Item)getComponent();
+ menuBarItem.getItemListeners().remove(this);
+
+ menuPopup.close();
+ menuPopup.setMenu(null);
+
+ super.uninstall();
+ }
+
+ @Override
+ public void mouseOver(Component component) {
+ super.mouseOver(component);
+
+ MenuBar.Item menuBarItem = (MenuBar.Item)getComponent();
+ MenuBar menuBar = menuBarItem.getMenuBar();
+
+ if (menuBar.isActive()) {
+ menuBarItem.requestFocus();
+ }
+ }
+
+ @Override
+ public boolean mouseDown(Component component, Mouse.Button button, int x, int y) {
+ boolean consumed = super.mouseDown(component, button, x, y);
+
+ MenuBar.Item menuBarItem = (MenuBar.Item)getComponent();
+ menuBarItem.requestFocus();
+
+ return consumed;
+ }
+
+ @Override
+ public void mouseClick(Component component, Mouse.Button button, int x, int y, int count) {
+ super.mouseClick(component, button, x, y, count);
+
+ MenuBar.Item menuBarItem = (MenuBar.Item)getComponent();
+ menuBarItem.press();
+ }
+
+ @Override
+ public boolean keyPressed(Component component, int keyCode, Keyboard.KeyLocation keyLocation) {
+ boolean consumed = false;
+
+ MenuBar.Item menuBarItem = (MenuBar.Item)getComponent();
+
+ if (keyCode == Keyboard.KeyCode.UP) {
+ menuPopup.requestFocus();
+ Component focusedComponent = Component.getFocusedComponent();
+ if (focusedComponent != null) {
+ focusedComponent.transferFocus(Direction.BACKWARD);
+ }
+
+ consumed = true;
+ } else if (keyCode == Keyboard.KeyCode.DOWN) {
+ menuPopup.requestFocus();
+ consumed = true;
+ } else if (keyCode == Keyboard.KeyCode.LEFT) {
+ menuBarItem.transferFocus(Direction.BACKWARD);
+ consumed = true;
+ } else if (keyCode == Keyboard.KeyCode.RIGHT) {
+ menuBarItem.transferFocus(Direction.FORWARD);
+ consumed = true;
+ } else if (keyCode == Keyboard.KeyCode.ENTER) {
+ menuBarItem.press();
+ consumed = true;
+ } else if (keyCode == Keyboard.KeyCode.ESCAPE) {
+ Component.clearFocus();
+ consumed = true;
+ } else {
+ consumed = super.keyPressed(component, keyCode, keyLocation);
+ }
+
+ return consumed;
+ }
+
+ @Override
+ public boolean keyReleased(Component component, int keyCode, Keyboard.KeyLocation keyLocation) {
+ boolean consumed = false;
+
+ MenuBar.Item menuBarItem = (MenuBar.Item)getComponent();
+
+ if (keyCode == Keyboard.KeyCode.SPACE) {
+ menuBarItem.press();
+ consumed = true;
+ } else {
+ consumed = super.keyReleased(component, keyCode, keyLocation);
+ }
+
+ return consumed;
+ }
+
+ @Override
+ public void enabledChanged(Component component) {
+ super.enabledChanged(component);
+
+ menuPopup.close();
+ }
+
+ @Override
+ public void focusedChanged(Component component, boolean temporary) {
+ super.focusedChanged(component, temporary);
+
+ final MenuBar.Item menuBarItem = (MenuBar.Item)getComponent();
+
+ if (component.isFocused()) {
+ if (!menuPopup.isOpen()) {
+ Display display = menuBarItem.getDisplay();
+ Point menuBarItemLocation = menuBarItem.mapPointToAncestor(display, 0, getHeight());
+
+ // TODO Ensure that the popup remains within the bounds of the display
+
+ menuPopup.setLocation(menuBarItemLocation.x, menuBarItemLocation.y);
+ menuPopup.open(menuBarItem);
+
+ // Listen for key events from the popup
+ menuPopup.getComponentKeyListeners().add(new ComponentKeyListener() {
+ public void keyTyped(Component component, char character) {
+ // No-op
+ }
+
+ public boolean keyPressed(Component component, int keyCode, Keyboard.KeyLocation keyLocation) {
+ if (keyCode == Keyboard.KeyCode.LEFT
+ || (keyCode == Keyboard.KeyCode.TAB
+ && Keyboard.isPressed(Keyboard.Modifier.SHIFT))) {
+ menuBarItem.transferFocus(Direction.BACKWARD);
+ } else if (keyCode == Keyboard.KeyCode.RIGHT
+ || keyCode == Keyboard.KeyCode.TAB) {
+ menuBarItem.transferFocus(Direction.FORWARD);
+ } else if (keyCode == Keyboard.KeyCode.ESCAPE) {
+ Component.clearFocus();
+ }
+
+ return false;
+ }
+
+ public boolean keyReleased(Component component, int keyCode, Keyboard.KeyLocation keyLocation) {
+ return false;
+ }
+ });
+ }
+ } else {
+ if (!temporary
+ && !menuPopup.containsFocus()) {
+ menuPopup.close();
+ }
+ }
+ }
+
+ public void buttonPressed(Button button) {
+ MenuBar.Item menuBarItem = (MenuBar.Item)getComponent();
+ MenuBar menuBar = menuBarItem.getMenuBar();
+
+ if (menuPopup.isOpen()) {
+ if (menuBar.isActive()) {
+ Component.clearFocus();
+ } else {
+ menuBar.setActive(true);
+ }
+ }
+ }
+
+ public void menuChanged(MenuBar.Item menuBarItem, Menu previousMenu) {
+ menuPopup.setMenu(menuBarItem.getMenu());
+ repaintComponent();
+ }
+}
Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/MenuButtonSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/MenuButtonSkin.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/MenuButtonSkin.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/MenuButtonSkin.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.skin;
+
+import pivot.util.Vote;
+import pivot.wtk.Button;
+import pivot.wtk.Component;
+import pivot.wtk.Dimensions;
+import pivot.wtk.Display;
+import pivot.wtk.Keyboard;
+import pivot.wtk.Menu;
+import pivot.wtk.MenuButton;
+import pivot.wtk.MenuButtonListener;
+import pivot.wtk.MenuPopup;
+import pivot.wtk.Mouse;
+import pivot.wtk.Point;
+import pivot.wtk.Window;
+import pivot.wtk.WindowStateListener;
+
+/**
+ * Abstract base class for menu button skins.
+ *
+ * @author gbrown
+ */
+public abstract class MenuButtonSkin extends ButtonSkin
+ implements MenuButtonListener {
+ protected boolean pressed = false;
+ protected MenuPopup menuPopup = new MenuPopup();
+
+ public MenuButtonSkin() {
+ menuPopup.getWindowStateListeners().add(new WindowStateListener() {
+ public Vote previewWindowOpen(Window window, Display display) {
+ return Vote.APPROVE;
+ }
+
+ public void windowOpenVetoed(Window window, Vote reason) {
+ // No-op
+ }
+
+ public void windowOpened(Window window) {
+ // No-op
+ }
+
+ public Vote previewWindowClose(Window window) {
+ return Vote.APPROVE;
+ }
+
+ public void windowCloseVetoed(Window window, Vote reason) {
+ // No-op
+ }
+
+ public void windowClosed(Window window, Display display) {
+ MenuButton menuButton = (MenuButton)getComponent();
+
+ if (menuButton.isFocusable()) {
+ menuButton.requestFocus();
+ }
+
+ repaintComponent();
+ }
+ });
+ }
+
+ @Override
+ public void install(Component component) {
+ super.install(component);
+
+ MenuButton menuButton = (MenuButton)getComponent();
+ menuButton.getMenuButtonListeners().add(this);
+
+ menuPopup.setMenu(menuButton.getMenu());
+ }
+
+ @Override
+ public void uninstall() {
+ MenuButton menuButton = (MenuButton)getComponent();
+ menuButton.getMenuButtonListeners().remove(this);
+
+ menuPopup.setMenu(null);
+
+ super.uninstall();
+ }
+
+ // Component state events
+ @Override
+ public void enabledChanged(Component component) {
+ super.enabledChanged(component);
+
+ menuPopup.close();
+ pressed = false;
+ }
+
+ @Override
+ public void focusedChanged(Component component, boolean temporary) {
+ super.focusedChanged(component, temporary);
+
+ // Close the popup if focus was transferred to a component whose
+ // window is not the popup
+ if (!component.isFocused()
+ && !menuPopup.containsFocus()) {
+ menuPopup.close();
+ }
+
+ pressed = false;
+ }
+
+ // Component mouse events
+ @Override
+ public void mouseOut(Component component) {
+ super.mouseOut(component);
+
+ pressed = false;
+ }
+
+ @Override
+ public boolean mouseDown(Component component, Mouse.Button button, int x, int y) {
+ boolean consumed = super.mouseDown(component, button, x, y);
+
+ // TODO Consume the event if the menu button is repeatable and the event
+ // occurs over the trigger
+
+ pressed = true;
+ repaintComponent();
+
+ return consumed;
+ }
+
+ @Override
+ public boolean mouseUp(Component component, Mouse.Button button, int x, int y) {
+ boolean consumed = super.mouseUp(component, button, x, y);
+
+ pressed = false;
+ repaintComponent();
+
+ return consumed;
+ }
+
+ @Override
+ public void mouseClick(Component component, Mouse.Button button, int x, int y, int count) {
+ MenuButton menuButton = (MenuButton)getComponent();
+
+ if (menuButton.isFocusable()) {
+ menuButton.requestFocus();
+ }
+
+ menuButton.press();
+
+ if (menuPopup.isShowing()) {
+ menuPopup.requestFocus();
+ }
+ }
+
+ @Override
+ public boolean keyPressed(Component component, int keyCode, Keyboard.KeyLocation keyLocation) {
+ boolean consumed = false;
+
+ if (keyCode == Keyboard.KeyCode.SPACE) {
+ pressed = true;
+ repaintComponent();
+ consumed = true;
+ } else {
+ consumed = super.keyPressed(component, keyCode, keyLocation);
+ }
+
+ return consumed;
+ }
+
+ @Override
+ public boolean keyReleased(Component component, int keyCode, Keyboard.KeyLocation keyLocation) {
+ boolean consumed = false;
+
+ MenuButton menuButton = (MenuButton)getComponent();
+
+ if (keyCode == Keyboard.KeyCode.SPACE) {
+ pressed = false;
+ repaintComponent();
+
+ menuButton.press();
+ } else {
+ consumed = super.keyReleased(component, keyCode, keyLocation);
+ }
+
+ return consumed;
+ }
+
+ // Button events
+ public void buttonPressed(Button button) {
+ if (menuPopup.isOpen()) {
+ menuPopup.close();
+ } else {
+ MenuButton menuButton = (MenuButton)getComponent();
+ Component content = menuPopup.getContent();
+
+ // Determine the popup's location and preferred size, relative
+ // to the button
+ Window window = menuButton.getWindow();
+
+ if (window != null) {
+ int width = getWidth();
+ int height = getHeight();
+
+ Display display = menuButton.getDisplay();
+
+ // Ensure that the popup remains within the bounds of the display
+ Point buttonLocation = menuButton.mapPointToAncestor(display, 0, 0);
+
+ Dimensions displaySize = display.getSize();
+ Dimensions popupSize = content.getPreferredSize();
+
+ int x = buttonLocation.x;
+ if (popupSize.width > width
+ && x + popupSize.width > displaySize.width) {
+ x = buttonLocation.x + width - popupSize.width;
+ }
+
+ int y = buttonLocation.y + height - 1;
+ if (y + popupSize.height > displaySize.height) {
+ if (buttonLocation.y - popupSize.height > 0) {
+ y = buttonLocation.y - popupSize.height + 1;
+ } else {
+ popupSize.height = displaySize.height - y;
+ }
+ } else {
+ popupSize.height = -1;
+ }
+
+ menuPopup.setLocation(x, y);
+ menuPopup.setPreferredSize(popupSize);
+ menuPopup.open(menuButton);
+
+ menuPopup.requestFocus();
+ }
+ }
+ }
+
+ public void menuChanged(MenuButton menuButton, Menu previousMenu) {
+ menuPopup.setMenu(menuButton.getMenu());
+ }
+
+ public void repeatableChanged(MenuButton menuButton) {
+ invalidateComponent();
+ }
+}
Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/MenuItemSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/MenuItemSkin.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/MenuItemSkin.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/MenuItemSkin.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.skin;
+
+import pivot.wtk.ApplicationContext;
+import pivot.wtk.Button;
+import pivot.wtk.Component;
+import pivot.wtk.Direction;
+import pivot.wtk.Display;
+import pivot.wtk.Keyboard;
+import pivot.wtk.Menu;
+import pivot.wtk.MenuPopup;
+import pivot.wtk.Mouse;
+import pivot.wtk.Point;
+
+/**
+ * Abstract base class for menu item skins.
+ *
+ * @author gbrown
+ */
+public abstract class MenuItemSkin extends ButtonSkin implements Menu.ItemListener {
+ protected MenuPopup menuPopup = new MenuPopup();
+
+ protected int buttonPressTimeoutID = -1;
+ protected int buttonPressInterval = 200;
+
+ @Override
+ public void install(Component component) {
+ super.install(component);
+
+ Menu.Item menuItem = (Menu.Item)component;
+ menuItem.getItemListeners().add(this);
+
+ menuPopup.setMenu(menuItem.getMenu());
+ }
+
+ @Override
+ public void uninstall() {
+ Menu.Item menuItem = (Menu.Item)getComponent();
+ menuItem.getItemListeners().remove(this);
+
+ menuPopup.close();
+ menuPopup.setMenu(null);
+
+ super.uninstall();
+ }
+
+ @Override
+ public void mouseOver(Component component) {
+ super.mouseOver(component);
+
+ ApplicationContext.clearInterval(buttonPressTimeoutID);
+
+ final Menu.Item menuItem = (Menu.Item)getComponent();
+ if (menuItem.getMenu() != null) {
+ buttonPressTimeoutID = ApplicationContext.setTimeout(new Runnable() {
+ public void run() {
+ menuItem.press();
+ }
+ }, buttonPressInterval);
+ }
+
+ menuItem.requestFocus();
+ }
+
+ @Override
+ public void mouseOut(Component component) {
+ super.mouseOut(component);
+ ApplicationContext.clearInterval(buttonPressTimeoutID);
+ }
+
+ @Override
+ public boolean mouseDown(Component component, Mouse.Button button, int x, int y) {
+ boolean consumed = super.mouseDown(component, button, x, y);
+ ApplicationContext.clearInterval(buttonPressTimeoutID);
+
+ return consumed;
+ }
+
+ @Override
+ public void mouseClick(Component component, Mouse.Button button, int x, int y, int count) {
+ super.mouseClick(component, button, x, y, count);
+
+ Menu.Item menuItem = (Menu.Item)getComponent();
+ menuItem.press();
+ }
+
+ @Override
+ public boolean keyPressed(Component component, int keyCode, Keyboard.KeyLocation keyLocation) {
+ boolean consumed = false;
+
+ ApplicationContext.clearInterval(buttonPressTimeoutID);
+
+ Menu.Item menuItem = (Menu.Item)getComponent();
+ Menu menu = menuItem.getMenu();
+
+ if (keyCode == Keyboard.KeyCode.UP) {
+ menuItem.transferFocus(Direction.BACKWARD);
+ consumed = true;
+ } else if (keyCode == Keyboard.KeyCode.DOWN) {
+ menuItem.transferFocus(Direction.FORWARD);
+ consumed = true;
+ } else if (keyCode == Keyboard.KeyCode.LEFT) {
+ Menu parentMenu = menuItem.getSection().getMenu();
+ Menu.Item parentMenuItem = parentMenu.getItem();
+ if (parentMenuItem != null) {
+ parentMenuItem.requestFocus();
+ consumed = true;
+ }
+
+ menuPopup.close();
+ } else if (keyCode == Keyboard.KeyCode.RIGHT) {
+ if (menu != null) {
+ if (!menuPopup.isOpen()) {
+ menuItem.press();
+ }
+
+ menu.requestFocus();
+ consumed = true;
+ }
+ } else if (keyCode == Keyboard.KeyCode.ENTER) {
+ menuItem.press();
+ consumed = true;
+ } else if (keyCode == Keyboard.KeyCode.TAB) {
+ // No-op
+ } else {
+ consumed = super.keyPressed(component, keyCode, keyLocation);
+ }
+
+ return consumed;
+ }
+
+ @Override
+ public boolean keyReleased(Component component, int keyCode, Keyboard.KeyLocation keyLocation) {
+ boolean consumed = false;
+
+ Menu.Item menuItem = (Menu.Item)getComponent();
+
+ if (keyCode == Keyboard.KeyCode.SPACE) {
+ menuItem.press();
+ consumed = true;
+ } else {
+ consumed = super.keyReleased(component, keyCode, keyLocation);
+ }
+
+ return consumed;
+ }
+
+ @Override
+ public void enabledChanged(Component component) {
+ super.enabledChanged(component);
+
+ menuPopup.close();
+ }
+
+ @Override
+ public void buttonPressed(Button button) {
+ Menu.Item menuItem = (Menu.Item)getComponent();
+ Menu menu = menuItem.getMenu();
+
+ if (menu != null
+ && !menuPopup.isOpen()) {
+ // Determine the popup's location and preferred size, relative
+ // to the menu item
+ Display display = menuItem.getDisplay();
+ Point menuItemLocation = menuItem.mapPointToAncestor(display, getWidth(), 0);
+
+ // TODO Ensure that the popup remains within the bounds of the display
+
+ menuPopup.setLocation(menuItemLocation.x, menuItemLocation.y);
+ menuPopup.open(menuItem);
+ }
+ }
+
+ public void menuChanged(Menu.Item menuItem, Menu previousMenu) {
+ menuPopup.setMenu(menuItem.getMenu());
+ repaintComponent();
+ }
+}
Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/PopupSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/PopupSkin.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/PopupSkin.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/PopupSkin.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.skin;
+
+import pivot.wtk.Component;
+import pivot.wtk.ComponentListener;
+import pivot.wtk.Container;
+import pivot.wtk.ContainerMouseListener;
+import pivot.wtk.Cursor;
+import pivot.wtk.Display;
+import pivot.wtk.Mouse;
+import pivot.wtk.Popup;
+import pivot.wtk.PopupListener;
+import pivot.wtk.Window;
+
+/**
+ * Popup skin.
+ *
+ * @author gbrown
+ */
+public class PopupSkin extends WindowSkin implements PopupListener {
+ private ComponentListener affiliateComponentListener = new ComponentListener() {
+ public void parentChanged(Component component, Container previousParent) {
+ // Ignore this event if it came from the affiliate's window.
+ // The window's parent may change as a result of a z-order change or
+ // the window being closed. As an owned window, this window will remain
+ // on top of the affiliate's window if the parent change is a result of
+ // a z-order change and will close if the parent change is a result
+ // of the affiliate's window being closed.
+
+ if (!(component instanceof Window)) {
+ // Remove this as a component listener on the previous parent's
+ // ancestry
+ Component ancestor = previousParent;
+
+ while (ancestor != null) {
+ ancestor.getComponentListeners().remove(this);
+ ancestor = ancestor.getParent();
+ }
+
+ // Close the popup
+ Popup popup = (Popup)getComponent();
+ popup.close();
+ }
+ }
+
+ public void sizeChanged(Component component, int previousWidth, int previousHeight) {
+ // Close the popup
+ Popup popup = (Popup)getComponent();
+ popup.close();
+ }
+
+ public void locationChanged(Component component, int previousX, int previousY) {
+ // Close the popup
+ Popup popup = (Popup)getComponent();
+ popup.close();
+ }
+
+ public void visibleChanged(Component component) {
+ // Close the popup
+ Popup popup = (Popup)getComponent();
+ popup.close();
+ }
+
+ public void styleUpdated(Component component, String styleKey, Object previousValue) {
+ // No-op
+ }
+
+ public void cursorChanged(Component component, Cursor previousCursor) {
+ // No-op
+ }
+
+ public void tooltipTextChanged(Component component, String previousTooltipText) {
+ // No-op
+ }
+ };
+
+ private ContainerMouseListener displayMouseListener = new ContainerMouseListener() {
+ public void mouseMove(Container container, int x, int y) {
+ }
+
+ public void mouseDown(Container container, Mouse.Button button, int x, int y) {
+ mouseEvent(container, x, y);
+ }
+
+ public void mouseUp(Container container, Mouse.Button button, int x, int y) {
+ }
+
+ public void mouseWheel(Container container, Mouse.ScrollType scrollType,
+ int scrollAmount, int wheelRotation, int x, int y) {
+ mouseEvent(container, x, y);
+ }
+
+ private void mouseEvent(Container container, int x, int y) {
+ // If the event did not occur within a window that is owned by
+ // this popup and did not occur within the popup's affiliate, close
+ // the popup
+ Display display = (Display)container;
+ Popup popup = (Popup)getComponent();
+
+ Window window = (Window)display.getComponentAt(x, y);
+ if (window == null
+ || !popup.isOwningAncestorOf(window)) {
+ Component affiliate = popup.getAffiliate();
+ Component descendant = display.getDescendantAt(x, y);
+
+ if (affiliate == null
+ || (affiliate instanceof Container
+ && !((Container)affiliate).isAncestor(descendant))
+ || descendant != affiliate) {
+ popup.close();
+ }
+ }
+ }
+ };
+
+ @Override
+ public void install(Component component) {
+ super.install(component);
+
+ Popup popup = (Popup)component;
+ popup.getPopupListeners().add(this);
+ }
+
+ @Override
+ public void uninstall() {
+ Popup popup = (Popup)getComponent();
+ popup.getPopupListeners().remove(this);
+
+ super.uninstall();
+ }
+
+ // Window events
+ @Override
+ public void windowOpened(Window window) {
+ // Add this as a component and container mouse listener on display
+ Display display = window.getDisplay();
+ display.getContainerMouseListeners().add(displayMouseListener);
+
+ // Add this as a component listener on the affiliate's ancestry
+ Popup popup = (Popup)window;
+ Component ancestor = popup.getAffiliate();
+
+ while (ancestor != null) {
+ ancestor.getComponentListeners().add(affiliateComponentListener);
+ ancestor = ancestor.getParent();
+ }
+ }
+
+ @Override
+ public void windowClosed(Window window, Display display) {
+ // Remove this as a component and container mouse listener on display
+ display.getContainerMouseListeners().remove(displayMouseListener);
+
+ // Remove this as a component listener on the affiliate's ancestry
+ Popup popup = (Popup)window;
+ Component ancestor = popup.getAffiliate();
+
+ while (ancestor != null) {
+ ancestor.getComponentListeners().remove(affiliateComponentListener);
+ ancestor = ancestor.getParent();
+ }
+ }
+
+ // Popup events
+ public void affiliateChanged(Popup popup, Component previousAffiliate) {
+ // No-op; the popup won't let the affiliate change while it is
+ // open, and we add/remove affiliate listeners in the open/close
+ // handlers
+ }
+}
Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/PushButtonSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/PushButtonSkin.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/PushButtonSkin.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/PushButtonSkin.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,99 @@
+package pivot.wtk.skin;
+
+import pivot.wtk.Component;
+import pivot.wtk.Keyboard;
+import pivot.wtk.Mouse;
+import pivot.wtk.PushButton;
+
+/**
+ * Abstract base class for push button skins.
+ *
+ * @author gbrown
+ */
+public abstract class PushButtonSkin extends ButtonSkin {
+ protected boolean pressed = false;
+
+ @Override
+ public void enabledChanged(Component component) {
+ super.enabledChanged(component);
+
+ pressed = false;
+ }
+
+ @Override
+ public void focusedChanged(Component component, boolean temporary) {
+ super.focusedChanged(component, temporary);
+
+ pressed = false;
+ }
+
+ @Override
+ public void mouseOut(Component component) {
+ super.mouseOut(component);
+
+ pressed = false;
+ }
+
+ @Override
+ public boolean mouseDown(Component component, Mouse.Button button, int x, int y) {
+ boolean consumed = super.mouseDown(component, button, x, y);
+
+ pressed = true;
+ repaintComponent();
+
+ return consumed;
+ }
+
+ @Override
+ public boolean mouseUp(Component component, Mouse.Button button, int x, int y) {
+ boolean consumed = super.mouseUp(component, button, x, y);
+
+ pressed = false;
+ repaintComponent();
+
+ return consumed;
+ }
+
+ @Override
+ public void mouseClick(Component component, Mouse.Button button, int x, int y, int count) {
+ PushButton pushButton = (PushButton)getComponent();
+
+ if (pushButton.isFocusable()) {
+ pushButton.requestFocus();
+ }
+
+ pushButton.press();
+ }
+
+ @Override
+ public boolean keyPressed(Component component, int keyCode, Keyboard.KeyLocation keyLocation) {
+ boolean consumed = false;
+
+ if (keyCode == Keyboard.KeyCode.SPACE) {
+ pressed = true;
+ repaintComponent();
+ } else {
+ consumed = super.keyPressed(component, keyCode, keyLocation);
+ }
+
+ return consumed;
+ }
+
+ @Override
+ public boolean keyReleased(Component component, int keyCode, Keyboard.KeyLocation keyLocation) {
+ boolean consumed = false;
+
+ PushButton pushButton = (PushButton)getComponent();
+
+ if (keyCode == Keyboard.KeyCode.SPACE) {
+ pressed = false;
+ repaintComponent();
+
+ pushButton.press();
+ } else {
+ consumed = super.keyReleased(component, keyCode, keyLocation);
+ }
+
+ return consumed;
+ }
+}
Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/RadioButtonSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/RadioButtonSkin.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/RadioButtonSkin.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/skin/RadioButtonSkin.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.skin;
+
+import pivot.wtk.Component;
+import pivot.wtk.Keyboard;
+import pivot.wtk.Mouse;
+import pivot.wtk.RadioButton;
+
+/**
+ * Abstract base class for radio button skins.
+ *
+ * @author gbrown
+ */
+public abstract class RadioButtonSkin extends ButtonSkin {
+ @Override
+ public void mouseClick(Component component, Mouse.Button button, int x, int y, int count) {
+ RadioButton radioButton = (RadioButton)getComponent();
+
+ radioButton.requestFocus();
+ radioButton.press();
+ }
+
+ @Override
+ public boolean keyReleased(Component component, int keyCode, Keyboard.KeyLocation keyLocation) {
+ boolean consumed = false;
+
+ RadioButton radioButton = (RadioButton)getComponent();
+
+ if (keyCode == Keyboard.KeyCode.SPACE) {
+ radioButton.press();
+ } else {
+ consumed = super.keyReleased(component, keyCode, keyLocation);
+ }
+
+ return consumed;
+ }
+
+}