001    /*
002     * Apache License
003     * Version 2.0, January 2004
004     * http://www.apache.org/licenses/
005     *
006     * Copyright 2008-2010 by chenillekit.org
007     *
008     * Licensed under the Apache License, Version 2.0 (the "License");
009     * you may not use this file except in compliance with the License.
010     * You may obtain a copy of the License at
011     *
012     * http://www.apache.org/licenses/LICENSE-2.0
013     */
014    
015    package org.chenillekit.tapestry.core.mixins;
016    
017    import org.apache.tapestry5.BindingConstants;
018    import org.apache.tapestry5.ClientElement;
019    import org.apache.tapestry5.ComponentResources;
020    import org.apache.tapestry5.MarkupWriter;
021    import org.apache.tapestry5.annotations.AfterRender;
022    import org.apache.tapestry5.annotations.Environmental;
023    import org.apache.tapestry5.annotations.Import;
024    import org.apache.tapestry5.annotations.InjectContainer;
025    import org.apache.tapestry5.annotations.Parameter;
026    import org.apache.tapestry5.annotations.SetupRender;
027    import org.apache.tapestry5.ioc.annotations.Inject;
028    import org.apache.tapestry5.services.Cookies;
029    import org.apache.tapestry5.services.javascript.JavaScriptSupport;
030    
031    /**
032     * Helper mixin that will render a variable element type.
033     * Similar to the Any component in Tapestry3.
034     *
035     * @version $Id: Resizable.java 674 2010-07-29 12:47:25Z homburgs $
036     */
037    @Import(library = {"../Chenillekit.js", "../Cookie.js", "${tapestry.scriptaculous}/dragdrop.js",
038                    "Resizable.js"}, stylesheet = {"Resizable.css"})
039    public class Resizable implements ClientElement
040    {
041            /**
042             * The field component to which this mixin is attached.
043             */
044            @InjectContainer
045            private ClientElement clientElement;
046    
047            @Inject
048            private ComponentResources resources;
049    
050            @Environmental
051            private JavaScriptSupport javascriptSupport;
052    
053            @Inject
054            private Cookies cookies;
055    
056            /**
057             * The id used to generate a page-unique client-side identifier for the component. If a component renders multiple
058             * times, a suffix will be appended to the to id to ensure uniqueness.
059             */
060            @Parameter(value = "prop:componentResources.id", defaultPrefix = BindingConstants.LITERAL)
061            private String clientId;
062    
063            /**
064             * let you allow to restrict the direction of resizing.
065             * 'vertical', 'horizontal' or empty for both
066             */
067            @Parameter(defaultPrefix = BindingConstants.LITERAL)
068            private String constraint;
069    
070            /**
071             * if true, width and height of the resizable element persists via cookie.
072             * default is 'false'
073             */
074            @Parameter(value = "false", defaultPrefix = BindingConstants.PROP)
075            private boolean persist;
076    
077            private String assignedClientId;
078    
079            @SetupRender
080            void setupRender()
081            {
082                    assignedClientId = javascriptSupport.allocateClientId(clientId);
083            }
084    
085            /**
086             * Tapestry render phase method. End a tag here.
087             *
088             * @param writer the markup writer
089             */
090            @AfterRender
091            void afterRender(MarkupWriter writer)
092            {
093                    // start handle south
094                    writer.element("div", "id", "handle_" + clientElement.getClientId(),
095                                               "class", "ck-resizable-handle");
096                    // end handle south
097                    writer.end();
098    
099                    if (persist)
100                    {
101                            int width = getIntValueFromCookie(clientElement.getClientId() + ".width");
102                            int height = getIntValueFromCookie(clientElement.getClientId() + ".height");
103    
104                            if (width > 0)
105                                    javascriptSupport.addScript("$('%s').style.width = '%dpx';", clientElement.getClientId(), width);
106    
107                            if (height > 0)
108                                    javascriptSupport.addScript("$('%s').style.height = '%dpx';", clientElement.getClientId(), height);
109                    }
110    
111                    String jsString = "%s = new Resizable('%s', {handle:$('handle_%s')";
112                    if (constraint != null)
113                            jsString += String.format(",constraint:'%s'", constraint);
114                    jsString += ", persist:%s});";
115    
116                    javascriptSupport.addScript(jsString, getClientId(), clientElement.getClientId(), clientElement.getClientId(), persist);
117            }
118    
119            /**
120             * Returns a unique id for the element. This value will be unique for any given rendering of a
121             * page. This value is intended for use as the id attribute of the client-side element, and will
122             * be used with any DHTML/Ajax related JavaScript.
123             */
124            public String getClientId()
125            {
126                    return assignedClientId;
127            }
128    
129            /**
130             * get an integer value from cookie.
131             *
132             * @param key the key of the value
133             *
134             * @return the integer value
135             */
136            private int getIntValueFromCookie(String key)
137            {
138                    int intValue = 0;
139                    String cookieValue = cookies.readCookieValue(key);
140    
141                    if (cookieValue != null)
142                    {
143                            try
144                            {
145                                    intValue = Integer.parseInt(cookieValue);
146                            }
147                            catch (NumberFormatException e)
148                            {
149                                    throw new RuntimeException(e);
150                            }
151                    }
152    
153                    return intValue;
154            }
155    }