package org.sigmah.client.ui.widget; /* * #%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 com.google.gwt.dom.client.Style; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.sigmah.client.page.Page; import org.sigmah.client.page.PageRequest; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.ui.AbsolutePanel; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.IsWidget; import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; import org.sigmah.client.i18n.I18N; import org.sigmah.shared.command.result.Authentication; import org.sigmah.shared.dto.referential.GlobalPermissionEnum; /** * Sub-menu widget. * * @author Maxime Lombard (mlombard@ideia.fr) * @author Denis Colliot (dcolliot@ideia.fr) */ public class SubMenuWidget implements IsWidget { /** * id of agenda sub menu. */ private final static String AGENDA_SUB_MENU_ID="agendaSubMenuId"; /** * Sub-menu orientation. */ public static enum Orientation { /** * Vertical sub-menu layout. */ VERTICAL, /** * Horizontal sub-menu layout. */ HORIZONTAL; private static final String CSS_SUBMENU = "sub-menu"; private static final String CSS_HORIZONTAL = "horizontal"; private static final String CSS_VERTICAL = "vertical"; /** * Return the given {@code orientation} corresponding {@link Panel} widget. * * @param orientation * The {@link Orientation} instance. * @return The given {@code orientation} corresponding {@link Panel} widget. * @throws IllegalArgumentException * If given {@code orientation} is {@code null}. */ private static Panel asPanel(final Orientation orientation) { if (orientation == null) { throw new IllegalArgumentException("Invalid orientation value."); } final Panel panel; switch (orientation) { case VERTICAL: panel = new VerticalPanel(); panel.setStyleName(CSS_SUBMENU); panel.addStyleName(CSS_VERTICAL); break; case HORIZONTAL: panel = new HorizontalPanel(); panel.setStyleName(CSS_SUBMENU); panel.addStyleName(CSS_HORIZONTAL); break; default: throw new IllegalArgumentException("Invalid orientation value."); } return panel; } } /** * Sub-menu listener interface. */ public static interface SubMenuListener { /** * Method executed on sub-menu click. * * @param menuItem * The selected sub-menu item. */ void onSubMenuClick(final SubMenuItem menuItem); } // Widget CSS style name. private static final String CSS_SUBMENU_ACTIVE = "active"; // Widget containers. private final Panel menuWrapper; private final Panel menuPanel; // Stores the MenuItem. private final List<SubMenuItem> menuItems; // Listeners. private final List<SubMenuListener> listeners; public SubMenuWidget(final Orientation orientation, final Map<Page, String> linksMap) { menuItems = new ArrayList<SubMenuItem>(); listeners = new ArrayList<SubMenuListener>(); menuPanel = Orientation.asPanel(orientation); menuWrapper = new AbsolutePanel(); menuWrapper.add(menuPanel); for (final Page linkedPage : linksMap.keySet()) { addMenu(linkedPage, linksMap.get(linkedPage)); } } /** * {@inheritDoc} */ @Override public Widget asWidget() { return menuWrapper; } /** * Registers the given {@code listener} to the widget. * * @param listener * The {@link SubMenuListener} instance. Does nothing if {@code null}. */ public void addListener(final SubMenuListener listener) { if (listener == null) { return; } listeners.add(listener); } /** * Initialize the menu widget regarding the given {@code currentPage}. * * @param currentPage * The current active page, may be {@code null}. */ public void initializeMenu(final Page currentPage, final Authentication authentication) { if (currentPage == null) { return; } for (final SubMenuItem menuItem : menuItems) { final PageRequest request = menuItem.getRequest(); if (request != null && currentPage == request.getPage()) { activeMenu(menuItem); } menuItem.setVisible(menuItem.hasRequiredPermissions(authentication)); } } /** * Changes the required permissions to view the menu item associated to * the given <code>page</code>. * * @param page * Page associated to the menu item to edit. * @param requiredPermissions * Required permissions to access this menu item. */ public void setRequiredPermissions(Page page, GlobalPermissionEnum... requiredPermissions) { for (final SubMenuItem menuItem : menuItems) { final PageRequest request = menuItem.getRequest(); if (request != null && page == request.getPage()) { menuItem.setRequiredPermissions(requiredPermissions); } } } /** * Method to add menu item to the sub-menu * * @param linkedPage * @param title */ private void addMenu(final Page linkedPage, final String title) { final SubMenuItem menuItem = new SubMenuItem(linkedPage); menuItem.setMenuItemTitle(title); if(Page.PROJECT_CALENDAR==linkedPage){ menuItem.getElement().setId(AGENDA_SUB_MENU_ID); } menuItem.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { if (isActive(menuItem)) { return; } // Should not activate the menu here. // UI update should be done once target page has been loaded. fireEvent(menuItem); } }); menuItems.add(menuItem); menuPanel.add(menuItem); } /** * Checks if the given menu item is active. * * @param menuItem * The menu item. * @return <code>true</code> if the menu item is active, <code>false</code> otherwise. */ private boolean isActive(final SubMenuItem menuItem) { if (menuItem == null) { return false; } return menuItem.getStyleName().contains(CSS_SUBMENU_ACTIVE); } /** * Fires the "menuActivated" event for the given menuItem. * * @param menuItem * The sub-menu item. */ private void fireEvent(final SubMenuItem menuItem) { for (final SubMenuListener listener : listeners) { listener.onSubMenuClick(menuItem); } } /** * Activates the given tab. * * @param tab * The tab. */ private void activeMenu(final SubMenuItem menuItem) { if (menuItem == null) { return; } for (final SubMenuItem item : menuItems) { item.removeStyleName(CSS_SUBMENU_ACTIVE); } menuItem.addStyleName(CSS_SUBMENU_ACTIVE); } /** * Show or hide the given <code>menuItem</code>. * * @param menuItem * Menu item to show or hide. * @param visible * <code>true</code> to show the item, <code>false</code> to hide it. */ private void setMenuVisibility(final SubMenuItem menuItem, final boolean visible) { if(visible) { menuItem.getElement().getStyle().clearDisplay(); } else { menuItem.getElement().getStyle().setDisplay(Style.Display.NONE); } } }