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