/******************************************************************************* * This is part of SketchChair, an open-source tool for designing your own furniture. * www.sketchchair.cc * * Copyright (C) 2012, Diatom Studio ltd. Contact: hello@diatom.cc * * This program 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. * * This program 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 ModalGUI; /** * controlP5 is a processing and java library for creating simple control GUIs. * * 2007 by Andreas Schlegel * * This library 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 2.1 * of the License, or (at your option) any later version. * This library 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 this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307 USA * * @author Andreas Schlegel (http://www.sojamo.de) * */ import java.util.ArrayList; import java.util.Date; import processing.core.PConstants; import processing.core.PGraphics; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; import cc.sketchchair.core.LOGGER; /** * description for singleline textfield. create a texfield with<br /> * <br /> * controlP5.addTextfield(theName,theX,theY,theWidth,theHeight); * * the Textfield implementation for ControlP5 tries its best to imitate the * usage and behavior of a terminal, the command line. * * @example ControlP5textfield * @nosuperclasses Controller * @related Controller */ public class GUITextfield extends GUIComponent { /* * TODO needs a lot of work! has gone through massive amounts of little * changes and adjustments. implement new fonts, current one is too small. * make the text go to the left when cursor goes beyond right border. make * textfield work for controlWindow * */ protected ArrayList myTextList = new ArrayList(); int myIndex = 1; int myPosition = 0; StringBuffer myTextline = new StringBuffer(); public boolean isTexfieldActive = false; private boolean isPasswordMode = false; protected boolean isAutoClear = true; protected boolean isKeepFocus = false; protected String _myStringValue; protected String myPasswordTextline = ""; public boolean isActive = false; public GUITextfield(float x, float y, float w, float h, ModalGUI c) { //this(x,y,w,h,applet); this.setController(c); this.setPos(x, y); this.setSize(w, h); } /** * @invisible * @param theControllerProperties * ControllerProperties * @return */ public GUITextfield(String theName, String theDefaultValue, int theX, int theY, int theWidth, int theHeight, ModalGUI c) { } /** * @invisible */ protected void adjust() { myPosition = myTextline.length(); if (myPosition < 0) { myPosition = 0; } } protected void checkClear() { if (isAutoClear) { myTextline = new StringBuffer(); myIndex = myTextList.size(); myPosition = 0; updateField(); } } /** * clear the current content of the textfield. */ public void clear() { myTextline = new StringBuffer(); myIndex = myTextList.size(); myPosition = 0; updateField(); } /** * get the current text of the textfield. * * @return String */ public String getText() { return myTextline.toString(); } /** * returns a string array that lists all text lines that have been confirmed * with a return. * * @return */ public String[] getTextList() { String[] s = new String[myTextList.size()]; myTextList.toArray(s); return s; } /** * @invisible * @param theElement * ControlP5XMLElement */ /* public void addToXMLElement( // ControlP5XMLElement theElement) { // theElement.setAttribute("type", "textfield"); // theElement.setAttribute("value", "" + stringValue()); } */ @Override public boolean hasFocus() { if (this.hasFocus || this.isActive) return true; else return false; } /** * returns the current state of the autoClear flag. * * @return */ public boolean isAutoClear() { return isAutoClear; } /** * check if the textfield is active and in focus. * * @return boolean */ public boolean isFocus() { return isTexfieldActive; } /** * set the textfield's focus to true or false. * * @param theFlag * boolean */ /* public void setFocus( boolean theFlag) { this.hasFocus = theFlag; if (theFlag == true) { mousePressed(); } else { mouseReleasedOutside(); } } */ /** * use true as parameter to force the textfield to stay in focus. to go back * to normal focus behavior, use false. * * @param theFlag */ public void keepFocus(boolean theFlag) { isKeepFocus = theFlag; if (isKeepFocus) { this.setFocus(true); } } /** * flip throught the texfield history with cursor keys UP and DOWN. go back * and forth with cursor keys LEFT and RIGHT. * * @invisible */ @Override public void keyEvent(KeyEvent theKeyEvent) { if (isTexfieldActive && isActive && theKeyEvent.getID() == KeyEvent.KEY_PRESSED) { if (theKeyEvent.getKeyCode() == KeyEvent.VK_UP) { if (myTextList.size() > 0 && myIndex > 0) { myIndex--; myTextline = new StringBuffer( (String) myTextList.get(myIndex)); adjust(); } } else if (theKeyEvent.getKeyCode() == KeyEvent.VK_DOWN) { myIndex++; if (myIndex >= myTextList.size()) { myIndex = myTextList.size(); myTextline = new StringBuffer(); } else { myTextline = new StringBuffer( (String) myTextList.get(myIndex)); } adjust(); } else if (theKeyEvent.getKeyCode() == KeyEvent.VK_LEFT) { if (myPosition > 0) { myPosition--; } } else if (theKeyEvent.getKeyCode() == KeyEvent.VK_RIGHT) { if (myPosition < myTextline.length()) { myPosition++; } } else if (theKeyEvent.getKeyCode() == KeyEvent.VK_DELETE || theKeyEvent.getKeyCode() == KeyEvent.VK_BACK_SPACE) { if (myTextline.length() > 0) { if (myPosition > 0) { myTextline.deleteCharAt(myPosition - 1); myPosition--; } } } else if (theKeyEvent.getKeyCode() == KeyEvent.VK_ENTER) { submit(); } else if (theKeyEvent.getKeyCode() != KeyEvent.VK_SHIFT && theKeyEvent.getKeyCode() != KeyEvent.VK_ALT && theKeyEvent.getKeyCode() != KeyEvent.VK_CONTROL) { if (theKeyEvent.getKeyCode() >= 31 && theKeyEvent.getKeyCode() <= 127) { myTextline.insert(myPosition, theKeyEvent.getKeyChar()); myPosition++; } } updateField(); } } /** * @invisible * @param theElement * ControlP5XMLElement */ /* public void addToXMLElement( // ControlP5XMLElement theElement) { // theElement.setAttribute("type", "textfield"); // theElement.setAttribute("value", "" + stringValue()); } */ @Override public void mouseWheelMoved(MouseWheelEvent e) { } @Override public void mouseEvent(MouseEvent e) { // if (e.getID() == MouseEvent.MOUSE_PRESSED) { if (isMouseOver()) wasClicked = true; } else if (e.getID() == MouseEvent.MOUSE_RELEASED && wasClicked && isMouseOver()) { // fireEventNotification(this, "Clicked"); this.isActive = true; this.isTexfieldActive = true; this.setFocus(true); } if (e.getID() == MouseEvent.MOUSE_RELEASED && wasClicked && !isMouseOver()) { this.isActive = false; this.isTexfieldActive = false; this.setFocus(false); } } /** * click the texfield to activate. * * @invisible * */ protected void mousePressed() { this.setFocus(true); //System.out.println("FOCUS"); isTexfieldActive = isActive = true; } /** * */ protected void mouseReleasedOutside() { if (isKeepFocus == false) { //System.out.println("UNFOCUS"); this.setFocus(false); isTexfieldActive = isActive = false; } } /** * @invisible * @param theApplet * PApplet */ @Override public void render(PGraphics g) { if (!this.visible) return; if (isTexfieldActive && isActive) { g.stroke(g.color(0, 0, 0)); } else { g.stroke(g.color(100, 100, 100)); } g.strokeWeight(1); g.fill(255); g.pushMatrix(); g.translate(this.getX(), this.getY()); g.rect(0, 1, this.getWidth(), this.getHeight()+1); g.fill(0); if (this.getText() != null) { g.textAlign = PConstants.LEFT; g.textAlignY = PConstants.CENTER; String activeMark = ""; if (this.hasFocus() && new Date().getTime() % 800 > 400) activeMark = "|"; if (this.controller.myFontMedium != null){ g.textFont(this.controller.myFontMedium); if(isPasswordMode) this.controller.applet.text(myPasswordTextline + activeMark, 5, 8, this.getWidth(), this.getHeight()); else{ this.controller.applet.text(this.getText() + activeMark, 5, 8); //this.controller.applet.text("hi"+this.getText(),0,0); } } g.noStroke(); //_myValueLabel.draw(theApplet, 4, 7); //_myCaptionLabel.draw(theApplet, 0, height + 4); // System.out.println(this.getText()); } g.popMatrix(); renderLabel(g); } /** * use setAutoClear(false) to not clear the content of the textfield after * confirming with return. * * @param theFlag */ public void setAutoClear(boolean theFlag) { isAutoClear = theFlag; } /** * set the mode of the textfield to password mode, each character is shown * as a "*" like e.g. in online password forms. * * @param theFlag * boolean */ public void setPasswordMode(boolean theFlag) { isPasswordMode = theFlag; } /** * setText does set the text of a textfield, but will not broadcast its * value. use setText to force the textfield to change its text. you can * call setText any time, nevertheless when autoClear is set to true (which * is the default), it will NOT work when called from within controlEvent or * within a method that has been identified by ControlP5 to forward messages * to, when return has been pressed to confirm a textfield.<br /> use * setAutoClear(false) to enable setText to be executed for the above case. * use yourTextfield.isAutoClear() to check if autoClear is true or false. * <br /> * setText replaces the current/latest content of a textfield but does NOT * overwrite the content. when scrolling through the list of textlines (use * key up and down), the previous content that has been replaced will be put * back into place again - since it has not been confirmed with return. * * @param theValue */ public void setText(String theValue) { myTextline = new StringBuffer(theValue); // myPosition = myTextline.length() - 1; _myStringValue = theValue; myPosition = myTextline.length(); // _myValueLabel.setWithCursorPosition(myTextline.toString(), myPosition); } @Override public void setup() { // TODO Auto-generated method stub } /* public Textfield( ControlP5 theControlP5, ControllerGroup theParent, String theName, String theDefaultValue, int theX, int theY, int theWidth, int theHeight) { super(theControlP5, theParent, theName, theX, theY, theWidth, theHeight); _myCaptionLabel = new Label(theName.toUpperCase(), color.colorLabel); _myCaptionLabel.setFixedSize(false); myBroadcastType = STRING; _myValueLabel.setWidth(width - 10); _myValueLabel.setHeight(15); _myValueLabel.set(">"); _myValueLabel.setColor(color.colorValue); _myValueLabel.toUpperCase(false); _myValueLabel.setFixedSize(true); _myValueLabel.setFont(ControlP5.standard56); } */ @Override public void hide(){ this.isActive = false; super.hide(); } /** * @invisible * @param theValue * float */ public void setValue(float theValue) { setValue(theValue+""); } /** * set the value of the textfield and will broadcast the new string value * immediately. what is the difference between setValue and setText? * setValue does broadcast the value that has been set, setText does not * broadcast the value, but only updates the content of a textfield. for * further information about how setText works, see the setText * documentation. * * @param theValue * String */ public void setValue(String theValue) { myTextline = new StringBuffer(theValue); // myPosition = myTextline.length() - 1; _myStringValue = theValue; myPosition = myTextline.length(); //_myValueLabel.setWithCursorPosition(myTextline.toString(), myPosition); //broadcast(myBroadcastType); } /** * make the controller execute a return event. submit the current content of * the texfield. * */ public void submit() { if (myTextline.length() > 0) { myTextList.add(myTextline.toString()); update(); checkClear(); } } /** * @invisible */ public void update() { _myStringValue = myTextline.toString(); setValue(_myStringValue); } protected void updateField() { if (isPasswordMode) { myPasswordTextline = ""; for (int i = 0; i < myTextline.length(); i++) { myPasswordTextline += "*"; } // _myValueLabel.setWithCursorPosition(myPasswordTextline, myPosition); } else { int offset = 0; // int m = _myValueLabel.bitFontRenderer.getWidth(myTextline.toString(), _myValueLabel,myPosition); //offset = (m>_myValueLabel.width()) ? _myValueLabel.width() - m:0; // _myValueLabel.setWithCursorPosition(myTextline.toString(), myPosition,offset); } } }