/********************************************************************************* * TotalCross Software Development Kit * * Copyright (C) 2001 Daniel Tauchke * * Copyright (C) 2001-2012 SuperWaba Ltda. * * All Rights Reserved * * * * This library and virtual machine 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. * * * * This file is covered by the GNU LESSER GENERAL PUBLIC LICENSE VERSION 3.0 * * A copy of this license is located in file license.txt at the root of this * * SDK or can be downloaded here: * * http://www.gnu.org/licenses/lgpl-3.0.txt * * * *********************************************************************************/ package totalcross.ui; import totalcross.sys.*; import totalcross.ui.event.*; import totalcross.ui.gfx.*; import totalcross.util.*; /** The ComboBoxEditable is a control usually used as an Edit that holds * old typed values. When the user types a word, it is automatically selected in * the ComboBox. Here's a sample of how to use it: * <pre> String[] items = {"Ana","Barbara","Raul","Marcelo","Eduardo","Denise","Michelle","Guilherme","Vera","Dulce","Leonardo","Andre","Gustavo","Anne","Renato","Zelia","Helio"}; ComboBoxEditable cbe = new ComboBoxEditable(items); cbe.qsort(); add(cbe, LEFT,BOTTOM-100); * </pre> */ public class ComboBoxEditable extends ComboBox implements PressListener, KeyListener // guich@tc113_3 { /** The edit used in this ComboBox. You can customize it if you need. */ public Edit edit; private boolean autoAdd,keepSorted; private String oldText; public ComboBoxEditable() { this((Object[])null); } public ComboBoxEditable(Object[] items) { this(new ListBox(items)); } public ComboBoxEditable(ListBox userListBox) { this(new ComboBoxDropDown(userListBox)); } public ComboBoxEditable(ComboBoxDropDown userPopList) { super(userPopList); pop.lb.setFocusLess(true); super.add(edit = new Edit(),true); edit.transparentBackground = true; edit.hasBorder = false; pop.lb.addPressListener(this); edit.addKeyListener(this); edit.addPressListener(this); tabOrder.removeElement(edit); pop.dontHideParent = true; } /** Set to true to add automatically new names that were typed in the edit. * @param on Flag indicating if autoAdd must be set * @param keepSorted If the list must be sorted after a new item is added by the autoAdd. */ public void setAutoAdd(boolean on, boolean keepSorted) { autoAdd = on; this.keepSorted = keepSorted; } protected void onFontChanged() { edit.setFont(font); pop.lb.setFont(font); } protected void onColorsChanged(boolean colorsChanged) { super.onColorsChanged(colorsChanged); edit.setBackForeColors(backColor,foreColor); } protected void onBoundsChanged(boolean screenChanged) { super.onBoundsChanged(screenChanged); Rect r = btn.getRect(); int yy = uiAndroid ? 2 : -2; int hh = fmH+Edit.prefH; if (r.x < width/2) // at left? edit.setRect(r.x2(), yy, width-r.x2(), hh); else edit.setRect(0, yy, r.x, hh); } public void onEvent(Event e) { switch (e.type) { case KeyEvent.ACTION_KEY_PRESS: // focus is not here yet edit.requestFocus(); break; case KeyEvent.KEY_PRESS: case KeyEvent.SPECIAL_KEY_PRESS: KeyEvent ke = (KeyEvent)e; if (ke.key == SpecialKeys.ESCAPE) unpop(); else if (ke.isActionKey()) actionkeyPressed(null); else if (e.target == edit) selectFromEdit(); break; case ControlEvent.FOCUS_OUT: unpop(); break; case ControlEvent.FOCUS_IN: if (e.target != this) popup(); return; } super.onEvent(e); } public void popup() { if (!pop.lb.isDisplayed()) { oldText = edit.getText(); // we can't open a Window, otherwise the user will not be able // to write in the Edit. So, we add the ListBox to our parent. updatePopRect(); parent.add(pop.lb); // guich@tc130: fix window position boolean toTop = pop.y < this.y; int h = pop.height; int ph = parent.getClientRect().height; if (h+this.height > ph) h = ph - this.height; pop.lb.setRect(SAME,toTop ? BEFORE : AFTER,pop.width,h,this); } if (getParentWindow().getFocus() != edit) edit.requestFocus(); } /** Closes the open ListBox. */ public void unpop() { String newText = edit.getText(); if (autoAdd && pop.lb.getSelectedIndex() == -1 && newText.length() > 0) { pop.lb.add(newText); if (keepSorted) pop.lb.qsort(true); pop.lb.setSelectedItem(newText); } boolean match = newText.equals(oldText); oldText = newText; if (!match) postPressedEvent(); parent.remove(pop.lb); } protected void drawSelectedItem(Graphics g) { // do nothing } private void setTextFromList() { if (getSelectedIndex() >= 0) edit.setText(getSelectedItem().toString()); getParentWindow().removeFocus(); getParentWindow().swapFocus(this); } private void selectFromEdit() { if (edit.getLength() == 0 || !pop.lb.setSelectedItemStartingWith(edit.getText(),true)) pop.lb.setSelectedIndex(-1); } public void controlPressed(ControlEvent e) { if (e.target == edit) selectFromEdit(); else setTextFromList(); } public void actionkeyPressed(KeyEvent e) { setTextFromList(); } public void keyPressed(KeyEvent e) { } public void specialkeyPressed(KeyEvent ke) { if (ke.isUpKey() || ke.isDownKey()) { int idx = pop.lb.getSelectedIndex(); if (Settings.circularNavigation) pop.lb.setSelectedIndex(ke.isDownKey() ? (idx+1)%pop.lb.itemCount : idx <= 0 ? pop.lb.itemCount-1 : idx-1); else pop.lb.setSelectedIndex(ke.isDownKey() ? Math.min((idx+1), pop.lb.itemCount-1) : Math.max(0, idx-1)); ke.consumed = true; return; } } public void getFocusableControls(Vector v) // kmeehl@tc100 { if (visible && isEnabled()) v.addElement(this); } public Control handleGeographicalFocusChangeKeys(KeyEvent ke) // kmeehl@tc100 { return this; } }