TileSet.java
  1  // HTMLParser Library $Name: v1_6_20060319 $ - A java-based parser for HTML
  2  // http://sourceforge.org/projects/htmlparser
  3  // Copyright (C) 2003 Derrick Oswald
  4  //
  5  // Revision Control Information
  6  //
  7  // $Source: /cvsroot/htmlparser/htmlparser/src/org/htmlparser/lexerapplications/thumbelina/TileSet.java,v $
  8  // $Author: derrickoswald $
  9  // $Date: 2004/07/31 16:42:30 $
 10  // $Revision: 1.2 $
 11  //
 12  // This library is free software; you can redistribute it and/or
 13  // modify it under the terms of the GNU Lesser General Public
 14  // License as published by the Free Software Foundation; either
 15  // version 2.1 of the License, or (at your option) any later version.
 16  //
 17  // This library is distributed in the hope that it will be useful,
 18  // but WITHOUT ANY WARRANTY; without even the implied warranty of
 19  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 20  // Lesser General Public License for more details.
 21  //
 22  // You should have received a copy of the GNU Lesser General Public
 23  // License along with this library; if not, write to the Free Software
 24  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 25  //
 26  
 27  package org.htmlparser.lexerapplications.thumbelina;
 28  
 29  import java.awt.Rectangle;
 30  import java.util.Enumeration;
 31  import java.util.Vector;
 32  
 33  /**
 34   * Class to track picture regions.
 35   */
 36  public class TileSet
 37  /*
 38      extends
 39          java.awt.Canvas
 40      implements
 41          java.awt.event.ActionListener,
 42          java.awt.event.MouseListener,
 43          java.awt.event.WindowListener
 44  */
 45  {
 46      /**
 47       * The list of Pictures.
 48       */
 49      protected Vector mRegions;
 50  
 51      /**
 52       * Construct a tile set.
 53       */
 54      public TileSet ()
 55      {
 56          mRegions = new Vector ();
 57      }
 58  
 59      /**
 60       * Get the number of tiles in this collection.
 61       * @return The number of pictures showing.
 62       * Note that the same image and URL may be showing
 63       * (different pieces) in several locations.
 64       */
 65      public int getSize ()
 66      {
 67          return (mRegions.size ());
 68      }
 69  
 70      /**
 71       * Get the list of pictures.
 72       * @return An enumeration over the picture objects in this set.
 73       */
 74      public Enumeration getPictures ()
 75      {
 76          return (mRegions.elements ());
 77      }
 78  
 79      /**
 80       * Add a single picture to the list.
 81       * @param r The picture to add.
 82       */
 83      public void add (final Picture r)
 84      {
 85          Vector regions; // this will be the new set
 86          Enumeration e;
 87          Picture rover;
 88          Rectangle intersection;
 89          Vector splits;
 90          Enumeration frags;
 91  
 92          regions = new Vector ();
 93          for (e = getPictures (); e.hasMoreElements (); )
 94          {
 95              rover = (Picture)e.nextElement ();
 96              if (rover.intersects (r))
 97              {
 98                  intersection = rover.intersection (r);
 99                  if (!intersection.equals (rover))
100                  {
101                      // incoming lies completely within the existing picture
102                      // or touches the existing picture somehow
103                      splits = split (r, rover, false);
104                      for (frags = splits.elements (); frags.hasMoreElements (); )
105                          regions.addElement (frags.nextElement ());
106                  }
107                  else
108                      // incoming covers existing... drop the existing picture
109                      // but be sure to release the image memory
110                      rover.setImage (null);
111              }
112              else
113                  // no conflict, keep the existing
114                  regions.addElement (rover);
115          }
116          regions.addElement (r);
117          mRegions = regions;
118      }
119  
120      /**
121       * Split the large picture.
122       * Strategy: split horizontally (full width strips top and bottom).
123       * NOTE: top and bottom make sense only in terms of AWT coordinates.
124       * @param small The incoming picture.
125       * @param large The encompassing picture. The attributes of this one
126       * are propagated to the fragments.
127       * @param keep If <code>true</code>, the center area is kept,
128       * otherwise discarded.
129       * @return The fragments from the large picture.
130       */
131      private Vector split (
132          final Picture small,
133          final Picture large,
134          final boolean keep)
135      {
136          Picture m;
137          Vector ret;
138  
139          ret = new Vector ();
140  
141          if (large.intersects (small))
142          {
143              Rectangle intersection = large.intersection (small);
144  
145              // if tops don't match split off the top
146              if ((intersection.y + intersection.height)
147                  != (large.y + large.height))
148              {
149                  m = new Picture (large);
150                  m.y = (intersection.y + intersection.height);
151                  m.height = (large.y + large.height) - m.y;
152                  ret.addElement (m);
153              }
154  
155              // if left sides don't match make a left fragment
156              if (intersection.x != large.x)
157              {
158                  m = new Picture (large);
159                  m.y = intersection.y;
160                  m.width = intersection.x - large.x;
161                  m.height = intersection.height;
162                  ret.addElement (m);
163              }
164  
165              // the center bit
166              if (keep)
167              {
168                  m = new Picture (large);
169                  m.x = intersection.x;
170                  m.y = intersection.y;
171                  m.width = intersection.width;
172                  m.height = intersection.height;
173                  ret.addElement (m);
174              }
175  
176              // if right sides don't match make a right fragment
177              if ((intersection.x + intersection.width)
178                  != (large.x + large.width))
179              {
180                  m = new Picture (large);
181                  m.x = intersection.x + intersection.width;
182                  m.y = intersection.y;
183                  m.width = (large.x + large.width) - m.x;
184                  m.height = intersection.height;
185                  ret.addElement (m);
186              }
187  
188              // if bottoms don't match split off the bottom
189              if (intersection.y != large.y)
190              {
191                  m = new Picture (large);
192                  m.height = (intersection.y - large.y);
193                  ret.addElement (m);
194              }
195          }
196  
197          return (ret);
198      }
199  
200      /**
201       * Find the Picture at position x,y
202       * @param x The x coordinate of the point to examine.
203       * @param y The y coordinate of the point to examine.
204       * @return The picture at that point, or <code>null</code>
205       * if there are none.
206       */
207      public Picture pictureAt (final int x, final int y)
208      {
209          Picture m;
210          Picture ret;
211  
212          ret = null;
213  
214          for (int i = 0; (null == ret) && (i < mRegions.size ()); i++)
215          {
216              m = (Picture)mRegions.elementAt (i);
217              if (m.contains (x, y))
218                  ret = m;
219          }
220  
221          return (ret);
222      }
223  
224      /**
225       * Move the given picture to the top of the Z order.
226       * @param picture The picture to add.
227       */
228      public void bringToTop (final Picture picture)
229      {
230          Picture m;
231          Picture ret;
232  
233          ret = null;
234  
235          for (int i = 0; (null == ret) && (i < mRegions.size ()); )
236          {
237              m = (Picture)mRegions.elementAt (i);
238              if (picture.same (m))
239                  mRegions.removeElementAt (i);
240              else
241                  i++;
242          }
243          add (picture);
244  
245      }
246  
247  //    //
248  //    // Unit test.
249  //    //
250  //
251  //    // and need to add:
252  //    extends
253  //        java.awt.Canvas
254  //    implements
255  //        java.awt.event.ActionListener,
256  //        java.awt.event.MouseListener,
257  //        java.awt.event.WindowListener
258  //    // to the class definition
259  //
260  //    boolean mVerbose;
261  //    int mCounter;
262  //    java.awt.Point origin;
263  //    Rectangle last;
264  //    int type;
265  //
266  //  static java.awt.MenuBar menuMain;
267  //  static java.awt.Menu Options;
268  //  static java.awt.MenuItem repeat;
269  //  static java.awt.MenuItem clear;
270  //    static java.awt.TextField status;
271  //
272  //    // checks if adding the rectangle causes an overlap
273  //    boolean checkAdd (Rectangle r, Vector v)
274  //    {
275  //        Enumeration e;
276  //        boolean ret;
277  //        ret = false;
278  //
279  //        for (e = v.elements (); !ret && e.hasMoreElements (); )
280  //            ret = r.intersects ((Rectangle)e.nextElement ());
281  //
282  //        return (ret);
283  //    }
284  //
285  //    void paintwait ()
286  //    {
287  //        java.awt.Graphics g = getGraphics ();
288  //        if (null != g)
289  //            paint (g);
290  //        Thread.yield ();
291  //        try
292  //        {
293  //            Thread.sleep (1000);
294  //        }
295  //        catch (Exception exception)
296  //        {
297  //        }
298  //    }
299  //
300  //    void add ()
301  //    {
302  //        if (null != last)
303  //        {
304  //            Picture m = new Picture (last);
305  //            try
306  //            {
307  //                m.setURL (new URL ("http://localhost/image#" + mCounter++));
308  //            }
309  //            catch (java.net.MalformedURLException murle)
310  //            {
311  //                murle.printStackTrace ();
312  //            }
313  //            this.add (m);
314  //            repaint ();
315  //        }
316  //    }
317  //
318  //    //
319  //    // WindowListener interface
320  //    //
321  //    public void windowOpened (java.awt.event.WindowEvent e) {}
322  //    public void windowClosing (java.awt.event.WindowEvent e)
323  //    {
324  //        System.exit (0);
325  //    }
326  //    public void windowClosed (java.awt.event.WindowEvent e) {}
327  //    public void windowIconified (java.awt.event.WindowEvent e) {}
328  //    public void windowDeiconified (java.awt.event.WindowEvent e) {}
329  //    public void windowActivated (java.awt.event.WindowEvent e) {}
330  //    public void windowDeactivated (java.awt.event.WindowEvent e) {}
331  //
332  //    //
333  //  // ActionListener interface
334  //  //
335  //  public void actionPerformed (java.awt.event.ActionEvent event)
336  //  {
337  //      Object object = event.getSource();
338  //        if (object == repeat)
339  //            add ();
340  //        else if (object == clear)
341  //        {
342  //            mRegions = new Vector ();
343  //            repaint ();
344  //        }
345  //    }
346  //
347  //    //
348  //    // MouseListener Interface
349  //    //
350  //
351  //    public void mouseClicked (java.awt.event.MouseEvent event)
352  //    {
353  //        if (mVerbose)
354  //            System.out.println ("DrawTarget.mouseClicked " + event);
355  //    }
356  //
357  //  public void mouseReleased (java.awt.event.MouseEvent event)
358  //    {
359  //        if (mVerbose)
360  //            System.out.println ("DrawTarget.mouseReleased " + event);
361  //        if (null != origin)
362  //        {
363  //            last = new Rectangle (
364  //                Math.min (origin.x, event.getX ()),
365  //                Math.min (origin.y, event.getY ()),
366  //                Math.abs (event.getX () - origin.x),
367  //                Math.abs (event.getY () - origin.y));
368  //            add ();
369  //            origin = null;
370  //        }
371  //    }
372  //
373  //  public void mouseEntered (java.awt.event.MouseEvent event)
374  //    {
375  //        if (mVerbose)
376  //            System.out.println ("DrawTarget.mouseEntered " + event);
377  //    }
378  //
379  //  public void mouseExited (java.awt.event.MouseEvent event)
380  //    {
381  //        if (mVerbose)
382  //            System.out.println ("DrawTarget.mouseExited " + event);
383  //    }
384  //
385  //    public void mousePressed (java.awt.event.MouseEvent event)
386  //    {
387  //        if (mVerbose)
388  //            System.out.println ("DrawTarget.mousePressed " + event);
389  //        if (event.isMetaDown ())
390  //        {
391  //            status.setText (getDetails (event.getX (), event.getY ()));
392  //        }
393  //        else
394  //            origin = new java.awt.Point (event.getX (), event.getY ());
395  //    }
396  //
397  //    public void update (java.awt.Graphics graphics)
398  //    {
399  //        paint (graphics);
400  //    }
401  //
402  //    static final java.awt.Color[] mColours =
403  //    {
404  //        java.awt.Color.blue,
405  //        java.awt.Color.cyan,
406  //        java.awt.Color.gray,
407  //        java.awt.Color.green,
408  //        java.awt.Color.orange,
409  //        java.awt.Color.pink,
410  //        java.awt.Color.red,
411  //        java.awt.Color.yellow,
412  //        java.awt.Color.lightGray,
413  //        java.awt.Color.darkGray,
414  //    };
415  //
416  //    public void paint (java.awt.Graphics graphics)
417  //    {
418  //        java.awt.Dimension size = getSize ();
419  //        graphics.setColor (getBackground ());
420  //        graphics.fillRect (0, 0, size.width + 1, size.height + 1);
421  //
422  //        if (0 == mRegions.size ())
423  //        {
424  //            graphics.setColor (getForeground ());
425  //            graphics.drawString (
426  //                "Click and drag to create a picture.", 10, 20);
427  //            graphics.drawString (
428  //                "Right click a picture for details.", 10, 40);
429  //        }
430  //        else
431  //        {
432  //            Enumeration e = getPictures ();
433  //            while (e.hasMoreElements ())
434  //            {
435  //                Picture m = (Picture)e.nextElement ();
436  //                String url = m.getURL ().toExternalForm ();
437  //                int n = url.indexOf ('#');
438  //                n = Integer.parseInt (url.substring (n + 1))
439  //                java.awt.Color colour = mColours[n % mColours.length];
440  //                graphics.setColor (colour);
441  //                graphics.fillRect (m.x, m.y, m.width + 1, m.height + 1);
442  //                graphics.setColor (java.awt.Color.black);
443  //                graphics.drawRect (m.x, m.y, m.width, m.height);
444  //            }
445  //            checkOverlap (graphics);
446  //        }
447  //    }
448  //
449  //    void checkOverlap (java.awt.Graphics graphics)
450  //    {
451  //        Picture m;
452  //        Picture _m;
453  //        Rectangle r;
454  //
455  //        graphics.setColor (java.awt.Color.magenta);
456  //        for (int i = 0; i < mRegions.size (); i++)
457  //        {
458  //            m = (Picture)mRegions.elementAt (i);
459  //            for (int j = i + 1; j < mRegions.size (); j++)
460  //            {
461  //                _m = (Picture)mRegions.elementAt (j);
462  //                if (m.intersects (_m))
463  //                {
464  //                    r = m.intersection (_m);
465  //                    System.out.println (
466  //                        "overlap ("
467  //                        + r.x
468  //                        + ","
469  //                        + r.y
470  //                        + ") ("
471  //                        + (r.x + r.width)
472  //                        + ","
473  //                        + (r.y + r.height)
474  //                        + ")");
475  //                    graphics.fillRect (r.x, r.y, r.width + 1, r.height + 1);
476  //                }
477  //            }
478  //        }
479  //    }
480  //
481  //    String getDetails (int x, int y)
482  //    {
483  //        Picture m;
484  //        String ret;
485  //
486  //        ret = null;
487  //
488  //        // find the Picture
489  //        for (int i = 0; (null == ret) && (i < mRegions.size ()); i++)
490  //        {
491  //            m = (Picture)mRegions.elementAt (i);
492  //            if (m.contains (x, y))
493  //                ret = m.toString ();
494  //        }
495  //        if (null == ret)
496  //            ret = "";
497  //
498  //        return (ret);
499  //    }
500  //
501  //    public static void main (String[] args)
502  //    {
503  //        java.awt.Frame frame;
504  //
505  //        frame = new java.awt.Frame ();
506  //        frame.setSize (400,400);
507  //      menuMain = new java.awt.MenuBar();
508  //      Options = new java.awt.Menu ("Options");
509  //        repeat = new java.awt.MenuItem("Repeat");
510  //      Options.add (repeat);
511  //      clear = new java.awt.MenuItem("Clear");
512  //      Options.add (clear);
513  //
514  //      menuMain.add (Options);
515  //      frame.setMenuBar (menuMain);
516  //
517  //        java.awt.Insets insets = frame.getInsets ();
518  //
519  //        TileSet buffy = new TileSet ();
520  //        buffy.setLocation (insets.left + 10, insets.top + 10);
521  //        buffy.setBackground (java.awt.Color.lightGray.brighter ());
522  //        buffy.setVisible (true);
523  //
524  //        frame.add (buffy, "Center");
525  //        status = new java.awt.TextField ();
526  //        frame.add (status, "South");
527  //
528  //        frame.addWindowListener (buffy);
529  //        buffy.addMouseListener (buffy);
530  //      repeat.addActionListener (buffy);
531  //      clear.addActionListener (buffy);
532  //
533  //        frame.setVisible (true);
534  //
535  //    }
536  }
537  
538  /*
539   * Revision Control Modification History
540   *
541   * $Log: TileSet.java,v $
542   * Revision 1.2  2004/07/31 16:42:30  derrickoswald
543   * Remove unused variables and other fixes exposed by turning on compiler warnings.
544   *
545   * Revision 1.1  2003/09/21 18:20:56  derrickoswald
546   * Thumbelina
547   * Created a lexer GUI application to extract images behind thumbnails.
548   * Added a task in the ant build script - thumbelina - to create the jar file.
549   * You need JDK 1.4.x to build it.  It can be run on JDK 1.3.x in crippled mode.
550   * Usage: java -Xmx256M thumbelina.jar [URL]
551   *
552   *
553   */