/*
@VaadinAddonLicenseForJavaFiles@
*/
package com.spaceapplications.vaadin.addon.eventtimeline.gwt.client;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.DateTimeService;
import com.vaadin.terminal.gwt.client.LocaleNotLoadedException;
import com.vaadin.terminal.gwt.client.Paintable;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.VConsole;
/**
* VEventTimelineWidget, based on original version from vaadin-timeline
*
* @author Thomas Neidhart / Space Applications Services NV/SA
* @author Florian Pirchner (add / remove bands)
* @author Peter Lehto / IT Mill Oy Ltd
* @author John Ahlroos / IT Mill Oy Ltd
*/
public class VEventTimelineWidget extends Composite implements Paintable {
// Style names
public static final String TAGNAME = "eventtimeline-widget";
public static final String CLASSNAME = "v-" + TAGNAME;
public static final String DISPLAY_CLASSNAME = CLASSNAME + "-display";
public static final String BROWSER_CLASSNAME = CLASSNAME + "-browser";
public static final String CAPTION_CLASSNAME = CLASSNAME + "-caption";
private static final String CLASSNAME_TOPBAR = CLASSNAME + "-topbar";
private static final String CLASSNAME_ZOOMBAR = CLASSNAME + "-zoombar";
private static final String CLASSNAME_ZOOMBARLABEL = CLASSNAME + "-label";
private static final String CLASSNAME_DATEFIELD = CLASSNAME + "-datefield";
private static final String CLASSNAME_DATEFIELDEDIT = CLASSNAME_DATEFIELD + "-edit";
private static final String CLASSNAME_DATERANGE = CLASSNAME + "-daterange";
private static final String CLASSNAME_LEGEND = CLASSNAME + "-legend";
private static final String CLASSNAME_MODELEGEND_ROW = CLASSNAME + "-modelegend";
private static final String CLASSNAME_BANDPAGE = CLASSNAME + "-pagenavigation";
private static final String CLASSNAME_BANDPAGE_LABEL = CLASSNAME_BANDPAGE + "-label";
private static final String CLASSNAME_BANDPAGE_NEXT = CLASSNAME_BANDPAGE + "-next";
private static final String CLASSNAME_BANDPAGE_PREVIOUS = CLASSNAME_BANDPAGE + "-previous";
private static final String CLASSNAME_BANDPAGE_PAGENUMBER = CLASSNAME_BANDPAGE + "-pagenumber";
public static final String ATTR_DATE = "date";
public static final String ATTR_STYLE = "css";
public static final String ATTR_DESCRIPTION = "desc";
public static final String ATTR_TIMETO = "tto";
public static final String ATTR_TIMEFROM = "tfrom";
public static final String ATTR_DATETO = "dto";
public static final String ATTR_DATEFROM = "dfrom";
public static final String ATTR_CAPTION = "caption";
public static final String ATTR_ID = "id";
public static final String ATTR_EVENT = "event";
public static final String ATTR_BANDID = "bandid";
public static final String ATTR_BAND = "band";
public static final String ATTR_BAND_PAGE_SIZE = "bandPageSize";
public static final String ATTR_END = "end";
public static final String ATTR_START = "start";
public static final String ATTR_EVENTS = "events";
public static final String ATTR_BAND_CAPTION = "bcaption";
public static final String ATTR_OPERATION = "operation";
public static final String ATTR_BANDS = "bands";
public static final String OPERATION_REMOVE = "remove";
public static final String OPERATION_ADD = "add";
private final ClickHandler zoomClickHandler = new ClickHandler() {
public void onClick(ClickEvent event) {
zoomLevelClicked(event);
}
};
private final ClickHandler pageNavigationClickHandler = new ClickHandler() {
public void onClick(ClickEvent event) {
pageNavigationClicked(event);
}
};
// Panels
private final HorizontalPanel topBar;
private final HorizontalPanel zoomBar;
private final HorizontalPanel dateRangeBar;
private final HorizontalPanel modeLegendBar;
// Legend
private final HorizontalPanel legend;
private final List<Label> legendValues = new ArrayList<Label>();
// Bands
private final VEventTimelineBandArea bandArea;
// Date selection
private final TextBox dateFrom;
private final TextBox dateTo;
private Date intervalStartDate, intervalEndDate;
// if true, then the current date ranges has to be set to the display and browser
private boolean uiRequiresRangeRefresh;
// Default UIDL stuff
private ApplicationConnection client;
private String uidlId;
// Initialization
private boolean initStage1Done = false;
private boolean initDone = false;
private boolean noDataAvailable = false;
private Date selectedStartDate, selectedEndDate;
// Components
private VEventTimelineDisplay display;
private VEventTimelineBrowser browser;
// Base
private final VerticalPanel root = new VerticalPanel();
private final Label caption;
private boolean isIdle = true;
private String initGridColor = "rgb(200,200,200)";
private boolean selectionLock = true;
private String currentLocale;
private DateTimeService dts;
// Event specific properties
private Date startDate = null;
private Date endDate = null;
// Band height property
private int bandHeight = -1;
// Zoom levels
private final Map<Anchor, Long> zoomLevels = new HashMap<Anchor, Long>();
// Component visibilities
private boolean browserIsVisible = true;
private boolean zoomIsVisible = true;
private boolean dateSelectVisible = true;
private boolean dateSelectEnabled = true;
private boolean legendVisible = false;
private boolean bandPagingVisible = false;
// Date formats
private DateTimeFormat displayFormat = DateTimeFormat.getFormat("MMM d, y");
private DateTimeFormat editFormat = DateTimeFormat.getFormat("dd-MM-yyyy");
private final DateTimeFormat dateformat_date = DateTimeFormat.getFormat("yyyy-MM-dd");
// Data Cache
private VClientCache cache = new VClientCache(this);
private boolean runningDataRequest = false;
// Band Navigation
private HorizontalPanel pageNavigationBar;
private Anchor previousPage;
private Label pageNumberText;
private Anchor nextPage;
public VEventTimelineWidget() {
dts = new DateTimeService();
root.setStyleName(CLASSNAME);
initWidget(root);
caption = new Label("");
caption.setStyleName(CAPTION_CLASSNAME);
caption.setVisible(false);
root.add(caption);
endDate = new Date();
startDate = new Date(endDate.getTime() - VEventTimelineDisplay.MONTH);
topBar = new HorizontalPanel();
topBar.setStyleName(CLASSNAME_TOPBAR);
topBar.setVisible(zoomIsVisible || dateSelectVisible
|| bandPagingVisible);
root.add(topBar);
zoomBar = new HorizontalPanel();
zoomBar.setStyleName(CLASSNAME_ZOOMBAR);
zoomBar.setVisible(zoomIsVisible);
Label zoomLbl = new Label("Zoom:");
zoomLbl.addStyleName(CLASSNAME_ZOOMBARLABEL);
zoomBar.add(zoomLbl);
topBar.add(zoomBar);
dateRangeBar = new HorizontalPanel();
dateRangeBar.setStyleName(CLASSNAME_DATERANGE);
dateRangeBar.setHorizontalAlignment(HorizontalPanel.ALIGN_RIGHT);
dateRangeBar.setVisible(dateSelectVisible);
dateFrom = new TextBox();
dateFrom.addValueChangeHandler(new ValueChangeHandler<String>() {
public void onValueChange(ValueChangeEvent<String> event) {
try {
Date newDate = dts.parseDate(event.getValue(),
editFormat.getPattern(), true);
if ((newDate.equals(startDate) || newDate.after(startDate))
&& (newDate.equals(endDate) || newDate
.before(endDate))) {
intervalStartDate = newDate;
setBrowserRange(intervalStartDate, intervalEndDate);
setDisplayRange(intervalStartDate, intervalEndDate);
dateFrom.setFocus(false);
} else {
dateFrom.setText(dts.formatDate(intervalStartDate,
editFormat.getPattern()));
}
} catch (IllegalArgumentException iae) {
dateFrom.setText(dts.formatDate(intervalStartDate,
editFormat.getPattern()));
}
}
});
dateFrom.addFocusHandler(new FocusHandler() {
public void onFocus(FocusEvent event) {
dateFrom.setStyleName(CLASSNAME_DATEFIELDEDIT);
dateFrom.setText(dts.formatDate(intervalStartDate,
editFormat.getPattern()));
dateFrom.selectAll();
}
});
dateFrom.addBlurHandler(new BlurHandler() {
public void onBlur(BlurEvent event) {
dateFrom.setStyleName(CLASSNAME_DATEFIELD);
dateFrom.setText(dts.formatDate(intervalStartDate,
displayFormat.getPattern()));
}
});
dateFrom.setReadOnly(!dateSelectEnabled);
dateFrom.setStyleName(CLASSNAME_DATEFIELD);
dateRangeBar.add(dateFrom);
Label dash = new Label();
dash.setText("-");
dateRangeBar.add(dash);
dateTo = new TextBox();
dateTo.addValueChangeHandler(new ValueChangeHandler<String>() {
public void onValueChange(ValueChangeEvent<String> event) {
try {
Date newDate = dts.parseDate(event.getValue(),
editFormat.getPattern(), true);
if ((newDate.equals(startDate) || newDate.after(startDate))
&& (newDate.equals(endDate) || newDate
.before(endDate))) {
intervalEndDate = newDate;
setBrowserRange(intervalStartDate, intervalEndDate);
setDisplayRange(intervalStartDate, intervalEndDate);
dateTo.setFocus(false);
} else {
dateTo.setText(dts.formatDate(intervalEndDate,
editFormat.getPattern()));
}
} catch (IllegalArgumentException iae) {
dateTo.setText(dts.formatDate(intervalEndDate,
editFormat.getPattern()));
}
}
});
dateTo.addFocusHandler(new FocusHandler() {
public void onFocus(FocusEvent event) {
dateTo.setStyleName(CLASSNAME_DATEFIELDEDIT);
dateTo.setText(dts.formatDate(intervalEndDate,
editFormat.getPattern()));
dateTo.selectAll();
}
});
dateTo.addBlurHandler(new BlurHandler() {
public void onBlur(BlurEvent event) {
dateTo.setStyleName(CLASSNAME_DATEFIELD);
dateTo.setText(dts.formatDate(intervalEndDate,
displayFormat.getPattern()));
}
});
dateTo.setReadOnly(!dateSelectEnabled);
dateTo.setStyleName(CLASSNAME_DATEFIELD);
dateRangeBar.add(dateTo);
topBar.add(dateRangeBar);
topBar.setCellHorizontalAlignment(dateRangeBar,
HorizontalPanel.ALIGN_RIGHT);
//
// band navigation area
//
pageNavigationBar = new HorizontalPanel();
pageNavigationBar.setHorizontalAlignment(HorizontalPanel.ALIGN_RIGHT);
pageNavigationBar.setStyleName(CLASSNAME_BANDPAGE);
pageNavigationBar.setVisible(bandPagingVisible);
pageNavigationBar.setHeight("31px");
topBar.add(pageNavigationBar);
topBar.setCellHorizontalAlignment(pageNavigationBar,
HorizontalPanel.ALIGN_RIGHT);
Label navigationLbl = new Label("Navigation:");
navigationLbl.addStyleName(CLASSNAME_BANDPAGE_LABEL);
pageNavigationBar.add(navigationLbl);
previousPage = new Anchor("Previous page");
pageNavigationBar.add(previousPage);
previousPage.addStyleName(CLASSNAME_BANDPAGE_PREVIOUS);
previousPage.addClickHandler(pageNavigationClickHandler);
pageNumberText = new Label();
pageNavigationBar.add(pageNumberText);
pageNumberText.addStyleName(CLASSNAME_BANDPAGE_PAGENUMBER);
pageNumberText.setText("1");
nextPage = new Anchor("Next page");
pageNavigationBar.add(nextPage);
nextPage.addStyleName(CLASSNAME_BANDPAGE_NEXT);
nextPage.addClickHandler(pageNavigationClickHandler);
legend = new HorizontalPanel();
legend.setVisible(legendVisible);
legend.setHeight("30px");
legend.setStyleName(CLASSNAME_LEGEND);
modeLegendBar = new HorizontalPanel();
modeLegendBar.setVisible(legendVisible);
modeLegendBar.setWidth("100%");
modeLegendBar.setHeight("31px");
modeLegendBar.setStyleName(CLASSNAME_MODELEGEND_ROW);
modeLegendBar.add(legend);
modeLegendBar.setCellHorizontalAlignment(legend, HorizontalPanel.ALIGN_RIGHT);
root.add(modeLegendBar);
//
// the band area
//
HorizontalPanel layout = new HorizontalPanel();
bandArea = new VEventTimelineBandArea(this);
bandArea.setWidth("100px");
layout.add(bandArea);
VerticalPanel main = new VerticalPanel();
// Add the display
display = new VEventTimelineDisplay(this);
main.add(display);
// Add the browser
browser = new VEventTimelineBrowser(this);
browser.setVisible(browserIsVisible);
main.add(browser);
layout.add(main);
root.add(layout);
}
public DateTimeService getDateTimeService() {
return dts;
}
private String currentHeight = null;
@Override
public void setHeight(String height) {
super.setHeight(height);
if (!height.equals(currentHeight)) {
// Reduce the amount of redraws caused by resizing
currentHeight = height;
recalculateHeights();
if (initDone) {
display.redraw();
browser.redraw();
}
}
}
private void recalculateHeights() {
int captionHeight = getCaptionHeight();
int topBarHeight = topBar.isVisible() ? 28 : 0;
int modeLegendBarHeight = modeLegendBar.isVisible() ? 31 : 0;
int browserHeight = browser.isVisible() ? 64 : 0;
int displayHeight = getWidgetHeight() - captionHeight - topBarHeight
- modeLegendBarHeight - browserHeight;
display.setHeight(displayHeight + "px");
}
private String currentWidth = null;
@Override
public void setWidth(String width) {
super.setWidth(width);
if (!width.equals(currentWidth) && width.contains("px")) {
currentWidth = width;
recalculateWidths();
if (initDone) {
display.redraw();
browser.redraw();
}
}
}
private void recalculateWidths() {
int width = getWidgetWidth();
topBar.setWidth(width + "px");
caption.setWidth((width - 5) + "px");
modeLegendBar.setWidth(width + "px");
display.setWidth(width - bandArea.getOffsetWidth() + "px");
browser.setWidth(width - bandArea.getOffsetWidth() + "px");
}
/**
* Adds a zoom level to the zoom bar
*
* @param caption
* The caption of the zoom level
* @param time
* The time in milliseconds of the zoom level
*/
private void addZoomLevel(String caption, Long time) {
Anchor level = new Anchor(caption);
level.addClickHandler(zoomClickHandler);
zoomLevels.put(level, time);
zoomBar.add(level);
}
/**
* A page navigation button was clicked
*
* @param evt
* The click event
*/
private void pageNavigationClicked(ClickEvent evt) {
boolean redraw = false;
int bandPage = bandArea.getVisiblePage();
if (evt.getSource() == nextPage) {
if (bandPage < bandArea.getPageCount() - 1) {
bandPage++;
bandArea.setVisiblePage(bandPage);
redraw = true;
}
} else {
if (bandPage > 0) {
bandPage--;
bandArea.setVisiblePage(bandPage);
redraw = true;
}
}
if (redraw) {
refreshPageNumber();
display.redraw();
browser.redraw();
fireBandNavigationClickEvent();
}
}
/**
* Initializes the widget
*/
private boolean init1(UIDL uidl) {
// Set initial data
setStartDate(uidl);
setEndDate(uidl);
setCaption(uidl);
setZoomCaption(uidl);
setPageNavigationCaptions(uidl);
setBandSelectionEnabled(uidl);
setSelectionLock(uidl);
setDateFormatInfo(uidl);
setLocale(uidl);
setBandHeight(uidl);
return true;
}
private void setStartDate(UIDL uidl) {
if (uidl.hasAttribute("startDate")) {
startDate = new Date(uidl.getLongAttribute("startDate"));
uiRequiresRangeRefresh = true;
}
}
private void setEndDate(UIDL uidl) {
if (uidl.hasAttribute("endDate")) {
endDate = new Date(uidl.getLongAttribute("endDate"));
uiRequiresRangeRefresh = true;
}
}
private void setCaption(UIDL uidl) {
if (uidl.hasAttribute("caption")) {
String captionText = uidl.getStringAttribute("caption");
if (!captionText.equals(caption.getText())) {
boolean captionWasVisible = caption.isVisible();
if (captionText.equals("")) {
caption.setText("");
caption.setVisible(false);
} else {
caption.setText(captionText);
caption.setVisible(true);
}
if (captionWasVisible != caption.isVisible()) {
recalculateHeights();
if (initDone) {
display.redraw();
browser.redraw();
}
}
}
}
}
private void setSelectionLock(UIDL uidl) {
if (uidl.hasAttribute("lock")) {
selectionLock = uidl.getBooleanAttribute("lock");
} else {
selectionLock = false;
}
}
private void setZoomLevels(UIDL uidl) {
if (uidl.hasAttribute("zoomLevels")) {
String[] levels = uidl.getStringArrayAttribute("zoomLevels");
if (zoomBar != null) {
for (Anchor lvl : zoomLevels.keySet()) {
zoomBar.remove(lvl);
}
}
zoomLevels.clear();
for (String level : levels) {
String[] levelArray = level.split(",");
if (levelArray.length == 2) {
String caption = levelArray[0];
Long time = Long.parseLong(levelArray[1]);
addZoomLevel(caption, time);
}
}
}
}
private void setZoomVisibility(UIDL uidl) {
if (uidl.hasAttribute("zoomVisibility")) {
zoomIsVisible = uidl.getBooleanAttribute("zoomVisibility");
if (zoomBar != null) {
zoomBar.setVisible(zoomIsVisible);
setTopBarVisibility(zoomIsVisible || dateSelectVisible
|| bandPagingVisible);
}
}
}
private void setZoomCaption(UIDL uidl) {
if (uidl.hasAttribute("zlvlcaption")) {
String caption = uidl.getStringAttribute("zlvlcaption");
Label lbl = (Label) zoomBar.getWidget(0);
lbl.setText(caption);
}
}
private void setBandHeight(UIDL uidl) {
if (uidl.hasAttribute("bandheight")) {
bandHeight = uidl.getIntAttribute("bandheight");
}
}
protected int getBandHeight() {
return bandHeight;
}
private void setPageNavigationVisibility(UIDL uidl) {
if (uidl.hasAttribute("bandPagingVisible")) {
bandPagingVisible = uidl.getBooleanAttribute("bandPagingVisible");
if (pageNavigationBar != null) {
pageNavigationBar.setVisible(bandPagingVisible);
setTopBarVisibility(zoomIsVisible || dateSelectVisible
|| bandPagingVisible);
}
}
}
private void setPageNavigationCaptions(UIDL uidl) {
if (uidl.hasAttribute("bpgingCaption")) {
String caption = uidl.getStringAttribute("bpgingCaption");
Label lbl = (Label) pageNavigationBar.getWidget(0);
lbl.setText(caption);
}
if (uidl.hasAttribute("bpgingCptPrevious")) {
String caption = uidl.getStringAttribute("bpgingCptPrevious");
previousPage.setText(caption);
}
if (uidl.hasAttribute("bpgingCptNext")) {
String caption = uidl.getStringAttribute("bpgingCptNext");
nextPage.setText(caption);
}
}
private void setBandSelectionEnabled(UIDL uidl) {
if (uidl.hasAttribute("bandSelectionEnabled")) {
boolean bandSelectionEnabled = uidl
.getBooleanAttribute("bandSelectionEnabled");
boolean oldValue = bandArea.isBandSelectionEnabled();
if (oldValue != bandSelectionEnabled) {
bandArea.setBandSelectionEnabled(bandSelectionEnabled);
}
}
}
private void setModeLegendBarVisibility(boolean visibility) {
boolean isVisible = modeLegendBar.isVisible();
if (isVisible != visibility) {
modeLegendBar.setVisible(visibility);
recalculateHeights();
if (initDone) {
display.redraw();
browser.redraw();
}
}
}
private void setTopBarVisibility(boolean visibility) {
boolean isVisible = topBar.isVisible();
if (isVisible != visibility) {
topBar.setVisible(visibility);
recalculateHeights();
if (initDone) {
display.redraw();
browser.redraw();
}
}
}
private Timer refreshTimer = new Timer() {
@Override
public void run() {
// Render the browser canvas (refreshes the selection after loading the data)
browser.refresh();
if (selectionLock) {
/*
* Update the selection manually. If the selection lock is not
* on the browser will update the display once it has finished
* loading and recalculated the new selection
*/
display.setRange(browser.getSelectedStartDate(), browser.getSelectedEndDate());
}
}
};
public boolean isSelectionLocked() {
return selectionLock;
}
private void setDirty(UIDL uidl) {
if (uidl.getBooleanAttribute("dirty") && initDone) {
refreshTimer.cancel();
refreshTimer.schedule(500);
}
}
private void setSelectionRange(UIDL uidl) {
if (uidl.hasVariable("selectStart") && uidl.hasVariable("selectEnd")) {
selectedStartDate = new Date(uidl.getLongVariable("selectStart"));
selectedEndDate = new Date(uidl.getLongVariable("selectEnd"));
uiRequiresRangeRefresh = true;
}
}
private void setGridColor(UIDL uidl) {
if (uidl.hasAttribute("gridColor")) {
String color = uidl.getStringAttribute("gridColor");
if (color == null || color.equals("")) {
initGridColor = null;
} else {
initGridColor = color;
}
if (initStage1Done) {
display.setGridColor(initGridColor);
}
}
}
private void setDateSelectEnabled(UIDL uidl) {
if (uidl.hasAttribute("dateSelectEnabled")) {
dateSelectEnabled = uidl.getBooleanAttribute("dateSelectEnabled");
dateFrom.setReadOnly(!dateSelectEnabled);
dateTo.setReadOnly(!dateSelectEnabled);
}
}
private void setDateSelectVisibility(UIDL uidl) {
if (uidl.hasAttribute("dateSelectVisibility")) {
dateSelectVisible = uidl
.getBooleanAttribute("dateSelectVisibility");
if (dateRangeBar != null) {
dateRangeBar.setVisible(dateSelectVisible);
setTopBarVisibility(zoomIsVisible || dateSelectVisible
|| bandPagingVisible);
}
}
}
private void setLegendVisibility(UIDL uidl) {
if (uidl.hasAttribute("legendVisibility")) {
legendVisible = uidl.getBooleanAttribute("legendVisibility");
if (legend != null) {
legend.setVisible(legendVisible);
setModeLegendBarVisibility(legendVisible);
}
}
}
private void setBrowserVisibility(UIDL uidl) {
if (uidl.hasAttribute("browserVisibility")) {
boolean browserWasVisible = browserIsVisible;
browserIsVisible = uidl.getBooleanAttribute("browserVisibility");
if (browser != null && browserWasVisible != browserIsVisible) {
browser.setVisible(browserIsVisible);
recalculateHeights();
if (initDone) {
display.redraw();
browser.redraw();
}
}
}
}
private void setLocale(UIDL uidl) {
if (uidl.hasAttribute("locale")) {
final String locale = uidl.getStringAttribute("locale");
try {
dts.setLocale(locale);
currentLocale = locale;
} catch (final LocaleNotLoadedException e) {
currentLocale = dts.getLocale();
VConsole.error("Tried to use an unloaded locale \"" + locale
+ "\". Using default locale (" + currentLocale + ").");
VConsole.error(e);
}
}
}
/**
* Sets the bands that should be shown. The uidl contains information
* whether bands are added or removed.
*
* @param uidl
*/
private void setBands(UIDL uidl) {
if (uidl.hasAttribute(ATTR_BAND_PAGE_SIZE)) {
int pageSize = uidl.getIntAttribute(ATTR_BAND_PAGE_SIZE);
bandArea.setPageSize(pageSize);
}
boolean hasContent = bandArea.getBandCount() != 0;
List<Integer> removedBands = new ArrayList<Integer>();
UIDL bands = uidl.getChildByTagName(ATTR_BANDS);
if (bands != null) {
Iterator<Object> it = bands.getChildIterator();
while (it.hasNext()) {
UIDL child = (UIDL) it.next();
if (child != null && ATTR_BAND.equals(child.getTag())) {
Integer id = child.getIntAttribute(ATTR_BANDID);
String operation = child.getStringAttribute("operation");
if (operation.equals(OPERATION_ADD)) {
String caption = child
.getStringAttribute(ATTR_BAND_CAPTION);
bandArea.addBand(id, caption);
if (hasContent) {
bandArea.navigateToBand(id);
}
} else if (operation.equals(OPERATION_REMOVE)) {
bandArea.removeBand(id);
removedBands.add(id);
}
}
}
}
if (removedBands.size() > 0) {
Integer[] bandIds = removedBands.toArray(new Integer[removedBands.size()]);
display.dataRemoved(bandIds);
browser.dataRemoved(bandIds);
}
if (!hasContent) {
bandArea.navigateToPage(0);
}
refreshPageNumber();
if (initDone) {
display.redraw();
browser.redraw();
}
}
/**
* Refreshes the page number.
*/
private void refreshPageNumber() {
pageNumberText.setText(Integer.toString(bandArea.getVisiblePage() + 1));
}
protected int getBandHeight(int band) {
return bandArea.getBandHeight(band);
}
private void handleOnePointGraph() {
if (startDate.equals(endDate)) {
long halfDay = VEventTimelineDisplay.DAY / 2L;
startDate = new Date(startDate.getTime() - halfDay);
endDate = new Date(endDate.getTime() + halfDay);
selectedStartDate = startDate;
selectedEndDate = endDate;
browser.setRange(selectedStartDate, selectedEndDate);
}
}
/*
* (non-Javadoc)
*
* @see
* com.vaadin.terminal.gwt.client.Paintable#updateFromUIDL(com.vaadin.terminal
* .gwt.client.UIDL, com.vaadin.terminal.gwt.client.ApplicationConnection)
*/
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
// Check parent components
if (client.updateComponent(this, uidl, true)) {
return;
}
// Store reference variables for later usage
this.client = client;
uidlId = uidl.getId();
// Initialization stage 1
if (!initStage1Done) {
initStage1Done = init1(uidl);
// Send init flag back to server along with the canvas width
client.updateVariable(uidlId, "init", true, false);
client.updateVariable(uidlId, "canvasWidth", getOffsetWidth(), true);
return;
// Initialization done
}
setBandHeight(uidl);
setCaption(uidl);
setBands(uidl);
setLocale(uidl);
setNoData(uidl);
setSelectionLock(uidl);
setStartDate(uidl);
setEndDate(uidl);
handleOnePointGraph();
setSelectionRange(uidl);
setBrowserVisibility(uidl);
setZoomVisibility(uidl);
setDateSelectVisibility(uidl);
setDateSelectEnabled(uidl);
setLegendVisibility(uidl);
setPageNavigationVisibility(uidl);
setZoomLevels(uidl);
setGridColor(uidl);
setZoomCaption(uidl);
setPageNavigationCaptions(uidl);
setBandSelectionEnabled(uidl);
setDateFormatInfo(uidl);
// Data received
List<VEvent> events = null;
UIDL bands = uidl.getChildByTagName("events");
if (bands != null) {
Long startTime = bands.getLongAttribute("start");
Long endTime = bands.getLongAttribute("end");
Iterator<Object> it = bands.getChildIterator();
while (it.hasNext()) {
UIDL child = (UIDL) it.next();
if (child != null && "band".equals(child.getTag())) {
Integer id = child.getIntAttribute("bandid");
// TODO Thomas
cache.removeFromCache(id);
events = getEvents(child);
cache.addToCache(id, new Date(startTime), new Date(endTime), events);
display.dataReceived(id, events);
browser.dataReceived(id, events);
}
}
runningDataRequest = false;
display.redraw();
}
if (!initDone) {
initDone = true;
}
if (isInitDone() && uiRequiresRangeRefresh) {
uiRequiresRangeRefresh = false;
browser.setRange(selectedStartDate, selectedEndDate);
display.setRange(selectedStartDate, selectedEndDate);
}
if (isInitDone()) {
if (browserIsVisible) {
browser.refresh();
}
}
setDirty(uidl);
}
private void setNoData(UIDL uidl) {
// Disable component since no data source has been defined on the server
if (uidl.hasAttribute("nodata")) {
setWidgetNoData(uidl.getBooleanAttribute("nodata"));
} else {
setWidgetNoData(false);
}
}
/** Transforms uidl to list of TimelineEvents */
protected List<VEvent> getEvents(UIDL childUIDL) {
int eventCount = childUIDL.getChildCount();
List<VEvent> events = new ArrayList<VEvent>();
for (int i = 0; i < eventCount; i++) {
UIDL eventUIDL = childUIDL.getChildUIDL(i);
String id = eventUIDL.getStringAttribute(ATTR_ID);
String caption = eventUIDL.getStringAttribute(ATTR_CAPTION);
String datefrom = eventUIDL.getStringAttribute(ATTR_DATEFROM);
String dateto = eventUIDL.getStringAttribute(ATTR_DATETO);
Long timefrom = eventUIDL.getLongAttribute(ATTR_TIMEFROM);
Long timeto = eventUIDL.getLongAttribute(ATTR_TIMETO);
String desc = eventUIDL.getStringAttribute(ATTR_DESCRIPTION);
String style = eventUIDL.getStringAttribute(ATTR_STYLE);
VEvent e = new VEvent();
e.setID(id);
e.setCaption(caption);
e.setDescription(desc);
e.setEnd(dateformat_date.parse(dateto));
e.setStart(dateformat_date.parse(datefrom));
e.setStartTime(timefrom);
e.setEndTime(timeto);
e.setStyleName(style);
events.add(e);
}
return events;
}
protected List<VEvent> getEventsFromStringArray(final String[] array) {
List<VEvent> events = new ArrayList<VEvent>();
for (String str : array) {
String[] vals = str.split(";");
VEvent e = new VEvent();
e.setID(vals[0]);
e.setCaption(vals[1]);
e.setStart(dateformat_date.parse(vals[2]));
e.setEnd(dateformat_date.parse(vals[3]));
e.setStartTime(Long.valueOf(vals[4]));
e.setEndTime(Long.valueOf(vals[5]));
e.setDescription(vals[6]);
e.setStyleName(vals[7]);
events.add(e);
}
return events;
}
/**
* Set the not data state
*
* @param enabled
*/
private void setWidgetNoData(boolean enabled) {
noDataAvailable = enabled;
display.displayNoDataMessage(enabled);
display.setEnabled(!enabled);
browser.setEnabled(!enabled);
dateFrom.setEnabled(!enabled);
dateTo.setEnabled(!enabled);
for (Anchor lvl : zoomLevels.keySet()) {
lvl.setEnabled(!enabled);
}
}
/**
* Get data from server.
*
* @param component
* The component which need the events
* @param startDate
* The start date of the events
* @param endDate
* The end date of the events
* @return Was the data fetched from the cache
*/
public boolean getEvents(VDataListener component, Date startDate,
Date endDate, boolean useCache) {
if (!component.isVisible()) {
return true;
}
isIdle = false;
GWT.log("trying to retrieve events: start=" + startDate.toString() + ", end=" + endDate.toString());
if (useCache) {
boolean gotFromCache = true;
for (VEventTimelineBand band : bandArea.getAllBands()) {
List<VEvent> events = cache.getFromCache(band.getId(), startDate, endDate);
if (events == null) {
gotFromCache = false;
break;
} else {
component.dataReceived(band.getId(), events);
}
}
component.dataReceivedAll();
if (gotFromCache) {
return true;
}
}
if (!runningDataRequest) {
GWT.log("retrieve from server");
// if the data could not be found in the cache, get it from the server
client.updateVariable(uidlId, "events",
new Object[] { Long.valueOf(startDate.getTime()),
Long.valueOf(endDate.getTime()) },
false);
getFromServer();
}
return false;
}
/**
* Set the displayed date range
*
* @param start
* The start date
* @param end
* The end date
*/
public void setDisplayRange(Date start, Date end) {
display.setRange(start, end);
}
/**
* Set the selected date range
*
* @param start
* The start date
* @param end
* The end date
*/
public void setBrowserRange(Date start, Date end) {
browser.setRange(start, end);
}
/**
* Calculates the maximum value of a list of values
*
* @param values
* The list of values
* @return The maximum value
*/
public static float getMaxValue(List<Float> values) {
if (values == null || values.size() == 0) {
return 0;
}
float max = values.get(0);
for (Float value : values) {
max = max < value.floatValue() ? value.floatValue() : max;
}
return max;
}
/**
* Returns the start date
*
* @return The start date
*/
public Date getStartDate() {
return startDate;
}
/**
* Returns the end date
*
* @return The end date
*/
public Date getEndDate() {
return endDate;
}
/**
* Issues a get request to fetch the requested data points
*/
public void getFromServer() {
runningDataRequest = true;
client.updateVariable(uidlId, "send", true, true);
}
/**
* Set the starting date text field
*
* @param date
* The date
*/
public void setFromDateTextField(Date date) {
intervalStartDate = date;
if (date != null) {
dateFrom.setText(dts.formatDate(date, displayFormat.getPattern()));
} else {
dateFrom.setText("");
}
}
/**
* Set the ending date text field
*
* @param date
* The date
*/
public void setToDateTextField(Date date) {
intervalEndDate = date;
if (date != null) {
dateTo.setText(dts.formatDate(date, displayFormat.getPattern()));
} else {
dateTo.setText("");
}
}
/**
* The top bar height
*
* @return Height in pixels
*/
public int getTopBarHeight() {
if (topBar.isVisible()) {
return topBar.getOffsetHeight();
} else {
return 0;
}
}
/**
* The caption height
*
* @return Height in pixels
*/
public int getCaptionHeight() {
if (caption.isVisible()) {
return caption.getOffsetHeight();
} else {
return 0;
}
}
/**
* The legend height
*
* @return height in pixels
*/
public int getLegendHeight() {
if (modeLegendBar.isVisible()) {
return modeLegendBar.getOffsetHeight();
} else {
return 0;
}
}
/**
* A zoom level was clicked
*
* @param evt
* The click event
*/
private void zoomLevelClicked(ClickEvent evt) {
evt.preventDefault();
// If we have no data do nothing
if (noDataAvailable) {
return;
}
// Was a zoom level clicked
Long time = zoomLevels.get(evt.getSource());
Long totalTime = getEndDate().getTime() - getStartDate().getTime();
if (totalTime >= time) {
// Calculate the center
Date center;
if (browserIsVisible) {
Long selectedTime = browser.getSelectedEndDate().getTime()
- browser.getSelectedStartDate().getTime();
center = new Date(browser.getSelectedStartDate().getTime()
+ selectedTime / 2L);
} else {
center = new Date(display.getSelectionStartDate().getTime()
+ time / 2L);
}
// Calculate start date
Date start = new Date(center.getTime() - time / 2L);
if (start.before(getStartDate())) {
start = getStartDate();
}
// Calculate end date
Date end = new Date(start.getTime() + time);
if (end.after(getEndDate())) {
end = getEndDate();
}
// Set the browser
if (browserIsVisible) {
setBrowserRange(start, end);
}
// Set the display
setDisplayRange(start, end);
} else {
if (browserIsVisible) {
setBrowserRange(getStartDate(), getEndDate());
}
setDisplayRange(getStartDate(), getEndDate());
}
}
/**
* Fire a date range change event
*/
public void fireDateRangeChangedEvent() {
if (display.getSelectionStartDate() != null
&& display.getSelectionEndDate() != null) {
Object[] values = new Object[] {
display.getSelectionStartDate().getTime(),
display.getSelectionEndDate().getTime(), };
client.updateVariable(uidlId, "drce", values, true);
}
}
/**
* Fire a event button click event
*
* @param indexes
*/
public void fireEventButtonClickEvent(String id) {
client.updateVariable(uidlId, "ebce", id, true);
}
/**
* Fires a event band navigation click event
*/
public void fireBandNavigationClickEvent() {
client.updateVariable(uidlId, "bandPage", bandArea.getVisiblePage(), true);
}
/**
* Fires a band selected event.
*
* @param bandId
*/
public void fireBandSelected(int bandId) {
client.updateVariable(uidlId, "bandSel", bandId, true);
}
/**
* Returns the height of the widget in pixels
*
* @return A pixel height
*/
@SuppressWarnings("deprecation")
public int getWidgetHeight() {
try {
int height = Integer.parseInt(DOM.getAttribute(root.getElement(),
"height").replaceAll("px", ""));
return height;
} catch (Exception e) {
try {
int height = Integer.parseInt(DOM.getStyleAttribute(
root.getElement(), "height").replaceAll("px", ""));
return height;
} catch (Exception f) {
return root.getOffsetHeight();
}
}
}
@SuppressWarnings("deprecation")
public int getWidgetWidth() {
try {
int width = Integer.parseInt(DOM.getAttribute(root.getElement(),
"width").replaceAll("px", ""));
return width;
} catch (Exception e) {
try {
int width = Integer.parseInt(DOM.getStyleAttribute(
root.getElement(), "width").replaceAll("px", ""));
return width;
} catch (Exception f) {
return root.getOffsetWidth();
}
}
}
/**
* Get the browser height
*
* @return The height in pixels
*/
public int getBrowserHeight() {
if (browserIsVisible) {
return browser.getOffsetHeight();
} else {
return 0;
}
}
/**
* The idle state of the widget
*
* @return If the widget is idle true is returned else false
*/
public boolean isIdle() {
return isIdle;
}
/**
* Sets the legend value
*
* @param graph
* The graph the value is from
* @param value
* The value
*/
public void setLegendValue(int graph, String value) {
if (legendValues.size() > graph) {
Label lbl = legendValues.get(graph);
if (lbl != null) {
lbl.setText(value);
}
}
}
/**
* Has the widget been properly initialized
*
* @return
*/
public boolean isInitDone() {
return initDone;
}
public Date getSelectedStartDate() {
return selectedStartDate;
}
public Date getSelectedEndDate() {
return selectedEndDate;
}
private void setDateFormatInfo(UIDL uidl) {
if (uidl.hasAttribute("dateformats")) {
String[] formats = uidl.getStringAttribute("dateformats").split(
"\\|");
DateTimeFormat dateSelectDisplaySimpleDateFormat = DateTimeFormat
.getFormat(formats[0]);
setSelectDisplayFormat(dateSelectDisplaySimpleDateFormat);
DateTimeFormat dateSelectEditSimpleDateFormat = DateTimeFormat
.getFormat(formats[1]);
setSelectEditFormat(dateSelectEditSimpleDateFormat);
DateTimeFormat shortYearFormat = DateTimeFormat
.getFormat(formats[2]);
display.setYearFormatShort(shortYearFormat);
DateTimeFormat longYearFormat = DateTimeFormat
.getFormat(formats[3]);
display.setYearFormatLong(longYearFormat);
DateTimeFormat shortMonthFormat = DateTimeFormat
.getFormat(formats[4]);
display.setMonthFormatShort(shortMonthFormat);
DateTimeFormat longMonthFormat = DateTimeFormat
.getFormat(formats[5]);
display.setMonthFormatLong(longMonthFormat);
DateTimeFormat shortDayFormat = DateTimeFormat
.getFormat(formats[6]);
display.setDayFormatShort(shortDayFormat);
DateTimeFormat longDayFormat = DateTimeFormat.getFormat(formats[7]);
display.setDayFormatLong(longDayFormat);
DateTimeFormat shortTimeFormat = DateTimeFormat
.getFormat(formats[8]);
display.setTimeFormatShort(shortTimeFormat);
DateTimeFormat longTimeFormat = DateTimeFormat
.getFormat(formats[9]);
display.setTimeFormatLong(longTimeFormat);
// Update scales by redrawing
if (initDone) {
display.redraw();
}
}
}
private void setSelectDisplayFormat(DateTimeFormat format) {
displayFormat = format;
setToDateTextField(intervalEndDate);
setFromDateTextField(intervalStartDate);
}
private void setSelectEditFormat(DateTimeFormat format) {
editFormat = format;
}
public void redrawDisplay() {
display.redraw();
}
}