All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.jaxx.widgets.extra.SimpleInternalFrame Maven / Gradle / Ivy

Go to download

Widgets graphiques utiles pour tous les développements (pour le moment sans lien avec JAXX).

There is a newer version: 3.0-alpha-17
Show newest version
/*
 * #%L
 * JAXX :: Extra Widgets
 * %%
 * Copyright (C) 2004 - 2017 CodeLutin
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as 
 * published by the Free Software Foundation, either version 3 of the 
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public 
 * License along with this program.  If not, see
 * .
 * #L%
 */
/*
 * Copyright (c) 2003 JGoodies Karsten Lentzsch. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 * 
 *  o Redistributions of source code must retain the above copyright notice, 
 *    this list of conditions and the following disclaimer. 
 *     
 *  o Redistributions in binary form must reproduce the above copyright notice, 
 *    this list of conditions and the following disclaimer in the documentation 
 *    and/or other materials provided with the distribution. 
 *     
 *  o Neither the name of JGoodies Karsten Lentzsch nor the names of 
 *    its contributors may be used to endorse or promote products derived 
 *    from this software without specific prior written permission. 
 *     
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

package org.nuiton.jaxx.widgets.extra;

import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.AbstractBorder;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Paint;

/**
 * A JPanel subclass that has a drop shadow border and that provides a header
 * with icon, title and tool bar.
 * This class can be used to replace the JInternalFrame,
 * for use outside of a JDesktopPane.
 * The SimpleInternalFrame is less flexible but often more usable; it avoids
 * overlapping windows and scales well up to IDE size.
 * Several customers have reported that they and their clients feel much better with both the
 * appearance and the UI feel.
 * The SimpleInternalFrame provides the following bound properties: frameIcon, title, toolBar, content, selected.
 * By default the SimpleInternalFrame is in selected state. If you don't do anything, multiple simple internal frames
 * will be displayed as selected.
 *
 * @author Karsten Lentzsch
 * @see javax.swing.JInternalFrame
 * @see javax.swing.JDesktopPane
 */

public class SimpleInternalFrame extends JPanel {

    private static final long serialVersionUID = 1L;

    private JLabel titleLabel = null;
    private GradientPanel gradientPanel = null;
    private JPanel headerPanel = null;
    private boolean isSelected;

    // Instance Creation ****************************************************

    public SimpleInternalFrame() {
        this(null, null, null, null);
    }

    /**
     * Constructs a SimpleInternalFrame with the specified title.
     *
     * @param title the initial title
     */
    public SimpleInternalFrame(String title) {
        this(null, title, null, null);
    }

    /**
     * Constructs a SimpleInternalFrame with the specified icon, and title.
     *
     * @param icon  the initial icon
     * @param title the initial title
     */
    public SimpleInternalFrame(Icon icon, String title) {
        this(icon, title, null, null);
    }

    /**
     * Constructs a SimpleInternalFrame with the specified title, tool bar, and
     * content panel.
     *
     * @param title   the initial title
     * @param bar     the initial tool bar
     * @param content the initial content pane
     */
    public SimpleInternalFrame(String title, JToolBar bar, JComponent content) {
        this(null, title, bar, content);
    }

    /**
     * Constructs a SimpleInternalFrame with the specified icon, title, tool
     * bar, and content panel.
     *
     * @param icon    the initial icon
     * @param title   the initial title
     * @param bar     the initial tool bar
     * @param content the initial content pane
     */
    public SimpleInternalFrame(Icon icon, String title, JToolBar bar,
                               JComponent content) {
        super(new BorderLayout());
        this.isSelected = false;
        this.titleLabel = new JLabel(title, icon, SwingConstants.LEADING);
        JPanel top = buildHeader(titleLabel, bar);
        if (title != null) {
            add(top, BorderLayout.NORTH);
        } else {
            // TODO add(new org.jext.gui.VoidComponent(), BorderLayout.NORTH);
        }
        if (content != null) {
            setContent(content);
        }
        setBorder(new ShadowBorder());
        setSelected(true);
        updateHeader();
    }

    // Public API ***********************************************************

    /**
     * Returns the frame's icon.
     *
     * @return the frame's icon
     */
    public Icon getFrameIcon() {
        return titleLabel.getIcon();
    }

    /**
     * Sets a new frame icon.
     *
     * @param newIcon the icon to be set
     */
    public void setFrameIcon(Icon newIcon) {
        Icon oldIcon = getFrameIcon();
        titleLabel.setIcon(newIcon);
        firePropertyChange("frameIcon", oldIcon, newIcon);
    }

    /**
     * Returns the frame's title text.
     *
     * @return String the current title text
     */
    public String getTitle() {
        return titleLabel.getText();
    }

    /**
     * Sets a new title text.
     *
     * @param newText the title text tp be set
     */
    public void setTitle(String newText) {
        String oldText = getTitle();
        titleLabel.setText(newText);
        firePropertyChange("title", oldText, newText);
    }

    /**
     * Returns the current toolbar, null if none has been set before.
     *
     * @return the current toolbar - if any
     */
    public JToolBar getToolBar() {
        return headerPanel.getComponentCount() > 1 ? (JToolBar) headerPanel
                .getComponent(1) : null;
    }

    /**
     * Sets a new tool bar in the header.
     *
     * @param newToolBar the tool bar to be set in the header
     */
    public void setToolBar(JToolBar newToolBar) {
        JToolBar oldToolBar = getToolBar();
        if (oldToolBar == newToolBar) {
            return;
        }
        if (oldToolBar != null) {
            headerPanel.remove(oldToolBar);
        }
        if (newToolBar != null) {
            newToolBar.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
            headerPanel.add(newToolBar, BorderLayout.EAST);
        }
        updateHeader();
        firePropertyChange("toolBar", oldToolBar, newToolBar);
    }

    /**
     * Returns the content - null, if none has been set.
     *
     * @return the current content
     */
    public Component getContent() {
        return hasContent() ? getComponent(1) : null;
    }

    /**
     * Sets a new panel content; replaces any existing content, if existing.
     *
     * @param newContent the panel's new content
     */
    public void setContent(Component newContent) {
        Component oldContent = getContent();
        if (hasContent()) {
            remove(oldContent);
        }
        add(newContent, BorderLayout.CENTER);
        firePropertyChange("content", oldContent, newContent);
    }

    /**
     * Answers if the panel is currently selected (or in other words active) or
     * not. In the selected state, the header background will be rendered
     * differently.
     *
     * @return boolean a boolean, where true means the frame is selected
     * (currently active) and false means it is not
     */
    public boolean isSelected() {
        return isSelected;
    }

    /**
     * This panel draws its title bar differently if it is selected, which may
     * be used to indicate to the user that this panel has the focus, or should
     * get more attention than other simple internal frames.
     *
     * @param newValue a boolean, where true means the frame is selected
     *                 (currently active) and false means it is not
     */
    public void setSelected(boolean newValue) {
        boolean oldValue = isSelected();
        isSelected = newValue;
        updateHeader();
        firePropertyChange("selected", oldValue, newValue);
    }

    /*
     * public void paintComponent(Graphics g) { super.paintComponent(g); if
     * (!isOpaque()) { return; } Color control = UIManager.getColor("control");
     * int width = getWidth(); int height = getHeight();
     * 
     * Graphics2D g2 = (Graphics2D) g;
     * 
     * Paint storedPaint = g2.getPaint(); g2.setPaint(new GradientPaint(0, 0,
     * Color.white, width, height, control)); g2.fillRect(0, 0, width, height);
     * g2.setPaint(storedPaint); }
     */
    // Building *************************************************************

    /**
     * Creates and answers the header panel, that consists of: an icon, a title
     * label, a tool bar, and a gradient background.
     *
     * @param label the label to paint the icon and text
     * @param bar   the panel's tool bar
     * @return the panel's built header area
     */
    private JPanel buildHeader(JLabel label, JToolBar bar) {
        gradientPanel = new GradientPanel(new BorderLayout(),
                                          getHeaderBackground());
        label.setOpaque(false);

        gradientPanel.add(label, BorderLayout.WEST);
        gradientPanel.setBorder(BorderFactory.createEmptyBorder(3, 4, 3, 1));

        headerPanel = new JPanel(new BorderLayout());
        headerPanel.add(gradientPanel, BorderLayout.CENTER);
        setToolBar(bar);
        headerPanel.setBorder(new RaisedHeaderBorder());
        headerPanel.setOpaque(false);
        return headerPanel;
    }

    /**
     * Updates the header.
     */
    private void updateHeader() {
        if (gradientPanel == null) {
            return;
        }
        gradientPanel.setBackground(getHeaderBackground());
        gradientPanel.setOpaque(isSelected());
        titleLabel.setForeground(getTextForeground(isSelected()));
        headerPanel.repaint();
    }

    /**
     * Updates the UI. In addition to the superclass behavior, we need to update
     * the header component.
     */
    @Override
    public void updateUI() {
        super.updateUI();
        if (titleLabel != null) {
            updateHeader();
        }
    }

    // Helper Code **********************************************************

    /**
     * Checks and answers if the panel has a content component set.
     *
     * @return true if the panel has a content, false if it's empty
     */
    private boolean hasContent() {
        return getComponentCount() > 1;
    }

    /**
     * Determines and answers the header's text foreground color. Tries to
     * lookup a special color from the L&F. In case it is absent, it uses the
     * standard internal frame forground.
     *
     * @param selected true to lookup the active color, false for the inactive
     * @return the color of the foreground text
     */
    protected Color getTextForeground(boolean selected) {
        // if (selected) return Color.BLUE;
        Color c = UIManager
                .getColor(selected ? "SimpleInternalFrame.activeTitleForeground"
                                  : "SimpleInternalFrame.inactiveTitleForeground");
        if (c != null) {
            return c;
        }
        return UIManager
                .getColor(selected ? "InternalFrame.activeTitleForeground"
                                  : "Label.foreground");

    }

    /**
     * Determines and answers the header's background color. Tries to lookup a
     * special color from the L&F. In case it is absent, it uses the standard
     * internal frame background.
     *
     * @return the color of the header's background
     */
    protected Color getHeaderBackground() {
        Color c = UIManager
                .getColor("SimpleInternalFrame.activeTitleBackground");
        if (c != null) {
            return c;
        }
        // if (LookUtils.IS_LAF_WINDOWS_XP_ENABLED)
        c = UIManager.getColor("InternalFrame.activeTitleGradient");
        return c != null ? c : UIManager
                .getColor("InternalFrame.activeTitleBackground");
    }

    // Helper Classes *******************************************************

    // A custom border for the raised header pseudo 3D effect.
    private static class RaisedHeaderBorder extends AbstractBorder {

        private static final long serialVersionUID = 1L;

        private static final Insets INSETS = new Insets(1, 1, 1, 0);

        @Override
        public Insets getBorderInsets(Component c) {
            return INSETS;
        }

        @Override
        public void paintBorder(Component c, Graphics g, int x, int y, int w,
                                int h) {

            g.translate(x, y);
            g.setColor(UIManager.getColor("controlLtHighlight"));
            g.fillRect(0, 0, w, 1);
            g.fillRect(0, 1, 1, h - 1);
            g.setColor(UIManager.getColor("controlShadow"));
            g.fillRect(0, h - 1, w, 1);
            g.translate(-x, -y);
        }
    }

    // A custom border that has a shadow on the right and lower sides.
    private static class ShadowBorder extends AbstractBorder {

        private static final long serialVersionUID = 1L;

        private static final Insets INSETS = new Insets(1, 1, 3, 3);

        @Override
        public Insets getBorderInsets(Component c) {
            return INSETS;
        }

        @Override
        public void paintBorder(Component c, Graphics g, int x, int y, int w,
                                int h) {

            Color shadow = UIManager.getColor("controlShadow");
            if (shadow == null) {
                shadow = Color.GRAY;
            }
            Color lightShadow = new Color(shadow.getRed(), shadow.getGreen(),
                                          shadow.getBlue(), 170);
            Color lighterShadow = new Color(shadow.getRed(), shadow.getGreen(),
                                            shadow.getBlue(), 70);
            g.translate(x, y);

            g.setColor(shadow);
            g.fillRect(0, 0, w - 3, 1);
            g.fillRect(0, 0, 1, h - 3);
            g.fillRect(w - 3, 1, 1, h - 3);
            g.fillRect(1, h - 3, w - 3, 1);
            // Shadow line 1
            g.setColor(lightShadow);
            g.fillRect(w - 3, 0, 1, 1);
            g.fillRect(0, h - 3, 1, 1);
            g.fillRect(w - 2, 1, 1, h - 3);
            g.fillRect(1, h - 2, w - 3, 1);
            // Shadow line2
            g.setColor(lighterShadow);
            g.fillRect(w - 2, 0, 1, 1);
            g.fillRect(0, h - 2, 1, 1);
            g.fillRect(w - 2, h - 2, 1, 1);
            g.fillRect(w - 1, 1, 1, h - 2);
            g.fillRect(1, h - 1, w - 2, 1);
            g.translate(-x, -y);
        }
    }

    // A panel with a horizontal gradient background.
    private static class GradientPanel extends JPanel {

        private static final long serialVersionUID = 1L;

        private GradientPanel(LayoutManager lm, Color background) {
            super(lm);
            setBackground(background);
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (!isOpaque()) {
                return;
            }
            Color control = UIManager.getColor("control");
            int width = getWidth();
            int height = getHeight();

            Graphics2D g2 = (Graphics2D) g;
            Paint storedPaint = g2.getPaint();
            g2.setPaint(new GradientPaint(0, 0, getBackground(), width, 0,
                                          control));
            g2.fillRect(0, 0, width, height);
            g2.setPaint(storedPaint);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy