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.BorderLayout; 022 import java.awt.Component; 023 import java.awt.Container; 024 import java.awt.Dimension; 025 import java.awt.Rectangle; 026 import java.awt.Toolkit; 027 import java.awt.event.ActionEvent; 028 import java.awt.event.ActionListener; 029 import java.awt.event.ContainerEvent; 030 import java.awt.event.ContainerListener; 031 import java.awt.event.KeyEvent; 032 import java.awt.event.KeyListener; 033 import java.awt.event.WindowAdapter; 034 import java.awt.event.WindowEvent; 035 import java.util.Arrays; 036 import java.util.Map; 037 import javax.swing.BorderFactory; 038 import javax.swing.JButton; 039 import javax.swing.JDialog; 040 import javax.swing.JEditorPane; 041 import javax.swing.JPanel; 042 import org.apache.log4j.Logger; 043 import org.objectweb.jac.aspects.gui.*; 044 import org.objectweb.jac.core.Collaboration; 045 import org.objectweb.jac.core.rtti.FieldItem; 046 import org.objectweb.jac.core.rtti.MethodItem; 047 import org.objectweb.jac.util.Semaphore; 048 import org.objectweb.jac.util.Strings; 049 050 /** 051 * This dialog is used to ask the parameters values when a method is 052 * called on a viewed JAC object.<p> 053 * 054 * @see View 055 * 056 * @author <a href="mailto:renaud@cnam.fr">Renaud Pawlak</a> 057 * @author <a href="mailto:laurent@aopsys.com">Laurent Martelli</a> 058 */ 059 public class Dialog extends JDialog 060 implements ActionListener, KeyListener, ContainerListener, DialogView 061 { 062 static Logger loggerEvents = Logger.getLogger("gui.events"); 063 064 String label; 065 DisplayContext context; 066 int width; 067 int height; 068 ViewFactory factory; 069 Object[] parameters; 070 String type; 071 072 boolean ok = false; 073 074 private JButton okButton; 075 private JButton cancelButton; 076 077 Semaphore semaphore = new Semaphore(); 078 String description; 079 View contentView; 080 081 /** 082 * Construct a dialog window. 083 * 084 * @param content the content of the dialog 085 * @param parent the parent window of the dialog 086 * @param description a text describing the dialog to the user 087 */ 088 public Dialog(View content, Object parent, 089 String title, String description) { 090 this.description = description; 091 this.contentView = content; 092 setModal(true); 093 setTitle(title); 094 095 Container contentPane = getContentPane(); 096 097 addWindowListener( new WindowAdapter() { 098 public void windowClosing(WindowEvent e) { 099 e.getWindow().dispose(); 100 } 101 } 102 ); 103 104 contentPane.add(BorderLayout.CENTER, (Component)content); 105 content.setParentView(this); 106 107 if (description != null) 108 { 109 JEditorPane descr = new JEditorPane("text/plain",description); 110 descr.setEditable(false); 111 descr.setBackground(null); 112 contentPane.add(BorderLayout.NORTH,descr); 113 } 114 115 JPanel p2 = new JPanel(); 116 p2.setBorder(BorderFactory.createEtchedBorder()); 117 okButton = addButton(p2,"Ok"); 118 cancelButton = addButton(p2,"Cancel"); 119 getRootPane().setDefaultButton(okButton); 120 contentPane.add(BorderLayout.SOUTH,p2); 121 pack(); 122 123 // open the box centerd in the screen... 124 Dimension screenDim = Toolkit.getDefaultToolkit().getScreenSize(); 125 Rectangle rect = getBounds(); 126 double left = (screenDim.getWidth()-rect.getWidth())/2; 127 double top = (screenDim.getHeight()-rect.getHeight())/2; 128 Rectangle newRect = new Rectangle( 129 (int)left,(int)top, 130 (int)rect.getWidth(),(int)rect.getHeight()); 131 setBounds(newRect); 132 133 addKeyAndContainerListenerRecursively(this); 134 135 attributes = Collaboration.get().getAttributes(); 136 137 setVisible (true); 138 // Do not place anything after this, since this a blocking call 139 } 140 141 /** Stores context attributes at creation time so they can be 142 restored by components when invoking methods */ 143 Map attributes; 144 145 // View interface 146 147 Border viewBorder; 148 149 /** 150 * Get the value of viewBorder. 151 * @return value of viewBorder. 152 */ 153 public Border getViewBorder() { 154 return viewBorder; 155 } 156 157 /** 158 * Set the value of viewBorder. 159 * @param v Value to assign to viewBorder. 160 */ 161 public void setViewBorder(Border v) { 162 this.viewBorder = v; 163 } 164 165 // style used to change display (css for web) 166 String style; 167 168 public void setStyle(String style) { 169 this.style = style; 170 } 171 172 public String getStyle() { 173 return style; 174 } 175 176 MethodItem message; 177 178 /** 179 * Get the value of message. 180 * @return value of message. 181 */ 182 public MethodItem getMessage() { 183 return message; 184 } 185 186 /** 187 * Get the value of description. 188 * @return value of description. 189 */ 190 public String getDescription() { 191 return description; 192 } 193 194 /** 195 * Set the value of description. 196 * @param v Value to assign to description. 197 */ 198 public void setDescription(String v) { 199 this.description = v; 200 } 201 202 View parentView; 203 204 /** 205 * Get the value of parentView. 206 * @return value of parentView. 207 */ 208 public View getParentView() { 209 return parentView; 210 } 211 212 /** 213 * Set the value of parentView. 214 * @param v Value to assign to parentView. 215 */ 216 public void setParentView(View v) { 217 this.parentView = v; 218 } 219 220 public View getRootView() { 221 if (parentView==null) 222 return this; 223 return parentView.getRootView(); 224 } 225 226 public boolean isDescendantOf(View ancestor) { 227 if (this==ancestor) 228 return true; 229 else if (parentView==null) 230 return false; 231 else 232 return parentView.isDescendantOf(ancestor); 233 } 234 235 /** 236 * Set the value of message. 237 * @param v Value to assign to message. 238 */ 239 public void setMessage(MethodItem v) { 240 this.message = v; 241 } 242 243 public void setContext(DisplayContext context) { 244 this.context = context; 245 } 246 247 public DisplayContext getContext() { 248 return context; 249 } 250 251 public void setFactory(ViewFactory factory) { 252 this.factory = factory; 253 } 254 255 public ViewFactory getFactory() { 256 return factory; 257 } 258 259 public void setLabel(String label) { 260 this.label = label; 261 setTitle(label); 262 } 263 264 public String getLabel() { 265 return label; 266 } 267 268 public void setWidth(int width) { 269 this.width = width; 270 } 271 272 public void setHeight(int height) { 273 this.height = height; 274 } 275 276 public void setType(String type) { 277 this.type = type; 278 } 279 280 public String getType() { 281 return type; 282 } 283 284 public void setParameters(Object[] parameters) { 285 this.parameters = parameters; 286 } 287 288 public Object[] getParameters() { 289 return parameters; 290 } 291 292 public boolean equalsView(ViewIdentity view) { 293 return 294 ( ( type!=null && 295 type.equals(view.getType()) ) 296 || (type==null && view.getType()==null ) ) 297 && ( ( parameters!=null && 298 Arrays.equals(parameters,view.getParameters()) ) 299 || (parameters==null && view.getParameters()==null) ); 300 } 301 302 public boolean equalsView(String type, Object[] parameters) { 303 return this.type.equals(type) 304 && Arrays.equals(this.parameters,parameters); 305 } 306 307 public void close(boolean validate) { 308 contentView.close(validate); 309 closed = true; 310 dispose(); 311 } 312 313 boolean closed = false; 314 315 public boolean isClosed() { 316 return closed; 317 } 318 319 public void setFocus(FieldItem field, Object option) { 320 } 321 322 // DialogView interface 323 324 public boolean waitForClose() { 325 loggerEvents.debug("waiting for "+Strings.hex(this)+" to be closed"); 326 semaphore.acquire(); 327 loggerEvents.debug("closed "+Strings.hex(this)+" -> "+ok); 328 return ok; 329 } 330 331 public View getContentView() { 332 return contentView; 333 } 334 335 public void restoreContext() { 336 loggerEvents.debug("Restoring attributes: "+attributes.keySet()); 337 Collaboration.get().setAttributes(attributes); 338 } 339 340 /** 341 * For internal use.<p> 342 */ 343 JButton addButton(Container c, String name) { 344 JButton button = new JButton(name); 345 button.addActionListener(this); 346 c.add(button); 347 return button; 348 } 349 350 /** 351 * Implements what is done when a button is pressed (may be either 352 * OK or CANCEL).<p> 353 * 354 * @param evt tell what button was pressed 355 */ 356 public void actionPerformed(ActionEvent evt) { 357 try { 358 Object source = evt.getSource(); 359 if (source==okButton) { 360 ok = true; 361 semaphore.release(); 362 } else if (source == cancelButton) { 363 ok = false; 364 semaphore.release(); 365 } 366 dispose(); 367 } catch (Exception e) { 368 e.printStackTrace(); 369 } 370 } 371 372 // KeyListener interface 373 public void keyPressed(KeyEvent event) { 374 int code = event.getKeyCode(); 375 switch (code) { 376 case KeyEvent.VK_ESCAPE: 377 ok = false; 378 semaphore.release(); 379 dispose(); 380 break; 381 default: 382 } 383 } 384 public void keyTyped(KeyEvent event) {} 385 public void keyReleased(KeyEvent event) {} 386 387 // ContainerListener interface 388 // Copied from http://www.javaworld.com/javaworld/javatips/jw-javatip69.html 389 390 public void componentAdded(ContainerEvent event) { 391 addKeyAndContainerListenerRecursively(event.getChild()); 392 } 393 394 /** 395 * Register as a KeyListener and ContainerListener on the component 396 * and its children recursively. 397 * @param c the component 398 */ 399 protected void addKeyAndContainerListenerRecursively(Component c) { 400 c.addKeyListener(this); 401 if (c instanceof Container) { 402 Container cont = (Container)c; 403 cont.addContainerListener(this); 404 Component[] children = cont.getComponents(); 405 for(int i=0; i<children.length; i++){ 406 addKeyAndContainerListenerRecursively(children[i]); 407 } 408 } 409 } 410 411 public void componentRemoved(ContainerEvent event) { 412 removeKeyAndContainerListenerRecursively(event.getChild()); 413 } 414 415 /** 416 * Unregister as a KeyListener and ContainerListener on the 417 * component and its children recursively. 418 * @param c the component 419 */ 420 protected void removeKeyAndContainerListenerRecursively(Component c) { 421 c.removeKeyListener(this); 422 if (c instanceof Container) { 423 Container cont = (Container)c; 424 cont.removeContainerListener(this); 425 Component[] children = cont.getComponents(); 426 for(int i=0; i<children.length; i++){ 427 removeKeyAndContainerListenerRecursively(children[i]); 428 } 429 } 430 } 431 }