/*
* Copyright (c) 2005-2016 Vincent Vandenschrick. All rights reserved.
*
* This file is part of the Jspresso framework.
*
* Jspresso is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Jspresso 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Jspresso. If not, see <http://www.gnu.org/licenses/>.
*/
package org.jspresso.framework.binding.masterdetail;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import org.jspresso.framework.binding.IMvcBinder;
import org.jspresso.framework.binding.IValueConnector;
import org.jspresso.framework.util.event.IItemSelectable;
import org.jspresso.framework.util.event.IItemSelectionListener;
import org.jspresso.framework.util.event.ItemSelectionEvent;
/**
* Default implementation of {@code IModelCascadingBinder}.
*
* @author Vincent Vandenschrick
*/
public class DefaultModelCascadingBinder implements IModelCascadingBinder {
private IMvcBinder mvcBinder;
/**
* {@inheritDoc}
*/
@Override
public void bind(IValueConnector masterConnector,
final IValueConnector detailConnector) {
if (masterConnector instanceof IItemSelectable) {
((IItemSelectable) masterConnector)
.addItemSelectionListener(new BoundConnectorSelectionListener(
detailConnector));
} else {
// Do not simply add the detail connector since it will propagate
// writability of the master to the detail which is wrong. see bug#342.
// } else if (masterConnector instanceof ICompositeValueConnector) {
// ((ICompositeValueConnector) masterConnector)
// .addChildConnector(detailConnector);
mvcBinder.bind(detailConnector, masterConnector.getModelConnector());
masterConnector.addPropertyChangeListener(
IValueConnector.MODEL_CONNECTOR_PROPERTY,
new BoundConnectorModelListener(detailConnector));
}
}
/**
* Sets the mvcBinder.
*
* @param mvcBinder
* the mvcBinder to set.
*/
public void setMvcBinder(IMvcBinder mvcBinder) {
this.mvcBinder = mvcBinder;
}
private final class BoundConnectorSelectionListener implements
IItemSelectionListener {
private final IValueConnector detailConnector;
/**
* Constructs a new {@code BoundConnectorSelectionListener} instance.
*
* @param detailConnector
* The detail connector tracking master connector's selection.
*/
public BoundConnectorSelectionListener(IValueConnector detailConnector) {
this.detailConnector = detailConnector;
}
/**
* {@inheritDoc}
*/
@Override
public void selectedItemChange(ItemSelectionEvent event) {
if (event.getSelectedItem() != null) {
mvcBinder.bind(detailConnector,
((IValueConnector) event.getSelectedItem()).getModelConnector());
} else {
mvcBinder.bind(detailConnector, null);
}
}
}
private final class BoundConnectorModelListener implements
PropertyChangeListener {
private final IValueConnector detailConnector;
/**
* Constructs a new {@code BoundConnectorModelListener} instance.
*
* @param detailConnector
* The detail connector tracking master connector's model.
*/
public BoundConnectorModelListener(IValueConnector detailConnector) {
this.detailConnector = detailConnector;
}
/**
* {@inheritDoc}
*/
@Override
public void propertyChange(PropertyChangeEvent evt) {
IValueConnector newModelConnector = (IValueConnector) evt.getNewValue();
mvcBinder.bind(detailConnector, newModelConnector);
detailConnector.setModelConnector(newModelConnector);
}
}
}