1 /* 2 * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package sun.awt.windows; 26 27 import java.awt.*; 28 import java.awt.peer.*; 29 import java.awt.event.ActionEvent; 30 import java.awt.event.ItemEvent; 31 32 final class WListPeer extends WComponentPeer implements ListPeer { 33 34 @Override 35 public boolean isFocusable() { 36 return true; 37 } 38 39 // ListPeer implementation 40 41 @Override 42 public int[] getSelectedIndexes() { 43 List l = (List)target; 44 int len = l.getItemCount(); 45 int sel[] = new int[len]; 46 int nsel = 0; 47 for (int i = 0 ; i < len ; i++) { 48 if (isSelected(i)) { 49 sel[nsel++] = i; 50 } 51 } 52 int selected[] = new int[nsel]; 53 System.arraycopy(sel, 0, selected, 0, nsel); 54 return selected; 55 } 56 57 @Override 58 public void add(String item, int index) { 59 addItem(item, index); 60 } 61 62 @Override 63 public void removeAll() { 64 clear(); 65 } 66 67 @Override 68 public void setMultipleMode (boolean b) { 69 setMultipleSelections(b); 70 } 71 72 @Override 73 public Dimension getPreferredSize(int rows) { 74 if ( fm == null ) { 75 List li = (List)target; 76 fm = getFontMetrics( li.getFont() ); 77 } 78 Dimension d = getMinimumSize(rows); 79 d.width = Math.max(d.width, getMaxWidth() + 20); 80 return d; 81 } 82 83 @Override 84 public Dimension getMinimumSize(int rows) { 85 return new Dimension(20 + fm.stringWidth("0123456789abcde"), 86 (fm.getHeight() * rows) + 4); // include borders 87 } 88 89 private FontMetrics fm; 90 public void addItem(String item, int index) { 91 addItems(new String[] {item}, index, fm.stringWidth(item)); 92 } 93 native void addItems(String[] items, int index, int width); 94 95 @Override 96 public native void delItems(int start, int end); 97 public void clear() { 98 List l = (List)target; 99 delItems(0, l.getItemCount()); 100 } 101 @Override 102 public native void select(int index); 103 @Override 104 public native void deselect(int index); 105 @Override 106 public native void makeVisible(int index); 107 public native void setMultipleSelections(boolean v); 108 public native int getMaxWidth(); 109 // Toolkit & peer internals 110 111 WListPeer(List target) { 112 super(target); 113 } 114 115 @Override 116 native void create(WComponentPeer parent); 117 118 @Override 119 void initialize() { 120 List li = (List)target; 121 122 fm = getFontMetrics( li.getFont() ); 123 124 // Fixed 6336384: setFont should be done before addItems 125 Font f = li.getFont(); 126 if (f != null) { 127 setFont(f); 128 } 129 130 // add any items that were already inserted in the target. 131 int nitems = li.getItemCount(); 132 if (nitems > 0) { 133 String[] items = new String[nitems]; 134 int maxWidth = 0; 135 int width = 0; 136 for (int i = 0; i < nitems; i++) { 137 items[i] = li.getItem(i); 138 width = fm.stringWidth(items[i]); 139 if (width > maxWidth) { 140 maxWidth = width; 141 } 142 } 143 addItems(items, 0, maxWidth); 144 } 145 146 // set whether this list should allow multiple selections. 147 setMultipleSelections(li.isMultipleMode()); 148 149 // select the item if necessary. 150 int sel[] = li.getSelectedIndexes(); 151 for (int i = 0 ; i < sel.length ; i++) { 152 select(sel[i]); 153 } 154 155 // make the visible position visible. 156 // fix for 4676536 by kdm@sparc.spb.su 157 // we should call makeVisible() after we call select() 158 // because of a bug in Windows which is manifested by 159 // incorrect scrolling of the selected item if the list 160 // height is less than an item height of the list. 161 int index = li.getVisibleIndex(); 162 if (index < 0 && sel.length > 0) { 163 index = sel[0]; 164 } 165 if (index >= 0) { 166 makeVisible(index); 167 } 168 169 super.initialize(); 170 } 171 172 @Override 173 public boolean shouldClearRectBeforePaint() { 174 return false; 175 } 176 177 private native void updateMaxItemWidth(); 178 179 /*public*/ native boolean isSelected(int index); 180 181 // update the fontmetrics when the font changes 182 @Override 183 synchronized void _setFont(Font f) 184 { 185 super._setFont( f ); 186 fm = getFontMetrics( ((List)target).getFont() ); 187 updateMaxItemWidth(); 188 } 189 190 // native callbacks 191 192 void handleAction(final int index, final long when, final int modifiers) { 193 final List l = (List)target; 194 WToolkit.executeOnEventHandlerThread(l, new Runnable() { 195 @Override 196 public void run() { 197 l.select(index); 198 postEvent(new ActionEvent(target, ActionEvent.ACTION_PERFORMED, 199 l.getItem(index), when, modifiers)); 200 } 201 }); 202 } 203 204 void handleListChanged(final int index) { 205 final List l = (List)target; 206 WToolkit.executeOnEventHandlerThread(l, new Runnable() { 207 @Override 208 public void run() { 209 postEvent(new ItemEvent(l, ItemEvent.ITEM_STATE_CHANGED, 210 Integer.valueOf(index), 211 isSelected(index)? ItemEvent.SELECTED : 212 ItemEvent.DESELECTED)); 213 214 } 215 }); 216 } 217 }