org.dominokit.domino.ui.tree.Tree Maven / Gradle / Ivy
package org.dominokit.domino.ui.tree;
import elemental2.dom.*;
import org.dominokit.domino.ui.icons.Icon;
import org.dominokit.domino.ui.icons.Icons;
import org.dominokit.domino.ui.search.Search;
import org.dominokit.domino.ui.style.ColorScheme;
import org.dominokit.domino.ui.style.Styles;
import org.dominokit.domino.ui.style.Unit;
import org.dominokit.domino.ui.utils.BaseDominoElement;
import org.dominokit.domino.ui.utils.DominoElement;
import org.dominokit.domino.ui.utils.ParentTreeItem;
import org.jboss.elemento.IsElement;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
import static org.jboss.elemento.Elements.*;
public class Tree extends BaseDominoElement> implements ParentTreeItem>, IsElement {
private HTMLElement title = span().css("title").element();
private ToggleTarget toggleTarget = ToggleTarget.ANY;
private TreeItemFilter> filter = (treeItem, searchToken) -> treeItem.getTitle().toLowerCase().contains(searchToken.toLowerCase());
private HTMLLIElement header = li()
.css("header")
.css("menu-header")
.add(title)
.element();
private HTMLUListElement root = ul()
.add(header)
.css("list")
.element();
private HTMLDivElement menu = div().style("overflow-x: hidden")
.css("menu")
.add(root)
.element();
private final int nextLevel = 1;
private TreeItem activeTreeItem;
private boolean autoCollapse = true;
private List> subItems = new ArrayList<>();
private boolean autoExpandFound;
private ColorScheme colorScheme;
private Search search;
private Icon searchIcon;
private Icon collapseAllIcon;
private Icon expandAllIcon;
private T value;
private final List> itemsClickListeners = new ArrayList<>();
public Tree() {
this("");
}
public Tree(String treeTitle) {
init(this);
if (isNull(treeTitle) || treeTitle.trim().isEmpty()) {
DominoElement.of(header)
.hide();
}
title.textContent = treeTitle;
}
public Tree(String treeTitle, T value) {
this(treeTitle);
this.value = value;
}
public Tree(T value) {
this("");
this.value = value;
}
public static Tree create(String title) {
Tree tree = new Tree<>(title);
return tree;
}
public static Tree create() {
Tree tree = new Tree<>();
DominoElement.of(tree.header)
.hide();
return tree;
}
public static Tree create(String title, T value) {
Tree tree = new Tree<>(title, value);
return tree;
}
public static Tree create(T value) {
Tree tree = new Tree<>(value);
return tree;
}
public Tree appendChild(TreeItem treeItem) {
root.appendChild(treeItem.element());
treeItem.setParent(this);
treeItem.setLevel(nextLevel);
treeItem.setToggleTarget(this.toggleTarget);
this.subItems.add(treeItem);
return this;
}
public Tree addSeparator() {
root.appendChild(li()
.css("gap")
.css("separator")
.add(a())
.element());
return this;
}
public Tree addGap() {
root.appendChild(li()
.css("gap")
.add(a())
.element());
return this;
}
public Tree setToggleTarget(ToggleTarget toggleTarget) {
if (nonNull(toggleTarget)) {
subItems.forEach(item -> item.setToggleTarget(toggleTarget));
this.toggleTarget = toggleTarget;
}
return this;
}
public Tree setColorScheme(ColorScheme colorScheme) {
if (nonNull(this.colorScheme)) {
style.remove(colorScheme.color().getBackground());
DominoElement.of(header).style().remove(this.colorScheme.darker_3().getBackground());
}
this.colorScheme = colorScheme;
style.add(colorScheme.color().getBackground());
DominoElement.of(header).style().add(this.colorScheme.darker_3().getBackground());
return this;
}
@Override
public TreeItem getActiveItem() {
return activeTreeItem;
}
@Override
public void setActiveItem(TreeItem activeItem) {
setActiveItem(activeItem, false);
}
@Override
public void setActiveItem(TreeItem activeItem, boolean silent) {
if (nonNull(this.activeTreeItem) && !this.activeTreeItem.equals(activeItem)) {
this.activeTreeItem.deactivate();
}
this.activeTreeItem = activeItem;
this.activeTreeItem.activate();
if (!silent) {
onTreeItemClicked(activeItem);
}
}
public DominoElement getHeader() {
return DominoElement.of(header);
}
public DominoElement getRoot() {
return DominoElement.of(root);
}
public DominoElement getTitle() {
return DominoElement.of(title);
}
public Tree autoHeight() {
root.style.height = CSSProperties.HeightUnionType.of("calc(100vh - 83px)");
element().style.height = CSSProperties.HeightUnionType.of("calc(100vh - 70px)");
return this;
}
public Tree autoHeight(int offset) {
root.style.height = CSSProperties.HeightUnionType.of("calc(100vh - " + offset + 13 + "px)");
element().style.height = CSSProperties.HeightUnionType.of("calc(100vh - " + offset + "px)");
return this;
}
public Tree enableSearch() {
search = Search.create(true)
.styler(style -> style.setHeight(Unit.px.of(40)))
.onSearch(Tree.this::filter)
.onClose(this::clearFilter);
searchIcon = Icons.ALL.search()
.style()
.setMarginBottom("0px")
.setMarginTop("0px")
.add(Styles.pull_right)
.setProperty("cursor", "pointer")
.get();
this.header.appendChild(search.element());
this.header.appendChild(searchIcon.element());
searchIcon.element().addEventListener("click", evt -> search.open());
return this;
}
public Tree enableFolding() {
collapseAllIcon = Icons.ALL.fullscreen_exit()
.style()
.setMarginBottom("0px")
.setMarginTop("0px")
.add(Styles.pull_right)
.setProperty("cursor", "pointer")
.get();
collapseAllIcon.element().addEventListener("click", evt -> collapseAll());
expandAllIcon = Icons.ALL.fullscreen()
.style()
.setMarginBottom("0px")
.setMarginTop("0px")
.add(Styles.pull_right)
.setProperty("cursor", "pointer")
.get();
expandAllIcon.element().addEventListener("click", evt -> expandAll());
header.appendChild(expandAllIcon.element());
header.appendChild(collapseAllIcon.element());
return this;
}
public void expandAll() {
getSubItems().forEach(TreeItem::expandAll);
}
public void collapseAll() {
getSubItems().forEach(TreeItem::collapseAll);
}
public void deactivateAll() {
getSubItems().forEach(TreeItem::deactivate);
}
public Tree autoExpandFound() {
this.autoExpandFound = true;
return this;
}
@Override
public boolean isAutoExpandFound() {
return autoExpandFound;
}
public void setAutoExpandFound(boolean autoExpandFound) {
this.autoExpandFound = autoExpandFound;
}
public void clearFilter() {
subItems.forEach(TreeItem::clearFilter);
}
public void filter(String searchToken) {
subItems.forEach(treeItem -> treeItem.filter(searchToken));
}
@Override
public Tree getTreeRoot() {
return this;
}
public Tree setAutoCollapse(boolean autoCollapse) {
this.autoCollapse = autoCollapse;
return this;
}
public Tree setTitle(String title) {
getTitle().setTextContent(title);
if (getHeader().isHidden()) {
getHeader().show();
}
return this;
}
public boolean isAutoCollapse() {
return autoCollapse;
}
@Override
public List> getSubItems() {
return new ArrayList<>(subItems);
}
public ParentTreeItem expand(boolean expandParent) {
return this;
}
public ParentTreeItem expand() {
return this;
}
@Override
public Optional> getParent() {
return Optional.empty();
}
@Override
public void activate() {
}
@Override
public void activate(boolean activateParent) {
}
public Search getSearch() {
return search;
}
public Icon getSearchIcon() {
return searchIcon;
}
public Icon getCollapseAllIcon() {
return collapseAllIcon;
}
public Icon getExpandAllIcon() {
return expandAllIcon;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
public Tree addItemClickListener(ItemClickListener itemClickListener) {
this.itemsClickListeners.add(itemClickListener);
return this;
}
public Tree removeItemClickListener(ItemClickListener itemClickListener) {
this.itemsClickListeners.remove(itemClickListener);
return this;
}
void onTreeItemClicked(TreeItem treeItem) {
this.itemsClickListeners.forEach(itemClickListener -> itemClickListener.onTreeItemClicked(treeItem));
}
public List> getActivePath() {
List> activeItems = new ArrayList<>();
TreeItem activeItem = getActiveItem();
while (nonNull(activeItem)) {
activeItems.add(activeItem);
activeItem = activeItem.getActiveItem();
}
return activeItems;
}
public List getActivePathValues() {
List activeValues = new ArrayList<>();
TreeItem activeItem = getActiveItem();
while (nonNull(activeItem)) {
activeValues.add(activeItem.getValue());
activeItem = activeItem.getActiveItem();
}
return activeValues;
}
@Override
public void removeItem(TreeItem item) {
subItems.remove(item);
item.remove();
}
public Tree setFilter(TreeItemFilter> filter) {
this.filter = filter;
return this;
}
@Override
public TreeItemFilter> getFilter() {
return this.filter;
}
@Override
public HTMLDivElement element() {
return menu;
}
public interface ItemClickListener {
void onTreeItemClicked(TreeItem treeItem);
}
}