org.nuiton.jaxx.widgets.extra.SimpleInternalFrame Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jaxx-widgets-extra Show documentation
Show all versions of jaxx-widgets-extra Show documentation
Widgets graphiques utiles pour tous les développements (pour le moment sans lien avec JAXX).
/*
* #%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);
}
}
}