| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to you 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 org.apache.pivot.wtk.skin.terra; |
| |
| import java.awt.Color; |
| import java.awt.Font; |
| import java.awt.GradientPaint; |
| import java.awt.Graphics2D; |
| |
| import org.apache.pivot.collections.ArrayList; |
| import org.apache.pivot.collections.Dictionary; |
| import org.apache.pivot.collections.Sequence; |
| import org.apache.pivot.util.Utils; |
| import org.apache.pivot.util.Vote; |
| import org.apache.pivot.wtk.Accordion; |
| import org.apache.pivot.wtk.AccordionAttributeListener; |
| import org.apache.pivot.wtk.AccordionListener; |
| import org.apache.pivot.wtk.AccordionSelectionListener; |
| import org.apache.pivot.wtk.Button; |
| import org.apache.pivot.wtk.ButtonGroup; |
| import org.apache.pivot.wtk.ButtonGroupListener; |
| import org.apache.pivot.wtk.Component; |
| import org.apache.pivot.wtk.ComponentStateListener; |
| import org.apache.pivot.wtk.Dimensions; |
| import org.apache.pivot.wtk.GraphicsUtilities; |
| import org.apache.pivot.wtk.Insets; |
| import org.apache.pivot.wtk.Keyboard; |
| import org.apache.pivot.wtk.Keyboard.KeyCode; |
| import org.apache.pivot.wtk.Keyboard.KeyLocation; |
| import org.apache.pivot.wtk.Keyboard.Modifier; |
| import org.apache.pivot.wtk.Mouse; |
| import org.apache.pivot.wtk.Platform; |
| import org.apache.pivot.wtk.Theme; |
| import org.apache.pivot.wtk.effects.ClipDecorator; |
| import org.apache.pivot.wtk.effects.Transition; |
| import org.apache.pivot.wtk.effects.TransitionListener; |
| import org.apache.pivot.wtk.effects.easing.Easing; |
| import org.apache.pivot.wtk.effects.easing.Quartic; |
| import org.apache.pivot.wtk.skin.ButtonSkin; |
| import org.apache.pivot.wtk.skin.ContainerSkin; |
| |
| /** |
| * Accordion skin. |
| */ |
| public class TerraAccordionSkin extends ContainerSkin implements AccordionListener, |
| AccordionSelectionListener, AccordionAttributeListener { |
| protected class PanelHeader extends Button { |
| private final Component panel; |
| |
| public PanelHeader(Component panel) { |
| this.panel = panel; |
| super.setToggleButton(true); |
| |
| setSkin(new PanelHeaderSkin()); |
| } |
| |
| @Override |
| public Object getButtonData() { |
| return Accordion.getHeaderData(panel); |
| } |
| |
| @Override |
| public void setButtonData(Object buttonData) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public Button.DataRenderer getDataRenderer() { |
| Accordion accordion = (Accordion) TerraAccordionSkin.this.getComponent(); |
| return accordion.getHeaderDataRenderer(); |
| } |
| |
| @Override |
| public void setDataRenderer(Button.DataRenderer dataRenderer) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public String getTooltipText() { |
| return Accordion.getTooltipText(panel); |
| } |
| |
| @Override |
| public void setTooltipText(String tooltipText) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public void setToggleButton(boolean toggleButton) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public void setTriState(boolean triState) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public void press() { |
| setSelected(true); |
| super.press(); |
| } |
| } |
| |
| protected class PanelHeaderSkin extends ButtonSkin { |
| @Override |
| public int getPreferredWidth(int height) { |
| PanelHeader panelHeader = (PanelHeader) getComponent(); |
| |
| Button.DataRenderer dataRenderer = panelHeader.getDataRenderer(); |
| dataRenderer.render(panelHeader.getButtonData(), panelHeader, false); |
| |
| int preferredWidth = dataRenderer.getPreferredWidth(-1) + buttonPadding.left |
| + buttonPadding.right + 2; |
| |
| return preferredWidth; |
| } |
| |
| @Override |
| public int getPreferredHeight(int width) { |
| PanelHeader panelHeader = (PanelHeader) getComponent(); |
| |
| Button.DataRenderer dataRenderer = panelHeader.getDataRenderer(); |
| dataRenderer.render(panelHeader.getButtonData(), panelHeader, false); |
| |
| // Include padding and border in constraint |
| int contentWidth = width; |
| if (contentWidth != -1) { |
| contentWidth = Math.max(contentWidth |
| - (buttonPadding.left + buttonPadding.right + 2), 0); |
| } |
| |
| int preferredHeight = dataRenderer.getPreferredHeight(contentWidth) + buttonPadding.top |
| + buttonPadding.bottom + 2; |
| |
| return preferredHeight; |
| } |
| |
| @Override |
| public Dimensions getPreferredSize() { |
| PanelHeader panelHeader = (PanelHeader) getComponent(); |
| |
| Button.DataRenderer dataRenderer = panelHeader.getDataRenderer(); |
| dataRenderer.render(panelHeader.getButtonData(), panelHeader, false); |
| |
| Dimensions preferredContentSize = dataRenderer.getPreferredSize(); |
| |
| int preferredWidth = preferredContentSize.width + buttonPadding.left |
| + buttonPadding.right + 2; |
| |
| int preferredHeight = preferredContentSize.height + buttonPadding.top |
| + buttonPadding.bottom + 2; |
| |
| return new Dimensions(preferredWidth, preferredHeight); |
| } |
| |
| @Override |
| public int getBaseline(int width, int height) { |
| PanelHeader panelHeader = (PanelHeader) getComponent(); |
| |
| Button.DataRenderer dataRenderer = panelHeader.getDataRenderer(); |
| dataRenderer.render(panelHeader.getButtonData(), panelHeader, false); |
| |
| int clientWidth = Math.max(width - (buttonPadding.left + buttonPadding.right + 2), 0); |
| int clientHeight = Math.max(height - (buttonPadding.top + buttonPadding.bottom + 2), 0); |
| |
| int baseline = dataRenderer.getBaseline(clientWidth, clientHeight); |
| |
| if (baseline != -1) { |
| baseline += buttonPadding.top + 1; |
| } |
| |
| return baseline; |
| } |
| |
| @Override |
| public void paint(Graphics2D graphics) { |
| PanelHeader panelHeader = (PanelHeader) getComponent(); |
| |
| int width = getWidth(); |
| int height = getHeight(); |
| |
| // Paint the background |
| if (!themeIsFlat()) { |
| graphics.setPaint(new GradientPaint(width / 2f, 0, buttonBevelColor, width / 2f, |
| height, buttonBackgroundColor)); |
| } else { |
| graphics.setPaint(buttonBackgroundColor); |
| } |
| graphics.fillRect(0, 0, width, height); |
| |
| // Paint the border |
| if (!themeIsFlat()) { |
| graphics.setPaint(borderColor); |
| GraphicsUtilities.drawRect(graphics, 0, 0, width, height); |
| } |
| |
| // Paint the content |
| Button.DataRenderer dataRenderer = panelHeader.getDataRenderer(); |
| dataRenderer.render(panelHeader.getButtonData(), panelHeader, false); |
| dataRenderer.setSize( |
| Math.max(width - (buttonPadding.left + buttonPadding.right + 2), 0), |
| Math.max(getHeight() - (buttonPadding.top + buttonPadding.bottom + 2), 0)); |
| |
| Graphics2D contentGraphics = (Graphics2D) graphics.create(); |
| contentGraphics.translate(buttonPadding.left + 1, buttonPadding.top + 1); |
| contentGraphics.clipRect(0, 0, dataRenderer.getWidth(), dataRenderer.getHeight()); |
| dataRenderer.paint(contentGraphics); |
| contentGraphics.dispose(); |
| } |
| |
| @Override |
| public boolean isFocusable() { |
| return false; |
| } |
| |
| @Override |
| public boolean mouseClick(Component component, Mouse.Button button, int x, int y, int count) { |
| PanelHeader panelHeader = (PanelHeader) getComponent(); |
| panelHeader.press(); |
| |
| return true; |
| } |
| |
| public Font getFont() { |
| return buttonFont; |
| } |
| |
| public Color getColor() { |
| return buttonColor; |
| } |
| |
| public Color getDisabledColor() { |
| return disabledButtonColor; |
| } |
| } |
| |
| public class SelectionChangeTransition extends Transition { |
| public final Component fromPanel; |
| public final Component toPanel; |
| |
| private Easing easing = new Quartic(); |
| |
| public SelectionChangeTransition(Component fromPanel, Component toPanel) { |
| super(selectionChangeDuration, selectionChangeRate, false); |
| this.fromPanel = fromPanel; |
| this.toPanel = toPanel; |
| } |
| |
| public float getEasedPercentComplete() { |
| return easing.easeOut(getElapsedTime(), 0, 1, getDuration()); |
| } |
| |
| @Override |
| public void start(TransitionListener transitionListener) { |
| fromPanel.getDecorators().add(previousSelectedPanelClipDecorator); |
| toPanel.getDecorators().add(selectedPanelClipDecorator); |
| |
| getComponent().setEnabled(false); |
| |
| super.start(transitionListener); |
| } |
| |
| @Override |
| public void stop() { |
| fromPanel.getDecorators().remove(previousSelectedPanelClipDecorator); |
| toPanel.getDecorators().remove(selectedPanelClipDecorator); |
| |
| getComponent().setEnabled(true); |
| |
| super.stop(); |
| } |
| |
| @Override |
| protected void update() { |
| invalidateComponent(); |
| } |
| } |
| |
| private ButtonGroup panelHeaderGroup = new ButtonGroup(); |
| private ArrayList<PanelHeader> panelHeaders = new ArrayList<>(); |
| |
| private Color borderColor; |
| private Insets padding; |
| private Font buttonFont; |
| private Color buttonColor; |
| private Color disabledButtonColor; |
| private Color buttonBackgroundColor; |
| private Insets buttonPadding; |
| |
| private int selectionChangeDuration = DEFAULT_SELECTION_CHANGE_DURATION; |
| private int selectionChangeRate = DEFAULT_SELECTION_CHANGE_RATE; |
| |
| private Color buttonBevelColor; |
| |
| private SelectionChangeTransition selectionChangeTransition = null; |
| private ClipDecorator previousSelectedPanelClipDecorator = new ClipDecorator(); |
| private ClipDecorator selectedPanelClipDecorator = new ClipDecorator(); |
| |
| private ComponentStateListener panelStateListener = new ComponentStateListener() { |
| @Override |
| public void enabledChanged(Component component) { |
| Accordion accordion = (Accordion) getComponent(); |
| int i = accordion.getPanels().indexOf(component); |
| panelHeaders.get(i).setEnabled(component.isEnabled()); |
| } |
| }; |
| |
| private static final int DEFAULT_SELECTION_CHANGE_DURATION = 250; |
| private static final int DEFAULT_SELECTION_CHANGE_RATE = 30; |
| |
| public TerraAccordionSkin() { |
| setBackgroundColor(4); |
| setBorderColor(7); |
| setButtonColor(12); |
| setDisabledButtonColor(7); |
| setButtonBackgroundColor(10); |
| |
| Theme theme = currentTheme(); |
| buttonFont = theme.getFont().deriveFont(Font.BOLD); |
| |
| padding = new Insets(4); |
| buttonPadding = new Insets(6, 8); // height, width |
| |
| panelHeaderGroup.getButtonGroupListeners().add(new ButtonGroupListener() { |
| @Override |
| public void selectionChanged(ButtonGroup buttonGroup, Button previousSelection) { |
| Button button = panelHeaderGroup.getSelection(); |
| int index = (button == null) ? -1 : panelHeaders.indexOf((PanelHeader) button); |
| |
| Accordion accordion = (Accordion) getComponent(); |
| accordion.setSelectedIndex(index); |
| } |
| }); |
| } |
| |
| @Override |
| public void setSize(int width, int height) { |
| if (selectionChangeTransition != null) { |
| selectionChangeTransition.end(); |
| } |
| |
| super.setSize(width, height); |
| } |
| |
| @Override |
| public void install(Component component) { |
| super.install(component); |
| |
| Accordion accordion = (Accordion) component; |
| accordion.getAccordionListeners().add(this); |
| accordion.getAccordionSelectionListeners().add(this); |
| accordion.getAccordionAttributeListeners().add(this); |
| } |
| |
| @Override |
| public int getPreferredWidth(int height) { |
| Accordion accordion = (Accordion) getComponent(); |
| |
| // The preferred width is the maximum unconstrained preferred width of |
| // the headers and the panels, plus border |
| int maxPanelHeaderWidth = 0; |
| for (PanelHeader panelHeader : panelHeaders) { |
| maxPanelHeaderWidth = Math.max(panelHeader.getPreferredWidth(), maxPanelHeaderWidth); |
| } |
| |
| int maxPanelWidth = 0; |
| for (Component panel : accordion.getPanels()) { |
| maxPanelWidth = Math.max(panel.getPreferredWidth(), maxPanelWidth); |
| } |
| |
| int preferredWidth = Math.max(maxPanelHeaderWidth, maxPanelWidth |
| + (padding.getWidth() + 2)); |
| |
| return preferredWidth; |
| } |
| |
| @Override |
| public int getPreferredHeight(int width) { |
| Accordion accordion = (Accordion) getComponent(); |
| |
| int preferredHeight = 0; |
| |
| // The preferred height is the sum of the constrained preferred heights |
| // of the headers and selected panel, plus border |
| for (PanelHeader panelHeader : panelHeaders) { |
| preferredHeight += panelHeader.getPreferredHeight(width) - 1; |
| } |
| |
| if (width != -1) { |
| width = Math.max(0, width - (padding.getWidth() + 2)); |
| } |
| |
| int maxPanelHeight = 0; |
| for (Component panel : accordion.getPanels()) { |
| maxPanelHeight = Math.max(maxPanelHeight, panel.getPreferredHeight(width)); |
| } |
| |
| preferredHeight += (maxPanelHeight + padding.getHeight() + 2); |
| |
| return preferredHeight; |
| } |
| |
| @Override |
| public Dimensions getPreferredSize() { |
| Accordion accordion = (Accordion) getComponent(); |
| |
| int preferredHeight = 0; |
| |
| int maxPanelHeaderWidth = 0; |
| for (PanelHeader panelHeader : panelHeaders) { |
| Dimensions preferredSize = panelHeader.getPreferredSize(); |
| maxPanelHeaderWidth = Math.max(preferredSize.width, maxPanelHeaderWidth); |
| preferredHeight += preferredSize.height - 1; |
| } |
| |
| int maxPanelWidth = 0; |
| int maxPanelHeight = 0; |
| |
| for (Component panel : accordion.getPanels()) { |
| Dimensions preferredSize = panel.getPreferredSize(); |
| maxPanelWidth = Math.max(preferredSize.width, maxPanelWidth); |
| maxPanelHeight = Math.max(maxPanelHeight, preferredSize.height); |
| } |
| |
| int preferredWidth = Math.max(maxPanelHeaderWidth, maxPanelWidth |
| + (padding.getWidth() + 2)); |
| |
| preferredHeight += (maxPanelHeight + padding.getHeight() + 2); |
| |
| return new Dimensions(preferredWidth, preferredHeight); |
| } |
| |
| @Override |
| public int getBaseline(int width, int height) { |
| int baseline = -1; |
| |
| if (panelHeaders.getLength() > 0) { |
| PanelHeader firstPanelHeader = panelHeaders.get(0); |
| baseline = firstPanelHeader.getBaseline(width, |
| firstPanelHeader.getPreferredHeight(width)); |
| } |
| |
| return baseline; |
| } |
| |
| @Override |
| public void layout() { |
| Accordion accordion = (Accordion) getComponent(); |
| |
| int width = getWidth(); |
| int height = getHeight(); |
| |
| int contentWidth = Math.max(width - (padding.getWidth() + 2), 0); |
| |
| // Determine the content height |
| int panelHeight = 0; |
| int contentHeight = 0; |
| |
| if (selectionChangeTransition == null) { |
| panelHeight = height; |
| for (PanelHeader panelHeader : panelHeaders) { |
| panelHeader.setSize(width, panelHeader.getPreferredHeight(width)); |
| panelHeight -= (panelHeader.getHeight() - 1); |
| } |
| |
| panelHeight = Math.max(panelHeight - 2, 0); |
| contentHeight = Math.max(panelHeight - padding.getHeight(), 0); |
| } else { |
| panelHeight = selectionChangeTransition.toPanel.getHeight() |
| + padding.getHeight(); |
| } |
| |
| // Lay out the components |
| Accordion.PanelSequence panels = accordion.getPanels(); |
| |
| int panelY = 0; |
| for (int i = 0, n = panels.getLength(); i < n; i++) { |
| Component panel = panels.get(i); |
| |
| PanelHeader panelHeader = panelHeaders.get(i); |
| panelHeader.setLocation(0, panelY); |
| panelY += (panelHeader.getHeight() - 1); |
| |
| if (selectionChangeTransition == null) { |
| Component toPanel = accordion.getSelectedPanel(); |
| |
| if (panel == toPanel) { |
| panel.setVisible(true); |
| |
| panel.setSize(contentWidth, contentHeight); |
| panel.setLocation(padding.left + 1, panelY + padding.top + 1); |
| |
| panelY += panelHeight + 1; |
| } else { |
| panel.setVisible(false); |
| } |
| } else { |
| if (selectionChangeTransition.isRunning()) { |
| if (panel == selectionChangeTransition.fromPanel) { |
| panel.setLocation(padding.left + 1, panelY + padding.top + 1); |
| |
| int previousSelectedPanelHeight = Math.round(panelHeight |
| * (1.0f - selectionChangeTransition.getEasedPercentComplete())); |
| previousSelectedPanelClipDecorator.setWidth(contentWidth); |
| previousSelectedPanelClipDecorator.setHeight(previousSelectedPanelHeight); |
| |
| panelY += previousSelectedPanelHeight + 1; |
| } |
| |
| if (panel == selectionChangeTransition.toPanel) { |
| panel.setLocation(padding.left + 1, panelY + padding.top + 1); |
| |
| int selectedPanelHeight = Math.round(panelHeight |
| * selectionChangeTransition.getEasedPercentComplete()); |
| selectedPanelClipDecorator.setWidth(contentWidth); |
| selectedPanelClipDecorator.setHeight(selectedPanelHeight); |
| |
| panelY += selectedPanelHeight; |
| } |
| } else { |
| selectionChangeTransition.toPanel.setSize(selectionChangeTransition.fromPanel.getSize()); |
| selectionChangeTransition.toPanel.setVisible(true); |
| } |
| } |
| } |
| } |
| |
| @Override |
| public void paint(Graphics2D graphics) { |
| // Call the base class to paint the background |
| super.paint(graphics); |
| |
| // Draw the border |
| int width = getWidth(); |
| int height = getHeight(); |
| |
| if (!themeIsFlat()) { |
| graphics.setPaint(borderColor); |
| GraphicsUtilities.drawRect(graphics, 0, 0, width, height); |
| } |
| } |
| |
| public Insets getPadding() { |
| return padding; |
| } |
| |
| public void setPadding(Insets padding) { |
| Utils.checkNull(padding, "padding"); |
| |
| this.padding = padding; |
| invalidateComponent(); |
| } |
| |
| public final void setPadding(Dictionary<String, ?> padding) { |
| setPadding(new Insets(padding)); |
| } |
| |
| public final void setPadding(Sequence<?> padding) { |
| setPadding(new Insets(padding)); |
| } |
| |
| public final void setPadding(int padding) { |
| setPadding(new Insets(padding)); |
| } |
| |
| public final void setPadding(Number padding) { |
| setPadding(new Insets(padding)); |
| } |
| |
| public final void setPadding(String padding) { |
| setPadding(Insets.decode(padding)); |
| } |
| |
| public Font getButtonFont() { |
| return buttonFont; |
| } |
| |
| public void setButtonFont(Font buttonFont) { |
| Utils.checkNull(buttonFont, "buttonFont"); |
| |
| this.buttonFont = buttonFont; |
| invalidateComponent(); |
| } |
| |
| public final void setButtonFont(String buttonFont) { |
| setButtonFont(decodeFont(buttonFont)); |
| } |
| |
| public final void setButtonFont(Dictionary<String, ?> buttonFont) { |
| setButtonFont(Theme.deriveFont(buttonFont)); |
| } |
| |
| public Color getBorderColor() { |
| return borderColor; |
| } |
| |
| public void setBorderColor(Color borderColor) { |
| Utils.checkNull(borderColor, "borderColor"); |
| |
| this.borderColor = borderColor; |
| repaintComponent(); |
| } |
| |
| public final void setBorderColor(String borderColor) { |
| setBorderColor(GraphicsUtilities.decodeColor(borderColor, "borderColor")); |
| } |
| |
| public final void setBorderColor(int borderColor) { |
| Theme theme = currentTheme(); |
| setBorderColor(theme.getColor(borderColor)); |
| } |
| |
| public Color getButtonColor() { |
| return buttonColor; |
| } |
| |
| public void setButtonColor(Color buttonColor) { |
| Utils.checkNull(buttonColor, "buttonColor"); |
| |
| this.buttonColor = buttonColor; |
| repaintComponent(); |
| } |
| |
| public final void setButtonColor(String buttonColor) { |
| setButtonColor(GraphicsUtilities.decodeColor(buttonColor, "buttonColor")); |
| } |
| |
| public final void setButtonColor(int buttonColor) { |
| Theme theme = currentTheme(); |
| setButtonColor(theme.getColor(buttonColor)); |
| } |
| |
| public Color getDisabledButtonColor() { |
| return disabledButtonColor; |
| } |
| |
| public void setDisabledButtonColor(Color disabledButtonColor) { |
| Utils.checkNull(disabledButtonColor, "disabledButtonColor"); |
| |
| this.disabledButtonColor = disabledButtonColor; |
| repaintComponent(); |
| } |
| |
| public final void setDisabledButtonColor(String disabledButtonColor) { |
| setDisabledButtonColor(GraphicsUtilities.decodeColor(disabledButtonColor, "disabledButtonColor")); |
| } |
| |
| public final void setDisabledButtonColor(int disabledButtonColor) { |
| Theme theme = currentTheme(); |
| setDisabledButtonColor(theme.getColor(disabledButtonColor)); |
| } |
| |
| public Color getButtonBackgroundColor() { |
| return buttonBackgroundColor; |
| } |
| |
| public void setButtonBackgroundColor(Color buttonBackgroundColor) { |
| Utils.checkNull(buttonBackgroundColor, "buttonBackgroundColor"); |
| |
| this.buttonBackgroundColor = buttonBackgroundColor; |
| buttonBevelColor = TerraTheme.brighten(buttonBackgroundColor); |
| repaintComponent(); |
| } |
| |
| public final void setButtonBackgroundColor(String buttonBackgroundColor) { |
| setButtonBackgroundColor(GraphicsUtilities.decodeColor(buttonBackgroundColor, "buttonBackgroundColor")); |
| } |
| |
| public final void setButtonBackgroundColor(int buttonBackgroundColor) { |
| Theme theme = currentTheme(); |
| setButtonBackgroundColor(theme.getColor(buttonBackgroundColor)); |
| } |
| |
| public Insets getButtonPadding() { |
| return buttonPadding; |
| } |
| |
| public void setButtonPadding(Insets buttonPadding) { |
| Utils.checkNull(buttonPadding, "buttonPadding"); |
| |
| this.buttonPadding = buttonPadding; |
| invalidateComponent(); |
| } |
| |
| public final void setButtonPadding(Dictionary<String, ?> buttonPadding) { |
| setButtonPadding(new Insets(buttonPadding)); |
| } |
| |
| public final void setButtonPadding(Sequence<?> buttonPadding) { |
| setButtonPadding(new Insets(buttonPadding)); |
| } |
| |
| public final void setButtonPadding(int buttonPadding) { |
| setButtonPadding(new Insets(buttonPadding)); |
| } |
| |
| public final void setButtonPadding(Number padding) { |
| setButtonPadding(new Insets(padding)); |
| } |
| |
| public final void setButtonPadding(String padding) { |
| setButtonPadding(Insets.decode(padding)); |
| } |
| |
| public int getSelectionChangeDuration() { |
| return selectionChangeDuration; |
| } |
| |
| public void setSelectionChangeDuration(int selectionChangeDuration) { |
| this.selectionChangeDuration = selectionChangeDuration; |
| } |
| |
| public int getSelectionChangeRate() { |
| return selectionChangeRate; |
| } |
| |
| public void setSelectionChangeRate(int selectionChangeRate) { |
| this.selectionChangeRate = selectionChangeRate; |
| } |
| |
| /** |
| * Key presses have no effect if the event has already been consumed.<p> |
| * CommandModifier + {@link KeyCode#KEYPAD_1 KEYPAD_1} to |
| * {@link KeyCode#KEYPAD_9 KEYPAD_9}<br>or CommandModifier + |
| * {@link KeyCode#N1 1} to {@link KeyCode#N9 9} Select the (enabled) pane at |
| * index 0 to 8 respectively<p> {@link Modifier#ALT ALT} + |
| * {@link KeyCode#UP UP} Select the next enabled panel.<br> |
| * {@link Modifier#ALT ALT} + {@link KeyCode#DOWN DOWN} Select the previous |
| * enabled panel. |
| * |
| * @see Platform#getCommandModifier() |
| */ |
| @Override |
| public boolean keyPressed(Component component, int keyCode, KeyLocation keyLocation) { |
| boolean consumed = super.keyPressed(component, keyCode, keyLocation); |
| |
| if (!consumed) { |
| Accordion accordion = (Accordion) getComponent(); |
| Accordion.PanelSequence panels = accordion.getPanels(); |
| |
| Modifier commandModifier = Platform.getCommandModifier(); |
| if (Keyboard.isPressed(commandModifier)) { |
| int selectedIndex = -1; |
| |
| switch (keyCode) { |
| case KeyCode.KEYPAD_1: |
| case KeyCode.N1: |
| selectedIndex = 0; |
| break; |
| |
| case KeyCode.KEYPAD_2: |
| case KeyCode.N2: |
| selectedIndex = 1; |
| break; |
| |
| case KeyCode.KEYPAD_3: |
| case KeyCode.N3: |
| selectedIndex = 2; |
| break; |
| |
| case KeyCode.KEYPAD_4: |
| case KeyCode.N4: |
| selectedIndex = 3; |
| break; |
| |
| case KeyCode.KEYPAD_5: |
| case KeyCode.N5: |
| selectedIndex = 4; |
| break; |
| |
| case KeyCode.KEYPAD_6: |
| case KeyCode.N6: |
| selectedIndex = 5; |
| break; |
| |
| case KeyCode.KEYPAD_7: |
| case KeyCode.N7: |
| selectedIndex = 6; |
| break; |
| |
| case KeyCode.KEYPAD_8: |
| case KeyCode.N8: |
| selectedIndex = 7; |
| break; |
| |
| case KeyCode.KEYPAD_9: |
| case KeyCode.N9: |
| selectedIndex = 8; |
| break; |
| |
| default: |
| break; |
| } |
| |
| if (selectedIndex >= 0 && selectedIndex < panels.getLength() |
| && panels.get(selectedIndex).isEnabled()) { |
| accordion.setSelectedIndex(selectedIndex); |
| consumed = true; |
| } |
| } else if (Keyboard.isPressed(Modifier.ALT)) { |
| int n = panels.getLength(); |
| int selectedIndex = accordion.getSelectedIndex(); |
| |
| switch (keyCode) { |
| case KeyCode.UP: |
| do { |
| selectedIndex--; |
| } while (selectedIndex >= 0 && !panels.get(selectedIndex).isEnabled()); |
| |
| break; |
| |
| case KeyCode.DOWN: |
| do { |
| selectedIndex++; |
| } while (selectedIndex < n && !panels.get(selectedIndex).isEnabled()); |
| |
| break; |
| |
| default: |
| break; |
| } |
| |
| if (selectedIndex >= 0 && selectedIndex < n |
| && panels.get(selectedIndex).isEnabled()) { |
| accordion.setSelectedIndex(selectedIndex); |
| consumed = true; |
| } |
| } |
| } |
| |
| return consumed; |
| } |
| |
| // Accordion events |
| @Override |
| public void panelInserted(Accordion accordion, int index) { |
| if (selectionChangeTransition != null) { |
| selectionChangeTransition.end(); |
| } |
| |
| // Add a header for the panel |
| Component panel = accordion.getPanels().get(index); |
| PanelHeader panelHeader = new PanelHeader(panel); |
| panelHeader.setButtonGroup(panelHeaderGroup); |
| panelHeaders.insert(panelHeader, index); |
| accordion.add(panelHeader); |
| |
| // Listen for state changes on the panel |
| panelHeader.setEnabled(panel.isEnabled()); |
| panel.getComponentStateListeners().add(panelStateListener); |
| |
| // If this is the first panel, select it |
| if (accordion.getPanels().getLength() == 1) { |
| accordion.setSelectedIndex(0); |
| } |
| |
| invalidateComponent(); |
| } |
| |
| @Override |
| public void panelsRemoved(Accordion accordion, int index, Sequence<Component> removed) { |
| if (selectionChangeTransition != null) { |
| selectionChangeTransition.end(); |
| } |
| |
| // Remove the headers |
| Sequence<PanelHeader> removedHeaders = panelHeaders.remove(index, removed.getLength()); |
| |
| for (int i = 0, n = removedHeaders.getLength(); i < n; i++) { |
| PanelHeader panelHeader = removedHeaders.get(i); |
| panelHeader.setButtonGroup(null); |
| |
| // Stop listening for state changes on the panel |
| panelHeader.panel.getComponentStateListeners().remove(panelStateListener); |
| |
| // Remove the header |
| accordion.remove(panelHeader); |
| } |
| |
| invalidateComponent(); |
| } |
| |
| @Override |
| public void headerDataRendererChanged(Accordion accordion, |
| Button.DataRenderer previousHeaderDataRenderer) { |
| for (Component panelHeader : panelHeaders) { |
| panelHeader.invalidate(); |
| } |
| } |
| |
| // Accordion selection events |
| @Override |
| public Vote previewSelectedIndexChange(final Accordion accordion, final int selectedIndex) { |
| Vote vote = Vote.APPROVE; |
| |
| if (accordion.isShowing() && accordion.isValid()) { |
| if (selectionChangeTransition == null) { |
| int previousSelectedIndex = accordion.getSelectedIndex(); |
| |
| if (selectedIndex != -1 && previousSelectedIndex != -1) { |
| Component fromPanel = accordion.getPanels().get(previousSelectedIndex); |
| Component toPanel = accordion.getPanels().get(selectedIndex); |
| |
| selectionChangeTransition = new SelectionChangeTransition(fromPanel, toPanel); |
| |
| layout(); |
| selectionChangeTransition.start(new TransitionListener() { |
| @Override |
| public void transitionCompleted(Transition transition) { |
| accordion.setSelectedIndex(selectedIndex); |
| selectionChangeTransition = null; |
| |
| invalidateComponent(); |
| } |
| }); |
| |
| vote = Vote.DEFER; |
| } |
| } else { |
| if (selectionChangeTransition.isRunning()) { |
| vote = Vote.DEFER; |
| } |
| } |
| } |
| |
| return vote; |
| } |
| |
| @Override |
| public void selectedIndexChangeVetoed(Accordion accordion, Vote reason) { |
| if (reason == Vote.DENY && selectionChangeTransition != null) { |
| // NOTE We stop, rather than end, the transition so the completion |
| // event isn't fired; if the event fires, the listener will set |
| // the selection state |
| selectionChangeTransition.stop(); |
| selectionChangeTransition = null; |
| invalidateComponent(); |
| } |
| } |
| |
| @Override |
| public void selectedIndexChanged(Accordion accordion, int previousSelectedIndex) { |
| int selectedIndex = accordion.getSelectedIndex(); |
| |
| if (selectedIndex != previousSelectedIndex) { |
| // This was not an indirect selection change |
| if (selectedIndex == -1) { |
| Button button = panelHeaderGroup.getSelection(); |
| if (button != null) { |
| button.setSelected(false); |
| } |
| } else { |
| Button button = panelHeaders.get(selectedIndex); |
| button.setSelected(true); |
| |
| Component selectedPanel = accordion.getPanels().get(selectedIndex); |
| selectedPanel.requestFocus(); |
| } |
| |
| invalidateComponent(); |
| } |
| } |
| |
| // Accordion attribute events |
| @Override |
| public void headerDataChanged(Accordion accordion, Component component, |
| Object previousHeaderData) { |
| int i = accordion.getPanels().indexOf(component); |
| panelHeaders.get(i).invalidate(); |
| } |
| |
| @Override |
| public void tooltipTextChanged(Accordion accordion, Component component, |
| String previousTooltipText) { |
| // No-op |
| } |
| } |