/*********************************************************************************
* TotalCross Software Development Kit - Litebase *
* Copyright (C) 2000-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. *
* *
*********************************************************************************/
package totalcross.db.sqlite.ui;
import totalcross.ui.gfx.*;
import totalcross.ui.*;
/**
* DBListBox is a simple implementation of a Listbox.
* You can use the up/down keys to scroll and enter the first
* letter of an item to select it.
* <p>
* Note: the color used in the setBackground method will be used in the scrollbar
* only. The background color of the control will be a lighter version of the
* given color.
* <p>
* Note: this is a special version for the LitebaseConnection. It accepts
* a String matrix as the input, and does not allow add/remove/set of elements,
* since it reflects the database and must be filled again after some row is
* updated.
* <p>
* Here is an example showing how it can be used:
*
* <pre>
* import litebase.ui.*;
* import litebase.*;
*
* public class MyProgram extends totalcross.ui.MainWindow
* {
* DBListBox lb;
*
* public void initUI()
* {
* ResultSet rs = driver.executeQuery("select rowid,name from person where name > 20");
* rs.first();
* lb = new DBListBox(rs.getStrings(-1,true,false),1); // display column 1
* add(lb,LEFT,TOP);
* }
*
* public void onEvent(totalcross.ui.event.Event event)
* {
* switch (event.type)
* {
* case totalcross.ui.event.ControlEvent.PRESSED:
* if (event.target == lb)
* String[] element = (String[])lb.getSelectedItem(); // in most cases, this is just a String and may be casted to such
* }
* }
* }
* </pre>
* The first item has index 0.
*/
public class DBListBox extends ListBox
{
/** The String items */
protected String [][]sitems;
/** Creates an empty Listbox. */
public DBListBox()
{
this(null,-1);
}
/** Creates a Listbox with the given items. */
public DBListBox(String[][] items, int displayCol)
{
super((Object[])null);
if (items != null)
{
sitems = items;
itemCount = items.length;
}
this.dataCol = displayCol;
}
/** Sets the column of the String matrix that will be used to display the
* elements.
*/
public void setDisplayCol(int displayCol)
{
this.dataCol = displayCol;
}
/** Returns the number of columns, if there are items.
*/
public int getColumnCount()
{
return sitems == null || sitems.length == 0 ? 1 : sitems[0].length;
}
/** <b>REPLACES</b> the current items with the given ones. */
public void add(Object []items)
{
if (items instanceof String[][])
{
sitems = (String[][])items;
itemCount = sitems.length;
sbar.setEnabled(isEnabled() && visibleItems < itemCount);
sbar.setMaximum(itemCount); // guich@210_12: forgot this line!
}
}
/** <b>REPLACES</b> the current items with the given ones. */
public void add(Object item)
{
if (item instanceof String[][])
add((Object[])item);
}
/** Does nothing */
public void insert(Object item, int index)
{
}
/** Empties this ListBox, setting all elements of the array to <code>null</code>
so they can be garbage collected.
<b>Attention!</b> If you used the same object array
to initialize two ListBoxes (or ComboBoxes), this method will null both ListBoxes
('cos they use the same array reference),
and you'll get a null pointer exception!
*/
public void removeAll() // guich@210_13
{
sitems = null;
sbar.setMaximum(0);
itemCount = 0;
offset=0; // wolfgang@330_23
repaint();
}
/** Does nothing */
public void remove(int itemIndex) // guich@200final_12: new method
{
}
/** Does nothing */
public void remove(Object item)
{
}
/** Does nothing */
public void setItemAt(int i, Object s)
{
}
/** Get the Object at the given Index. Returns a String array, or null if i is out of range. */
public Object getItemAt(int i)
{
if (0 <= i && i < itemCount)
return sitems[i];
return null;
}
/** Returns the selected item of the Listbox or null if none is selected */
public Object getSelectedItem()
{
return selectedIndex >= 0 ? sitems[selectedIndex] : null;
}
/** Returns the position of the selected item of the Listbox or -1 if the listbox has no selected index yet. */
public int getSelectedIndex()
{
return selectedIndex;
}
/** Returns all items in this ListBox. The array can be casted to String[][].
*/
public Object []getItems()
{
return sitems;
}
protected Object []getItemsArray()
{
return sitems;
}
/** Returns the index of the object at the given column. */
public int indexOf(Object name, int col)
{
for (int i = 0; i < sitems.length; i++)
if (sitems[i][col].equals(name))
return i;
return -1;
}
/** Select an item and scroll to it if necessary. Note: select must be called only after the control has been added to the container and its rect has been set. */
public void setSelectedIndex(int i)
{
if (0 <= i && i < itemCount && i != selectedIndex/* && height != 0*/) // flsobral@220_14: commented height!=0 otherwise combobox are not properly set. (same problem observed with listbox)
{
offset=i;
int vi = sbar.getVisibleItems();
int ma = sbar.getMaximum();
if (offset+vi > ma) // astein@200b4_195: fix list items from being lost when the comboBox.setSelectedIndex() method is used
offset=Math.max(ma-vi,0); // guich@220_4: fixed bug when the listbox is greater than the current item count
selectedIndex = i;
sbar.setValue(offset); // guich@210_9: fixed scrollbar update when selecting items
repaint();
}
else
if (i == -1) // guich@200b4_191: unselect all items
{
offset = 0;
sbar.setValue(0);
selectedIndex = -1;
repaint();
}
}
/** Returns the number of items */
public int size()
{
return itemCount;
}
/** Does nothing */
public void add(Control control)
{
}
/** Does nothing */
public void remove(Control control)
{
}
/** Does nothing */
protected void find(char c)
{
}
/** You can extend ListBox and overide this method to draw the items */
protected void drawItem(Graphics g, int index, int dx, int dy)
{
//Vm. debug(this+" index: "+index+", items.size: "+items.size()+", dx,dy = "+dx+","+dy);
if (0 <= index && index < itemCount)
g.drawText(sitems[index][dataCol],dx,dy);
}
/** Returns the width of the given item index with the current fontmetrics. Note: if you overide this class you must implement this method. */
protected int getItemWidth(int index)
{
if (sitems == null) return 0;
return fm.stringWidth(sitems[index][dataCol]);
}
private void qsort(int first, int last) // guich@220_34
{
String[][] sitems = this.sitems;
int low = first;
int high = last;
if (first >= last)
return;
String mid = sitems[(first+last) >> 1][dataCol];
while (true)
{
while (high >= low && mid.compareTo(sitems[low][dataCol]) > 0) // guich@_566_25: added "high > low" here and below - guich@_568_5: changed to >=
low++;
while (high >= low && mid.compareTo(sitems[high][dataCol]) < 0)
high--;
if (low <= high)
{
String []temp = sitems[low];
sitems[low++] = sitems[high];
sitems[high--] = temp;
}
else break;
}
if (first < high)
qsort(first,high);
if (low < last)
qsort(low,last);
}
/** Sorts the elements of this ListBox. The current selection is cleared. */
public void qsort()
{
qsort(0,itemCount-1);
setSelectedIndex(-1);
}
public String getText()
{
return selectedIndex < 0 ? "" : sitems[selectedIndex][dataCol];
}
}