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 */