/*
* 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.Color;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import javax.swing.JEditorPane;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.text.BadLocationException;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import org.apache.log4j.Logger;
import ca.sqlpower.object.SPVariableHelper;
import ca.sqlpower.swingui.object.InsertVariableAction;
import ca.sqlpower.swingui.object.VariableInserter;
import ca.sqlpower.swingui.object.VariableLabel;
import edu.umd.cs.piccolo.PCanvas;
import edu.umd.cs.piccolo.PNode;
import edu.umd.cs.piccolo.event.PBasicInputEventHandler;
import edu.umd.cs.piccolo.event.PInputEvent;
import edu.umd.cs.piccolo.nodes.PPath;
import edu.umd.cs.piccolo.nodes.PText;
/**
* This class is similar to the EditablePStyledText class except this class also handles a Option Box which
* will line up right under the JEditorPane. It will handle mouse events on the options and append to the
* JEditorPane.
*/
public class EditablePStyledTextWithOptionBox extends EditablePStyledText {
private static final Logger logger = Logger.getLogger(EditablePStyledText.class);
/**
* One pixel space for adjusting the whereOptionBox with the whereTextBox.
*/
private static final int ONE_PIXEL_SPACE=1;
/**
* The options box that will display a list of where clause options
*/
private PPath whereOptionBox;
/**
* This listener will set the text of this PStyledText and hide the editor
* pane when the editor pane loses focus (ie: clicked away from the editor).
*/
private FocusListener editorFocusListener = new FocusListener() {
public void focusLost(FocusEvent e) {
if(boxClicked) {
boxClicked = false;
getEditorPane().requestFocus();
return;
} else {
whereOptionBox.removeFromParent();
getStyledTextEventHandler().stopEditing();
}
}
public void focusGained(FocusEvent e) {
whereOptionBox.translate(
getGlobalFullBounds().getX()-whereOptionBox.getXOffset()-ONE_PIXEL_SPACE,
(getGlobalFullBounds().getY() + getEditorPane().getHeight())-whereOptionBox.getYOffset());
if (!queryPen.getTopLayer().isAncestorOf(whereOptionBox))
queryPen.getTopLayer().addChild(whereOptionBox);
whereOptionBox.moveToFront();
}
};
/**
* This is the width of the WHERE option's box
*/
private static final int WHERE_OPTION_BOX_WIDTH = 100;
/**
* This is the height of the Where option's box
*/
private static final int WHERE_OPTION_BOX_HIEGHT = 90;
private boolean boxClicked;
private final QueryPen queryPen;
private final SPVariableHelper variablesHelper;
/**
* This is an Array of Where Options for the whereOptionsBox
*/
private static final String[] whereOptions = new String[]{"<", ">",
"=", "<>", ">=", "<=", "BETWEEN", "LIKE", "IN", "NOT" };
public EditablePStyledTextWithOptionBox(String startingText, QueryPen queryPenRef, PCanvas canvas, int minCharCountSize) {
this(startingText, queryPenRef, canvas, minCharCountSize, null);
}
public EditablePStyledTextWithOptionBox(String startingText, QueryPen queryPenRef, final PCanvas canvas, int minCharCountSize, SPVariableHelper variables) {
super(startingText, queryPenRef, canvas, minCharCountSize);
this.queryPen = queryPenRef;
this.variablesHelper = variables;
getEditorPane().removeFocusListener(getEditorFocusListener());
getEditorPane().addFocusListener(editorFocusListener);
if (this.variablesHelper != null) {
// Substitutes the variables for the nice variables labels
VariableLabel.insertLabels(this.variablesHelper, (StyledDocument)getDocument(), getEditorPane());
// Maps CTRL+SPACE to insert variable
getEditorPane().getInputMap().put(
KeyStroke.getKeyStroke(
KeyEvent.VK_SPACE,
InputEvent.CTRL_MASK),
"insertVariable");
getEditorPane().getActionMap().put(
"insertVariable",
new InsertVariableAction(
"Insert variable",
this.variablesHelper,
null,
new VariableInserter() {
public void insert(String variable) {
try {
getEditorPane().setText(getEditorPane().getText().trim());
getEditorPane().getDocument().insertString(
getEditorPane().getCaretPosition(),
variable,
null);
} catch (BadLocationException e) {
throw new IllegalStateException(e);
}
syncWithDocument();
getStyledTextEventHandler().stopEditing();
}
},
this.getEditorPane()));
}
whereOptionBox = PPath.createRectangle(0, 0
, (float)WHERE_OPTION_BOX_WIDTH, (float)WHERE_OPTION_BOX_HIEGHT);
whereOptionBox.addInputEventListener(new PBasicInputEventHandler() {
@Override
public void mousePressed(PInputEvent event) {
boxClicked = true;
}
});
// Add the whereOptions to the whereOptionsBox with Mouse Listeners.
int yLoc = 0;
int xLoc = 0;
for(String whereOption : whereOptions) {
final PText newOption = new PText(whereOption);
final PNode background = new PNode();
background.setTransparency((float)0.3);
newOption.addAttribute(StyleConstants.FontFamily, UIManager.getFont("List.font").getFamily());
newOption.translate((WHERE_OPTION_BOX_WIDTH/3)*xLoc+ ONE_PIXEL_SPACE*3, (getHeight()+ 1) * yLoc+ ONE_PIXEL_SPACE*5);
background.setBounds(newOption.getBounds().getX(), newOption.getBounds().getY()
,newOption.getBounds().getWidth()+ 3, newOption.getBounds().getHeight()+3);
newOption.addChild(background);
background.setPaint(Color.gray);
background.setVisible(false);
newOption.addInputEventListener(new PBasicInputEventHandler() {
@Override
public void mouseEntered(PInputEvent event) {
background.setVisible(true);
newOption.repaint();
}
@Override
public void mouseExited(PInputEvent event) {
background.setVisible(false);
newOption.repaint();
}
@Override
public void mousePressed(PInputEvent event) {
JEditorPane whereEditorPane = getEditorPane();
try {
whereEditorPane.getDocument().insertString(whereEditorPane.getCaretPosition()
, newOption.getText(), null);
} catch (BadLocationException e) {
logger.debug("Bad Location when trying to insert whereOption on whereText");
throw new IllegalStateException(e);
}
}
});
yLoc++;
if(yLoc > 4) {
yLoc = 0;
xLoc = 1;
}
whereOptionBox.addChild(newOption);
}
}
// public void syncWithDocument() {
// if (this.variablesHelper == null) {
// super.syncWithDocument();
// } else {
// getEditorPane().setText(getEditorPane().getText().trim());
// VariableLabel.insertLabelsForPicollo((StyledDocument)getDocument());
// if (getEditorPane().getText() == null || getEditorPane().getText().trim().equals("") ) {
// getEditorPane().setText(startingText);
// } else if ( getEditorPane().getText().length() < minCharCountSize) {
// StringBuffer sb = new StringBuffer();
// for (int i = 0; i < minCharCountSize - getEditorPane().getText().length(); i++) {
// sb.append(" ");
// }
// getEditorPane().setText(getEditorPane().getText() + sb.toString());
// }
// super.syncWithDocument();
// VariableLabel.removeLabelsForPicollo((StyledDocument)getDocument());
// }
// }
public PPath getOptionBox() {
return whereOptionBox;
}
}