/*
* Copyright 2009 Andrew Pietsch
*
* 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.dragome.forms.bindings.client.form;
import java.util.ArrayList;
import java.util.List;
import com.dragome.forms.bindings.client.format.Format;
import com.dragome.forms.bindings.client.format.FormatException;
import com.dragome.forms.bindings.client.list.ArrayListModel;
import com.dragome.forms.bindings.client.list.GuardedListModelChangedHandler;
import com.dragome.forms.bindings.client.value.ValueHolder;
import com.dragome.forms.bindings.client.value.ValueModel;
import com.dragome.forms.bindings.extra.user.client.Command;
import com.dragome.model.interfaces.ValueChangeEvent;
import com.dragome.model.interfaces.ValueChangeHandler;
import com.dragome.model.interfaces.list.ListModel;
import com.dragome.model.interfaces.list.ListModelChangedEvent;
import com.dragome.model.interfaces.list.MutableListModel;
/**
* Created by IntelliJ IDEA.
* User: andrew
* Date: Aug 5, 2009
* Time: 1:02:17 PM
* To change this template use File | Settings | File Templates.
*/
public class FormattedListFieldModelImpl<T> extends AbstractListFieldModelBase<T> implements FormattedListFieldModel<T>
{
private ValueHolder<Format<T>> formatModel= new ValueHolder<Format<T>>();
private ArrayListModel<String> textModel= new ArrayListModel<String>();
private ListFormatExceptionPolicy<T> formatExceptionPolicy= new ListFormatExceptionPolicy<T>()
{
public void onFormatException(String value, List<T> values, FormatException e)
{
}
};
private GuardedListModelChangedHandler<T> valueMonitor= new GuardedListModelChangedHandler<T>()
{
public void onGuardedListDataChanged(ListModelChangedEvent<T> event)
{
writeValuesToText();
}
};
private GuardedListModelChangedHandler<String> textMonitor= new GuardedListModelChangedHandler<String>()
{
public void onGuardedListDataChanged(ListModelChangedEvent<String> event)
{
writeTextToValues();
}
};
private ValueChangeHandler<Format<T>> formatMonitor= new ValueChangeHandler<Format<T>>()
{
public void onValueChange(ValueChangeEvent<Format<T>> event)
{
writeValuesToText();
}
};
public FormattedListFieldModelImpl(FormModel formModel, ListModel<T> source, Format<T> format, ListFormatExceptionPolicy<T> exceptionPolicy, Class<T> valueType)
{
super(formModel, source, valueType);
setFormat(format);
setFormatExceptionPolicy(exceptionPolicy);
addListModelChangedHandler(valueMonitor);
textModel.addListModelChangedHandler(textMonitor);
formatModel.addValueChangeHandler(formatMonitor);
}
public MutableListModel<String> getTextModel()
{
return textModel;
}
public void setFormat(Format<T> format)
{
if (format == null)
{
throw new NullPointerException("format is null");
}
this.formatModel.setValue(format);
}
public Format<T> getFormat()
{
return formatModel.getValue();
}
public ValueModel<Format<T>> getFormatModel()
{
return formatModel;
}
public void sanitiseText()
{
// we try and sanitise the users text by parsing it and
// reformatting it. We don't touch the real value while doing this
// as if the current text value is invalid we'll actually blat the
// current value.
ArrayList<String> sanitisedTextValues= new ArrayList<String>(size());
for (String text : textModel)
{
sanitisedTextValues.add(sanitiseText(text));
}
updateTextModel(sanitisedTextValues);
}
public Command sanitiseTextCommand()
{
return new Command()
{
public void execute()
{
sanitiseText();
}
};
}
private String sanitiseText(String text)
{
try
{
Format<T> format= getFormat();
T value= format.parse(text);
return format.format(value);
}
catch (FormatException e)
{
return text;
}
}
public ListFormatExceptionPolicy<T> getFormatExceptionPolicy()
{
return formatExceptionPolicy;
}
public void setFormatExceptionPolicy(ListFormatExceptionPolicy<T> formatExceptionPolicy)
{
if (formatExceptionPolicy == null)
{
throw new NullPointerException("formatExceptionPolicy is null");
}
this.formatExceptionPolicy= formatExceptionPolicy;
}
private void writeTextToValues()
{
ArrayList<T> newValues= new ArrayList<T>(textModel.size());
for (String value : (ListModel<String>) textModel)
{
try
{
newValues.add(getFormat().parse(value));
}
catch (FormatException e)
{
formatExceptionPolicy.onFormatException(value, newValues, e);
}
}
updateModelValues(newValues);
}
private void writeValuesToText()
{
ArrayList<String> newValues= new ArrayList<String>(size());
for (T value : (ListModel<T>) this)
{
newValues.add(getFormat().format(value));
}
updateTextModel(newValues);
}
private void updateModelValues(ArrayList<T> newValues)
{
try
{
valueMonitor.setIgnoreEvents(true);
setElements(newValues);
}
finally
{
valueMonitor.setIgnoreEvents(false);
}
}
private void updateTextModel(ArrayList<String> newValues)
{
try
{
textMonitor.setIgnoreEvents(true);
textModel.setElements(newValues);
}
finally
{
textMonitor.setIgnoreEvents(false);
}
}
}