// BlogBridge -- RSS feed reader, manager, and web based service
// Copyright (C) 2002-2006 by R. Pito Salas
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software Foundation;
// either version 2 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 Public License for more details.
//
// You should have received a copy of the GNU General Public License along with this program;
// if not, write to the Free Software Foundation, Inc., 59 Temple Place,
// Suite 330, Boston, MA 02111-1307 USA
//
// Contact: R. Pito Salas
// mailto:pitosalas@users.sourceforge.net
// More information: about BlogBridge
// http://www.blogbridge.com
// http://sourceforge.net/projects/blogbridge
//
// $Id: CoolInternalFrame.java,v 1.25 2006/01/08 05:07:31 kyank Exp $
//
package com.salas.bb.utils.uif;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.uif.util.SystemUtils;
import javax.swing.*;
import java.awt.*;
/**
* A header and a body in a nice shaded frame.
*
* The body is any component.
* The header is constructed from a title, subtitle and header control component, which are
* laid out in two rows. The Title is in the top left of the header, and has a bigger font. The
* control component is in the top right. And the subtitle spans the whole bottom of the header,
* in a smaller font.
*/
public class CoolInternalFrame extends JPanel
{
private static final int TITLE_FONT_SIZE = 12;
private static final int TITLE_FONT_STYLE = Font.BOLD;
private static final String TITLE_FONT_FACE_MAC = "Franklin Gothic Medium";
private static final String TITLE_FONT_FACE = "Sans Serif";
private static final Color COLOR_BORDER = Color.decode("#797979");
private static final Color COLOR_GRADIENT_TOP = Color.decode("#0c98c2");
private static final Color COLOR_GRADIENT_BOTTOM = Color.decode("#086091");
private static final Color COLOR_TITLE_SHADOW = Color.decode("#000040");
private ShadowLabel titleLabel;
private JLabel subtitleLabel;
private JPanel headerPanel;
private JComponent headerCtrlComp;
private boolean isSelected;
// Instance Creation ****************************************************
/**
* Constructs a <code>CoolInternalPane</code> with the specified title.
*
* @param title the initial title
*/
public CoolInternalFrame(String title)
{
this(title, null, null, null);
}
/**
* Constructs a <code>CoolInternalPane</code> with the specified title, tool bar, and content
* panel.
*
* @param title initial title.
* @param subtitle initial subtitle.
* @param hdrControls initial header controls component.
* @param content initial content pane.
*/
public CoolInternalFrame(String title, String subtitle, JComponent hdrControls,
JComponent content)
{
this(null, title, subtitle, hdrControls, content);
}
/**
* Constructs a <code>CoolInternalPane</code> with the specified parameters.
*
* @param icon initial icon.
* @param title initial title.
* @param subtitle initial subtitle.
* @param hdrControls initial header controls component.
* @param content initial content pane.
*/
public CoolInternalFrame(Icon icon, String title, String subtitle, JComponent hdrControls,
JComponent content)
{
super(new BorderLayout());
isSelected = false;
// Build the labels
titleLabel = new ShadowLabel(title, icon, SwingConstants.LEADING, COLOR_TITLE_SHADOW);
subtitleLabel = new JLabel(subtitle);
setupLabels();
// Build the header and add it to the whole frame
headerCtrlComp = hdrControls;
JPanel header = buildHeader();
add(header, BorderLayout.NORTH);
// If there is a content Component, then add it
if (content != null) setContent(content);
// Final steps
setBorder(BorderFactory.createLineBorder(COLOR_BORDER));
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 to be set.
*/
public void setTitle(String newText)
{
String oldText = getTitle();
titleLabel.setText(newText);
firePropertyChange("title", oldText, newText);
}
/**
* Sets the subtitle text.
*
* @param newText title text to be set.
*/
public void setSubtitle(String newText)
{
String oldText = getSubTitle();
subtitleLabel.setText(newText);
firePropertyChange("title", oldText, newText);
}
/**
* Returns subtitle text.
*
* @return text.
*/
private String getSubTitle()
{
return subtitleLabel.getText();
}
/**
* Returns the current header controls component, null if none has been set before.
*
* @return the current header control component (if any).
*/
public JComponent getHeaderCtrlComp()
{
return headerCtrlComp;
}
/**
* Sets a new header control component.
*
* @param newhdrContrlComp the header control component to be set in the header.
*/
public void setHeaderControl(JComponent newhdrContrlComp)
{
JComponent oldhdrContrlComp = getHeaderCtrlComp();
if (oldhdrContrlComp == newhdrContrlComp) return;
if (oldhdrContrlComp != null)
{
headerPanel.remove(oldhdrContrlComp);
}
if (newhdrContrlComp != null)
{
newhdrContrlComp.setBorder(null);
CellConstraints cc = new CellConstraints();
headerPanel.add(newhdrContrlComp, cc.xywh(5, 2, 1, 3, "r, c"));
}
headerCtrlComp = newhdrContrlComp;
updateHeader();
firePropertyChange("toolBar", oldhdrContrlComp, newhdrContrlComp);
}
/**
* Returns the content or 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);
}
// Building *************************************************************
/**
* Creates the appropriately laied out Header for the CoolInternalFrame.
*
* @return the header.
*/
private JPanel buildHeader()
{
FormLayout layout = new FormLayout(
"11px, pref, min:grow, 2px, pref, 11px",
"6px, pref, 1px, pref, 8px");
headerPanel = new GradientPanel(layout);
CellConstraints cc = new CellConstraints();
headerPanel.add(titleLabel, cc.xy(2, 2));
headerPanel.add(subtitleLabel, cc.xyw(2, 4, 3));
if (headerCtrlComp != null) headerPanel.add(headerCtrlComp, cc.xywh(5, 2, 1, 3, "r, c"));
headerPanel.setOpaque(SystemUtils.IS_OS_MAC);
return headerPanel;
}
/**
* Set up the desired forns and opacities for the two labels.
*/
private void setupLabels()
{
titleLabel.setOpaque(false);
titleLabel.setFont(new Font(TITLE_FONT_FACE, TITLE_FONT_STYLE, TITLE_FONT_SIZE));
subtitleLabel.setOpaque(false);
subtitleLabel.setFont(subtitleLabel.getFont().deriveFont(9.0f));
}
/**
* Updates the header.
*/
private void updateHeader()
{
headerPanel.setOpaque(isSelected());
titleLabel.setForeground(getTextForeground(isSelected()));
subtitleLabel.setForeground(getSubTitleForeground(isSelected()));
if (headerCtrlComp != null)
{
headerCtrlComp.setOpaque(false);
headerCtrlComp.setBackground(Color.RED);
}
headerPanel.repaint();
}
/**
* Returns sub-title foreground color.
*
* @param selected if the sub-title is selected.
*
* @return color.
*/
protected Color getSubTitleForeground(boolean selected)
{
return getTextForeground(selected);
}
/**
* Updates the UI. In addition to the superclass behavior, we need to update the header
* component.
*/
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)
{
return Color.WHITE;
}
/**
* A panel with a horizontal gradient background.
*/
private static final class GradientPanel extends JPanel
{
/**
* Creates panel.
*
* @param lm layout manager.
*/
private GradientPanel(LayoutManager lm)
{
super(lm);
}
/**
* Paints component on a given graphics context.
*
* @param g graphics context.
*/
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if (isOpaque())
{
Color color1 = COLOR_GRADIENT_TOP;
Color color2 = COLOR_GRADIENT_BOTTOM;
int width = getWidth();
int height = getHeight();
Graphics2D g2 = (Graphics2D)g;
Paint storedPaint = g2.getPaint();
g2.setPaint(new GradientPaint(0, 0, color1, 0, height, color2));
g2.fillRect(0, 0, width, height);
g2.setPaint(storedPaint);
Color lighter = COLOR_GRADIENT_TOP;
g2.setColor(lighter);
g2.drawLine(0, height - 2, width, height - 2);
}
}
}
}