1 /*
   2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation. Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package org.netbeans.jemmy.operators;
  26 
  27 import java.awt.Component;
  28 import java.awt.Window;
  29 import java.util.ArrayList;
  30 import java.util.Arrays;
  31 import java.util.Hashtable;
  32 import java.util.List;
  33 
  34 import javax.swing.JComponent;
  35 import javax.swing.JToolTip;
  36 import javax.swing.plaf.ToolTipUI;
  37 
  38 import org.netbeans.jemmy.ComponentChooser;
  39 import org.netbeans.jemmy.ComponentSearcher;
  40 import org.netbeans.jemmy.TimeoutExpiredException;
  41 import org.netbeans.jemmy.Waitable;
  42 
  43 /**
  44  * <BR>
  45  * <BR>
  46  * Timeouts used: <BR>
  47  * {@code ComponentOperator.WaitComponentTimeout} - time to wait component
  48  * displayed.<BR>
  49  * {@code ComponentOperator.WaitStateTimeout} - time to wait for tip text. <BR>
  50  *
  51  * @see org.netbeans.jemmy.Timeouts
  52  */
  53 public class JToolTipOperator extends JComponentOperator {
  54 
  55     /**
  56      * Identifier for a "tip text" property.
  57      *
  58      * @see #getDump()
  59      */
  60     public static final String TIP_TEXT_DPROP = "TipText";
  61 
  62     /**
  63      * Constructs a JToolTipOperator object, waiting for a shown
  64      * JToolTip.
  65      */
  66     public JToolTipOperator() {
  67         this(TRUE_CHOOSER);
  68     }
  69 
  70     /**
  71      * Constructs a JToolTipOperator object for a given JToolTip component.
  72      *
  73      * @param toolTip
  74      *            a component
  75      */
  76     public JToolTipOperator(JToolTip toolTip) {
  77         super(toolTip);
  78     }
  79 
  80     /**
  81      * Constructs a JToolTipOperator object waiting for the JToolTip having a
  82      * given tip text (compared using default string comparator).
  83      *
  84      * @param tipText
  85      *            tip text.
  86      * @see #getDefaultStringComparator()
  87      */
  88     public JToolTipOperator(String tipText) {
  89         this(waitJToolTip(new JToolTipByTipTextFinder(tipText,
  90                 getDefaultStringComparator())));
  91     }
  92 
  93     /**
  94      * Constructs a JToolTipOperator object waiting for the JToolTip
  95      * associated with the given component. Uses {@code comp}'s timeout and
  96      * output for waiting. Copies environment from {@code comp}.
  97      *
  98      * @param comp
  99      *            component on which tool tip associated
 100      * @see #copyEnvironment(org.netbeans.jemmy.operators.Operator)
 101      */
 102     public JToolTipOperator(ComponentOperator comp) {
 103         this(comp, TRUE_CHOOSER);
 104     }
 105 
 106     /**
 107      * Constructs a JToolTipOperator object waiting for the JToolTip
 108      * conforming to the given component chooser.
 109      *
 110      * @param chooser
 111      *            a component chooser specifying searching criteria.
 112      */
 113     public JToolTipOperator(ComponentChooser chooser) {
 114         this(null, chooser);
 115     }
 116 
 117     /**
 118      * Constructs a JToolTipOperator object waiting for the JToolTip
 119      * associated with the given component and conforming to the given
 120      * component chooser. Uses {@code comp}'s timeout and output for waiting.
 121      * Copies environment from {@code comp}.
 122      *
 123      * @param comp
 124      *            component on which tool tip associated
 125      * @param chooser
 126      *            a component chooser specifying searching criteria.
 127      * @see #copyEnvironment(org.netbeans.jemmy.operators.Operator)
 128      */
 129     public JToolTipOperator(ComponentOperator comp, ComponentChooser chooser) {
 130         this(waitJToolTip(comp, chooser));
 131         if(comp != null) {
 132             copyEnvironment(comp);
 133         }
 134     }
 135 
 136     /**
 137      * Constructs a JToolTipOperator object waiting for the JToolTip
 138      * associated with the given component and having the given tip text.
 139      * Uses {@code comp}'s string comparator for tip text comparison, timeout
 140      * and output for waiting. Copies environment from {@code comp}.
 141      *
 142      * @param comp
 143      *            component on which tool tip associated
 144      * @param tipText
 145      *            tip text
 146      * @see #getComparator()
 147      * @see #copyEnvironment(org.netbeans.jemmy.operators.Operator)
 148      */
 149     public JToolTipOperator(ComponentOperator comp, String tipText) {
 150         this(waitJToolTip(comp,
 151                 new JToolTipByTipTextFinder(tipText, comp.getComparator())));
 152         copyEnvironment(comp);
 153     }
 154 
 155     /**
 156      * Searches for the JToolTip associated with the given component and
 157      * conforming to the given component chooser. Uses {@code comp}'s timeout
 158      * and output for waiting.
 159      *
 160      * @param comp
 161      *            component on which tool tip associated
 162      * @param chooser
 163      *            a component chooser specifying searching criteria.
 164      * @return JToolTip instance or null if component was not found.
 165      */
 166     public static JToolTip findJToolTip(ComponentOperator comp,
 167             ComponentChooser chooser) {
 168         List<Window> windowList;
 169         if(comp != null && comp.getWindow() != null) {
 170             windowList = new ArrayList<>(
 171                     Arrays.asList(comp.getWindow().getOwnedWindows()));
 172             windowList.add(comp.getWindow());
 173         } else {
 174             windowList = new ArrayList<>(
 175                     Arrays.asList(WindowOperator.getWindows()));
 176         }
 177         ComponentChooser toolTipChooser = new JToolTipFinder(chooser);
 178         for (Window w : windowList) {
 179             ComponentSearcher searcher = new ComponentSearcher(w);
 180             Component[] components = searcher.findComponents(toolTipChooser);
 181             if (components.length > 0) {
 182                 if(comp!= null && comp.getSource() != null) {
 183                     if(comp.getSource().equals(
 184                             ((JToolTip) components[0]).getComponent())) {
 185                         return (JToolTip) components[0];
 186                     }
 187                 } else {
 188                     return (JToolTip) components[0];
 189                 }
 190             }
 191         }
 192         return null;
 193     }
 194 
 195 
 196     /**
 197      * Searches for a JToolTip.
 198      *
 199      * @return JToolTip instance or null if component was not found.
 200      */
 201     public static JToolTip findJToolTip() {
 202         return findJToolTip(null);
 203     }
 204 
 205     /**
 206      * Searches for the JToolTip associated with the given component. Uses
 207      * {@code comp}'s timeout and output for waiting.
 208      *
 209      * @param comp
 210      *            component on which tool tip associated
 211      * @return JToolTip instance or null if component was not found.
 212      */
 213     public static JToolTip findJToolTip(ComponentOperator comp) {
 214         return findJToolTip(comp, TRUE_CHOOSER);
 215     }
 216 
 217     /**
 218      * Searches for the JToolTip associated with the given component and
 219      * looking for given tip text using specified string comparator options.
 220      * Uses {@code comp}'s timeout and output for waiting.
 221      *
 222      * @param comp
 223      *            component on which tool tip associated
 224      * @param tipText
 225      *            Tip text.
 226      * @param ce
 227      *            Compare text exactly.
 228      * @param ccs
 229      *            Compare text case sensitively.
 230      * @return JToolTip instance or null if component was not found.
 231      * @see DefaultStringComparator
 232      * @see JToolTipByTipTextFinder
 233      */
 234     public static JToolTip findJToolTip(ComponentOperator comp, String tipText,
 235             boolean ce, boolean ccs) {
 236         return findJToolTip(comp, new JToolTipByTipTextFinder(tipText,
 237                 new DefaultStringComparator(ce, ccs)));
 238     }
 239 
 240     /**
 241      * Waits for a JToolTip.
 242      *
 243      * @return JToolTip instance.
 244      * @see TimeoutExpiredException
 245      */
 246     public static JToolTip waitJToolTip() {
 247         return waitJToolTip(TRUE_CHOOSER);
 248     }
 249 
 250 
 251     /**
 252      * Waits for the first JToolTip associated with the given component.
 253      *
 254      * @param comp
 255      *            component on which tool tip associated
 256      * @return JToolTip instance.
 257      * @see TimeoutExpiredException
 258      */
 259     public static JToolTip waitJToolTip(ComponentOperator comp) {
 260         return waitJToolTip(comp, TRUE_CHOOSER);
 261     }
 262 
 263     /**
 264      * Waits for the JToolTip conforming to the given component
 265      * chooser.
 266      *
 267      * @param chooser
 268      *            a component chooser specifying searching criteria.
 269      * @return JToolTip instance.
 270      * @see TimeoutExpiredException
 271      */
 272     public static JToolTip waitJToolTip(ComponentChooser chooser) {
 273         return waitJToolTip(null, chooser);
 274     }
 275 
 276     /**
 277      * Waits for the JToolTip associated with the given component and
 278      * conforming to the specified component chooser.
 279      *
 280      * @param comp
 281      *            component on which tool tip associated
 282      * @param chooser
 283      *            a component chooser specifying searching criteria.
 284      * @return JToolTip instance.
 285      * @see TimeoutExpiredException
 286      */
 287     public static JToolTip waitJToolTip(ComponentOperator comp,
 288             ComponentChooser chooser) {
 289         return Operator.getEnvironmentOperator().
 290                 waitState(new Waitable<JToolTip, Void>() {
 291             @Override
 292             public JToolTip actionProduced(Void obj) {
 293                 return findJToolTip(comp, chooser);
 294             }
 295 
 296             @Override
 297             public String getDescription() {
 298                 return "Wait for JTooltip to be displayed for Component = "
 299                         + comp + ", " + "chooser = " + chooser;
 300             }
 301 
 302             @Override
 303             public String toString() {
 304                 return "JToolTipOperator.waitJToolTip.Waitable{description = "
 305                         + getDescription() + '}';
 306             }
 307         });
 308     }
 309 
 310     /**
 311      * Waits for the JToolTip associated with the given component and having
 312      * the given tip text compared using given string comparator options.
 313      *
 314      * @param comp
 315      *            component on which tool tip associated
 316      * @param tipText
 317      *            Tip text.
 318      * @param ce
 319      *            Compare text exactly.
 320      * @param ccs
 321      *            Compare text case sensitively.
 322      * @return JToolTip instance.
 323      * @see TimeoutExpiredException
 324      */
 325     public static JToolTip waitJToolTip(ComponentOperator comp, String tipText,
 326             boolean ce, boolean ccs) {
 327         return waitJToolTip(comp, new JToolTipByTipTextFinder(tipText,
 328                 new DefaultStringComparator(ce, ccs)));
 329     }
 330 
 331     /**
 332      * Waits for the given tip text. Uses {@linkplain #getComparator()}
 333      * comparator.
 334      *
 335      * @param tipText
 336      *            Tip text to wait for.
 337      * @see TimeoutExpiredException
 338      */
 339     public void waitTipText(String tipText) {
 340         getOutput().printLine("Wait \"" + tipText
 341                 + "\" tip text in JToolTip \n    : " + toStringSource());
 342         getOutput().printGolden("Wait \"" + tipText + "\" tip text");
 343         waitState(new JToolTipByTipTextFinder(tipText, getComparator()));
 344     }
 345 
 346     /**
 347      * Returns information about the component.
 348      *
 349      * @return Map of component properties.
 350      */
 351     @Override
 352     public Hashtable<String, Object> getDump() {
 353         Hashtable<String, Object> result = super.getDump();
 354         String tipText = getTipText();
 355         if (tipText != null) {
 356             result.put(TIP_TEXT_DPROP, tipText);
 357         } else {
 358             result.put(TIP_TEXT_DPROP, "null");
 359         }
 360         return result;
 361     }
 362 
 363     ////////////////////////////////////////////////////////
 364     // Mapping //
 365 
 366     /**
 367      * Maps {@linkplain JToolTip#getTipText()} through queue
 368      *
 369      * @return
 370      */
 371     public String getTipText() {
 372         return runMapping(new MapAction<String>("getTipText") {
 373             @Override
 374             public String map() {
 375                 return ((JToolTip) getSource()).getTipText();
 376             }
 377         });
 378     }
 379 
 380     /**
 381      * Maps {@linkplain JToolTip#getComponent()} through queue
 382      *
 383      * @return
 384      */
 385     public JComponent getComponent() {
 386         return runMapping(new MapAction<JComponent>("getComponent") {
 387             @Override
 388             public JComponent map() {
 389                 return ((JToolTip) getSource()).getComponent();
 390             }
 391         });
 392     }
 393 
 394     /**
 395      * Maps {@linkplain JToolTip#getUI()} through queue
 396      *
 397      * @return
 398      */
 399     public ToolTipUI getUI() {
 400         return runMapping(new MapAction<ToolTipUI>("getUI") {
 401             @Override
 402             public ToolTipUI map() {
 403                 return ((JToolTip) getSource()).getUI();
 404             }
 405         });
 406     }
 407 
 408     /**
 409      * Maps {@linkplain JToolTip#setTipText(String)} through queue
 410      *
 411      * @param tipText
 412      */
 413     public void setTipText(final String tipText) {
 414         runMapping(new MapVoidAction("setTipText") {
 415             @Override
 416             public void map() {
 417                 ((JToolTip) getSource()).setTipText(tipText);
 418             }
 419         });
 420     }
 421 
 422     /**
 423      * Maps {@linkplain JToolTip#setComponent(JComponent)} through queue
 424      *
 425      * @param component
 426      */
 427     public void setComponent(final JComponent component) {
 428         runMapping(new MapVoidAction("setComponent") {
 429             @Override
 430             public void map() {
 431                 ((JToolTip) getSource()).setComponent(component);
 432             }
 433         });
 434     }
 435     // End of mapping //
 436     ////////////////////////////////////////////////////////
 437 
 438 
 439     /**
 440      * Allows to find JToolTip by tip text.
 441      */
 442     public static class JToolTipByTipTextFinder implements ComponentChooser {
 443 
 444         String tipText;
 445         StringComparator comparator;
 446 
 447         /**
 448          * Constructs JToolTipByTipTextFinder.
 449          *
 450          * @param tipText
 451          *            a tip text pattern
 452          * @param comparator
 453          *            specifies string comparison algorithm.
 454          */
 455         public JToolTipByTipTextFinder(String tipText,
 456                 StringComparator comparator) {
 457             this.tipText = tipText;
 458             this.comparator = comparator;
 459         }
 460 
 461         /**
 462          * Constructs JToolTipByTipTextFinder.
 463          *
 464          * @param tipText
 465          *            a tip text pattern
 466          */
 467         public JToolTipByTipTextFinder(String tipText) {
 468             this(tipText, Operator.getDefaultStringComparator());
 469         }
 470 
 471         @Override
 472         public boolean checkComponent(Component comp) {
 473             if (comp instanceof JToolTip) {
 474                 if (((JToolTip) comp).getTipText() != null) {
 475                     return (comparator.equals(((JToolTip) comp).getTipText(),
 476                             tipText));
 477                 }
 478             }
 479             return false;
 480         }
 481 
 482         @Override
 483         public String getDescription() {
 484             return "JToolTip with tip text \"" + tipText + "\"";
 485         }
 486 
 487         @Override
 488         public String toString() {
 489             return "JToolTipByTipTextFinder{" + "tipText=" + tipText
 490                     + ", comparator=" + comparator + '}';
 491         }
 492     }
 493 
 494     /**
 495      * Allows to find JToolTips among components.
 496      */
 497     public static class JToolTipFinder extends Finder {
 498 
 499         /**
 500          * Constructs JToolTipFinder chaining another component chooser.
 501          *
 502          * @param sf
 503          *            other searching criteria.
 504          */
 505         public JToolTipFinder(ComponentChooser sf) {
 506             super(JToolTip.class, sf);
 507         }
 508 
 509         /**
 510          * Constructs JToolTipFinder.
 511          */
 512         public JToolTipFinder() {
 513             super(JToolTip.class);
 514         }
 515     }
 516 
 517     private static final ComponentChooser TRUE_CHOOSER = ComponentSearcher
 518             .getTrueChooser("Any JToolTip");
 519 }