|
|||||||||||||||||||
Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
AnchorDialog.java | 42.9% | 64.3% | 55.6% | 59.5% |
|
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 |
} |
|