1 7 8 package org.jdesktop.swing; 9 10 import java.awt.Component ; 11 import java.awt.Dimension ; 12 13 import java.awt.datatransfer.DataFlavor ; 14 import java.awt.datatransfer.Clipboard ; 15 import java.awt.datatransfer.Transferable ; 16 17 import java.awt.event.ActionEvent ; 18 import java.awt.event.ItemEvent ; 19 import java.awt.event.ItemListener ; 20 21 import java.beans.PropertyChangeEvent ; 22 import java.beans.PropertyChangeListener ; 23 24 import java.io.IOException ; 25 import java.io.Reader ; 26 27 import java.net.URL ; 28 29 import java.util.Vector ; 30 import java.util.HashMap ; 31 import java.util.Map ; 32 import java.util.Set ; 33 34 import java.util.regex.Matcher ; 35 import java.util.regex.Pattern ; 36 37 import javax.swing.*; 38 39 import javax.swing.undo.CannotRedoException ; 40 import javax.swing.undo.CannotUndoException ; 41 import javax.swing.undo.UndoManager ; 42 43 import javax.swing.event.CaretEvent ; 44 import javax.swing.event.CaretListener ; 45 import javax.swing.event.UndoableEditEvent ; 46 import javax.swing.event.UndoableEditListener ; 47 48 import javax.swing.text.AttributeSet ; 49 import javax.swing.text.Document ; 50 import javax.swing.text.EditorKit ; 51 import javax.swing.text.Element ; 52 import javax.swing.text.MutableAttributeSet ; 53 import javax.swing.text.Segment ; 54 import javax.swing.text.SimpleAttributeSet ; 55 import javax.swing.text.StyleConstants ; 56 import javax.swing.text.StyledDocument ; 57 import javax.swing.text.StyledEditorKit ; 58 59 import javax.swing.text.html.HTML ; 60 import javax.swing.text.html.HTMLDocument ; 61 62 import org.jdesktop.swing.actions.ActionManager; 63 64 74 public class JXEditorPane extends JEditorPane implements Searchable { 75 76 private Matcher matcher; 77 78 private UndoableEditListener undoHandler; 79 private UndoManager undoManager; 80 private CaretListener caretHandler; 81 private JComboBox selector; 82 83 private final static String ACTION_FIND = "find"; 85 private final static String ACTION_UNDO = "undo"; 86 private final static String ACTION_REDO = "redo"; 87 88 public JXEditorPane() { 89 init(); 90 } 91 92 public JXEditorPane(String url) throws IOException { 93 super(url); 94 init(); 95 } 96 97 public JXEditorPane(String type, String text) { 98 super(type, text); 99 init(); 100 } 101 102 public JXEditorPane(URL initialPage) throws IOException { 103 super(initialPage); 104 init(); 105 } 106 107 private void init() { 108 addPropertyChangeListener(new PropertyHandler()); 109 getDocument().addUndoableEditListener(getUndoableEditListener()); 110 initActions(); 111 } 112 113 private class PropertyHandler implements PropertyChangeListener { 114 public void propertyChange(PropertyChangeEvent evt) { 115 String name = evt.getPropertyName(); 116 if (name.equals("document")) { 117 Document doc = (Document )evt.getOldValue(); 118 if (doc != null) { 119 doc.removeUndoableEditListener(getUndoableEditListener()); 120 } 121 122 doc = (Document )evt.getNewValue(); 123 if (doc != null) { 124 doc.addUndoableEditListener(getUndoableEditListener()); 125 } 126 } 127 } 128 129 } 130 131 CaretListener getCaretListener() { 133 return caretHandler; 134 } 135 136 UndoableEditListener getUndoableEditListener() { 138 if (undoHandler == null) { 139 undoHandler = new UndoHandler(); 140 undoManager = new UndoManager (); 141 } 142 return undoHandler; 143 } 144 145 148 public void setEditorKit(EditorKit kit) { 149 super.setEditorKit(kit); 150 151 if (kit instanceof StyledEditorKit ) { 152 if (caretHandler == null) { 153 caretHandler = new CaretHandler(); 154 } 155 addCaretListener(caretHandler); 156 } 157 } 158 159 162 protected void initActions() { 163 ActionMap map = getActionMap(); 164 map.put(ACTION_FIND, new Actions(ACTION_FIND)); 165 map.put(ACTION_UNDO, new Actions(ACTION_UNDO)); 166 map.put(ACTION_REDO, new Actions(ACTION_REDO)); 167 } 168 169 171 private class UndoHandler implements UndoableEditListener { 172 public void undoableEditHappened(UndoableEditEvent evt) { 173 undoManager.addEdit(evt.getEdit()); 174 updateActionState(); 175 } 176 } 177 178 181 private void updateActionState() { 182 Runnable doEnabled = new Runnable () { 184 public void run() { 185 ActionManager manager = Application.getInstance().getActionManager(); 186 manager.setEnabled(ACTION_UNDO, undoManager.canUndo()); 187 manager.setEnabled(ACTION_REDO, undoManager.canRedo()); 188 } 189 }; 190 SwingUtilities.invokeLater(doEnabled); 191 } 192 193 197 private class Actions extends UIAction { 198 Actions(String name) { 199 super(name); 200 } 201 202 public void actionPerformed(ActionEvent evt) { 203 String name = getName(); 204 if (ACTION_FIND.equals(name)) { 205 find(); 206 } 207 else if (ACTION_UNDO.equals(name)) { 208 try { 209 undoManager.undo(); 210 } catch (CannotUndoException ex) { 211 ex.printStackTrace(); 212 } 213 updateActionState(); 214 } 215 else if (ACTION_REDO.equals(name)) { 216 try { 217 undoManager.redo(); 218 } catch (CannotRedoException ex) { 219 ex.printStackTrace(); 220 } 221 updateActionState(); 222 } 223 else { 224 System.out.println("ActionHandled: " + name); 225 } 226 227 } 228 } 229 230 236 public JComboBox getParagraphSelector() { 237 if (selector == null) { 238 selector = new ParagraphSelector(); 239 } 240 return selector; 241 } 242 243 247 private class ParagraphSelector extends JComboBox implements ItemListener { 248 249 private Map itemMap; 250 251 public ParagraphSelector() { 252 253 itemMap = new HashMap (); 255 itemMap.put(HTML.Tag.P, "Paragraph"); 256 itemMap.put(HTML.Tag.H1, "Heading 1"); 257 itemMap.put(HTML.Tag.H2, "Heading 2"); 258 itemMap.put(HTML.Tag.H3, "Heading 3"); 259 itemMap.put(HTML.Tag.H4, "Heading 4"); 260 itemMap.put(HTML.Tag.H5, "Heading 5"); 261 itemMap.put(HTML.Tag.H6, "Heading 6"); 262 itemMap.put(HTML.Tag.PRE, "Preformatted"); 263 264 Vector items = new Vector (); 266 items.addElement(HTML.Tag.P); 267 items.addElement(HTML.Tag.H1); 268 items.addElement(HTML.Tag.H2); 269 items.addElement(HTML.Tag.H3); 270 items.addElement(HTML.Tag.H4); 271 items.addElement(HTML.Tag.H5); 272 items.addElement(HTML.Tag.H6); 273 items.addElement(HTML.Tag.PRE); 274 275 setModel(new DefaultComboBoxModel(items)); 276 setRenderer(new ParagraphRenderer()); 277 addItemListener(this); 278 setFocusable(false); 279 } 280 281 public void itemStateChanged(ItemEvent evt) { 282 if (evt.getStateChange() == ItemEvent.SELECTED) { 283 applyTag((HTML.Tag )evt.getItem()); 284 } 285 } 286 287 private class ParagraphRenderer extends DefaultListCellRenderer { 288 289 public ParagraphRenderer() { 290 setOpaque(true); 291 } 292 293 public Component getListCellRendererComponent(JList list, 294 Object value, 295 int index, 296 boolean isSelected, 297 boolean cellHasFocus) { 298 super.getListCellRendererComponent(list, value, index, isSelected, 299 cellHasFocus); 300 301 setText((String )itemMap.get(value)); 302 303 return this; 304 } 305 } 306 307 308 } 311 312 315 protected void applyTag(HTML.Tag tag) { 316 Document doc = getDocument(); 317 if (!(doc instanceof HTMLDocument )) { 318 return; 319 } 320 HTMLDocument hdoc = (HTMLDocument )doc; 321 int start = getSelectionStart(); 322 int end = getSelectionEnd(); 323 324 Element element = hdoc.getParagraphElement(start); 325 MutableAttributeSet newAttrs = new SimpleAttributeSet (element.getAttributes()); 326 newAttrs.addAttribute(StyleConstants.NameAttribute, tag); 327 328 hdoc.setParagraphAttributes(start, end - start, newAttrs, true); 329 } 330 331 private JXFindDialog dialog = null; 332 333 337 public void paste() { 338 Clipboard clipboard = getToolkit().getSystemClipboard(); 339 Transferable content = clipboard.getContents(this); 340 if (content != null) { 341 DataFlavor [] flavors = content.getTransferDataFlavors(); 342 try { 343 for (int i = 0; i < flavors.length; i++) { 344 if (String .class.equals(flavors[i].getRepresentationClass())) { 345 Object data = content.getTransferData(flavors[i]); 346 347 if (flavors[i].isMimeTypeEqual("text/plain")) { 348 replaceSelection(data.toString()); 350 break; 351 } 367 } 368 } 369 } catch (Exception ex) { 370 ex.printStackTrace(); 371 } 372 } 373 } 374 375 private void find() { 376 if (dialog == null) { 377 dialog = new JXFindDialog(this); 378 } 379 dialog.setVisible(true); 380 } 381 382 public int search(String searchString) { 383 return search(searchString, -1); 384 } 385 386 public int search(String searchString, int columnIndex) { 387 Pattern pattern = null; 388 if (searchString != null) { 389 return search(Pattern.compile(searchString, 0), columnIndex); 390 } 391 return -1; 392 } 393 394 public int search(Pattern pattern) { 395 return search(pattern, -1); 396 } 397 398 public int search(Pattern pattern, int startIndex) { 399 return search(pattern, startIndex, false); 400 } 401 402 405 public int search(Pattern pattern, int startIndex, boolean backwards) { 406 if (pattern == null) { 407 return -1; 408 } 409 410 int start = startIndex + 1; 411 int end = -1; 412 413 Segment segment = new Segment (); 414 try { 415 Document doc = getDocument(); 416 doc.getText(start, doc.getLength() - start, segment); 417 } catch (Exception ex) { 418 ex.printStackTrace(); 419 } 420 421 matcher = pattern.matcher(segment.toString()); 422 if (matcher.find()) { 423 start = matcher.start() + startIndex; 424 end = matcher.end() + startIndex; 425 select(start + 1, end + 1); 426 } else { 427 return -1; 428 } 429 return end; 430 } 431 432 438 private class CaretHandler implements CaretListener { 439 public void caretUpdate(CaretEvent evt) { 440 StyledDocument document = (StyledDocument )getDocument(); 441 int dot = evt.getDot(); 442 Element elem = document.getCharacterElement(dot); 443 AttributeSet set = elem.getAttributes(); 444 445 ActionManager manager = Application.getInstance().getActionManager(); 446 manager.setSelected("font-bold", StyleConstants.isBold(set)); 447 manager.setSelected("font-italic", StyleConstants.isItalic(set)); 448 manager.setSelected("font-underline", StyleConstants.isUnderline(set)); 449 450 elem = document.getParagraphElement(dot); 451 set = elem.getAttributes(); 452 453 if (selector != null) { 455 selector.setSelectedItem(set.getAttribute(StyleConstants.NameAttribute)); 456 } 457 458 switch (StyleConstants.getAlignment(set)) { 459 case StyleConstants.ALIGN_LEFT: 463 manager.setSelected("left-justify", true); 464 break; 465 466 case StyleConstants.ALIGN_CENTER: 467 manager.setSelected("center-justify", true); 468 break; 469 470 case StyleConstants.ALIGN_RIGHT: 471 manager.setSelected("right-justify", true); 472 break; 473 } 474 } 475 } 476 } 477 | Popular Tags |