Clover coverage report -
Coverage timestamp: Sun Apr 18 2004 21:32:30 EDT
file stats: LOC: 389   Methods: 18
NCLOC: 203   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
AnchorDialog.java 42.9% 64.3% 55.6% 59.5%
coverage coverage
 1   
 /*
 2   
  * SimplyHTML, a word processor based on Java, HTML and CSS
 3   
  * Copyright (C) 2002 Ulrich Hilger
 4   
  *
 5   
  * This program is free software; you can redistribute it and/or
 6   
  * modify it under the terms of the GNU General Public License
 7   
  * as published by the Free Software Foundation; either version 2
 8   
  * of the License, or (at your option) any later version.
 9   
  *
 10   
  * This program is distributed in the hope that it will be useful,
 11   
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12   
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13   
  * GNU General Public License for more details.
 14   
  *
 15   
  * You should have received a copy of the GNU General Public License
 16   
  * along with this program; if not, write to the Free Software
 17   
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 18   
  */
 19   
 
 20   
 import java.awt.*;
 21   
 import java.awt.event.*;
 22   
 import javax.swing.*;
 23   
 import javax.swing.border.*;
 24   
 import javax.swing.event.*;
 25   
 import javax.swing.text.*;
 26   
 import javax.swing.text.html.*;
 27   
 import java.util.*;
 28   
 import java.io.*;
 29   
 import java.net.*;
 30   
 
 31   
 /**
 32   
  * Dialog to create and edit link anchors.
 33   
  *
 34   
  * @author Ulrich Hilger
 35   
  * @author Light Development
 36   
  * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
 37   
  * @author <a href="mailto:info@lightdev.com">info@lightdev.com</a>
 38   
  * @author published under the terms and conditions of the
 39   
  *      GNU General Public License,
 40   
  *      for details see file gpl.txt in the distribution
 41   
  *      package of this software
 42   
  *
 43   
  * @version stage 11, April 27, 2003
 44   
  */
 45   
 
 46   
 public class AnchorDialog extends DialogShell implements
 47   
     ActionListener, CaretListener, ListSelectionListener, DocumentListener
 48   
 {
 49   
 
 50   
   /** dialog components */
 51   
   private JList anchorList;
 52   
   private JButton addAnchor;
 53   
   private JButton delAnchor;
 54   
   private SHTMLEditorPane editor;
 55   
   private DocumentPane dp;
 56   
 
 57   
   /** the document this dialog was constructed with */
 58   
   private Document doc = null;
 59   
 
 60   
   /** the URL this document was loaded from (if loaded from this dialog) */
 61   
   private URL url = null;
 62   
 
 63   
   /** table for document anchors */
 64   
   private Hashtable anchorTable = new Hashtable();
 65   
 
 66   
   /** indicates whether or not changes to the document need to be saved */
 67   
   private boolean needsSaving = true;
 68   
 
 69   
   /** the help id for this dialog */
 70   
   private static final String helpTopicId = "item165";
 71   
 
 72   
   //private int renderMode;
 73   
 
 74   
   /**
 75   
    * create an <code>AnchorDialog</code>
 76   
    *
 77   
    * @param parent  the parent dialog of this dialog
 78   
    * @param title  the dialog title
 79   
    * @param doc  the document to edit anchors of
 80   
    */
 81  0
   public AnchorDialog(Dialog parent, String title, Document doc) {
 82  0
     super(parent, title, helpTopicId);
 83  0
     initDialog(doc, null/*, renderMode*/);
 84   
   }
 85   
 
 86   
   /**
 87   
    * create an <code>AnchorDialog</code>
 88   
    *
 89   
    * @param parent  the parent frame of this dialog
 90   
    * @param title  the dialog title
 91   
    * @param doc  the document to edit anchors of
 92   
    */
 93  1
   public AnchorDialog(Frame parent, String title, Document doc) {
 94  1
     super(parent, title, helpTopicId);
 95  1
     initDialog(doc, null/*, renderMode*/);
 96   
   }
 97   
 
 98   
   /**
 99   
    * create an <code>AnchorDialog</code>
 100   
    *
 101   
    * @param parent  the parent frame of this dialog
 102   
    * @param title  the dialog title
 103   
    * @param url  the document url
 104   
    */
 105  0
   public AnchorDialog(Dialog parent, String title, URL url) {
 106  0
     super(parent, title, helpTopicId);
 107  0
     initDialog(null, url/*, renderMode*/);
 108   
   }
 109   
 
 110   
   /**
 111   
    * create an <code>AnchorDialog</code>
 112   
    *
 113   
    * @param parent  the parent frame of this dialog
 114   
    * @param title  the dialog title
 115   
    * @param url  the document url
 116   
    */
 117  0
   public AnchorDialog(Frame parent, String title, URL url) {
 118  0
     super(parent, title, helpTopicId);
 119  0
     initDialog(null, url/*, renderMode*/);
 120   
   }
 121   
 
 122   
   /**
 123   
    * initialize this <code>AnchorDialog</code>
 124   
    *
 125   
    * <p>If a document is passed, anchors of this document
 126   
    * are edited. If doc is null and a url is passed, this
 127   
    * document is loaded (and saved).</p>
 128   
    *
 129   
    * @param doc  the document to edit anchors of, or null
 130   
    * @param url  the url to load a document from, or null
 131   
    */
 132  1
   private void initDialog(Document doc, URL url) {
 133   
 
 134  1
     this.url = url;
 135   
     //this.renderMode = renderMode;
 136   
 
 137   
     // create anchor panel
 138  1
     JPanel anchorPanel = new JPanel(new BorderLayout());
 139  1
     anchorPanel.setBorder(new TitledBorder(new EtchedBorder(
 140   
         EtchedBorder.LOWERED),
 141   
         FrmMain.dynRes.getResourceString(FrmMain.resources, "anchorPanelLabel")));
 142   
     //getAnchors(doc);
 143  1
     anchorList = new JList(/*anchorTable.keySet().toArray()*/);
 144  1
     anchorPanel.add(new JScrollPane(anchorList), BorderLayout.CENTER);
 145  1
     anchorList.addListSelectionListener(this);
 146  1
     addAnchor = new JButton(FrmMain.dynRes.getResourceString(FrmMain.resources, "addImgBtnTitle"));
 147  1
     addAnchor.addActionListener(this);
 148  1
     delAnchor = new JButton(FrmMain.dynRes.getResourceString(FrmMain.resources, "delImgBtnTitle"));
 149  1
     delAnchor.addActionListener(this);
 150   
 
 151   
     // use a help panel to add add/del buttons
 152  1
     JPanel helpPanel = new JPanel();
 153  1
     helpPanel.add(addAnchor);
 154  1
     helpPanel.add(delAnchor);
 155  1
     anchorPanel.add(helpPanel, BorderLayout.SOUTH);
 156   
 
 157   
     // init DocumentPane
 158  1
     if(doc != null) {
 159  1
       needsSaving = false;
 160  1
       dp = new DocumentPane("HTML");
 161  1
       doc.addDocumentListener(this);
 162  1
       dp.setDocument(doc);
 163  1
       this.doc = doc;
 164   
     }
 165   
     else {
 166  0
       needsSaving = true;
 167  0
       dp = new DocumentPane(url, 1, "HTML"/*, renderMode*/);
 168  0
       this.doc = dp.getDocument();
 169   
     }
 170   
 
 171   
     // init editor to our needs
 172  1
     editor = dp.getEditor();
 173  1
     editor.setEditable(false);
 174  1
     editor.addCaretListener(this);
 175   
 
 176   
     // create document panel
 177  1
     JPanel docPanel = new JPanel(new BorderLayout());
 178  1
     docPanel.setBorder(new TitledBorder(new EtchedBorder(
 179   
         EtchedBorder.LOWERED),
 180   
         FrmMain.dynRes.getResourceString(FrmMain.resources, "docPanelLabel")));
 181  1
     docPanel.add(dp, BorderLayout.CENTER);
 182   
 
 183   
     // use a help panel to properly align anchorPanel and docPanel
 184  1
     helpPanel = new JPanel(new BorderLayout());
 185  1
     helpPanel.add(anchorPanel, BorderLayout.WEST);
 186  1
     helpPanel.add(docPanel, BorderLayout.CENTER);
 187   
 
 188   
     // get content pane of DialogShell to add components to
 189  1
     Container contentPane = super.getContentPane();
 190  1
     ((JComponent) contentPane).setPreferredSize(new Dimension(600,500));
 191  1
     contentPane.add(helpPanel, BorderLayout.CENTER);
 192   
 
 193   
     // add help button
 194   
 
 195   
 
 196   
     // cause optimal placement of all elements
 197  1
     pack();
 198   
 
 199  1
     updateAnchorList();
 200  1
     addAnchor.setEnabled(false);
 201  1
     delAnchor.setEnabled(false);
 202   
   }
 203   
 
 204   
   /**
 205   
    * overridden to addd some custom cleanup upon closing of dialog
 206   
    */
 207  1
   public void dispose() {
 208  1
     editor.removeCaretListener(this);
 209  1
     doc.removeDocumentListener(this);
 210  1
     super.dispose();
 211   
   }
 212   
 
 213   
   /**
 214   
    * re-display the list of anchors of the document
 215   
    */
 216  3
   private void updateAnchorList() {
 217  3
     getAnchors(doc);
 218  3
     anchorList.setListData(anchorTable.keySet().toArray());
 219   
   }
 220   
 
 221   
   /**
 222   
    * get the anchors of a given document
 223   
    *
 224   
    * @param doc the document to get anchors from
 225   
    */
 226  3
   private void getAnchors(Document doc) {
 227  3
     String aTag = HTML.Tag.A.toString();
 228  3
     Object nameAttr;
 229  3
     Object link;
 230  3
     anchorTable.clear();
 231  3
     ElementIterator eli = new ElementIterator(doc);
 232  3
     Element elem = eli.first();
 233  3
     while(elem != null) {
 234  24
       link = elem.getAttributes().getAttribute(HTML.Tag.A);
 235  24
       if(link != null) {
 236  2
         nameAttr = ((AttributeSet) link).getAttribute(HTML.Attribute.NAME);
 237  2
         if(nameAttr != null) {
 238   
           //model.addElement(nameAttr);
 239  2
           anchorTable.put(nameAttr, elem);
 240   
         }
 241   
       }
 242  24
       elem = eli.next();
 243   
     }
 244   
   }
 245   
 
 246   
   /**
 247   
    * get an anchor name and add it at the current editor location
 248   
    */
 249  1
   private void doAddAnchor() {
 250  1
     String anchorName = Util.nameInput(
 251   
         null,
 252   
         "",
 253   
         "addAnchorTitle",
 254   
         "addAnchorText");
 255  1
     if(anchorName != null) {
 256  1
       editor.insertAnchor(anchorName);
 257  1
       saveChanges();
 258  1
       updateAnchorList();
 259   
     }
 260   
   }
 261   
 
 262   
   /**
 263   
    * save changes to the document
 264   
    */
 265  1
   private void saveChanges() {
 266  1
     if(needsSaving) {
 267  0
       if(url != null) {
 268  0
         try {
 269  0
           dp.saveDocument(/*renderMode*/);
 270   
         }
 271   
         catch(Exception e) {
 272  0
           Util.errMsg(this, e.getMessage(), e);
 273   
         }
 274   
       }
 275   
     }
 276   
   }
 277   
 
 278   
   /**
 279   
    * get the anchor currently selected in the list of anchors
 280   
    *
 281   
    * @return  the anchor name, or null if none is selected
 282   
    */
 283  0
   public String getAnchor() {
 284  0
     String anchorName = null;
 285  0
     if(anchorList.getSelectedIndex() > -1) {
 286  0
       anchorName = anchorList.getSelectedValue().toString();
 287   
     }
 288  0
     return anchorName;
 289   
   }
 290   
 
 291   
   /**
 292   
    * remove an anchor from the document
 293   
    */
 294  0
   private void doDelAnchor() {
 295  0
     String anchorName = anchorList.getSelectedValue().toString();
 296  0
     dp.getEditor().removeAnchor(anchorName);
 297  0
     saveChanges();
 298  0
     updateAnchorList();
 299   
   }
 300   
 
 301   
   /**
 302   
    * ActionListener implementatin for proper handling of
 303   
    * buttons
 304   
    */
 305  2
   public void actionPerformed(ActionEvent e) {
 306  2
     Object src = e.getSource();
 307  2
     if(src.equals(addAnchor)) {
 308  1
       doAddAnchor();
 309   
     }
 310  1
     else if(src.equals(delAnchor)) {
 311  0
       doDelAnchor();
 312   
     }
 313   
     else {
 314  1
       super.actionPerformed(e);
 315   
     }
 316   
   }
 317   
 
 318   
   /**
 319   
    * ListSelectionListener implementation to properly react to
 320   
    * changes in the list of anchors
 321   
    */
 322  0
   public void valueChanged(ListSelectionEvent e) {
 323  0
     Object src = e.getSource();
 324  0
     if(src.equals(anchorList)) {
 325   
     //if(!ignoreAnchorListChanges) {
 326  0
       Highlighter h = editor.getHighlighter();
 327  0
       Highlighter.HighlightPainter p = new DefaultHighlighter.DefaultHighlightPainter(Color.yellow);
 328  0
       Object o = anchorList.getSelectedValue();
 329  0
       if(o != null) {
 330  0
         Element elem = (Element) anchorTable.get(anchorList.getSelectedValue());
 331  0
         int start = elem.getStartOffset();
 332  0
         int end = elem.getEndOffset();
 333  0
         try {
 334  0
           if(end == start) {
 335  0
             end = start + 3;
 336   
           }
 337  0
           editor.select(start, end);
 338  0
           h.removeAllHighlights();
 339  0
           h.addHighlight(start, end, p);
 340   
         }
 341   
         catch(BadLocationException ble) {
 342  0
           ble.printStackTrace();
 343   
         }
 344   
       }
 345   
     //}
 346   
     }
 347   
   }
 348   
 
 349   
   /**
 350   
    * CaretListener implementation to adjust 'add anchor' button
 351   
    * according to whether or not a selection is present in the document
 352   
    * to possibly add an anchor to
 353   
    */
 354  1
   public void caretUpdate(CaretEvent e) {
 355  1
     Object src = e.getSource();
 356  1
     if(src.equals(editor)) {
 357  1
       addAnchor.setEnabled(editor.getSelectionStart() != editor.getSelectionEnd());
 358  1
       delAnchor.setEnabled(anchorList.getSelectedIndex() > -1);
 359   
     }
 360   
   }
 361   
 
 362   
   /* -------- DocumentListener implementation start ------------*/
 363   
 
 364   
   /**
 365   
    * listens to inserts into the document to track whether or not the document
 366   
    * needs to be saved.
 367   
    */
 368  0
   public void insertUpdate(DocumentEvent e) {
 369  0
     updateAnchorList();
 370   
   }
 371   
 
 372   
   /**
 373   
    * listens to removes into the document to track whether or not the document
 374   
    * needs to be saved.
 375   
    */
 376  0
   public void removeUpdate(DocumentEvent e) {
 377  0
     updateAnchorList();
 378   
   }
 379   
 
 380   
   /**
 381   
    * listens to changes on the document to track whether or not the document
 382   
    * needs to be saved.
 383   
    */
 384  1
   public void changedUpdate(DocumentEvent e) {
 385  1
     updateAnchorList();
 386   
   }
 387   
 
 388   
   /* -------- DocumentListener implementation end ------------*/
 389   
 }