1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.ui.vaadin.editor;
35
36 import info.magnolia.ui.vaadin.gwt.client.editor.VImageEditor;
37
38 import java.io.Serializable;
39 import java.util.ArrayList;
40 import java.util.List;
41 import java.util.Map;
42
43 import org.vaadin.rpc.ServerSideHandler;
44 import org.vaadin.rpc.ServerSideProxy;
45 import org.vaadin.rpc.client.Method;
46
47 import com.vaadin.terminal.PaintException;
48 import com.vaadin.terminal.PaintTarget;
49 import com.vaadin.terminal.Resource;
50 import com.vaadin.ui.AbstractComponent;
51 import com.vaadin.ui.ClientWidget;
52
53
54
55
56 @ClientWidget(VImageEditor.class)
57 public class ImageEditor extends AbstractComponent implements ServerSideHandler {
58
59 private static final int DEFAULT_MIN_DIMENSION = 200;
60
61 private int minDimension = DEFAULT_MIN_DIMENSION;
62
63 private int marginsPx = 20;
64
65 private boolean isCropAspectRatioLocked = false;
66
67 private boolean isAttached = false;
68
69 private String fileName = "";
70
71 private String mimeType = "";
72
73 private final ServerSideProxy proxy = new ServerSideProxy(this) {
74 {
75 register("croppedAreaReady", new Method() {
76
77 @Override
78 public void invoke(String methodName, Object[] params) {
79 final CropArea area = new CropArea(getInt(params[0]), getInt(params[1]), getInt(params[2]), getInt(params[3]));
80 for (final CropListener listener : listeners) {
81 listener.onCrop(area);
82 }
83 }
84 });
85 }
86
87 public int getInt(Object intObj) {
88 return (Integer) intObj;
89 }
90 };
91
92 private Resource source;
93
94 private final List<CropListener> listeners = new ArrayList<CropListener>();
95
96 private boolean isCropping = false;
97
98 public ImageEditor() {
99 setImmediate(true);
100 }
101
102 public void addCropListener(CropListener listener) {
103 listeners.add(listener);
104 }
105
106 public void setMarginsPx(int marginsPx) {
107 this.marginsPx = marginsPx;
108 callOnceIfAttached("setMarginsPx", marginsPx);
109 }
110
111 public void setSource(Resource source) {
112 this.source = source;
113 callOnceIfAttached("setSource", this.source);
114 }
115
116 public void setCropping(boolean isCropping) {
117 this.isCropping = isCropping;
118 callOnceIfAttached("setCropping", isCropping);
119 }
120
121 public void fetchCropArea() {
122 callOnceIfAttached("fetchCropArea");
123 }
124
125 public void setCropAspectRatioLocked(boolean isLocked) {
126 this.isCropAspectRatioLocked = isLocked;
127 callOnceIfAttached("lockAspectRatio", isLocked);
128 }
129
130 public void setMinDimension(int minDimension) {
131 this.minDimension = minDimension;
132 callOnceIfAttached("setMinDimension", minDimension);
133 }
134
135 public void setFileName(String fileName) {
136 this.fileName = fileName;
137 callOnceIfAttached("setFileName", fileName);
138 }
139
140 public void setMimeType(String mimeType) {
141 this.mimeType = mimeType;
142 callOnceIfAttached("setMimeType", mimeType);
143 }
144
145 public boolean isCropping() {
146 return isCropping;
147 }
148
149 public boolean isAspectRatioLocked() {
150 return this.isCropAspectRatioLocked;
151 }
152
153 private void callOnceIfAttached(String methodName, Object... params) {
154 if (isAttached) {
155 proxy.callOnce(methodName, params);
156 }
157 }
158
159 @Override
160 public void paintContent(PaintTarget target) throws PaintException {
161 super.paintContent(target);
162 proxy.paintContent(target);
163 }
164
165 @Override
166 public void changeVariables(Object source, Map<String, Object> variables) {
167 super.changeVariables(source, variables);
168 proxy.changeVariables(source, variables);
169 }
170
171 @Override
172 public Object[] initRequestFromClient() {
173 proxy.callOnce("setSource", this.source);
174 proxy.callOnce("setCropping", isCropping);
175 proxy.callOnce("setMinDimension", minDimension);
176 proxy.callOnce("setMarginsPx", marginsPx);
177 proxy.callOnce("setFileName", fileName);
178 proxy.callOnce("setMimeType", mimeType);
179 if (isAspectRatioLocked()) {
180 proxy.callOnce("lockAspectRatio", isCropAspectRatioLocked);
181 }
182 return new Object[] {};
183 }
184
185 @Override
186 public void callFromClient(String method, Object[] params) {
187 throw new RuntimeException("Unhandled call from client: " + method);
188 }
189
190 @Override
191 public void attach() {
192 super.attach();
193 this.isAttached = true;
194 }
195
196 @Override
197 public void detach() {
198 super.detach();
199 this.isAttached = false;
200 }
201
202
203
204
205 public interface CropListener {
206 void onCrop(final CropArea area);
207 }
208
209
210
211
212 public static class CropArea implements Serializable {
213 private final int top;
214
215 private final int left;
216
217 private final int width;
218
219 private final int height;
220
221 public CropArea(int left, int top, int width, int height) {
222 this.top = top;
223 this.left = left;
224 this.width = width;
225 this.height = height;
226 }
227
228 public int getTop() {
229 return top;
230 }
231
232 public int getLeft() {
233 return left;
234 }
235
236 public int getWidth() {
237 return width;
238 }
239
240 public int getHeight() {
241 return height;
242 }
243
244 @Override
245 public String toString() {
246 return "[" + "w:" + getWidth() + "h:" + getHeight() + "l:" + getLeft() + "t:" + getTop() + "]";
247 }
248 }
249 }