/**********************************************
* Copyright (C) 2011 Lukas Laag
* This file is part of svgreal.
*
* svgreal is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* svgreal is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with svgreal. If not, see http://www.gnu.org/licenses/
**********************************************/package org.vectomatic.svg.edit.client.model;
import java.util.Collection;
import java.util.Map;
import com.extjs.gxt.ui.client.data.ChangeEvent;
import com.extjs.gxt.ui.client.data.ChangeEventSupport;
import com.extjs.gxt.ui.client.data.ChangeListener;
import com.extjs.gxt.ui.client.data.Model;
import com.extjs.gxt.ui.client.data.PropertyChangeEvent;
import com.extjs.gxt.ui.client.store.Store;
import com.extjs.gxt.ui.client.util.Util;
import com.google.gwt.core.client.GWT;
/**
* Base class for GXT {@link com.extjs.gxt.ui.client.data.Model}
* implementations which rely on a {@link MetaModel} to supply
* the model properties.
* @author laaglu
*/
public abstract class AbstractModel<U> implements Model {
/**
* To implement ChangeEventSource
*/
protected transient ChangeEventSupport changeEventSupport;
/**
* The native object backing this model
*/
protected U element;
public AbstractModel(U element) {
this.element = element;
changeEventSupport = new ChangeEventSupport();
}
public abstract MetaModel<U> getMetaModel();
public U getElement() {
return element;
}
/**
* Returns the store which contains this model
* @return
*/
public abstract Store getStore();
///////////////////////////////////////////////////
// Implementation of the ModelData interface
///////////////////////////////////////////////////
@Override
public <X> X get(String property) {
IMetadata propertyDefinition = getMetaModel().getMetadata(property);
assert propertyDefinition != null : "Undefined property " + property;
return (X)propertyDefinition.get(element);
}
@Override
public Map<String, Object> getProperties() {
return getMetaModel().getProperties(element);
}
@Override
public Collection<String> getPropertyNames() {
return getMetaModel().getPropertyNames();
}
@Override
public <X> X remove(String property) {
IMetadata propertyDefinition = getMetaModel().getMetadata(property);
assert propertyDefinition != null : "Undefined property " + property;
X oldValue = (X)propertyDefinition.remove(element);
notifyPropertyChanged(propertyDefinition.getName(), null, oldValue);
return oldValue;
}
@Override
public <X> X set(String property, X value) {
IMetadata propertyDefinition = getMetaModel().getMetadata(property);
assert propertyDefinition != null : "Undefined property " + property;
X oldValue = (X)propertyDefinition.set(element, value);
GWT.log("AbstractModel.set(" + property + ") = " + oldValue + ", " + value);
notifyPropertyChanged(propertyDefinition.getName(), value, oldValue);
return oldValue;
}
///////////////////////////////////////////////////
// Implementation of the ChangeEventSource interface
///////////////////////////////////////////////////
@Override
public void addChangeListener(ChangeListener... listener) {
changeEventSupport.addChangeListener(listener);
}
@Override
public void removeChangeListener(ChangeListener... listener) {
changeEventSupport.removeChangeListener(listener);
}
@Override
public void removeChangeListeners() {
changeEventSupport.removeChangeListeners();
}
@Override
public void setSilent(boolean silent) {
changeEventSupport.setSilent(silent);
}
@Override
public void notify(ChangeEvent event) {
changeEventSupport.notify(event);
}
protected void notifyPropertyChanged(String name, Object value, Object oldValue) {
if (!Util.equalWithNull(value, oldValue)) {
notify(new PropertyChangeEvent(Update, this, name, oldValue, value));
}
}
public boolean isSilent() {
return changeEventSupport.isSilent();
}
protected void fireEvent(int type) {
notify(new ChangeEvent(type, this));
}
protected void fireEvent(int type, Model item) {
notify(new ChangeEvent(type, this, item));
}
}