/* * Copyright (c) 2010-2016 Evolveum * * 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.evolveum.midpoint.web.component.menu; import com.evolveum.midpoint.gui.api.component.BasePanel; import com.evolveum.midpoint.gui.api.page.PageBase; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.web.component.breadcrumbs.Breadcrumb; import com.evolveum.midpoint.web.component.breadcrumbs.BreadcrumbPageClass; import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; import com.evolveum.midpoint.web.security.SecurityUtils; import org.apache.wicket.AttributeModifier; import org.apache.wicket.IPageFactory; import org.apache.wicket.Session; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.markup.html.AjaxLink; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.WebPage; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.link.Link; import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.model.AbstractReadOnlyModel; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import org.apache.wicket.model.PropertyModel; import org.apache.wicket.request.flow.RedirectToUrlException; import java.io.Serializable; import java.util.List; /** * @author Viliam Repan (lazyman) */ public class MainMenuPanel extends BasePanel<MainMenuItem> { private static final long serialVersionUID = 1L; private static final String ID_ITEM = "item"; private static final String ID_LINK = "link"; private static final String ID_LABEL = "label"; private static final String ID_ICON = "icon"; private static final String ID_SUBMENU = "submenu"; private static final String ID_ARROW = "arrow"; private static final String ID_BUBBLE = "bubble"; private static final String ID_SUB_ITEM = "subItem"; private static final String ID_SUB_LINK = "subLink"; private static final String ID_SUB_LABEL = "subLabel"; private static final Trace LOGGER = TraceManager.getTrace(MainMenuPanel.class); public MainMenuPanel(String id, IModel<MainMenuItem> model) { super(id, model); initLayout(); } private void initLayout() { final MainMenuItem menu = getModelObject(); WebMarkupContainer item = new WebMarkupContainer(ID_ITEM); item.add(AttributeModifier.replace("class", new AbstractReadOnlyModel<String>() { private static final long serialVersionUID = 1L; @Override public String getObject() { if (menu.isMenuActive((WebPage) getPage())) { return "active"; } for (MenuItem item : menu.getItems()) { if (item.isMenuActive((WebPage) getPage())) { return "active"; } } return !menu.getItems().isEmpty() ? "treeview" : null; } })); add(item); WebMarkupContainer link; if (menu.getPageClass() != null) { link = new AjaxLink(ID_LINK) { private static final long serialVersionUID = 1L; @Override public void onClick(AjaxRequestTarget target) { mainMenuPerformed(menu); } }; } else if (menu instanceof AdditionalMenuItem){ link = new AjaxLink(ID_LINK) { private static final long serialVersionUID = 1L; @Override public void onClick(AjaxRequestTarget target) { additionalMenuPerformed(menu); } }; } else { link = new WebMarkupContainer(ID_LINK); } item.add(link); WebMarkupContainer icon = new WebMarkupContainer(ID_ICON); icon.add(AttributeModifier.replace("class", new PropertyModel<>(menu, MainMenuItem.F_ICON_CLASS))); link.add(icon); Label label = new Label(ID_LABEL, menu.getNameModel()); link.add(label); final PropertyModel<String> bubbleModel = new PropertyModel<>(menu, MainMenuItem.F_BUBBLE_LABEL); Label bubble = new Label(ID_BUBBLE, bubbleModel); bubble.add(new VisibleEnableBehaviour() { private static final long serialVersionUID = 1L; @Override public boolean isVisible() { return bubbleModel.getObject() != null; } }); link.add(bubble); WebMarkupContainer arrow = new WebMarkupContainer(ID_ARROW); arrow.add(new VisibleEnableBehaviour() { private static final long serialVersionUID = 1L; @Override public boolean isVisible() { return !menu.getItems().isEmpty() && bubbleModel.getObject() == null; } }); link.add(arrow); WebMarkupContainer submenu = new WebMarkupContainer(ID_SUBMENU); submenu.add(new VisibleEnableBehaviour() { private static final long serialVersionUID = 1L; @Override public boolean isVisible() { return !menu.getItems().isEmpty(); } }); item.add(submenu); ListView<MenuItem> subItem = new ListView<MenuItem>(ID_SUB_ITEM, new Model((Serializable) menu.getItems())) { @Override protected void populateItem(ListItem<MenuItem> listItem) { createSubmenu(listItem); } }; submenu.add(subItem); } private void createSubmenu(final ListItem<MenuItem> listItem) { final MenuItem menuItem = listItem.getModelObject(); listItem.add(AttributeModifier.replace("class", new AbstractReadOnlyModel<String>() { private static final long serialVersionUID = 1L; @Override public String getObject() { return menuItem.isMenuActive((WebPage) getPage()) ? "active" : null; } })); Link<String> subLink = new Link<String>(ID_SUB_LINK) { private static final long serialVersionUID = 1L; @Override public void onClick() { menuItemPerformed(menuItem); } }; listItem.add(subLink); Label subLabel = new Label(ID_SUB_LABEL, menuItem.getNameModel()); subLink.add(subLabel); listItem.add(new VisibleEnableBehaviour() { private static final long serialVersionUID = 1L; @Override public boolean isVisible() { MenuItem mi = listItem.getModelObject(); boolean visible = true; if (mi.getVisibleEnable() != null) { visible = mi.getVisibleEnable().isVisible(); } return visible && SecurityUtils.isMenuAuthorized(mi); } @Override public boolean isEnabled() { MenuItem mi = listItem.getModelObject(); if (mi.getVisibleEnable() == null) { return true; } return mi.getVisibleEnable().isEnabled(); } }); } private void menuItemPerformed(MenuItem menu) { LOGGER.trace("menuItemPerformed: {}", menu); IPageFactory pFactory = Session.get().getPageFactory(); WebPage page = pFactory.newPage(menu.getPageClass(), menu.getParams()); if (!(page instanceof PageBase)) { setResponsePage(page); return; } PageBase pageBase = (PageBase) page; // IMPORTANT: we need to re-bundle the name to a new models // that will not be connected to the old page reference // otherwise the old page will somehow remain in the memory // I have no idea how it could do that and especially how // several old pages can remain in memory. But if the model // is not re-bundled here then the page size grows and never // falls. MainMenuItem mainMenuItem = getModelObject(); String name = mainMenuItem.getNameModel().getObject(); Breadcrumb bc = new Breadcrumb(new Model<>(name)); bc.setIcon(new Model<>(mainMenuItem.getIconClass())); pageBase.addBreadcrumb(bc); List<MenuItem> items = mainMenuItem.getItems(); if (!items.isEmpty() && mainMenuItem.isInsertDefaultBackBreadcrumb()) { MenuItem first = items.get(0); IModel<String> nameModel = first.getNameModel(); BreadcrumbPageClass invisibleBc = new BreadcrumbPageClass(new Model<>(nameModel.getObject()), first.getPageClass(), first.getParams()); invisibleBc.setVisible(false); pageBase.addBreadcrumb(invisibleBc); } setResponsePage(page); } private void mainMenuPerformed(MainMenuItem menu) { LOGGER.trace("mainMenuPerformed: {}", menu); if (menu.getParams() == null) { setResponsePage(menu.getPageClass()); } else { setResponsePage(menu.getPageClass(), menu.getParams()); } } private void additionalMenuPerformed(MainMenuItem menu) { LOGGER.trace("additionalMenuPerformed: {}", menu); if (menu.getPageClass() != null) { setResponsePage(menu.getPageClass()); } else { throw new RedirectToUrlException(((AdditionalMenuItem)menu).getTargetUrl()); } } }