Skip to content

Commit

Permalink
added tabs icon support for tabbed panel
Browse files Browse the repository at this point in the history
  • Loading branch information
1azyman committed Jan 4, 2023
1 parent 8600713 commit 0dfde33
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
package com.evolveum.midpoint.gui.api.component.tabs;

import com.evolveum.midpoint.gui.api.model.CountModelProvider;
import com.evolveum.midpoint.gui.api.model.CssIconModelProvider;
import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour;
import org.apache.wicket.model.IModel;

Expand All @@ -15,7 +16,7 @@
*
* @author semancik
*/
public abstract class CountablePanelTab extends PanelTab implements CountModelProvider {
public abstract class CountablePanelTab extends PanelTab implements CountModelProvider, CssIconModelProvider {

private static final long serialVersionUID = 1L;

Expand Down Expand Up @@ -44,5 +45,10 @@ public String getObject() {
};
}

@Override
public IModel<String> getCssIconModel() {
return () -> null;
}

public abstract String getCount();
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
*/
package com.evolveum.midpoint.gui.api.model;

import com.evolveum.midpoint.gui.api.GuiStyleConstants;

import org.apache.wicket.model.IModel;

/**
Expand All @@ -24,4 +26,20 @@ public interface CountModelProvider {
*/
IModel<String> getCountModel();

default IModel<String> getCountCssClassModel() {
return () -> {
IModel<String> countModel = getCountModel();

if (countModel == null) {
return GuiStyleConstants.CLASS_BADGE_PASSIVE;
}

String count = countModel.getObject();
if ("0".equals(count)) {
return GuiStyleConstants.CLASS_BADGE_PASSIVE;
} else {
return GuiStyleConstants.CLASS_BADGE_ACTIVE;
}
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright (c) 2010-2023 Evolveum and contributors
*
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
*/

package com.evolveum.midpoint.gui.api.model;

import org.apache.wicket.model.IModel;

/**
* Created by Viliam Repan (lazyman).
*/
@FunctionalInterface
public interface CssIconModelProvider {

IModel<String> getCssIconModel();
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
<div class="card-header p-0 border-bottom-0">
<ul class="nav nav-tabs" wicket:id="tabs-container">
<li class="nav-item" wicket:id="tabs">
<a class="nav-link" href="#" wicket:id="link">
<a class="nav-link d-flex gap-2 align-items-center" href="#" wicket:id="link">
<i wicket:id="icon"/>
<span wicket:id="title"/>
<small class="badge" wicket:id="count"/>
</a>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.io.Serializable;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Component;
import org.apache.wicket.WicketRuntimeException;
Expand All @@ -28,8 +29,9 @@
import org.apache.wicket.util.lang.Args;
import org.jetbrains.annotations.Nullable;

import com.evolveum.midpoint.gui.api.GuiStyleConstants;
import com.evolveum.midpoint.gui.api.model.CountModelProvider;
import com.evolveum.midpoint.gui.api.model.CssIconModelProvider;
import com.evolveum.midpoint.web.component.util.VisibleBehaviour;

/**
* @author lazyman
Expand All @@ -49,6 +51,7 @@ public class TabbedPanel<T extends ITab> extends Panel {
protected static final String ID_TITLE = "title";
protected static final String ID_COUNT = "count";
protected static final String ID_LINK = "link";
private static final String ID_ICON = "icon";

private final IModel<List<T>> tabs;
/**
Expand All @@ -66,13 +69,13 @@ public TabbedPanel(final String id, final List<T> tabs, @Nullable RightSideItemP
}

public TabbedPanel(final String id, final List<T> tabs, IModel<Integer> model, @Nullable RightSideItemProvider rightSideItemProvider) {
this(id, new Model((Serializable) tabs), model, rightSideItemProvider);
this(id, Model.ofList(tabs), model, rightSideItemProvider);
}

/**
* Constructor
*
* @param id component id
* @param id component id
* @param tabs list of ITab objects used to represent tabs
*/
public TabbedPanel(final String id, final IModel<List<T>> tabs) {
Expand All @@ -82,16 +85,16 @@ public TabbedPanel(final String id, final IModel<List<T>> tabs) {
/**
* Constructor
*
* @param id component id
* @param tabs list of ITab objects used to represent tabs
* @param id component id
* @param tabs list of ITab objects used to represent tabs
* @param model model holding the index of the selected tab
*/
public TabbedPanel(final String id, final IModel<List<T>> tabs, IModel<Integer> model, RightSideItemProvider rightSideItemProvider) {
super(id, model);

this.tabs = Args.notNull(tabs, "tabs");

final IModel<Integer> tabCount = new IModel<Integer>() {
final IModel<Integer> tabCount = new IModel<>() {
private static final long serialVersionUID = 1L;

@Override
Expand Down Expand Up @@ -123,7 +126,6 @@ protected LoopItem newItem(final int iteration) {
loop.setOutputMarkupId(true);
loop.setOutputMarkupPlaceholderTag(true);


tabsContainer.add(loop);

WebMarkupContainer rightSideTabItem = new WebMarkupContainer(RIGHT_SIDE_TAB_ITEM_ID);
Expand All @@ -144,38 +146,33 @@ protected void populateLoopItem(LoopItem item) {

final WebMarkupContainer titleLink = newLink(ID_LINK, index);
titleLink.add(AttributeAppender.append("class", () -> getSelectedTab() == index ? getSelectedTabCssClass() : ""));

titleLink.add(newTitle(ID_TITLE, tab.getTitle(), index));
titleLink.setOutputMarkupPlaceholderTag(true);
titleLink.setOutputMarkupId(true);
item.add(titleLink);

final IModel<String> countModel;
IModel<String> iconCssClass = null;
if (tab instanceof CssIconModelProvider) {
iconCssClass = ((CssIconModelProvider) tab).getCssIconModel();
}
titleLink.add(newIcon(ID_ICON, iconCssClass));
titleLink.add(newTitle(ID_TITLE, tab.getTitle(), index));

final IModel<String> count;
final IModel<String> countCssClass;
if (tab instanceof CountModelProvider) {
countModel = ((CountModelProvider)tab).getCountModel();
CountModelProvider cmp = (CountModelProvider) tab;
count = cmp.getCountModel();
countCssClass = cmp.getCountCssClassModel();
} else {
countModel = null;
count = null;
countCssClass = null;
}
Label countLabel = new Label(ID_COUNT, countModel);
countLabel.setVisible(countModel != null);

Label countLabel = new Label(ID_COUNT, count);
countLabel.setOutputMarkupId(true);
countLabel.setOutputMarkupPlaceholderTag(true);
countLabel.add(AttributeModifier.append("class", new IModel<String>() {
private static final long serialVersionUID = 1L;

@Override
public String getObject() {
if (countModel == null) {
return GuiStyleConstants.CLASS_BADGE_PASSIVE;
}
String count = countModel.getObject();
if ("0".equals(count)) {
return GuiStyleConstants.CLASS_BADGE_PASSIVE;
} else {
return GuiStyleConstants.CLASS_BADGE_ACTIVE;
}
}
}));
countLabel.add(AttributeModifier.append("class", () -> countCssClass != null ? countCssClass.getObject() : null));
countLabel.add(new VisibleBehaviour(() -> count != null));
titleLink.add(countLabel);
}

Expand Down Expand Up @@ -264,26 +261,25 @@ protected void onBeforeRender() {
super.onBeforeRender();
}


/**
* @return the value of css class attribute that will be added to last tab. The default value is
* <code>last</code>
* <code>last</code>
*/
protected String getLastTabCssClass() {
return "";
}

/**
* @return the value of css class attribute that will be added to a div containing the tabs. The
* default value is <code>tab-row</code>
* default value is <code>tab-row</code>
*/
protected String getTabContainerCssClass() {
return "tab-row";
}

/**
* @return the value of css class attribute that will be added to selected tab. The default
* value is <code>selected</code>
* value is <code>selected</code>
*/
protected String getSelectedTabCssClass() {
return "active";
Expand All @@ -296,13 +292,21 @@ public final IModel<List<T>> getTabs() {
return tabs;
}

protected Component newIcon(final String id, IModel<String> iconCssClass) {
Label label = new Label(id);
label.add(AttributeModifier.replace("class", iconCssClass));
label.add(new VisibleBehaviour(() -> iconCssClass != null && StringUtils.isNotEmpty(iconCssClass.getObject())));

return label;
}

/**
* Factory method for tab titles. Returned component can be anything that can attach to span
* tags such as a fragment, panel, or a label
*
* @param titleId id of tiatle component
* @param titleId id of tiatle component
* @param titleModel model containing tab title
* @param index index of tab
* @param index index of tab
* @return title component
*/
protected Component newTitle(final String titleId, final IModel<?> titleModel, final int index) {
Expand Down Expand Up @@ -339,8 +343,8 @@ protected Component newTitle(final String titleId, final IModel<?> titleModel, f
* </pre>
*
* @param linkId component id with which the link should be created
* @param index index of the tab that should be activated when this link is clicked. See
* {@link #setSelectedTab(int)}.
* @param index index of the tab that should be activated when this link is clicked. See
* {@link #setSelectedTab(int)}.
* @return created link component
*/
protected WebMarkupContainer newLink(final String linkId, final int index) {
Expand Down Expand Up @@ -482,7 +486,8 @@ public boolean isVisible(int index) {
if (tabsList.size() <= index) {
return false;
}
T tab = tabsList == null || tabsList.size() == 0 ? null : tabs.getObject().get(index);

T tab = tabs.getObject().get(index);
visible = tab != null && tab.isVisible();
if (tab != null) {
visibilities[index] = visible;
Expand All @@ -500,17 +505,18 @@ public boolean isVisible(int index) {
*
* @param index Index of new tab.
*/
protected void onTabChange(int index) {}
protected void onTabChange(int index) {
}

@FunctionalInterface
public interface RightSideItemProvider extends Serializable {
Component createRightSideItem(String id);
}

public void reloadCountLabels(AjaxRequestTarget target){
Loop tabbedPanel = ((Loop)get(ID_TABS_CONTAINER).get(ID_TABS));
public void reloadCountLabels(AjaxRequestTarget target) {
Loop tabbedPanel = ((Loop) get(ID_TABS_CONTAINER).get(ID_TABS));
int tabsCount = tabbedPanel.getIterations();
for (int i = 0; i < tabsCount; i++){
for (int i = 0; i < tabsCount; i++) {
Component countLabel = tabbedPanel.get(Integer.toString(i)).get(ID_LINK).get(ID_COUNT);
if (countLabel != null) {
target.add(countLabel);
Expand Down

0 comments on commit 0dfde33

Please sign in to comment.