com.intellij.ui.JBCardLayout.java Source code

Java tutorial

Introduction

Here is the source code for com.intellij.ui.JBCardLayout.java

Source

/*
 * Copyright 2000-2014 JetBrains s.r.o.
 *
 * 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 com.intellij.ui;

import com.intellij.openapi.wm.IdeFocusManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * User: Vassiliy.Kudryashov
 */
public class JBCardLayout extends CardLayout {
    public enum SwipeDirection {
        FORWARD, BACKWARD, AUTO
    }

    private Map<String, Component> myMap = new LinkedHashMap<String, Component>();
    private int mySwipeTime = 200;//default value, provide setter if need
    private int mySwipeSteps = 20;//default value, provide setter if need
    private final Timer myTimer = new Timer(Math.max(1, mySwipeTime / mySwipeSteps), null);
    private Component mySwipeFrom = null;
    private Component mySwipeTo = null;

    public JBCardLayout() {
        this(0, 0);
    }

    public JBCardLayout(int hgap, int vgap) {
        super(hgap, vgap);
    }

    @Override
    public void addLayoutComponent(String name, Component comp) {
        super.addLayoutComponent(name, comp);
        myMap.put(name, comp);
    }

    @Override
    public void removeLayoutComponent(Component comp) {
        stopSwipeIfNeed();
        super.removeLayoutComponent(comp);
        for (Iterator<Map.Entry<String, Component>> iterator = myMap.entrySet().iterator(); iterator.hasNext();) {
            Map.Entry<String, Component> entry = iterator.next();
            if (entry.getValue() == comp) {
                iterator.remove();
                break;
            }
        }
    }

    @Override
    public void layoutContainer(Container parent) {
        if (!myTimer.isRunning()) {
            super.layoutContainer(parent);
        }
    }

    public void swipe(@NotNull final Container parent, @NotNull final String name,
            @NotNull SwipeDirection direction) {
        swipe(parent, name, direction, null);
    }

    public void swipe(@NotNull final Container parent, @NotNull final String name,
            @NotNull SwipeDirection direction, final @Nullable Runnable onDone) {
        stopSwipeIfNeed();
        mySwipeFrom = findVisible(parent);
        mySwipeTo = myMap.get(name);
        if (mySwipeTo == null)
            return;
        if (mySwipeFrom == null || mySwipeFrom == mySwipeTo) {
            super.show(parent, name);
            if (onDone != null) {
                onDone.run();
            }
            return;
        }
        final boolean isForward;
        if (direction == SwipeDirection.AUTO) {
            boolean b = true;
            for (Component component : myMap.values()) {
                if (component == mySwipeFrom || component == mySwipeTo) {
                    b = component == mySwipeFrom;
                    break;
                }
            }
            isForward = b;
        } else {
            isForward = direction == SwipeDirection.FORWARD;
        }
        final double[] linearProgress = new double[1];
        linearProgress[0] = 0;
        final long startTime = System.currentTimeMillis();
        ActionListener listener = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                long timePassed = System.currentTimeMillis() - startTime;
                if (timePassed >= mySwipeTime) {
                    Component currentFocusComponent = IdeFocusManager.getGlobalInstance()
                            .getFocusedDescendantFor(parent);
                    show(parent, name);
                    if (currentFocusComponent != null)
                        currentFocusComponent.requestFocusInWindow();
                    if (onDone != null) {
                        onDone.run();
                    }
                    return;
                }
                linearProgress[0] = Math.min(1, Math.max(0, (float) timePassed / mySwipeTime));
                double naturalProgress = (1 - Math.cos(Math.PI * linearProgress[0])) / 2;
                Rectangle bounds = parent.getBounds();
                Insets insets = parent.getInsets();
                bounds.setLocation(insets.left, insets.top);
                bounds.width -= insets.left + insets.right;
                bounds.height -= insets.top + insets.bottom;
                Rectangle r = new Rectangle(bounds);
                int x = (int) ((naturalProgress * r.width));
                r.translate(isForward ? -x : x, 0);
                mySwipeFrom.setBounds(r);
                Rectangle r2 = new Rectangle(bounds);
                r2.translate(isForward ? r2.width - x : x - r2.width, 0);
                mySwipeTo.setVisible(true);
                mySwipeTo.setBounds(r2);
                parent.repaint();
            }
        };
        for (ActionListener actionListener : myTimer.getActionListeners()) {
            myTimer.removeActionListener(actionListener);
        }
        myTimer.addActionListener(listener);
        myTimer.start();
    }

    private void stopSwipeIfNeed() {
        if (myTimer.isRunning()) {
            myTimer.stop();
            mySwipeFrom = null;
            if (mySwipeTo != null) {
                mySwipeTo.setVisible(false);
                mySwipeTo = null;
            }
        }
    }

    @Nullable
    private static Component findVisible(Container parent) {
        for (int i = 0; i < parent.getComponentCount(); i++) {
            Component component = parent.getComponent(i);
            if (component.isVisible())
                return component;
        }
        return null;
    }

    @Override
    public void first(Container parent) {
        stopSwipeIfNeed();
        super.first(parent);
    }

    @Override
    public void next(Container parent) {
        stopSwipeIfNeed();
        super.next(parent);
    }

    @Override
    public void previous(Container parent) {
        stopSwipeIfNeed();
        super.previous(parent);
    }

    @Override
    public void last(Container parent) {
        stopSwipeIfNeed();
        super.last(parent);
    }

    @Override
    public void show(Container parent, String name) {
        stopSwipeIfNeed();
        super.show(parent, name);
    }

    public static void main(String[] args) throws IOException {
        final JBCardLayout cardLayout = new JBCardLayout();

        JFrame f = new JFrame();
        JPanel p = new JPanel(new BorderLayout());
        final JPanel centerPanel = new JPanel(cardLayout);
        for (int i = 0; i < 10; i++) {
            JLabel l = new JLabel("Page #" + (i + 1), SwingConstants.CENTER);
            l.setOpaque(true);
            int red = 50 + (int) (Math.random() * 100);
            int green = 50 + (int) (Math.random() * 100);
            int blue = 50 + (int) (Math.random() * 100);
            l.setForeground(new Color(red, green, blue));
            red = 255 - (int) (Math.random() * 55);
            green = 255 - (int) (Math.random() * 55);
            blue = 255 - (int) (Math.random() * 55);
            l.setBackground(new Color(red, green, blue));
            l.setFont(l.getFont().deriveFont(40F));
            centerPanel.add(l, "page" + i);
        }
        final int[] cursor = new int[1];
        JButton prevButton = new JButton("<<");
        JButton nextButton = new JButton(">>");
        prevButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                cursor[0]--;
                if (cursor[0] < 0) {
                    cursor[0] = 9;
                }
                cardLayout.swipe(centerPanel, "page" + cursor[0], SwipeDirection.BACKWARD);
            }
        });
        nextButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                cursor[0] = (cursor[0] + 1) % 10;
                cardLayout.swipe(centerPanel, "page" + cursor[0], SwipeDirection.FORWARD);
            }
        });

        p.setLayout(new BorderLayout());
        p.add(prevButton, BorderLayout.WEST);
        p.add(centerPanel, BorderLayout.CENTER);
        p.add(nextButton, BorderLayout.EAST);
        f.setContentPane(p);
        f.setSize(new Dimension(600, 800));
        f.setLocationRelativeTo(null);
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        f.setVisible(true);
    }

    public Component findComponentById(String id) {
        return myMap.get(id);
    }
}