Fix listbox & popumenu uicontrols tests.
[scilab.git] / scilab / modules / gui / src / java / org / scilab / modules / gui / bridge / popupmenu / SwingScilabPopupMenu.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) 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.popupmenu;
16
17 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_VALUE__;
18
19 import java.awt.event.ActionEvent;
20 import java.awt.event.ActionListener;
21
22 import javax.swing.JComboBox;
23
24 import org.scilab.modules.graphic_objects.graphicController.GraphicController;
25 import org.scilab.modules.gui.SwingViewWidget;
26 import org.scilab.modules.gui.SwingViewObject;
27 import org.scilab.modules.gui.events.callback.CommonCallBack;
28 import org.scilab.modules.gui.menubar.MenuBar;
29 import org.scilab.modules.gui.popupmenu.SimplePopupMenu;
30 import org.scilab.modules.gui.textbox.TextBox;
31 import org.scilab.modules.gui.toolbar.ToolBar;
32 import org.scilab.modules.gui.utils.Position;
33 import org.scilab.modules.gui.utils.PositionConverter;
34 import org.scilab.modules.gui.utils.ScilabRelief;
35 import org.scilab.modules.gui.utils.ScilabSwingUtilities;
36 import org.scilab.modules.gui.utils.Size;
37
38 /**
39  * Swing implementation for Scilab PopupMenu in GUIs
40  * @author Vincent COUVERT
41  * @author Marouane BEN JELLOUL
42  */
43 public class SwingScilabPopupMenu extends JComboBox implements SwingViewObject, SimplePopupMenu {
44
45     private static final long serialVersionUID = -4366581303317502544L;
46
47     private String uid;
48
49     private CommonCallBack callback;
50
51     /**
52      * Constructor
53      */
54     public SwingScilabPopupMenu() {
55         super();
56         /* Bug 3635 fixed: allow arrow keys to browse items */
57         putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
58         ActionListener actionListener = new ActionListener() {
59             public void actionPerformed(ActionEvent e) {
60                 Double[] scilabIndices = new Double[1];
61                 scilabIndices[0] = (double) getUserSelectedIndex();
62                 GraphicController.getController().setProperty(uid, __GO_UI_VALUE__, scilabIndices);
63                 if (callback != null) {
64                     callback.actionPerformed(null);
65                 }
66
67
68             }
69         };
70         addActionListener(actionListener);
71     }
72
73     /**
74      * Draws a swing Scilab tab
75      * @see org.scilab.modules.gui.uielement.UIElement#draw()
76      */
77     public void draw() {
78         this.setVisible(true);
79     }
80
81     /**
82      * Gets the dimensions (width and height) of a swing Scilab tab
83      * @return the dimensions of the tab
84      * @see org.scilab.modules.gui.uielement.UIElement#getDims()
85      */
86     public Size getDims() {
87         return new Size(getWidth(), getHeight());
88     }
89
90     /**
91      * Gets the position (X-coordinate and Y-coordinate) of a swing Scilab tab
92      * @return the position of the tab
93      * @see org.scilab.modules.gui.uielement.UIElement#getPosition()
94      */
95     public Position getPosition() {
96         return PositionConverter.javaToScilab(getLocation(), getSize(), getParent());
97     }
98
99     /**
100      * Sets the dimensions (width and height) of a swing Scilab tab
101      * @param newSize the dimensions we want to set to the tab
102      * @see org.scilab.modules.gui.uielement.UIElement#setDims(org.scilab.modules.gui.utils.Size)
103      */
104     public void setDims(Size newSize) {
105         setSize(newSize.getWidth(), newSize.getHeight());
106         doLayout(); /* Needed !! because PopupMenu is badly drawn else */
107     }
108
109     /**
110      * Sets the position (X-coordinate and Y-coordinate) of a swing Scilab tab
111      * @param newPosition the position we want to set to the tab
112      * @see org.scilab.modules.gui.uielement.UIElement#setPosition(org.scilab.modules.gui.utils.Position)
113      */
114     public void setPosition(Position newPosition) {
115         Position javaPosition = PositionConverter.scilabToJava(newPosition, getDims(), getParent());
116         setLocation(javaPosition.getX(), javaPosition.getY());
117     }
118
119     /**
120      * Add a callback to the PopupMenu
121      * @param callback the callback to set.
122      */
123     public void setCallback(CommonCallBack callback) {
124         this.callback = callback;
125     }
126
127     /**
128      * Setter for MenuBar
129      * @param menuBarToAdd the MenuBar associated to the Tab.
130      */
131     public void addMenuBar(MenuBar menuBarToAdd) {
132         /* Unimplemented for PopupMenus */
133         throw new UnsupportedOperationException();
134     }
135
136     /**
137      * Setter for ToolBar
138      * @param toolBarToAdd the ToolBar associated to the Tab.
139      */
140     public void addToolBar(ToolBar toolBarToAdd) {
141         /* Unimplemented for PopupMenus */
142         throw new UnsupportedOperationException();
143     }
144
145     /**
146      * Getter for MenuBar
147      * @return MenuBar: the MenuBar associated to the Tab.
148      */
149     public MenuBar getMenuBar() {
150         /* Unimplemented for PopupMenus */
151         throw new UnsupportedOperationException();
152     }
153
154     /**
155      * Getter for ToolBar
156      * @return ToolBar: the ToolBar associated to the Tab.
157      */
158     public ToolBar getToolBar() {
159         /* Unimplemented for PopupMenus */
160         throw new UnsupportedOperationException();
161     }
162
163     /**
164      * Get the text if the PopupMenu items
165      * @return the items
166      * @see org.scilab.modules.gui.widget.Widget#getText()
167      */
168     public String getText() {
169         /* Unimplemented for PopupMenus */
170         throw new UnsupportedOperationException();
171     }
172
173     /**
174      * Set the text of the PopupMenu items
175      * @param text the text of the items
176      * @see org.scilab.modules.gui.widget.Widget#setText(java.lang.String)
177      */
178     public void setText(String text) {
179         /* Unimplemented for PopupMenus */
180         throw new UnsupportedOperationException();
181     }
182
183     /**
184      * Set the horizontal alignment for the PopupMenu text
185      * @param alignment the value for the alignment (See ScilabAlignment.java)
186      */
187     public void setHorizontalAlignment(String alignment) {
188         // Nothing to do here
189     }
190
191     /**
192      * Set the vertical alignment for the PopupMenu text
193      * @param alignment the value for the alignment (See ScilabAlignment.java)
194      */
195     public void setVerticalAlignment(String alignment) {
196         // Nothing to do here
197     }
198
199     /**
200      * Set the selected index of the PopupMenu
201      * @param index the index of the item to be selected
202      */
203     public void setUserSelectedIndex(int index) {
204         /* Remove the listener to avoid the callback to be executed */
205         if (this.callback != null) {
206             removeActionListener(this.callback);
207         }
208
209         for (int i = 0; i < getItemCount(); i++) {
210             // Scilab indices in Value begin at 1 and Java indices begin at 0
211             if (i == (index - 1)) {
212                 getModel().setSelectedItem(getItemAt(i));
213             }
214         }
215
216         /* Put back the listener */
217         if (this.callback != null) {
218             addActionListener(this.callback);
219         }
220     }
221
222     /**
223      * Get the selected index of the PopupMenu
224      * @return the index of the item selected
225      */
226     public int getUserSelectedIndex() {
227         Object itemSelected = getModel().getSelectedItem();
228         for (int i = 0; i < getItemCount(); i++) {
229             if (itemSelected.equals(getItemAt(i))) {
230                 // Scilab indices in Value begin at 1 and Java indices begin at 0
231                 return i + 1;
232             }
233         }
234         return -1;
235     }
236
237     /**
238      * Get the text of all the PopupMenu items
239      * @return the text items
240      */
241     public String[] getAllItemsText() {
242         String[] retValue = new String[getItemCount()];
243         for (int i = 0; i < getItemCount(); i++) {
244             retValue[i] = getItemAt(i).toString();
245         }
246         return retValue;
247
248     }
249
250     /**
251      * Get the number of items in the PopupMenu
252      * @return the number of items
253      */
254     public int getNumberOfItems() {
255         return getItemCount();
256     }
257
258     /**
259      * Set the text of the PopupMenu items
260      * @param text the text of the items
261      */
262     public void setText(String[] text) {
263         /* Do we need to update the strings */
264         /* Test performed to avoid loops when the model is updated from here */
265         boolean updateNeeded = false;
266         String[] previousText = getAllItemsText();
267         if (previousText.length != text.length) {
268             updateNeeded = true;
269         } else {
270             for (int k = 0; k < text.length; k++) {
271                 if (!text[k].equals(previousText[k])) {
272                     updateNeeded = true;
273                     break;
274                 }
275             }
276         }
277         if (!updateNeeded) {
278             return;
279         }
280
281         /* Remove the listener to avoid the callback to be executed */
282         if (this.callback != null) {
283             removeActionListener(this.callback);
284         }
285
286         /* Clear previous items */
287         removeAllItems();
288
289         if (text.length == 1 & text[0].length() == 0) {
290             /* Clear the popup items */
291             return;
292         } else {
293             for (int i = 0; i < text.length; i++) {
294                 addItem(new SwingScilabPopupMenuItem(text[i]));
295             }
296         }
297
298         /* Remove the listener to avoid the callback to be executed */
299         if (this.callback != null) {
300             addActionListener(this.callback);
301         }
302
303     }
304
305     /**
306      * Set the Relief of the PopupMenu
307      * @param reliefType the type of the relief to set (See ScilabRelief.java)
308      */
309     public void setRelief(String reliefType) {
310         setBorder(ScilabRelief.getBorderFromRelief(reliefType));
311     }
312
313     /**
314      * Destroy the PopupMenu
315      */
316     public void destroy() {
317         ScilabSwingUtilities.removeFromParent(this);
318     }
319
320     /**
321      * Setter for InfoBar
322      * @param infoBarToAdd the InfoBar associated to the PopupMenu.
323      */
324     public void addInfoBar(TextBox infoBarToAdd) {
325         /* Unimplemented for PopupMenus */
326         throw new UnsupportedOperationException();
327     }
328
329     /**
330      * Getter for InfoBar
331      * @return the InfoBar associated to the PopupMenu.
332      */
333     public TextBox getInfoBar() {
334         /* Unimplemented for PopupMenus */
335         throw new UnsupportedOperationException();
336     }
337
338     /**
339      * Class created as a workaround for bug: http://bugzilla.scilab.org/show_bug.cgi?id=7898
340      * This bug is a Java bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4133743
341      *
342      * This workaround has been proposed by a user on Java bug tracker.
343      *
344      * The toString method will be used to display the elements, but because the class inherits its
345      * equals method from Object instead of String, none of the elements are considered duplicates.
346      *
347      */
348     private class SwingScilabPopupMenuItem {
349
350         private String textOfItem;
351
352         /**
353          * Constructor
354          * @param text the text displayed in the item
355          */
356         public SwingScilabPopupMenuItem(String text) {
357             textOfItem = text;
358         }
359
360         /**
361          * Overload Object toString() method
362          * @return the item converted to String
363          * @see java.lang.Object#toString()
364          */
365         @Override
366         public String toString() {
367             return textOfItem;
368         }
369     }
370
371     /**
372      * Set the UID
373      * @param id the UID
374      */
375     public void setId(String id) {
376         uid = id;
377     }
378
379     /**
380      * Get the UID
381      * @return the UID
382      */
383     public String getId() {
384         return uid;
385     }
386
387     /**
388      * Generic update method
389      * @param property property name
390      * @param value property value
391      */
392     public void update(int property, Object value) {
393         SwingViewWidget.update(this, property, value);
394     }
395 }
396
397