/* * Copyright 2012 Axel Winkler, Daniel Dunér * * This file is part of Daxplore Presenter. * * Daxplore Presenter is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 2.1 of the License, or * (at your option) any later version. * * Daxplore Presenter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Daxplore Presenter. If not, see <http://www.gnu.org/licenses/>. */ package org.daxplore.presenter.client; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import org.daxplore.presenter.chart.ChartPanelPresenter; import org.daxplore.presenter.client.event.CloseWarningBannerEvent; import org.daxplore.presenter.client.event.CloseWarningBannerHandler; import org.daxplore.presenter.client.event.QueryReadyEvent; import org.daxplore.presenter.client.event.QueryReadyHandler; import org.daxplore.presenter.client.event.QueryUpdateEvent; import org.daxplore.presenter.client.event.QueryUpdateHandler; import org.daxplore.presenter.client.event.SelectionUpdateEvent; import org.daxplore.presenter.client.event.SelectionUpdateHandler; import org.daxplore.presenter.client.event.SetWarningBannerEvent; import org.daxplore.presenter.client.event.SetWarningBannerHandler; import org.daxplore.presenter.client.json.Groups; import org.daxplore.presenter.client.json.Perspectives; import org.daxplore.presenter.client.json.Prefix; import org.daxplore.presenter.client.model.StatDataServerModel; import org.daxplore.presenter.client.resources.DaxploreConfig; import org.daxplore.presenter.client.ui.ChartTypeOptionsPanel; import org.daxplore.presenter.client.ui.PerspectivePanel; import org.daxplore.presenter.client.ui.QuestionPanel; import org.daxplore.presenter.client.ui.StagePanel; import org.daxplore.presenter.client.ui.WarningBanner; import org.daxplore.presenter.shared.QueryDefinition; import org.daxplore.presenter.shared.QueryDefinition.QueryFlag; import org.daxplore.presenter.shared.QuestionMetadata; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.user.client.History; import com.google.gwt.user.client.ui.RootPanel; import com.google.inject.Inject; import com.google.web.bindery.event.shared.EventBus; /** * This acts as a central point in the application. * * <p>It is named "Presenter" after the Model-View-Presenter design pattern. The * project does not properly adhere to the MVP pattern, though.</p> */ public class Presenter implements ValueChangeHandler<String>, SelectionUpdateHandler, SetWarningBannerHandler, CloseWarningBannerHandler, QueryUpdateHandler, QueryReadyHandler { private final PerspectivePanel perspectivePanel; private final QuestionPanel questionPanel; private final ChartPanelPresenter chartPanelPresenter; private QuestionMetadata questionMetadata; private final EventBus eventBus; private DaxploreConfig config; private StatDataServerModel statDataServerModel; private final String prefix; private Perspectives perspectives; private Groups groups; private ChartTypeOptionsPanel optionsPanel; private StagePanel stagePanel; @Inject protected Presenter(PerspectivePanel perspectivePanel, QuestionPanel questionPanel, EventBus eventBus, ChartPanelPresenter chartPanelPresenter, ChartTypeOptionsPanel optionsPanel, QuestionMetadata questionMetadata, DaxploreConfig config, StatDataServerModel statDataServerModel, Prefix prefix, Perspectives perspectives, Groups groups, StagePanel stagePanel) { this.perspectivePanel = perspectivePanel; this.questionPanel = questionPanel; this.questionMetadata = questionMetadata; this.chartPanelPresenter = chartPanelPresenter; this.eventBus = eventBus; this.config = config; this.statDataServerModel = statDataServerModel; this.prefix = prefix.getPrefix(); this.perspectives = perspectives; this.groups = groups; this.optionsPanel = optionsPanel; this.stagePanel = stagePanel; SelectionUpdateEvent.register(eventBus, this); SetWarningBannerEvent.register(eventBus, this); CloseWarningBannerEvent.register(eventBus, this); QueryUpdateEvent.register(eventBus, this); QueryReadyEvent.register(eventBus, this); History.addValueChangeHandler(this); } /** * Create a new query. * * <p>The query is constructed based on user selections in the current * site.</p> * * <p>You can choose if you want to set browser history or not.</p> * * @param setHistory * true, if the browser history should be set */ private void makeQuery(boolean setHistory) { List<QueryFlag> flags = new LinkedList<>(); String questionID = questionPanel.getQuestionID(); String perspectiveID = perspectivePanel.getQuestionID(); List<Integer> perspectiveOptions = perspectivePanel.getPerspectiveOptions(); if(questionMetadata.hasSecondary(questionID) && questionMetadata.hasSecondary(perspectiveID) && optionsPanel.useSecondarySelected()) { flags.add(QueryFlag.SECONDARY); } if(perspectiveOptions.size()==0 || perspectivePanel.useTotalSelected()) { flags.add(QueryFlag.TOTAL); } QueryDefinition queryDefinition = new QueryDefinition(questionMetadata, perspectiveID, questionID, perspectiveOptions, flags); eventBus.fireEvent(new QueryUpdateEvent(queryDefinition)); String historyString = queryDefinition.getAsString(); if (setHistory) { History.newItem(historyString, false); Tracking.googleAnalyticsEvent(prefix + " chart", queryDefinition.getAsHumanString(prefix)); Tracking.iFrame(historyString); } } /** * Restore the page to a state defined by a string as defined by * QueryDefinition. * * @param storeString * the string that defines the state to be restored * @param setHistory * true, if the browser history should be set */ public void restore(String storeString, boolean setHistory) { try { QueryDefinition queryDefinition = new QueryDefinition(questionMetadata, storeString); Tracking.googleAnalyticsEvent(prefix + " chart", queryDefinition.getAsHumanString(prefix)); Tracking.iFrame(queryDefinition.getAsString()); eventBus.fireEvent(new QueryUpdateEvent(queryDefinition)); if (setHistory) { String historyString = queryDefinition.getAsString(); History.newItem(historyString, false); } } catch (IllegalArgumentException e) { showDefaultChart(); } } public void showDefaultChart() { String firstQuestionID = ""; for(int i=0; i<groups.getGroupCount(); i++) { List<String> questionIDs = groups.getQuestionIDs(i); if(questionIDs.size()>0) { firstQuestionID = questionIDs.get(0); break; } } String firstPerspectiveID = perspectives.getQuestionIDs().get(0); List<Integer> selectedOptions = new ArrayList<>(0); int selectedPerspectiveOptions = Math.min(questionMetadata.getOptionCount(firstPerspectiveID), config.defaultSelectedPerspectiveOptions()); for(int i=0; i<selectedPerspectiveOptions; i++) { selectedOptions.add(i); } ArrayList<QueryFlag> flags = new ArrayList<>(0); QueryDefinition queryDefinition = new QueryDefinition(questionMetadata, firstQuestionID, firstPerspectiveID, selectedOptions, flags); eventBus.fireEvent(new QueryUpdateEvent(queryDefinition)); } /** * {@inheritDoc} */ @Override public void onValueChange(ValueChangeEvent<String> event) { String req = event.getValue(); if (req != null) { restore(req, false); } } /** * {@inheritDoc} */ @Override public void onSelectionUpdate(SelectionUpdateEvent event) { makeQuery(true); } /** * {@inheritDoc} */ @Override public void onSetWarningBanner(SetWarningBannerEvent event) { setWarningBanner(event.getWarningBanner()); } /** * {@inheritDoc} */ @Override public void onCloseWarningBanner(CloseWarningBannerEvent event) { removeWarningBanner(); } private WarningBanner currentWarning = null; private void setWarningBanner(WarningBanner warning) { RootPanel warningSection = RootPanel.get("ID-general-warning"); if (currentWarning != null) { warningSection.remove(currentWarning); } currentWarning = warning; warningSection.add(warning); } private void removeWarningBanner() { RootPanel warningSection = RootPanel.get("ID-general-warning"); if (currentWarning != null) { warningSection.remove(currentWarning); currentWarning = null; } } /** * {@inheritDoc} */ @Override public void onQueryUpdate(QueryUpdateEvent event) { statDataServerModel.makeRequest(event.getQueryDefinition()); } /** * {@inheritDoc} */ @Override public void onQueryReady(QueryReadyEvent event) { chartPanelPresenter.onQueryReady(event.getQueryDefinition(), event.getQueryData()); stagePanel.setLegend(chartPanelPresenter.getExternalLegend()); } }