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 package org.utgenome.gwt.utgb.client;
26
27 import java.util.ArrayList;
28 import java.util.HashMap;
29
30 import org.utgenome.gwt.utgb.client.track.TrackFrame;
31 import org.utgenome.gwt.utgb.client.track.TrackGroup;
32 import org.utgenome.gwt.utgb.client.track.TrackGroupProperty;
33 import org.utgenome.gwt.utgb.client.track.TrackGroupPropertyChange;
34 import org.utgenome.gwt.utgb.client.track.TrackGroupPropertyChangeListener;
35 import org.utgenome.gwt.utgb.client.track.TrackQueue;
36 import org.utgenome.gwt.utgb.client.track.TrackWindow;
37 import org.utgenome.gwt.utgb.client.track.UTGBProperty;
38 import org.utgenome.gwt.utgb.client.ui.RoundCornerFrame;
39 import org.utgenome.gwt.utgb.client.util.BrowserInfo;
40 import org.utgenome.gwt.utgb.client.util.Properties;
41 import org.utgenome.gwt.utgb.client.util.StringUtil;
42 import org.utgenome.gwt.utgb.client.view.TrackView;
43 import org.utgenome.gwt.widget.client.Style;
44
45 import com.google.gwt.core.client.EntryPoint;
46 import com.google.gwt.core.client.GWT;
47 import com.google.gwt.dom.client.Element;
48 import com.google.gwt.dom.client.EventTarget;
49 import com.google.gwt.event.dom.client.KeyCodes;
50 import com.google.gwt.event.logical.shared.ResizeEvent;
51 import com.google.gwt.event.logical.shared.ResizeHandler;
52 import com.google.gwt.event.logical.shared.ValueChangeEvent;
53 import com.google.gwt.event.logical.shared.ValueChangeHandler;
54 import com.google.gwt.user.client.Command;
55 import com.google.gwt.user.client.DOM;
56 import com.google.gwt.user.client.DeferredCommand;
57 import com.google.gwt.user.client.Event;
58 import com.google.gwt.user.client.History;
59 import com.google.gwt.user.client.Window;
60 import com.google.gwt.user.client.Event.NativePreviewEvent;
61 import com.google.gwt.user.client.rpc.AsyncCallback;
62 import com.google.gwt.user.client.ui.DockPanel;
63 import com.google.gwt.user.client.ui.Label;
64 import com.google.gwt.user.client.ui.PopupPanel;
65 import com.google.gwt.user.client.ui.RootPanel;
66
67 public class UTGBEntryPointBase implements EntryPoint {
68
69 private final DockPanel basePanel = new DockPanel();
70 private final TrackGroup trackGroup = new TrackGroup("root");
71 private TrackGroup mainGroup;
72 private final TrackQueue trackQueue = new TrackQueue(trackGroup);
73
74 private HashMap<String, String> queryParam = new HashMap<String, String>();
75
76 public TrackGroup getTrackGroup() {
77 return trackGroup;
78 }
79
80 public TrackQueue getTrackQueue() {
81 return trackQueue;
82 }
83
84 public DockPanel getBasePanel() {
85 return basePanel;
86 }
87
88
89
90
91
92
93
94 public class KeyboardShortcut implements Event.NativePreviewHandler {
95 public void onPreviewNativeEvent(NativePreviewEvent event) {
96
97
98 int type = event.getTypeInt();
99 int keyCode = event.getNativeEvent().getKeyCode();
100
101 switch (type) {
102 case Event.ONKEYDOWN:
103 EventTarget eventTarget = event.getNativeEvent().getEventTarget();
104 if (Element.is(eventTarget)) {
105 Element e = eventTarget.cast();
106 String tagName = e.getTagName();
107
108 if (tagName.equalsIgnoreCase("input"))
109 break;
110
111
112 if (event.getNativeEvent().getAltKey())
113 break;
114
115 double scrollPercentage = 20.0;
116 if (event.getNativeEvent().getShiftKey())
117 scrollPercentage = 25.0;
118
119 switch (keyCode) {
120 case KeyCodes.KEY_RIGHT:
121 trackGroup.getPropertyWriter().scrollTrackWindow(scrollPercentage);
122 event.getNativeEvent().preventDefault();
123 break;
124 case KeyCodes.KEY_LEFT:
125 trackGroup.getPropertyWriter().scrollTrackWindow(-scrollPercentage);
126 event.getNativeEvent().preventDefault();
127 break;
128 case KeyCodes.KEY_UP:
129 trackGroup.getPropertyWriter().scaleUpTrackWindow();
130 event.getNativeEvent().preventDefault();
131 break;
132 case KeyCodes.KEY_DOWN:
133 trackGroup.getPropertyWriter().scaleDownTrackWindow();
134 event.getNativeEvent().preventDefault();
135 break;
136 }
137
138 }
139 break;
140 }
141
142 }
143
144 }
145
146 public void onModuleLoad() {
147 RPCServiceManager.initServices();
148 queryParam = BrowserInfo.getURLQueryRequestParameters();
149 RootPanel.get().setStyleName("utgb");
150
151 basePanel.add(trackQueue, DockPanel.CENTER);
152
153 History.addValueChangeHandler(new HistoryChangeHandler());
154 Event.addNativePreviewHandler(new KeyboardShortcut());
155
156
157 Window.addResizeHandler(new ResizeHandler() {
158
159 public void onResize(ResizeEvent e) {
160 adjustTrackWidth();
161
162 }
163 });
164
165
166 main();
167
168 if (BrowserInfo.isIE()) {
169 showErrorMessage("IE does not support canvas feature in HTML5 for drawing grpahics in the browser, so we strongly recommend you to use another browser supporting HTML5, e.g., Google Chrome, Firefox, Safari, Opera, etc.");
170 }
171
172 }
173
174 public static int computeTrackWidth() {
175 int newBrowserWidth = Window.getClientWidth();
176 return Math.max((int) (newBrowserWidth * 0.95) - TrackFrame.INFOPANEL_WIDTH, 150);
177 }
178
179 private void adjustTrackWidth() {
180 int newTrackWidth = computeTrackWidth();
181 for (TrackGroup g : trackGroup.getTrackGroupList()) {
182 g.setTrackWindowWidth(newTrackWidth);
183 }
184
185 }
186
187 public void displayTrackView() {
188
189 if (queryParam.containsKey("view")) {
190 loadView(queryParam.get("view"));
191 }
192 else {
193 loadView("default-view");
194 }
195
196 RootPanel rootPanel = RootPanel.get("utgb-main");
197 if (rootPanel != null) {
198 rootPanel.add(basePanel);
199 }
200 else {
201 RootPanel.get().add(new Label("Error: <div id=\"utgb-main\"></div> tag is not found in this HTML file."));
202 }
203 }
204
205
206
207
208
209
210 public void loadView(String viewName) {
211
212 RPCServiceManager.getRPCService().getTrackView(viewName, new AsyncCallback<TrackView>() {
213 public void onFailure(Throwable e) {
214 showErrorMessage("failed to load view: " + e.getMessage());
215 }
216
217 public void onSuccess(TrackView v) {
218 try {
219 mainGroup = TrackGroup.createTrackGroup(v);
220
221
222 String hash = BrowserInfo.getHash();
223 if (hash != null && hash.length() > 0)
224 hash = hash.substring(1);
225 setQueryParam(mainGroup, hash);
226 trackGroup.addTrackGroup(mainGroup);
227 mainGroup.addTrackGroupPropertyChangeListener(new URLRewriter(mainGroup));
228 }
229 catch (UTGBClientException e) {
230 showErrorMessage("failed to load view: " + e.getMessage());
231 GWT.log(e.getMessage(), e);
232 }
233 }
234 });
235
236 }
237
238 private static class URLRewriter implements TrackGroupPropertyChangeListener {
239 public final TrackGroup group;
240
241 public URLRewriter(TrackGroup group) {
242 this.group = group;
243 }
244
245 public void onChange(TrackGroupPropertyChange change, TrackWindow newWindow) {
246 if (newWindow != null || (change != null && change.containsOneOf(UTGBProperty.coordinateParameters)))
247 setBrowserURL();
248 }
249
250 public void setBrowserURL() {
251 ArrayList<String> prop = new ArrayList<String>();
252
253 TrackGroupProperty propertyReader = group.getPropertyReader();
254 TrackWindow w = group.getTrackWindow();
255 prop.add("start=" + w.getStartOnGenome());
256 prop.add("end=" + w.getEndOnGenome());
257
258 for (String key : propertyReader.keySet()) {
259 prop.add(key + "=" + propertyReader.getProperty(key));
260 }
261
262 String n = StringUtil.join(prop, ";");
263 String prev = History.getToken();
264
265 if (prev != null && prev.equals(n))
266 return;
267 else {
268 History.newItem(n, false);
269 String s = propertyReader.getProperty(UTGBProperty.TARGET) + ":" + w.getStartOnGenome() + "-" + w.getEndOnGenome();
270 Window.setTitle(s + " - UTGB");
271 }
272
273 }
274
275 }
276
277 private class HistoryChangeHandler implements ValueChangeHandler<String> {
278
279 public HistoryChangeHandler() {
280 }
281
282 public void onValueChange(ValueChangeEvent<String> e) {
283 if (mainGroup != null)
284 setQueryParam(mainGroup, e.getValue());
285 }
286 }
287
288 private static void setQueryParam(TrackGroup group, String queryParam) {
289 TrackWindow w = group.getTrackWindow();
290
291 Properties p = getProperties(queryParam);
292 if (p.containsKey("start")) {
293 int start = Integer.parseInt(p.get("start"));
294 int end = p.containsKey("end") ? Integer.parseInt(p.get("end")) : start + 1000;
295 w = w.newWindow(start, end);
296 }
297
298 p.remove("start");
299 p.remove("end");
300
301 group.getPropertyWriter().setProperty(p, w);
302 }
303
304 private static Properties getProperties(String query) {
305 Properties properties = new Properties();
306 if (query == null || query.length() < 1)
307 return properties;
308
309 String[] keyAndValue = query.split(";");
310 for (int i = 0; i < keyAndValue.length; i++) {
311 String[] kv = keyAndValue[i].split("=");
312 if (kv.length > 1)
313 properties.put(kv[0], BrowserInfo.unescape(kv[1]));
314 else
315 properties.put(kv[0], "");
316 }
317
318 return properties;
319
320 }
321
322 public void main() {
323 displayTrackView();
324 }
325
326 private static RoundCornerFrame errorFrame;
327 private static Label errorLabel = new Label();
328 private static PopupPanel errorPopup = new PopupPanel(true);
329 {
330 errorFrame = new RoundCornerFrame("FF6699", 0.7f, 2);
331 errorFrame.setWidth("400px");
332 errorFrame.setWidget(errorLabel);
333 Style.fontColor(errorLabel, "white");
334 errorPopup.setWidget(errorFrame);
335 }
336
337 public static void showErrorMessage(final String message) {
338
339 DeferredCommand.addCommand(new Command() {
340
341 public void execute() {
342 errorLabel.setText(message);
343 int x = Window.getClientWidth() / 2 - 200;
344 int y = 10;
345 errorPopup.setPopupPosition(x, y);
346 errorPopup.show();
347 }
348 });
349 }
350
351 public static void hideLoadingMessage() {
352 Element _loadingMessage = DOM.getElementById("loading");
353 if (_loadingMessage != null) {
354 RootPanel.setVisible(_loadingMessage, false);
355 }
356 }
357
358 public static void showLoadingMessage() {
359 Element _loadingMessage = DOM.getElementById("loading");
360 if (_loadingMessage != null) {
361 RootPanel.setVisible(_loadingMessage, true);
362 }
363 }
364
365 }