View Javadoc
1 /*** 2 * Created by IntelliJ IDEA. 3 * User: Lennart 4 * Date: 26-aug-2003 5 * Time: 14:54:33 6 */ 7 package comics.gui; 8 9 import comics.gui.progressbars.DefaultProgressBar; 10 11 import javax.swing.*; 12 import java.awt.*; 13 import java.awt.event.*; 14 import java.io.File; 15 import java.io.InputStream; 16 import java.io.IOException; 17 import java.util.*; 18 19 /* 20 * CVS information: 21 * 22 * $Revision: 1.5 $ 23 * $Date: 2003/12/13 16:54:53 $ 24 */ 25 26 /*** 27 * This class embodies a JPanel one can use to draw a picture in. 28 * 29 * @author Lennart Martens 30 */ 31 public class PicturePanel extends JPanel { 32 33 /*** 34 * This JLabel will hold the picture. 35 */ 36 private JLabel lblPicture = null; 37 38 /*** 39 * Contains the currently displayed image. 40 */ 41 private ImageIcon imgPicture = null; 42 43 /*** 44 * The label with the caption for the picture. 45 */ 46 private JLabel lblCaption = null; 47 48 /*** 49 * The parent folder for all the comics. 50 */ 51 private String iParentFolder = null; 52 53 /*** 54 * The Vector with all the files for the comic. 55 */ 56 private Vector allFiles = new Vector(); 57 58 /*** 59 * This HashMap contains all the available comics. 60 */ 61 private HashMap comics = null; 62 63 /*** 64 * The index of the comic file in the 'allFiles' Vector, 65 * that is currently on view. 66 */ 67 private int index = 0; 68 69 /*** 70 * The progressbar, if desired. 71 */ 72 private DefaultProgressBar progress = null; 73 74 /*** 75 * A dummy frame for the progressbar. 76 */ 77 private JFrame progressFrame = null; 78 79 /*** 80 * The combobox with all the available comics. 81 */ 82 private JComboBox cmbComics = new JComboBox(); 83 84 /*** 85 * This JButton selects the comic currently in the 86 * cmbComics for display. 87 */ 88 private JButton btnSelectComic = new JButton("Select"); 89 90 /*** 91 * This JCheckbox allows automatic frame size changes whenever the comic does not fit the current 92 * screen. 93 */ 94 private JCheckBox chkAutoResize = new JCheckBox("Adjust screen size to comic"); 95 96 /*** 97 * The button to navigate to the first comic. 98 */ 99 private JButton first = new JButton("First"); 100 /*** 101 * The button to navigate to the last comic. 102 */ 103 private JButton last = new JButton("Last"); 104 /*** 105 * The button to navigate to the next comic. 106 */ 107 private JButton next = new JButton("Next"); 108 /*** 109 * The button to navigate to the previous comic. 110 */ 111 private JButton previous = new JButton("Previous"); 112 /*** 113 * The button to navigate to a random comic. 114 */ 115 private JButton random = new JButton("Random"); 116 117 /*** 118 * This button allows the selection of a parent folder. 119 */ 120 private JButton chooseFolder = new JButton("Choose parent folder..."); 121 122 /*** 123 * This variable shows whether or not a comic was selected already. 124 */ 125 private boolean somethingSelected = false; 126 127 /*** 128 * Reference to the parent frame so that we might call resize on it when its initialized. 129 */ 130 private JFrame iParentFrame = null; 131 132 /*** 133 * This variable caches the maximum height of the display which is used when 134 * auto-adjusting window size to fit comic. If the window size has to be adjusted outside of 135 * max height or width, no resizing is done. 136 */ 137 private int iMaxHeight = 0; 138 139 /*** 140 * This variable caches the maximum width of the display which is used when 141 * auto-adjusting window size to fit comic. If the window size has to be adjusted outside of 142 * max height or width, no resizing is done. 143 */ 144 private int iMaxWidth = 0; 145 146 /*** 147 * The properties file to convert ucomics comic designations 148 * into full names. 149 */ 150 private static Properties conversion = null; 151 152 /*** 153 * This constructor takes care of creating the GUI. 154 */ 155 public PicturePanel() { 156 JPanel comp = new JPanel(new BorderLayout(0, 5)); 157 158 lblPicture = new JLabel(); 159 lblPicture.setToolTipText("Click left button to enlarge, right button to shrink."); 160 lblPicture.addMouseListener(new MouseAdapter() { 161 /*** 162 * Invoked when a mouse button has been pressed on a component. 163 */ 164 public void mousePressed(MouseEvent e) { 165 if(e.getButton() == MouseEvent.BUTTON2 || e.getButton() == MouseEvent.BUTTON3) { 166 rescalePicture(-1.5); 167 } else { 168 rescalePicture(1.5); 169 } 170 } 171 }); 172 lblPicture.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR)); 173 lblPicture.setHorizontalAlignment(JLabel.CENTER); 174 lblPicture.setVerticalAlignment(JLabel.CENTER); 175 lblPicture.setVerticalTextPosition(JLabel.CENTER); 176 lblPicture.setHorizontalTextPosition(JLabel.CENTER); 177 comp.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createLoweredBevelBorder(), BorderFactory.createEmptyBorder(5,5,5,5))); 178 179 lblCaption = new JLabel(); 180 lblCaption.setHorizontalAlignment(JLabel.CENTER); 181 lblCaption.setHorizontalTextPosition(JLabel.CENTER); 182 183 comp.add(new JScrollPane(lblPicture), BorderLayout.CENTER); 184 comp.add(lblCaption, BorderLayout.SOUTH); 185 186 JPanel jpanIntermediate = new JPanel(); 187 jpanIntermediate.add(cmbComics); 188 btnSelectComic.setMnemonic(KeyEvent.VK_S); 189 btnSelectComic.addActionListener(new ActionListener() { 190 public void actionPerformed(ActionEvent e) { 191 String key = (String)cmbComics.getSelectedItem(); 192 String name = (String)comics.get(key); 193 somethingSelected = true; 194 setRootFolder(iParentFolder + name); 195 } 196 }); 197 jpanIntermediate.add(btnSelectComic); 198 chkAutoResize.setSelected(true); 199 jpanIntermediate.add(chkAutoResize); 200 201 202 this.setLayout(new BorderLayout(0, 10)); 203 this.add(this.getButtons(), BorderLayout.SOUTH); 204 this.add(comp, BorderLayout.CENTER); 205 this.add(jpanIntermediate, BorderLayout.NORTH); 206 207 208 // Load the conversion properties file. 209 try { 210 if(conversion == null) { 211 conversion = new Properties(); 212 InputStream is = this.getClass().getClassLoader().getResourceAsStream("comics.properties"); 213 if(is != null) { 214 conversion.load(is); 215 String folder = conversion.getProperty("rootfolder"); 216 File test = new File(folder); 217 if(!test.exists()) { 218 throw new IOException("Unable to find specified folder!"); 219 } 220 this.setParentFolder(folder); 221 is.close(); 222 } 223 } 224 } catch(Exception e) { 225 // Let the user select the parent folder manually. 226 selectParentFolder(); 227 if(iParentFolder == null) { 228 System.exit(0); 229 } 230 } 231 } 232 233 /*** 234 * This constructor creates the GUI and keeps a reference to the parent frame which wan be used for resizing. 235 * 236 * @param aParent JFrame with the parent frame. 237 */ 238 public PicturePanel(JFrame aParent) { 239 this(); 240 this.iParentFrame = aParent; 241 // Also record the screen boundaries here. 242 Dimension screensize = Toolkit.getDefaultToolkit().getScreenSize(); 243 this.iMaxHeight = screensize.height; 244 this.iMaxWidth = screensize.width; 245 } 246 247 /*** 248 * This method allows the setting of a new picture on the panel. 249 * 250 * @param aFilename String with the filename for the picture to load. 251 */ 252 public void setPicture(String aFilename) { 253 this.imgPicture = new ImageIcon(aFilename, aFilename); 254 // See if we should check for resizing. 255 if(chkAutoResize.isSelected()){ 256 // Do the resize if necessary. 257 boolean resizeNecessary = false; 258 int height = 0; 259 int width = 0; 260 if(imgPicture.getIconHeight()+40 > lblPicture.getHeight()) { 261 resizeNecessary = true; 262 height = (imgPicture.getIconHeight()+40) - lblPicture.getHeight(); 263 } 264 if(imgPicture.getIconWidth()+40 > lblPicture.getWidth()) { 265 resizeNecessary = true; 266 width = (imgPicture.getIconWidth()+40) - lblPicture.getWidth(); 267 } 268 // Resize? And if so, do we have a the reference to the parent frame to resize it? 269 if(resizeNecessary && iParentFrame != null) { 270 int newHeight = iParentFrame.getHeight()+height; 271 int newWidth = iParentFrame.getWidth()+width; 272 // See if we are within screen limits. 273 if(newHeight < this.iMaxHeight && newWidth < this.iMaxWidth) { 274 iParentFrame.setSize(newWidth, newHeight); 275 } 276 } 277 } 278 lblPicture.setIcon(imgPicture); 279 lblCaption.setText(aFilename); 280 } 281 282 /*** 283 * This method allows the setting of a new picture on the panel. 284 * 285 * @param aFilename File with the filename for the picture to load. 286 */ 287 public void setPicture(File aFilename) { 288 try { 289 this.setPicture(aFilename.getCanonicalPath()); 290 } catch(Exception e) { 291 e.printStackTrace(); 292 } 293 } 294 295 /*** 296 * This method will rescale the picture according to the multiplication 297 * specified. If this is a negative multiplication, it will be converted into the 298 * (-1/x) form. EG., -4 becomes (-1/-4) = 0.25. 299 * 300 * @param times double with the scaling factor (if negative, becomes (-1/x) - see above. 301 */ 302 public void rescalePicture(double times) { 303 if(!checkSelected()) { 304 return; 305 } 306 if(times < 0) { 307 times = -1.0/times; 308 } 309 Image image = this.imgPicture.getImage(); 310 int width = image.getWidth(null); 311 int height = image.getHeight(null); 312 image = image.getScaledInstance((int)(width*times), (int)(height*times), Image.SCALE_SMOOTH); 313 imgPicture = new ImageIcon(image, imgPicture.getDescription()); 314 lblPicture.setIcon(imgPicture); 315 } 316 317 318 /*** 319 * This method takes a root path from which all pictures are read, and each of these can be displayed. 320 * 321 * @param aFolder String with the path for the root folder. 322 */ 323 public void setRootFolder(String aFolder) { 324 this.allFiles = new Vector(); 325 File root = new File(aFolder); 326 addContents(root); 327 // Sort. 328 Collections.sort(allFiles); 329 index = 0; 330 if(somethingSelected) { 331 this.setPicture((File)allFiles.get(index)); 332 previous.setEnabled(false); 333 } 334 } 335 336 /*** 337 * This method allows the setting of the parent folder for all the comics. 338 * 339 * @param aFolder String with the parent folder (the one above all the comments). 340 */ 341 public void setParentFolder(String aFolder) { 342 comics = new HashMap(); 343 this.iParentFolder = aFolder.trim(); 344 if(!iParentFolder.endsWith("//") || !iParentFolder.endsWith("/")) { 345 iParentFolder += "/"; 346 } 347 File[] files = new File(aFolder).listFiles(); 348 for(int i = 0; i < files.length; i++) { 349 File lFile = files[i]; 350 if(lFile.isDirectory()) { 351 String name = lFile.getName().trim(); 352 String key = name; 353 if(conversion.containsKey(name)) { 354 key = conversion.getProperty(name); 355 } 356 this.comics.put(key, name); 357 } 358 } 359 Object[] names = comics.keySet().toArray(); 360 Arrays.sort(names); 361 cmbComics.setModel(new DefaultComboBoxModel(names)); 362 } 363 364 /*** 365 * Main method is for testing purposes. 366 * 367 * @param args String[] with the start-up arguments. 368 */ 369 public static void main(String[] args) { 370 371 final JFrame tc = new JFrame("Comics!"); 372 tc.addWindowListener(new WindowAdapter() { 373 /*** 374 * Invoked when a window is in the process of being closed. 375 * The close operation can be overridden at this point. 376 */ 377 public void windowClosing(WindowEvent e) { 378 tc.dispose(); 379 System.exit(0); 380 } 381 }); 382 PicturePanel pp = new PicturePanel(tc); 383 tc.getContentPane().add(pp, BorderLayout.CENTER); 384 tc.setBounds(300, 300, 800, 400); 385 tc.setVisible(true); 386 } 387 388 /*** 389 * This method recurses through the parent directory and reads all the gif, jpeg and jpg 390 * files into a Vector. 391 * 392 * @param aFolder File with the root folder to recurse from. 393 */ 394 private void addContents(File aFolder) { 395 File[] list = aFolder.listFiles(); 396 progressFrame = new JFrame(); 397 progress = new DefaultProgressBar(progressFrame, "Loading comics", 0, list.length, "Loading from '" + aFolder.getName() + "'..."); 398 InnerRecursion ir = new InnerRecursion(list, progress); 399 progress.setSize(300, progress.getPreferredSize().height); 400 Thread t = new Thread(ir); 401 t.start(); 402 progress.setVisible(true); 403 progressFrame.dispose(); 404 // verify that we have found something. 405 // Otherwise signal the lack of selection via the somethingSelected boolean. 406 if(allFiles.size() == 0) { 407 JOptionPane.showMessageDialog(this, "No graphics files (.gif, .jpg or .jpeg) found in the specified path!", "No graphics files found!", JOptionPane.WARNING_MESSAGE); 408 somethingSelected = false; 409 } 410 } 411 412 /*** 413 * This methods generates the button panel for the application. 414 * 415 * @return JPanel with the buttons. 416 */ 417 private JPanel getButtons() { 418 // The buttonpanel. 419 JPanel jpanButtons = new JPanel(); 420 jpanButtons.setLayout(new BoxLayout(jpanButtons, BoxLayout.X_AXIS)); 421 422 // First button. 423 first.setMnemonic(KeyEvent.VK_F); 424 first.addActionListener(new ActionListener() { 425 public void actionPerformed(ActionEvent e) { 426 if(!checkSelected()) { 427 return; 428 } 429 index = 0; 430 setPicture((File)allFiles.get(index)); 431 previous.setEnabled(false); 432 if(!next.isEnabled()) { 433 next.setEnabled(true); 434 } 435 } 436 }); 437 438 // Last button. 439 last.setMnemonic(KeyEvent.VK_L); 440 last.addActionListener(new ActionListener() { 441 public void actionPerformed(ActionEvent e) { 442 if(!checkSelected()) { 443 return; 444 } 445 index = allFiles.size()-1; 446 setPicture((File)allFiles.get(index)); 447 next.setEnabled(false); 448 if(!previous.isEnabled()) { 449 previous.setEnabled(true); 450 } 451 } 452 }); 453 454 // Random button. 455 random.setMnemonic(KeyEvent.VK_R); 456 random.addActionListener(new ActionListener() { 457 public void actionPerformed(ActionEvent e) { 458 if(!checkSelected()) { 459 return; 460 } 461 index = (int)(Math.random()*allFiles.size()); 462 setPicture((File)allFiles.get(index)); 463 if(index > 0 && !previous.isEnabled()) { 464 previous.setEnabled(true); 465 } 466 if (index < allFiles.size()-1 && !next.isEnabled()) { 467 next.setEnabled(true); 468 } 469 } 470 }); 471 472 // Next button. 473 next.setMnemonic(KeyEvent.VK_N); 474 next.addActionListener(new ActionListener() { 475 public void actionPerformed(ActionEvent e) { 476 if(!checkSelected()) { 477 return; 478 } 479 if(index < allFiles.size()-1) { 480 index++; 481 setPicture((File)allFiles.get(index)); 482 if(!previous.isEnabled()) { 483 previous.setEnabled(true); 484 } 485 } else { 486 next.setEnabled(false); 487 } 488 } 489 }); 490 491 // Previous button. 492 previous.setMnemonic(KeyEvent.VK_P); 493 previous.addActionListener(new ActionListener() { 494 public void actionPerformed(ActionEvent e) { 495 if(!checkSelected()) { 496 return; 497 } 498 if(index > 0) { 499 index--; 500 setPicture((File)allFiles.get(index)); 501 if(!next.isEnabled()) { 502 next.setEnabled(true); 503 } 504 } else { 505 previous.setEnabled(false); 506 } 507 } 508 }); 509 510 // Select parent folder button. 511 chooseFolder.setMnemonic(KeyEvent.VK_C); 512 chooseFolder.addActionListener(new ActionListener() { 513 public void actionPerformed(ActionEvent e) { 514 selectParentFolder(); 515 } 516 }); 517 518 // Adding the buttons to the panel. 519 jpanButtons.add(Box.createHorizontalStrut(15)); 520 jpanButtons.add(chooseFolder); 521 jpanButtons.add(Box.createHorizontalGlue()); 522 jpanButtons.add(random); 523 jpanButtons.add(Box.createHorizontalStrut(5)); 524 jpanButtons.add(first); 525 jpanButtons.add(Box.createHorizontalStrut(5)); 526 jpanButtons.add(previous); 527 jpanButtons.add(Box.createHorizontalStrut(5)); 528 jpanButtons.add(next); 529 jpanButtons.add(Box.createHorizontalStrut(5)); 530 jpanButtons.add(last); 531 jpanButtons.add(Box.createHorizontalStrut(15)); 532 533 534 return jpanButtons; 535 } 536 537 /*** 538 * This method returns 'true' when some comic was selected, 539 * and displays a warning message and returns 'false' otherwise. 540 * 541 * @return boolean to indicate whether a comic was selected. 542 */ 543 private boolean checkSelected() { 544 if(!somethingSelected) { 545 JOptionPane.showMessageDialog(this, "No comic selected to perform requested operation on!", "No comic selected!", JOptionPane.WARNING_MESSAGE); 546 } 547 return this.somethingSelected ; 548 } 549 550 /*** 551 * This method pops up a GUI component (JFileChooser) where the user can select a parent folder. 552 */ 553 private void selectParentFolder() { 554 JFileChooser fc = new JFileChooser("/"); 555 fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 556 if(fc.showDialog(this, "Select folder") == JFileChooser.CANCEL_OPTION) { 557 return; 558 } 559 File f = fc.getSelectedFile(); 560 String parentDir = f.getAbsolutePath(); 561 this.setParentFolder(parentDir); 562 } 563 564 /*** 565 * Inner class for the recursive reading of the selected comic root folder. 566 */ 567 private class InnerRecursion implements Runnable { 568 569 /*** 570 * The list of files in the root folder. 571 */ 572 private File[] list = null; 573 574 /*** 575 * The progressbar. 576 */ 577 private DefaultProgressBar progress = null; 578 579 /*** 580 * This constructor takes the list of files in the root folder, as 581 * well as a progress bar. 582 * 583 * @param aList File[] with the listing of the root folder. 584 * @param aProgress DefaultProgressBar with the progressbar. 585 */ 586 public InnerRecursion(File[] aList, DefaultProgressBar aProgress) { 587 list = aList; 588 progress = aProgress; 589 } 590 591 /*** 592 * Run method for the thread. 593 */ 594 public void run() { 595 // Cycling through the root folder. 596 for(int i = 0; i < list.length; i++) { 597 // Set the progress and a new message. 598 progress.setValue(i); 599 progress.setMessage("Reading through " + list[i]); 600 // List all files. 601 File item = list[i]; 602 // If it's a directory, recurse, if it's a file with the 603 // correct extension, add it to the full list. 604 if(item.isDirectory()) { 605 this.recurse(item); 606 } else if(item.getName().endsWith(".gif") || item.getName().endsWith(".jpg") || item.getName().endsWith(".GIF") || item.getName().endsWith(".JPG") || item.getName().endsWith(".jpeg") || item.getName().endsWith(".JPEG")) { 607 allFiles.add(item); 608 } 609 } 610 // Set progressbar to full length. 611 progress.setValue(progress.getMaximum()); 612 } 613 614 /*** 615 * This method allows the recursing through the specified directory. 616 * 617 * @param aFile File with the directory to recurse through. 618 */ 619 private void recurse(File aFile) { 620 // List all files. 621 File[] lList = aFile.listFiles(); 622 // Cycle all the files. 623 // If it's a directory, recurse. 624 // Else if it's a file with the correct extension, add it 625 // to the full list. 626 for(int i = 0; i < lList.length; i++) { 627 File item = lList[i]; 628 if(item.isDirectory()) { 629 this.recurse(item); 630 } else if(item.getName().endsWith(".gif") || item.getName().endsWith(".jpg") || item.getName().endsWith(".GIF") || item.getName().endsWith(".JPG") || item.getName().endsWith(".jpeg") || item.getName().endsWith(".JPEG")) { 631 allFiles.add(item); 632 } 633 } 634 } 635 } 636 }

This page was automatically generated by Maven