Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-1232633

fp.bugs 2975 either Container.locate() is off by one object in width and height

    XMLWordPrintable

    Details

    • Subcomponent:
    • Resolved In Build:
      1.0.2
    • CPU:
      x86, sparc
    • OS:
      solaris_2.5, windows_nt
    • Verification:
      Verified

      Description

      All platforms: Container.locate(int x, int y) makes the coordinates that it sends to
      Component.inside(int x, int y) relative to the component, not itself.
      Component.inside(int x, int y) assumes that the coordinates that it receives are
      relative to its parent, and so converts them to be relative to itself.

      The result is that on a 3 X 3 grid, you can never locate the items on the last column
      or row.

      Steps to reproduce
      Compile and run the attached code
      Move the mouse over each of the buttons
      // Note the output to System.out, the program never locates the last button
      // in the applet

      import java.awt.*;
      import java.applet.Applet;

      public class InsideTest extends Applet
      {
          private final int ROWS = 4;
          private final int COLS = 3;
          public void init()
          {

             setLayout( new GridLayout(ROWS, COLS) );
             for (int i = 1; i <= ROWS * COLS; ++i )
             {
                add( new Button( Integer.toString( i ) ) );
             }
             resize(300, 300);
          }

          public boolean mouseMove(Event ev, int x, int y)
          {
             Component comp = locate(x, y);
             System.out.println("Coordinates: X: " + x + " Y: " + y);
             System.out.println("Component: " + comp);
             return super.mouseMove(ev, x, y);
          }


          public static void main(String argv[])
          {
             AppletFrame.startApplet("InsideTest", "Component.inside() Test", argv);
          }


      /* I'm commenting this out to make it easier to reproduce the problem.
       * Once you've reproduced the problem, try using this version of
       * locate.
       *
          public Component locate(int x, int y)
          {
             if ( !inside(x, y) )
             {
                return null;
             }
             for (int i = 0 ; i < this.countComponents() ; i++)
             {
                Component comp = this.getComponent(i);
                if ( (comp != null) && comp.inside(x, y) )
                {
                   return comp;
                }
             }

             return this;
          } // end locate()

       *
       * End of commented out method locate()
       */

      } // end class InsideTest

      /* Generic Applet to Application Frame
       * @(#)AppletFrame.java 1.4 02 Dec 1995 15:28:07
       * @author Kevin A. Smith
       *
       * Here's a sample main() function that you can add to your applet class:
       *
       * public static void main(String args[])
       * {
       * AppletFrame.startApplet( <ClassName>, "Application Title");
       * }
       *
       * The class AppletFrame provides a simple AWT Frame window for running
       * applications.
       *
       */

      import java.awt.Frame;
      import java.awt.Event;
      import java.awt.Dimension;
      import java.applet.Applet;

      // Applet to Application Frame window
      class AppletFrame extends Frame
      {

          public static void startApplet(String className,
                                         String title,
                                         String args[])
          {
             // local variables
             Applet a;
             Dimension appletSize;

             try
             {
                // create an instance of your applet class
                a = (Applet) Class.forName(className).newInstance();
             }
             catch (ClassNotFoundException e) { return; }
             catch (InstantiationException e) { return; }
             catch (IllegalAccessException e) { return; }

             // initialize the applet
             a.init();
             a.start();
        
             // create new application frame window
             AppletFrame f = new AppletFrame(title);
        
             // add applet to frame window
             f.add("Center", a);
        
             // resize frame window to fit applet
             // assumes that the applet sets its own size
             // otherwise, you should set a specific size here.
             appletSize = a.size();
             f.pack();
             f.resize(appletSize);

             // show the window
             f.show();
        
          } // end startApplet()
        
        
          // constructor needed to pass window title to class Frame
          public AppletFrame(String name)
          {
             // call java.awt.Frame(String) constructor
             super(name);
          }

          // needed to allow window close
          public boolean handleEvent(Event e)
          {
             // Window Destroy event
             if (e.id == Event.WINDOW_DESTROY)
             {
                // exit the program
                System.exit(0);
                return true;
             }
             
             // it's good form to let the super class look at any
             // unhandled events
             return super.handleEvent(e);

          } // end handleEvent()

      } // end class AppletFrame

      The description field as copied from bug report 1244154 follows:

      From: Larry Liang <###@###.###>
      This does not look like form output to me.


      Hi,

      There is a bug in the Container.java class,

      Container.class line 349
      if ((comp != null) && comp.inside(x - comp.x, y - comp.y)){

      the inside() call should be:
      comp.inside(x, y)

      because it expects coordinates of the parent object, not relative to
      the current component. This bug caused deliverEvent() to deliver
      events to the wrong component. Thanks.

      Larry
      // This is an example program to show two bugs in AWT:
      // The Container.locate() function and
      // the Component.inside() function
      //
      // Container.locate(x, y) is supposed to return the component where the
      // (x, y) coordinate falls. But in the call to comp.inside(), it incorrectly
      // subtracted the location x and y value from the (x, y) parameter
      // respectively, and causes the component returned by the locate function
      // to be incorrect.
      //
      // Component.inside(x, y) is supposed to return true if the (x, y) point
      // is inside the component, and false otherwise. But it fails to check
      // if the (x, y) is less than the left edge and top edge. Therefore if
      // the x < location().x or y < location().y, it still returns true.
      //
      // Usage:
      // start the applet
      // click in any one of the box
      // The output should be:
      // print the current box number
      // print the box number to the right of current box
      // iterate through all components of the parent, and
      // print the box number of all those that have inside(x,y)
      // returning a true value. If the inside function is
      // correct, there should only be one box, the current box.
      //
      // Fix:
      // In file "Container.java" line 349, replace:
      // if ((comp != null) && comp.inside(x - comp.x, y - comp.y)) {
      // with:
      // if ((comp != null) && comp.inside(x, y)) {
      //
      // In file "Component.java" line 804, replace:
      // return (x >= 0) && ((x-this.x) < width) && (y >= 0) && ((y-this.y) < height);
      // with:
      // return ((x-this.x) >= 0) && ((x-this.x) < width) && ((y-this.y) >= 0) && ((y-this.y) < height);
      //

      import java.awt.*;
      import java.applet.*;

      public class awtbug extends Applet {
         static int total = 9;

         public awtbug() {
            setLayout(new GridLayout(1, total));
            for(int i = 0; i < total; i++) {
               add(new TestButton(i));
            }
         }
      }

      class TestButton extends Canvas {
         public TestButton(int num) {
            this.num = num;
         }

         public void paint(Graphics g) {
            g.drawRect(0, 0, size().width - 2, size().height - 2);
            g.drawString(Integer.toString(num), size().width / 2,
                         size().height / 2);
         }

         public boolean mouseDown(Event e, int x, int y) {
            identify();
            Container parent = getParent();
            if(num < awtbug.total - 1) {
               e.translate(location().x, location().y);
               TestButton sibling = (TestButton) parent.locate(e.x+size().width, e.y);
               System.out.print("My right hand button is: ");
               sibling.identify();
            }

            System.out.println("("+e.x+","+e.y+") is in the following boxes:");
            int cnt = parent.countComponents();
            for(int i = 0; i < cnt; i++) {
               TestButton box = (TestButton) parent.getComponent(i);
               if(box.inside(e.x, e.y)) {
                  box.identify();
               }
            }

            return(false);
         }

         public void identify() {
            System.out.println("Button " + num);
         }

         int num;
      }

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              amfowler Anne Fowler (Inactive)
              Reporter:
              kasmithsunw Kevin Smith (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: