package org.sigmah.client.ui.view; /* * #%L * Sigmah * %% * Copyright (C) 2010 - 2016 URD * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% */ import java.util.Collection; import java.util.HashSet; import org.sigmah.client.i18n.I18N; import org.sigmah.client.ui.presenter.ApplicationPresenter; import org.sigmah.client.ui.presenter.zone.AppLoaderPresenter; import org.sigmah.client.ui.presenter.zone.AuthenticationBannerPresenter; import org.sigmah.client.ui.presenter.zone.MenuBannerPresenter; import org.sigmah.client.ui.presenter.zone.MessageBannerPresenter; import org.sigmah.client.ui.presenter.zone.OfflineBannerPresenter; import org.sigmah.client.ui.presenter.zone.OrganizationBannerPresenter; import org.sigmah.client.ui.view.base.AbstractView; import org.sigmah.client.ui.view.base.HasPageMessage; import org.sigmah.client.ui.view.zone.MessageBannerView; import org.sigmah.client.ui.widget.Loadable; import org.sigmah.client.util.ClientUtils; import org.sigmah.client.util.MessageType; import com.extjs.gxt.ui.client.widget.Viewport; import com.extjs.gxt.ui.client.widget.layout.FitLayout; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.HasClickHandlers; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Anchor; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.InlineLabel; import com.google.gwt.user.client.ui.IsWidget; import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; import com.google.inject.Singleton; /** * <p> * Application frame view. * </p> * <p> * This is the only <em>view</em> that does not inherit {@link AbstractView}. * </p> * * @author Denis Colliot (dcolliot@ideia.fr) * @author Claire Yang (cyang@ideia.fr) * @author Tom Miette (tmiette@ideia.fr) */ @Singleton public class ApplicationView implements ApplicationPresenter.View, HasPageMessage { /** * <p> * Application viewport displaying {@code com.extjs.gxt.ui} components. * </p> * <p> * Slightly edited version of {@link com.extjs.gxt.ui.client.widget.Viewport} that do not necessarily span to the * entire page dimensions. * A simple inheritance is not possible due to {@link #onAttach()} method implementation. * </p> * * @author Denis Colliot (dcolliot@ideia.fr) */ private static class ApplicationViewport extends Viewport { /** * The widgets which dimensions should be taken in account during viewport resizing. */ private final Collection<Widget> widgets; private Integer calculatedWidth; private Integer calculatedHeight; /** * Initializes the application viewport. * * @param widgets * The widgets which dimensions should be taken in account during viewport resizing. */ public ApplicationViewport(final Collection<Widget> widgets) { super(); this.widgets = widgets; setLayout(new FitLayout()); syncSize(); setBorders(false); } /** * <p> * {@inheritDoc} * </p> * <p> * Takes care of {@link #widgets} heights and {@link ApplicationView#contentPanel} paddings during update. * </p> */ @Override public void setSize(final int width, final int height) { int extraHeight = 0; int extraWidth = 0; // Calculating dynamically extra dimensions (in pixels). if (widgets != null && !isCalculatedSize(width, height)) { for (final Widget widget : widgets) { if (widget == null || !widget.isAttached()) { continue; } extraHeight += widget.getOffsetHeight(); } extraHeight += CONTENT_PADDING_TOP + CONTENT_PADDING_BOTTOM; extraWidth += CONTENT_PADDING_LEFT + CONTENT_PADDING_RIGHT; } // Updating viewport size. calculatedWidth = width - extraWidth; calculatedHeight = height - extraHeight; super.setSize(calculatedWidth, calculatedHeight); } /** * Is the given size equals to last calculated size? * * @param width * The received width. * @param height * The received height. * @return {@code true} if the given size equals to last calculated size. */ private boolean isCalculatedSize(final int width, final int height) { return new Integer(width).equals(calculatedWidth) && new Integer(height).equals(calculatedHeight); } } // Content panel dynamic padding values. private static final int CONTENT_PADDING_TOP = 10; private static final int CONTENT_PADDING_BOTTOM = CONTENT_PADDING_TOP; private static final int CONTENT_PADDING_LEFT = 15; private static final int CONTENT_PADDING_RIGHT = CONTENT_PADDING_LEFT; /** * <p> * Header area widgets which height should be taken in account for viewport dimensions. * </p> * <p> * Make sure to update {@link #viewport} dimensions if one of the referenced widgets dimensions is dynamically * changed. * </p> */ private final Collection<Widget> headerWidgets; private Panel panel; private Panel headerPanel; private Panel headerLeftPanel; private Panel headerMenuPanel; private Panel headerMiddlePanel; private Panel headerRightPanel; private Panel menuPanel; private Panel messagePanel; private Panel pageMessagePanel; private HTML pageMessageLabel; private Panel contentPanel; private ApplicationViewport viewport; private Anchor creditsMenu; private Anchor bugReportMenu; private Anchor helpMenu; /** * Instantiates the application frame. */ public ApplicationView() { buildView(); headerWidgets = new HashSet<Widget>(); headerWidgets.add(headerPanel); headerWidgets.add(menuPanel); headerWidgets.add(messagePanel); // Root panel initialization. RootPanel.get().add(this); // Viewport initialization (after widgets build). viewport = new ApplicationViewport(headerWidgets); contentPanel.add(viewport); } /** * Builds the view. */ private void buildView() { // -- // Header. // -- headerLeftPanel = new FlowPanel(); headerLeftPanel.getElement().setId("header-left"); headerMiddlePanel = new FlowPanel(); headerMiddlePanel.getElement().setId("header-middle"); headerRightPanel = new FlowPanel(); headerRightPanel.getElement().setId("header-right"); headerPanel = new FlowPanel(); headerPanel.getElement().setId("header"); headerPanel.add(headerLeftPanel); headerPanel.add(headerMiddlePanel); headerPanel.add(headerRightPanel); // Menu. creditsMenu = new Anchor(I18N.CONSTANTS.credits()); bugReportMenu = new Anchor(I18N.CONSTANTS.bugReport()); helpMenu = new Anchor(I18N.CONSTANTS.help()); headerMenuPanel = new FlowPanel(); headerMenuPanel.getElement().setId("header-menu"); headerMenuPanel.add(creditsMenu); headerMenuPanel.add(new InlineLabel(" | ")); headerMenuPanel.add(bugReportMenu); headerMenuPanel.add(new InlineLabel(" | ")); headerMenuPanel.add(helpMenu); // -- // Tabs. // -- menuPanel = new FlowPanel(); menuPanel.getElement().setId("menu"); // -- // Message. // -- messagePanel = new FlowPanel(); messagePanel.getElement().setId("app-message"); pageMessagePanel = new SimplePanel(); pageMessagePanel.addStyleName(MessageBannerView.CSS_PANEL); pageMessagePanel.setVisible(false); pageMessageLabel = new HTML(); pageMessageLabel.addStyleName(MessageBannerView.CSS_MESSAGE); pageMessagePanel.add(pageMessageLabel); // -- // Content. // -- contentPanel = new SimplePanel(); contentPanel.getElement().setId("content"); // Dynamic paddings. contentPanel.getElement().getStyle().setPaddingTop(CONTENT_PADDING_TOP, Unit.PX); contentPanel.getElement().getStyle().setPaddingBottom(CONTENT_PADDING_BOTTOM, Unit.PX); contentPanel.getElement().getStyle().setPaddingLeft(CONTENT_PADDING_LEFT, Unit.PX); contentPanel.getElement().getStyle().setPaddingRight(CONTENT_PADDING_RIGHT, Unit.PX); // -- // Loading screen. // -- // -- // Main panel. // -- panel = new FlowPanel(); panel.getElement().setId("application"); panel.add(headerPanel); panel.add(menuPanel); panel.add(messagePanel); panel.add(contentPanel); } /** * {@inheritDoc} */ @Override public Widget asWidget() { return panel; } /** * {@inheritDoc} */ @Override public void initialize() { // Not used (everything is initialized in the constructor). } /** * {@inheritDoc} */ @Override public void onViewRevealed() { // Not used. } /** * {@inheritDoc} */ @Override public Loadable[] getLoadables() { // Not used. return null; } /** * {@inheritDoc} */ @Override public boolean isFullPage() { // Not used. return false; } /** * {@inheritDoc} */ @Override public void hideLoadingPanel() { final RootPanel panel = RootPanel.get("loading"); if (panel != null) { panel.setVisible(false); } } /** * {@inheritDoc} */ @Override public void initZones(OrganizationBannerPresenter.View organizationBannerView, AuthenticationBannerPresenter.View authenticationBannerPresenter, OfflineBannerPresenter.View offlineBannerPresenter, AppLoaderPresenter.View appLoaderPresenter, MenuBannerPresenter.View menuBannerPresenter, MessageBannerPresenter.View messageBannerPresenter) { // Organization logo. headerLeftPanel.add(organizationBannerView.getLogoPanel()); // User name. headerMiddlePanel.add(authenticationBannerPresenter.getNamePanel()); // Organization name. headerMiddlePanel.add(organizationBannerView.getNamePanel()); // User name. headerRightPanel.add(authenticationBannerPresenter.getLogoutPanel()); // Header menu. headerRightPanel.add(headerMenuPanel); // Offline status. headerRightPanel.add(offlineBannerPresenter.getStatusPanel()); // Loader. headerRightPanel.add(appLoaderPresenter.getLoaderPanel()); // Menu. menuPanel.add(menuBannerPresenter.getMenuPanel()); final HTML clear = new HTML(); clear.getElement().getStyle().setProperty("clear", "both"); menuPanel.add(clear); // Ensures 'menuPanel' proper height in DOM tree. // Application message. messagePanel.add(messageBannerPresenter.getMessagePanel()); messagePanel.add(pageMessagePanel); } /** * {@inheritDoc} */ @Override public void showPresenter(final IsWidget presenterWidget, boolean fullPage) { viewport.removeFromParent(); if (fullPage) { // View is displayed on entire page. viewport = new ApplicationViewport(null); RootPanel.get().add(viewport); } else { // View is displayed within content panel. viewport = new ApplicationViewport(headerWidgets); contentPanel.add(viewport); } viewport.add(presenterWidget.asWidget()); viewport.layout(); } /** * {@inheritDoc} */ @Override public HasClickHandlers getCreditsHandler() { return creditsMenu; } /** * {@inheritDoc} */ @Override public HasClickHandlers getBugReportHandler() { return bugReportMenu; } /** * {@inheritDoc} */ @Override public HasClickHandlers getHelpHandler() { return helpMenu; } /** * {@inheritDoc} */ @Override public void updateViewportSize() { viewport.setSize(Window.getClientWidth(), Window.getClientHeight()); } /** * {@inheritDoc} */ @Override public void setPageMessageVisible(boolean visible) { pageMessagePanel.setVisible(visible); } /** * {@inheritDoc} */ @Override public void setPageMessage(String html) { setPageMessageVisible(ClientUtils.isNotBlank(html)); pageMessageLabel.setHTML(html); } /** * {@inheritDoc} */ @Override public void setPageMessage(String html, MessageType type) { setPageMessage(html); setPageMessageType(type); } /** * {@inheritDoc} */ @Override public void setPageMessageType(MessageType type) { MessageType.applyStyleName(pageMessagePanel, type); } }