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.layout.lazylayout.widget;
35
36 import info.magnolia.ui.vaadin.gwt.client.jquerywrapper.JQueryWrapper;
37 import info.magnolia.ui.vaadin.gwt.client.layout.lazylayout.connector.ThumbnailLayoutState;
38 import info.magnolia.ui.vaadin.gwt.client.layout.lazylayout.connector.ThumbnailService;
39 import info.magnolia.ui.vaadin.gwt.client.pinch.MagnoliaPinchRecognizer;
40 import info.magnolia.ui.vaadin.gwt.client.pinch.MagnoliaPinchStartEvent;
41 import info.magnolia.ui.vaadin.gwt.shared.Range;
42
43 import java.util.Deque;
44 import java.util.HashSet;
45 import java.util.LinkedList;
46 import java.util.List;
47 import java.util.Set;
48 import java.util.stream.IntStream;
49
50 import com.google.gwt.core.client.Scheduler;
51 import com.google.gwt.dom.client.DivElement;
52 import com.google.gwt.dom.client.Element;
53 import com.google.gwt.dom.client.ImageElement;
54 import com.google.gwt.dom.client.NativeEvent;
55 import com.google.gwt.dom.client.SpanElement;
56 import com.google.gwt.dom.client.Style;
57 import com.google.gwt.event.dom.client.ClickEvent;
58 import com.google.gwt.event.dom.client.ContextMenuEvent;
59 import com.google.gwt.event.dom.client.ScrollEvent;
60 import com.google.gwt.event.dom.client.ScrollHandler;
61 import com.google.gwt.user.client.DOM;
62 import com.google.gwt.user.client.ui.FlowPanel;
63 import com.google.gwt.user.client.ui.ScrollPanel;
64 import com.googlecode.mgwt.dom.client.recognizer.pinch.UIObjectToOffsetProvider;
65 import com.googlecode.mgwt.dom.client.recognizer.tap.MultiTapEvent;
66 import com.googlecode.mgwt.dom.client.recognizer.tap.MultiTapRecognizer;
67 import com.googlecode.mgwt.ui.client.widget.touch.TouchDelegate;
68 import com.vaadin.client.Util;
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 public class EscalatorPanel extends FlowPanel {
85
86 private static final String THUMBNAIL_LAYOUT_STYLE_NAME = "thumbnail-layout";
87 private static final String THUMBNAIL_SCROLLER_STYLE_NAME = "thumbnail-scroller";
88 private static final String THUMBNAIL_VIEWPORT_STYLE_NAME = "thumbnail-viewport";
89 private static final String THUMBNAIL_PLACEHOLDER_STYLE_NAME = "placeholder";
90 private static final String THUMBNAIL_STYLE_NAME = "thumbnail";
91
92
93
94
95 public interface Listener {
96
97 void onThumbnailClicked(int index, boolean isMetaKeyPressed, boolean isShiftKeyPressed);
98
99 void onThumbnailRightClicked(int index, int xPos, int yPos);
100
101 void onThumbnailDoubleClicked(int index);
102
103 }
104
105 private Flyweight flyweight;
106
107 private final ScrollPanel scroller = new ScrollPanel();
108
109 private final DivElement imageContainer = DivElement.as(DOM.createDiv());
110
111 private final DivElement upperSpacer = DivElement.as(DOM.createDiv());
112
113 private final DivElement lowerSpacer = DivElement.as(DOM.createDiv());
114
115 private ThumbnailService thumbnailService;
116
117 private Deque<Element> floatingThumbnails = new LinkedList<>();
118
119 private int absoluteOffset = 0;
120
121 private int thumbnailAmount;
122
123 private int thumbnailsInRow;
124
125 private int rowsInViewport;
126
127 private ThumbnailsSizeKeeper size;
128
129 private boolean isScrollProcessorLocked = false;
130
131 private Listener listener;
132
133 private final Slidert/client/layout/lazylayout/widget/Slider.html#Slider">Slider thumbnailSizeSlider = new Slider();
134
135 private final ScrollHandler scrollHandler = new ScrollHandler() {
136
137 private int lastScrollTop = 0;
138
139 @Override
140 public void onScroll(ScrollEvent event) {
141 if (isScrollProcessorLocked) {
142 return;
143 }
144 int newScrollTop = event.getRelativeElement().getScrollTop();
145 int delta = lastScrollTop - newScrollTop;
146 escalate(newScrollTop, delta);
147 lastScrollTop = newScrollTop;
148 }
149 };
150
151
152
153
154
155 private void escalate(int newScrollTop, int delta) {
156 int lsHeight = lowerSpacer.getOffsetHeight();
157 int usHeight = upperSpacer.getOffsetHeight();
158
159 int thumbnailHeight = size.height();
160
161 boolean moveOccurred = false;
162
163 if (delta != 0) {
164
165
166
167
168 if (delta < 0) {
169 while (newScrollTop - usHeight >= thumbnailHeight && lsHeight > 0) {
170 moveOccurred = true;
171
172 usHeight += thumbnailHeight;
173 lsHeight -= thumbnailHeight;
174
175 this.absoluteOffset = usHeight / size.height() * thumbnailsInRow;
176
177
178 if (!areAllVisibleThumbnailsCleared()) {
179 releaseThumbnailRow(true);
180 addStubs(Range.withLength(getCurrentlyDisplayedThumbnails(), thumbnailsInRow));
181 }
182 }
183 } else {
184
185
186
187 while (usHeight - newScrollTop > 0 && usHeight > 0) {
188 moveOccurred = true;
189
190 usHeight -= thumbnailHeight;
191 lsHeight += thumbnailHeight;
192
193 this.absoluteOffset = usHeight / size.height() * thumbnailsInRow;
194
195
196 if (!areAllVisibleThumbnailsCleared()) {
197 releaseThumbnailRow(false);
198 addStubs(Range.between(0, thumbnailsInRow));
199 }
200 }
201 }
202 }
203
204 if (moveOccurred) {
205 setSpacersHeight(usHeight, lsHeight);
206 resize();
207 }
208 }
209
210 public EscalatorPanel(final Listener listener, Flyweight flyweight) {
211 this.listener = listener;
212 this.flyweight = flyweight;
213
214 final TouchDelegatent/widget/touch/TouchDelegate.html#TouchDelegate">TouchDelegate touchDelegate = new TouchDelegate(this);
215 touchDelegate.addTouchHandler(new MagnoliaPinchRecognizer(touchDelegate, new UIObjectToOffsetProvider(scroller)));
216 MultiTapRecognizerizer/tap/MultiTapRecognizer.html#MultiTapRecognizer">MultiTapRecognizer multitapRecognizer = new MultiTapRecognizer(touchDelegate, 1, 2);
217 touchDelegate.addTouchHandler(multitapRecognizer);
218
219 addHandler(event -> {
220
221
222
223
224 }, MagnoliaPinchStartEvent.TYPE);
225
226 addDomHandler(event -> {
227 final NativeEvent nativeEvent = event.getNativeEvent();
228 final Element element = findThumbnail(Element.as(nativeEvent.getEventTarget()));
229 if (element != null) {
230 boolean isMetaKeyPressed = nativeEvent.getMetaKey();
231 boolean isShiftPressed = nativeEvent.getShiftKey();
232 EscalatorPanel.this.listener.onThumbnailClicked(
233 getThumbnailIndex(element),
234 isMetaKeyPressed,
235 isShiftPressed);
236 }
237 }, ClickEvent.getType());
238
239 addDomHandler(event -> {
240 Element thumbnail = findThumbnail(Element.as(event.getNativeEvent().getEventTarget()));
241 if (thumbnail != null) {
242 EscalatorPanel.this.listener.onThumbnailRightClicked(
243 getThumbnailIndex(thumbnail),
244 event.getNativeEvent().getClientX(),
245 event.getNativeEvent().getClientY());
246 }
247 }, ContextMenuEvent.getType());
248
249 addHandler(event -> {
250 int x = event.getTouchStarts().get(0).get(0).getPageX();
251 int y = event.getTouchStarts().get(0).get(0).getPageY();
252 final Element thumbnail = findThumbnail(Util.getElementFromPoint(x, y));
253 if (thumbnail != null) {
254 EscalatorPanel.this.listener.onThumbnailDoubleClicked(getThumbnailIndex(thumbnail));
255 }
256 }, MultiTapEvent.getType());
257
258 thumbnailSizeSlider.addValueChangeHandler(event -> scale(event.getValue().floatValue() / 100f));
259
260 add(thumbnailSizeSlider);
261
262 this.size = new ThumbnailsSizeKeeper(imageContainer);
263
264 addStyleName(THUMBNAIL_LAYOUT_STYLE_NAME);
265 imageContainer.addClassName(THUMBNAIL_VIEWPORT_STYLE_NAME);
266
267 scroller.getElement().appendChild(imageContainer);
268 scroller.addStyleName(THUMBNAIL_SCROLLER_STYLE_NAME);
269 scroller.addScrollHandler(scrollHandler);
270
271 scroller.getElement().insertFirst(upperSpacer);
272 scroller.getElement().insertAfter(lowerSpacer, imageContainer);
273
274 add(scroller);
275
276 }
277
278 public EscalatorPanel(Listener listener) {
279 this(listener, new Flyweight());
280 }
281
282 public final int getCurrentThumbnailOffset() {
283 return absoluteOffset;
284 }
285
286 public int getCurrentlyDisplayedThumbnails() {
287 return imageContainer.getChildCount() - getPlaceholderCount();
288 }
289
290 public void initialize(int thumbnailAmount, int offset, ThumbnailLayoutState.ThumbnailSize size, float scaleRatio, boolean isFirstUpdateFromState) {
291 this.imageContainer.removeAllChildren();
292
293 this.thumbnailAmount = thumbnailAmount;
294 this.size.updateAllElementsSize(size.width, size.height);
295
296 if (scaleRatio > 0) {
297 this.size.scale(scaleRatio);
298 } else {
299 this.size.scale(0.8f);
300 }
301
302
303 resize();
304
305 thumbnailSizeSlider.setValue(this.size.getScaleRatio() * 100d, false);
306 scroller.setVerticalScrollPosition((offset / thumbnailsInRow) * size.height);
307 }
308
309 public void setThumbnailService(ThumbnailService thumbnailService) {
310 this.thumbnailService = thumbnailService;
311 }
312
313 public void setThumbnailAmount(int amount) {
314 if (this.thumbnailAmount != amount) {
315 this.thumbnailAmount = amount;
316 resize();
317 }
318 }
319
320 public void setElementSize(int width, int height) {
321 if (size.updateAllElementsSize(width, height)) {
322 resize();
323 }
324 }
325
326 public Range getDisplayedRange() {
327 return Range.between(absoluteIndex(0), absoluteIndex(getCurrentlyDisplayedThumbnails()));
328 }
329
330 public void resize() {
331 int initialScrollTop = scroller.getVerticalScrollPosition();
332 int viewportWidth = getScrollableWidth();
333 int scrollerHeight = getScrollableHeight();
334 int thumbnailHeight = size.height();
335
336 if (scrollerHeight == 0 || viewportWidth == 0 || thumbnailHeight == 0) {
337 return;
338 }
339
340 int thumbnailWidth = size.width();
341 this.thumbnailsInRow = (int) Math.round((double) viewportWidth / thumbnailWidth);
342 int totalRows = (int) Math.ceil((double) thumbnailAmount / thumbnailsInRow);
343
344 int scaledWidth = viewportWidth / thumbnailsInRow - 1;
345 size.scaleToWidth(scaledWidth);
346 thumbnailHeight = size.height();
347
348 this.rowsInViewport = Math.min((int) Math.ceil((double) scrollerHeight / thumbnailHeight) + 1, totalRows);
349
350 final Range totalRange = Range.between(0, thumbnailAmount);
351
352 Range offsetRange = Range.between(0, absoluteOffset);
353 Range viewportActualRange = Range.withLength(absoluteOffset, getCurrentlyDisplayedThumbnails());
354 Range remainingRange = totalRange.partitionWith(viewportActualRange)[2];
355
356 removePlaceholders();
357
358 boolean rangesAreInOrder = false;
359
360
361
362
363
364
365 while (!rangesAreInOrder) {
366
367
368
369
370
371
372 int offsetRangeRemainder = offsetRange.length() % thumbnailsInRow;
373 if (offsetRangeRemainder != 0) {
374 addStubs(Range.withLength(relativeIndex(viewportActualRange.getStart()), offsetRangeRemainder));
375 offsetRange = offsetRange.expand(0, -offsetRangeRemainder);
376 viewportActualRange = viewportActualRange.expand(offsetRangeRemainder, 0);
377 absoluteOffset -= offsetRangeRemainder;
378 }
379
380
381
382
383
384 Range viewportCalculatedRange = Range.withLength(absoluteOffset, rowsInViewport * thumbnailsInRow);
385
386
387
388
389
390 final Range[] calculatedVsTotalRange = viewportCalculatedRange.partitionWith(totalRange);
391 final Range beyondTheTotalRange = calculatedVsTotalRange[2];
392
393
394
395
396 viewportCalculatedRange = calculatedVsTotalRange[1];
397
398
399
400
401 if (viewportCalculatedRange.isSubsetOf(viewportActualRange)) {
402
403 int overflow = viewportActualRange.partitionWith(viewportCalculatedRange)[2].length();
404 releaseThumbnails(Range.withLength(getCurrentlyDisplayedThumbnails() - overflow, overflow));
405 viewportActualRange = viewportActualRange.expand(0, -overflow);
406 remainingRange = remainingRange.expand(overflow, 0);
407
408
409
410 } else if (viewportActualRange.isSubsetOf(viewportCalculatedRange)) {
411
412 int lack = viewportCalculatedRange.partitionWith(viewportActualRange)[2].length();
413 addStubs(Range.withLength(getCurrentlyDisplayedThumbnails(), lack));
414 viewportActualRange = viewportActualRange.expand(0, lack);
415 remainingRange = remainingRange.expand(-lack, 0);
416 }
417
418
419
420
421
422 if (!beyondTheTotalRange.isEmpty()) {
423 int rowsToShift = (int) Math.floor((double) beyondTheTotalRange.length() / thumbnailsInRow);
424 int toQueryFromOffset = rowsToShift * thumbnailsInRow;
425 if (toQueryFromOffset > 0) {
426 absoluteOffset -= toQueryFromOffset;
427 offsetRange = offsetRange.expand(0, -toQueryFromOffset);
428 viewportActualRange = viewportActualRange.expand(toQueryFromOffset, 0);
429 addStubs(Range.between(0, toQueryFromOffset));
430 }
431 }
432
433
434
435 rangesAreInOrder = offsetRange.length() % thumbnailsInRow == 0;
436 }
437
438
439 int remainder = getCurrentlyDisplayedThumbnails() % thumbnailsInRow;
440 if (remainder > 0) {
441 IntStream.range(0, thumbnailsInRow - remainder).forEach($ ->
442 imageContainer.insertAfter(createThumbnailPlaceholder(size.width()), imageContainer.getLastChild()));
443 }
444
445
446
447
448
449 int usH = upperSpacer.getOffsetHeight();
450
451 int viewportHeight = rowsInViewport * thumbnailHeight;
452 int upperSpacerHeight = (int) Math.ceil(offsetRange.length() / thumbnailsInRow) * thumbnailHeight;
453 int lowerSpacerHeight = (int) Math.ceil(remainingRange.length() / thumbnailsInRow) * thumbnailHeight;
454
455
456 scroller.setHeight(scrollerHeight + "px");
457 scroller.getElement().getStyle().setOverflowX(Style.Overflow.HIDDEN);
458
459 imageContainer.getStyle().setWidth(viewportWidth, Style.Unit.PX);
460 imageContainer.getStyle().setHeight(viewportHeight, Style.Unit.PX);
461
462 setSpacersHeight(upperSpacerHeight, lowerSpacerHeight);
463
464
465
466
467 isScrollProcessorLocked = true;
468 scroller.setVerticalScrollPosition(initialScrollTop + upperSpacerHeight - usH);
469 Scheduler.get().scheduleFinally(() -> {
470 isScrollProcessorLocked = false;
471 return false;
472 });
473
474 updateViewport();
475 }
476
477 protected Element findThumbnail(Element element) {
478 if (element != imageContainer && element != null && imageContainer.isOrHasChild(element)) {
479 Element result = element;
480 while (result.getParentElement() != imageContainer) {
481 result = result.getParentElement();
482 }
483 return result;
484 }
485 return null;
486 }
487
488 public void updateImageCaption(String caption, int index) {
489 flyweight.setCaption(caption, Element.as(getImageContainer().getChild(relativeIndex(index))));
490 }
491
492 protected int getThumbnailIndex(Element element) {
493 return absoluteIndex(Util.getChildElementIndex(element));
494 }
495
496 protected void scale(float ratio) {
497 thumbnailService.onThumbnailsScaled(ratio);
498 size.scale(ratio);
499 resize();
500 }
501
502 private void addStubs(Range relativeRange) {
503 int currentThumbnailOffset = getCurrentThumbnailOffset();
504 final Range actualRange = relativeRange.expand(-currentThumbnailOffset, currentThumbnailOffset).restrictTo(Range.between(0, thumbnailAmount));
505
506 int relativeStartIndex = relativeIndex(actualRange.getStart());
507
508 Element previousElement = relativeStartIndex == 0 ? null : Element.as(imageContainer.getChild(relativeStartIndex - 1));
509 for (int i = 0; i < actualRange.length(); ++i) {
510 final Element stub = floatingThumbnails.isEmpty() ? flyweight.createThumbnail() : floatingThumbnails.pop();
511 size.applySizeToElement(stub);
512 if (previousElement == null) {
513 imageContainer.insertFirst(stub);
514 } else {
515 imageContainer.insertAfter(stub, previousElement);
516 }
517 previousElement = stub;
518 }
519 }
520
521 private void updateViewport() {
522 final Range visibleRange = Range.between(absoluteIndex(0), absoluteIndex(getCurrentlyDisplayedThumbnails()));
523 if (areAllVisibleThumbnailsCleared()) {
524 final Range availableRange = Range.between(0, thumbnailAmount);
525 if (!visibleRange.isSubsetOf(availableRange)) {
526 Range thumbnailsToRelease = visibleRange.partitionWith(availableRange)[2];
527 if (!thumbnailsToRelease.isEmpty()) {
528 for (int i = 0; i < thumbnailsToRelease.length(); ++i) {
529 clearThumbnail(Element.as(imageContainer.getLastChild()));
530 }
531 }
532 }
533 }
534 this.thumbnailService.onViewportChanged(Range.between(absoluteIndex(0), absoluteIndex(getCurrentlyDisplayedThumbnails())));
535 }
536
537 public void updateImageSource(String url, int index) {
538 flyweight.setImageSrc(url, Element.as(imageContainer.getChild(relativeIndex(index))));
539 }
540
541 public int relativeIndex(int index) {
542 return index - getCurrentThumbnailOffset();
543 }
544
545 private int absoluteIndex(int relativeIndex) {
546 return getCurrentThumbnailOffset() + relativeIndex;
547 }
548
549 private void releaseThumbnailRow(boolean inFront) {
550 for (int i = 0; i < thumbnailsInRow; ++i) {
551 final Element thumbnail = (Element) (inFront ? imageContainer.getFirstChild() : imageContainer.getLastChild());
552 clearThumbnail(thumbnail);
553 }
554 }
555
556 private void releaseThumbnails(Range between) {
557 final Set<Element> toRelease = new HashSet<>();
558 for (int i = between.getStart(); i < between.getEnd(); ++i) {
559 toRelease.add(Element.as(imageContainer.getChild(i)));
560 }
561
562 for (final Element thumbnail : toRelease) {
563 clearThumbnail(thumbnail);
564 }
565 }
566
567 private Element createThumbnailPlaceholder(int width) {
568 final DivElement thumbnail = DivElement.as(DOM.createDiv());
569 thumbnail.addClassName(THUMBNAIL_STYLE_NAME);
570 thumbnail.addClassName(THUMBNAIL_PLACEHOLDER_STYLE_NAME);
571 thumbnail.getStyle().setWidth(width, Style.Unit.PX);
572 thumbnail.getStyle().setHeight(0, Style.Unit.PX);
573 thumbnail.getStyle().setDisplay(Style.Display.INLINE_BLOCK);
574 thumbnail.getStyle().setVisibility(Style.Visibility.HIDDEN);
575
576 return thumbnail;
577 }
578
579 private void clearThumbnail(Element thumbnail) {
580 if (!thumbnail.hasClassName(THUMBNAIL_PLACEHOLDER_STYLE_NAME)) {
581 flyweight.clear(thumbnail);
582 floatingThumbnails.push(thumbnail);
583 }
584 thumbnail.removeFromParent();
585 }
586
587 public void updateIconFontStyle(String style, int index) {
588 flyweight.setIconFontStyle(style, Element.as(imageContainer.getChild(relativeIndex(index))));
589 }
590
591 public void setSelectedThumbnailsViaIndices(List<Integer> indices) {
592 clearSelection();
593 for (int absIndex : indices) {
594 Element.as(imageContainer.getChild(relativeIndex(absIndex))).addClassName("selected");
595 }
596 }
597
598 private void setSpacersHeight(int usHeight, int lsHeight) {
599 upperSpacer.getStyle().setHeight(Math.max(usHeight, 0), Style.Unit.PX);
600 lowerSpacer.getStyle().setHeight(Math.max(lsHeight, 0), Style.Unit.PX);
601 }
602
603 private void clearSelection() {
604 final JQueryWrapper selectedThumbnails = JQueryWrapper.select(DOM.asOld(imageContainer)).find(".selected");
605 if (selectedThumbnails != null) {
606 selectedThumbnails.removeClass("selected");
607 }
608 }
609
610 private void removePlaceholders() {
611 if (imageContainer.getChildCount() > 0) {
612 while (imageContainer.getLastChild().getChildCount() == 0) {
613 clearThumbnail((Element) imageContainer.getLastChild());
614 }
615 }
616 }
617
618 private boolean areAllVisibleThumbnailsCleared() {
619 return getCurrentlyDisplayedThumbnails() == JQueryWrapper.select(DOM.asOld(imageContainer)).find(".cleared").size();
620 }
621
622 private int getPlaceholderCount() {
623 return JQueryWrapper.select(DOM.asOld(imageContainer)).find("." + THUMBNAIL_PLACEHOLDER_STYLE_NAME).size();
624 }
625
626 private int getScrollableHeight() {
627 return getElement().getOffsetHeight() - thumbnailSizeSlider.getOffsetHeight();
628 }
629
630 private int getScrollableWidth() {
631 return getOffsetWidth();
632 }
633
634
635
636
637 static class Flyweight {
638
639 static final String THUMBNAIL_STYLE_NAME = "thumbnail";
640 static final String THUMBNAIL_IMAGE_STYLE_NAME = "thumbnail-image";
641 public static final String CLEARED_STYLE_NAME = "cleared";
642
643 Element createThumbnail() {
644 final DivElement thumbnail = DivElement.as(DOM.createDiv());
645 thumbnail.addClassName(THUMBNAIL_STYLE_NAME);
646 thumbnail.getStyle().setDisplay(Style.Display.INLINE_BLOCK);
647
648 final SpanElement caption = SpanElement.as(DOM.createSpan());
649 caption.getStyle().setDisplay(Style.Display.NONE);
650
651 final ImageElement image = ImageElement.as(DOM.createImg());
652 image.addClassName(THUMBNAIL_IMAGE_STYLE_NAME);
653 image.getStyle().setDisplay(Style.Display.NONE);
654
655 thumbnail.appendChild(image);
656 thumbnail.appendChild(caption);
657
658 return thumbnail;
659 }
660
661 void setImageSrc(String src, Element thumbnail) {
662 final Element img = getImage(thumbnail);
663 final Element caption = getCaption(thumbnail);
664
665 img.getStyle().setDisplay(Style.Display.BLOCK);
666 caption.getStyle().setDisplay(Style.Display.BLOCK);
667
668 img.setAttribute("src", src);
669 thumbnail.removeClassName(CLEARED_STYLE_NAME);
670 }
671
672 void setIconFontStyle(String style, Element thumbnail) {
673
674 }
675
676 private Element getCaption(Element thumbnail) {
677 return Element.as(thumbnail.getChild(1));
678 }
679
680 Element getImage(Element thumbnail) {
681 return Element.as(thumbnail.getChild(0));
682 }
683
684 public void clear(Element thumbnail) {
685 Element caption = getCaption(thumbnail);
686 caption.setInnerText("");
687 caption.getStyle().setDisplay(Style.Display.NONE);
688
689 Element image = getImage(thumbnail);
690 image.removeAttribute("src");
691 image.getStyle().setDisplay(Style.Display.NONE);
692
693 thumbnail.addClassName(CLEARED_STYLE_NAME);
694 }
695
696 void setCaption(String newCaption, Element thumbnail) {
697 final Element caption = getCaption(thumbnail);
698 caption.setInnerHTML(newCaption);
699 caption.getStyle().setDisplay(Style.Display.BLOCK);
700
701 final Element img = getImage(thumbnail);
702 img.getStyle().setDisplay(Style.Display.BLOCK);
703
704 thumbnail.removeClassName(CLEARED_STYLE_NAME);
705 }
706 }
707
708 public DivElement getImageContainer() {
709 return imageContainer;
710 }
711 }