Return-Path: <nobody@hermes.java.sun.com>
Received: from fort-point-station.mit.edu by po10.mit.edu (8.9.2/4.7) id FAA09194; Wed, 11 Oct 2000 05:02:56 -0400 (EDT)
Received: from hermes.java.sun.com (hermes.java.sun.com [204.160.241.85])
	by fort-point-station.mit.edu (8.9.2/8.9.2) with ESMTP id FAA14355;
	Wed, 11 Oct 2000 05:02:48 -0400 (EDT)
Received: (from nobody@localhost)
	by hermes.java.sun.com (8.9.3+Sun/8.9.1) id JAA25471;
	Wed, 11 Oct 2000 09:04:19 GMT
Date: Wed, 11 Oct 2000 09:04:19 GMT
Message-Id: <200010110904.JAA25471@hermes.java.sun.com>
X-Authentication-Warning: hermes.java.sun.com: Processed from queue /bulkmail/data/ed_42/mqueue9
X-Mailing: 275
From: JDCTechTips@sun.com
Subject: JDC Tech Tips October 10, 2000
To: JDCMember@sun.com
Reply-To: JDCTechTips@sun.com
Errors-To: bounced_mail@hermes.java.sun.com
Precedence: junk
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
X-Mailer: Beyond Email 2.2


 J  D  C    T  E  C  H    T  I  P  S

                      TIPS, TECHNIQUES, AND SAMPLE CODE


WELCOME to the Java Developer Connection(sm) (JDC) Tech Tips, 
October 10, 2000. This issue covers:

         * Customizing JToolTips
         * Shadowing
                  
These tips were developed using Java(tm) 2 SDK, Standard Edition, 
v 1.3.

You can view this issue of the Tech Tips on the Web at
http://developer.java.sun.com/developer/TechTips/2000/tt1010.html
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

CUSTOMIZING JTOOLTIPS

JToolTip is a Swing class that you use to provide a tip for 
a Swing component. When the mouse cursor is moved over the 
component, a short text message is displayed describing the 
function of the component.

It's easy to set a tip for a component; you just say:

    comp.setToolTipText("tip text");

Let's look at a couple of ways of customizing tool tips, in the 
context of the following application:

    import java.awt.*;
    import java.awt.event.*;
    import java.awt.image.*;
    import javax.swing.*;
    
    // a customized label that displays a color fade image
    
    class ColorLabel extends JLabel {
        private static final int WIDTH = 100;  // label width
        private static final int HEIGHT = 100; // label height
        private static final int SZ = 20;      // size of tip area
    
        private static Image img;      // generated image for label
        private static ImageIcon icon; // ImageIcon for the image
    
        // generate a color fade image
        // adapted from 1.3 java/awt/image/MemoryImageSource.java
    
        static {
    
            // generate the pixel array
    
            int pixels[] = new int[WIDTH * HEIGHT];
            int index = 0;
            for (int y = 0; y < HEIGHT; y++) {
                int red = (y * 255) / (HEIGHT - 1);
                for (int x = 0; x < WIDTH; x++) {
                    int blue = (x * 255) / (WIDTH - 1);
                    pixels[index++] = (255 << 24) |
                        (red << 16) | blue;
                }
            }
    
            // generate the actual image from the pixels
    
            img = Toolkit.getDefaultToolkit().createImage(
                new MemoryImageSource(WIDTH, HEIGHT, pixels,
                0, WIDTH));
            icon = new ImageIcon(img);
        }
    
        // an inner class, objects of which represent one
        // customized tooltip with bounding box and text specified
    
        static class Tip {
            Rectangle rect;
            String text;
            Tip(Rectangle r, String t) {
                rect = r;
                text = t;
            }
        };
    
        // the list of custom tooltips
    
        static Tip tips[] = {
            new Tip(new Rectangle(0, 0, SZ, SZ),
                "Black Part"),
            new Tip(new Rectangle(WIDTH - SZ, 0, SZ, SZ),
                "Blue Part"),
            new Tip(new Rectangle(0, HEIGHT - SZ, SZ, SZ),
                "Red Part"),
            new Tip(new Rectangle(WIDTH - SZ, HEIGHT - SZ, SZ, SZ),
                "Pink Part"),
        };
    
        // constructor for ColorLabel
        // set the label image and the default tooltip text
    
        public ColorLabel() {
            super(icon);
            setToolTipText("Color Fade Example");
        }
    
        // override of JComponent.getToolTipText to support
        // custom tooltips based on the mouse position
    
        public String getToolTipText(MouseEvent e) {
    
            // get mouse position
    
            Point p = e.getPoint();
    
            // see if it's in any of the custom tooltip
            // bounding boxes
    
            for (int i = 0; i < tips.length; i++) {
                if (tips[i].rect.contains(p)) {
                    return tips[i].text;
                }
            }
    
            // if not, return default
    
            return getToolTipText();
        }
    }
    
    
    public class ToolTipDemo {
        public static void main(String args[]) {
    
            // set up the frame and the window closing event handler
    
            JFrame frame = new JFrame("ToolTipDemo");
            frame.addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                    System.exit(0);
                }
            });
    
            // create an Exit button with a customized
            // tooltip that uses an italicized font
    
            JButton button = new JButton("Exit") {
                public JToolTip createToolTip() {
                    JToolTip t = super.createToolTip();
                    t.setFont(new Font("TimesRoman",
                        Font.ITALIC, 16));
                    return t;
                }
            };
            button.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    System.exit(0);
                }
            });
            button.setToolTipText("Terminate the application");
    
            // set up the panel
    
            JPanel panel = new JPanel();
    
            panel.add(new ColorLabel());
            panel.add(button);
    
            // display the frame
    
            frame.getContentPane().add(panel);
            frame.setSize(200, 150);
            frame.setLocation(300, 200);
            frame.setVisible(true);
        }
    }

This program draws a color fade box on the screen. A color fade is
a gradual change from one color to another, for example from black
to blue across the top of the box. The color fade example is
adapted from that found in the comments in
java/awt/image/MemoryImageSource.java for JDK 1.3.

The color fade is calculated into a pixel array, which is then
used to construct the Image object. An ImageIcon is then formed
from the image. The ImageIcon is used to set the icon for the 
JLabel object that represents the box. There's also an Exit button 
drawn next to the box.

The first type of tooltip customization is for the Exit button. 
The text of the tip is changed to a 16-point italicized Times Roman 
font. The program does this by overriding JComponent.createToolTip. 
Notice that the overriding method calls the superclass's
createToolTip method to get the tip object; the overriding method
then sets the font for the object.

The other kind of customization is more sophisticated. If you have
an application with a complex GUI component in it, it would be nice
to customize tooltips based on the position of the mouse within the
component.

To do this, you can override JComponent.getToolTipText(MouseEvent). 
By default, this method simply returns the text that was set with
setToolTipText. But you can specify your own version of the method,
and obtain the mouse cursor position; you can then return custom 
text based on the position.

The example program above sets a general tip "Color Fade Example" 
for the color fade box. Then the program calls getToolTipText to get
the mouse position. getToolTipText also checks whether the mouse is
in any of the four corners of the box. A corner is defined to be 20
x 20 pixels. If the mouse is in one of the corners, a custom tip
such as "Blue Part" is displayed.

Other types of tooltip customization are possible, for example,
you can set a preferred location for the display of a tooltip.

For more information about tooltips, see the "Tooltips" section
in Chapter 4 of "Graphic Java - Mastering the JFC 3rd Edition, 
Volume II Swing" by David Geary.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

SHADOWING

Suppose you're reading some Java code, and you come across
something like this:

    class A {
        int A = 37;
        A() {
            int A = 47;
            A aref = new A() {
                int A = 57;
                void A() {}
            };
        }
    }

This usage is legal, but not necessarily desirable. In fact, it 
raises an interesting question about how the Java programming
language specification treats conflicting names. There are 
several terms used in this area to describe various cases:
shadowing, overriding, hiding, and obscuring. This tip looks at 
an example of each of these.

First an important point needs to be made: just because the
Java programming language allows you to do something, it doesn't 
always mean that it's a desirable thing to do. For example, it's 
legal to say:

    class A {
        int A;
    }

in a program, but you probably shouldn't because it's confusing. 
The best way to handle issues with conflicting names is to simply
avoid them as far as possible. For example, you can avoid many 
problems if you follow a coding convention that specifies that 
the first letter of a type name (such as "class A") should be 
capitalized, while the first letter of a field name (such as 
"int A") should be lowercase. 

Now let's look at an example of shadowing:

    public class Shadow {
        int a;
        int b;
    
        // parameters a/b shadow instance variables a/b
    
        public Shadow(int a, int b) {
    
            // set parameter equal to itself
    
            a = a;
    
            // set instance variable b equal to parameter b
    
            this.b = b;
        }
    
        public static void main(String args[]) {
            Shadow s = new Shadow(37, 47);
            System.out.println("a = " + s.a);
            System.out.println("b = " + s.b);
        }
    }
    
When your run Shadow, you should see:

    a = 0
    b = 47
   
One place shadowing comes up is when you have field names and
parameter names that are the same, and you want to use the
parameters to set the fields:

    int a;

    public void f(int a) {
        a = a;
    }

This doesn't work, because the parameter "a" shadows the field "a",
that is, the parameter name blocks access via a simple name to the
field name. You can get around this problem by saying:

    this.a = a;

which means "set field a to parameter a". Whether this style of
usage is desirable or not depends on your particular biases; one
point in its favor is that you don't have to invent parameter names
like "a1" or "_a".

The second example is one that illustrates overriding:

    class A {
        void f() {
            System.out.println("A.f");
        }
    }
    
    public class Override extends A {
    
        // instance method f overrides instance method A.f
    
        void f() {
            System.out.println("Override.f");
        }
    
        void g() {
            // call Override.f
    
            f();
    
            // call A.f
    
            super.f();
        }
    
        public static void main(String args[]) {
            Override o = new Override();
            o.g();
        }
    }
    
When you run Override, you should see:

    Override.f
    A.f

In this example, the method Override.f overrides the method A.f. 
If you have an object of type Override, and call f, Override.f 
is called. However if you have an object of type A, A.f is called.
This approach is a standard part of object-oriented programming. 
For example, java.lang.Object declares a hashCode method, but
subclasses, such as String, provide an overriding version of the
method. The overriding version is tailored to the particular type 
of data represented by the class.

You can call the superclass method by using the notation:

    super.f();

A third example is that of hiding:

    class A {
        static void f() {
            System.out.println("A.f");
        }
        void g() {
            System.out.println("A.g");
        }
    }
    
    public class Hide extends A {
        static void f() {
            System.out.println("Hide.f");
        }
        void g() {
            System.out.println("Hide.g");
        }
        public static void main(String args[]) {
            A aref = new Hide();
    
            // call A.f()
    
            aref.f();
    
            // call Hide.g()
    
            aref.g();
        }
    }

When you run Hide, you should see:

    A.f
    Hide.g

In this example, Hide.f hides A.f, and Hide.g overrides A.g. 
One way of seeing the difference between hiding and overriding 
is to note that overriding applies to regular instance methods; 
the actual method that is called is determined at run time 
based on the type of the object (a so-called "virtual function").
This sort of dynamic lookup does not happen for static methods 
or for fields. For example, in this code:

    class A {
        int x = 37;
        void f() {
            System.out.println("A.f");
        }
    }
    
    public class Lookup extends A {
        int x = 47;
        void f() {
            System.out.println("Lookup.f");
        }
        public static void main(String args[]) {
            A aref = new Lookup();
    
            // call Lookup.f

            aref.f();

            // display A.x
    
            System.out.println(aref.x);
        }
    }

the method reference through "aref" results in Lookup.f being
called, but the field reference obtains A.x. Or to say it another
way, the actual class of an object determines which instance method
is called. But for fields, the type of the reference is used 
(here it's aref, of type A). When you run Lookup, you should see:

    Lookup.f
    37

The final example illustrates the idea of obscuring:

    class A {
        static int MIN_PRIORITY = 59;
    };
    
    public class Obscure {
        static A Thread;
    
        public static void main(String args[]) {
    
            // print value of class variable Thread.MIN_PRIORITY
    
            System.out.println(Thread.MIN_PRIORITY);
    
            // print value of java.lang.Thread.MIN_PRIORITY
    
            System.out.println(java.lang.Thread.MIN_PRIORITY);
        }
    }
    
When you run Obscure, you should see:

    59
    1

Consider the first print statement in this example, that prints:

    Thread.MIN_PRIORITY

There are two possible meanings for this expression: either the
static field MIN_PRIORITY in the class java.lang.Thread, or the
static field MIN_PRIORITY in the class variable Thread in class
Obscure.

The Java language specification says that in this situation,
variables are chosen in preference to types. So the static field 
in the class variable Thread is printed. You can work around this 
by fully qualifying the class name Thread, as the example shows:

    java.lang.Thread.MIN_PRIORITY

This code example is very sneaky, and represents a poor coding 
style.

For more information about shadowing, see section 6.3.2, 
"Obscured Declarations," section 7.5.2, "Type-Import-on-Demand 
Declaration," section 8.4.6, Inheritance, Overriding, and Hiding," 
section 8.4.8.5, "Example: Invocation of Hidden Class Methods," 
and section 14.4.3, "Shadowing of Names by Local variables" 
in "The Java Language Specification Second Edition" by Gosling, 
Joy, Steele, and Bracha (http://java.sun.com/docs/books/jls/).

.  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .

- NOTE

Sun respects your online time and privacy. The Java Developer 
Connection mailing lists are used for internal Sun Microsystems(tm) 
purposes only. You have received this email because you elected 
to subscribe. To unsubscribe, go to the Subscriptions page 
(http://developer.java.sun.com/subscription/), uncheck the 
appropriate checkbox, and click the Update button.


- SUBSCRIBE

To subscribe to a JDC newsletter mailing list, go to the 
Subscriptions page (http://developer.java.sun.com/subscription/), 
choose the newsletters you want to subscribe to, and click Update.


- FEEDBACK
Comments? Send your feedback on the JDC Tech Tips to:

jdc-webmaster@sun.com


- ARCHIVES
You'll find the JDC Tech Tips archives at:

http://java.sun.com/jdc/TechTips/index.html


- COPYRIGHT
Copyright 2000 Sun Microsystems, Inc. All rights reserved.
901 San Antonio Road, Palo Alto, California 94303 USA.

This document is protected by copyright. For more information, see:

http://java.sun.com/jdc/copyright.html


This issue of the JDC Tech Tips is written by Glen McCluskey.

JDC Tech Tips 
October 10, 2000












