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.track;
26
27 import org.utgenome.gwt.utgb.client.ui.Icon;
28 import org.utgenome.gwt.utgb.client.ui.IconImage;
29 import org.utgenome.gwt.utgb.client.util.Optional;
30 import org.utgenome.gwt.widget.client.Style;
31
32 import com.google.gwt.event.dom.client.ClickEvent;
33 import com.google.gwt.event.dom.client.ClickHandler;
34 import com.google.gwt.event.dom.client.HasAllMouseHandlers;
35 import com.google.gwt.event.dom.client.MouseDownEvent;
36 import com.google.gwt.event.dom.client.MouseDownHandler;
37 import com.google.gwt.event.dom.client.MouseMoveEvent;
38 import com.google.gwt.event.dom.client.MouseMoveHandler;
39 import com.google.gwt.event.dom.client.MouseOutEvent;
40 import com.google.gwt.event.dom.client.MouseOutHandler;
41 import com.google.gwt.event.dom.client.MouseOverEvent;
42 import com.google.gwt.event.dom.client.MouseOverHandler;
43 import com.google.gwt.event.dom.client.MouseUpEvent;
44 import com.google.gwt.event.dom.client.MouseUpHandler;
45 import com.google.gwt.user.client.DOM;
46 import com.google.gwt.user.client.Event;
47 import com.google.gwt.user.client.ui.AbsolutePanel;
48 import com.google.gwt.user.client.ui.Composite;
49 import com.google.gwt.user.client.ui.DockPanel;
50 import com.google.gwt.user.client.ui.HTML;
51 import com.google.gwt.user.client.ui.HorizontalPanel;
52 import com.google.gwt.user.client.ui.Image;
53 import com.google.gwt.user.client.ui.Label;
54 import com.google.gwt.user.client.ui.ScrollPanel;
55 import com.google.gwt.user.client.ui.SimplePanel;
56 import com.google.gwt.user.client.ui.VerticalPanel;
57
58
59
60
61
62
63
64
65 public class TrackFrame extends SimplePanel {
66 public static final int SCROLLBAR_WIDTH = 25;
67 public static final int INFOPANEL_WIDTH = 250;
68 private static IconImage _dragBarIcon = Design.getIconImage(Design.TRACK_BORDER_V);
69 private static IconImage _resizeBarIcon = Design.getIconImage(Design.TRACK_BORDER_H);
70
71 class DragBar extends Image implements MouseOverHandler, MouseOutHandler {
72 public DragBar() {
73 super(_dragBarIcon.getImageURL());
74 setStyleName("drag-bar");
75 setSize("4px", "100%");
76 setTitle("drag & drop to change track order");
77 }
78
79 public void register(HasAllMouseHandlers w) {
80 w.addMouseOverHandler(this);
81 w.addMouseOutHandler(this);
82 }
83
84 public void onMouseOver(MouseOverEvent e) {
85 setUrl(_dragBarIcon.getMouseOverImageURL());
86 }
87
88 public void onMouseOut(MouseOutEvent e) {
89 setUrl(_dragBarIcon.getImageURL());
90 }
91
92 @Override
93 protected void onAttach() {
94 super.onAttach();
95 setUrl(_dragBarIcon.getImageURL());
96 }
97 }
98
99 class ResizeBar extends Image implements MouseMoveHandler, MouseOverHandler, MouseOutHandler, MouseDownHandler, MouseUpHandler {
100 private TrackFrame _targetFrame;
101 private boolean isMouseDown = false;
102 private int initialY_Position = 0;
103 private int initial_height = 0;
104 private boolean enabled = true;
105
106 public ResizeBar(final TrackFrame targetWidget) {
107 super(_resizeBarIcon.getImageURL());
108 this._targetFrame = targetWidget;
109 setStyleName("drag-bar");
110 setSize(INFOPANEL_WIDTH + "px", "2px");
111 enableResize();
112 setTitle("Drag this bar to resize tracks");
113
114 register(this);
115 }
116
117 private void register(HasAllMouseHandlers w) {
118 w.addMouseMoveHandler(this);
119
120 w.addMouseUpHandler(this);
121 w.addMouseDownHandler(this);
122
123 w.addMouseOverHandler(this);
124 w.addMouseOutHandler(this);
125 }
126
127 public void onMouseMove(MouseMoveEvent e) {
128 if (!enabled)
129 return;
130
131 if (isMouseDown) {
132 final int diff = (e.getScreenY()) - initialY_Position;
133 final int newSize = initial_height + diff;
134 _targetFrame.resize(newSize);
135 _frameState.setPreviousFrameHeight(newSize);
136 }
137 }
138
139 public void onMouseUp(MouseUpEvent e) {
140 if (!enabled)
141 return;
142
143 if (isMouseDown) {
144 isMouseDown = false;
145 unpack();
146 _frameState.setMinimized(false);
147 hideButton.update();
148 }
149 Event.releaseCapture(e.getRelativeElement());
150 }
151
152 public void onMouseDown(MouseDownEvent e) {
153 if (!enabled)
154 return;
155
156 isMouseDown = true;
157 initialY_Position = e.getScreenY();
158 initial_height = _targetFrame.getOffsetHeight();
159 Event.setCapture(e.getRelativeElement());
160 }
161
162 public void onMouseOver(MouseOverEvent e) {
163 if (!enabled)
164 return;
165
166 setUrl(_resizeBarIcon.getMouseOverImageURL());
167 }
168
169 public void onMouseOut(MouseOutEvent e) {
170 if (!enabled)
171 return;
172
173 setUrl(_resizeBarIcon.getImageURL());
174 }
175
176 public void disableResize() {
177 enabled = false;
178 DOM.setStyleAttribute(this.getElement(), "cursor", "default");
179 }
180
181 public void enableResize() {
182 enabled = true;
183 DOM.setStyleAttribute(this.getElement(), "cursor", "n-resize");
184 }
185 }
186
187 class WindowButton extends Icon {
188 IconImage _icon;
189
190 public WindowButton(IconImage icon) {
191 super(icon);
192
193 }
194 }
195
196 class ConfigButton extends WindowButton implements MouseDownHandler {
197 public ConfigButton() {
198 super(Design.getIconImage(Design.ICON_CONFIG));
199 setTitle("config");
200
201 addMouseDownHandler(this);
202 }
203
204 public void onMouseDown(MouseDownEvent e) {
205 TrackConfig configPopup = _track.getConfig();
206 assert (configPopup != null);
207 configPopup.setPopupPosition(this.getAbsoluteLeft() + 2, this.getAbsoluteTop() + 13);
208 configPopup.show();
209 }
210 }
211
212 class HideButton extends WindowButton implements ClickHandler {
213
214
215
216
217 public HideButton() {
218 super(Design.getIconImage(Design.ICON_HIDE));
219 setTitle("minimize");
220 addClickHandler(this);
221 }
222
223 public void onClick(ClickEvent e) {
224 switchMinimization();
225 update();
226 }
227
228 public void update() {
229 if (_frameState.isMinimized()) {
230 setIcon(Design.getIconImage(Design.ICON_SHOW));
231 setTitle("restore");
232 }
233 else {
234 setIcon(Design.getIconImage(Design.ICON_HIDE));
235 setTitle("minimize");
236 }
237 }
238 }
239
240 class PackButton extends WindowButton implements ClickHandler {
241 public PackButton() {
242 super(Design.getIconImage(Design.ICON_PACK));
243 setTitle("adjust height");
244 addClickHandler(this);
245 }
246
247 public void onClick(ClickEvent e) {
248 switchPackUnpack();
249 update();
250 }
251
252 public void update() {
253
254 updateIcon();
255 }
256
257 public void updateIcon() {
258 if (_trackWidgetFrame.getOffsetHeight() <= _layoutPanel.getOffsetHeight())
259 setIcon(Design.getIconImage(Design.ICON_PACK));
260 else
261 setIcon(Design.getIconImage(Design.ICON_UNPACK));
262 }
263 }
264
265 class CloseButton extends WindowButton implements ClickHandler {
266 TrackFrame _frame;
267
268 public CloseButton(TrackFrame frame) {
269 super(Design.getIconImage(Design.ICON_CLOSE));
270 setTitle("close");
271 this._frame = frame;
272 addClickHandler(this);
273 }
274
275 public void onClick(ClickEvent e) {
276 getTrack().getTrackGroup().removeTrack(_track);
277 }
278 }
279
280 private final Track _track;
281 private final HorizontalPanel _layoutPanel = new HorizontalPanel();
282 private final DragBar _dragBar = new DragBar();
283 private final ResizeBar _resizeBar = new ResizeBar(this);
284 private final TrackInfoPanel _infoPanel;
285 private final ScrollPanel _scrollPanel = new ScrollPanel();
286 private final DockPanel _trackWidgetFrame = new DockPanel();
287 private final Label _messageLabel = new Label();
288 private final ConfigButton configButton = new ConfigButton();
289 private final HideButton hideButton = new HideButton();
290 private final PackButton packButton = new PackButton();
291 private final CloseButton closeButton = new CloseButton(this);
292 TrackFrameState _frameState = new TrackFrameState();
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310 class TrackInfoPanel extends Composite implements TrackInfoChangeListener {
311 private final AbsolutePanel basePanel = new AbsolutePanel();
312 private final HorizontalPanel _labelFrame = new HorizontalPanel();
313 private final VerticalPanel frameWithResizeBar = new VerticalPanel();
314 private final Image _loadingIcon = new Image(Design.IMAGE_NOW_LOADING);
315 private final HTML _trackLabel = new HTML();
316 private final int DRAGBAR_WIDTH = 4;
317 private final int RESIZE_BAR_HEIGHT = 2;
318 private boolean _disablePackButton = false;
319 private Optional<Boolean> _disableConfigButton = new Optional<Boolean>();
320 private boolean _disableCloseButton = false;
321 private boolean _disableHideButton = false;
322 private boolean _nowLoading = false;
323
324 public TrackInfoPanel(TrackFrame trackFrame, int height) {
325 String h = height + "px";
326 basePanel.setStyleName("track-info");
327 basePanel.setSize(INFOPANEL_WIDTH + "px", h);
328
329 basePanel.add(_dragBar, 0, 0);
330 _dragBar.register(_trackLabel);
331
332
333 _trackLabel.setStyleName("track-label");
334 _trackLabel.setWidth((INFOPANEL_WIDTH - 20) + "px");
335 Style.trimOverflowedText(_trackLabel);
336
337 updateTrackLabel();
338 _labelFrame.setSize("100%", "100%");
339 _labelFrame.setVerticalAlignment(HorizontalPanel.ALIGN_MIDDLE);
340 _labelFrame.setHorizontalAlignment(HorizontalPanel.ALIGN_LEFT);
341 _labelFrame.add(_trackLabel);
342
343 frameWithResizeBar.setSize((INFOPANEL_WIDTH - DRAGBAR_WIDTH) + "px", "100%");
344 frameWithResizeBar.setVerticalAlignment(VerticalPanel.ALIGN_BOTTOM);
345 frameWithResizeBar.add(_labelFrame);
346 frameWithResizeBar.add(_resizeBar);
347 basePanel.add(frameWithResizeBar, DRAGBAR_WIDTH, 0);
348
349 drawIcon();
350
351 getTrack().getTrackInfo().addChangeListener(this);
352 initWidget(basePanel);
353 }
354
355 void disablePackButton() {
356 _disablePackButton = true;
357 basePanel.remove(packButton);
358 drawIcon();
359 }
360
361 void disableConfigButton() {
362 _disableConfigButton.set(true);
363 basePanel.remove(configButton);
364 drawIcon();
365 }
366
367 void enableConfigButton() {
368 _disableConfigButton.set(false);
369 drawIcon();
370 }
371
372 void disableCloseButton() {
373 _disableCloseButton = true;
374 basePanel.remove(closeButton);
375 drawIcon();
376 }
377
378 void disableHideButton() {
379 _disableHideButton = true;
380 basePanel.remove(hideButton);
381 drawIcon();
382 }
383
384 static final int ICON_WIDTH = 15 + 1;
385
386 void drawIcon() {
387 final int yOffset = 1;
388 int xPos = INFOPANEL_WIDTH;
389 if (!_disableCloseButton) {
390 xPos -= ICON_WIDTH;
391 basePanel.add(closeButton, xPos, yOffset);
392 }
393 if (!_disableHideButton) {
394 xPos -= ICON_WIDTH;
395 basePanel.add(hideButton, xPos, yOffset);
396 }
397 if (!_disablePackButton) {
398 xPos -= ICON_WIDTH;
399 basePanel.add(packButton, xPos, yOffset);
400 }
401 if (!isDisabledConfigButton()) {
402 xPos -= ICON_WIDTH;
403 basePanel.add(configButton, xPos, yOffset);
404 }
405 }
406
407 private boolean isDisabledConfigButton() {
408 if (_disableConfigButton.isDefined())
409 return !_disableConfigButton.get();
410 else {
411 return !(_track.getConfig() != null && _track.getConfig().hasProperties());
412 }
413 }
414
415 public void nowLoading(boolean nowLoading) {
416 _nowLoading = nowLoading;
417 if (_nowLoading) {
418 int xPos = INFOPANEL_WIDTH;
419 int numIcon = 0;
420 if (!_disableCloseButton)
421 numIcon++;
422 if (!_disableHideButton)
423 numIcon++;
424 if (!_disablePackButton)
425 numIcon++;
426 if (!isDisabledConfigButton())
427 numIcon++;
428 xPos -= ICON_WIDTH * (numIcon + 1);
429 basePanel.add(_loadingIcon, xPos, 1);
430 }
431 else {
432 basePanel.remove(_loadingIcon);
433 }
434 }
435
436 void updateTrackLabel() {
437 TrackInfo info = getTrack().getTrackInfo();
438 _trackLabel.setText(info.getTrackName());
439 _trackLabel.setTitle(info.getTrackName() + ": " + info.getDescription());
440
441 String linkURL = info.getLinkURL();
442 if (linkURL.length() > 0) {
443 _trackLabel.setHTML("<a href=\"" + linkURL + "\" target=\"_blank\">" + info.getTrackName() + "</a>");
444 }
445 }
446
447 public void onChange(TrackInfo info) {
448 updateTrackLabel();
449 }
450 }
451
452 public TrackFrame(Track track, int width, int height) {
453 this._track = track;
454 _frameState.setMinFrameHeight(track.getMinimumWindowHeight());
455 _frameState.setPreviousFrameHeight(height);
456 _infoPanel = new TrackInfoPanel(this, height);
457
458
459
460
461 _layoutPanel.add(_infoPanel);
462
463
464 _trackWidgetFrame.setWidth("100%");
465 _trackWidgetFrame.setStyleName("track");
466 _trackWidgetFrame.add(_track.getWidget(), DockPanel.CENTER);
467 _messageLabel.setStyleName("trackframe-message");
468 _messageLabel.setWidth("100%");
469 _messageLabel.setHorizontalAlignment(Label.ALIGN_CENTER);
470 _scrollPanel.setWidget(_trackWidgetFrame);
471 _scrollPanel.setSize((width + SCROLLBAR_WIDTH) + "px", height + "px");
472 _layoutPanel.add(_scrollPanel);
473 this.add(_layoutPanel);
474 setFrameHeight(height);
475 _track.setFrame(this);
476 }
477
478 public TrackFrame(Track track, int width) {
479 this(track, width, track.getDefaultWindowHeight());
480 }
481
482 public void setFrameHeight(int height) {
483 String h = _frameState.resizeFrameHeight(height) + "px";
484 _infoPanel.setHeight(h);
485 _scrollPanel.setHeight(h);
486 _layoutPanel.setHeight(h);
487 }
488
489 public int getContentHeight() {
490 if (_frameState.isMinimized())
491 return _frameState.getPreviousFrameHeight();
492 else
493 return _scrollPanel.getOffsetHeight();
494 }
495
496 public void resize(int height) {
497 setFrameHeight(height);
498 packButton.updateIcon();
499 _track.getTrackGroup().notifyResize();
500 _track.onChangeTrackHeight(height);
501 }
502
503 public void adjustFrameHeight() {
504 if (_frameState.isPacked()) {
505
506 int newHeight = _trackWidgetFrame.getOffsetHeight();
507 setFrameHeight(newHeight);
508 }
509 resizeTrackAreaWidth(_track.getTrackGroup().getTrackWindow().getPixelWidth());
510 }
511
512 public void onUpdateTrackWidget() {
513 adjustFrameHeight();
514 packButton.updateIcon();
515 _track.getTrackGroup().notifyResize();
516 }
517
518 public void resizeTrackAreaWidth(int newWidth) {
519 _scrollPanel.setWidth((newWidth + SCROLLBAR_WIDTH) + "px");
520 }
521
522 public void open() {
523 if (_frameState.isMinimized())
524 switchMinimization();
525 }
526
527 public void minimize() {
528 if (!_frameState.isMinimized()) {
529 switchMinimization();
530 }
531 }
532
533 private int appropriateWidgetHeight(boolean toMinimize, boolean toPack) {
534 if (toMinimize)
535
536 return TrackFrameState.DEFAULT_MIN_TRACKFRAME_HEIGHT;
537 else if (toPack) {
538 if (_frameState.isMinimized())
539 return _frameState.getPreviousFrameHeight();
540 else
541
542 return _trackWidgetFrame.getOffsetHeight();
543 }
544 else
545 return _frameState.getPreviousFrameHeight();
546 }
547
548 public void switchMinimization() {
549 int height = appropriateWidgetHeight(!_frameState.isMinimized(), _frameState.isPacked());
550 if (_frameState.isMinimized()) {
551
552 }
553 else {
554 _frameState.setPreviousFrameHeight(this.getOffsetHeight());
555
556 }
557 _frameState.setMinimized(!_frameState.isMinimized());
558 resize(height);
559 hideButton.update();
560 }
561
562 public void switchPackUnpack() {
563 open();
564 int height = appropriateWidgetHeight(_frameState.isMinimized(), !_frameState.isPacked());
565 resize(height);
566 _frameState.setPacked(!_frameState.isPacked());
567 packButton.update();
568 }
569
570
571
572
573 public void pack() {
574 if (!_frameState.isPacked())
575 switchPackUnpack();
576 }
577
578
579
580
581 public void unpack() {
582 if (_frameState.isPacked())
583 switchPackUnpack();
584 }
585
586 public void setPacked(boolean packed) {
587 if (packed)
588 pack();
589 else
590 unpack();
591 }
592
593 public void enableConfig() {
594 _infoPanel.enableConfigButton();
595 }
596
597 public void disableConfig() {
598 _infoPanel.disableConfigButton();
599 }
600
601 public boolean isPacked() {
602 return _frameState.isPacked();
603 }
604
605 public void disablePack() {
606 _infoPanel.disablePackButton();
607 }
608
609 public void disableResize() {
610 _resizeBar.disableResize();
611 }
612
613 public void enableResize() {
614 _resizeBar.enableResize();
615 }
616
617 public void disableClose() {
618 _infoPanel.disableCloseButton();
619 }
620
621 public void disableHide() {
622 _infoPanel.disableHideButton();
623 }
624
625 public Track getTrack() {
626 return _track;
627 }
628
629 public Label getFrameBar() {
630 return _infoPanel._trackLabel;
631 }
632
633 public Label getMessageLabel() {
634 return _messageLabel;
635 }
636
637 public void setVisibleMessageLabel(final boolean visible) {
638 if (visible) {
639 if (_trackWidgetFrame.getWidgetIndex(_messageLabel) == -1) {
640 _trackWidgetFrame.add(_messageLabel, DockPanel.NORTH);
641 }
642 _messageLabel.setText("");
643 }
644 else {
645 if (_trackWidgetFrame.getWidgetIndex(_messageLabel) != -1) {
646 _trackWidgetFrame.remove(_messageLabel);
647 }
648 }
649 }
650
651 public void writeMessage(String message) {
652 if (_trackWidgetFrame.getWidgetIndex(_messageLabel) == -1) {
653 _trackWidgetFrame.add(_messageLabel, DockPanel.NORTH);
654 }
655 _messageLabel.setText(message);
656 }
657
658 public void eraseMessage(boolean eraseLabel) {
659 if (_trackWidgetFrame.getWidgetIndex(_messageLabel) != -1) {
660 if (eraseLabel)
661 _trackWidgetFrame.remove(_messageLabel);
662 else
663 _messageLabel.setText("");
664 }
665 }
666
667 public void setFrameState(TrackFrameState frameState) {
668 _frameState = frameState;
669 packButton.update();
670 hideButton.update();
671
672 }
673
674 public void setNowLoading() {
675 _infoPanel.nowLoading(true);
676 }
677
678 public void loadingDone() {
679 _infoPanel.nowLoading(false);
680 }
681 }