/*
* Copyright (c) 2008, SQL Power Group Inc.
*
* This file is part of Wabit.
*
* Wabit 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.
*
* Wabit 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ca.sqlpower.swingui.querypen;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JCheckBox;
import org.apache.log4j.Logger;
import ca.sqlpower.object.SPVariableHelper;
import ca.sqlpower.query.Item;
import ca.sqlpower.query.StringItem;
import edu.umd.cs.piccolo.PCanvas;
import edu.umd.cs.piccolo.PNode;
import edu.umd.cs.piccolox.pswing.PSwing;
/**
* This PNode displays a single constant. These PNodes will be contained by a
* {@link ConstantsPane}. A constant is allowed to be edited and can be removed
* from the {@link ConstantsPane}.
*/
public class ConstantPNode extends PNode implements CleanupPNode {
private static final Logger logger = Logger.getLogger(ConstantPNode.class);
private static final int SPACING_SIZE = 8;
private static final String LONG_EMPTY_STRING = " ";
/**
* The item this PNode is displaying.
*/
private final Item item;
private JCheckBox selectionCheckbox;
private EditablePStyledText constantText;
private EditablePStyledText aliasText;
private EditablePStyledTextWithOptionBox whereText;
private final List<PropertyChangeListener> changeListeners;
private EditStyledTextListener removeItemListener = new EditStyledTextListener() {
private String oldText;
public void editingStopping() {
if (constantText.getEditorPane().getText().length() <= 0) {
removeItem();
} else if (item instanceof StringItem) {
((StringItem)item).setName(constantText.getEditorPane().getText());
}
for (PropertyChangeListener listener : changeListeners) {
listener.propertyChange(new PropertyChangeEvent(constantText, Item.PROPERTY_ITEM, oldText, constantText.getEditorPane().getText().trim()));
}
}
public void editingStarting() {
oldText = constantText.getEditorPane().getText();
}
};
private void removeItem() {
logger.debug("removing item");
for (PropertyChangeListener l : changeListeners) {
l.propertyChange(new PropertyChangeEvent(ConstantPNode.this, Item.PROPERTY_ITEM_REMOVED, item, null));
}
item.getContainer().removeItem(item);
}
/**
* Listens to the item that backs this node and updates its fields
* if the model changes.
* <p>
* This also re-fires events which may not be used in the future.
*/
private final PropertyChangeListener itemChangeListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals("selected")) {
selectionCheckbox.setSelected(item.isSelected());
} else if (evt.getPropertyName().equals("alias")) {
aliasText.getEditorPane().setText(item.getAlias());
aliasText.syncWithDocument();
} else if (evt.getPropertyName().equals("where")) {
whereText.getEditorPane().setText(item.getWhere());
whereText.syncWithDocument();
} else if (evt.getPropertyName().equals(Item.PROPERTY_ITEM)) {
constantText.getEditorPane().setText(evt.getNewValue().toString());
if (constantText.getEditorPane().getText().length() <= 0) {
removeItem();
} else {
logger.debug("Model Name changed, updating view");
constantText.syncWithDocument();
}
}
for (PropertyChangeListener l : changeListeners) {
l.propertyChange(evt);
}
}
};
/**
* The query this node is attached to as its parent.
*/
private final QueryPen queryPen;
public ConstantPNode(Item source, QueryPen mouseStates, PCanvas canvas) {
this(source, mouseStates, canvas, null);
}
public ConstantPNode(Item source, QueryPen mouseStates, PCanvas canvas, SPVariableHelper variables) {
this.item = source;
this.queryPen = mouseStates;
item.addPropertyChangeListener(itemChangeListener);
changeListeners = new ArrayList<PropertyChangeListener>();
selectionCheckbox = new JCheckBox();
selectionCheckbox.setOpaque(false);
selectionCheckbox.setSelected(item.isSelected());
PSwing swingCheckbox = new PSwing(selectionCheckbox);
addChild(swingCheckbox);
selectionCheckbox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (selectionCheckbox.isSelected()) {
queryPen.getModel().selectItem(item);
} else {
queryPen.getModel().unselectItem(item);
}
}
});
constantText = new EditablePStyledText(source.getName(), mouseStates, canvas);
constantText.addEditStyledTextListener(removeItemListener);
double yPos = (swingCheckbox.getFullBounds().getHeight() - constantText.getHeight())/2;
constantText.translate(swingCheckbox.getFullBounds().getWidth() + SPACING_SIZE, yPos);
addChild(constantText);
if (item.getAlias().trim().length() > 0) {
aliasText = new EditablePStyledText(item.getAlias(), mouseStates, canvas, LONG_EMPTY_STRING.length());
} else {
aliasText = new EditablePStyledText(LONG_EMPTY_STRING, mouseStates, canvas, LONG_EMPTY_STRING.length());
}
aliasText.addEditStyledTextListener(new EditStyledTextListener() {
public void editingStopping() {
item.setAlias(aliasText.getEditorPane().getText().trim());
}
public void editingStarting() {
//do nothing
}
});
aliasText.translate(swingCheckbox.getFullBounds().getWidth() + constantText.getWidth() + 2 * SPACING_SIZE, yPos);
addChild(aliasText);
if (item.getWhere().trim().length() > 0) {
whereText = new EditablePStyledTextWithOptionBox(item.getWhere(), mouseStates, canvas, LONG_EMPTY_STRING.length(), variables);
} else {
whereText = new EditablePStyledTextWithOptionBox(LONG_EMPTY_STRING, mouseStates, canvas, LONG_EMPTY_STRING.length(), variables);
}
whereText.addEditStyledTextListener(new EditStyledTextListener() {
public void editingStopping() {
item.setWhere(whereText.getEditorPane().getText().trim());
}
public void editingStarting() {
//do nothing
}
});
whereText.translate(swingCheckbox.getFullBounds().getWidth() + constantText.getWidth() + aliasText.getWidth() + 3 * SPACING_SIZE, yPos);
addChild(whereText);
}
public Item getItem() {
return item;
}
public String getAlias() {
return aliasText.getEditorPane().getText().trim();
}
public String getWhereText() {
return whereText.getEditorPane().getText().trim();
}
public double getAliasOffset() {
return selectionCheckbox.getWidth() + constantText.getWidth() + 2 * SPACING_SIZE;
}
public double getWhereOffset() {
double offset = aliasText.getFullBounds().getX() + aliasText.getWidth() + SPACING_SIZE;
logger.debug("Returning where offset of " + offset + " where position is currently " + whereText.getFullBounds().getX());
return offset;
}
public void setAliasXPosition(double position) {
aliasText.translate(position - aliasText.getFullBounds().getX(), 0);
whereText.translate(position - aliasText.getFullBounds().getX(), 0);
}
public void setWhereXPosition(double position) {
whereText.translate(position - whereText.getFullBounds().getX(), 0);
}
public void addChangeListener(PropertyChangeListener l) {
changeListeners.add(l);
}
public void removeChangeListener(PropertyChangeListener l) {
changeListeners.remove(l);
}
public void setSelected(boolean selected) {
selectionCheckbox.setSelected(selected);
if (selected) {
queryPen.getModel().selectItem(item);
} else {
queryPen.getModel().unselectItem(item);
}
}
public boolean isInSelect() {
return selectionCheckbox.isSelected();
}
public void cleanup() {
item.removePropertyChangeListener(itemChangeListener);
}
public Item getModel() {
return item;
}
}