| /* |
| * 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); |
| } |