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