1 /*
   2  * Copyright (c) 1996, 2014, 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     @SuppressWarnings("deprecation")
  43     public int[] getSelectedIndexes() {
  44         List l = (List)target;
  45         int len = l.countItems();
  46         int sel[] = new int[len];
  47         int nsel = 0;
  48         for (int i = 0 ; i < len ; i++) {
  49             if (isSelected(i)) {
  50                 sel[nsel++] = i;
  51             }
  52         }
  53         int selected[] = new int[nsel];
  54         System.arraycopy(sel, 0, selected, 0, nsel);
  55         return selected;
  56     }
  57 
  58     /* New method name for 1.1 */
  59     @Override
  60     public void add(String item, int index) {
  61         addItem(item, index);
  62     }
  63 
  64     /* New method name for 1.1 */
  65     @Override
  66     public void removeAll() {
  67         clear();
  68     }
  69 
  70     /* New method name for 1.1 */
  71     @Override
  72     public void setMultipleMode (boolean b) {
  73         setMultipleSelections(b);
  74     }
  75 
  76     /* New method name for 1.1 */
  77     @Override
  78     public Dimension getPreferredSize(int rows) {
  79         return preferredSize(rows);
  80     }
  81 
  82     /* New method name for 1.1 */
  83     @Override
  84     public Dimension getMinimumSize(int rows) {
  85         return minimumSize(rows);
  86     }
  87 
  88     private FontMetrics   fm;
  89     public void addItem(String item, int index) {
  90         addItems(new String[] {item}, index, fm.stringWidth(item));
  91     }
  92     native void addItems(String[] items, int index, int width);
  93 
  94     @Override
  95     public native void delItems(int start, int end);
  96     @SuppressWarnings("deprecation")
  97     public void clear() {
  98         List l = (List)target;
  99         delItems(0, l.countItems());
 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 
 110     public Dimension preferredSize(int v) {
 111         if ( fm == null ) {
 112             List li = (List)target;
 113             fm = getFontMetrics( li.getFont() );
 114         }
 115         Dimension d = minimumSize(v);
 116         d.width = Math.max(d.width, getMaxWidth() + 20);
 117         return d;
 118     }
 119     public Dimension minimumSize(int v) {
 120         return new Dimension(20 + fm.stringWidth("0123456789abcde"),
 121                              (fm.getHeight() * v) + 4); // include borders
 122     }
 123 
 124     // Toolkit & peer internals
 125 
 126     WListPeer(List target) {
 127         super(target);
 128     }
 129 
 130     @Override
 131     native void create(WComponentPeer parent);
 132 
 133     @Override
 134     @SuppressWarnings("deprecation")
 135     void initialize() {
 136         List li = (List)target;
 137 
 138         fm = getFontMetrics( li.getFont() );
 139 
 140         // Fixed 6336384: setFont should be done before addItems
 141         Font  f = li.getFont();
 142         if (f != null) {
 143             setFont(f);
 144         }
 145 
 146         // add any items that were already inserted in the target.
 147         int  nitems = li.countItems();
 148         if (nitems > 0) {
 149             String[] items = new String[nitems];
 150             int maxWidth = 0;
 151             int width = 0;
 152             for (int i = 0; i < nitems; i++) {
 153                 items[i] = li.getItem(i);
 154                 width = fm.stringWidth(items[i]);
 155                 if (width > maxWidth) {
 156                     maxWidth = width;
 157                 }
 158             }
 159             addItems(items, 0, maxWidth);
 160         }
 161 
 162         // set whether this list should allow multiple selections.
 163         setMultipleSelections(li.allowsMultipleSelections());
 164 
 165         // select the item if necessary.
 166         int sel[] = li.getSelectedIndexes();
 167         for (int i = 0 ; i < sel.length ; i++) {
 168             select(sel[i]);
 169         }
 170 
 171         // make the visible position visible.
 172         // fix for 4676536 by kdm@sparc.spb.su
 173         // we should call makeVisible() after we call select()
 174         // because of a bug in Windows which is manifested by
 175         // incorrect scrolling of the selected item if the list
 176         // height is less than an item height of the list.
 177         int index = li.getVisibleIndex();
 178         if (index < 0 && sel.length > 0) {
 179             index = sel[0];
 180         }
 181         if (index >= 0) {
 182             makeVisible(index);
 183         }
 184 
 185         super.initialize();
 186     }
 187 
 188     @Override
 189     public boolean shouldClearRectBeforePaint() {
 190         return false;
 191     }
 192 
 193     private native void updateMaxItemWidth();
 194 
 195     /*public*/ native boolean isSelected(int index);
 196 
 197     // update the fontmetrics when the font changes
 198     @Override
 199     synchronized void _setFont(Font f)
 200     {
 201         super._setFont( f );
 202             fm = getFontMetrics( ((List)target).getFont() );
 203         updateMaxItemWidth();
 204     }
 205 
 206     // native callbacks
 207 
 208     void handleAction(final int index, final long when, final int modifiers) {
 209         final List l = (List)target;
 210         WToolkit.executeOnEventHandlerThread(l, new Runnable() {
 211             @Override
 212             public void run() {
 213                 l.select(index);
 214                 postEvent(new ActionEvent(target, ActionEvent.ACTION_PERFORMED,
 215                                           l.getItem(index), when, modifiers));
 216             }
 217         });
 218     }
 219 
 220     void handleListChanged(final int index) {
 221         final List l = (List)target;
 222         WToolkit.executeOnEventHandlerThread(l, new Runnable() {
 223             @Override
 224             public void run() {
 225                 postEvent(new ItemEvent(l, ItemEvent.ITEM_STATE_CHANGED,
 226                                 Integer.valueOf(index),
 227                                 isSelected(index)? ItemEvent.SELECTED :
 228                                                    ItemEvent.DESELECTED));
 229 
 230             }
 231         });
 232     }
 233 }