package org.jtheque.ui.components; /* * Copyright JTheque (Baptiste Wicht) * * 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. */ import org.jtheque.i18n.LanguageService; import org.jtheque.ui.ViewComponent; import org.jtheque.utils.collections.CollectionUtils; import org.jdesktop.jxlayer.JXLayer; import org.jdesktop.jxlayer.plaf.BufferedLayerUI; import javax.swing.JComponent; import javax.swing.JTabbedPane; import javax.swing.Timer; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.Component; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import java.util.List; /** * A tabbed pane with different layer. * * @author Baptiste Wicht */ public class LayerTabbedPane extends JTabbedPane implements ViewComponent { private final List<JXLayer<JComponent>> components = CollectionUtils.newList(5); private final LanguageService languageService; /** * Construct a new LayerTabbedPane. * * @param languageService The language service. */ public LayerTabbedPane(LanguageService languageService) { super(); this.languageService = languageService; addChangeListener(new TabbedAnimatingChangeListener()); } /** * Add an internationalized tab. * * @param key The internationalization key. * @param component The component to add. */ public final void addInternationalizedTab(String key, JComponent component) { addLayeredTab(languageService.getMessage(key), component); } /** * Add a tab. * * @param title The title of the tab. * @param component The tab component. */ public final void addLayeredTab(String title, JComponent component) { JXLayer<JComponent> layerComponent = new JXLayer<JComponent>(component); components.add(layerComponent); addTab(title, layerComponent); } @Override public final JComponent getSelectedComponent() { if (getSelectedIndex() != -1) { return components.get(getSelectedIndex()).getView(); } return null; } /** * Return the selected layer. * * @return the selected layer or null if there is no selected layer. */ final JXLayer<JComponent> getSelectedLayer() { JXLayer<JComponent> layer = null; if (getSelectedIndex() != -1) { layer = components.get(getSelectedIndex()); } return layer; } /** * Return the layer at a certain index. * * @param index The index for which we search the layer. * * @return the corresponding layer. */ final JXLayer<JComponent> getLayerAt(int index) { return components.get(index); } /** * A listener to animate the tabbed pane. * * @author Baptiste Wicht */ private static final class TabbedAnimatingChangeListener implements ChangeListener { private int index; private final Timer timer; private final AnimationLayerUI layerUI; private float delta; private static final int ANIMATION_DELAY = 50; /** * Construct a new <code>TabbedAnimatingChangeListener</code>. */ private TabbedAnimatingChangeListener() { super(); delta = 0.1f; layerUI = new AnimationLayerUI(); timer = new Timer(ANIMATION_DELAY, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (layerUI.getAlpha() <= delta) { layerUI.setAlpha(0); timer.stop(); return; } layerUI.setAlpha(layerUI.getAlpha() - delta); } }); } /** * Return the current delta for alpha. * * @return The delta for alpha value. */ public float getDelta() { return delta; } /** * Set the delta for alpha. * * @param delta The delta. */ public void setDelta(float delta) { if (delta <= 0 || delta > 1) { throw new IllegalArgumentException(); } this.delta = delta; } @Override public void stateChanged(ChangeEvent e) { LayerTabbedPane pane = (LayerTabbedPane) e.getSource(); JXLayer<JComponent> layer = pane.getSelectedLayer(); JXLayer<JComponent> oldLayer = pane.getLayerAt(index); if (oldLayer != null && layer != null) { layerUI.setAlpha(1 - layerUI.getAlpha()); layerUI.setComponent(oldLayer); oldLayer.setUI(layer.getUI()); layer.setUI(layerUI); //painter.org.jtheque.update(); timer.start(); index = pane.getSelectedIndex(); } } } @Override public Object getImpl() { return this; } /** * A layer UI for the animation. * * @author Baptiste Wicht */ private static final class AnimationLayerUI extends BufferedLayerUI<JComponent> { private static final long serialVersionUID = 4575416080010970635L; private transient BufferedImage componentImage; /** * Construct a new <code>AnimationLayerUI</code>. */ private AnimationLayerUI() { setAlpha(0); setIncrementalUpdate(false); } /** * Set the component to paint. * * @param component The component to paint. */ public void setComponent(Component component) { if (component == null || component.getWidth() <= 0 || component.getHeight() <= 0) { componentImage = null; } else { if (componentImage == null || componentImage.getWidth() != component.getWidth() || componentImage.getHeight() != component.getHeight()) { componentImage = createBuffer(component.getWidth(), component.getHeight()); } Graphics g = componentImage.getGraphics(); component.paint(g); g.dispose(); } } @Override public void paint(Graphics g, JComponent c) { // always paint the layer c.paint(g); super.paint(g, c); } @Override protected void paintLayer(Graphics2D graphics2D, JXLayer<? extends JComponent> jxLayer) { if (componentImage != null) { // paint the old layer with diminishing alpha graphics2D.drawImage(componentImage, 0, 0, null); } } } }