Clover coverage report -
Coverage timestamp: Sun Apr 18 2004 21:32:30 EDT
file stats: LOC: 779   Methods: 26
NCLOC: 509   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
LinkDialog.java 19.6% 47.9% 50% 41.9%
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.text.*;
 25   
 import javax.swing.text.html.*;
 26   
 import java.util.*;
 27   
 import java.io.*;
 28   
 import java.net.*;
 29   
 
 30   
 /**
 31   
  * Dialog to create and edit links.
 32   
  *
 33   
  * @author Ulrich Hilger
 34   
  * @author Light Development
 35   
  * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
 36   
  * @author <a href="mailto:info@lightdev.com">info@lightdev.com</a>
 37   
  * @author published under the terms and conditions of the
 38   
  *      GNU General Public License,
 39   
  *      for details see file gpl.txt in the distribution
 40   
  *      package of this software
 41   
  *
 42   
  * @version stage 11, April 27, 2003
 43   
  */
 44   
 
 45   
 public class LinkDialog extends DialogShell implements ActionListener {
 46   
 
 47   
   /** table for link types: name -> type */
 48   
   private Hashtable linkTypes;
 49   
 
 50   
   /** table for link types: type -> name */
 51   
   private Hashtable linkTypeNames;
 52   
 
 53   
   /** cache for link address */
 54   
   private String addressCache = null;
 55   
 
 56   
   /** the document this dialog was constructed with */
 57   
   private Document doc;
 58   
 
 59   
   /** dialog components */
 60   
   private JComboBox linkStyle;
 61   
   private JComboBox linkType;
 62   
   private JTextField linkAddress;
 63   
   private JButton browseAddress;
 64   
   private JTextField linkAnchor;
 65   
   private JButton browseAnchor;
 66   
   private JTextField linkText;
 67   
   private JRadioButton showAsText;
 68   
   private JRadioButton showAsImage;
 69   
   private String linkImageFileName;
 70   
   private ImagePreview linkImage;
 71   
   private JButton setImage;
 72   
   private JTextField linkImgWidth;
 73   
   private JTextField linkImgHeight;
 74   
   private JPanel linkTextPanel;
 75   
   private JPanel linkImagePanel;
 76   
 
 77   
   /** some constants */
 78   
   private String LINK_TYPE_KEY = "linkType";
 79   
   private String LINK_TYPE_NAME_KEY = "linkTypeName";
 80   
   private String LINK_TYPE_RELATIVE_KEY = FrmMain.dynRes.getResourceString(FrmMain.resources, "linkType1");
 81   
   private String LINK_TYPE_NEWS_KEY = FrmMain.dynRes.getResourceString(FrmMain.resources, "linkType7");
 82   
   private String LINK_TYPE_MAILTO_KEY = FrmMain.dynRes.getResourceString(FrmMain.resources, "linkType8");
 83   
   private String LINK_TYPE_RELATIVE = FrmMain.dynRes.getResourceString(FrmMain.resources, "linkTypeName1");
 84   
   private String LINK_TYPE_LOCAL = FrmMain.dynRes.getResourceString(FrmMain.resources, "linkTypeName2");
 85   
   private String LINK_TYPE_NEWS = FrmMain.dynRes.getResourceString(FrmMain.resources, "linkTypeName7");
 86   
   private String LINK_TYPE_MAILTO = FrmMain.dynRes.getResourceString(FrmMain.resources, "linkTypeName8");
 87   
 
 88   
   /** indicates, whether or not action handlers should react on events */
 89   
   private boolean ignoreActions = false;
 90   
 
 91   
   /** the image directory for the document links are edited from in this dialog */
 92   
   private File imgDir;
 93   
 
 94   
   /** the currently selected image file for this link */
 95   
   private String imgFile = null;
 96   
 
 97   
   /** the help id for this dialog */
 98   
   private static final String helpTopicId = "item164";
 99   
 
 100   
   //private int renderMode;
 101   
 
 102   
   /**
 103   
    * construct a new LinkDialog
 104   
    *
 105   
    * If the selection (selectionStart and selectionEnd) has an existing link,
 106   
    * edit this link
 107   
    * Create a link for the selected text otherwise.
 108   
    *
 109   
    * @param parent  the parent frame for the dialog
 110   
    * @param title  the dialog title
 111   
    * @param doc  the document to edit link settings for
 112   
    */
 113  1
   public LinkDialog(Frame parent, String title, Document doc, int selectionStart, int selectionEnd,
 114   
                     File imgDir/*, int renderMode*/)
 115   
   {
 116   
 
 117   
     // initialize DialogShell
 118  1
     super(parent, title, helpTopicId);
 119   
 
 120   
     // save document for later use
 121  1
     this.doc = doc;
 122  1
     this.imgDir = imgDir;
 123   
     //this.renderMode = renderMode;
 124   
 
 125   
     // layout and constraints to use later on
 126  1
     GridBagLayout g = new GridBagLayout();
 127  1
     GridBagConstraints c = new GridBagConstraints();
 128   
 
 129   
     // create link style selector
 130  1
     JPanel p = new JPanel(g);
 131  1
     JLabel lb = new JLabel(FrmMain.dynRes.getResourceString(FrmMain.resources, "linkStyleLabel"));
 132  1
     Util.addGridBagComponent(p, lb, g, c, 0, 0, GridBagConstraints.EAST);
 133  1
     Vector styleNames = Util.getStyleNamesForTag(((SHTMLDocument) doc).getStyleSheet(), HTML.Tag.A.toString());
 134  1
     String standardStyleName = FrmMain.dynRes.getResourceString(FrmMain.resources, "standardStyleName");
 135  1
     styleNames.insertElementAt(standardStyleName, 0);
 136  1
     linkStyle = new JComboBox(styleNames);
 137  1
     Util.addGridBagComponent(p, linkStyle, g, c, 1, 0, GridBagConstraints.WEST);
 138   
 
 139   
     // create link type selector
 140  1
     lb = new JLabel(FrmMain.dynRes.getResourceString(FrmMain.resources, "linkTypeLabel"));
 141  1
     Util.addGridBagComponent(p, lb, g, c, 0, 1, GridBagConstraints.EAST);
 142  1
     buildLinkTypes();
 143  1
     linkType = new JComboBox(linkTypeNames.values().toArray());
 144  1
     linkType.addActionListener(this);
 145  1
     Util.addGridBagComponent(p, linkType, g, c, 1, 1, GridBagConstraints.WEST);
 146   
 
 147   
     // create link address field
 148  1
     lb = new JLabel(FrmMain.dynRes.getResourceString(FrmMain.resources, "linkAddressLabel"));
 149  1
     Util.addGridBagComponent(p, lb, g, c, 0, 2, GridBagConstraints.EAST);
 150  1
     linkAddress = new JTextField();
 151  1
     linkAddress.setPreferredSize(new Dimension(300, 20));
 152  1
     linkAddress.setMaximumSize(new Dimension(500, 20));
 153  1
     linkAddress.addActionListener(this);
 154  1
     Util.addGridBagComponent(p, linkAddress, g, c, 1, 2, GridBagConstraints.WEST, 2, 1, GridBagConstraints.HORIZONTAL, 1, 0);
 155  1
     browseAddress = new JButton(FrmMain.dynRes.getResourceString(FrmMain.resources, "linkBrowseLabel"));
 156  1
     browseAddress.addActionListener(this);
 157  1
     Util.addGridBagComponent(p, browseAddress, g, c, 3, 2, GridBagConstraints.WEST);
 158   
 
 159   
     // create link anchor field
 160  1
     lb = new JLabel(FrmMain.dynRes.getResourceString(FrmMain.resources, "linkAnchorLabel"));
 161  1
     Util.addGridBagComponent(p, lb, g, c, 0, 3, GridBagConstraints.EAST);
 162  1
     linkAnchor = new JTextField();
 163  1
     linkAnchor.setPreferredSize(new Dimension(150, 20));
 164  1
     linkAnchor.setMaximumSize(new Dimension(500, 20));
 165  1
     Util.addGridBagComponent(p, linkAnchor, g, c, 1, 3, GridBagConstraints.WEST, 1, 1, GridBagConstraints.HORIZONTAL, 1, 0);
 166  1
     browseAnchor = new JButton(FrmMain.dynRes.getResourceString(FrmMain.resources, "linkBrowseLabel"));
 167  1
     browseAnchor.addActionListener(this);
 168  1
     Util.addGridBagComponent(p, browseAnchor, g, c, 2, 3, GridBagConstraints.WEST);
 169   
 
 170   
     // create link display selector
 171  1
     lb = new JLabel(FrmMain.dynRes.getResourceString(FrmMain.resources, "linkDisplayLabel"));
 172  1
     Util.addGridBagComponent(p, lb, g, c, 0, 4, GridBagConstraints.EAST);
 173  1
     showAsText = new JRadioButton(FrmMain.dynRes.getResourceString(FrmMain.resources, "showAsTextLabel"));
 174  1
     showAsText.addActionListener(this);
 175  1
     showAsImage = new JRadioButton(FrmMain.dynRes.getResourceString(FrmMain.resources, "showAsImageLabel"));
 176  1
     showAsImage.addActionListener(this);
 177  1
     JPanel helpPanel = new JPanel();
 178  1
     helpPanel.add(showAsText);
 179  1
     helpPanel.add(showAsImage);
 180  1
     Util.addGridBagComponent(p, helpPanel, g, c, 1, 4, GridBagConstraints.WEST);
 181  1
     ButtonGroup bg = new ButtonGroup();
 182  1
     bg.add(showAsText);
 183  1
     bg.add(showAsImage);
 184   
 
 185   
     // create link text panel
 186  1
     linkTextPanel = new JPanel(new BorderLayout());
 187  1
     linkTextPanel.setBorder(new TitledBorder(new EtchedBorder(
 188   
         EtchedBorder.LOWERED),
 189   
         FrmMain.dynRes.getResourceString(FrmMain.resources, "linkTextLabel")));
 190  1
     linkText = new JTextField();
 191  1
     linkText.setPreferredSize(new Dimension(400, 20));
 192  1
     linkText.setMaximumSize(new Dimension(500, 20));
 193  1
     linkTextPanel.add(linkText, BorderLayout.CENTER);
 194  1
     Util.addGridBagComponent(p, linkTextPanel, g, c, 1, 5, GridBagConstraints.WEST, 2, 1, GridBagConstraints.HORIZONTAL, 1, 0);
 195   
     //linkTextPanel.setVisible(false);
 196   
 
 197   
     // create link image panel
 198  1
     linkImagePanel = new JPanel(new BorderLayout(5, 5));
 199  1
     linkImagePanel.setBorder(new TitledBorder(new EtchedBorder(
 200   
         EtchedBorder.LOWERED),
 201   
         FrmMain.dynRes.getResourceString(FrmMain.resources, "linkImageLabel")));
 202  1
     linkImage = new ImagePreview();
 203  1
     linkImage.setPreferredSize(new Dimension(70, 70));
 204  1
     linkImagePanel.add(new JScrollPane(linkImage), BorderLayout.CENTER);
 205  1
     helpPanel = new JPanel(g);
 206  1
     lb = new JLabel(FrmMain.dynRes.getResourceString(FrmMain.resources, "imgWidthLabel"));
 207  1
     Util.addGridBagComponent(helpPanel, lb, g, c, 0, 0, GridBagConstraints.EAST);
 208  1
     linkImgWidth = new JTextField();
 209  1
     linkImgWidth.setPreferredSize(new Dimension(50, 20));
 210  1
     linkImgWidth.setMinimumSize(new Dimension(50, 20));
 211  1
     linkImgWidth.setEditable(false);
 212  1
     Util.addGridBagComponent(helpPanel, linkImgWidth, g, c, 1, 0, GridBagConstraints.WEST);
 213  1
     lb = new JLabel(FrmMain.dynRes.getResourceString(FrmMain.resources, "imgHeightLabel"));
 214  1
     Util.addGridBagComponent(helpPanel, lb, g, c, 0, 1, GridBagConstraints.EAST);
 215  1
     linkImgHeight = new JTextField();
 216  1
     linkImgHeight.setPreferredSize(new Dimension(50, 20));
 217  1
     linkImgHeight.setMinimumSize(new Dimension(50, 20));
 218  1
     linkImgHeight.setEditable(false);
 219  1
     Util.addGridBagComponent(helpPanel, linkImgHeight, g, c, 1, 1, GridBagConstraints.WEST);
 220  1
     setImage = new JButton(FrmMain.dynRes.getResourceString(FrmMain.resources, "setImageLabel"));
 221  1
     setImage.addActionListener(this);
 222  1
     Util.addGridBagComponent(helpPanel, setImage, g, c, 1, 2, GridBagConstraints.WEST);
 223  1
     JPanel helpPanel2 = new JPanel(new BorderLayout());
 224  1
     helpPanel2.add(helpPanel, BorderLayout.NORTH);
 225  1
     linkImagePanel.add(helpPanel2, BorderLayout.EAST);
 226  1
     Util.addGridBagComponent(p, linkImagePanel, g, c, 1, 5, GridBagConstraints.WEST, 2, 1, GridBagConstraints.BOTH, 1, 1);
 227   
 
 228   
     // get content pane of DialogShell to add components to
 229  1
     Container contentPane = super.getContentPane();
 230   
 
 231   
     // add panels to content pane of DialogShell
 232  1
     contentPane.add(p, BorderLayout.CENTER);
 233   
 
 234   
     // cause optimal placement of all elements
 235  1
     pack();
 236   
 
 237   
     // init dialog with existing link (if any)
 238  1
     if(!setExistingLink(selectionStart, selectionEnd)) {
 239  1
       setLinkText(selectionStart, selectionEnd);
 240   
     }
 241   
 
 242   
   }
 243   
 
 244   
   /**
 245   
    * set the link text component of this dialog from the document
 246   
    * this dialog is associated to
 247   
    *
 248   
    * @param start  the start position of the link text in the document
 249   
    * @param end  the end position of the link text in the document
 250   
    */
 251  2
   private void setLinkText(int start, int end) {
 252  2
     try {
 253  2
       linkText.setText(doc.getText(start, end - start));
 254   
       //System.out.println("showAsText = true");
 255  2
       showAsText.setSelected(true);
 256  2
       linkTextPanel.setVisible(true);
 257  2
       linkImagePanel.setVisible(false);
 258   
     }
 259   
     catch(BadLocationException ble) {
 260  0
       Util.errMsg(this, ble.getLocalizedMessage(), ble);
 261   
     }
 262   
   }
 263   
 
 264   
   /**
 265   
    * set components of this dialog from an exisiting link in
 266   
    * the associated document (if any).
 267   
    *
 268   
    * @param selStart  the start position of the text currently selected in the document
 269   
    * @param selEnd  the end position of the text currently selected in the document
 270   
    *
 271   
    * @return ture, if a link was found, false if not
 272   
    */
 273  1
   private boolean setExistingLink(int selStart, int selEnd) {
 274  1
     setIgnoreActions(true);
 275  1
     Element e = Util.findLinkElementUp(((SHTMLDocument) doc).getCharacterElement(selStart));
 276  1
     boolean foundLink = (e != null);
 277  1
     if(foundLink) {
 278  0
       AttributeSet elemAttrs = e.getAttributes();
 279  0
       Object linkAttr = elemAttrs.getAttribute(HTML.Tag.A);
 280  0
       Object href = ((AttributeSet) linkAttr).getAttribute(HTML.Attribute.HREF);
 281  0
       if(href != null) {
 282  0
         try {
 283  0
           setDialogFromUrl(new URL(href.toString()));
 284   
         }
 285   
         catch(Exception ex) {
 286  0
           setDialogFromRelative(href.toString());
 287   
         }
 288  0
         Object img = elemAttrs.getAttribute(HTML.Attribute.SRC);
 289  0
         if(img != null) {
 290  0
           setLinkImage(img, elemAttrs);
 291   
         }
 292   
         else {
 293  0
           setLinkText(e.getStartOffset(), e.getEndOffset());
 294   
         }
 295   
       }
 296   
     }
 297   
     else {
 298  1
       linkType.setSelectedItem(LINK_TYPE_LOCAL);
 299  1
       setLinkText(selStart, selEnd);
 300   
     }
 301  1
     setIgnoreActions(false);
 302  1
     return foundLink;
 303   
   }
 304   
 
 305   
   /**
 306   
    * set the link image to be shown in this dialog from a given
 307   
    * image file name and AttributeSet
 308   
    *
 309   
    * @param imgAttr  the file name of the image to be shown
 310   
    * @param attrSet  the set of attributes having width and height of the image (if any)
 311   
    */
 312  0
   public void setLinkImage(Object imgAttr, AttributeSet attrSet) {
 313  0
     String wStr = null;
 314  0
     String hStr = null;
 315  0
     if(imgAttr != null) {
 316  0
       imgFile = Util.resolveRelativePath(imgAttr.toString(), ((SHTMLDocument) doc).getBase().getPath()).replace(
 317   
           Util.URL_SEPARATOR_CHAR, File.separatorChar);
 318  0
       while(imgFile.startsWith(File.separator)) {
 319  0
         imgFile = imgFile.substring(1);
 320   
       }
 321   
     }
 322  0
     Object width = attrSet.getAttribute(HTML.Attribute.WIDTH);
 323  0
     if(width != null) {
 324  0
       wStr = width.toString();
 325   
     }
 326  0
     Object height = attrSet.getAttribute(HTML.Attribute.HEIGHT);
 327  0
     if(height != null) {
 328  0
       hStr = height.toString();
 329   
     }
 330  0
     setImageSpecs(wStr, hStr);
 331  0
     showAsImage.setSelected(true);
 332  0
     linkTextPanel.setVisible(false);
 333  0
     linkImagePanel.setVisible(true);
 334   
   }
 335   
 
 336   
   /**
 337   
    * get the text to be displayed for the link
 338   
    *
 339   
    * @return the link text
 340   
    */
 341  1
   public String getLinkText() {
 342  1
     return linkText.getText();
 343   
   }
 344   
 
 345   
   /**
 346   
    * get the style name (attribute 'class') to be used for
 347   
    * a link
 348   
    *
 349   
    * @return the style name
 350   
    */
 351  1
   public String getStyleName() {
 352  1
     return linkStyle.getSelectedItem().toString();
 353   
   }
 354   
 
 355   
   /**
 356   
    * set this dialog to ignore actions
 357   
    *
 358   
    * @param ignore  indicator whether or not to ignore actions
 359   
    */
 360  2
   public void setIgnoreActions(boolean ignore) {
 361  2
     ignoreActions = ignore;
 362   
   }
 363   
 
 364   
   /**
 365   
    * set the components of this dialog from a given URL
 366   
    *
 367   
    * @param url  the url to set link components from
 368   
    */
 369  0
   private void setDialogFromUrl(URL url) {
 370  0
     if(url != null) {
 371  0
       String protName;
 372  0
       String protocol = url.getProtocol();
 373  0
       if(protocol != null) {
 374  0
         protName = (String) linkTypeNames.get(protocol);
 375   
       }
 376   
       else {
 377  0
         protName = (String) linkTypeNames.get(LINK_TYPE_RELATIVE_KEY);
 378   
       }
 379  0
       if(protName != null) {
 380  0
         linkType.setSelectedItem(protName);
 381   
       }
 382  0
       setLinkAddress(getPathFromUrl(url, protocol));
 383  0
       linkAnchor.setText(url.getRef());
 384   
     }
 385   
   }
 386   
 
 387   
   /**
 388   
    * extract the path from a URL
 389   
    *
 390   
    * @param url  the url to get the path from
 391   
    * @param protocol  the protocol of the url
 392   
    *
 393   
    * @return the path of the URL
 394   
    */
 395  0
   private String getPathFromUrl(URL url, String protocol) {
 396  0
     String path = "";
 397  0
     String urlStr = url.toString();
 398  0
     int pos = urlStr.indexOf(protocol);
 399  0
     if(pos > -1) {
 400  0
       path = urlStr.substring(protocol.length());
 401  0
       while(path.startsWith(Util.URL_SEPARATOR) || path.startsWith(Util.PROTOCOL_SEPARATOR)) {
 402  0
         path = path.substring(1);
 403   
       }
 404   
     }
 405  0
     pos = path.indexOf(Util.ANCHOR_SEPARATOR);
 406  0
     if(pos > -1) {
 407  0
       path = path.substring(0, pos);
 408   
     }
 409  0
     return path;
 410   
   }
 411   
 
 412   
   /**
 413   
    * set components of this dialog from a relative link path
 414   
    *
 415   
    * @param hrefStr  the relative link to show in the dialog
 416   
    */
 417  0
   private void setDialogFromRelative(String hrefStr) {
 418  0
     linkType.setSelectedItem(LINK_TYPE_RELATIVE);
 419  0
     int pos = hrefStr.indexOf(Util.ANCHOR_SEPARATOR);
 420  0
     if(pos > -1) {
 421  0
       linkAnchor.setText(hrefStr.substring(pos + 1));
 422  0
       hrefStr = hrefStr.substring(0, pos);
 423   
     }
 424  0
     setLinkAddress(hrefStr);
 425   
   }
 426   
 
 427   
   /**
 428   
    * build link type tables to match
 429   
    * type names by types and vice versa
 430   
    */
 431  1
   private void buildLinkTypes() {
 432  1
     String name;
 433  1
     String type;
 434  1
     linkTypes = new Hashtable(); // key = type name -> value = type
 435  1
     linkTypeNames = new Hashtable(); // key = type -> value = type name
 436  1
     for(int i = 1; i < 9; i++) {
 437  8
       type = FrmMain.dynRes.getResourceString(FrmMain.resources, LINK_TYPE_KEY + Integer.toString(i));
 438  8
       name = FrmMain.dynRes.getResourceString(FrmMain.resources, LINK_TYPE_NAME_KEY + Integer.toString(i));
 439  8
       linkTypes.put(name, type);
 440  8
       linkTypeNames.put(type, name);
 441   
     }
 442   
   }
 443   
 
 444   
   /**
 445   
    * get the chosen protocol
 446   
    */
 447  1
   private String getProtocol() {
 448  1
     String prot = null;
 449  1
     try {
 450  1
       String protName = linkType.getSelectedItem().toString();
 451  1
       if(!protName.equalsIgnoreCase(LINK_TYPE_RELATIVE)) {
 452  1
         prot = transformProtocol(linkTypes.get(protName).toString());
 453   
       }
 454   
     }
 455   
     catch(Exception e) {}
 456  1
     return prot;
 457   
   }
 458   
 
 459   
   /**
 460   
    * transform a given protocol to be shown in the correct notation
 461   
    */
 462  1
   private String transformProtocol(String protName) {
 463  1
     StringBuffer prot = new StringBuffer(protName);
 464  1
     if(protName.equalsIgnoreCase(LINK_TYPE_MAILTO_KEY) || protName.equalsIgnoreCase(LINK_TYPE_NEWS_KEY)) {
 465  0
       prot.append(Util.PROTOCOL_SEPARATOR);
 466   
     }
 467   
     else {
 468  1
       if(!protName.equalsIgnoreCase(LINK_TYPE_RELATIVE_KEY)) {
 469  1
         prot.append(Util.PROTOCOL_SEPARATOR + Util.URL_SEPARATOR);
 470   
       }
 471   
     }
 472  1
     return prot.toString();
 473   
   }
 474   
 
 475   
   /**
 476   
    * get a file from a file chooser
 477   
    *
 478   
    * @return the chosen file, or null, if none has been chosen or cancel has benn pressed
 479   
    */
 480  0
   private File chooseFile() {
 481  0
     File file = null;
 482  0
     JFileChooser chooser = new JFileChooser();
 483  0
     chooser.setMultiSelectionEnabled(false);
 484  0
     chooser.setSelectedFile(new File(((SHTMLDocument) doc).getBase().getFile()));
 485  0
     if(chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
 486  0
       file = chooser.getSelectedFile();
 487   
     }
 488  0
     return file;
 489   
   }
 490   
 
 491   
   /**
 492   
    * set the address field of this <code>LinkDialog</code>
 493   
    *
 494   
    * @param address  the address to be set
 495   
    */
 496  0
   private void setLinkAddress(String address) {
 497  0
     addressCache = getLinkAddress();
 498  0
     linkAddress.setText(address);
 499   
   }
 500   
 
 501   
   /**
 502   
    * get a set of attributes to represent the link
 503   
    * defined in this dialog
 504   
    *
 505   
    * @return the set of attributes defining this link
 506   
    */
 507  0
   public AttributeSet getLinkAttribute() {
 508  0
     SimpleAttributeSet aSet = new SimpleAttributeSet();
 509  0
     aSet.addAttribute(HTML.Attribute.HREF, getHref());
 510  0
     SimpleAttributeSet set = new SimpleAttributeSet();
 511  0
     if(showAsImage.isSelected()) {
 512  0
       SimpleAttributeSet imgSet = new SimpleAttributeSet();
 513  0
       imgSet.addAttribute(HTML.Attribute.SRC, imgFile);
 514  0
       set.addAttribute(HTML.Tag.IMG, imgSet);
 515   
     }
 516  0
     set.addAttribute(HTML.Tag.A, aSet);
 517  0
     return set;
 518   
   }
 519   
 
 520   
   /**
 521   
    * get the file name of the image to be taken
 522   
    * for the link defined in this dialog
 523   
    *
 524   
    * @return the image file name
 525   
    */
 526  1
   public String getLinkImage() {
 527  1
     if(showAsImage.isSelected()) {
 528  0
       return imgFile;
 529   
     }
 530   
     else {
 531  1
       return null;
 532   
     }
 533   
   }
 534   
 
 535   
   /**
 536   
    * get the size of the image to be taken
 537   
    * for the link defined in this dialog
 538   
    *
 539   
    * @return the image size
 540   
    */
 541  1
   public Dimension getLinkImageSize() {
 542  1
     if(showAsImage.isSelected()) {
 543  0
       try {
 544  0
         return new Dimension(Integer.parseInt(linkImgWidth.getText()), Integer.parseInt(linkImgHeight.getText()));
 545   
       }
 546   
       catch(Exception e) {
 547  0
         return null;
 548   
       }
 549   
     }
 550   
     else {
 551  1
       return null;
 552   
     }
 553   
   }
 554   
 
 555   
   /**
 556   
    * get the currently selected link address
 557   
    *
 558   
    * @return the link address
 559   
    */
 560  0
   public String getLinkAddress() {
 561  0
     String link = linkAddress.getText();
 562  0
     String prot = getProtocol();
 563  0
     if(prot != null &&
 564   
        !prot.equalsIgnoreCase(transformProtocol(LINK_TYPE_RELATIVE_KEY)) &&
 565   
        !prot.equalsIgnoreCase(transformProtocol(LINK_TYPE_MAILTO_KEY)) &&
 566   
        !link.startsWith(Util.URL_SEPARATOR))
 567   
     {
 568  0
       link = Util.URL_SEPARATOR + link;
 569   
     }
 570  0
     return link;
 571   
   }
 572   
 
 573   
   /**
 574   
    * get the link reference
 575   
    *
 576   
    * @return the object this link refers to
 577   
    */
 578  1
   public String getHref() {
 579  1
     StringBuffer href = new StringBuffer();
 580  1
     String prot = getProtocol();
 581   
 
 582  1
     String linkAddrText = linkAddress.getText();
 583  1
     String linkAnchText = linkAnchor.getText();
 584   
 
 585  1
     if((linkAddrText == null || linkAddrText.length() < 1) && (linkAnchText != null && linkAnchText.length() > 0)) {
 586   
       // link to an anchor inside this document
 587  1
       href.append(Util.ANCHOR_SEPARATOR);
 588  1
       href.append(linkAnchText);
 589   
     }
 590   
     else {
 591  0
       if(prot != null) {
 592  0
         href.append(prot);
 593   
       }
 594  0
       href.append(getLinkAddress());
 595  0
       String anchor = linkAnchor.getText();
 596  0
       if(anchor.length() > 0) {
 597  0
         href.append(Util.ANCHOR_SEPARATOR);
 598  0
         href.append(anchor);
 599   
       }
 600   
     }
 601  1
     return href.toString();
 602   
   }
 603   
 
 604   
   /**
 605   
    * get the file this link refers to (if any)
 606   
    *
 607   
    * @return the file this link refers to, or null if no file is referenced
 608   
    */
 609  0
   private File getLinkedFile() {
 610  0
     File file = null;
 611  0
     try {
 612  0
       String prot = linkType.getSelectedItem().toString();
 613  0
       if(prot.equalsIgnoreCase(LINK_TYPE_LOCAL)) {
 614  0
         file = new File(getLinkAddress().replace(Util.URL_SEPARATOR_CHAR, File.separatorChar));
 615   
       }
 616  0
       else if(prot.equalsIgnoreCase(LINK_TYPE_RELATIVE)) {
 617  0
         File from = new File(((SHTMLDocument) doc).getBase().getPath());
 618  0
         String toStr = getLinkAddress();
 619  0
         File to = new File(toStr);
 620  0
         file = new File(Util.resolveRelativePath(getLinkAddress(), ((SHTMLDocument) doc).getBase().getPath()));
 621   
       }
 622   
     }
 623   
     catch(Exception e) {}
 624  0
     return file;
 625   
   }
 626   
 
 627   
   /** -------- ActionListener implementation start (including additional handling methods) ---------- */
 628   
 
 629   
   /**
 630   
    * actionListener implementation to control dialog components
 631   
    */
 632  2
   public void actionPerformed(ActionEvent e) {
 633  2
     if(!ignoreActions) {
 634  1
       Object src = e.getSource();
 635  1
       if(src.equals(showAsText)) {
 636  0
         linkTextPanel.setVisible(true);
 637  0
         linkImagePanel.setVisible(false);
 638   
       }
 639  1
       else if(src.equals(showAsImage)) {
 640  0
         linkTextPanel.setVisible(false);
 641  0
         linkImagePanel.setVisible(true);
 642   
       }
 643  1
       else if(src.equals(browseAddress)) {
 644  0
         File file = chooseFile();
 645  0
         if(file != null) {
 646  0
           setLinkAddress(file.getPath().replace(File.separatorChar, Util.URL_SEPARATOR_CHAR));
 647   
         }
 648   
       }
 649  1
       else if(src.equals(linkType)) {
 650  0
         handleLinkTypeAction();
 651   
       }
 652  1
       else if(src.equals(browseAnchor)) {
 653  0
         handleBrowseAnchorAction();
 654   
       }
 655  1
       else if(src.equals(setImage)) {
 656  0
         handleLinkImageAction();
 657   
       }
 658   
       else {
 659  1
         super.actionPerformed(e);
 660   
       }
 661   
     }
 662   
   }
 663   
 
 664   
   /**
 665   
    * handle an action performed by the component that allows
 666   
    * selection of a link image
 667   
    */
 668  0
   private void handleLinkImageAction() {
 669  0
     ImageDialog dlg = new ImageDialog(this,
 670   
                                      FrmMain.dynRes.getResourceString(FrmMain.resources,
 671   
                                      "imageDialogTitle"),
 672   
                                      imgDir);
 673  0
     if(imgFile != null) {
 674  0
       dlg.setImage(imgFile, linkImgWidth.getText(), linkImgHeight.getText());
 675   
     }
 676  0
     Util.center(this, dlg);
 677  0
     dlg.setModal(true);
 678  0
     dlg.show();
 679   
 
 680   
     /** if the user made a selection, apply it to the document */
 681  0
     if(dlg.getResult() == DialogShell.RESULT_OK) {
 682  0
       imgFile = Util.resolveRelativePath(dlg.getImageSrc(), ((SHTMLDocument) doc).getBase().getPath()).replace(
 683   
           Util.URL_SEPARATOR_CHAR, File.separatorChar);
 684  0
       while(imgFile.startsWith(File.separator)) {
 685  0
         imgFile = imgFile.substring(1);
 686   
       }
 687  0
       setImageSpecs(dlg.getImgWidth().toString(), dlg.getImgHeight().toString());
 688   
     }
 689   
   }
 690   
 
 691   
   /**
 692   
    * set the properties of the image to be shown for
 693   
    * the link defined ni this dialog
 694   
    *
 695   
    * @param width  image width
 696   
    * @param height image height
 697   
    */
 698  0
   private void setImageSpecs(String width, String height) {
 699  0
     ImageIcon icon = new ImageIcon(imgFile);
 700  0
     linkImage.setImage(icon);
 701  0
     linkImage.setScale(100);
 702  0
     if(width != null) {
 703  0
       linkImgWidth.setText(width);
 704  0
       linkImage.setPreviewWidth(Integer.parseInt(width));
 705   
     }
 706  0
     if(height != null) {
 707  0
       linkImgHeight.setText(height);
 708  0
       linkImage.setPreviewHeight(Integer.parseInt(height));
 709   
     }
 710   
   }
 711   
 
 712   
   /**
 713   
    * handle an action performed by the component that allows
 714   
    * selection of a link protocol ('link type' on the GUI)
 715   
    */
 716  0
   private void handleLinkTypeAction() {
 717  0
     String type = linkType.getSelectedItem().toString();
 718  0
     browseAddress.setEnabled(type.equalsIgnoreCase(LINK_TYPE_LOCAL));
 719  0
     browseAnchor.setEnabled(type.equalsIgnoreCase(LINK_TYPE_LOCAL) || type.equalsIgnoreCase(LINK_TYPE_RELATIVE));
 720  0
     if(type.equalsIgnoreCase(LINK_TYPE_RELATIVE)) {
 721  0
       try {
 722  0
         File from = new File(((SHTMLDocument) doc).getBase().getPath());
 723  0
         String toStr = getLinkAddress();
 724  0
         File to = new File(toStr);
 725  0
         setLinkAddress(Util.getRelativePath(from, to));
 726   
       }
 727   
       catch(Exception ex) {
 728  0
         Util.errMsg(this, null, ex);
 729   
       }
 730   
     }
 731  0
     else if(type.equalsIgnoreCase(LINK_TYPE_LOCAL)) {
 732  0
       try {
 733  0
         String absPath = ((SHTMLDocument) doc).getBase().getFile().substring(1);
 734  0
         String relPath = getLinkAddress();
 735  0
         setLinkAddress(Util.URL_SEPARATOR + Util.resolveRelativePath(relPath, absPath));
 736   
       }
 737   
       catch(Exception ex) {
 738  0
         Util.errMsg(this, ex.getMessage(), ex);
 739   
       }
 740   
     }
 741   
   }
 742   
 
 743   
   /**
 744   
    * handle an action performed by the button used
 745   
    * to browse anchors of a given file
 746   
    */
 747  0
   private void handleBrowseAnchorAction() {
 748   
     //System.out.println("LinkDialog actionPerformed browseAnchor file=" + getLinkedFile().getAbsolutePath());
 749  0
     try {
 750  0
       AnchorDialog dlg;
 751  0
       File file = getLinkedFile();
 752  0
       String linkAddrText = linkAddress.getText();
 753  0
       if(linkAddrText == null || linkAddrText.length() < 1) {
 754  0
         dlg = new AnchorDialog(
 755   
             this,
 756   
             FrmMain.dynRes.getResourceString(FrmMain.resources, "anchorDialogTitle"),
 757   
             doc);
 758   
       }
 759   
       else {
 760  0
         dlg = new AnchorDialog(
 761   
             this,
 762   
             FrmMain.dynRes.getResourceString(FrmMain.resources, "anchorDialogTitle"),
 763   
             file.toURL());
 764   
       }
 765  0
       Util.center(this, dlg);
 766  0
       dlg.setModal(true);
 767  0
       dlg.show();
 768  0
       if(dlg.getResult() == DialogShell.RESULT_OK) {
 769  0
         linkAnchor.setText(dlg.getAnchor());
 770   
       }
 771   
     }
 772   
     catch(MalformedURLException ex) {
 773  0
       Util.errMsg(this, ex.getMessage(), ex);
 774   
     }
 775   
   }
 776   
 
 777   
   /** -------- ActionListener implementation end  (including additional handling methods) ---------- */
 778   
 
 779   
 }