/* This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV This program is free software; you can redistribute it and/or modify it under the terms of the GNU Affero 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program; if not, see http://www.gnu.org/licenses or write to the Free Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 */ package com.servoy.j2db.server.headlessclient.dataui; import java.io.Serializable; import org.apache.wicket.AttributeModifier; import org.apache.wicket.Component; import org.apache.wicket.IResourceListener; import org.apache.wicket.MetaDataKey; import org.apache.wicket.ResourceReference; import org.apache.wicket.Session; import org.apache.wicket.behavior.IIgnoreDisabledComponentBehavior; import org.apache.wicket.behavior.SimpleAttributeModifier; import org.apache.wicket.model.AbstractReadOnlyModel; import org.apache.wicket.model.IComponentAssignedModel; import org.apache.wicket.model.IModel; import org.apache.wicket.model.IWrapModel; import org.apache.wicket.model.Model; import org.apache.wicket.util.string.Strings; import com.servoy.j2db.IApplication; import com.servoy.j2db.server.headlessclient.WebClient; import com.servoy.j2db.server.headlessclient.WebClientSession; import com.servoy.j2db.ui.IComponent; import com.servoy.j2db.util.Debug; /** * This AttributeModifier will display the tooltip of an {@link IComponent#getToolTipText()} in the browser. * add the instance to the behavior list of your wicket component. * * @author jcompagner * @since 5.0 */ public class TooltipAttributeModifier extends AttributeModifier implements IIgnoreDisabledComponentBehavior { private static final long serialVersionUID = 1L; /** * The attribute modifier instance to add to the behavior list of your Wicket {@link IComponent} for displaying its tooltip */ public static final TooltipAttributeModifier INSTANCE = new TooltipAttributeModifier(); public static final MetaDataKey<Serializable> TOOLTIP_METADATA = new MetaDataKey<Serializable>() { private static final long serialVersionUID = 1L; }; /** * Construct. * * @param attribute * @param replaceModel */ private TooltipAttributeModifier() { super("onmouseover", true, new TooltipModel()); } @Override public void bind(final Component component) { super.bind(component); component.add(new SimpleAttributeModifier("onmouseout", "hidetip();") { @Override public boolean isEnabled(Component component) { String tooltip = getToolTipForComponent(component); if (tooltip == null) { return false; } return super.isEnabled(component); } }); } static String getToolTipForComponent(Component component) { String tooltip = null; if (component instanceof IComponent || component instanceof SortableCellViewHeader || component.getMetaData(TOOLTIP_METADATA) != null) { if (component instanceof IComponent) { tooltip = ((IComponent)component).getToolTipText(); } if (component instanceof SortableCellViewHeader) { tooltip = ((SortableCellViewHeader)component).getToolTipText(); } if (tooltip == null) { tooltip = (String)component.getMetaData(TOOLTIP_METADATA); } return tooltip; } return null; } @Override public boolean isEnabled(Component component) { if (!component.isEnabledInHierarchy()) { return false; } else return super.isEnabled(component); } private static class TooltipModel extends Model implements IComponentAssignedModel { private static final long serialVersionUID = 1L; /** * @see org.apache.wicket.model.IComponentAssignedModel#wrapOnAssignment(org.apache.wicket.Component) */ public IWrapModel wrapOnAssignment(Component component) { return new TooltipWrapModel(component); } private class TooltipWrapModel extends AbstractReadOnlyModel implements IWrapModel { private static final long serialVersionUID = 1L; private final Component component; /** * @param component */ public TooltipWrapModel(Component component) { this.component = component; } /** * @see org.apache.wicket.model.AbstractReadOnlyModel#getObject() */ @SuppressWarnings("nls") @Override public Object getObject() { String tooltip = getToolTipForComponent(component); if (!WebClient.isMobile() && tooltip != null) { int initialDelay = 750; int dismissDelay = 5000; if (Session.exists()) { // blobloaders only works for components that implements IResourceListern (currently only Button/Labels/HtmlArea) if (component instanceof IResourceListener) { tooltip = StripHTMLTagsConverter.convertBlobLoaderReferences(tooltip, component).toString(); } else { if (tooltip.indexOf("media:///servoy_blobloader") != -1) { Debug.log("Component: " + component + " doenst support sevoy_blobloader references " + tooltip); } } WebClient webClient = ((WebClientSession)Session.get()).getWebClient(); tooltip = StripHTMLTagsConverter.convertMediaReferences(tooltip, webClient.getSolutionName(), new ResourceReference("media"), "", false).toString(); Object initialDelayValue = webClient.getClientProperty(IApplication.TOOLTIP_INITIAL_DELAY); if (initialDelayValue instanceof Number) initialDelay = ((Number)initialDelayValue).intValue(); Object dismissDelayValue = webClient.getClientProperty(IApplication.TOOLTIP_DISMISS_DELAY); if (dismissDelayValue instanceof Number) dismissDelay = ((Number)dismissDelayValue).intValue(); } boolean isHTMLText = tooltip.trim().toLowerCase().startsWith("<html>"); tooltip = tooltip.replace("\r\n", isHTMLText ? " " : "<br>"); tooltip = tooltip.replace("\n", isHTMLText ? " " : "<br>"); if (!isHTMLText) { tooltip = "<html><span style='white-space:nowrap'>" + Strings.escapeMarkup(tooltip, false, false) + "</span></html>"; // ' character not handled well tooltip = tooltip.replace("'", "\'"); } tooltip = tooltip.replace("\\", "\\\\"); tooltip = tooltip.replace("\'", "\\\'"); return "showtip(event, '" + tooltip + "'," + initialDelay + "," + dismissDelay + ");"; } return null; } /** * @see org.apache.wicket.model.IWrapModel#getWrappedModel() */ public IModel getWrappedModel() { return TooltipModel.this; } } } }