1 4 package com.tc; 5 6 import org.apache.commons.io.IOUtils; 7 import org.apache.xmlbeans.XmlError; 8 import org.apache.xmlbeans.XmlException; 9 10 import com.tc.admin.common.XAbstractAction; 11 import com.tc.admin.common.XTextPane; 12 13 import java.awt.Color ; 14 import java.awt.Toolkit ; 15 import java.awt.event.ActionEvent ; 16 import java.awt.event.ActionListener ; 17 import java.awt.event.InputEvent ; 18 import java.awt.event.KeyEvent ; 19 import java.io.File ; 20 import java.io.FileInputStream ; 21 import java.io.StringReader ; 22 import java.util.ArrayList ; 23 import java.util.Collection ; 24 import java.util.Iterator ; 25 import java.util.List ; 26 27 import javax.swing.Action ; 28 import javax.swing.ImageIcon ; 29 import javax.swing.JOptionPane ; 30 import javax.swing.JPopupMenu ; 31 import javax.swing.JSeparator ; 32 import javax.swing.KeyStroke ; 33 import javax.swing.Timer ; 34 import javax.swing.event.DocumentEvent ; 35 import javax.swing.event.DocumentListener ; 36 import javax.swing.event.UndoableEditEvent ; 37 import javax.swing.text.DefaultStyledDocument ; 38 import javax.swing.text.SimpleAttributeSet ; 39 import javax.swing.text.StyleConstants ; 40 import javax.swing.text.StyledDocument ; 41 import javax.swing.undo.UndoManager ; 42 import javax.swing.undo.UndoableEdit ; 43 44 public class ConfigTextPane extends XTextPane { 45 private static final int SHORTCUT_KEY_MASK = 46 Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); 47 48 private SaveAction m_saveAction; 49 private UndoAction m_undoAction; 50 private RedoAction m_redoAction; 51 52 private static final String SAVE_CMD = "Save"; 53 private static final String UNDO_CMD = "Undo"; 54 private static final String REDO_CMD = "Redo"; 55 56 private static final KeyStroke SAVE_STROKE = 57 KeyStroke.getKeyStroke(KeyEvent.VK_S, SHORTCUT_KEY_MASK, false); 58 private static final KeyStroke UNDO_STROKE = 59 KeyStroke.getKeyStroke(KeyEvent.VK_Z, SHORTCUT_KEY_MASK, false); 60 private static final KeyStroke REDO_STROKE = 61 KeyStroke.getKeyStroke(KeyEvent.VK_Z, SHORTCUT_KEY_MASK|InputEvent.SHIFT_MASK, false); 62 63 private ConfigTextListener m_configTextListener; 64 private SimpleAttributeSet m_errorAttrSet; 65 private Timer m_parseTimer; 66 private MyUndoManager m_undoManager; 67 68 public ConfigTextPane() { 69 super(); 70 71 m_errorAttrSet = new SimpleAttributeSet (); 72 StyleConstants.setForeground(m_errorAttrSet, Color.red); 73 74 m_undoManager = new MyUndoManager(); 75 76 JPopupMenu popup = getPopupMenu(); 77 popup.add(new JSeparator ()); 78 popup.add(m_undoAction = new UndoAction()); 79 popup.add(m_redoAction = new RedoAction()); 80 popup.add(new JSeparator ()); 81 popup.add(m_saveAction = new SaveAction()); 82 popup.add(new SaveAsAction()); 83 84 getActionMap().put(SAVE_CMD, m_saveAction); 85 getActionMap().put(UNDO_CMD, m_undoAction); 86 getActionMap().put(REDO_CMD, m_redoAction); 87 88 getInputMap().put(SAVE_STROKE, SAVE_CMD); 89 getInputMap().put(UNDO_STROKE, UNDO_CMD); 90 getInputMap().put(REDO_STROKE, REDO_CMD); 91 92 m_parseTimer = new Timer (2000, new ParseTimerAction()); 93 m_parseTimer.setRepeats(false); 94 95 m_configTextListener = new ConfigTextListener(); 96 } 97 98 private void removeListeners() { 99 m_parseTimer.stop(); 100 getDocument().removeDocumentListener(m_configTextListener); 101 removeUndoableEditListener(); 102 } 103 104 private void addListeners() { 105 getDocument().addDocumentListener(m_configTextListener); 106 addUndoableEditListener(); 107 } 108 109 public void load(String filename) { 110 FileInputStream fis = null; 111 112 removeListeners(); 113 try { 114 fis = new FileInputStream (new File (filename)); 115 setContent(IOUtils.toString(fis)); 116 hasErrors(); 117 } catch(Exception e) { 118 e.printStackTrace(); 119 } finally { 120 IOUtils.closeQuietly(fis); 121 } 122 addListeners(); 123 } 124 125 public void set(String text) { 126 removeListeners(); 127 try { 128 setContent(text); 129 hasErrors(); 130 } catch(Exception e) { 131 e.printStackTrace(); 132 } 133 addListeners(); 134 } 135 136 class ConfigTextListener implements DocumentListener { 137 public void insertUpdate(DocumentEvent e) { 138 m_saveAction.setEnabled(true); 139 m_parseTimer.stop(); 140 m_parseTimer.start(); 141 } 142 143 public void removeUpdate(DocumentEvent e) { 144 m_saveAction.setEnabled(true); 145 m_parseTimer.stop(); 146 m_parseTimer.start(); 147 } 148 149 public void changedUpdate(DocumentEvent e) {} 150 } 151 152 class ParseTimerAction implements ActionListener { 153 public void actionPerformed(ActionEvent ae) { 154 checkForErrors(); 155 } 156 } 157 158 private void checkForErrors() { 159 setEditable(false); 160 removeListeners(); 161 hasErrors(); 162 addListeners(); 163 setEditable(true); 164 } 165 166 class SaveAction extends XAbstractAction { 167 SaveAction() { 168 super("Save"); 169 setAccelerator(SAVE_STROKE); 170 String uri = "/com/tc/admin/icons/save_edit.gif"; 171 setSmallIcon(new ImageIcon (getClass().getResource(uri))); 172 setEnabled(false); 173 } 174 175 public void actionPerformed(ActionEvent ae) { 176 save(); 177 } 178 } 179 180 class SaveAsAction extends XAbstractAction { 181 SaveAsAction() { 182 super("Save As..."); 183 String uri = "/com/tc/admin/icons/saveas_edit.gif"; 184 setSmallIcon(new ImageIcon (getClass().getResource(uri))); 185 } 186 187 public void actionPerformed(ActionEvent ae) { 188 saveAs(); 189 } 190 } 191 192 public boolean hasErrors() { 193 boolean hasErrors = false; 194 195 clearAllStyles(); 196 197 try { 198 TextLineInfo lineInfo = getLineInfo(); 199 200 try { 201 ConfigHelper configHelper = getMainFrame().getConfigHelper(); 202 List errors = configHelper.validate(getText()); 203 204 hasErrors = errors.size() > 0; 205 handleErrors(errors, lineInfo); 206 } catch(XmlException e) { 207 hasErrors = true; 208 209 Collection c = e.getErrors(); 210 ArrayList errorList = new ArrayList (); 211 212 if(c != null) { 213 errorList.addAll(c); 214 handleErrors(new ArrayList (c), lineInfo); 215 } else { 216 errorList.add(e); 217 getMainFrame().setConfigErrors(errorList); 218 } 219 } 220 } catch(Exception e) {e.printStackTrace();} 221 222 return hasErrors; 223 } 224 225 private void clearAllStyles() { 226 StyledDocument doc = (StyledDocument )getDocument(); 227 doc.setCharacterAttributes(0, doc.getLength(), SimpleAttributeSet.EMPTY, true); 228 } 229 230 private void handleErrors(List errorList, TextLineInfo lineInfo) { 231 StyledDocument doc = (StyledDocument )getDocument(); 232 Iterator errors = errorList.iterator(); 233 XmlError error; 234 235 while(errors.hasNext()) { 236 error = (XmlError)errors.next(); 237 238 int line = error.getLine(); 239 int col = error.getColumn(); 240 int start = lineInfo.offset(line-1) + col-1; 241 int len = getElementLength(start); 242 243 doc.setCharacterAttributes(start, len, m_errorAttrSet, true); 244 } 245 246 getMainFrame().setConfigErrors(errorList); 247 } 248 249 private int getElementLength(int start) { 250 StyledDocument doc = (StyledDocument )getDocument(); 251 252 try { 253 String text = doc.getText(start, doc.getLength()-start); 254 int nameEnd = text.indexOf('>'); 255 String name = text.substring(1, nameEnd); 256 String endTok = "</"+name+">"; 257 int endIndex = text.indexOf(endTok); 258 259 if(endIndex != -1) { 260 return endIndex + endTok.length(); 261 } 262 else { 263 return nameEnd+1; 264 } 265 } catch(Exception e ) { 266 return 1; 267 } 268 } 269 270 private void addUndoableEditListener() { 271 ((DefaultStyledDocument )getDocument()).addUndoableEditListener(m_undoManager); 272 } 273 274 private void removeUndoableEditListener() { 275 ((DefaultStyledDocument )getDocument()).removeUndoableEditListener(m_undoManager); 276 } 277 278 private TextLineInfo getLineInfo() { 279 try { 280 return new TextLineInfo(new StringReader (getText())); 281 } catch(Exception e) { 282 return new TextLineInfo(); 283 } 284 } 285 286 void selectError(XmlError error) { 287 TextLineInfo lineInfo = getLineInfo(); 288 int line = error.getLine(); 289 int col = error.getColumn(); 290 int start = lineInfo.offset(line-1) + col-1; 291 int len = getElementLength(start); 292 293 setCaretPosition(start); 294 moveCaretPosition(start+len); 295 296 requestFocusInWindow(); 297 } 298 299 private SessionIntegratorFrame getMainFrame() { 300 return (SessionIntegratorFrame)getAncestorOfClass(SessionIntegratorFrame.class); 301 } 302 303 private void save() { 304 SessionIntegratorFrame frame = getMainFrame(); 305 306 removeListeners(); 307 if(hasErrors()) { 308 String msg = "There are configuration errors. Save anyway?"; 309 String title = frame.getTitle(); 310 int type = JOptionPane.YES_NO_OPTION; 311 int answer = JOptionPane.showConfirmDialog(frame, msg, title, type); 312 313 if(answer == JOptionPane.YES_OPTION) { 314 frame.saveXML(getContent()); 315 } 316 } 317 else { 318 frame.saveXML(getContent()); 319 } 320 addListeners(); 321 m_undoManager.discardAllEdits(); 322 m_saveAction.setEnabled(false); 323 m_undoAction.setEnabled(false); 324 m_redoAction.setEnabled(false); 325 } 326 327 private void saveAs() { 328 SessionIntegratorFrame frame = getMainFrame(); 329 330 removeListeners(); 331 if(hasErrors()) { 332 String msg = "There are configuration errors. Save anyway?"; 333 String title = frame.getTitle(); 334 int type = JOptionPane.YES_NO_OPTION; 335 int answer = JOptionPane.showConfirmDialog(frame, msg, title, type); 336 337 if(answer == JOptionPane.YES_OPTION) { 338 frame.exportConfiguration(); 339 } 340 } 341 else { 342 frame.exportConfiguration(); 343 } 344 addListeners(); 345 } 346 347 class MyUndoManager extends UndoManager { 348 public UndoableEdit nextUndoable() { 349 return editToBeUndone(); 350 } 351 352 public UndoableEdit nextRedoable() { 353 return editToBeRedone(); 354 } 355 356 public void undoableEditHappened(UndoableEditEvent e) { 357 super.undoableEditHappened(e); 358 m_undoAction.setEnabled(canUndo()); 359 m_redoAction.setEnabled(canRedo()); 360 } 361 } 362 363 class UndoAction extends XAbstractAction { 364 UndoAction() { 365 super("Undo"); 366 setAccelerator(UNDO_STROKE); 367 String uri = "/com/tc/admin/icons/undo_edit.gif"; 368 setSmallIcon(new ImageIcon (getClass().getResource(uri))); 369 setEnabled(false); 370 } 371 372 public void actionPerformed(ActionEvent ae) { 373 UndoableEdit next = m_undoManager.nextUndoable(); 374 375 if(next != null) { 376 m_undoManager.undo(); 377 378 setEnabled(m_undoManager.canUndo()); 379 m_redoAction.setEnabled(m_undoManager.canRedo()); 380 } 381 } 382 } 383 384 class RedoAction extends XAbstractAction { 385 RedoAction() { 386 super("Redo"); 387 setAccelerator(REDO_STROKE); 388 String uri = "/com/tc/admin/icons/redo_edit.gif"; 389 setSmallIcon(new ImageIcon (getClass().getResource(uri))); 390 setEnabled(false); 391 } 392 393 public void actionPerformed(ActionEvent ae) { 394 UndoableEdit next = m_undoManager.nextRedoable(); 395 396 if(next != null) { 397 m_undoManager.redo(); 398 setEnabled(m_undoManager.canRedo()); 399 m_undoAction.setEnabled(m_undoManager.canUndo()); 400 } 401 } 402 } 403 404 Action getSaveAction() { return m_saveAction; } 405 Action getUndoAction() { return m_undoAction; } 406 Action getRedoAction() { return m_redoAction; } 407 Action getCutAction() { return m_helper.getCutAction(); } 408 Action getCopyAction() { return m_helper.getCopyAction(); } 409 Action getPasteAction() { return m_helper.getPasteAction(); } 410 } 411 | Popular Tags |