/********************************************************************************* * 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.ui.event.*; import totalcross.sys.*; /** * ComboBoxDropDown is a simple implementation of a PopUp Listbox. Used by the ComboBox class. */ public class ComboBoxDropDown extends Window { /** The assigned ListBox. */ public ListBox lb; /** Set to true if want to make the control popup below or above always, and not only if WinCE */ public boolean dontHideParent = true; // guich@200b4_205: let the user choose to not hide the parent control /** Set to true to make this pop have the screen height */ public boolean fullHeight; // guich@330_52 /** Set to true to make this popup have the screen width */ public boolean fullWidth; // guich@550_19 private int selected; // guich@580_27 /** Creates a ComboBoxDropDown with coordinates that will be set later via the setRect method. */ public ComboBoxDropDown() { this(new ListBox()); } /** Creates a ComboBoxDropDown with the given ListBox. You can extend the ListBox to * draw the items by yourself and use this constructor so the ComboBoxDropDown will * use your class and not the default ListBox one. Note that this constructor forces * the ListBox.simpleBorder to true. */ public ComboBoxDropDown(ListBox lb) { if (uiAndroid) transparentBackground = lb.transparentBackground = true; started = true; // avoid calling the initUI method this.lb = lb; lb.simpleBorder = true; super.add(lb); focusTraversable = false; // kmeehl@tc100 lb.focusTraversable = false; } /** Sets the font of the controls inside this window */ protected void onFontChanged() // guich@200b4_153 { if (lb != null) lb.setFont(font); } /** Sets the absolute rect of the parent's control. The ComboBoxDropDown * rect will be computed based on that rectangle. */ public void setRect(int x, int y, int width, int height, Control relative, boolean screenChanged) { if (lb.size() > 0) { // Now calculate the position on the screen // set the x any y coordinate to fit to // the screen by the given width and height. if (fullWidth) { x = 0; width = Settings.screenWidth; } else { int origW = width; // width fit to screen - keep same size of parent control if possible, and less than the screen width width = Math.min(Math.max(uiFlat ? width : (width-2),lb.getPreferredWidth()),Settings.screenWidth-10); if (x+width > Settings.screenWidth) // guich@220_24: make sure the pop doesnt go beyond the screen { x += origW-width; // guich@tc115_57 if (x+width > Settings.screenWidth || x < 0) x = Settings.screenWidth - width; } } // height fit to screen int ih = lb.itemCount > 0 ? lb.getItemHeight(0) : fmH; int prefH = lb.getPreferredHeight(); int remainsAtBottom = Settings.screenHeight - (y+height); int remainsAtTop = y; if (prefH <= remainsAtBottom) // can fit at bottom? { if (dontHideParent) y += height-1; // put window below parent's height = prefH; } else if (prefH <= remainsAtTop) // can fit at top? { if (dontHideParent) y -= prefH-1; // put window above parent's else y += height-prefH-1; // put window below parent's - guich@210_5: fix popping up a PalmOS Combo placed in the LEFT,BOTTOM. height = prefH; } else // cant fit on screen if (fullHeight/* && prefH > Settings.screenHeight*/) // guich@330_52 - guich@402_7: commented 2nd part { height = Math.min(prefH,((int)((Settings.screenHeight-6) / ih))*ih + 6); y = (Settings.screenHeight-height)>>1; } else if (remainsAtBottom >= remainsAtTop) // more area at bottom? { if (dontHideParent) y += height-1; // put win below parent's using parent's height height = ((int)((remainsAtBottom-6) / ih)) * ih + 6; if (!dontHideParent) height += ih; // guich@220_24 } else { height = ((int)((remainsAtTop-6) / ih)) * ih + 6; if (!dontHideParent) // guich@220_24: hide parent? add one more row to the height { height += ih; y += ih; } y -= height-1; } // End of the "fit to screen part" } super.setRect(x,y,width,height,null,screenChanged); lb.setRect(0,0,width,height,null,screenChanged); } /** Close the popup list with a click outside its bounds */ protected boolean onClickedOutside(PenEvent event) { if (event.type == PenEvent.PEN_DOWN) // kmeehl@tc100: only unpop for pen_down, to make it easier to manipulate { setHighlighting(); // kmeehl@tc100: set highlighting back to allow navigation through controls again unpop(); } return true; } public void onEvent(Event event) { switch (event.type) { case KeyEvent.SPECIAL_KEY_PRESS: if (event.target == lb && ((KeyEvent)event).key == SpecialKeys.ESCAPE) // brunos@tc120: ESCAPE means: cancel selection and close dropdown { lb.setSelectedIndex(selected); // restore original selection, since the user is canceling requestFocus(); // guich@tc123_15 unpop(); } break; //case KeyEvent.ACTION_KEY_PRESS: // kmeehl@tc100 - guich@tc113_9: commented out case ControlEvent.PRESSED: if (event.target == lb && topMost == this) // guich@tc305: fix problem when a MLB is inside a window, this unpop was closing the window unpop(); break; } } public int getPreferredWidth() { return lb.getPreferredWidth() + insets.left+insets.right; } public int getPreferredHeight() { return lb.getPreferredHeight() + insets.top+insets.bottom; } protected void onPopup() // guich@321_13 { selected = lb.getSelectedIndex(); if (lb instanceof MultiListBox) ((MultiListBox)lb).cbddOnPopup(); } protected void postUnpop() { if (lb instanceof MultiListBox) ((MultiListBox)lb).cbddOnUnpop(); else if (selected != lb.getSelectedIndex()) // guich@580_27 postPressedEvent(); } }