/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.facebook.tsdb.tsdash.client.presenter;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.TreeMap;
import com.facebook.tsdb.tsdash.client.event.AutoReloadEvent;
import com.facebook.tsdb.tsdash.client.event.AutoReloadEventHandler;
import com.facebook.tsdb.tsdash.client.event.TimeRangeChangeEvent;
import com.facebook.tsdb.tsdash.client.model.ApplicationState;
import com.facebook.tsdb.tsdash.client.model.TimeRange;
import com.facebook.tsdb.tsdash.client.model.ApplicationState.TimeMode;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.HasWidgets;
public class TimePresenter implements Presenter {
public interface TimeWidget {
HasClickHandlers historyModeButton();
HasClickHandlers absoluteModeButton();
Object selectedMode();
void selectedMode(Object button);
HasClickHandlers last15mButton();
HasClickHandlers last1hButton();
HasClickHandlers last6hButton();
HasClickHandlers last1dButton();
HasClickHandlers last1wButton();
Object selectedHistory();
void selectedHistory(Object button);
HasValue<Date> timeFromValue();
HasValue<Date> timeToValue();
HasValueChangeHandlers<Date> timeFrom();
HasValueChangeHandlers<Date> timeTo();
}
private final HandlerManager eventBus;
private final TimeWidget widget;
// values for the history buttons, in seconds
private final HashMap<Object, Long> historyButton2Range =
new HashMap<Object, Long>();
private final TreeMap<Long, Object> historyRange2Button =
new TreeMap<Long, Object>();
public TimePresenter(HandlerManager eventBus, TimeWidget widget) {
this.eventBus = eventBus;
this.widget = widget;
bindWidget();
bindAutoReload();
historyButton2Range.put(widget.last15mButton(), (long) 15 * 60);
historyButton2Range.put(widget.last1hButton(), (long) 60 * 60);
historyButton2Range.put(widget.last6hButton(), (long) 6 * 60 * 60);
historyButton2Range.put(widget.last1dButton(), (long) 24 * 60 * 60);
historyButton2Range.put(widget.last1wButton(), (long) 7 * 24 * 60 * 60);
// create the inverse mapping by using a tree-map in order to have the
// ranges sorted
for (Object button : historyButton2Range.keySet()) {
historyRange2Button.put(historyButton2Range.get(button), button);
}
}
private void bindAutoReload() {
eventBus.addHandler(AutoReloadEvent.TYPE, new AutoReloadEventHandler() {
@Override
public void onPeriodChange(AutoReloadEvent event) {
// not interesting here
}
@Override
public void onEnable(AutoReloadEvent event) {
// this is not interesting either
}
@Override
public void onLaunch(AutoReloadEvent event) {
TimeRange current = new TimeRange(event.getPeriod());
// update only the absolute date values
widget.timeFromValue().setValue(new Date(current.from), false);
widget.timeToValue().setValue(new Date(current.to), false);
}
});
}
private void bindWidget() {
ClickHandler modeHandler = new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
// ignore the selected click
if (widget.selectedMode().equals(event.getSource())) {
return;
}
widget.selectedMode(event.getSource());
}
};
widget.historyModeButton().addClickHandler(modeHandler);
widget.absoluteModeButton().addClickHandler(modeHandler);
// bind the history mode buttons
ClickHandler historyOptionsHandler = new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
if (event.getSource().equals(widget.selectedHistory())) {
return;
}
widget.selectedHistory(event.getSource());
// fire time range change event
TimeRange timeRange = new TimeRange(
historyButton2Range.get(event.getSource()));
// sync the absolute time elements
widget.timeFromValue()
.setValue(new Date(timeRange.from), false);
widget.timeToValue().setValue(new Date(timeRange.to), false);
// fire the event to the application controller
eventBus.fireEvent(new TimeRangeChangeEvent(TimeMode.HISTORY,
timeRange));
}
};
widget.last15mButton().addClickHandler(historyOptionsHandler);
widget.last1hButton().addClickHandler(historyOptionsHandler);
widget.last6hButton().addClickHandler(historyOptionsHandler);
widget.last1dButton().addClickHandler(historyOptionsHandler);
widget.last1wButton().addClickHandler(historyOptionsHandler);
// bind the absolute mode date pickers
widget.timeFrom().addValueChangeHandler(new ValueChangeHandler<Date>() {
@Override
public void onValueChange(ValueChangeEvent<Date> event) {
Date to = widget.timeToValue().getValue();
if (event.getValue().after(to)) {
Window.alert("Incorrect 'from' date");
widget.timeFromValue().setValue(
new Date(to.getTime() - 15 * 60 * 1000), false);
return;
}
TimeRange range = new TimeRange(event.getValue().getTime(), to
.getTime());
eventBus.fireEvent(new TimeRangeChangeEvent(TimeMode.ABSOLUTE,
range));
widget.selectedHistory(null);
}
});
widget.timeTo().addValueChangeHandler(new ValueChangeHandler<Date>() {
@Override
public void onValueChange(ValueChangeEvent<Date> event) {
Date from = widget.timeFromValue().getValue();
if (from.after(event.getValue())) {
Window.alert("Incorrect 'to' date");
widget.timeToValue().setValue(new Date(), false);
return;
}
TimeRange range = new TimeRange(from.getTime(), event
.getValue().getTime());
eventBus.fireEvent(new TimeRangeChangeEvent(TimeMode.ABSOLUTE,
range));
widget.selectedHistory(null);
}
});
}
private void selectHistoryRange(TimeRange timeRange) {
boolean selected = false;
// assuming the ranges are sorted (we use a tree-map)
long range = 0;
for (Iterator<Long> it = historyRange2Button.keySet().iterator(); it
.hasNext();) {
range = it.next();
if (timeRange.getSeconds() <= range) {
widget.selectedHistory(historyRange2Button.get(range));
selected = true;
break;
}
}
if (!selected) {
// we get the last value of range
widget.selectedHistory(historyRange2Button.get(range));
}
}
private void initTimeWidget(ApplicationState appState) {
selectHistoryRange(appState.timeRange);
widget.timeToValue().setValue(new Date(appState.timeRange.to), false);
widget.timeFromValue().setValue(new Date(appState.timeRange.from),
false);
if (appState.timeMode.equals(TimeMode.HISTORY)) {
widget.selectedMode(widget.historyModeButton());
} else if (appState.timeMode.equals(TimeMode.ABSOLUTE)) {
widget.selectedMode(widget.absoluteModeButton());
}
}
@Override
public void go(HasWidgets container, ApplicationState appState) {
container.add((com.google.gwt.user.client.ui.Widget) widget);
initTimeWidget(appState);
}
}