/*
* Rapid Beans Framework: DocumentTreeCellRenderer.java
*
* Copyright (C) 2009 Martin Bluemel
*
* Creation Date: 02/11/2006
*
* 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 Lesser General Public License for more details.
* You should have received a copies of the GNU Lesser General Public License and the
* GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
package org.rapidbeans.presentation.swing;
import java.awt.Component;
import java.util.List;
import java.util.MissingResourceException;
import javax.swing.ImageIcon;
import javax.swing.JTree;
import javax.swing.tree.DefaultTreeCellRenderer;
import org.rapidbeans.core.basic.RapidBean;
import org.rapidbeans.core.common.RapidBeansLocale;
import org.rapidbeans.core.exception.RapidBeansRuntimeException;
import org.rapidbeans.core.type.TypePropertyCollection;
import org.rapidbeans.core.type.TypeRapidBean;
import org.rapidbeans.core.util.StringHelper;
import org.rapidbeans.datasource.Document;
import org.rapidbeans.presentation.Application;
import org.rapidbeans.presentation.ApplicationManager;
/**
* cell renderer for the Swing implementation for a tree view for a bean
* document.
*
* @author Martin Bluemel
*/
public final class DocumentTreeCellRenderer extends DefaultTreeCellRenderer {
/**
* serial version UID.
*/
private static final long serialVersionUID = 1L;
/**
* the bean document presented as tree.
*/
private Document document = null;
/**
* the locale.
*/
private RapidBeansLocale locale;
/**
* constructor.
*
* @param doc
* the document
* @param loc
* the locale
*/
public DocumentTreeCellRenderer(final Document doc, final RapidBeansLocale loc) {
this.document = doc;
this.locale = loc;
if (this.locale == null) {
throw new RapidBeansRuntimeException("no locale specified");
}
}
/**
* Sets the value of the current tree cell to value. If selected is true,
* the cell will be drawn as if selected. If expanded is true the node is
* currently expanded and if leaf is true the node represets a leaf and if
* hasFocus is true the node currently has focus. tree is the JTree the
* receiver is being configured for. Returns the Component that the renderer
* uses to draw the value.
*
* @param tree
* the tree
* @param value
* the bean or Collection Property to render
* @param isSelected
* if the tree node is selected
* @param expanded
* if the tree node is expanded
* @param leaf
* if the tree node is a leaf
* @param row
* the row
* @param hasGotFocus
* if the tree node has the focus
*
* @return the tree cell renderer component
*/
public Component getTreeCellRendererComponent(final JTree tree, final Object value, final boolean isSelected,
final boolean expanded, final boolean leaf, final int row, final boolean hasGotFocus) {
String text = null;
ImageIcon icon = null;
DocumentTreeCellRenderer comp = (DocumentTreeCellRenderer) super.getTreeCellRendererComponent(tree, value,
isSelected, expanded, leaf, row, hasGotFocus);
if (value instanceof RapidBean) {
text = findText((RapidBean) value);
icon = findIcon((RapidBean) value, false);
} else if (value instanceof DocumentTreeNodeBeanLink) {
text = findText(((DocumentTreeNodeBeanLink) value).getLinkedBean());
icon = findIcon(((DocumentTreeNodeBeanLink) value).getLinkedBean(), true);
} else if (value instanceof DocumentTreeNodePropCol) {
text = findText((DocumentTreeNodePropCol) value);
icon = findIcon((DocumentTreeNodePropCol) value);
}
comp.setText(text);
comp.setIcon(icon);
return comp;
}
/**
* Finds a GUI text for a bean in a tree view.
*
* @param bean
* the bean for which we need a text
*
* @return the found text or null if none found
*/
private String findText(final RapidBean bean) {
String text = null;
// 1) take resource definition: treeview.beanlabel.<path>
// e. g.
// treeview.beanlabel.masterdata.clubs.trainingdates.trainerplannings
try {
if (bean.getContainer() != null && bean.getContainer() instanceof Document) {
final String path = ((Document) bean.getContainer()).getPath(bean, '.');
final String pattern = "treeview.beanlabel." + path;
final String s = this.locale.getStringGui(pattern);
text = bean.expandPropertyValues(s, this.locale);
}
} catch (MissingResourceException e) {
text = null;
}
// 1b) take resource definition:
// treeview.beanlabel.<documentprefix>*.<path>
// e. g.
// treeview.beanlabel.masterdata.clubs.trainingdates.trainerplannings
if (text == null) {
try {
if (bean.getContainer() != null && bean.getContainer() instanceof Document) {
final List<String> sa = StringHelper.split(
"treeview.beanlabel." + ((Document) bean.getContainer()).getPath(bean, '.'), ".");
if (sa.size() > 3) {
final String docname = sa.get(2);
final int docnamepos = docname.indexOf('_');
if (docnamepos != -1) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < sa.size(); i++) {
if (i > 0) {
sb.append('.');
}
if (i == 2) {
sb.append(docname.substring(0, docnamepos + 1));
sb.append('*');
} else {
sb.append(sa.get(i));
}
}
final String pattern = sb.toString();
text = bean.expandPropertyValues(this.locale.getStringGui(pattern), this.locale);
}
}
}
} catch (MissingResourceException e) {
text = null;
}
}
// 2) default: take the internationalized stringified identity
if (text == null) {
text = bean.toStringGuiId(this.locale);
}
return text;
}
/**
* Finds a GUI text for a collection property node in a tree view.
*
* @param colNode
* the bean for which we need a text
*
* @return the found text or null if none found
*/
private String findText(final DocumentTreeNodePropCol colNode) {
String text = null;
// daisy chain of tries to find an appropriate text for
// compositions collection (or container) properties
// try tree view resource string specifically defined for this kind of
// document
// "document.<document config name>.treeview.<property name>.label"
try {
text = this.locale.getStringGui("document." + this.document.getConfigNameOrName() + ".treeview."
+ colNode.getColProp().getType().getPropName() + ".label");
} catch (MissingResourceException e) {
text = null;
}
// try resource string defined for this property
// "bean.<lowercased typename>.prop.<property name>.label"
// defined for the bean type or one of it's parent types
if (text == null) {
TypeRapidBean type = colNode.getColProp().getBean().getType();
while (text == null && type != null) {
try {
final String key = "bean." + type.getName().toLowerCase() + ".prop."
+ colNode.getColProp().getType().getPropName();
text = this.locale.getStringGui(key);
} catch (MissingResourceException e) {
text = null;
type = type.getSupertype();
}
}
}
// in case of an association property
// try resource string defined for the
// target type or one of it's parent types
// "bean.<lowercased target typename>(.plural)" or
// "bean.<lowercased target typename>" in case of maxmult == 1
if (text == null && colNode.getColProp().getType() instanceof TypePropertyCollection) {
final TypePropertyCollection colPropType = (TypePropertyCollection) colNode.getColProp().getType();
TypeRapidBean type = colPropType.getTargetType();
while (text == null && type != null) {
try {
text = type.toStringGui(this.locale, (colPropType.getMaxmult() != 1), colPropType.getPropName());
String key = "bean." + type.getName().toLowerCase();
if (colPropType.getMaxmult() != 1) {
key += ".plural";
}
text = locale.getStringGui(key);
} catch (MissingResourceException e) {
if (colPropType.getMaxmult() != 1) {
try {
final String key1 = "bean." + type.getName().toLowerCase();
text = locale.getStringGui(key1);
text += "s";
} catch (MissingResourceException e1) {
text = null;
type = type.getSupertype();
}
} else {
text = null;
type = type.getSupertype();
}
}
}
}
// fallback 2: property name (not localized)
if (text == null) {
text = colNode.getColProp().getType().getPropName();
}
return text;
}
/**
* Finds an Icon for a bean in a tree view.
*
* @param bean
* the bean for which we need a text
* @param link
* determines if it is a bean or a link to a bean.
*
* @return the found text or null if none found
*/
private static ImageIcon findIcon(final RapidBean bean, final boolean link) {
ImageIcon icon = null;
if (ApplicationManager.getApplication() != null && ApplicationManager.getApplication().getMainwindow() != null
&& ((MainWindowSwing) ApplicationManager.getApplication().getMainwindow()).getIconManager() != null) {
icon = ((MainWindowSwing) ApplicationManager.getApplication().getMainwindow()).getIconManager().getIcon(
bean.getType());
}
if (icon == null) {
if (bean.getContainer() != null && bean == ((Document) bean.getContainer()).getRoot()) {
icon = getIconBeanRoot();
} else if (link) {
icon = getIconBeanLink();
}
}
if (icon == null) {
icon = getIconBean();
}
return icon;
}
/**
* Finds an Icon for a bean Collection Property in a tree view.
*
* @param colNode
* the collection property node for which we query an icon
*
* @return the found icon or null if none found
*/
private ImageIcon findIcon(final DocumentTreeNodePropCol colNode) {
ImageIcon icon = null;
if (((TypePropertyCollection) colNode.getColProp().getType()).isComposition()) {
icon = getIconColPropComposition();
} else {
icon = getIconColPropLink();
}
return icon;
}
private static ImageIcon iconBeanRoot = null;
private static ImageIcon getIconBeanRoot() {
if (iconBeanRoot == null) {
iconBeanRoot = new ImageIcon(Application.class.getResource("pictures/root.gif"));
}
return iconBeanRoot;
}
private static ImageIcon iconBeanLink = null;
private static ImageIcon getIconBeanLink() {
if (iconBeanLink == null) {
iconBeanLink = new ImageIcon(Application.class.getResource("pictures/beanlink.gif"));
}
return iconBeanLink;
}
private static ImageIcon iconBean = null;
private static ImageIcon getIconBean() {
if (iconBean == null) {
iconBean = new ImageIcon(Application.class.getResource("pictures/bean.gif"));
}
return iconBean;
}
private static ImageIcon iconColPropComposition = null;
private static ImageIcon getIconColPropComposition() {
if (iconColPropComposition == null) {
iconColPropComposition = new ImageIcon(Application.class.getResource("pictures/property.gif"));
}
return iconColPropComposition;
}
private static ImageIcon iconColPropLink = null;
private static ImageIcon getIconColPropLink() {
if (iconColPropLink == null) {
iconColPropLink = new ImageIcon(Application.class.getResource("pictures/propertyLink.gif"));
}
return iconColPropLink;
}
}