/*
* Copyright 2006 Wicket Stuff
*
* 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.googlecode.wicketwebbeans.datepicker;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Component;
import org.apache.wicket.ResourceReference;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.util.convert.IConverter;
import org.apache.wicket.util.convert.converters.DateConverter;
/**
* Popup mode of the DatePicker
*
* <p>
* Link your datepicker to a textfield like this:
* </p>
* <p>
* (Java)
*
* <pre>
* TextField dateField = new TextField("dateField", Date.class);
* add(dateField);
* add(new PopupDatePicker("dateFieldPicker", dateField));
* </pre>
*
* (html)
*
* <pre>
* <input type="text" wicket:id="dateField" size="10" />
* <span wicket:id="dateFieldPicker" />
* </pre>
*
* </p>
* <p>
* Your target doesn't have to be a text field however, attach to any tag that
* is supported by JSCalendar.
* </p>
*
* @author Frank Bille Jensen
*/
public class PopupDatePicker extends DatePicker
{
private static final long serialVersionUID = 1L;
/**
* Attribute modifier that modifies/ adds an attribute with value of the
* given component's path.
*/
private final static class PathAttributeModifier extends AttributeModifier
{
private static final long serialVersionUID = 1L;
/**
* Construct.
*
* @param attribute
* the attribute to modify
* @param pathProvider
* the component that provides the path
*/
public PathAttributeModifier(String attribute, final Component pathProvider)
{
super(attribute, true, new Model<String>()
{
private static final long serialVersionUID = 1L;
public String getObject()
{
if (pathProvider.getOutputMarkupId())
{
return pathProvider.getMarkupId();
}
// do this lazily, so we know for sure we have the whole
// path including the page etc.
return pathProvider.getPath();
}
});
}
}
/**
* Button that triggers the popup.
*/
private final static class TriggerButton extends WebMarkupContainer
{
private static final long serialVersionUID = 1L;
/**
* Construct.
*
* @param id
* component id
* @param resourceReference
* button icon reference
*/
public TriggerButton(final String id, final ResourceReference resourceReference)
{
super(id);
add(new PathAttributeModifier("id", this));
IModel<String> srcReplacement = new Model<String>()
{
private static final long serialVersionUID = 1L;
public String getObject()
{
return (String) urlFor(resourceReference);
};
};
add(new AttributeModifier("src", true, srcReplacement));
}
}
/** the receiving component. */
private final Component target;
/** the button that triggers the popup. */
private TriggerButton triggerButton;
/**
* Construct with a default button and style.
*
* @param id
* the component id
* @param target
* the receiving component
*/
public PopupDatePicker(String id, Component target)
{
this(id, target, new DatePickerSettings());
}
/**
* Construct with a default button and style.
*
* @param id
* the component id
* @param label
* the label for target component.
* @param target
* the receiving component
*/
public PopupDatePicker(String id, Component label, Component target)
{
this(id, label, target, new DatePickerSettings());
}
/**
* Construct.
*
* @param id
* the component id
* @param target
* the receiving component
* @param settings
* datepicker properties
*/
public PopupDatePicker(final String id, final Component target,
final DatePickerSettings settings)
{
this(id, null, target, settings);
}
/**
* Construct.
*
* @param id
* the component id
* @param label
* the label component (may be null)
* @param target
* the receiving component
* @param settings
* datepicker properties
*/
public PopupDatePicker(final String id, final Component label, final Component target,
final DatePickerSettings settings)
{
super(id, settings);
if (target == null)
{
throw new IllegalArgumentException("Target must be not null");
}
target.add(new PathAttributeModifier("id", target));
this.target = target;
if (label != null)
{
label.add(new PathAttributeModifier("for", target));
}
add(triggerButton = new TriggerButton("trigger", settings.getIcon()));
}
protected void appendSettings(Map<String, String> settings)
{
String targetId = target.getOutputMarkupId() ? target.getMarkupId() : target.getPath();
settings.put("inputField", "\"" + targetId + "\"");
settings.put("button", "\"" + triggerButton.getPath() + "\"");
}
@Override
protected DateConverter getDateConverter()
{
IConverter converter = target.getConverter(Date.class);
if (converter instanceof DateConverter)
{
return (DateConverter)converter;
}
return super.getDateConverter();
}
@Override
protected Locale getDatePickerLocale()
{
return target.getLocale();
}
}