/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.wicket.extensions.markup.html.repeater.tree.content;
import java.util.Optional;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.core.util.string.CssUtils;
import org.apache.wicket.extensions.markup.html.repeater.tree.AbstractTree;
import org.apache.wicket.extensions.markup.html.repeater.tree.AbstractTree.State;
import org.apache.wicket.extensions.markup.html.repeater.tree.ITreeProvider;
import org.apache.wicket.model.IModel;
/**
* A typical folder representation of nodes in a tree.
*
* The link is used to expand/collapse the tree depending on the {@link State} of the current node.
* Nodes without children are not clickable. Subclasses may change this behavior by overriding
* {@link #isClickable()} and {@link #onClick(Optional<AjaxRequestTarget>)}.
*
* @author svenmeier
*/
public class Folder<T> extends StyledLinkLabel<T>
{
private static final long serialVersionUID = 1L;
public static final String OTHER_CSS_CLASS_KEY = CssUtils.key(Folder.class, "other");
public static final String CLOSED_CSS_CLASS_KEY = CssUtils.key(Folder.class, "closed");
public static final String OPEN_CSS_CLASS_KEY = CssUtils.key(Folder.class, "open");
public static final String SELECTED_CSS_CLASS_KEY = CssUtils.key(Folder.class, "selected");
private AbstractTree<T> tree;
public Folder(String id, AbstractTree<T> tree, IModel<T> model)
{
super(id, model);
this.tree = tree;
}
/**
* Clickable if node can be expanded/collapsed, i.e. has children.
*
* @see ITreeProvider#hasChildren(Object)
*/
@Override
protected boolean isClickable()
{
T t = getModelObject();
return tree.getProvider().hasChildren(t);
}
/**
* Toggle the node's {@link State} on click.
*/
@Override
protected void onClick(Optional<AjaxRequestTarget> targetOptional)
{
T t = getModelObject();
if (tree.getState(t) == State.EXPANDED)
{
tree.collapse(t);
}
else
{
tree.expand(t);
}
}
/**
* Delegates to others methods depending wether the given model is a folder, expanded, collapsed
* or selected.
*
* @see ITreeProvider#hasChildren(Object)
* @see AbstractTree#getState(Object)
* @see #isSelected()
* @see #getOpenStyleClass()
* @see #getClosedStyleClass()
* @see #getOtherStyleClass(Object)
* @see #getSelectedStyleClass()
*/
@Override
protected String getStyleClass()
{
T t = getModelObject();
String styleClass;
if (tree.getProvider().hasChildren(t))
{
if (tree.getState(t) == State.EXPANDED)
{
styleClass = getOpenStyleClass();
}
else
{
styleClass = getClosedStyleClass();
}
}
else
{
styleClass = getOtherStyleClass(t);
}
if (isSelected())
{
styleClass += " " + getSelectedStyleClass();
}
return styleClass;
}
/**
* Optional attribute which decides if an additional "selected" style class should be rendered.
*
* @return defaults to <code>false</code>
*/
protected boolean isSelected()
{
return false;
}
/**
* Get a style class for nodes without children.
*
* @param t
* node
* @return CSS style class
*
* @see ITreeProvider#hasChildren(Object)
*/
protected String getOtherStyleClass(T t)
{
return getString(OTHER_CSS_CLASS_KEY);
}
/**
* Get a style class for anything other than closed or open folders.
*
* @return CSS style class
*
* @see State#COLLAPSED
*/
protected String getClosedStyleClass()
{
return getString(CLOSED_CSS_CLASS_KEY);
}
/**
* Get a style class for anything other than closed or open folders.
*
* @return CSS style class
*
* @see State#EXPANDED
*/
protected String getOpenStyleClass()
{
return getString(OPEN_CSS_CLASS_KEY);
}
/**
* Get a style class to render for a selected folder.
*
* @return CSS style class
*
* @see #isSelected()
*/
protected String getSelectedStyleClass()
{
return getString(SELECTED_CSS_CLASS_KEY);
}
}