/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo 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.
*
* OpenFlexo 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 OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.ie.view.widget;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Insets;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.util.Enumeration;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.SwingConstants;
import org.openflexo.foundation.DataModification;
import org.openflexo.foundation.FlexoObservable;
import org.openflexo.foundation.ie.dm.DisplayNeedUpdate;
import org.openflexo.foundation.ie.dm.DisplayNeedsRefresh;
import org.openflexo.foundation.ie.dm.WidgetAddedToSequence;
import org.openflexo.foundation.ie.dm.WidgetRemovedFromSequence;
import org.openflexo.foundation.ie.dm.table.ColSpanDecrease;
import org.openflexo.foundation.ie.dm.table.ColSpanIncrease;
import org.openflexo.foundation.ie.dm.table.ConstraintUpdated;
import org.openflexo.foundation.ie.dm.table.RowSpanDecrease;
import org.openflexo.foundation.ie.dm.table.RowSpanIncrease;
import org.openflexo.foundation.ie.widget.IEHTMLTableConstraints;
import org.openflexo.foundation.ie.widget.IEHTMLTableWidget;
import org.openflexo.foundation.ie.widget.IESequenceWidget;
import org.openflexo.foundation.ie.widget.IETDWidget;
import org.openflexo.foundation.ie.widget.IEWidget;
import org.openflexo.foundation.ie.widget.OperatorChanged;
import org.openflexo.ie.view.IEContainer;
import org.openflexo.ie.view.IEViewUtils;
import org.openflexo.ie.view.IEWOComponentView;
import org.openflexo.ie.view.controller.IEController;
import org.openflexo.ie.view.controller.dnd.IEDTListener;
public class IESequenceWidgetWidgetView extends IEWidgetView<IESequenceWidget> implements IEContainer {
private static final Logger logger = Logger.getLogger(IESequenceWidgetWidgetView.class.getPackage().getName());
public static final int LAYOUT_GAP = 2;
/**
* @param model
*/
public IESequenceWidgetWidgetView(IEController ieController, IESequenceWidget model, boolean addDnDSupport,
IEWOComponentView componentView) {
super(ieController, model, addDnDSupport, componentView);
setOpaque(false);
setLayout(new IETDFlowLayout(getAlignement(), getHorizontalGap(), getVerticalGap(), SwingConstants.TOP));
Enumeration en = model.elements();
IEWidget widget = null;
while (en.hasMoreElements()) {
widget = (IEWidget) en.nextElement();
add(_componentView.getViewForWidget(widget, true));
}
if (logger.isLoggable(Level.FINE)) {
logger.fine("Sequence Widget Widget View Bounds:" + getBounds());
}
this.setDropTarget(new DropTarget(this, DnDConstants.ACTION_COPY, new IEDTListener(ieController, this, getModel())));
if (getModel().getOperator() != null) {
setBorder(IEViewUtils.getBorderForOperator(getModel().getOperator()));
}
validate();
}
public int getHorizontalGap() {
return LAYOUT_GAP;
}
public int getVerticalGap() {
return LAYOUT_GAP;
}
/**
* @return the FlowLayout alignement for this view. Default value is FlowLayout.LEFT
* @see FlowLayout
*/
protected int getAlignement() {
return FlowLayout.LEFT;
}
public int getAvailableWidth() {
Dimension d = getMaximumSize();
Insets i = getInsets();
int retval = d.width - 2 * getHorizontalGap() - i.left - i.right;
if (getModel().isSubsequence()) {
retval -= 2 * getHorizontalGap() * getModel().getSequenceDepth();
}
return retval;
}
/**
* Overrides getMaximumSize
*
* @see javax.swing.JComponent#getMaximumSize()
*/
@Override
public Dimension getMaximumSize() {
Container p = getParent();
if (p instanceof IESequenceWidgetWidgetView) {
Dimension d = ((IESequenceWidgetWidgetView) p).getMaximumSize();
if (d.width == 0) {
return d;
}
d.height -= 2 * getVerticalGap();
d.width -= 2 * getHorizontalGap();
return d;
} else if (p instanceof IEWOComponentView) {
Dimension d = ((IEWOComponentView) p).getMaximumSize();
int subsequenceCount = getModel().getSequenceDepth();
d.width = ((IEWOComponentView) p).getMaxWidth() - subsequenceCount * getHorizontalGap() * 2;
return d;
} else if (p instanceof ButtonPanel) {
return p.getMaximumSize();
} else {
return getSize();
}
}
@Override
public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
if (d.height < IETDWidget.MIN_HEIGHT) {
d.height = IETDWidget.MIN_HEIGHT;
}
if (d.width < IETDWidget.MIN_WIDTH) {
d.width = IETDWidget.MIN_WIDTH;
}
return d;
}
public int getChildCount() {
return getSequenceModel().length();
}
public IEHTMLTableConstraints getConstraints() {
return getSequenceModel().td().getConstraints();
}
protected Component findView(IEWidget w) {
for (int i = 0; i < getComponentCount(); i++) {
if (((IEWidgetView) getComponent(i)).getModel().equals(w)) {
return getComponent(i);
}
}
if (logger.isLoggable(Level.FINE)) {
logger.fine("cannot find a view for widget : " + w);
}
return null;
}
/**
* Overrides setDefaultBorder
*
* @see org.openflexo.ie.view.widget.IEWidgetView#setDefaultBorder()
*/
@Override
public void setDefaultBorder() {
if (getModel().getOperator() != null) {
setBorder(IEViewUtils.getBorderForOperator(getModel().getOperator()));
} else {
setBorder(EMPTY_BORDER_1);
}
}
protected void handleWidgetInserted(IEWidget widget) {
add(_componentView.getViewForWidget(widget, true), widget.getIndex());
validate();
revalidate();
repaint();
}
protected void handleWidgetRemoved(IEWidget widget) {
if (widget instanceof IEHTMLTableWidget) {
widget = ((IEHTMLTableWidget) widget).getSequenceTR();
}
Component v = findView(widget);
if (v != null) {
remove(v);
revalidate();
repaint();
}
}
/*
* (non-Javadoc)
*
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
*/
@Override
public void update(FlexoObservable arg0, DataModification modif) {
if (modif instanceof DisplayNeedUpdate || modif instanceof ConstraintUpdated || modif instanceof ColSpanDecrease
|| modif instanceof RowSpanDecrease || modif instanceof ColSpanIncrease || modif instanceof RowSpanIncrease) {
revalidate();
repaint();
} else if (modif instanceof WidgetAddedToSequence && arg0 == getModel()) {
handleWidgetInserted((IEWidget) modif.newValue());
} else if (modif instanceof WidgetRemovedFromSequence && arg0 == getModel()) {
handleWidgetRemoved((IEWidget) modif.oldValue());
} else if (modif instanceof OperatorChanged && arg0 == getModel()) {
if (getModel().getOperator() != null) {
setBorder(IEViewUtils.getBorderForOperator(getModel().getOperator()));
}
} else if (modif instanceof DisplayNeedsRefresh && arg0 == getModel()) {
revalidate();
repaint();
} else {
super.update(arg0, modif);
}
}
public IESequenceWidget getSequenceModel() {
return getModel();
}
@Override
public Color getBackground() {
if (getSequenceModel() != null) {
return getSequenceModel().getBackground();
} else {
return super.getBackground();
}
}
public int findInsertionIndex(int dropX, int dropY) {
int i = 0;
for (i = 0; i < getComponentCount(); i++) {
if (dropX < getComponent(i).getX() + getComponent(i).getWidth() / 2
&& dropY < getComponent(i).getY() + getComponent(i).getHeight()) {
return i;
} else if (dropY < getComponent(i).getY()) {
return i;
}
}
return i;
}
public int getContentLength() {
int r = 0;
for (int i = 0; i < getComponentCount(); i++) {
r = r + getComponent(i).getPreferredSize().width;
}
return r;
}
}