Add a listener to update the listboxtop property correctly.
[scilab.git] / scilab / modules / gui / src / java / org / scilab / modules / gui / bridge / listbox / SwingScilabListBox.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2007 - INRIA - Vincent Couvert
4  * Copyright (C) 2007 - INRIA - Marouane BEN JELLOUL
5  * Copyright (C) 2010-2011 - DIGITEO - Vincent COUVERT
6  *
7  * This file must be used under the terms of the CeCILL.
8  * This source file is licensed as described in the file COPYING, which
9  * you should have received as part of this distribution.  The terms
10  * are also available at
11  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
12  *
13  */
14
15 package org.scilab.modules.gui.bridge.listbox;
16
17 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_LISTBOXTOP__;
18 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_VALUE__;
19
20 import java.awt.Color;
21 import java.awt.Font;
22 import java.awt.event.AdjustmentEvent;
23 import java.awt.event.AdjustmentListener;
24 import java.awt.event.MouseEvent;
25 import java.awt.event.MouseListener;
26
27 import javax.swing.DefaultListModel;
28 import javax.swing.JList;
29 import javax.swing.JScrollPane;
30 import javax.swing.ListSelectionModel;
31
32 import org.scilab.modules.graphic_objects.graphicController.GraphicController;
33 import org.scilab.modules.gui.SwingViewWidget;
34 import org.scilab.modules.gui.SwingViewObject;
35 import org.scilab.modules.gui.events.callback.CommonCallBack;
36 import org.scilab.modules.gui.listbox.SimpleListBox;
37 import org.scilab.modules.gui.menubar.MenuBar;
38 import org.scilab.modules.gui.textbox.TextBox;
39 import org.scilab.modules.gui.toolbar.ToolBar;
40 import org.scilab.modules.gui.utils.Position;
41 import org.scilab.modules.gui.utils.PositionConverter;
42 import org.scilab.modules.gui.utils.ScilabRelief;
43 import org.scilab.modules.gui.utils.ScilabSwingUtilities;
44 import org.scilab.modules.gui.utils.Size;
45
46 /**
47  * Swing implementation for Scilab ListBox in GUIs
48  * @author Vincent COUVERT
49  * @author Marouane BEN JELLOUL
50  */
51 public class SwingScilabListBox extends JScrollPane implements SwingViewObject, SimpleListBox {
52
53     private static final long serialVersionUID = 3507396207331058895L;
54
55     private String uid;
56
57     private CommonCallBack callback;
58
59     private MouseListener mouseListener;
60
61     private AdjustmentListener adjustmentListener;
62
63     /**
64      * the JList we use
65      */
66     private JList list;
67
68     /**
69      * Constructor
70      */
71     public SwingScilabListBox() {
72         super();
73         getViewport().add(getList());
74
75         mouseListener = new MouseListener() {
76             public void mouseClicked(MouseEvent e) {
77                 // Scilab indices in Value begin at 1 and Java indices begin at 0
78                 int[] javaIndices = getList().getSelectedIndices().clone();
79                 Double[] scilabIndices = new Double[javaIndices.length];
80                 for (int i = 0; i < getList().getSelectedIndices().length; i++) {
81                     scilabIndices[i] = (double) javaIndices[i] + 1;
82                 }
83                 GraphicController.getController().setProperty(uid, __GO_UI_VALUE__, scilabIndices);
84                 if (e.getButton() == MouseEvent.BUTTON1 && callback != null) {
85                     callback.actionPerformed(null);
86                 }
87             }
88             public void mouseEntered(MouseEvent arg0) { }
89             public void mouseExited(MouseEvent arg0) { }
90             public void mousePressed(MouseEvent arg0) { }
91             public void mouseReleased(MouseEvent arg0) { }
92         };
93         getList().addMouseListener(mouseListener);
94         adjustmentListener = new AdjustmentListener() {
95             public void adjustmentValueChanged(AdjustmentEvent arg0) {
96                 int listboxtopValue = getList().getUI().locationToIndex(getList(), getViewport().getViewPosition()) + 1;
97                 Integer[] modelValue = new Integer[1];
98                 modelValue[0] = listboxtopValue;
99                 GraphicController.getController().setProperty(uid, __GO_UI_LISTBOXTOP__, modelValue);
100             }
101         };
102         getVerticalScrollBar().addAdjustmentListener(adjustmentListener);
103     }
104
105     /**
106      * To get the Background color of the element.
107      * @return color the Color
108      */
109     public Color getBackground() {
110         return getList().getBackground();
111     }
112
113     /**
114      * To get the Font of the element.
115      * @return font the Font
116      */
117     public Font getFont() {
118         return getList().getFont();
119     }
120
121     /**
122      * To get the Foreground color of the element.
123      * @return color the Color
124      */
125     public Color getForeground() {
126         return getList().getForeground();
127     }
128
129     /**
130      * To set the Background color of the element.
131      * @param color the Color
132      */
133     public void setBackground(Color color) {
134         getList().setBackground(color);
135     }
136
137     /**
138      * To set the Font of the element.
139      * @param font the Font
140      */
141     public void setFont(Font font) {
142         getList().setFont(font);
143     }
144
145     /**
146      * To set the Foreground color of the element.
147      * @param color the Color
148      */
149     public void setForeground(Color color) {
150         getList().setForeground(color);
151     }
152
153     /**
154      * Draws a swing Scilab tab
155      * @see org.scilab.modules.gui.uielement.UIElement#draw()
156      */
157     public void draw() {
158         this.setVisible(true);
159         this.doLayout();
160     }
161
162     /**
163      * Gets the dimensions (width and height) of a swing Scilab tab
164      * @return the dimensions of the tab
165      * @see org.scilab.modules.gui.uielement.UIElement#getDims()
166      */
167     public Size getDims() {
168         return new Size(getWidth(), getHeight());
169     }
170
171     /**
172      * Gets the position (X-coordinate and Y-coordinate) of a swing Scilab tab
173      * @return the position of the tab
174      * @see org.scilab.modules.gui.uielement.UIElement#getPosition()
175      */
176     public Position getPosition() {
177         return PositionConverter.javaToScilab(getLocation(), getSize(), getParent());
178     }
179
180     /**
181      * Sets the dimensions (width and height) of a swing Scilab tab
182      * @param newSize the dimensions we want to set to the tab
183      * @see org.scilab.modules.gui.uielement.UIElement#setDims(org.scilab.modules.gui.utils.Size)
184      */
185     public void setDims(Size newSize) {
186         setSize(newSize.getWidth(), newSize.getHeight());
187     }
188
189     /**
190      * Sets the position (X-coordinate and Y-coordinate) of a swing Scilab tab
191      * @param newPosition the position we want to set to the tab
192      * @see org.scilab.modules.gui.uielement.UIElement#setPosition(org.scilab.modules.gui.utils.Position)
193      */
194     public void setPosition(Position newPosition) {
195         Position javaPosition = PositionConverter.scilabToJava(newPosition, getDims(), getParent());
196         setLocation(javaPosition.getX(), javaPosition.getY());
197     }
198
199     /**
200      * Sets the visibility status of an UIElement
201      * @param newVisibleState the visibility status we want to set for the UIElement
202      *                      (true if the UIElement is visible, false if not)
203      */
204     public void setVisible(boolean newVisibleState) {
205         super.setVisible(newVisibleState);
206         list.setVisible(newVisibleState);
207     }
208
209     /**
210      * Sets the enable status of an UIElement
211      * @param newEnableState the enable status we want to set for the UIElement
212      *                      (true if the UIElement is enabled, false if not)
213      */
214     public void setEnabled(boolean newEnableState) {
215         if (newEnableState != super.isEnabled()) {
216             super.setEnabled(newEnableState);
217             getList().setEnabled(newEnableState);
218             if (newEnableState) {
219                 if (mouseListener != null) {
220                     getList().addMouseListener(mouseListener);
221                 }
222             } else {
223                 if (mouseListener != null) {
224                     getList().removeMouseListener(mouseListener);
225                 }
226             }
227         }
228     }
229
230     /**
231      * Add a callback to the CheckBox
232      * @param cb the callback to set.
233      */
234     public void setCallback(CommonCallBack cb) {
235         this.callback = cb;
236     }
237
238     /**
239      * Setter for MenuBar
240      * @param menuBarToAdd the MenuBar associated to the Tab.
241      */
242     public void addMenuBar(MenuBar menuBarToAdd) {
243         /* Unimplemented for ListBoxes */
244         throw new UnsupportedOperationException();
245     }
246
247     /**
248      * Setter for ToolBar
249      * @param toolBarToAdd the ToolBar associated to the Tab.
250      */
251     public void addToolBar(ToolBar toolBarToAdd) {
252         /* Unimplemented for ListBoxes */
253         throw new UnsupportedOperationException();
254     }
255
256     /**
257      * Getter for MenuBar
258      * @return MenuBar: the MenuBar associated to the Tab.
259      */
260     public MenuBar getMenuBar() {
261         /* Unimplemented for ListBoxes */
262         throw new UnsupportedOperationException();
263     }
264
265     /**
266      * Getter for ToolBar
267      * @return ToolBar: the ToolBar associated to the Tab.
268      */
269     public ToolBar getToolBar() {
270         /* Unimplemented for ListBoxes */
271         throw new UnsupportedOperationException();
272     }
273
274     /**
275      * Get the first item text
276      * @return the items
277      * @see org.scilab.modules.gui.widget.Widget#getText()
278      */
279     public String getText() {
280         /* Unimplemented for ListBoxes */
281         throw new UnsupportedOperationException();
282     }
283
284     /**
285      * Get the text of all the list items
286      * @return the items
287      * @see org.scilab.modules.gui.listbox.ListBox#getAllItemsText()
288      */
289     public String[] getAllItemsText() {
290         String[] retValue = new String[getList().getModel().getSize()];
291         for (int i = 0; i < getList().getModel().getSize(); i++) {
292             retValue[i] = (String) getList().getModel().getElementAt(i);
293         }
294         return retValue;
295     }
296
297     /**
298      * Get the number of items in the list
299      * @return the number of items
300      * @see org.scilab.modules.gui.listbox.ListBox#getNumberOfItems()
301      */
302     public int getNumberOfItems() {
303         return getList().getModel().getSize();
304     }
305
306     /**
307      * Set the text of the list items
308      * @param text the text of the items
309      * @see org.scilab.modules.gui.widget.Widget#setText(java.lang.String)
310      */
311     public void setText(String text) {
312         DefaultListModel model = new DefaultListModel();
313         model.addElement(text);
314         getList().setModel(model);
315         revalidate();
316     }
317
318     /**
319      * Set the text of the list items
320      * @param text the text of the items
321      * @see org.scilab.modules.gui.widget.Widget#setText(java.lang.String)
322      */
323     public void setText(String[] text) {
324         /* Do we need to update the strings */
325         /* Test performed to avoid loops when the model is updated from here */
326         boolean updateNeeded = false;
327         String[] previousText = getAllItemsText();
328         if (previousText.length != text.length) {
329             updateNeeded = true;
330         } else {
331             for (int k = 0; k < text.length; k++) {
332                 if (text[k].compareTo(previousText[k]) != 0) {
333                     updateNeeded = true;
334                     break;
335                 }
336             }
337         }
338         if (!updateNeeded) {
339             return;
340         }
341
342         DefaultListModel model = new DefaultListModel();
343         for (int i = 0; i < text.length; i++) {
344             model.addElement(text[i]);
345         }
346         getList().setModel(model);
347         revalidate();
348     }
349
350     /**
351      * Set the horizontal alignment for the ListBox text
352      * @param alignment the value for the alignment (See ScilabAlignment.java)
353      */
354     public void setHorizontalAlignment(String alignment) {
355         // Nothing to do here
356     }
357
358     /**
359      * Set the vertical alignment for the ListBox text
360      * @param alignment the value for the alignment (See ScilabAlignment.java)
361      */
362     public void setVerticalAlignment(String alignment) {
363         // Nothing to do here
364     }
365
366     /**
367      * Set if more than one item can be selected in a ListBox
368      * @param status true if multiple selection is enabled
369      */
370     public void setMultipleSelectionEnabled(boolean status) {
371         if (status) {
372             getList().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
373         } else {
374             getList().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
375         }
376     }
377
378     /**
379      * Set the selected indices of the ListBox
380      * @param indices the indices of the items to be selected
381      */
382     public void setSelectedIndices(int[] indices) {
383         // Scilab indices in Value begin at 1 and Java indices begin at 0
384         int[] javaIndices = indices.clone();
385         for (int i = 0; i < javaIndices.length; i++) {
386             javaIndices[i] = javaIndices[i] - 1;
387         }
388
389         /* Remove the listener to avoid the callback to be executed */
390         if (mouseListener != null) {
391             getList().removeMouseListener(mouseListener);
392         }
393
394         getList().setSelectedIndices(javaIndices);
395
396         /* Put back the listener */
397         if (mouseListener != null) {
398             getList().addMouseListener(mouseListener);
399         }
400     }
401
402     /**
403      * Get the selected indices of the ListBox
404      * @return the indices of the items selected
405      */
406     public int[] getSelectedIndices() {
407         // Scilab indices in Value begin at 1 and Java indices begin at 0
408         int[] javaIndices = getList().getSelectedIndices().clone();
409         int[] scilabIndices = javaIndices.clone();
410         for (int i = 0; i < getList().getSelectedIndices().length; i++) {
411             scilabIndices[i] = scilabIndices[i] + 1;
412         }
413         return scilabIndices;
414     }
415
416     /**
417      * Get the number of items selected in the ListBox
418      * @return the number of items selected
419      */
420     public int getSelectionSize() {
421         return getList().getSelectedIndices().length;
422     }
423
424     /**
425      * Get or create the list component
426      * @return the list
427      */
428     private JList getList() {
429         if (list == null) {
430             list = new JList();
431             list.setLayoutOrientation(JList.VERTICAL);
432             list.setModel(new DefaultListModel());
433         }
434         return list;
435     }
436
437     /**
438      * Set the Relief of the ListBox
439      * @param reliefType the type of the relief to set (See ScilabRelief.java)
440      */
441     public void setRelief(String reliefType) {
442         setBorder(ScilabRelief.getBorderFromRelief(reliefType));
443     }
444
445     /**
446      * Destroy the ListBox
447      */
448     public void destroy() {
449         ScilabSwingUtilities.removeFromParent(this);
450     }
451
452     /**
453      * Setter for InfoBar
454      * @param infoBarToAdd the InfoBar associated to the ListBox.
455      */
456     public void addInfoBar(TextBox infoBarToAdd) {
457         /* Unimplemented for ListBoxes */
458         throw new UnsupportedOperationException();
459     }
460
461     /**
462      * Getter for InfoBar
463      * @return the InfoBar associated to the ListBox.
464      */
465     public TextBox getInfoBar() {
466         /* Unimplemented for ListBoxes */
467         throw new UnsupportedOperationException();
468     }
469
470     /**
471      * Adjusts the view so that the element given by index is displayed at the top of the ListBox.
472      * @param index the index of the element to be displayed at the top of the ListBox.
473      */
474     public void setListBoxTop(int index) {
475         getVerticalScrollBar().removeAdjustmentListener(adjustmentListener);
476         if (index > 0) {
477             getViewport().setViewPosition(getList().getUI().indexToLocation(getList(), index - 1));
478             doLayout();
479         }
480         getVerticalScrollBar().addAdjustmentListener(adjustmentListener);
481     }
482
483     /**
484      * Gets the index of the element displayed at the top of the ListBox
485      * @return the index of the element displayed at the top of the ListBox
486      */
487     public int getListBoxTop() {
488         return getList().getUI().locationToIndex(getList(), getViewport().getViewPosition()) + 1;
489     }
490
491     /**
492      * Set the UID
493      * @param id the UID
494      */
495     public void setId(String id) {
496         uid = id;
497     }
498
499     /**
500      * Get the UID
501      * @return the UID
502      */
503     public String getId() {
504         return uid;
505     }
506
507     /**
508      * Generic update method
509      * @param property property name
510      * @param value property value
511      */
512     public void update(int property, Object value) {
513         SwingViewWidget.update(this, property, value);
514     }
515 }