package de.flower.common.ui.panel;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import de.flower.common.util.Clazz;
import de.flower.common.util.Strings;
import org.apache.commons.lang3.StringUtils;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.markup.Markup;
import org.apache.wicket.markup.html.panel.GenericPanel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
import java.util.List;
/**
* @author flowerrrr
*/
public class BasePanel<T> extends GenericPanel<T> {
private static final Logger log = LoggerFactory.getLogger(BasePanel.class);
private IOnCloseCallback onCloseCallback;
public BasePanel() {
this(null, null);
}
public BasePanel(IModel<T> model) {
this(null, model);
}
protected BasePanel(String id) {
this(id, null);
}
protected BasePanel(String id, IModel<T> model) {
super(getId(id, BasePanel.class), model);
if (log.isTraceEnabled()) log.trace("new " + getId());
setOutputMarkupId(true);
// always append a css class to the panels
add(new AttributeAppender("class", Model.of(getCssClasses()), " "));
}
/**
* Should be called by a panel that can be dismissed/closed, like in modal windows or panels that should be hidden
* when editing is finished.
*/
protected void onClose(AjaxRequestTarget target) {
if (onCloseCallback != null) {
onCloseCallback.onClose(target);
}
}
protected String getPanelMarkup() {
return null;
}
@Override
public Markup getAssociatedMarkup() {
String markup = getPanelMarkup();
if (markup != null) {
return Markup.of("<wicket:panel>" + markup + "</wicket:panel>");
} else {
return super.getAssociatedMarkup();
}
}
/**
* Most panels let the basepanel determine the id. using default id provides a
* good naming strategy in your code.
* Must use static method cause it is used in super() call.
*
*/
protected static String getId(String id, final Class<?> callee) {
if (id != null) {
return id;
} else {
Class<?> thisClass = Clazz.getThisClassStatic(callee);
if (Clazz.isAnonymousClass(thisClass)) {
thisClass = Clazz.getSuperClass(thisClass);
}
String className = Clazz.getShortName(thisClass);
return Strings.uncapitalize(className);
}
}
@VisibleForTesting
protected String getCssClasses() {
List<Class<?>> panelClasses = Clazz.getClassList(this.getClass(), BasePanel.class);
panelClasses = Lists.newArrayList(Collections2.filter(panelClasses, new Predicate<Class<?>>() {
@Override
public boolean apply(final Class<?> input) {
return !Clazz.isAnonymousClass(input);
}
}));
List<String> cssClasses = Lists.transform(panelClasses, new Function<Class<?>, String>() {
@Override
public String apply(final Class<?> input) {
return getCssClass(input);
}
});
return StringUtils.join(cssClasses, " ");
}
public static String getCssClass(Class<?> clazz) {
// return Strings.camelCaseToHyphen(getClassName(clazz)).toLowerCase();
return getClassName(clazz);
}
private static String getClassName(Class<?> clazz) {
if (Clazz.isAnonymousClass(clazz)) {
return Clazz.getSuperClass(clazz).getSimpleName();
} else {
return clazz.getSimpleName();
}
}
public IOnCloseCallback getOnCloseCallback() {
return onCloseCallback;
}
public void setOnCloseCallback(final IOnCloseCallback onCloseCallback) {
this.onCloseCallback = onCloseCallback;
}
public interface IOnCloseCallback extends Serializable {
void onClose(AjaxRequestTarget target);
}
}