/* * 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 com.facebook.tsdb.tsdash.client.event.AutoReloadEvent; import com.facebook.tsdb.tsdash.client.event.GraphEvent; import com.facebook.tsdb.tsdash.client.event.GraphEventHandler; import com.facebook.tsdb.tsdash.client.event.KeyboardShortcutEvent; import com.facebook.tsdb.tsdash.client.event.KeyboardShortcutHandler; import com.facebook.tsdb.tsdash.client.event.StateChangeEvent; import com.facebook.tsdb.tsdash.client.event.StateChangeHandler; import com.facebook.tsdb.tsdash.client.model.ApplicationState; import com.google.gwt.core.client.Scheduler; import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ChangeHandler; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.HasChangeHandlers; import com.google.gwt.event.dom.client.HasClickHandlers; import com.google.gwt.event.shared.HandlerManager; import com.google.gwt.user.client.ui.HasText; import com.google.gwt.user.client.ui.HasWidgets; import com.google.gwt.user.client.ui.Widget; public class AutoreloadPresenter implements Presenter { private int remaining; private Scheduler.RepeatingCommand activeCmd = null; private static int[] periodOptions = { 3, 5, 15 }; public interface AutoreloadWidget { HasClickHandlers startButton(); HasClickHandlers stopButton(); void setStartVisible(boolean visible); void setStopVisible(boolean visible); boolean isReloading(); void setPeriodVisible(boolean visible); void setStatusVisible(boolean visible); void setRemainingSeconds(int seconds); void selectPeriodOption(int index); int selectedPeriodOption(); void setPeriodOptions(int[] periodOptions); HasChangeHandlers period(); void setLoadingVisible(boolean visible); HasText loadingStatus(); } private final HandlerManager eventBus; private final AutoreloadWidget widget; public AutoreloadPresenter(HandlerManager eventBus, AutoreloadWidget widget) { this.eventBus = eventBus; this.widget = widget; bindWidget(); widget.setPeriodOptions(periodOptions); listenCtrlSpaceShortcut(); listenGraphEvents(); listenStateChange(); } private void bindWidget() { ClickHandler toggleHandler = new ClickHandler() { @Override public void onClick(ClickEvent event) { enable(!widget.isReloading()); eventBus.fireEvent(new AutoReloadEvent( AutoReloadEvent.Action.ENABLE, widget.isReloading(), getPeriodOption())); } }; widget.startButton().addClickHandler(toggleHandler); widget.stopButton().addClickHandler(toggleHandler); widget.period().addChangeHandler(new ChangeHandler() { @Override public void onChange(ChangeEvent event) { // fire period change eventBus.fireEvent(new AutoReloadEvent( AutoReloadEvent.Action.PERIOD_CHANGE, widget .isReloading(), getPeriodOption())); fireTimeCount(); } }); } private void listenStateChange() { eventBus.addHandler(StateChangeEvent.TYPE, new StateChangeHandler() { @Override public void onViewChange(StateChangeEvent event) { } @Override public void onMetricChange(StateChangeEvent event) { setByState(event.getAppState()); } @Override public void onTimeChange(StateChangeEvent event) { setByState(event.getAppState()); } @Override public void onPlotParamsChange(StateChangeEvent event) { } @Override public void onAutoReloadChange(StateChangeEvent event) { } @Override public void onScreenChange(StateChangeEvent event) { } }); } private void listenCtrlSpaceShortcut() { eventBus.addHandler(KeyboardShortcutEvent.TYPE, new KeyboardShortcutHandler() { @Override public void onCtrlSpace(KeyboardShortcutEvent event) { enable(!widget.isReloading()); eventBus.fireEvent(new AutoReloadEvent( AutoReloadEvent.Action.ENABLE, widget .isReloading(), getPeriodOption())); } @Override public void onCtrlF(KeyboardShortcutEvent event) { // ignore } }); } private void triggerReload() { if (!widget.isReloading()) { return; } widget.setStatusVisible(false); eventBus.fireEvent(new AutoReloadEvent(AutoReloadEvent.Action.LAUNCH, widget.isReloading(), getPeriodOption())); } private void listenGraphEvents() { eventBus.addHandler(GraphEvent.TYPE, new GraphEventHandler() { @Override public void onLoaded(GraphEvent event) { widget.setLoadingVisible(false); if (widget.isReloading()) { widget.setStatusVisible(true); fireTimeCount(); } } @Override public void onLoadingData(GraphEvent event) { widget.setLoadingVisible(true); widget.loadingStatus().setText("Loading data..."); } @Override public void onStartRendering(GraphEvent event) { widget.setLoadingVisible(true); widget.loadingStatus().setText("Rendering chart..."); } }); } private int getPeriodOption() { int index = widget.selectedPeriodOption(); return periodOptions[index]; } private void selectPeriodOption(int periodValue) { for (int i = 0; i < periodOptions.length; i++) { if (periodOptions[i] == periodValue) { widget.selectPeriodOption(i); break; } } } private void fireTimeCount() { remaining = getPeriodOption(); widget.setRemainingSeconds(remaining); activeCmd = new Scheduler.RepeatingCommand() { @Override public boolean execute() { if (activeCmd != this) { return false; } remaining--; if (remaining == 0) { // trigger time update triggerReload(); return false; } widget.setRemainingSeconds(remaining); return true; } }; Scheduler.get().scheduleFixedDelay(activeCmd, 1000); } private void enable(boolean autoreload) { widget.setLoadingVisible(false); widget.setStartVisible(!autoreload); widget.setStopVisible(autoreload); widget.setStatusVisible(autoreload); widget.setPeriodVisible(autoreload); if (autoreload) { fireTimeCount(); } } private void disable() { widget.setLoadingVisible(false); widget.setStartVisible(false); widget.setStopVisible(false); widget.setStatusVisible(false); widget.setPeriodVisible(false); } private void setByState(ApplicationState appState) { if (appState.needsAutoreload()) { enable(appState.autoReload); } else { disable(); } } @Override public void go(HasWidgets container, ApplicationState appState) { container.add((Widget) widget); selectPeriodOption(appState.reloadPeriod); setByState(appState); } }