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 }