001    package net.sf.tacos.components.scriptaculous;
002    
003    import java.util.Collection;
004    import java.util.HashMap;
005    import java.util.Map;
006    
007    import org.apache.tapestry.AbstractComponent;
008    import org.apache.tapestry.IActionListener;
009    import org.apache.tapestry.IDirect;
010    import org.apache.tapestry.IMarkupWriter;
011    import org.apache.tapestry.IRequestCycle;
012    import org.apache.tapestry.IScript;
013    import org.apache.tapestry.Tapestry;
014    import org.apache.tapestry.TapestryUtils;
015    import org.apache.tapestry.engine.DirectServiceParameter;
016    import org.apache.tapestry.engine.IEngineService;
017    import org.apache.tapestry.engine.ILink;
018    import org.apache.tapestry.listener.ListenerInvoker;
019    
020    /**
021     * Implementation of the <a href="http://wiki.script.aculo.us/scriptaculous/show/Droppables">Droppables</a>.
022     * <p>
023     * This component makes a html element droppable. Droppables are elements which allow Draggables to be dropped on.
024     * When a draggable is released over a droppable, a listener method may be triggered to inform your application
025     * about the dropped element. 
026     * </p>
027     * 
028     * <p>Example:
029     * <pre>&lt;div jwcid="@tacos:Droppable" listener="listener:onDrop" hoverClass="literal:hoverCss" /&gt;</pre>
030     * </p>
031     * 
032     * @author Igor Drobiazko
033     * @since 4.1
034     * @see Draggable
035     */
036    public abstract class Droppable extends AbstractComponent implements IDirect{
037            /**
038             * Name of the {@link IRequestCycle} parameter whose value is the
039             * identifier of the dropped draggable
040             * @see {@link IRequestCycle#getParameter(String)}
041             */
042            public static final String DRAGGABLE_PARAMETER = "draggable";
043            
044            /**
045             * {@inheritDoc}
046             */
047            protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle) {
048            writer.begin(getTemplateTagName());
049            renderIdAttribute(writer, cycle);
050            renderInformalParameters(writer, cycle);
051            renderBody(writer, cycle);
052            writer.end();
053            
054            Map params = new HashMap();
055            params.put("component", this);
056            params.put("accept", getAccept());
057            params.put("hoverClass", getHoverClass());
058            if(getListener()!=null)
059                    params.put("url", getLink().getURL());
060            
061            getScript().execute(this, cycle, TapestryUtils.getPageRenderSupport(cycle, this), params);
062            }
063            
064            /**
065             * {@inheritDoc}
066             */
067            public void trigger(IRequestCycle cycle) {
068            IActionListener listener = getListener();
069            if (listener == null)
070                throw Tapestry.createRequiredParameterException(this, "listener");
071            
072            getListenerInvoker().invokeListener(listener, this, cycle);
073            }
074            
075            /**Returns a link*/
076            private ILink getLink(){
077                    return getEngine().getLink(isStateful(), new DirectServiceParameter(this));
078            }
079    
080        /** Injected listener parameter, may be null. */
081        public abstract IActionListener getListener();
082        /** Injected script. */
083        public abstract IScript getScript();
084        /** Injected listener invoker. */
085        public abstract ListenerInvoker getListenerInvoker();
086        /** Injected engine service . */
087        public abstract IEngineService getEngine();
088            /**
089             * Returns {@link String[]} or {@link Collection} of strings describing CSS classes.
090             * The Droppable will only accept {@link Draggable} that have one or more of these CSS classes.
091             */
092        public abstract Collection getAccept();
093        /**
094         * Returns the CSS class this Droppable will have
095         * when an accepted {@link Draggable} is hovered over it.
096         */
097        public abstract String getHoverClass();
098    }