// 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: ComponentsFactory.java,v 1.12 2008/06/26 13:41:58 spyromus Exp $ // package com.salas.bb.utils.uif; import com.jgoodies.binding.adapter.ToggleButtonAdapter; import com.jgoodies.binding.beans.PropertyAdapter; import com.jgoodies.binding.value.BufferedValueModel; import com.jgoodies.binding.value.ValueModel; import com.jgoodies.uif.util.ResourceUtils; import com.jgoodies.uifextras.util.UIFactory; import javax.swing.*; import java.awt.*; import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; /** * Factory of components. */ public final class ComponentsFactory { /** * Hidden utility class constructor. */ private ComponentsFactory() { } /** * Creates a scrollable instructions text box wrapped with scroll pane. * * @param text text. * * @return component. */ public static JComponent createInstructionsBox(String text) { JTextArea instructions = createInstructionsArea(text); return new JScrollPane(instructions); } /** * Creates an instructions area. * * @param text text to initialize area with. * * @return area. */ public static JTextArea createInstructionsArea(String text) { JTextArea instructions = new JTextArea(text); instructions.setWrapStyleWord(true); instructions.setLineWrap(true); instructions.setTabSize(4); Color background = instructions.getBackground(); instructions.setEditable(false); instructions.setBackground(background); UifUtilities.smallerFont(instructions); instructions.setMargin(new Insets(10, 10, 10, 10)); return instructions; } /** * Creates radio-button with mnemonized text. * * @param textWithMnemonic text with mnemonic mark. * * @return created radio-button. */ public static JRadioButton createRadioButton(String textWithMnemonic) { return createRadioButton(textWithMnemonic, null); } /** * Creates radio-button with mnemonized text. * * @param textWithMnemonic text with mnemonic mark. * @param model model to use for radio-button. * * @return created radio-button. */ public static JRadioButton createRadioButton(String textWithMnemonic, ButtonModel model) { JRadioButton button = new JRadioButton(); if (model != null) button.setModel(model); setTextAndMnemonic(button, textWithMnemonic); return button; } /** * Creates check-box with mnemonized text. * * @param textWithMnemonic text with mnemonic mark. * * @return created check-box. */ public static JCheckBox createCheckBox(String textWithMnemonic) { return createCheckBox(textWithMnemonic, null); } /** * Creates check-box with mnemonized text. * * @param textWithMnemonic text with mnemonic mark. * @param model model of check box. * * @return created check-box. */ public static JCheckBox createCheckBox(String textWithMnemonic, ButtonModel model) { JCheckBox checkBox = new JCheckBox(); if (model != null) checkBox.setModel(model); setTextAndMnemonic(checkBox, textWithMnemonic); return checkBox; } /** * Creates check-box with mnemonized text. * * @param textWithMnemonic text with mnemonic mark. * @param bean bean to bind this check box to. * @param propertyName name of the bean property. * @param trigger channel to trigger the commit operation. * * @return created check-box. */ public static JCheckBox createCheckBox(String textWithMnemonic, Object bean, String propertyName, ValueModel trigger) { return createCheckBox(textWithMnemonic, new ToggleButtonAdapter( new BufferedValueModel(new PropertyAdapter(bean, propertyName), trigger))); } /** * Creates button with mnemonized text. * * @param textWithMnemonic text with mnemonic mark. * * @return created button. */ public static JButton createButton(String textWithMnemonic) { JButton button = new JButton(); setTextAndMnemonic(button, textWithMnemonic); return button; } /** * Creates label with mnemonized text. * * @param textWithMnemonic text with mnemonic mark. * * @return created label. */ public static JLabel createLabel(String textWithMnemonic) { MnemonicHolder holder = findMnemonic(textWithMnemonic); JLabel label = new JLabel(holder.text); if (holder.mnemonicIndex != -1) { label.setDisplayedMnemonic(holder.mnemonicChar); label.setDisplayedMnemonicIndex(holder.mnemonicIndex); } return label; } /** * Sets the mnemonic to existing button. * * @param button button. * @param textWithMenmonic text with mnemonic. * * @return button. */ public static AbstractButton setTextAndMnemonic(AbstractButton button, String textWithMenmonic) { setTextAndMnemonic(button, findMnemonic(textWithMenmonic)); return button; } /** * Creates wrapped multi-line label with font and cursor similar to other labels. * * @param text text to initialize with. * * @return label. */ public static JTextArea createWrappedMultilineLabel(String text) { final JTextArea mlLabel = UIFactory.createWrappedMultilineLabel(text); final JLabel label = new JLabel(); mlLabel.setFont(label.getFont()); mlLabel.setCursor(label.getCursor()); return mlLabel; } /** * Sets text and mnemonic to button. * * @param button button. * @param holder holder of mnemonic information. */ private static void setTextAndMnemonic(AbstractButton button, MnemonicHolder holder) { button.setText(holder.text); if (holder.mnemonicIndex != -1) { button.setMnemonic(holder.mnemonicChar); button.setDisplayedMnemonicIndex(holder.mnemonicIndex); } } /** * Finds mnemonic mark in text, records it and removes. * * @param textWithMnemonic text with mnemonic mark. * * @return results of search (text without mark and marked char). */ private static MnemonicHolder findMnemonic(String textWithMnemonic) { MnemonicHolder holder = new MnemonicHolder(); holder.text = textWithMnemonic; holder.mnemonicChar = (char)0; holder.mnemonicIndex = -1; if (textWithMnemonic != null) { int index = textWithMnemonic.indexOf('&'); if (index != -1) { holder.mnemonicIndex = index; holder.mnemonicChar = textWithMnemonic.charAt(index + 1); int len = textWithMnemonic.length(); StringBuffer sb = new StringBuffer(len - 1); sb.append(textWithMnemonic.substring(0, index)); sb.append(textWithMnemonic.substring(index + 1, len)); holder.text = sb.toString(); } } return holder; } /** * Creates separator with collapsable icon to the left from label and connects it to * the given component. The clicking on icon controls visibility of the component. * * @param textWithMnemonic text with mnemonic mark. * @param comp component visibility of which to control. * * @return separator read for the form. */ public static JComponent createCollapsibleSeparator(String textWithMnemonic, final JComponent comp) { MnemonicHolder holder = findMnemonic(textWithMnemonic); CollapseControlLabel label = new CollapseControlLabel(holder.text); if (holder.mnemonicIndex != -1) { label.setDisplayedMnemonic(holder.mnemonicChar); label.setDisplayedMnemonicIndex(holder.mnemonicIndex); } if (comp != null) { comp.setVisible(!label.isCollapsed()); label.addPropertyChangeListener("collapsed", new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { boolean collapsed = (Boolean)evt.getNewValue(); comp.setVisible(!collapsed); } }); } return label; } /** * Holder for de-mnemonized text and mnemonic index. */ private static class MnemonicHolder { private String text; private char mnemonicChar; private int mnemonicIndex; } /** * Special label with small collapsing icon to the left from label. * When the collapsing state changes it fires "collapsed" property change event. */ private static class CollapseControlLabel extends JLabel { private static final Icon ICON_COL_OUT = ResourceUtils.getIcon("ccl.col.out"); private static final Icon ICON_COL_OVR = ResourceUtils.getIcon("ccl.col.ovr"); private static final Icon ICON_EXP_OUT = ResourceUtils.getIcon("ccl.exp.out"); private static final Icon ICON_EXP_OVR = ResourceUtils.getIcon("ccl.exp.ovr"); private static final boolean DEFAULT_COLLAPSED = true; private boolean collapsed; private boolean over; public CollapseControlLabel(String text) { this(text, DEFAULT_COLLAPSED); } public CollapseControlLabel(String text, boolean aCollapsed) { super(text); setCollapsed(aCollapsed); enableEvents(AWTEvent.MOUSE_EVENT_MASK); } public void setCollapsed(boolean aCollapsed) { if (collapsed != aCollapsed) { collapsed = aCollapsed; updateCollapseIcon(); firePropertyChange("collapsed", !collapsed, collapsed); } } public boolean isCollapsed() { return collapsed; } private void updateCollapseIcon() { Icon icon; if (collapsed) { icon = over ? ICON_COL_OVR : ICON_COL_OUT; } else { icon = over ? ICON_EXP_OVR : ICON_EXP_OUT; } setIcon(icon); } protected void processEvent(AWTEvent e) { int id = e.getID(); switch (id) { case MouseEvent.MOUSE_ENTERED: over = true; updateCollapseIcon(); break; case MouseEvent.MOUSE_EXITED: over = false; updateCollapseIcon(); break; case MouseEvent.MOUSE_CLICKED: setCollapsed(!collapsed); break; default: super.processEvent(e); break; } } } }