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.gwt.client.editor;
35
36 import com.google.gwt.core.client.GWT;
37 import com.google.gwt.dom.client.Document;
38 import com.google.gwt.dom.client.Element;
39 import com.google.gwt.dom.client.HeadElement;
40 import com.google.gwt.dom.client.LinkElement;
41 import com.google.gwt.dom.client.Node;
42 import com.google.gwt.event.shared.EventBus;
43 import com.google.gwt.event.shared.SimpleEventBus;
44 import com.google.gwt.user.client.ui.Composite;
45 import com.vaadin.terminal.gwt.client.ApplicationConnection;
46 import com.vaadin.terminal.gwt.client.Paintable;
47 import com.vaadin.terminal.gwt.client.UIDL;
48 import com.vaadin.terminal.gwt.client.VConsole;
49
50 import info.magnolia.ui.vaadin.gwt.client.editor.dom.CmsNode;
51 import info.magnolia.ui.vaadin.gwt.client.editor.dom.Comment;
52 import info.magnolia.ui.vaadin.gwt.client.editor.dom.MgnlElement;
53 import info.magnolia.ui.vaadin.gwt.client.editor.dom.processor.AbstractMgnlElementProcessor;
54 import info.magnolia.ui.vaadin.gwt.client.editor.dom.processor.CommentProcessor;
55 import info.magnolia.ui.vaadin.gwt.client.editor.dom.processor.ElementProcessor;
56 import info.magnolia.ui.vaadin.gwt.client.editor.dom.processor.MgnlElementProcessorFactory;
57 import info.magnolia.ui.vaadin.gwt.client.editor.event.DeleteComponentEvent;
58 import info.magnolia.ui.vaadin.gwt.client.editor.event.DeleteComponentEventHandler;
59 import info.magnolia.ui.vaadin.gwt.client.editor.event.EditComponentEvent;
60 import info.magnolia.ui.vaadin.gwt.client.editor.event.EditComponentEventHandler;
61 import info.magnolia.ui.vaadin.gwt.client.editor.event.NewAreaEvent;
62 import info.magnolia.ui.vaadin.gwt.client.editor.event.NewAreaEventHandler;
63 import info.magnolia.ui.vaadin.gwt.client.editor.event.NewComponentEvent;
64 import info.magnolia.ui.vaadin.gwt.client.editor.event.NewComponentEventHandler;
65 import info.magnolia.ui.vaadin.gwt.client.editor.event.SelectElementEvent;
66 import info.magnolia.ui.vaadin.gwt.client.editor.event.SelectElementEventHandler;
67 import info.magnolia.ui.vaadin.gwt.client.editor.event.SortComponentEvent;
68 import info.magnolia.ui.vaadin.gwt.client.editor.event.SortComponentEventHandler;
69 import info.magnolia.ui.vaadin.gwt.client.editor.jsni.event.FrameLoadedEvent;
70 import info.magnolia.ui.vaadin.gwt.client.editor.model.Model;
71 import info.magnolia.ui.vaadin.gwt.client.editor.model.ModelImpl;
72 import info.magnolia.ui.vaadin.gwt.client.editor.model.focus.FocusModel;
73 import info.magnolia.ui.vaadin.gwt.client.editor.model.focus.FocusModelImpl;
74 import info.magnolia.ui.vaadin.gwt.client.editor.widget.controlbar.PageBar;
75
76 import org.vaadin.rpc.client.ClientSideHandler;
77 import org.vaadin.rpc.client.ClientSideProxy;
78 import org.vaadin.rpc.client.Method;
79
80 import java.util.List;
81
82
83
84
85
86 public class VPageEditor extends Composite implements VPageEditorView.Listener, Paintable, ClientSideHandler {
87
88
89 private static final String PAGE_EDITOR_CSS = "/VAADIN/themes/admincentraltheme/pageeditor.css";
90
91
92 private final VPageEditorView view;
93 private final Model model;
94 private final EventBus eventBus;
95 private final FocusModel focusModel;
96
97 protected ApplicationConnection client;
98 private ClientSideProxy proxy;
99 private String paintableId;
100
101 private VPageEditorParameters pageEditorParameters;
102
103
104 public VPageEditor() {
105 this.eventBus = new SimpleEventBus();
106
107 this.view = new VPageEditorViewImpl(eventBus);
108 this.model = new ModelImpl();
109 this.focusModel = new FocusModelImpl(eventBus, model);
110
111
112 initWidget(view.asWidget());
113
114 view.setListener(this);
115
116 registerDomEventHandlers();
117 registerEditorEventHandlers();
118
119
120
121 proxy = new ClientSideProxy(this) {
122 {
123 register("refresh", new Method() {
124 @Override
125 public void invoke(String methodName, Object[] params) {
126 view.reload();
127 }
128 });
129
130 register("load", new Method() {
131 @Override
132 public void invoke(String methodName, Object[] params) {
133 String json = String.valueOf(params[0]);
134 pageEditorParameters = VPageEditorParameters.parse(json);
135 view.setUrl(pageEditorParameters.getContextPath() + pageEditorParameters.getNodePath());
136 }
137 });
138 }
139 };
140
141 }
142
143 @Override
144 public boolean initWidget(Object[] objects) {
145 return false;
146 }
147
148 @Override
149 public void handleCallFromServer(String method, Object[] params) {
150 VConsole.error("Unhandled RPC call from server: " + method);
151 }
152
153 @Override
154 public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
155 this.client = client;
156 this.paintableId = uidl.getId();
157 if (client.updateComponent(this, uidl, true)) {
158 return;
159 }
160
161 proxy.update(this, uidl, client);
162 }
163
164 private void registerDomEventHandlers() {
165
166 eventBus.addHandler(FrameLoadedEvent.TYPE, new FrameLoadedEvent.Handler() {
167
168 @Override
169 public void handle(FrameLoadedEvent event) {
170 model.reset();
171 if (pageEditorParameters.isPreview()) {
172 return;
173 }
174
175 view.initSelectionListener();
176
177 Document document = event.getFrameDocument();
178 process(event.getFrameDocument());
179
180 if (model.getRootPage().getControlBar() != null) {
181 ((PageBar)model.getRootPage().getControlBar()).setPageTitle(document.getTitle());
182 }
183 focusModel.init();
184 }
185
186 });
187 }
188
189 private void registerEditorEventHandlers() {
190
191 eventBus.addHandler(SelectElementEvent.TYPE, new SelectElementEventHandler() {
192
193 @Override
194 public void onSelectElement(SelectElementEvent selectElementEvent) {
195 proxy.call("selectElement", selectElementEvent.getType(), selectElementEvent.getJson());
196 }
197
198 });
199
200 eventBus.addHandler(NewAreaEvent.TYPE, new NewAreaEventHandler() {
201 @Override
202 public void onNewArea(NewAreaEvent newAreaEvent) {
203 proxy.call("newArea", newAreaEvent.getWorkSpace(), newAreaEvent.getNodeType(), newAreaEvent.getPath());
204 }
205 });
206
207 eventBus.addHandler(NewComponentEvent.TYPE, new NewComponentEventHandler() {
208 @Override
209 public void onNewComponent(NewComponentEvent newComponentEvent) {
210 proxy.call("newComponent", newComponentEvent.getWorkSpace(), newComponentEvent.getPath(), newComponentEvent.getAvailableComponents());
211 }
212 });
213
214 eventBus.addHandler(EditComponentEvent.TYPE, new EditComponentEventHandler() {
215 @Override
216 public void onEditComponent(EditComponentEvent editComponentEvent) {
217 proxy.call("editComponent", editComponentEvent.getWorkspace(), editComponentEvent.getPath(), editComponentEvent.getDialog());
218 }
219 });
220
221 eventBus.addHandler(DeleteComponentEvent.TYPE, new DeleteComponentEventHandler() {
222 @Override
223 public void onDeleteComponent(DeleteComponentEvent deleteComponentEvent) {
224 proxy.call("deleteComponent", deleteComponentEvent.getWorkspace(), deleteComponentEvent.getPath());
225 }
226 });
227 eventBus.addHandler(SortComponentEvent.TYPE, new SortComponentEventHandler() {
228 @Override
229 public void onSortComponent(SortComponentEvent sortComponentEvent) {
230 proxy.call("sortComponent", sortComponentEvent.getWorkspace(), sortComponentEvent.getParentPath(), sortComponentEvent.getSourcePath(), sortComponentEvent.getTargetPath(), sortComponentEvent.getOrder());
231 }
232 });
233 }
234
235 public Model getModel() {
236 return model;
237 }
238
239 @Override
240 public void selectElement(final Element element) {
241 focusModel.selectElement(element);
242 }
243
244 private void injectEditorStyles(final Document document) {
245 HeadElement head = HeadElement.as(document.getElementsByTagName("head").getItem(0));
246 LinkElement cssLink = document.createLinkElement();
247 cssLink.setType("text/css");
248 cssLink.setRel("stylesheet");
249 cssLink.setHref(pageEditorParameters.getContextPath() + PAGE_EDITOR_CSS);
250 head.insertFirst(cssLink);
251 }
252
253 private void process(final Document document) {
254 injectEditorStyles(document);
255
256 long startTime = System.currentTimeMillis();
257 processDocument(document.getDocumentElement(), null);
258 processMgnlElements();
259
260 GWT.log("Time spent to process cms comments: " + (System.currentTimeMillis() - startTime) + "ms");
261
262 }
263
264 private void processDocument(Node node, MgnlElement mgnlElement) {
265 boolean proceed = true;
266 if (mgnlElement == null && model.getRootPage() != null) {
267 mgnlElement = model.getRootPage();
268 }
269 for (int i = 0; i < node.getChildCount(); i++) {
270 Node childNode = node.getChild(i);
271 if (childNode.getNodeType() == Comment.COMMENT_NODE) {
272
273 try {
274 CommentProcessor processor = new CommentProcessor();
275 mgnlElement = processor.process(model, childNode, mgnlElement);
276 } catch (IllegalArgumentException e) {
277 GWT.log("Not CMSComment element, skipping: " + e.toString());
278 } catch (Exception e) {
279 GWT.log("Caught undefined exception: " + e.toString());
280 }
281 } else if (childNode.getNodeType() == Node.ELEMENT_NODE && mgnlElement != null && !mgnlElement.isPage()) {
282 proceed = ElementProcessor.process(model, childNode, mgnlElement);
283 }
284 if (proceed) {
285 processDocument(childNode, mgnlElement);
286 }
287 }
288
289 }
290
291 private void processMgnlElements() {
292 CmsNode root = model.getRootPage();
293 List<CmsNode> elements = root.getDescendants();
294 elements.add(root);
295 for (CmsNode element : elements) {
296
297 try {
298 AbstractMgnlElementProcessor processor = MgnlElementProcessorFactory.getProcessor(model, eventBus, element.asMgnlElement());
299 processor.process();
300 } catch (IllegalArgumentException e) {
301 GWT.log("MgnlFactory could not instantiate class. The element is neither an area nor component.");
302 }
303 }
304 }
305
306 }