001    /*
002      Copyright (C) 2001-2003 Renaud Pawlak <renaud@aopsys.com>>, 
003                              Laurent Martelli <laurent@aopsys.com>
004      
005      This program is free software; you can redistribute it and/or modify
006      it under the terms of the GNU Lesser General Public License as
007      published by the Free Software Foundation; either version 2 of the
008      License, or (at your option) any later version.
009    
010      This program is distributed in the hope that it will be useful,
011      but WITHOUT ANY WARRANTY; without even the implied warranty of
012      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013      GNU Lesser General Public License for more details.
014    
015      You should have received a copy of the GNU Lesser General Public License
016      along with this program; if not, write to the Free Software
017      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
018    
019    package org.objectweb.jac.aspects.gui.swing;
020    
021    import java.awt.Component;
022    import java.awt.Container;
023    import java.awt.event.ActionEvent;
024    import java.awt.event.ActionListener;
025    import java.util.Arrays;
026    import java.util.HashMap;
027    import javax.swing.AbstractButton;
028    import javax.swing.BoxLayout;
029    import javax.swing.JComponent;
030    import javax.swing.JMenuBar;
031    import javax.swing.JMenuItem;
032    import org.apache.log4j.Logger;
033    import org.objectweb.jac.aspects.gui.Border;
034    import org.objectweb.jac.aspects.gui.Callback;
035    import org.objectweb.jac.aspects.gui.DisplayContext;
036    import org.objectweb.jac.aspects.gui.EventHandler;
037    import org.objectweb.jac.aspects.gui.GuiAC;
038    import org.objectweb.jac.aspects.gui.InvokeEvent;
039    import org.objectweb.jac.aspects.gui.Menu;
040    import org.objectweb.jac.aspects.gui.MenuView;
041    import org.objectweb.jac.aspects.gui.ResourceManager;
042    import org.objectweb.jac.aspects.gui.View;
043    import org.objectweb.jac.aspects.gui.ViewFactory;
044    import org.objectweb.jac.aspects.gui.ViewIdentity;
045    import org.objectweb.jac.aspects.session.SessionAC;
046    import org.objectweb.jac.core.Collaboration;
047    import org.objectweb.jac.core.rtti.FieldItem;
048    import org.objectweb.jac.core.rtti.MethodItem;
049    import org.objectweb.jac.util.Strings;
050    
051    public class MenuBar extends JMenuBar implements MenuView, ActionListener {
052        static Logger logger = Logger.getLogger("gui.menu");
053        static Logger loggerContext = Logger.getLogger("display-context");
054        static Logger loggerEvents = Logger.getLogger("gui.events");
055    
056        String label;
057        DisplayContext context;
058        int width;
059        int height;
060        ViewFactory factory;
061    
062        Object[] parameters;
063        String type;
064    
065        // label -> AbstractMethodItem
066        HashMap actions = new HashMap();
067    
068    
069        // style used to change display (css for web)
070        String style;
071    
072        public void setStyle(String style) {
073            this.style = style;
074        }
075    
076        public String getStyle() {
077            return style;
078        }
079    
080        Border viewBorder;
081       
082        /**
083         * Get the value of viewBorder.
084         * @return value of viewBorder.
085         */
086        public Border getViewBorder() {
087            return viewBorder;
088        }
089       
090        /**
091         * Set the value of viewBorder.
092         * @param v  Value to assign to viewBorder.
093         */
094        public void setViewBorder(Border  v) {
095            this.viewBorder = v;
096        }
097       
098        public MenuBar(ViewFactory factory, DisplayContext context) {
099            logger.debug("new MenuBar");
100            this.factory = factory;
101            this.context = context;      
102        }
103    
104        public MenuBar() {
105            logger.debug("new MenuBar");
106        }
107    
108        // View interface
109    
110        String description;
111       
112        /**
113         * Get the value of description.
114         * @return value of description.
115         */
116        public String getDescription() {
117            return description;
118        }
119       
120        /**
121         * Set the value of description.
122         * @param v  Value to assign to description.
123         */
124        public void setDescription(String  v) {
125            this.description = v;
126        }
127       
128        View parentView;
129       
130        /**
131         * Get the value of parentView.
132         * @return value of parentView.
133         */
134        public View getParentView() {
135            return parentView;
136        }
137       
138        /**
139         * Set the value of parentView.
140         * @param v  Value to assign to parentView.
141         */
142        public void setParentView(View  v) {
143            this.parentView = v;
144        }
145    
146        public View getRootView() {
147            if (parentView==null)
148                return this;
149            return parentView.getRootView();
150        }
151    
152        public boolean isDescendantOf(View ancestor) {
153            if (this==ancestor)
154                return true;
155            else if (parentView==null)
156                return false;
157            else
158                return parentView.isDescendantOf(ancestor);
159        }
160    
161        MethodItem message;
162       
163        /**
164         * Get the value of message.
165         * @return value of message.
166         */
167        public MethodItem getMessage() {
168            return message;
169        }
170       
171        /**
172         * Set the value of message.
173         * @param v  Value to assign to message.
174         */
175        public void setMessage(MethodItem  v) {
176            this.message = v;
177        }
178    
179        public void setContext(DisplayContext context) {
180            loggerContext.debug("setContext on "+this);
181            this.context = context;
182        }
183    
184        public DisplayContext getContext() {
185            return context;
186        }
187    
188        public void setFactory(ViewFactory factory) {
189            this.factory = factory;
190        }
191    
192        public ViewFactory getFactory() {
193            return factory;
194        }
195    
196        public void setLabel(String label) {
197            this.label = label;
198        }
199    
200        public String getLabel() {
201            return label;
202        }
203    
204        public void setWidth(int width) {
205            this.width = width;
206        }
207    
208        public void setHeight(int height) {
209            this.height = height;
210        }
211    
212        public void setType(String type) {
213            this.type = type;
214        }
215    
216        public String getType() {
217            return type;
218        }
219    
220        public void setParameters(Object[] parameters) {
221            this.parameters = parameters;
222        }
223       
224        public Object[] getParameters() {
225            return parameters;
226        }
227    
228    
229        public void close(boolean validate) {
230            closed = true;
231        }
232    
233        boolean closed = false;
234    
235        public boolean isClosed() {
236            return closed;
237        }
238    
239        public void setFocus(FieldItem field, Object option) {
240        }
241    
242    
243        public boolean equalsView(ViewIdentity view) {
244            return 
245                ( ( type!=null && 
246                    type.equals(view.getType()) )
247                  || (type==null && view.getType()==null ) )
248                && ( ( parameters!=null && 
249                       Arrays.equals(parameters,view.getParameters()) ) 
250                     || (parameters==null && view.getParameters()==null) );
251        }
252    
253        public boolean equalsView(String type, Object[] parameters) {
254            return this.type.equals(type)
255                && Arrays.equals(this.parameters,parameters);
256        }
257    
258        // MenuView interface
259    
260        public void addSubMenu(String label, String icon, MenuView submenu) {
261            ((AbstractButton)submenu).setText(label);
262            ((AbstractButton)submenu).setMnemonic(getMnemonic(this,label));
263            add((JComponent)submenu);
264        }
265    
266        public void addAction(String label, String icon, Callback callback) {
267            JMenuItem item = new JMenuItem(label,ResourceManager.getIcon(icon));
268            item.setActionCommand(label);
269            item.addActionListener(this);
270            item.setMnemonic(getMnemonic(this,label));
271            actions.put(label,callback);
272            add(item);
273        }
274    
275        /**
276         * Returns a mnemonic (keyboard shortcut) not already used
277         *
278         * @param container check for used mnemonic in this container
279         * @param label the label to get a mnemonic for
280         * @return a mnemonic for the label, 0 if none could be
281         * computed. The mnemonic is a character contained in the label
282         */
283        public static char getMnemonic(Container container, String label) {
284            logger.debug("getMnemonic for \""+label+"\" in "+Strings.hex(container));
285            StringBuffer usedMnemonics = new StringBuffer();
286            for (int i=0; i<container.getComponentCount(); i++) {
287                Component component = container.getComponent(i);
288                if (component instanceof AbstractButton) {
289                    AbstractButton button = (AbstractButton)component;
290                    logger.debug("  Mnemonic of "+Strings.hex(component)+
291                                 ": "+(char)button.getMnemonic());
292                    if (button.getMnemonic()!=0)
293                        usedMnemonics.append(Character.toLowerCase((char)button.getMnemonic()));
294                } else {
295                    logger.debug("  Skipping "+Strings.hex(component));
296                }
297            }
298            logger.debug("  usedMnemonics="+usedMnemonics);
299            for (int i=0; i<label.length(); i++) {
300                char c = Character.toLowerCase(label.charAt(i));
301                if (usedMnemonics.indexOf(""+c)==-1) {
302                    logger.debug("  -> "+c);
303                    return label.charAt(i);
304                }
305            }
306    
307            return 0;
308        }
309       
310        String position = Menu.TOP;   
311        /**
312         * Get the value of position.
313         * @return value of position.
314         */
315        public String getPosition() {
316            return position;
317        }
318    
319        /**
320         * Set the value of position.
321         * @param v Value to assign to position. If null, use the default
322         * position.
323         */
324        public void setPosition(String  v) {
325            logger.debug("setPosition("+v+")");
326            this.position = v;
327            if (position==null)
328                position = Menu.TOP;
329            if (position.equals(Menu.TOP)||position.equals(Menu.BOTTOM)) {
330                setLayout(new BoxLayout(this,BoxLayout.X_AXIS));
331            } else {
332                //getLayout(
333                setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
334            }      
335        }
336    
337        public void addSeparator() {
338        }
339    
340        public String toString() {
341            return Integer.toString(hashCode());
342        }
343    
344        // implementation of java.awt.event.ActionListener interface
345    
346        public void actionPerformed(ActionEvent event)
347        {
348            loggerEvents.debug("MenuBar.actionPerformed("+event.getActionCommand()+")");
349            Collaboration.get().addAttribute(
350                SessionAC.SESSION_ID, GuiAC.getLocalSessionID());
351            Callback callback = (Callback)actions.get(event.getActionCommand());
352            EventHandler.get().onInvoke(
353                context,
354                new InvokeEvent(this,null,callback.getMethod(),callback.getParameters()),
355                true,
356                null,null);
357        }
358    
359    }
360