1 /*
   2  * $Id$
   3  *
   4  * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
   5  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   6  *
   7  * This code is free software; you can redistribute it and/or modify it
   8  * under the terms of the GNU General Public License version 2 only, as
   9  * published by the Free Software Foundation.  Oracle designates this
  10  * particular file as subject to the "Classpath" exception as provided
  11  * by Oracle in the LICENSE file that accompanied this code.
  12  *
  13  * This code is distributed in the hope that it will be useful, but WITHOUT
  14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  16  * version 2 for more details (a copy is included in the LICENSE file that
  17  * accompanied this code).
  18  *
  19  * You should have received a copy of the GNU General Public License version
  20  * 2 along with this work; if not, write to the Free Software Foundation,
  21  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  22  *
  23  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  24  * or visit www.oracle.com if you need additional information or have any
  25  * questions.
  26  */
  27 package com.sun.javatest.tool;
  28 
  29 import java.awt.BorderLayout;
  30 import java.awt.Component;
  31 import java.lang.ref.WeakReference;
  32 import java.util.ArrayList;
  33 import java.util.Iterator;
  34 import java.util.List;
  35 import java.util.Map;
  36 
  37 import javax.swing.JDialog;
  38 import javax.swing.JMenuBar;
  39 import javax.swing.JPanel;
  40 
  41 import com.sun.javatest.TestSuite;
  42 import com.sun.javatest.WorkDirectory;
  43 import com.sun.javatest.tool.jthelp.ContextHelpManager;
  44 import com.sun.javatest.tool.jthelp.HelpBroker;
  45 import com.sun.javatest.util.DynamicArray;
  46 
  47 /**
  48  * A base class for tools to appear on the JT Harness desktop.
  49  */
  50 public abstract class Tool extends JPanel
  51 {
  52     /**
  53      * An observer interface for use by those that wishing to monitor changes
  54      * to a tool.
  55      */
  56     public interface Observer {
  57         /**
  58          * The title of a tool has been changed.
  59          * @param source The tool whose title has been changed.
  60          * @param newValue The new title for the tool.
  61          */
  62         void titleChanged(Tool source, String newValue);
  63 
  64         /**
  65          * The short title of a tool has been changed.
  66          * @param source The tool whose title has been changed.
  67          * @param newValue The new title for the tool.
  68          */
  69         void shortTitleChanged(Tool source, String newValue);
  70 
  71         /**
  72          * A tool has been disposed.
  73          * @param source the tool that has been disposed
  74          */
  75         void toolDisposed(Tool source);
  76     }
  77 
  78     //--------------------------------------------------------------------------
  79 
  80     /**
  81      * Add an observer to be notified of changes to a tool.
  82      * @param o the observer to be added
  83      * @see #removeObserver
  84      */
  85     synchronized public void addObserver(Observer o) {
  86         observers = (Observer[])DynamicArray.append(observers, o);
  87     }
  88 
  89     /**
  90      * Remove a previously registered observer so that it will no longer
  91      *  be notified of changes to a tool.
  92      * @param o the observer to be removed
  93      * @see #addObserver
  94      */
  95     synchronized public void removeObserver(Observer o) {
  96         observers = (Observer[])DynamicArray.remove(observers, o);
  97     }
  98 
  99     //--------------------------------------------------------------------------
 100 
 101     /**
 102      * Get the menu bar for a tool.
 103      * This should just contain the tool-specific menus. The desktop will
 104      * automatically add and display the standard menus on the menu bar.
 105      * @return a menu bar containing tool-specific menus
 106      */
 107     public abstract JMenuBar getMenuBar();
 108 
 109     /**
 110      * Set the title string for the tool. This will normally the displayed
 111      * by the desktop in the title bar of the window containing the tool.
 112      * @param key key to be used to get title text from resource bundle
 113      * @see #getTitle
 114      */
 115     protected void setI18NTitle(String key) {
 116         setLocalizedTitle(uif.getI18NString(key));
 117     }
 118 
 119     /**
 120      * Set the title string for the tool. This will normally the displayed
 121      * by the desktop in the title bar of the window containing the tool.
 122      * @param key key to be used to get title text from resource bundle
 123      * @param arg item for substitution into string from resource bundle
 124      * @see com.sun.javatest.util.I18NResourceBundle
 125      * @see #getTitle
 126      */
 127     protected void setI18NTitle(String key, Object arg) {
 128         setLocalizedTitle(uif.getI18NString(key, arg));
 129     }
 130 
 131     /**
 132      * Set the title string for the tool. This will normally the displayed
 133      * by the desktop in the title bar of the window containing the tool.
 134      * @param key key to be used to get title text from resource bundle
 135      * @param args items for substitution into string from resource bundle
 136      * @see com.sun.javatest.util.I18NResourceBundle
 137      * @see #getTitle
 138      */
 139     protected void setI18NTitle(String key, Object[] args) {
 140         setLocalizedTitle(uif.getI18NString(key, args));
 141     }
 142 
 143     /**
 144      * Set the title string for the tool. This will normally the displayed
 145      * by the desktop in the title bar of the window containing the tool.
 146      * @param newTitle the title string for the tool
 147      * @see #getTitle
 148      */
 149     private synchronized void setLocalizedTitle(String newTitle) {
 150         if (title == null ? newTitle == null : title.equals(newTitle))
 151             return;
 152 
 153         title = newTitle;
 154         for (int i = 0; i < observers.length; i++) {
 155             observers[i].titleChanged(this, title);
 156         }
 157     }
 158 
 159     /**
 160      * Get the title string for the tool.
 161      * @return the title string for the tool
 162      * @see #setI18NTitle(String)
 163      * @see #setI18NTitle(String,Object)
 164      * @see #setI18NTitle(String,Object[])
 165      */
 166     public String getTitle() {
 167         return title;
 168     }
 169 
 170     /**
 171      * Set a short title for the tool. This will normally be displayed
 172      * by the desktop in situations where there is not room for the
 173      * full title.
 174      * @param newShortTitle the short title string for the tool
 175      * @see #getShortTitle
 176      */
 177     public void setShortTitle(String newShortTitle) {
 178         if (shortTitle == null ? newShortTitle == null : shortTitle.equals(newShortTitle))
 179             return;
 180 
 181         shortTitle = newShortTitle;
 182         for (int i = 0; i < observers.length; i++) {
 183             observers[i].shortTitleChanged(this, shortTitle);
 184         }
 185     }
 186 
 187     /**
 188      * Get a short title for the tool.
 189      * @return the short title string for the tool
 190      * @see #setShortTitle
 191      */
 192     public String getShortTitle() {
 193         if (shortTitle != null)
 194             return shortTitle;
 195         else if (title != null)
 196             return title;
 197         else
 198             return getName();
 199     }
 200 
 201     /**
 202      * Get a list of any test suites that are being used by this tool.
 203      * @return a list of test suites being used by the tool, or null if none
 204      */
 205     public TestSuite[] getLoadedTestSuites() {
 206         return null;
 207     }
 208 
 209     /**
 210      * Get a list of any work directories that are being used by this tool.
 211      * @return a list of work directories being used by the tool, or null if none
 212      */
 213     public WorkDirectory[] getLoadedWorkDirectories() {
 214         return null;
 215     }
 216 
 217     /**
 218      * Get the creation time for this tool. This is used by the desktop
 219      * to help preserve a consistent order when changing between desktop
 220      * styles.
 221      * @return a standard long cvalue, as returned by
 222      * System.currentTimeMillis, indicating the time the tool was created
 223      */
 224     public long getCreationTime() {
 225         return creationTime;
 226     }
 227 
 228 
 229 
 230     //--------------------------------------------------------------------------
 231 
 232     /**
 233      * Release any resources this tool may be referencing.
 234      * This is for "destroying" this tool instance.
 235      */
 236     public void dispose() {
 237         removeAll();
 238         uif.dispose();
 239 
 240         for (int i = observers.length - 1; i >= 0; i--)
 241             observers[i].toolDisposed(this);
 242 
 243         observers = new Observer[0];
 244     }
 245 
 246     //--------------------------------------------------------------------------
 247 
 248     /**
 249      * Create a tool object.
 250      * The resources used are from your resource bundle:
 251      * <table>
 252      * <tr><td><i>uiKey</i>.name <td>accessible name text
 253      * </table>
 254      * @param m the manager for this tool
 255      * @param uiKey the component name for this tool
 256      */
 257     protected Tool(ToolManager m, String uiKey) {
 258         super(new BorderLayout());
 259         setName(uiKey + ":" + (toolIndex++));
 260         setFocusable(false);
 261         manager = m;
 262         uif = new UIFactory(this, m.getDesktop().getHelpBroker());
 263         uif.setAccessibleName(this, uiKey);
 264         uif.setToolTip(this, uiKey);
 265         creationTime = System.currentTimeMillis();
 266     }
 267 
 268     /**
 269      * Create a tool object.
 270      * @param m the manager for this tool
 271      * @param uiKey the component name for this tool
 272      * @param helpID the help ID for context-sensitive help for this tool
 273      */
 274     protected Tool(ToolManager m, String uiKey, String helpID) {
 275         this(m, uiKey);
 276 
 277         ContextHelpManager.setHelpIDString(this, helpID);
 278     }
 279 
 280     /**
 281      * Get the manager for this tool.
 282      * @return the manager for this tool
 283      */
 284     public ToolManager getManager() {
 285         return manager;
 286     }
 287 
 288     /**
 289      * Get the desktop for this tool.
 290      * @return the desktop for this tool
 291      */
 292     public Desktop getDesktop() {
 293         return manager.getDesktop();
 294     }
 295 
 296     /**
 297      * Get the help broker used to provide help for this tool.
 298      * @return the help broker used to provide help for this tool
 299      */
 300     public HelpBroker getHelpBroker() {
 301         return manager.getDesktop().getHelpBroker();
 302     }
 303 
 304     /**
 305      * Save information about a tool in a map, so that the
 306      * tool can be restored in a later invocation of JT Harness.
 307      * The tool must also implement the following method
 308      * <code>public static Tool restore(Map m)</code>
 309      * which will be invoked to recreate the tool.
 310      * @param m the map in which to store the significant state
 311      * of the tool
 312      */
 313     protected abstract void save(Map m);
 314 
 315 
 316     /**
 317      * Restore information about a tool from a map, and configure
 318      * the tool according this information.
 319      * @param m the map in which to store the significant state
 320      * of the tool
 321      */
 322     protected abstract void restore(Map m);
 323 
 324 
 325     /**
 326      * Get a list (if any) of the reasons why it might be inadvisable
 327      * to close the tool at this point. This will normally include
 328      * information about unsaved data or tasks in progress.
 329      * @return a list of alerts about why the user might not want
 330      * to close the tool at this time; the list may be empty or null
 331      * to indicate that there are no such reasons
 332      */
 333     protected String[] getCloseAlerts() {
 334         return null;
 335     }
 336 
 337 
 338     /**
 339      * Set the helpID for this component.  The help
 340      * will be shown if and when the focus is on this component
 341      * and the standard Help key (F1) is pressed.
 342      * @param helpID the ID for the help to be displayed
 343      */
 344     protected void setHelp(String helpID) {
 345         setHelp(this, helpID);
 346     }
 347 
 348     /**
 349      * Set the helpID for a specific component.  The help
 350      * will be shown if and when the focus is on the specified component
 351      * and the standard Help key (F1) is pressed.
 352      * @param comp the component in question
 353      * @param helpID the ID for the help to be displayed
 354      */
 355     protected void setHelp(Component comp, String helpID) {
 356         HelpBroker b = getHelpBroker();
 357         if (b != null) {
 358             if (comp instanceof JDialog) {
 359                 JDialog d = (JDialog) comp;
 360                 Desktop.addHelpDebugListener(d);
 361                 b.enableHelpKey(d.getRootPane(), helpID);
 362                 ContextHelpManager.setHelpIDString(d.getRootPane(), helpID);
 363             } else {
 364                 b.enableHelpKey(comp, helpID);
 365                 ContextHelpManager.setHelpIDString(comp, helpID);
 366             }
 367         }
 368     }
 369 
 370     /**
 371      * Set a button to be a Help button and to invoke the help
 372      * view set to a specific helpID.
 373      * @param comp the button to be made into a help button
 374      * @param helpID the ID for the help to be displayed when the
 375      * button is pressed
 376      */
 377     protected void setHelpOnButton(Component comp, String helpID) {
 378         HelpBroker b = getHelpBroker();
 379         if (b != null)
 380             b.enableHelpKey(comp, helpID);
 381     }
 382 
 383     /**
 384      * Get an array containing the set of ToolDialogs owned by this tool.
 385      * @return an array containing the set of ToolDialogs owned by this tool
 386      */
 387     public ToolDialog[] getToolDialogs() {
 388         if (toolDialogs == null)
 389             return new ToolDialog[0];
 390 
 391         ArrayList l = new ArrayList();
 392         for (Iterator iter = toolDialogs.iterator(); iter.hasNext(); ) {
 393             WeakReference r = (WeakReference) (iter.next());
 394             ToolDialog td = (ToolDialog) (r.get());
 395             if (td == null)
 396                 iter.remove();
 397             else
 398                 l.add(td);
 399         }
 400 
 401         return (ToolDialog[]) (l.toArray(new ToolDialog[l.size()]));
 402     }
 403 
 404     /**
 405      * Record a ToolDialog as belonging to this tool.
 406      * @param td the tool dialog to be registered as belonging to this tool.
 407      */
 408     void addToolDialog(ToolDialog td) {
 409         if (td == null)
 410             throw new NullPointerException();
 411 
 412         if (toolDialogs == null)
 413             toolDialogs = new ArrayList();
 414 
 415         toolDialogs.add(new WeakReference(td));
 416     }
 417 
 418     void setDeskView(DeskView view) {
 419         deskView = view;
 420     }
 421 
 422     DeskView getDeskView() {
 423         return deskView;
 424     }
 425 
 426     /**
 427      * The UI factory used to create GUI components.
 428      */
 429     protected final UIFactory uif;
 430     private ToolManager manager;
 431     private String title;
 432     private String shortTitle;
 433     private String helpID;
 434     private long creationTime;
 435     private List toolDialogs;
 436     private DeskView deskView;
 437     private Observer[] observers = new Observer[0];
 438     private static int toolIndex;
 439 }