001/*
002 *  PDFEditor.java
003 *  $URL: svn://svn.webarts.bc.ca/open/trunk/projects/WebARTS/ca/bc/webarts/tools/pdf/PDFEditor.java $
004 *  $Revision: 1297 $
005 *  $Date: 2019-04-18 18:25:12 -0700 (Thu, 18 Apr 2019) $
006 *  Copyright (c) 2002 Tom B. Gutwin P.Eng.
007 *
008 *  This program is free software; you can redistribute it and/or
009 *  modify it under the terms of the GNU General Public License
010 *  as published by the Free Software Foundation; either version 2
011 *  of the License, or any later version.
012 *
013 *  This program is distributed in the hope that it will be useful,
014 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
015 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 *  GNU General Public License for more details.
017 *
018 *  You should have received a copy of the GNU General Public License
019 *  along with this program; if not, write to the Free Software
020 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
021 */
022package ca.bc.webarts.tools.pdf;
023
024import ca.bc.webarts.tools.pdf.CropPDF;
025import ca.bc.webarts.tools.pdf.TwoUpPDF;
026
027import ca.bc.webarts.widgets.AutoButtonBar;
028import ca.bc.webarts.widgets.ClassConstants;
029import ca.bc.webarts.widgets.ColouredLabel;
030import ca.bc.webarts.widgets.JAboutBox;
031import ca.bc.webarts.widgets.Splash;
032import ca.bc.webarts.widgets.Util;
033
034import java.awt.BorderLayout;
035import java.awt.FlowLayout;
036import java.awt.Color;
037import java.awt.Component;
038import java.awt.Dimension;
039import java.awt.Event;
040import java.awt.Font;
041import java.awt.Image;
042import java.awt.Label;
043import java.awt.Panel;
044import java.awt.event.ActionEvent;
045import java.awt.event.ActionListener;
046import java.awt.event.KeyEvent;
047import java.awt.event.WindowAdapter;
048import java.awt.event.WindowEvent;
049
050import java.io.File;
051
052import java.net.URL;
053import java.net.MalformedURLException;
054
055import java.util.Iterator;
056
057import javax.swing.ImageIcon;
058import javax.swing.JButton;
059import javax.swing.JCheckBox;
060import javax.swing.JFrame;
061import javax.swing.JMenu;
062import javax.swing.JMenuBar;
063import javax.swing.JMenuItem;
064import javax.swing.JOptionPane;
065import javax.swing.JPanel;
066import javax.swing.JTabbedPane;
067import javax.swing.JComboBox;
068import javax.swing.KeyStroke;
069
070import org.apache.log4j.Logger;
071import org.apache.log4j.LogManager;
072import org.apache.log4j.Priority;
073import org.apache.log4j.PropertyConfigurator;
074
075import com.pdfgo.pdf.Document;
076import com.pdfgo.pdf.PDFException;
077
078
079/**
080 * PDFEditor is a utility application to help you massage existing PDF files
081 * into a cropped form that lets you see more per page. Its basic capabilities
082 * are: <ul><li>to load and view a PDF,</li><li>selectivly crop the edges or
083 * margin from a document,</li><li>automatically take the cropped PDF and format
084 * it into a 2Up view of the document</li><li>enlarges the cropped pages to fill
085 * the newly created 2Up page (eliminating all that empty whitespace on a normal
086 * 2Up page)</li><li>allows for alternating odd/even page margins when an
087 * original document has a binding offset</li><li>allows for the inclusion of an
088 * alternating even/odd page binding offset on the resultant 2Up page so you can
089 * print the pages double sided</li><li>add bookmarks (to be done)</li>
090 * <li>rearrange bookmarks (to be done).</li></ul>
091 * <p><b>It does it all in Java (no native code calls) and its FREE!</b></p>
092 * <br>All PDF document handling is done using the freely available iText PDF
093 * Java library -
094 * <a href="http://www.lowagie.com/iText/">http://www.lowagie.com/iText/</a>
095 * <br>The viewing of the PDF docs requires the PDFGo library -
096 * <a href="http://www.pdfgo.com">http://www.pdfgo.com</a> the
097 * <a href="http://www.pdfgo.com/downloads.html">free demo version</a>
098 * is enough for this application to work, since the actual processing of the
099 * pdfs is handled by Lowagie iText.
100 * <hr><br>License: GNU GPL<pre>
101 * This program is free software; you can redistribute it and/or modify it
102 * under the terms of the GNU General Public License as published by the Free
103 * Software Foundation; version 2 of the License.
104 *
105 * This program is distributed in the hope that it will be useful, but WITHOUT
106 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
107 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
108 * more details.
109 *
110 * You should have received a copy of the GNU General Public License along
111 * with this program; if not, write to the Free Software Foundation, Inc.,
112 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.</pre>
113 *
114 * @author     tgutwin
115 * @created    August 12, 2002
116 */
117public class PDFEditor extends JFrame implements AutoMenuBarUser, ActionListener
118{
119  /**  Constant holding the users file seperator. ("/" or "\")  */
120  private final static String SYSTEM_FILE_SEPERATOR = File.separator;
121
122  /**  Constant holding the users file seperator. ("/" or "\")  */
123  private final static String SYSTEM_LINE_SEPERATOR =
124    System.getProperty("line.separator");
125
126  /**  The application name string  */
127  private final static String APP_NAME = "PDFEditor";
128
129  /**  A Class holder for its name (used in Logging).  */
130  private static String className_ = PDFEditor.class.getName();
131
132  /**  The log4j logger object. */
133  protected static Logger logger_ = Logger.getLogger(className_);
134
135  /** The Crop PDF helper object that abstracts and performs the cropping. **/
136  protected CropPDF cropper_ = null;
137
138  /**
139   * The 2Up Crop PDF helper object that abstracts and performs the creation
140   * of the 2Up doc.
141   **/
142  protected TwoUpPDF twoUpper_ = null;
143
144  /**  A generic Class accessable Label that is used throughout for Debug
145   *   Stmnts to the screen. */
146  protected ColouredLabel myDebugLabel_ =
147    new ColouredLabel(new Color(5,5,100),
148                      Color.white,
149                      new Font("SanSerif", Font.PLAIN, 11),
150                      "Crop Controls Go Here.");
151
152  /** The class holder for the URL of the current PDF being manipulated. **/
153  URL inputPDFURL_ = null;
154
155  /**
156   * The class holder for the filename of the current PDF being manipulated.
157   **/
158  String inputPDF_ = "";
159
160  /**
161   * A control panel/holder for the control buttons at the top of the original
162   * PDF view screen.
163   **/
164  JPanel borderCropControlPanel1_ = null;
165
166  /**
167   * A control panel/holder for the control buttons at the top of the Cropped
168   * PDF view screen.
169   **/
170  JPanel borderCropControlPanel2_ = null;
171
172  /**
173   * A control panel/holder for the control buttons at the top of the Cropped2Up
174   * PDF view screen.
175   **/
176  JPanel borderCropControlPanel3_ = null;
177
178  /**
179   * A control panel/holder for the control buttons at the top of the 4th tab
180   * pane. (Currently unused)
181   **/
182  JPanel borderCropControlPanel4_ = null;
183
184  /**
185    * A Checkbox to select if the page cropping will alternate left/right
186    * margins given that the original doc had even/odd page margins for a
187    * binding offset.
188    **/
189  JCheckBox facingPageMargins_ = null;
190
191  /**
192    * A Checkbox to select if the Two Up page will have alternating even/odd top
193    * page margin to allow for a twosided binding offset on the long side
194    * of the page.
195    **/
196  JCheckBox bindingPageMargins_ = null;
197
198  /**
199   * The class holder for the amount to crop of the <b>left</b> edge of the original
200   * PDF documen when creating the Cropped PDF. Please use the get and set
201   * methods to access this instance var.
202   **/
203  private float leftCrop_ = 0.25f;
204
205  /**
206   * The class holder for the amount to crop of the <b>right</b> edge of the original
207   * PDF documen when creating the Cropped PDF. Please use the get and set
208   * methods to access this instance var.
209   **/
210  private float rightCrop_ = 0.25f;
211
212  /**
213   * The class holder for the amount to crop of the <b>top</b> edge of the original
214   * PDF documen when creating the Cropped PDF. Please use the get and set
215   * methods to access this instance var.
216   **/
217  private float topCrop_ = 0.25f;
218
219  /**
220   * The class holder for the amount to crop of the <b>bottom</b> edge of the original
221   * PDF documen when creating the Cropped PDF. Please use the get and set
222   * methods to access this instance var.
223   **/
224  private float bottomCrop_ = 0.25f;
225
226  /**
227   * The instance object that represents the original PDF document.
228   **/
229  Document originalPDFDoc_ = new Document();
230
231  /**
232   * The instance object that represents the original Cropped PDF document.
233   **/
234  Document croppedPDFDoc_ = new Document();
235
236  /**
237   * The instance object that represents the original Cropped 2Up PDF document.
238   **/
239  Document cropped2UpPDFDoc_ = new Document();
240
241  /**
242   * The iText PDF Document object.
243   **/
244   com.itextpdf.text.Document iTextDoc = null;
245
246  /**
247   *  The MenuBar. All creating and setup is handled by the the AutoMenuBar
248   *  class.
249   *
250   * @see    AutoMenuBar
251   */
252  private AutoMenuBar menuBar_ = null;
253
254  /**  A class constant representing an ID value for the Open Menuitem. **/
255
256  final static int OPEN_MENUREF = 100;
257
258  /**  A class constant representing an ID value for the Save Menuitem. **/
259  final static int SAVE_MENUREF = 101;
260
261  /**  A class constant representing an ID value for the Print Menuitem. **/
262  final static int PRINT_MENUREF = 103;
263
264  /**  A class constant representing an ID value for the Close Menuitem. **/
265  final static int CLOSE_MENUREF = 105;
266
267  /**  A class constant representing an ID value for the Exit Menuitem. **/
268  final static int EXIT_MENUREF = 106;
269
270  /**  A class constant representing an ID value for the Debug Level Menuitem. **/
271  final static int DEBUGLEVEL_MENUREF = 200;
272
273  /**  A class constant representing an ID value for the Java Look And Feel Menuitem. **/
274  final static int JLF_MENUREF = 202;
275
276  /**  A class constant representing an ID value for the Platform Look And Feel Menuitem. **/
277  final static int PLF_MENUREF = 203;
278
279  /**  A class constant representing an ID value for the Motif Look And Feel Menuitem. **/
280  final static int MLF_MENUREF = 204;
281
282  /**  A class constant representing an ID value for the Help Menuitem. **/
283  final static int HELP_MENUREF = 300;
284
285  /**  A class constant representing an ID value for the About Menuitem. **/
286  final static int ABOUT_MENUREF = 302;
287
288
289  /**  Basic constructor for this Object that only gets the frame title setup..  */
290  public PDFEditor()
291  {
292    final String methodName = className_ + ": Constructor()";
293    logger_.debug("Entering " + methodName);
294    setTitle("PDFEditor - Java PDF Editing by Tom B. Gutwin, WebARTS Design");
295    logger_.debug("Exiting " + methodName);
296  }
297
298  /** Setter for the inputPDF_ field.**/
299  public void setInputPDF_(String inputPDF)
300  {
301    this.inputPDF_ = inputPDF;
302  }
303
304
305  /** Getter for the inputPDF_ field.**/
306  public String getInputPDF_()
307  {
308    return inputPDF_;
309  }
310
311
312  /** Setter for the leftCrop_ field.**/
313  public void setLeftCrop_(float leftCrop)
314  {
315    final String methodName = className_ + ": setLeftCrop_("+leftCrop+")";
316    logger_.debug("Entering " + methodName);
317    this.leftCrop_ = leftCrop;
318    logger_.debug("Exiting " + methodName);
319  }
320
321
322  /** Getter for the leftCrop_ field.**/
323  public float getLeftCrop_()
324  {
325    return leftCrop_;
326  }
327
328
329  /** Setter for the rightCrop_ field.**/
330  public void setRightCrop_(float rightCrop)
331  {
332    final String methodName = className_ + ": setRightCrop_("+rightCrop+")";
333    logger_.debug("Entering " + methodName);
334    this.rightCrop_ = rightCrop;
335    logger_.debug("Exiting " + methodName);
336  }
337
338
339  /** Getter for the rightCrop_ field.**/
340  public float getRightCrop_()
341  {
342    return rightCrop_;
343  }
344
345
346  /** Setter for the topCrop_ field.**/
347  public void setTopCrop_(float topCrop)
348  {
349    final String methodName = className_ + ": setTopCrop_("+topCrop+")";
350    logger_.debug("Entering " + methodName);
351    this.topCrop_ = topCrop;
352    logger_.debug("Exiting " + methodName);
353  }
354
355
356  /** Getter for the topCrop_ field.**/
357  public float getTopCrop_()
358  {
359    return topCrop_;
360  }
361
362
363  /** Setter for the bottomCrop_ field.**/
364  public void setBottomCrop_(float bottomCrop)
365  {
366    final String methodName = className_ + ": setBottomCrop_("+bottomCrop+")";
367    logger_.debug("Entering " + methodName);
368    this.bottomCrop_ = bottomCrop;
369    logger_.debug("Exiting " + methodName);
370  }
371
372
373  /** Getter for the bottomCrop_ field.**/
374  public float getBottomCrop_()
375  {
376    return bottomCrop_;
377  }
378
379
380  /**
381   *
382   * Returns the String representing the filename of the Cropped-2up file that
383   * is based on the input PDF filename.
384   *
385   */
386  private String get2UpCroppedPDFName()
387  {
388    final String methodName = className_ + ": get2UpCroppedPDFName()";
389    logger_.debug("Entering " + methodName);
390    logger_.debug("Exiting " + methodName);
391    return inputPDF_.substring(0,inputPDF_.length()-4)+"-Crop-2Up.pdf";
392  }
393
394
395  /**
396   *
397   * Returns the String representing the filename of the Cropped file that
398   * is based on the input PDF filename.
399   */
400  private String getCroppedPDFName()
401  {
402    final String methodName = className_ + ": getCroppedPDFName()";
403    logger_.debug("Entering " + methodName);
404    logger_.debug("Exiting " + methodName);
405    return inputPDF_.substring(0,inputPDF_.length()-4)+"-Crop.pdf";
406  }
407
408
409  /**
410   * Perform the actual cropping of the Doc. All
411   * processing is done using the WebARTS Library Tool
412   * <a href="CropPDF.html">ca.bc.webarts.tools.CropPDF</a> which wraps all
413   * the calls to the lowagie iText Library..
414   *
415   */
416  private void doCrop()
417  {
418    final String methodName = className_ + ": doCrop()";
419    logger_.debug("Entering " + methodName);
420    boolean faceMargins = (facingPageMargins_!=null?
421                           facingPageMargins_.isSelected():
422                           false);
423    if (faceMargins)
424    {
425      logger_.debug("   Calling CropPDF ("+
426          leftCrop_+", "+rightCrop_+", "+topCrop_+", "+bottomCrop_+", "+
427          rightCrop_+", "+leftCrop_+", "+topCrop_+", "+bottomCrop_+")");
428      cropper_ = new CropPDF(leftCrop_, rightCrop_, topCrop_, bottomCrop_,
429                             rightCrop_, leftCrop_, topCrop_, bottomCrop_,
430                             getInputPDF_());
431    }
432    else
433    {
434      logger_.debug("   Calling CropPDF ("+leftCrop_+", "+rightCrop_+", "+topCrop_+", "+bottomCrop_+")");
435      cropper_ = new CropPDF(leftCrop_, rightCrop_, topCrop_, bottomCrop_,
436                             getInputPDF_());
437    }
438    cropper_.doCrop(faceMargins);
439
440    logger_.debug("Exiting " + methodName);
441
442  }
443
444
445  /**
446   * Perform the actual conversion of the Cropped Doc to the 2Up Doc. All
447   * processing is done using the WebARTS Library Tool
448   * <a href="TwoUpPDF.html">ca.bc.webarts.tools.TwoUpPDF</a> which wraps all
449   * the calls to the lowagie iText Library..
450   *
451   */
452  private void do2Up()
453  {
454    final String methodName = className_ + ": do2Up()";
455    logger_.debug("Entering " + methodName);
456    if (bindingPageMargins_.isSelected())
457    {
458      String [] cropAmounts = {"-doubleBind", "0.0", cropper_.getOutFileName()};
459      TwoUpPDF.main(cropAmounts);
460    }
461    else
462    {
463      String [] cropAmounts = {cropper_.getOutFileName()};
464      TwoUpPDF.main(cropAmounts);
465    }
466
467    logger_.debug("Exiting " + methodName);
468  }
469
470
471  /**
472   *  Initializes the GUI Main Area Panel (the tabbed pane, the
473   *  inner panels etc.)
474   *
475   * @return JPanel the panel to go into the Main center area of jAckup
476   */
477  private JPanel init2UpCroppedPDFPanel()
478  {
479    final String methodName = className_ + ": init2UpCroppedPDFPanel()";
480    logger_.debug("Entering " + methodName);
481
482    JPanel retVal = new JPanel(new BorderLayout());
483    retVal.add(new ColouredLabel(new Color(5,5,100),
484                                 Color.white,
485                                 new Font("SanSerif", Font.PLAIN, 11),
486                                 "Cropped-2Up PDF Placeholder"));
487    try
488    {
489      //originalPDFDoc_ = new Document();
490      cropped2UpPDFDoc_.setFile(get2UpCroppedPDFName());
491      cropped2UpPDFDoc_.setToolbarVisible(true);
492      cropped2UpPDFDoc_.fitPage();
493      if (cropped2UpPDFDoc_.getPeer() != null)
494        retVal = cropped2UpPDFDoc_.getPeer();
495    }
496    catch (Exception ex)
497    {
498      ex.printStackTrace();
499    }
500    logger_.debug("Exiting " + methodName);
501    return retVal;
502  }
503
504
505  /**
506   *  Initializes the GUI Main Area Panel (the tabbed pane, the
507   *  inner panels etc.)
508   *
509   * @return JPanel the panel to go into the Main center area of jAckup
510   */
511  private JPanel initCroppedPDFPanel()
512  {
513    final String methodName = className_ + ": initCroppedPDFPanel()";
514    logger_.debug("Entering " + methodName);
515
516    JPanel retVal = new JPanel(new BorderLayout());
517    retVal.add(new ColouredLabel(new Color(5,5,100),
518                                 Color.white,
519                                 new Font("SanSerif", Font.PLAIN, 11),
520                                 "Cropped PDF Placeholder"));
521    try
522    {
523      croppedPDFDoc_.setFile(getCroppedPDFName());
524      croppedPDFDoc_.setToolbarVisible(true);
525      croppedPDFDoc_.fitPage();
526      if (croppedPDFDoc_.getPeer() != null)
527        retVal = croppedPDFDoc_.getPeer();
528    }
529    catch (Exception ex)
530    {
531      ex.printStackTrace();
532    }
533    logger_.debug("Exiting " + methodName);
534    return retVal;
535  }
536
537
538  /**
539   *  Initializes the GUI Main Area Panel (the tabbed pane, the
540   *  inner panels etc.)
541   *
542   * @return JPanel the panel to go into the Main center area of jAckup
543   */
544  private void refreshCroppedView()
545  {
546    final String methodName = className_ + ": refreshCroppedView()";
547    logger_.debug("Entering " + methodName);
548
549    try
550    {
551      croppedPDFDoc_.setUrl((new File(getCroppedPDFName())).toURL());
552      //cropped2UpPDFDoc_.setUrl((new File(get2UpCroppedPDFName())).toURL());
553    }
554    catch (MalformedURLException badUrlEx)
555    {
556      logger_.debug("cannot convert "+getCroppedPDFName()+" to a URL.");
557    }
558    catch (PDFException pdfEx)
559    {
560      logger_.debug("cannot update PDF to "+getCroppedPDFName());
561    }
562
563    logger_.debug("Exiting " + methodName);
564  }
565
566
567  /**
568   *  Initializes the GUI Main Area Panel (the tabbed pane, the
569   *  inner panels etc.)
570   *
571   * @return JPanel the panel to go into the Main center area of jAckup
572   */
573  private void refresh2UpView()
574  {
575    final String methodName = className_ + ": refresh2UpView()";
576    logger_.debug("Entering " + methodName);
577
578    try
579    {
580      //croppedPDFDoc_.setUrl((new File(getCroppedPDFName())).toURL());
581      cropped2UpPDFDoc_.setUrl((new File(get2UpCroppedPDFName())).toURL());
582    }
583    catch (MalformedURLException badUrlEx)
584    {
585      logger_.debug("cannot convert "+get2UpCroppedPDFName()+" to a URL.");
586    }
587    catch (PDFException pdfEx)
588    {
589      logger_.debug("cannot update PDF to "+get2UpCroppedPDFName());
590    }
591
592    logger_.debug("Exiting " + methodName);
593  }
594
595
596  /**
597   *  Initializes the original PDF Document view panel.
598   *
599   * @return JPanel the panel to go into the Main center area of jAckup
600   */
601  private JPanel initOriginalPDFPanel()
602  {
603    final String methodName = className_ + ": initOriginalPDFPanel()";
604    logger_.debug("Entering " + methodName);
605
606    JPanel retVal = new JPanel(new BorderLayout());
607    retVal.add(new ColouredLabel(new Color(5,5,100),
608                                 Color.white,
609                                 new Font("SanSerif", Font.PLAIN, 11),
610                                 "PDF Placeholder"));
611    try
612    {
613      iTextDoc = CropPDF.parsePDFFile(inputPDF_);
614      originalPDFDoc_.setFile(inputPDF_);
615      originalPDFDoc_.setToolbarVisible(true);
616      originalPDFDoc_.fitPage();
617      if (originalPDFDoc_.getPeer() != null)
618        retVal = originalPDFDoc_.getPeer();
619    }
620    catch (Exception ex)
621    {
622      ex.printStackTrace();
623    }
624    logger_.debug("Exiting " + methodName);
625    return retVal;
626  }
627
628
629  /**
630   *  Initializes the GUI Main Area Panel (the tabbed pane, the
631   *  inner panels etc.)
632   *
633   * @return JPanel the panel to go into the Main center area of jAckup
634   */
635  private JPanel initMainArea()
636  {
637    final String methodName = className_ + ": initMainArea()";
638    logger_.debug("Entering " + methodName);
639
640    JPanel retVal = new JPanel(new BorderLayout());
641    JTabbedPane tabbedPane = new JTabbedPane();
642    JPanel tab1Content = new JPanel(new BorderLayout());
643    JPanel tab2Content = new JPanel(new BorderLayout());
644    JPanel tab3Content = new JPanel(new BorderLayout());
645    JPanel tab4Content = new JPanel(new BorderLayout());
646    URL codeBase = null;
647    try
648    {
649      codeBase = new URL("file:///d:/tbg/pkgs/images");
650    }
651    catch (java.net.MalformedURLException t)
652    {
653      logger_.debug("caught exception: " + t );
654    }
655
656    String[] possibleCropValues = { "0.1", "0.2", "0.25", "0.3", "0.4", "0.5",
657                                    "0.6", "0.7", "0.75", "0.8", "0.9", "1.0",
658                                    "1.1", "1.2", "1.25", "1.5"};
659
660
661    // ****build the Panel 1 Control Bar
662    borderCropControlPanel1_  = new JPanel(new BorderLayout());
663    String [] p1ButtonNames = {"moveLeft", "moveRight", "moveUp", "moveDown", "delete", "add"};
664    String [] p1ButtonTips  = {"Move the selected bookmark Left",
665                               "Move the selected bookmark Right",
666                               "Move the selected bookmark Up",
667                               "Move the selected bookmark Down",
668                               "Delete the selected bookmark",
669                               "Add A New bookmark"};
670    AutoButtonBar p1ButtonBar =
671        new AutoButtonBar(codeBase, p1ButtonNames, p1ButtonTips, this);
672    borderCropControlPanel1_.add(p1ButtonBar,"Center");
673
674    // ****build the Panel 2 Control Bar
675    borderCropControlPanel2_  = new JPanel(new BorderLayout());
676    JPanel p1 = new JPanel(new FlowLayout(FlowLayout.LEFT,3,3));
677    JPanel p2 = new JPanel(new FlowLayout(FlowLayout.RIGHT,10,3));
678    JPanel p3 = new JPanel(new FlowLayout(FlowLayout.LEFT,10,3));
679    Dimension dimens = new Dimension(70,25);
680    JComboBox leftCropBox = new JComboBox(possibleCropValues);
681    leftCropBox.setEditable(true);
682    leftCropBox.setPreferredSize(dimens);
683    leftCropBox.addActionListener(new leftCropActionListener(leftCropBox));
684    JComboBox rightCropBox = new JComboBox(possibleCropValues);
685    rightCropBox.setEditable(true);
686    rightCropBox.setPreferredSize(dimens);
687    rightCropBox.addActionListener(new rightCropActionListener(rightCropBox));
688    JComboBox topCropBox = new JComboBox(possibleCropValues);
689    topCropBox.setEditable(true);
690    topCropBox.setPreferredSize(dimens);
691    topCropBox.addActionListener(new topCropActionListener(topCropBox));
692    JComboBox bottomCropBox = new JComboBox(possibleCropValues);
693    bottomCropBox.setEditable(true);
694    bottomCropBox.setPreferredSize(dimens);
695    bottomCropBox.addActionListener(new bottomCropActionListener(bottomCropBox));
696    Color backLabelColour = new Color(210,210,210);
697    p1.add(new ColouredLabel(backLabelColour,
698                                          Color.black,
699                                          new Font("SanSerif", Font.PLAIN, 10),
700                                          "Left:"));
701    p1.add(leftCropBox);
702    p1.add(new ColouredLabel(backLabelColour,
703                                          Color.black,
704                                          new Font("SanSerif", Font.PLAIN, 10),
705                                          "   Right:"));
706    p1.add(rightCropBox);
707    p1.add(new ColouredLabel(backLabelColour,
708                                          Color.black,
709                                          new Font("SanSerif", Font.PLAIN, 10),
710                                          "   Top:"));
711    p1.add(topCropBox);
712    p1.add(new ColouredLabel(backLabelColour,
713                                          Color.black,
714                                          new Font("SanSerif", Font.PLAIN, 10),
715                                          "   Bottom:"));
716    p1.add(bottomCropBox);
717    facingPageMargins_ = new JCheckBox("Alternate Facing Page Margins");
718    bindingPageMargins_ = new JCheckBox("Offset for Two Sided \nPrint Binding");
719    p3.add(facingPageMargins_);
720    p3.add(bindingPageMargins_);
721
722    JButton doCropButton = new JButton("Do Crop");
723    doCropButton.addActionListener(this);
724    p2.add(doCropButton);
725    borderCropControlPanel2_.add(p1,"West");
726    borderCropControlPanel2_.add(p2,"Center");
727    borderCropControlPanel2_.add(p3,"South");
728
729    borderCropControlPanel3_  = new JPanel(new BorderLayout());
730    borderCropControlPanel3_.add(new ColouredLabel(new Color(5,5,100),
731                                          Color.white,
732                                          new Font("SanSerif", Font.PLAIN, 11),
733                                          "Panel 3 Controls Go Here."),"Center");
734    tab1Content.add(borderCropControlPanel1_,"North");
735    tab1Content.add(initOriginalPDFPanel(),"Center");
736    tab2Content.add(borderCropControlPanel2_,"North");
737    tab2Content.add(initCroppedPDFPanel(),"Center");
738    tab3Content.add(borderCropControlPanel3_,"North");
739    tab3Content.add(init2UpCroppedPDFPanel(),"Center");
740    tabbedPane.add("Original PDF", tab1Content);
741    tabbedPane.add("Cropped PDF", tab2Content);
742    tabbedPane.add("Two Up Cropped PDF", tab3Content);
743    tabbedPane.add("Tab4", tab4Content);
744    tabbedPane.setForeground(Color.black);
745    tabbedPane.setBackgroundAt(0,new Color(200,255,255));
746    tabbedPane.setBackgroundAt(1,new Color(255,255,200));
747    tabbedPane.setBackgroundAt(2,new Color(255,200,255));
748    tabbedPane.setBackgroundAt(3,new Color(200,200,255));
749    tabbedPane.setToolTipTextAt(0,"Tab1 ToolTip");
750    tabbedPane.setToolTipTextAt(1,"Tab2 ToolTip");
751    tabbedPane.setToolTipTextAt(2,"Tab3 ToolTip");
752    tabbedPane.setToolTipTextAt(3,"Tab4 ToolTip");
753    retVal.add(tabbedPane,"Center");
754
755    logger_.debug("Exiting " + methodName);
756    return retVal;
757  }
758
759
760  /**
761   *  Initializes the GUI upon startup. Sets up the menu, the tabbed pane, the
762   *  inner panels etc.
763   */
764  private void initGui()
765  {
766    final String methodName = className_ + ": initGui()";
767    logger_.debug("Entering " + methodName);
768
769    /*
770     *  create the menu bar
771     */
772    menuBar_ = new AutoMenuBar(this); //initMenuBar();
773    menuBar_.addListeners();
774    JPanel mainAreaPanel = initMainArea();
775
776    getContentPane().add(menuBar_, "North");
777    getContentPane().add(mainAreaPanel, "Center");
778
779    logger_.debug("Exiting " + methodName);
780  }
781
782
783  /**  Forces a repaint to this apps menubar.  */
784  private void repaintMenuBar()
785  {
786    final String methodName = className_ + ": repaintMenuBar()";
787
788    if (menuBar_ != null)
789    {
790      menuBar_.repaint();
791    }
792    logger_.debug("Exiting " + methodName);
793  }
794
795
796  /**
797   *  Adds an ActionListener to the JMenuItem that is supplied in the passed
798   *  param.
799   *
800   * @param  menuItem  The feature to be added to the Listener attribute
801   */
802  public void addListener(JMenuItem menuItem)
803  {
804    // Logger Trace Method Enter
805    final String methodName = className_ + ": addListener(JMenuItem)";
806    logger_.debug("Entering " + methodName);
807
808    /*  use a simple indexOf helper function to look through the menu
809     *  items and return an int to represent its HASH position   */
810    String toolTipText = menuItem.getToolTipText();
811    int indexRef = menuBar_.indexOf(toolTipText);
812
813    StringBuffer sb = new StringBuffer("    Adding a listener for menu item: ");
814    sb.append(toolTipText);
815    sb.append(" - ");
816    sb.append(indexRef);
817    logger_.debug(sb.toString());
818
819    final Component finalMenuItem = menuItem;
820    /**  The log4j logger final object. */
821    final Logger finalLogger = logger_;
822    switch (indexRef)
823    {
824        case OPEN_MENUREF:
825          /*
826           *  Save Window Data To File
827           */
828          menuItem.addActionListener(new openActionListener(finalMenuItem));
829          break;
830
831        case SAVE_MENUREF:
832          /*
833           *  Save Window Data To File
834           */
835          menuItem.addActionListener(new saveActionListener(finalMenuItem));
836          break;
837
838        case PRINT_MENUREF:
839          /*
840           *  print
841           */
842          menuItem.addActionListener(new printActionListener(finalMenuItem));
843          break;
844
845        case CLOSE_MENUREF:
846          /*
847           *  close
848           */
849          menuItem.addActionListener(
850            new closeActionListener(finalMenuItem));
851          break;
852
853        case EXIT_MENUREF:
854          /*
855           *  exit
856           */
857          menuItem.addActionListener(
858            new exitActionListener(finalMenuItem));
859          break;
860
861        case DEBUGLEVEL_MENUREF:
862          /*
863           *  Set The Debug Level
864           */
865          menuItem.addActionListener(
866            new debuglevelActionListener(finalMenuItem));
867          break;
868
869        case JLF_MENUREF:
870          /*
871           *  Set the L&F to Java
872           */
873          menuItem.addActionListener(
874            new jlfActionListener(finalMenuItem));
875          break;
876
877        case PLF_MENUREF:
878          /*
879           *  Set the L&F to Platform
880           */
881          menuItem.addActionListener(
882            new plfActionListener(finalMenuItem));
883          break;
884
885        case MLF_MENUREF:
886          /*
887           *  Set the L&F to Motif
888           */
889           menuItem.addActionListener(
890            new mlfActionListener(finalMenuItem));
891          break;
892
893        case HELP_MENUREF:
894          /*
895           *  Open the Help window
896           */
897          menuItem.addActionListener(
898            new helpActionListener(finalMenuItem));
899          break;
900
901        case ABOUT_MENUREF:
902          /*
903           *  Open the About Box
904           */
905          menuItem.addActionListener(
906            new aboutActionListener(finalMenuItem));
907          break;
908
909        default:
910          // Logger Trace Method Enter
911          finalLogger.warn("Unknown MenuItem Reference. Cannot Add A Listener:"+
912                            indexRef);
913
914    }
915    logger_.debug("Exiting " + methodName);
916
917  }
918
919
920  /**
921   *  Does the initial loading of the document and then gets the cropped
922   *  versions done and ready for initial display and editing.
923   *
924   * @return    success or not.
925   */
926  private boolean doInitialLoadAndCrop()
927  {
928    boolean retVal = true;
929    final String methodName = className_ + ": doInitialLoadAndCrop()";
930    logger_.debug("Entering " + methodName);
931
932    try
933    {
934      doCrop();
935      logger_.debug("   Calling TwoUpPDF");
936      String [] cropAmounts = {cropper_.getOutFileName()};
937      TwoUpPDF.main(cropAmounts);
938
939    }
940    catch ( Exception ex)
941    {
942      logger_.debug("Error Preparing inital files");
943      logger_.debug(ex);
944      retVal = false;
945    }
946
947    logger_.debug("Exiting " + methodName);
948    return retVal;
949  }
950
951
952  /**
953   *  Gets the Log object that the class instance is using.
954   *
955   * @return    The Log.
956   */
957  public Logger getLogger()
958  {
959    final String methodName = className_ + ": getLogger()";
960    logger_.debug("Entering " + methodName);
961
962    logger_.debug("Exiting " + methodName);
963    return logger_;
964  }
965
966
967  /**
968   *  The main entrypoint for this class. class
969   *
970   * @param  arg  The command line arguments
971   */
972  public static void main(String[] args)
973  {
974    // log4j logger config
975    PropertyConfigurator.configure(System.getProperty("user.home")+
976                                   "/logs/log4jConfig.txt");
977    logger_.debug("Entering PDFEditor:main(String[])");
978
979    String splashGraphic = "/images/dont_pan.jpg";
980    logger_.debug("Loading Splash Graphic.");
981    Image splashImage = Util.loadImage(splashGraphic);
982    Panel p = new Panel();
983    /*
984     *  p.setBorder(new CompoundBorder(
985     *  new MatteBorder(1,1,1,1,Color.black),
986     *  new EmptyBorder(12,12,12,12)));
987     */
988    p.setBackground(new Color(210, 210, 210));
989    Label l = new Label("Please wait while loading.");
990    p.add(l);
991    logger_.debug("Splashing.");
992    Splash frame = new Splash(splashImage, 10000, p);
993
994    logger_.debug("Instantiating the PDFEditor Object.");
995    final PDFEditor classInstance = new PDFEditor();
996    //Util.setIconForApp(classInstance, "/images/PDFEditorIcon.jpg");
997
998    classInstance.addWindowListener(
999      new WindowAdapter()
1000      {
1001        public void windowClosing(WindowEvent e)
1002        {
1003          logger_.info("Window Closing - Close Logger and exit!");
1004          //close up the log then vamoose
1005          LogManager.shutdown();
1006          System.exit(0);
1007        }
1008      }
1009    );
1010
1011    if (args.length > 0)
1012      classInstance.setInputPDF_(args[0]);
1013    classInstance.doInitialLoadAndCrop();
1014    classInstance.initGui();
1015    classInstance.pack();
1016    classInstance.toFront();
1017    frame.finishSplash();
1018    classInstance.setVisible(true);
1019
1020    logger_.info("Exiting PDFEditor:main(String[])");
1021  }
1022
1023
1024  /**
1025   * Handles all the Actions originating from the Control Buttons.
1026   *
1027   * @param e  Description of Parameter
1028   */
1029  public void actionPerformed(ActionEvent e)
1030  {
1031    // Logger Trace Method Enter
1032    final String methodName = className_ + ": actionPerformed()";
1033    logger_.debug("Entering " + methodName);
1034
1035    JButton actionButtion = ((JButton) (e.getSource()));
1036    ImageIcon buttonIcon = (ImageIcon) actionButtion.getIcon();
1037    String command = "";
1038    if (actionButtion != null)
1039    {
1040      command = actionButtion.getText();
1041    }
1042    try
1043    {
1044      /* Move Bookmark Left Button Was Pressed */
1045      /* *********************** */
1046      if (command.trim().equals("moveLeft"))
1047      {
1048        logger_.info(command.trim()+" Button Pressed");
1049      }
1050      /* Move Bookmark Right Button Was Pressed */
1051      /* *********************** */
1052      else if (command.trim().equals("moveRight"))
1053      {
1054        logger_.info(command.trim()+" Button Pressed");
1055      }
1056
1057      /* Do Crop Button Was Pressed */
1058      /* *********************** */
1059      else if (command.trim().equals("Do Crop"))
1060      {
1061        logger_.info(command.trim()+" Button Pressed");
1062        doCrop();
1063        do2Up();
1064
1065        refreshCroppedView();
1066        refresh2UpView();
1067      }
1068    }
1069    catch (Exception ex)
1070    {
1071      logger_.debug("Action Listener Exception", ex);
1072    }
1073    logger_.debug("Exiting " + methodName);
1074  }
1075
1076
1077  /** Listener for the leftCrop drop Down JComboBox. **/
1078  private class leftCropActionListener implements ActionListener
1079  {
1080    /**  The log4j logger final object. */
1081    final Logger finalLogger = PDFEditor.logger_;
1082    JComboBox leftBox = null;
1083
1084    public leftCropActionListener(Component mi)
1085    {
1086      super();
1087      leftBox = (JComboBox)mi;
1088    }
1089    /**
1090     *  .
1091     *
1092     * @param  event  The Initiating event
1093     */
1094    public void actionPerformed(ActionEvent event)
1095    {
1096
1097      // Logger Trace Method Enter
1098      final String innerClassMethodName =
1099        "leftCropActionListener.actionPerformed ";
1100      finalLogger.debug("Entering " + innerClassMethodName);
1101
1102      /*
1103       *  now add the specific stuff for this Menu Item
1104       */
1105      setLeftCrop_(Float.parseFloat((String)leftBox.getSelectedItem()));
1106      finalLogger.debug("   leftCrop = " + getLeftCrop_());
1107      // logger method exit
1108      finalLogger.debug("Exiting " + innerClassMethodName);
1109    }
1110  }
1111
1112
1113  /** Listener for the leftCrop drop Down JComboBox. **/
1114  private class rightCropActionListener implements ActionListener
1115  {
1116    /**  The log4j logger final object. */
1117    final Logger finalLogger = PDFEditor.logger_;
1118    JComboBox rightBox = null;
1119
1120    public rightCropActionListener(Component mi)
1121    {
1122      super();
1123      rightBox = (JComboBox)mi;
1124    }
1125    /**
1126     *  .
1127     *
1128     * @param  event  The Initiating event
1129     */
1130    public void actionPerformed(ActionEvent event)
1131    {
1132
1133      // Logger Trace Method Enter
1134      final String innerClassMethodName =
1135        "rightCropActionListener.actionPerformed ";
1136      finalLogger.debug("Entering " + innerClassMethodName);
1137
1138      /*
1139       *  now add the specific stuff for this Menu Item
1140       */
1141      setRightCrop_(Float.parseFloat((String)rightBox.getSelectedItem()));
1142      finalLogger.debug("   rightCrop = " + getRightCrop_());
1143      // logger method exit
1144      finalLogger.debug("Exiting " + innerClassMethodName);
1145    }
1146  }
1147
1148
1149  /** Listener for the leftCrop drop Down JComboBox. **/
1150  private class topCropActionListener implements ActionListener
1151  {
1152    /**  The log4j logger final object. */
1153    final Logger finalLogger = PDFEditor.logger_;
1154    JComboBox box = null;
1155
1156    public topCropActionListener(Component mi)
1157    {
1158      super();
1159      box = (JComboBox)mi;
1160    }
1161    /**
1162     *  .
1163     *
1164     * @param  event  The Initiating event
1165     */
1166    public void actionPerformed(ActionEvent event)
1167    {
1168
1169      // Logger Trace Method Enter
1170      final String innerClassMethodName =
1171        "topCropActionListener.actionPerformed ";
1172      finalLogger.debug("Entering " + innerClassMethodName);
1173
1174      /*
1175       *  now add the specific stuff for this Menu Item
1176       */
1177      setTopCrop_(Float.parseFloat((String)box.getSelectedItem()));
1178      finalLogger.debug("   topCrop = " + getTopCrop_());
1179      // logger method exit
1180      finalLogger.debug("Exiting " + innerClassMethodName);
1181    }
1182  }
1183
1184
1185  /** Listener for the bottomCrop drop Down JComboBox. **/
1186  private class bottomCropActionListener implements ActionListener
1187  {
1188    /**  The log4j logger final object. */
1189    final Logger finalLogger = PDFEditor.logger_;
1190    JComboBox box = null;
1191
1192    public bottomCropActionListener(Component mi)
1193    {
1194      super();
1195      box = (JComboBox)mi;
1196    }
1197    /**
1198     *  .
1199     *
1200     * @param  event  The Initiating event
1201     */
1202    public void actionPerformed(ActionEvent event)
1203    {
1204
1205      // Logger Trace Method Enter
1206      final String innerClassMethodName =
1207        "bottomCropActionListener.actionPerformed ";
1208      finalLogger.debug("Entering " + innerClassMethodName);
1209
1210      /*
1211       *  now add the specific stuff for this Menu Item
1212       */
1213      setBottomCrop_(Float.parseFloat((String)box.getSelectedItem()));
1214      finalLogger.debug("   bottomCrop = " + getBottomCrop_());
1215      // logger method exit
1216      finalLogger.debug("Exiting " + innerClassMethodName);
1217    }
1218  }
1219
1220
1221  private class openActionListener implements ActionListener
1222  {
1223    /**  The log4j logger final object. */
1224    final Logger finalLogger = PDFEditor.logger_;
1225    Component menuItem = null;
1226
1227    public openActionListener(Component mi)
1228    {
1229      super();
1230      menuItem = mi;
1231    }
1232    /**
1233     *  Creates a new jAckup file with default settings.
1234     *
1235     * @param  event  The Initiating event
1236     */
1237    public void actionPerformed(ActionEvent event)
1238    {
1239      // Logger Trace Method Enter
1240      final String innerClassMethodName =
1241        "openActionListener.actionPerformed - " + OPEN_MENUREF;
1242      finalLogger.debug("Entering " + innerClassMethodName);
1243
1244      repaintMenuBar();
1245      /*
1246       *  now add the specific stuff for this Menu Item
1247       */
1248      finalLogger.debug("Open MenuItem Selected");
1249      String fileNameToOpen =
1250          Util.chooseAFilename(((Component) (event.getSource())),
1251                               System.getProperty("user.dir"),
1252                               null,
1253                               false);
1254      if (fileNameToOpen != null && !fileNameToOpen.equals(""))
1255      {
1256        setInputPDF_(fileNameToOpen);
1257        doInitialLoadAndCrop();
1258        try
1259        {
1260          iTextDoc = CropPDF.parsePDFFile(fileNameToOpen);
1261          originalPDFDoc_.setUrl((new File(fileNameToOpen)).toURL());
1262          croppedPDFDoc_.setUrl((new File(getCroppedPDFName())).toURL());
1263          cropped2UpPDFDoc_.setUrl((new File(get2UpCroppedPDFName())).toURL());
1264        }
1265        catch (MalformedURLException badUrlEx)
1266        {
1267          finalLogger.debug("cannot convert "+fileNameToOpen+" to a URL.");
1268        }
1269        catch (PDFException pdfEx)
1270        {
1271          finalLogger.debug("cannot update PDF to "+fileNameToOpen);
1272        }
1273      }
1274
1275      // logger method exit
1276      finalLogger.debug("Exiting " + innerClassMethodName);
1277    }
1278  }
1279
1280
1281  private class saveActionListener implements ActionListener
1282  {
1283    /**  The log4j logger final object. */
1284    final Logger finalLogger = PDFEditor.logger_;
1285    Component menuItem = null;
1286
1287    public saveActionListener(Component mi)
1288    {
1289      super();
1290      menuItem = mi;
1291    }
1292    /**
1293     *  Creates a new jAckup file with default settings.
1294     *
1295     * @param  event  The Initiating event
1296     */
1297    public void actionPerformed(ActionEvent event)
1298    {
1299
1300      // Logger Trace Method Enter
1301      final String innerClassMethodName =
1302        "saveActionListener.actionPerformed - " + SAVE_MENUREF;
1303      finalLogger.debug("Entering " + innerClassMethodName);
1304
1305      repaintMenuBar();
1306      /*
1307       *  now add the specific stuff for this Menu Item
1308       */
1309
1310      // logger method exit
1311      finalLogger.debug("Exiting " + innerClassMethodName);
1312    }
1313  }
1314
1315
1316  private class printActionListener implements ActionListener
1317  {
1318    /**  The log4j logger final object. */
1319    final Logger finalLogger = PDFEditor.logger_;
1320    Component menuItem = null;
1321
1322    public printActionListener(Component mi)
1323    {
1324      super();
1325      menuItem = mi;
1326    }
1327    /**
1328     *  Creates a new jAckup file with default settings.
1329     *
1330     * @param  event  The Initiating event
1331     */
1332    public void actionPerformed(ActionEvent event)
1333    {
1334
1335      // Logger Trace Method Enter
1336      final String innerClassMethodName =
1337        "printActionListener.actionPerformed - " + PRINT_MENUREF;
1338      finalLogger.debug("Entering " + innerClassMethodName);
1339
1340      repaintMenuBar();
1341      /*
1342       *  now add the specific stuff for this Menu Item
1343       */
1344
1345      // logger method exit
1346      finalLogger.debug("Exiting " + innerClassMethodName);
1347    }
1348  }
1349
1350
1351  private class closeActionListener implements ActionListener
1352  {
1353    /**  The log4j logger final object. */
1354    final Logger finalLogger = PDFEditor.logger_;
1355    Component menuItem = null;
1356
1357    public closeActionListener(Component mi)
1358    {
1359      super();
1360      menuItem = mi;
1361    }
1362    /**
1363     *  Creates a new jAckup file with default settings.
1364     *
1365     * @param  event  The Initiating event
1366     */
1367    public void actionPerformed(ActionEvent event)
1368    {
1369
1370      // Logger Trace Method Enter
1371      final String innerClassMethodName =
1372        "closeActionListener.actionPerformed - " + CLOSE_MENUREF;
1373      finalLogger.debug("Entering " + innerClassMethodName);
1374
1375      repaintMenuBar();
1376      /*
1377       *  now add the specific stuff for this Menu Item
1378       */
1379
1380      // logger method exit
1381      finalLogger.debug("Exiting " + innerClassMethodName);
1382    }
1383  }
1384
1385
1386  private class exitActionListener implements ActionListener
1387  {
1388    /**  The log4j logger final object. */
1389    final Logger finalLogger = PDFEditor.logger_;
1390    Component menuItem = null;
1391
1392    public exitActionListener(Component mi)
1393    {
1394      super();
1395      menuItem = mi;
1396    }
1397    /**
1398     *  Creates a new jAckup file with default settings.
1399     *
1400     * @param  event  The Initiating event
1401     */
1402    public void actionPerformed(ActionEvent event)
1403    {
1404
1405      // Logger Trace Method Enter
1406      final String innerClassMethodName =
1407        "printpreviewActionListener.actionPerformed - " + EXIT_MENUREF;
1408      finalLogger.debug("Entering " + innerClassMethodName);
1409
1410      repaintMenuBar();
1411      /*
1412       *  now add the specific stuff for this Menu Item
1413       */
1414      LogManager.shutdown();
1415      System.exit(0);
1416    }
1417  }
1418
1419
1420  private class debuglevelActionListener implements ActionListener
1421  {
1422    /**  The log4j logger final object. */
1423    final Logger finalLogger = PDFEditor.logger_;
1424    Component menuItem = null;
1425
1426    public debuglevelActionListener(Component mi)
1427    {
1428      super();
1429      menuItem = mi;
1430    }
1431    /**
1432     *  Creates a new file with default settings.
1433     *
1434     * @param  event  The Initiating event
1435     */
1436    public void actionPerformed(ActionEvent event)
1437    {
1438
1439      // Logger Trace Method Enter
1440      final String innerClassMethodName =
1441        "debuglevelActionListener.actionPerformed - " + DEBUGLEVEL_MENUREF;
1442      finalLogger.debug("Entering " + innerClassMethodName);
1443
1444      repaintMenuBar();
1445      /*
1446       *  now add the specific stuff for this Menu Item
1447       */
1448
1449      // logger method exit
1450      finalLogger.debug("Exiting " + innerClassMethodName);
1451    }
1452  }
1453
1454
1455  private class jlfActionListener implements ActionListener
1456  {
1457    /**  The log4j logger final object. */
1458    final Logger finalLogger = PDFEditor.logger_;
1459    Component menuItem = null;
1460
1461    public jlfActionListener(Component mi)
1462    {
1463      super();
1464      menuItem = mi;
1465    }
1466    /**
1467     *  Creates a new jAckup file with default settings.
1468     *
1469     * @param  event  The Initiating event
1470     */
1471    public void actionPerformed(ActionEvent event)
1472    {
1473
1474      // Logger Trace Method Enter
1475      final String innerClassMethodName =
1476        "jlfActionListener.actionPerformed - " + JLF_MENUREF;
1477      finalLogger.debug("Entering " + innerClassMethodName);
1478
1479      repaintMenuBar();
1480      /*
1481       *  now add the specific stuff for this Menu Item
1482       */
1483      Util.setTheLookAndFeel(Util.METAL_LOOKANDFEEL, menuItem);
1484
1485      // logger method exit
1486      finalLogger.debug("Exiting " + innerClassMethodName);
1487    }
1488  }
1489
1490
1491  private class plfActionListener implements ActionListener
1492  {
1493    /**  The log4j logger final object. */
1494    final Logger finalLogger = PDFEditor.logger_;
1495    Component menuItem = null;
1496
1497    public plfActionListener(Component mi)
1498    {
1499      super();
1500      menuItem = mi;
1501    }
1502    /**
1503     *  Creates a new jAckup file with default settings.
1504     *
1505     * @param  event  The Initiating event
1506     */
1507    public void actionPerformed(ActionEvent event)
1508    {
1509
1510      // Logger Trace Method Enter
1511      final String innerClassMethodName = this.getClass().getName() + "." +
1512        "actionPerformed - " + PLF_MENUREF;
1513      finalLogger.debug("Entering " + innerClassMethodName);
1514
1515      repaintMenuBar();
1516      /*
1517       *  now add the specific stuff for this Menu Item
1518       */
1519      Util.setTheLookAndFeel(Util.WINDOZE_LOOKANDFEEL, menuItem);
1520
1521      // logger method exit
1522      finalLogger.debug("Exiting " + innerClassMethodName);
1523    }
1524  }
1525
1526
1527  private class mlfActionListener implements ActionListener
1528  {
1529    /**  The log4j logger final object. */
1530    final Logger finalLogger = PDFEditor.logger_;
1531    Component menuItem = null;
1532
1533    public mlfActionListener(Component mi)
1534    {
1535      super();
1536      menuItem = mi;
1537    }
1538    /**
1539     *  Creates a new jAckup file with default settings.
1540     *
1541     * @param  event  The Initiating event
1542     */
1543    public void actionPerformed(ActionEvent event)
1544    {
1545
1546      // Logger Trace Method Enter
1547      final String innerClassMethodName = this.getClass().getName() + "." +
1548        "actionPerformed - " + MLF_MENUREF;
1549      finalLogger.debug("Entering " + innerClassMethodName);
1550
1551      repaintMenuBar();
1552      /*
1553       *  now add the specific stuff for this Menu Item
1554       */
1555      Util.setTheLookAndFeel(Util.MOTIF_LOOKANDFEEL, menuItem);
1556
1557      // logger method exit
1558      finalLogger.debug("Exiting " + innerClassMethodName);
1559    }
1560  }
1561
1562
1563  private class helpActionListener implements ActionListener
1564  {
1565    /**  The log4j logger final object. */
1566    final Logger finalLogger = PDFEditor.logger_;
1567    Component menuItem = null;
1568
1569    public helpActionListener(Component mi)
1570    {
1571      super();
1572      menuItem = mi;
1573    }
1574    /**
1575     *  Creates a new jAckup file with default settings.
1576     *
1577     * @param  event  The Initiating event
1578     */
1579    public void actionPerformed(ActionEvent event)
1580    {
1581
1582      // Logger Trace Method Enter
1583      final String innerClassMethodName = this.getClass().getName() + "." +
1584        "actionPerformed - " + HELP_MENUREF;
1585      finalLogger.debug("Entering " + innerClassMethodName);
1586
1587      repaintMenuBar();
1588      /*
1589       *  now add the specific stuff for this Menu Item
1590       */
1591
1592      // logger method exit
1593      finalLogger.debug("Exiting " + innerClassMethodName);
1594    }
1595  }
1596
1597
1598  private class aboutActionListener implements ActionListener
1599  {
1600    /**  The log4j logger final object. */
1601    final Logger finalLogger = PDFEditor.logger_;
1602    Component menuItem = null;
1603
1604    public aboutActionListener(Component mi)
1605    {
1606      super();
1607      menuItem = mi;
1608    }
1609    /**
1610     *  Creates a new jAckup file with default settings.
1611     *
1612     * @param  event  The Initiating event
1613     */
1614    public void actionPerformed(ActionEvent event)
1615    {
1616
1617      // Logger Trace Method Enter
1618      final String innerClassMethodName = this.getClass().getName() + "." +
1619        "actionPerformed - " + ABOUT_MENUREF;
1620      finalLogger.debug("Entering " + innerClassMethodName);
1621
1622      repaintMenuBar();
1623      /*
1624       *  now add the specific stuff for this Menu Item
1625       */
1626      JAboutBox box = new JAboutBox("PDFEditor Acrobat Editor Utility", "");
1627      box.show();
1628      box.toFront();
1629
1630      // logger method exit
1631      finalLogger.debug("Exiting " + innerClassMethodName);
1632    }
1633  }
1634
1635
1636}
1637
1638class AutoMenuBar extends JMenuBar
1639{
1640  /**  A Class holder for its name (used in Logging).  */
1641  private static String className_ = "AutoMenuBar";
1642
1643  /**  Constant holding the users file seperator. ("/" or "\")  */
1644  private final static String SYSTEM_FILE_SEPERATOR = File.separator;
1645
1646  /**  String Tokens used to automatically create the menu bar.  */
1647  private String menuName[] = {"File", "Options", "Help"};
1648
1649  /**
1650   *  String Tokens used to automatically create the menu items for each menu on
1651   *  the menubar. It is a 2D array of strings that will be used to create
1652   *  menuitems. If there are 4 menus... there will be 4 lists holding the
1653   *  words/Strings to use for the menu items.
1654   */
1655  private String menuItemName[][] = {
1656      {"Open", "Save", "---", "Print...", "---", "Close", "Exit"},
1657      {"Set Debug Output Level...", "---",
1658      "Java L&F", "Platform L&F", "Motif L&F"},
1659      {"Help", "---", "About PDFEditor..."}};
1660
1661  /**  An Enumeration index for the menu items. */
1662  private final static int MENUREF[][] =
1663    {
1664      {PDFEditor.OPEN_MENUREF, PDFEditor.SAVE_MENUREF, 999,
1665       PDFEditor.PRINT_MENUREF, 998, PDFEditor.CLOSE_MENUREF,
1666       PDFEditor.EXIT_MENUREF},
1667      {PDFEditor.DEBUGLEVEL_MENUREF, 997, PDFEditor.JLF_MENUREF,
1668       PDFEditor.PLF_MENUREF, PDFEditor.MLF_MENUREF},
1669      {PDFEditor.HELP_MENUREF, 996, PDFEditor.ABOUT_MENUREF }
1670    };
1671
1672  /**
1673   *  The Tokens used to automatically assign the Mnemonic for each menu items.
1674   *  It is a 2D array of chars that will be used to assign the Mnemonic. If
1675   *  there are 4 menus... there will be 4 lists holding the chars to use as the
1676   *  Mnemonic for the menu items.
1677   */
1678  private char menuItemMnemonic[][] = {
1679      {'o', 's', ' ', 'P', ' ', 'C', 'x'},
1680      {'D', ' ', 'J', 'P', 'M'},
1681      {'H', ' ', 'b'}};
1682
1683  /**
1684   *  The Tokens used when automatically assigning the accel key for each menu
1685   *  items. It is a 2D array of ints that will be used to assign the accel key
1686   *  constant. If there are 4 menus... there will be 4 lists holding the ints
1687   *  to use as the accel key constant value for the menu items.
1688   */
1689  private int menuItemAccel[][] = {
1690      {KeyEvent.VK_O, KeyEvent.VK_S, 0,
1691      KeyEvent.VK_A, 0,
1692      KeyEvent.VK_W, KeyEvent.VK_Q},
1693      {0, 0, 0, 0, 0},
1694      {KeyEvent.VK_F1, 0, KeyEvent.VK_F12}};
1695
1696  /**
1697   *  The Tokens used when automatically assigning the 2nd level of accel key
1698   *  for each menu items. It is a 2D array of ints that will be used to assign
1699   *  the accel key constant. If there are 4 menus... there will be 4 lists
1700   *  holding the ints to use as the accel key constant value for the menu
1701   *  items.
1702   */
1703  private int menuItemAccel2[][] = {
1704      {Event.CTRL_MASK, Event.CTRL_MASK, 0, Event.CTRL_MASK | Event.SHIFT_MASK,
1705      0, Event.CTRL_MASK, Event.CTRL_MASK},
1706      {0, 0, 0, 0, 0},
1707      {0, 0, 0}};
1708
1709  /**
1710   *  String Tokens used to automatically create the menu items tooltip for each
1711   *  menu on the menubar. It is a 2D array of strings that will be used to
1712   *  create menuitems tooltips. If there are 4 menus... there will be 4 lists
1713   *  holding the words/Strings to use for the menu items tooltip.
1714   */
1715  private String menuToolTip[][] =
1716      {{"Open PDF from File...",
1717      "Save Current PDFEditor Plan",
1718      "---", "Print Current PDFEditor Plan", "---",
1719      "Close Current PDF", "Exit Application"},
1720      {"Set Debug Output Level...", "---",
1721      "Set the User Interface to the Java-Metal L&F",
1722      "Set the User Interface to the Platform L&F",
1723      "Set the User Interface to the Motif L&F"},
1724      {"Help On using PDFEditor", "---", "About PDFEditor..."}};
1725
1726  /**
1727   *  boolean Tokens used to enable automatic creation of the menu items for
1728   *  each menu on the menubar. It is a 2D array of booleans each one a flag
1729   *  directly refering to the menu item arrays already setup. If there are 4
1730   *  menus... there will be 4 lists holding the flags to use. If a value of
1731   *  false is specified the menu item will NOT get created.
1732   */
1733  private boolean menuItemShown[][] = {
1734      {true, true, true, true, true, true, true},
1735      {true, true, true, true, true},
1736      {true, true, true}};
1737
1738  /**
1739   *  boolean Tokens used to enable the menu items for each menu on the menubar.
1740   *  It is a 2D array of booleans each one a flag directly refering to the menu
1741   *  item arrays already setup. If there are 4 menus... there will be 4 lists
1742   *  holding the flags to use. If a value of false is specified the menu item
1743   *  will be grayed.
1744   */
1745  private boolean menuItemEnabled[][] = {
1746      {true, true, true, false, true, true, true},
1747      {true, true, true, true, true},
1748      {false, true, true}};
1749
1750  /**
1751   *  Suffix applied to the key used in resource file lookups for an image.
1752   */
1753  private final static String IMAGESUFFIX = "Image.gif";
1754
1755  /**
1756   *  Prefix applied to the key used in resource file lookups for an image.
1757   */
1758  private final static String IMAGEPREFIX = "/images";
1759
1760  /**
1761   *  The Parent Owner of this Auto Menu Bar.
1762   **/
1763   private AutoMenuBarUser parent;
1764
1765
1766
1767  public AutoMenuBar(AutoMenuBarUser passedUser)
1768  {
1769    super();
1770    parent = passedUser;
1771    this.initMenuBar();
1772  }
1773
1774
1775  /**
1776   *  Populates the menuitms into it. It uses a set of
1777   *  predefined String arrays that it loops through to create the menus. This
1778   *  way the menus can be easily changed by simply adding or removing entrys in
1779   *  the arrays. You can set the name, Accelerator, Mnemonic, Tooltip,
1780   *  enabled/disabled (clickable/gray), and even if the item gets created at
1781   *  all! <P>
1782   *
1783   *  The fields it uses are:
1784   *  <UL>
1785   *    <LI> menuItemShown
1786   *    <LI> menuName
1787   *    <LI> menuItemName
1788   *    <LI> menuItemAccel
1789   *    <LI> menuItemAccel2
1790   *  </UL>
1791   *
1792   *
1793   * @return    JMenuBar
1794   * @see       jAckup#createMenuItem(int,int)
1795   */
1796  private void initMenuBar()
1797  {
1798    final String methodName = className_ + ": initMenuBar()";
1799
1800    int i;
1801    int j;
1802    JMenu tempMenu;
1803
1804    for (i = 0; i < menuName.length; i++)
1805    {
1806      tempMenu = new JMenu(menuName[i]);
1807      for (j = 0; j < menuItemName[i].length; j++)
1808      {
1809        if (menuItemShown[i][j])
1810        {
1811          if (menuItemName[i][j].equals("---"))
1812          {
1813            tempMenu.addSeparator();
1814          }
1815          else
1816          /*
1817           *  Use the HELPER function called *createMenuItem* to actually do
1818           *  the menuItem Object creation
1819           */
1820              if (menuItemAccel[i][j] != 0)
1821          {
1822            tempMenu.add(createMenuItem(i, j)).setAccelerator(
1823                KeyStroke.getKeyStroke(menuItemAccel[i][j],
1824                menuItemAccel2[i][j]));
1825          }
1826          else
1827          {
1828            tempMenu.add(createMenuItem(i, j));
1829          }
1830        }
1831      }
1832      this.add(tempMenu);
1833    }
1834  }
1835
1836
1837  /**
1838   *  Aa simple indexOf helper function to look through the menu items and
1839   *  return an int to represent its HASH position
1840   *
1841   * @param  s  Description of Parameter
1842   * @return    int A value that is the HASH in the menuItem array for the
1843   *      menuItem passed in as a param
1844   */
1845  protected int indexOf(String s)
1846  {
1847    final String methodName = className_ + ": indexOf(String " + s + ")";
1848    //
1849
1850    int i = 0;
1851    int j = 0;
1852    int retVal = 0;
1853    if (s != null)
1854    {
1855      try
1856      {
1857        for (j = 0; j < menuName.length; j++)
1858        {
1859          for (i = 0; i < menuToolTip[j].length; i++)
1860          {
1861            if (s.equals(menuToolTip[j][i]))
1862            {
1863              retVal = MENUREF[j][i];
1864              i = menuToolTip[j].length - 1;
1865              j = menuName.length - 1;
1866            }
1867          }
1868        }
1869      }
1870      catch (java.lang.ArrayIndexOutOfBoundsException t)
1871      {
1872         /* don't do anything just return the retVal =0;*/
1873         retVal =0;
1874      }
1875    }
1876    return retVal;
1877  }
1878
1879
1880   /**
1881   *  This is the hook through which all menu items are created. The fields it
1882   *  uses are:
1883   *  <UL>
1884   *    <LI> menuItemMnemonic
1885   *    <LI> menuToolTip
1886   *    <LI> menuItemEnabled
1887   *  </UL>
1888   *
1889   *
1890   * @param  menuRef      Description of Parameter
1891   * @param  menuItemRef  Description of Parameter
1892   * @return              Description of the Returned Value
1893   * @see                 jAckup#initMenuBar()
1894   */
1895  private JMenuItem createMenuItem(int menuRef, int menuItemRef)
1896  {
1897    final String methodName = className_ + ": createMenuItem(int, int)";
1898
1899    String cmd = menuItemName[menuRef][menuItemRef];
1900    JMenuItem mi = new JMenuItem(menuItemName[menuRef][menuItemRef]);
1901    mi.setMnemonic(menuItemMnemonic[menuRef][menuItemRef]);
1902    StringBuffer imgFile = new StringBuffer(IMAGEPREFIX);
1903    imgFile.append(SYSTEM_FILE_SEPERATOR);
1904    imgFile.append(menuItemName[menuRef][menuItemRef]);
1905    imgFile.append(IMAGESUFFIX);
1906    Image menuItmImg = Util.loadImage(imgFile.toString());
1907    mi.setHorizontalTextPosition(JButton.RIGHT);
1908
1909    if (menuItmImg != null)
1910    {
1911      mi.setIcon(new ImageIcon(menuItmImg));
1912    }
1913
1914    mi.setToolTipText(menuToolTip[menuRef][menuItemRef]);
1915    mi.setEnabled(menuItemEnabled[menuRef][menuItemRef]);
1916
1917    return mi;
1918  }
1919
1920  /**
1921   * loops through the menuitems adding all the listeners by calling the parent
1922   * addListener menthod.
1923   **/
1924  public void addListeners()
1925  {
1926
1927    // loop through menuitems adding the listeners.
1928    int i;
1929    int j;
1930    JMenu tempMenu;
1931
1932    for (i = 0; i < menuName.length; i++)
1933    {
1934      tempMenu = this.getMenu(i);
1935      for (j = 0; j < menuItemName[i].length; j++)
1936      {
1937        /*
1938         *  call the one size fits all method to add the appropriate
1939         *  listener to this menu item
1940         */
1941        if (!menuItemName[i][j].equals("---"))
1942          parent.addListener(tempMenu.getItem(j));
1943      }
1944    }
1945  }
1946
1947
1948}
1949
1950interface AutoMenuBarUser
1951{
1952  /**
1953   *  Adds an ActionListener to the JMenuItem that is supplied in the passed
1954   *  param.
1955   *
1956   * @param  menuItem  The feature to be added to the Listener attribute
1957   */
1958  public void addListener(JMenuItem menuItem);
1959}
1960
1961
1962