1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.vectomatic.svg.edit.client;
19
20 import java.io.IOException;
21 import java.util.ArrayList;
22 import java.util.List;
23
24 import org.vectomatic.dom.svg.OMSVGSVGElement;
25 import org.vectomatic.dom.svg.utils.OMSVGParser;
26 import org.vectomatic.dom.svg.utils.SVGConstants;
27
28 import com.extjs.gxt.ui.client.event.Events;
29 import com.extjs.gxt.ui.client.event.Listener;
30 import com.extjs.gxt.ui.client.event.MenuEvent;
31 import com.extjs.gxt.ui.client.event.MessageBoxEvent;
32 import com.extjs.gxt.ui.client.event.SelectionListener;
33 import com.extjs.gxt.ui.client.event.WindowEvent;
34 import com.extjs.gxt.ui.client.util.Rectangle;
35 import com.extjs.gxt.ui.client.util.Size;
36 import com.extjs.gxt.ui.client.widget.Component;
37 import com.extjs.gxt.ui.client.widget.Info;
38 import com.extjs.gxt.ui.client.widget.MessageBox;
39 import com.extjs.gxt.ui.client.widget.Viewport;
40 import com.extjs.gxt.ui.client.widget.menu.Menu;
41 import com.extjs.gxt.ui.client.widget.menu.MenuBar;
42 import com.extjs.gxt.ui.client.widget.menu.MenuBarItem;
43 import com.extjs.gxt.ui.client.widget.menu.MenuItem;
44 import com.extjs.gxt.ui.client.widget.menu.SeparatorMenuItem;
45 import com.google.gwt.core.client.EntryPoint;
46 import com.google.gwt.core.client.GWT;
47 import com.google.gwt.http.client.Request;
48 import com.google.gwt.http.client.RequestBuilder;
49 import com.google.gwt.http.client.RequestCallback;
50 import com.google.gwt.http.client.RequestException;
51 import com.google.gwt.http.client.Response;
52 import com.google.gwt.user.client.DOM;
53 import com.google.gwt.user.client.ui.DialogBox;
54 import com.google.gwt.user.client.ui.RootPanel;
55
56
57
58
59
60 public class VectomaticApp2 implements EntryPoint {
61 static VectomaticApp2 APP;
62 private List<SVGWindow> windows;
63 private SVGWindow activeWindow;
64 private int windowX, windowY;
65 private Viewport viewPort;
66 private MenuBar menuBar;
67 private Menu recentDocsMenu;
68 private MenuItem resetViewItem;
69 private MenuItem tileWindowsItem;
70 private MenuItem stackWindowsItem;
71 private MenuItem closeWindowItem;
72 private SelectionListener<MenuEvent> dispatcher;
73 private MessageBox openUrlBox;
74 private RSSReader rssReader;
75 private AboutDialog aboutDialog;
76
77 public void onModuleLoad() {
78 APP = this;
79 GWT.setUncaughtExceptionHandler(new GWT.UncaughtExceptionHandler() {
80 public void onUncaughtException(Throwable throwable) {
81 GWT.log("Uncaught exception", throwable);
82 if (!GWT.isScript()) {
83 String text = "Uncaught exception: ";
84 while (throwable != null) {
85 StackTraceElement[] stackTraceElements = throwable
86 .getStackTrace();
87 text += throwable.toString() + "\n";
88 for (int i = 0; i < stackTraceElements.length; i++) {
89 text += " at " + stackTraceElements[i] + "\n";
90 }
91 throwable = throwable.getCause();
92 if (throwable != null) {
93 text += "Caused by: ";
94 }
95 }
96 DialogBox dialogBox = new DialogBox(true);
97 DOM.setStyleAttribute(dialogBox.getElement(),
98 "backgroundColor", "#ABCDEF");
99 System.err.print(text);
100 text = text.replaceAll(" ", " ");
101 dialogBox.setHTML("<pre>" + text + "</pre>");
102 dialogBox.center();
103 }
104 }
105 });
106 AppBundle.INSTANCE.css().ensureInjected();
107 windows = new ArrayList<SVGWindow>();
108 viewPort = new Viewport();
109
110 Menu fileMenu = new Menu();
111 final MenuItem openUrlItem = new MenuItem(AppConstants.INSTANCE.openUrlMenuItem());
112 fileMenu.add(openUrlItem);
113 final MenuItem openRssFeedItem = new MenuItem(AppConstants.INSTANCE.openRssFeedMenuItem());
114 fileMenu.add(openRssFeedItem);
115 MenuItem recentDocumentsItem = new MenuItem(AppConstants.INSTANCE.recentDocumentsMenuItem());
116 recentDocsMenu = new Menu();
117 recentDocumentsItem.setSubMenu(recentDocsMenu);
118 fileMenu.add(recentDocumentsItem);
119
120 Menu windowMenu = new Menu();
121 resetViewItem = new MenuItem(AppConstants.INSTANCE.resetViewMenuItem());
122 windowMenu.add(resetViewItem);
123 windowMenu.add(new SeparatorMenuItem());
124 tileWindowsItem = new MenuItem(AppConstants.INSTANCE.tileWindowsMenuItem());
125 windowMenu.add(tileWindowsItem);
126 stackWindowsItem = new MenuItem(AppConstants.INSTANCE.stackWindowsMenuItem());
127 windowMenu.add(stackWindowsItem);
128 windowMenu.add(new SeparatorMenuItem());
129 closeWindowItem = new MenuItem(AppConstants.INSTANCE.closeWindowMenuItem());
130 windowMenu.add(closeWindowItem);
131
132 Menu aboutMenu = new Menu();
133 final MenuItem aboutItem = new MenuItem(AppConstants.INSTANCE.aboutMenuItem());
134 aboutMenu.add(aboutItem);
135
136 menuBar = new MenuBar();
137 menuBar.setBorders(true);
138 menuBar.setStyleAttribute("borderTop", "none");
139 menuBar.add(new MenuBarItem(AppConstants.INSTANCE.fileMenu(), fileMenu));
140 menuBar.add(new MenuBarItem(AppConstants.INSTANCE.windowMenu(), windowMenu));
141 menuBar.add(new MenuBarItem(AppConstants.INSTANCE.aboutMenu(), aboutMenu));
142
143 dispatcher = new SelectionListener<MenuEvent>() {
144 @Override
145 public void componentSelected(MenuEvent me) {
146 MenuItem item = (MenuItem) me.getItem();
147 if (item.getParentMenu() == recentDocsMenu) {
148 openRecent(item.getText());
149 } else if (item == openUrlItem) {
150 openUrl();
151 } else if (item == openRssFeedItem) {
152 openRssFeed();
153 } else if (item == resetViewItem) {
154 resetView();
155 } else if (item == tileWindowsItem) {
156 tileWindows();
157 } else if (item == stackWindowsItem) {
158 stackWindows();
159 } else if (item == closeWindowItem) {
160 closeWindow(activeWindow);
161 } else if (item == aboutItem) {
162 about();
163 }
164 }
165 };
166 openUrlItem.addSelectionListener(dispatcher);
167 openRssFeedItem.addSelectionListener(dispatcher);
168 resetViewItem.addSelectionListener(dispatcher);
169 tileWindowsItem.addSelectionListener(dispatcher);
170 stackWindowsItem.addSelectionListener(dispatcher);
171 closeWindowItem.addSelectionListener(dispatcher);
172 aboutItem.addSelectionListener(dispatcher);
173
174 viewPort.add(menuBar);
175 addWindow(AppBundle.INSTANCE.fish().getSvg(), "fish.svg");
176 addWindow(AppBundle.INSTANCE.fries().getSvg(), "fries.svg");
177 viewPort.setStyleAttribute("background-color", SVGConstants.CSS_BEIGE_VALUE);
178
179 update();
180 RootPanel.get().add(viewPort);
181 }
182
183 public SVGWindow addWindow(OMSVGSVGElement svg, String title) {
184 SVGWindow window = GWT.create(SVGWindow.class);
185 window.setSvg(svg);
186 window.setHeading(title);
187 windows.add(window);
188
189
190 window.addListener(Events.Activate, new Listener<WindowEvent>() {
191
192 @Override
193 public void handleEvent(WindowEvent we) {
194 activeWindow = (SVGWindow) we.getWindow();
195 }
196 });
197 window.addListener(Events.BeforeHide, new Listener<WindowEvent>() {
198
199 @Override
200 public void handleEvent(WindowEvent we) {
201 closeWindow((SVGWindow) we.getWindow());
202 }
203 });
204
205
206 List<Component> recentDocs = recentDocsMenu.getItems();
207 boolean alreadyInRecentDocs = false;
208 for (Component item : recentDocs) {
209 MenuItem menuItem = (MenuItem)item;
210 if (title.equals(menuItem.getText())) {
211 alreadyInRecentDocs = true;
212 break;
213 }
214 }
215 if (!alreadyInRecentDocs) {
216 if (recentDocs.size() >= 8) {
217 Component oldestItem = recentDocs.get(0);
218 oldestItem.removeAllListeners();
219 recentDocsMenu.remove(oldestItem);
220 }
221 MenuItem windowItem = new MenuItem(title);
222 windowItem.addSelectionListener(dispatcher);
223 recentDocsMenu.add(windowItem);
224 }
225
226
227 int windowBarHeight = getWindowBarHeight();
228 windowY += windowBarHeight;
229 window.setPagePosition(windowX, windowY);
230 windowX += windowBarHeight;
231
232 viewPort.add(window);
233 window.setVisible(true);
234 update();
235 return window;
236 }
237
238 public void openUrl() {
239 GWT.log("openUrl()");
240 openUrlBox = MessageBox.prompt(AppConstants.INSTANCE.openUrlMenuItem(), AppConstants.INSTANCE.openUrlText());
241 openUrlBox.addCallback(new Listener<MessageBoxEvent>() {
242 public void handleEvent(MessageBoxEvent be) {
243 load(be.getValue());
244 }
245 });
246 }
247
248 public void info(String command, String message) {
249 Info.display(command, message);
250 }
251
252 public void load(final String url) {
253 OMSVGSVGElement svg = null;
254 if ("fish.svg".equals(url)) {
255 svg = AppBundle.INSTANCE.fish().getSvg();
256 addWindow(svg, url);
257 } else if ("fries.svg".equals(url)) {
258 svg = AppBundle.INSTANCE.fries().getSvg();
259 addWindow(svg, url);
260 } else {
261 String resourceUrl = GWT.getHostPageBaseURL() + "fetch?url=" + url + "&type=text/xml";
262 RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.GET, resourceUrl);
263 requestBuilder.setCallback(new RequestCallback() {
264 public void onError(Request request, Throwable e) {
265 GWT.log("Cannot fetch " + url, e);
266 info(AppConstants.INSTANCE.openUrlMenuItem(), AppMessages.INSTANCE.loadErrorMessage(url, e.getMessage()));
267 }
268
269 private void onSuccess(Request request, Response response) {
270 OMSVGSVGElement svg = OMSVGParser.parse(response.getText());
271 addWindow(svg, url);
272 }
273
274 public void onResponseReceived(Request request, Response response) {
275 if (response.getStatusCode() == Response.SC_OK) {
276 onSuccess(request, response);
277 } else {
278 onError(request, new IOException(AppMessages.INSTANCE.httpErrorMessage(Integer.toString(response.getStatusCode()))));
279 }
280 }
281 });
282 try {
283 requestBuilder.send();
284 } catch (RequestException e) {
285 GWT.log("Cannot fetch " + url, e);
286 info(AppConstants.INSTANCE.openUrlMenuItem(), AppMessages.INSTANCE.loadErrorMessage(url, e.getMessage()));
287 }
288 }
289 }
290
291 public void openRecent(String url) {
292 GWT.log("openRecent(" + url + ")");
293 load(url);
294 }
295
296 public void openRssFeed() {
297 GWT.log("openRssFeed()");
298 if (rssReader == null) {
299 rssReader = new RSSReader();
300 }
301 rssReader.show();
302 }
303
304 public void resetView() {
305 GWT.log("resetView()");
306 activeWindow.setRotationCompass(0);
307 activeWindow.setScaleSlider(50);
308 }
309 public void tileWindows() {
310 GWT.log("tileWindows()");
311 Rectangle rect = getRectangle();
312 int count = windows.size();
313 int cols = (int)Math.ceil(Math.sqrt(count));
314 int rows = (int)Math.ceil((double)count/cols);
315 GWT.log("cols=" + cols + "; rows=" + rows);
316 Size windowSize = new Size(rect.width / cols, rect.height / rows);
317 int index = 0;
318 for (SVGWindow window : windows) {
319 window.setSize(windowSize.width, windowSize.height);
320 int x = index % cols;
321 int y = index / cols;
322 window.setPagePosition(rect.x + x * windowSize.width, rect.y + y * windowSize.height);
323 index++;
324 }
325 }
326 public void stackWindows() {
327 GWT.log("stackWindows()");
328 Rectangle rect = getRectangle();
329 Size size = viewPort.getSize();
330 Size windowSize = new Size((int)(size.width * 0.75f), (int)(size.height * 0.75f));
331 int windowBarHeight = getWindowBarHeight();
332 int index = 0;
333 for (SVGWindow window : windows) {
334 window.setSize(windowSize.width, windowSize.height);
335 int x = rect.x + index * windowBarHeight;
336 int y = rect.y + index * windowBarHeight;
337 window.setPagePosition(x, y);
338 index++;
339 if (y + windowSize.height > size.height) {
340 x = rect.x;
341 y = rect.y;
342 index = 0;
343 }
344 }
345 }
346 public void closeWindow(SVGWindow window) {
347 GWT.log("closeWindow()");
348 if (window != null) {
349 window.removeAllListeners();
350 windows.remove(window);
351 activeWindow = null;
352 window.hide();
353 update();
354 }
355 }
356 public void about() {
357 GWT.log("about()");
358 if (aboutDialog == null) {
359 aboutDialog = new AboutDialog();
360 }
361 aboutDialog.show();
362 }
363 public Rectangle getRectangle() {
364 int windowBarHeight = getWindowBarHeight();
365 Size viewPortSize = viewPort.getSize();
366 Rectangle rect = new Rectangle(0, windowBarHeight, viewPortSize.width, viewPortSize.height - windowBarHeight);
367 return rect;
368 }
369 public static final int getWindowBarHeight() {
370 return 22;
371 }
372
373 private void update() {
374 closeWindowItem.setEnabled(windows.size() > 0);
375 tileWindowsItem.setEnabled(windows.size() > 0);
376 stackWindowsItem.setEnabled(windows.size() > 0);
377 resetViewItem.setEnabled(windows.size() > 0);
378 }
379 }