001    // Copyright 2004, 2005 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry.contrib.link;
016    
017    import org.apache.hivemind.ApplicationRuntimeException;
018    import org.apache.tapestry.IMarkupWriter;
019    import org.apache.tapestry.IRequestCycle;
020    import org.apache.tapestry.Tapestry;
021    import org.apache.tapestry.components.ILinkComponent;
022    import org.apache.tapestry.engine.ILink;
023    import org.apache.tapestry.link.ILinkRenderer;
024    
025    /**
026     * An {@link ILinkRenderer} implementation that generates an HTML button.
027     * This is particularly useful for implementing cancel buttons.
028     * 
029     * @author Paul Ferraro
030     * @since 4.0
031     */
032    public class ButtonLinkRenderer implements ILinkRenderer
033    {
034        public static final ILinkRenderer SHARED_INSTANCE = new ButtonLinkRenderer();
035    
036        /**
037         * @see org.apache.tapestry.link.ILinkRenderer#renderLink(org.apache.tapestry.IMarkupWriter,
038         *      org.apache.tapestry.IRequestCycle, org.apache.tapestry.components.ILinkComponent)
039         */
040        public void renderLink(IMarkupWriter writer, IRequestCycle cycle, ILinkComponent component)
041        {
042            if (cycle.getAttribute(Tapestry.LINK_COMPONENT_ATTRIBUTE_NAME) != null)
043            {
044                String message = Tapestry.getMessage("AbstractLinkComponent.no-nesting");
045                throw new ApplicationRuntimeException(message, component, null, null);
046            }
047    
048            cycle.setAttribute(Tapestry.LINK_COMPONENT_ATTRIBUTE_NAME, component);
049    
050            ILink link = component.getLink(cycle);
051    
052            writer.begin("button");
053            writer.attribute("type", "button");
054    
055            if (component.isDisabled())
056            {
057                writer.attribute("disabled", "disabled");
058            }
059    
060            if (!cycle.isRewinding()) {
061                String url = link.getURL(component.getAnchor(), true);
062                String target = component.getTarget();
063                String onclick = (target == null) ? getScript(url) : getScript(url, target);
064    
065                writer.attribute("onclick", onclick);
066            }
067            
068            component.renderAdditionalAttributes(writer, cycle);
069    
070            IMarkupWriter wrappedWriter = writer.getNestedWriter();
071    
072            component.renderBody(wrappedWriter, cycle);
073    
074            wrappedWriter.close();
075    
076            writer.end();
077    
078            cycle.removeAttribute(Tapestry.LINK_COMPONENT_ATTRIBUTE_NAME);
079        }
080    
081        /**
082         * Generates the onclick event handler that opens the specified url in the current window.
083         * @param url the url generated by this link
084         * @return a JavaScript onclick event handler
085         */
086        protected String getScript(String url)
087        {
088            return "window.location='" + url + "'";
089        }
090    
091        /**
092         * Generates the onclick event handler that opens the specified url in the specified window or frame.
093         * @param url the url generated by this link
094         * @param target the name of the target window or frame
095         * @return a JavaScript onclick event handler
096         */
097        protected String getScript(String url, String target)
098        {
099            return "window.open('" + url + "','" + target + "')";
100        }
101    }