       1 /*
       2  * Copyright (c) 2010, 2013, 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
      26 package javafx.scene;
      27
      28 import java.net.MalformedURLException;
      29 import java.net.URL;
      30 import javafx.scene.image.Image;
      31 import com.sun.javafx.cursor.CursorFrame;
      32 import com.sun.javafx.cursor.CursorType;
      33 import com.sun.javafx.cursor.StandardCursorFrame;
      34
      35 /**
      36  * A class to encapsulate the bitmap representation of the mouse cursor.
      37  * @since JavaFX 2.0
      38  */
      39 public abstract class Cursor {
      40     /**
      41      * The default cursor type (gets set if no cursor is defined).
      42      */
      43     public static final Cursor DEFAULT =
      44             new StandardCursor("DEFAULT", CursorType.DEFAULT);
      45
      46     /**
      47      * The crosshair cursor type.
      48      */
      49     public static final Cursor CROSSHAIR =
      50             new StandardCursor("CROSSHAIR", CursorType.CROSSHAIR);
      51
      52     /**
      53      * The text cursor type.
      54      */
      55     public static final Cursor TEXT =
      56             new StandardCursor("TEXT", CursorType.TEXT);
      57
      58     /**
      59      * The wait cursor type.
      60      */
      61     public static final Cursor WAIT =
      62             new StandardCursor("WAIT", CursorType.WAIT);
      63
      64     /**
      65      * The south-west-resize cursor type.
      66      */
      67     public static final Cursor SW_RESIZE =
      68             new StandardCursor("SW_RESIZE", CursorType.SW_RESIZE);
      69
      70     /**
      71      * The south-east-resize cursor type.
      72      */
      73     public static final Cursor SE_RESIZE =
      74             new StandardCursor("SE_RESIZE", CursorType.SE_RESIZE);
      75
      76     /**
      77      * The north-west-resize cursor type.
      78      */
      79     public static final Cursor NW_RESIZE =
      80             new StandardCursor("NW_RESIZE", CursorType.NW_RESIZE);
      81
      82     /**
      83      * The north-east-resize cursor type.
      84      */
      85     public static final Cursor NE_RESIZE =
      86             new StandardCursor("NE_RESIZE", CursorType.NE_RESIZE);
      87
      88     /**
      89      * The north-resize cursor type.
      90      */
      91     public static final Cursor N_RESIZE =
      92             new StandardCursor("N_RESIZE", CursorType.N_RESIZE);
      93
      94     /**
      95      * The south-resize cursor type.
      96      */
      97     public static final Cursor S_RESIZE =
      98             new StandardCursor("S_RESIZE", CursorType.S_RESIZE);
      99
     100     /**
     101      * The west-resize cursor type.
     102      */
     103     public static final Cursor W_RESIZE =
     104             new StandardCursor("W_RESIZE", CursorType.W_RESIZE);
     105
     106     /**
     107      * The east-resize cursor type.
     108      */
     109     public static final Cursor E_RESIZE =
     110             new StandardCursor("E_RESIZE", CursorType.E_RESIZE);
     111
     112     /**
     113      * A cursor with a hand which is open
     114      */
     115     public static final Cursor OPEN_HAND =
     116             new StandardCursor("OPEN_HAND", CursorType.OPEN_HAND);
     117
     118     /**
     119      * A cursor with a hand that is closed, often used when
     120      * "grabbing", for example, when panning.
     121      */
     122     public static final Cursor CLOSED_HAND =
     123             new StandardCursor("CLOSED_HAND", CursorType.CLOSED_HAND);
     124
     125     /**
     126      * The hand cursor type, resembling a pointing hand, often
     127      * used to indicate that something can be clicked, such as
     128      * a hyperlink.
     129      */
     130     public static final Cursor HAND =
     131             new StandardCursor("HAND", CursorType.HAND);
     132
     133     /**
     134      * The move cursor type.
     135      */
     136     public static final Cursor MOVE =
     137             new StandardCursor("MOVE", CursorType.MOVE);
     138
     139     /**
     140      * The disappear cursor type. This is often used when dragging
     141      * something, such that when the user releases the mouse, the
     142      * item will disappear. On Mac, this is used when dragging items
     143      * off a toolbar or in other such situations.
     144      */
     145     public static final Cursor DISAPPEAR =
     146             new StandardCursor("DISAPPEAR", CursorType.DISAPPEAR);
     147
     148     /**
     149      * The horizontal cursor type.
     150      */
     151     public static final Cursor H_RESIZE =
     152             new StandardCursor("H_RESIZE", CursorType.H_RESIZE);
     153
     154     /**
     155      * The vertical cursor type.
     156      */
     157     public static final Cursor V_RESIZE =
     158             new StandardCursor("V_RESIZE", CursorType.V_RESIZE);
     159
     160     /**
     161      * The none cursor type. On platforms that don't support
     162      * custom cursors, this will be the same as {@code DEFAULT}.
     163      */
     164     public static final Cursor NONE =
     165             new StandardCursor("NONE", CursorType.NONE);
     166
     167     private String name = "CUSTOM";
     168
     169     Cursor() { }
     170     Cursor(String name) {
     171         this.name = name;
     172     }
     173
     174     abstract CursorFrame getCurrentFrame();
     175
     176     /**
     177      * Activates the cursor. Cursor should be activated to make sure
     178      * that the {@code impl_getCurrentFrame} returns up-to date values.
     179      */
     180     void activate() {
     181         // no activation necessary for standard cursors
     182     }
     183
     184     /**
     185      * Deactivates the cursor. Cursor should be deactivated, when no longer in
     186      * use to make it collectible by GC.
     187      */
     188     void deactivate() {
     189     }
     190
     191     /**
     192      * Returns a string representation for the cursor.
     193      * @return a string representation for the cursor.
     194      */
     195     @Override public String toString() {
     196         return name;
     197     }
     198
     199     // PENDING_DOC_REVIEW
     200     /**
     201      * Returns a cursor for the specified identifier. The identifier can be
     202      * either a name of some standard cursor or a valid URL string. If the
     203      * identifier names a standard cursor the corresponding cursor is returned.
     204      * In the case of a URL string, the method returns a new {@code ImageCursor}
     205      * created for that URL.
     206      *
     207      * @param identifier the cursor identifier
     208      * @return the cursor for the identifier
     209      * @throws IllegalArgumentException if the cursor identifier is not a
     210      *      valid URL string nor any standard cursor name
     211      */
     212     public static Cursor cursor(final String identifier) {
     213         if (identifier == null) {
     214             throw new NullPointerException(
     215                     "The cursor identifier must not be null");
     216         }
     217
     218         if (isUrl(identifier)) {
     219             return new ImageCursor(new Image(identifier));
     220         }
     221
     222         String uName = identifier.toUpperCase();
     223         if (uName.equals(DEFAULT.name)) {
     224             return DEFAULT;
     225         } else if(uName.equals(CROSSHAIR.name)) {
     226             return CROSSHAIR;
     227         } else if (uName.equals(TEXT.name)) {
     228             return TEXT;
     229         } else if (uName.equals(WAIT.name)) {
     230             return WAIT;
     231         } else if (uName.equals(MOVE.name)) {
     232             return MOVE;
     233         } else if (uName.equals(SW_RESIZE.name)) {
     234             return SW_RESIZE;
     235         } else if (uName.equals(SE_RESIZE.name)) {
     236             return SE_RESIZE;
     237         } else if (uName.equals(NW_RESIZE.name)) {
     238             return NW_RESIZE;
     239         } else if (uName.equals(NE_RESIZE.name)) {
     240             return NE_RESIZE;
     241         } else if (uName.equals(N_RESIZE.name)) {
     242             return N_RESIZE;
     243         } else if (uName.equals(S_RESIZE.name)) {
     244             return S_RESIZE;
     245         } else if (uName.equals(W_RESIZE.name)) {
     246             return W_RESIZE;
     247         } else if (uName.equals(E_RESIZE.name)) {
     248             return E_RESIZE;
     249         } else if (uName.equals(OPEN_HAND.name)) {
     250             return OPEN_HAND;
     251         } else if (uName.equals(CLOSED_HAND.name)) {
     252             return CLOSED_HAND;
     253         } else if (uName.equals(HAND.name)) {
     254             return HAND;
     255         } else if (uName.equals(H_RESIZE.name)) {
     256             return H_RESIZE;
     257         } else if (uName.equals(V_RESIZE.name)) {
     258             return V_RESIZE;
     259         } else if (uName.equals(DISAPPEAR.name)) {
     260             return DISAPPEAR;
     261         } else if (uName.equals(NONE.name)) {
     262             return NONE;
     263         }
     264
     265         throw new IllegalArgumentException("Invalid cursor specification");
     266     }
     267
     268     private static boolean isUrl(final String identifier) {
     269         try {
     270             new URL(identifier);
     271         } catch (final MalformedURLException e) {
     272             return false;
     273         }
     274
     275         return true;
     276     }
     277
     278     private static final class StandardCursor extends Cursor {
     279         private final CursorFrame singleFrame;
     280
     281         public StandardCursor(final String name, final CursorType type) {
     282             super(name);
     283             singleFrame = new StandardCursorFrame(type);
     284         }
     285
     286         @Override
     287         CursorFrame getCurrentFrame() {
     288             return singleFrame;
     289         }
     290     }
     291 }