blob: 664425337240182c3394e41b4978693eeeb7cc7a [file] [log] [blame]
/*
* Copyright 1995-2004 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.awt.motif;
import java.awt.*;
import java.awt.peer.*;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
class MListPeer extends MComponentPeer implements ListPeer {
native void create(MComponentPeer parent);
void initialize() {
List li = (List)target;
/* add any items that were already inserted in the target. */
int nitems = li.countItems();
for (int i = 0; i < nitems; i++) {
addItem(li.getItem(i), -1);
}
/* set whether this list should allow multiple selections. */
setMultipleSelections(li.allowsMultipleSelections());
/* make the visible position visible. */
int index = li.getVisibleIndex();
if (index >= 0) {
makeVisible(index);
}
/* select the item if necessary. */
int sel[] = li.getSelectedIndexes();
for (int i = 0 ; i < sel.length ; i++) {
select(sel[i]);
}
/* BugID 4060345 to avoid showing scrollbar in empty List */
if (nitems == 0) {
addItem(" ", 0);
delItems(0, 0);
}
super.pSetScrollbarBackground(getParent_NoClientCode(li).getBackground());
if (!target.isBackgroundSet()) {
target.setBackground(SystemColor.text);
}
if (!target.isForegroundSet()) {
target.setForeground(SystemColor.textText);
}
super.initialize();
}
MListPeer(List target) {
super(target);
}
/* New method name for 1.1 */
public void add(String item, int index) {
addItem(item, index);
}
/* New method name for 1.1 */
public void removeAll() {
clear();
}
/* New method name for 1.1 */
public void setMultipleMode (boolean b) {
setMultipleSelections(b);
}
/* New method name for 1.1 */
public Dimension getPreferredSize(int rows) {
return preferredSize(rows);
}
/* New method name for 1.1 */
public Dimension getMinimumSize(int rows) {
return minimumSize(rows);
}
public void setForeground(Color c) {
pSetInnerForeground(c);
}
public native void setBackground(Color c);
public native void setMultipleSelections(boolean v);
public native boolean isSelected(int index);
public native void addItem(String item, int index);
public native void delItems(int start, int end);
public native void select(int index);
public native void deselect(int index);
public native void makeVisible(int index);
public void clear() {
List l = (List)target;
int count = l.countItems();
if (count > 0) {
delItems(0, count-1);
}
}
public int[] getSelectedIndexes() {
List l = (List)target;
int len = l.countItems();
int sel[] = new int[len];
int nsel = 0;
for (int i = 0 ; i < len ; i++) {
if (isSelected(i)) {
sel[nsel++] = i;
}
}
int selected[] = new int[nsel];
System.arraycopy(sel, 0, selected, 0, nsel);
return selected;
}
// NOTE: This method may be called by privileged threads.
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
public void action(int index, final long when, final int modifiers) {
final List list = (List)target;
final int selectIndex = index;
MToolkit.executeOnEventHandlerThread(list, new Runnable() {
public void run() {
list.select(selectIndex);
postEvent(new ActionEvent(target, ActionEvent.ACTION_PERFORMED,
list.getItem(selectIndex), when,
modifiers));
}
});
} // action()
// NOTE: This method may be called by privileged threads.
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
public void handleListChanged(int index) {
final MListPeer listPeer = this;
final List list = (List)target;
final int listIndex = index;
MToolkit.executeOnEventHandlerThread(list, new Runnable() {
public void run() {
int selected[] = listPeer.getSelectedIndexes();
boolean isSelected = false;
for (int i=0; i < selected.length; i++) {
if (listIndex == selected[i]) {
isSelected = true;
break;
}
}
postEvent(new ItemEvent(list, ItemEvent.ITEM_STATE_CHANGED,
Integer.valueOf(listIndex),
isSelected? ItemEvent.SELECTED : ItemEvent.DESELECTED));
}
});
} // handleListChanged()
public Dimension minimumSize() {
return minimumSize(4);
}
public Dimension preferredSize(int v) {
return minimumSize(v);
}
public Dimension minimumSize(int v) {
FontMetrics fm = getFontMetrics(((List)target).getFont());
return new Dimension(SCROLLBAR + 2*MARGIN +
fm.stringWidth("0123456789abcde"),
((fm.getHeight()+2*SPACE) * v) +
2*MARGIN);
}
public boolean isFocusable() {
return true;
}
/*
* Print the native component by rendering the Motif look ourselves.
* ToDo(aim): needs to query native motif for more accurate size and
* color information, selected items, and item offset.
*/
final static int MARGIN = 2;
final static int SPACE = 1;
final static int SCROLLBAR = 16;
int fontHeight;
int fontAscent;
int fontLeading;
int vval;
int hval;
int vmax;
int hmax;
public void print(Graphics g) {
List l = (List)target;
Dimension d = l.size();
Color bg = l.getBackground();
Color fg = l.getForeground();
int numItems = l.getItemCount();
FontMetrics fm = getFontMetrics(l.getFont());
int w, h;
int vvis, hvis, vmin, hmin;
int max = 0;
for (int i = 0; i < numItems; i++) {
int len = fm.stringWidth(l.getItem(i));
max = Math.max(max, len);
}
fontHeight = fm.getHeight();
fontAscent = fm.getAscent();
fontLeading = fm.getLeading();
hmin = vmin = 0;
vvis = itemsInWindow(true);
vmax = Math.max(numItems - vvis, 0);
h = d.height - SCROLLBAR;
if (vmax != 0) {
w = d.width - SCROLLBAR;
hvis = w - ((2 * SPACE) + (2 * MARGIN));
hmax = Math.max(max - hvis, 0);
} else {
w = d.width;
hvis = w - ((2 * SPACE) + (2 * MARGIN));
hmax = Math.max(max - hvis, 0);
}
if (hmax == 0) {
h = d.height;
vvis = itemsInWindow(false);
vmax = Math.max(numItems - vvis, 0);
}
if (vmax == 0) {
w = d.width;
hvis = w - ((2 * SPACE) + (2 * MARGIN));
hmax = Math.max(max - hvis, 0);
}
hval = 0;
vval = 0;
/*
System.out.println("print List: "+d.width+"x"+d.height+" numItems="+numItems+
"max="+max+" vsb=("+vmin+".."+vmax+","+vval+","+vvis+
") hsb=("+hmin+".."+hmax+","+hval+","+hvis+")");
*/
g.setColor(bg);
g.fillRect(0, 0, w, h);
if (hmax != 0) {
int sbw = d.width - ((vmax == 0) ? 0 : SCROLLBAR);
g.fillRect(1, d.height - SCROLLBAR - 3, sbw - 1, SCROLLBAR - 3);
Graphics ng = g.create();
try {
ng.translate(0, d.height - (SCROLLBAR - 2));
drawScrollbar(ng, bg, SCROLLBAR - 2, sbw,
hmin, hmax, hval, hvis, true);
} finally {
ng.dispose();
}
}
if (vmax != 0) {
int sbh = d.height - ((hmax == 0) ? 0 : SCROLLBAR);
g.fillRect(d.width - SCROLLBAR - 3, 1, SCROLLBAR - 3, sbh - 1);
Graphics ng = g.create();
try {
ng.translate(d.width - (SCROLLBAR - 2), 0);
drawScrollbar(ng, bg, SCROLLBAR - 2, sbh,
vmin, vmax, vval, vvis, false);
} finally {
ng.dispose();
}
}
draw3DRect(g, bg, 0, 0, w - 1, h - 1, false);
if (numItems > 0) {
int n = itemsInWindow(hmax != 0);
int e = Math.min(numItems - 1, (vval + n) - 1);
paintItems(g, bg, fg, vval, e);
}
target.print(g);
}
int itemsInWindow(boolean scrollbarVisible) {
Dimension d = target.size();
int h;
if (scrollbarVisible) {
h = d.height - ((2 * MARGIN) + SCROLLBAR);
} else {
h = d.height - 2*MARGIN;
}
int i = fontHeight - fontLeading;
return h / (i + (2 * SPACE));
}
void paintItem(Graphics g, Color bg, Color fg, int index, boolean isSelected) {
List l = (List)target;
Dimension d = l.size();
int numItems = l.getItemCount();
Color shadow = bg.darker();
if ((index < vval) || (index >= (vval + itemsInWindow(hmax != 0)))) {
return;
}
int w = d.width - ((2 * MARGIN) + ((vmax != 0)? SCROLLBAR : 0));
int h = (fontHeight - fontLeading);
int htotal = h + (2 * SPACE);
int index2y = MARGIN + (index * htotal) + SPACE;
int y = index2y - (vval * htotal);
int x = MARGIN + SPACE;
Graphics ng = g.create();
try {
if (index > numItems - 1) {
ng.setColor(bg);
ng.fillRect(x - 2, y - 2, w, h + 4);
return;
}
if (isSelected) {
ng.setColor(shadow);
ng.fillRect(x - 1, y - 1, w - 2, h + 2);
} else {
ng.setColor(bg);
ng.fillRect(x - 1, y - 1, w - 2, h + 2);
}
ng.setColor(bg);
ng.drawRect(x - 2, y - 2, w - 1, h + 3);
ng.setColor(fg);
String str = (String)l.getItem(index);
ng.clipRect(x, y, w - (2 * SPACE), h);
ng.drawString(str, x - hval, y + fontAscent);
} finally {
ng.dispose();
}
}
void paintItems(Graphics g, Color bg, Color fg, int s, int e) {
for (int i = s ; i <= e ; i++) {
paintItem(g, bg, fg, i, false);
}
}
public boolean handlesWheelScrolling() {return true;}
public void handleEvent(AWTEvent e) {
if (e.getID() == MouseEvent.MOUSE_WHEEL) {
MouseWheelEvent mwe = (MouseWheelEvent)e;
nativeHandleMouseWheel(mwe.getScrollType(),
mwe.getScrollAmount(),
mwe.getWheelRotation());
}
else {
super.handleEvent(e);
}
}
native void nativeHandleMouseWheel(int scrollType,
int scrollAmount,
int wheelRotation);
}