0001: /*
0002: * Copyright 2001-2006 C:1 Financial Services GmbH
0003: *
0004: * This software is free software; you can redistribute it and/or
0005: * modify it under the terms of the GNU Lesser General Public
0006: * License Version 2.1, as published by the Free Software Foundation.
0007: *
0008: * This software is distributed in the hope that it will be useful,
0009: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0010: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0011: * Lesser General Public License for more details.
0012: *
0013: * You should have received a copy of the GNU Lesser General Public
0014: * License along with this library; if not, write to the Free Software
0015: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
0016: */
0017:
0018: package de.finix.contelligent.client.gui.text;
0019:
0020: import java.awt.Color;
0021: import java.awt.event.ActionEvent;
0022: import java.awt.event.KeyAdapter;
0023: import java.awt.event.KeyEvent;
0024: import java.io.File;
0025: import java.io.FileNotFoundException;
0026: import java.io.FileReader;
0027: import java.io.FileWriter;
0028: import java.io.IOException;
0029: import java.io.InputStream;
0030: import java.io.OutputStream;
0031: import java.io.Reader;
0032: import java.io.Writer;
0033: import java.util.HashMap;
0034: import java.util.List;
0035: import java.util.Map;
0036: import java.util.Vector;
0037: import java.util.logging.Level;
0038: import java.util.logging.Logger;
0039:
0040: import javax.swing.Action;
0041: import javax.swing.InputMap;
0042: import javax.swing.JEditorPane;
0043: import javax.swing.JFileChooser;
0044: import javax.swing.JOptionPane;
0045: import javax.swing.KeyStroke;
0046: import javax.swing.SwingUtilities;
0047: import javax.swing.text.AttributeSet;
0048: import javax.swing.text.BadLocationException;
0049: import javax.swing.text.DefaultEditorKit;
0050: import javax.swing.text.Document;
0051: import javax.swing.text.MutableAttributeSet;
0052: import javax.swing.text.SimpleAttributeSet;
0053: import javax.swing.text.StyleConstants;
0054: import javax.swing.text.StyledEditorKit;
0055: import javax.swing.undo.UndoManager;
0056:
0057: import de.finix.contelligent.client.base.ComponentFactory;
0058: import de.finix.contelligent.client.base.ContelligentComponent;
0059: import de.finix.contelligent.client.base.ContelligentConstants;
0060: import de.finix.contelligent.client.event.ContelligentComponentDisplayEvent;
0061: import de.finix.contelligent.client.gui.ContelligentAction;
0062: import de.finix.contelligent.client.gui.View;
0063: import de.finix.contelligent.client.i18n.Resources;
0064: import de.finix.contelligent.client.modules.preferences.PreferencesModule;
0065: import de.finix.contelligent.client.util.CharsetUtil;
0066: import de.finix.contelligent.client.util.ExceptionDialog;
0067:
0068: //spellcheck
0069: //import azcheck.ui.JSpellDialog;
0070:
0071: public class ContelligentEditorKit extends StyledEditorKit {
0072:
0073: private final static Object[] OK_OPTIONS = { Resources
0074: .getLocalString("ok") };
0075:
0076: public final static int PLAIN_TEXT = 0;
0077:
0078: public final static int HANDLE_CONTELLIGENT_TAG = 1;
0079:
0080: public final static int HANDLE_MARKUP = 2;
0081:
0082: private final static int TEXT_MODE = 0;
0083:
0084: private final static int TAG_MODE = 1;
0085:
0086: private final static Color SEARCH_HIGHLIGHT_COLOR = Color.cyan;
0087:
0088: private final static Color REPLACED_HIGHLIGHT_COLOR = Color.green;
0089:
0090: private static Logger logger = Logger
0091: .getLogger(ContelligentEditorKit.class.getName());
0092:
0093: // For search actions
0094: private FindAction findAction = new FindAction();
0095:
0096: private ReplaceAction replaceAction = new ReplaceAction();
0097:
0098: private FindAgainAction findAgainAction = new FindAgainAction();
0099:
0100: private CancelSearchAction cancelAction = new CancelSearchAction();
0101:
0102: private FindDialog findDialog = null;
0103:
0104: private ReplaceDialog replaceDialog = null;
0105:
0106: private UndoAction undoAction = new UndoAction();
0107:
0108: private RedoAction redoAction = new RedoAction();
0109:
0110: // do not construct new action objects to keep garbage small
0111: // additionally, if we use the same action over and over again
0112: // we can be sure, MenuAndToolbarComposer deregisters all
0113: // pending listeners from our action before using next time...
0114: private ImportAction importAction = new ImportAction();
0115:
0116: private ExportAction exportAction = new ExportAction();
0117:
0118: private NormalTextAction normalTextAction = new NormalTextAction();
0119:
0120: private BoldTextAction boldTextAction = new BoldTextAction();
0121:
0122: private UnderlineTextAction underlineTextAction = new UnderlineTextAction();
0123:
0124: private ItalicTextAction italicTextAction = new ItalicTextAction();
0125:
0126: private ToggleTagAction toggleTagAction = new ToggleTagAction();
0127:
0128: private CutTextAction cutTextAction = new CutTextAction();
0129:
0130: private CopyTextAction copyTextAction = new CopyTextAction();
0131:
0132: private PasteTextAction pasteTextAction = new PasteTextAction();
0133:
0134: // private SpellCheckAction spellCheckAction = new SpellCheckAction();
0135: // private AutoSpellCheckAction autoSpellCheckAction = new
0136: // AutoSpellCheckAction();
0137:
0138: // special action needing component
0139: private LinkAction linkAction = new LinkAction();
0140:
0141: private EditAction editAction = new EditAction();
0142:
0143: // internal data for searching
0144: private int serachIndexFrom = 0;
0145:
0146: private int orgPos = 0;
0147:
0148: // make this static to preserve selections over more than one editor
0149: private static String searchString = "";
0150:
0151: private static String replaceString = "";
0152:
0153: private int replaceOption;
0154:
0155: private int featureSet;
0156:
0157: private int featureSetRich;
0158:
0159: private JEditorPane editor;
0160:
0161: private TextEditor textEditor; // needed to update resource (bug #295)
0162:
0163: private final boolean isFeatureRichEditor;
0164:
0165: private View view;
0166:
0167: public ContelligentEditorKit(int featureSet, View view) {
0168: this .featureSet = this .featureSetRich = featureSet;
0169: this .isFeatureRichEditor = true;
0170: this .view = view;
0171: }
0172:
0173: public ContelligentEditorKit(View view) {
0174: this .featureSet = this .featureSetRich = PLAIN_TEXT;
0175: this .isFeatureRichEditor = false;
0176: this .view = view;
0177: }
0178:
0179: /**
0180: * Sets the textEditor.
0181: *
0182: * @param textEditor
0183: * The textEditor to set
0184: */
0185: public void setTextEditor(TextEditor textEditor) {
0186: this .textEditor = textEditor;
0187: }
0188:
0189: public void setEditor(JEditorPane editor) {
0190: this .editor = editor;
0191:
0192: InputMap im = editor.getInputMap();
0193:
0194: KeyStroke typed010 = KeyStroke.getKeyStroke("typed \010"); // old code
0195: KeyStroke bksp = KeyStroke.getKeyStroke("BACK_SPACE");
0196: KeyStroke ctrlH = KeyStroke.getKeyStroke("ctrl H");
0197:
0198: // remove old binding
0199: InputMap parent = im;
0200: while (parent != null) {
0201: parent.remove(typed010);
0202: parent = parent.getParent();
0203: }
0204:
0205: // rebind backspace
0206: im.put(bksp, DefaultEditorKit.deletePrevCharAction);
0207:
0208: // add a new binding (just as an example, we dont need this)
0209: // im.put(ctrlH, DefaultEditorKit.backwardAction);
0210:
0211: editor.addKeyListener(new KeyAdapter() {
0212: public void keyPressed(KeyEvent e) {
0213: if (!e.isActionKey()
0214: && !e.isControlDown()
0215: && KeyStroke.getKeyStroke("control F")
0216: .getKeyCode() != e.getKeyCode()
0217: && KeyStroke.getKeyStroke("control G")
0218: .getKeyCode() != e.getKeyCode()) {
0219: clearAllSearchMarks();
0220: getEditor().requestFocus();
0221: }
0222: }
0223: });
0224: }
0225:
0226: public void updateUndoRedo() {
0227: JEditorPane editor = getEditor();
0228: if (editor != null) {
0229: ContelligentStyledDocument document = (ContelligentStyledDocument) editor
0230: .getDocument();
0231: if (document != null) {
0232: final UndoManager um = document.getUndoManager();
0233: // be careful, this has to be in Event-Dispatch-Thread!
0234: // Otherwise deadlock in java.awt.ContelligentComponent
0235: // in public void enable() can occur while calling
0236: // getTreeLock().
0237: Runnable updateActions = new Runnable() {
0238: public void run() {
0239: undoAction.setEnabled(um.canUndo());
0240: redoAction.setEnabled(um.canRedo());
0241: }
0242: };
0243: if (SwingUtilities.isEventDispatchThread()) {
0244: updateActions.run();
0245: } else {
0246: SwingUtilities.invokeLater(updateActions);
0247: }
0248: }
0249: }
0250: }
0251:
0252: protected JEditorPane getEditor() {
0253: return editor;
0254: }
0255:
0256: public void mousePressed(int offset) {
0257: if (editor != null) {
0258: ContelligentStyledDocument document = (ContelligentStyledDocument) editor
0259: .getDocument();
0260: AttributeSet attributes = document.getCharacterElement(
0261: offset).getAttributes();
0262: Integer type = (Integer) attributes
0263: .getAttribute(ContelligentStyledDocument.TYPE);
0264: if (!editor.isEditable()
0265: && (type != null)
0266: && type
0267: .equals(ContelligentStyledDocument.COMPONENT_REFERENCE)) {
0268: // navigate to component...
0269: AttributeSet tag = (AttributeSet) attributes
0270: .getAttribute(ContelligentStyledDocument.TAG);
0271: Map tagAttributes = (Map) tag
0272: .getAttribute(ContelligentStyledDocument.TAG_ATTRIBUTES);
0273: String path = (String) tagAttributes.get("path");
0274: if (path.indexOf('?') > 0) {
0275: path = path.substring(0, path.indexOf('?'));
0276: }
0277: logger.log(Level.INFO, "Path=" + path);
0278: if (!path.startsWith("/")) {
0279: String parentPath = textEditor.getComponent()
0280: .getPath()
0281: + "/";
0282: while (path.startsWith("../") || path.equals("..")) {
0283: int cutoff = parentPath.substring(0,
0284: parentPath.length() - 1).lastIndexOf(
0285: "/");
0286: parentPath = parentPath
0287: .substring(0, cutoff + 1);
0288: if (path.startsWith("../")) {
0289: path = path.substring(3);
0290: } else {
0291: path = path.substring(2);
0292: }
0293: }
0294: path = parentPath + path;
0295: }
0296: ComponentFactory
0297: .getInstance()
0298: .fireComponentAddAbortedEvent(
0299: new ContelligentComponentDisplayEvent(
0300: this ,
0301: path,
0302: ContelligentComponentDisplayEvent.COMPONENT_SELECTED));
0303: }
0304: }
0305: }
0306:
0307: public class ImportAction extends StyledTextAction implements
0308: ContelligentAction {
0309: public ImportAction() {
0310: super ("import_action");
0311: putValue(Action.SMALL_ICON, Resources.importIcon);
0312: putValue(ROLLOVER_ICON, Resources.importIconRollOver);
0313: putValue(Action.SHORT_DESCRIPTION,
0314: "import_action_description");
0315: putValue(TYPE, PUSH_ACTION);
0316: putValue(ACTION_TYPE, TEXT_ACTION);
0317: putValue(ACTION_GROUP, TEXT_EXTERN_GROUP);
0318: putValue(ACTION_POS, TEXT_EXTERN_IMPORT);
0319: putValue(MENU_TARGET, MENU);
0320: putValue(BUTTON_TARGET, NO_BUTTON);
0321: }
0322:
0323: /**
0324: * Replace the current text by the text selected by the user
0325: *
0326: * @param e
0327: * the action event
0328: */
0329: public void actionPerformed(ActionEvent e) {
0330: if (editor != null) {
0331: ContelligentStyledDocument document = (ContelligentStyledDocument) editor
0332: .getDocument();
0333: final JFileChooser fc = new JFileChooser();
0334: int returnVal = fc.showOpenDialog(null);
0335: if (returnVal == JFileChooser.APPROVE_OPTION) {
0336: File file = fc.getSelectedFile();
0337: try {
0338: FileReader fileReader = new FileReader(file);
0339: read(fileReader, document, 0);
0340: fileReader.close();
0341: } catch (FileNotFoundException fnfe) {
0342: // file not found
0343: ExceptionDialog.show(fnfe);
0344: } catch (IOException ioe) {
0345: ExceptionDialog.show(ioe);
0346: } catch (BadLocationException ble) {
0347: ExceptionDialog.show(ble);
0348: }
0349: }
0350: }
0351: }
0352: }
0353:
0354: public class ExportAction extends StyledTextAction implements
0355: ContelligentAction {
0356: public ExportAction() {
0357: super ("export_action");
0358: putValue(Action.SMALL_ICON, Resources.exportIcon);
0359: putValue(ROLLOVER_ICON, Resources.exportIconRollOver);
0360: putValue(Action.SHORT_DESCRIPTION,
0361: "export_action_description");
0362: putValue(TYPE, PUSH_ACTION);
0363: putValue(ACTION_TYPE, TEXT_ACTION);
0364: putValue(ACTION_GROUP, TEXT_EXTERN_GROUP);
0365: putValue(ACTION_POS, TEXT_EXTERN_EXPORT);
0366: putValue(MENU_TARGET, MENU);
0367: putValue(BUTTON_TARGET, NO_BUTTON);
0368: }
0369:
0370: /**
0371: * Writes the document by using the specific write method
0372: *
0373: * @param e
0374: * the action event
0375: */
0376: public void actionPerformed(ActionEvent e) {
0377: if (editor != null) {
0378: ContelligentStyledDocument document = (ContelligentStyledDocument) editor
0379: .getDocument();
0380: final JFileChooser fc = new JFileChooser();
0381: int returnVal = fc.showSaveDialog(null);
0382: if (returnVal == JFileChooser.APPROVE_OPTION) {
0383: File file = fc.getSelectedFile();
0384: try {
0385: FileWriter fileWriter = new FileWriter(file);
0386: write(fileWriter, document, 0, document
0387: .getLength());
0388: fileWriter.close();
0389: } catch (IOException ioe) {
0390: ExceptionDialog.show(ioe);
0391: } catch (BadLocationException ble) {
0392: ExceptionDialog.show(ble);
0393: }
0394: }
0395: } else {
0396: logger.log(Level.WARNING, "No editor specified!");
0397: }
0398: }
0399: }
0400:
0401: /*
0402: * public class SpellCheckAction extends AbstractAction implements
0403: * ContelligentAction {
0404: *
0405: * public SpellCheckAction() { super("spell_check_action");
0406: * putValue(Action.SMALL_ICON, Resources.spellcheckIcon); putValue(TYPE,
0407: * PUSH_ACTION); putValue(ACTION_TYPE, TEXT_ACTION); putValue(ACTION_GROUP,
0408: * TEXT_SPELLCHECK_GROUP); putValue(ACTION_POS, TEXT_SPELLCHECK_CHECK);
0409: * putValue(MENU_TARGET, MENU); putValue(BUTTON_TARGET, TOOLBAR);
0410: * putValue(POPUP_TARGET, POPUP_MENU); }
0411: *
0412: * public void actionPerformed(ActionEvent e) {
0413: * JSpellDialog.check(getEditor(), Resources.getLocale().toString()); } }
0414: *
0415: * public class AutoSpellCheckAction extends AbstractAction implements
0416: * ContelligentAction { public AutoSpellCheckAction() {
0417: * super("auto_spell_check_action"); //putValue(Action.SMALL_ICON,
0418: * Resources.updateFromExternalIcon); putValue(TYPE, TOGGLE_ACTION);
0419: * putValue(ACTION_TYPE, TEXT_ACTION); putValue(ACTION_GROUP,
0420: * TEXT_SPELLCHECK_GROUP); putValue(ACTION_POS, TEXT_SPELLCHECK_ONTHEFLY);
0421: * putValue(MENU_TARGET, MENU); //putValue(BUTTON_TARGET, TOOLBAR);
0422: * putValue(POPUP_TARGET, POPUP_MENU); putValue(STATE, OFF); }
0423: *
0424: * public void actionPerformed(ActionEvent e) { if (
0425: * getValue(ContelligentAction.STATE) == ContelligentAction.ON ) {
0426: * putValue(ContelligentAction.STATE, ContelligentAction.OFF);
0427: * JSpellDialog.disableAutoCheck(getEditor()); } else {
0428: * putValue(ContelligentAction.STATE, ContelligentAction.ON);
0429: * JSpellDialog.enableAutoCheck(getEditor(),
0430: * Resources.getLocale().toString()); } } }
0431: */
0432:
0433: public class NormalTextAction extends StyledTextAction implements
0434: ContelligentAction {
0435: public NormalTextAction() {
0436: super ("normal_action");
0437: putValue(Action.SMALL_ICON, Resources.normalIcon);
0438: putValue(ROLLOVER_ICON, Resources.normalIconRollOver);
0439: putValue(Action.SHORT_DESCRIPTION,
0440: "normal_action_description");
0441: putValue(TYPE, PUSH_ACTION);
0442: putValue(ACTION_TYPE, TEXT_ACTION);
0443: putValue(ACTION_GROUP, TEXT_MARKUP_GROUP);
0444: putValue(ACTION_POS, TEXT_MARKUP_NORMAL);
0445: putValue(MENU_TARGET, MENU);
0446: putValue(BUTTON_TARGET, TOOLBAR);
0447: putValue(POPUP_TARGET, POPUP_MENU);
0448: putValue(Action.ACCELERATOR_KEY, KeyStroke
0449: .getKeyStroke(Resources
0450: .getLocalString("normal_action_keystroke")));
0451: }
0452:
0453: /**
0454: * Resets all style attributes.
0455: *
0456: * @param e
0457: * the action event
0458: */
0459: public void actionPerformed(ActionEvent e) {
0460: if (editor != null) {
0461: SimpleAttributeSet sas = new SimpleAttributeSet();
0462: StyleConstants.setItalic(sas, false);
0463: StyleConstants.setBold(sas, false);
0464: StyleConstants.setUnderline(sas, false);
0465: setCharacterAttributes(editor, sas, false);
0466: editor.requestFocus();
0467: }
0468: }
0469: }
0470:
0471: public class UnderlineTextAction extends UnderlineAction implements
0472: ContelligentAction {
0473: public UnderlineTextAction() {
0474: super ();
0475: putValue(Action.NAME, "underline_action");
0476: putValue(Action.SMALL_ICON, Resources.underlineIcon);
0477: putValue(ROLLOVER_ICON, Resources.underlineIconRollOver);
0478: putValue(Action.SHORT_DESCRIPTION,
0479: "underline_action_description");
0480: putValue(TYPE, PUSH_ACTION);
0481: putValue(ACTION_TYPE, TEXT_ACTION);
0482: putValue(ACTION_GROUP, TEXT_MARKUP_GROUP);
0483: putValue(ACTION_POS, TEXT_MARKUP_UNDERLINE);
0484: putValue(MENU_TARGET, MENU);
0485: putValue(BUTTON_TARGET, TOOLBAR);
0486: putValue(POPUP_TARGET, POPUP_MENU);
0487: putValue(
0488: Action.ACCELERATOR_KEY,
0489: KeyStroke
0490: .getKeyStroke(Resources
0491: .getLocalString("underline_action_keystroke")));
0492: }
0493:
0494: public void actionPerformed(ActionEvent e) {
0495: if (editor != null) {
0496: MutableAttributeSet attr = getInputAttributes();
0497: boolean underline = (StyleConstants.isUnderline(attr)) ? false
0498: : true;
0499: SimpleAttributeSet sas = new SimpleAttributeSet();
0500: StyleConstants.setUnderline(sas, underline);
0501: setCharacterAttributes(editor, sas, false);
0502: editor.requestFocus();
0503: }
0504: }
0505: }
0506:
0507: public class BoldTextAction extends BoldAction implements
0508: ContelligentAction {
0509: public BoldTextAction() {
0510: super ();
0511: putValue(Action.NAME, "bold_action");
0512: putValue(Action.SMALL_ICON, Resources.boldIcon);
0513: putValue(ROLLOVER_ICON, Resources.boldIconRollOver);
0514: putValue(Action.SHORT_DESCRIPTION,
0515: "bold_action_description");
0516: putValue(TYPE, PUSH_ACTION);
0517: putValue(ACTION_TYPE, TEXT_ACTION);
0518: putValue(ACTION_GROUP, TEXT_MARKUP_GROUP);
0519: putValue(ACTION_POS, TEXT_MARKUP_BOLD);
0520: putValue(MENU_TARGET, MENU);
0521: putValue(BUTTON_TARGET, TOOLBAR);
0522: putValue(POPUP_TARGET, POPUP_MENU);
0523: putValue(Action.ACCELERATOR_KEY, KeyStroke
0524: .getKeyStroke(Resources
0525: .getLocalString("bold_action_keystroke")));
0526: }
0527:
0528: public void actionPerformed(ActionEvent e) {
0529: if (editor != null) {
0530: MutableAttributeSet attr = getInputAttributes();
0531: boolean bold = (StyleConstants.isBold(attr)) ? false
0532: : true;
0533: SimpleAttributeSet sas = new SimpleAttributeSet();
0534: StyleConstants.setBold(sas, bold);
0535: setCharacterAttributes(editor, sas, false);
0536: editor.requestFocus();
0537: }
0538: }
0539: }
0540:
0541: public class ItalicTextAction extends ItalicAction implements
0542: ContelligentAction {
0543: public ItalicTextAction() {
0544: super ();
0545: putValue(Action.NAME, "italic_action");
0546: putValue(Action.SMALL_ICON, Resources.italicIcon);
0547: putValue(ROLLOVER_ICON, Resources.italicIconRollOver);
0548: putValue(Action.SHORT_DESCRIPTION,
0549: "italic_action_description");
0550: putValue(TYPE, PUSH_ACTION);
0551: putValue(ACTION_TYPE, TEXT_ACTION);
0552: putValue(ACTION_GROUP, TEXT_MARKUP_GROUP);
0553: putValue(ACTION_POS, TEXT_MARKUP_ITALIC);
0554: putValue(MENU_TARGET, MENU);
0555: putValue(BUTTON_TARGET, TOOLBAR);
0556: putValue(POPUP_TARGET, POPUP_MENU);
0557: putValue(Action.ACCELERATOR_KEY, KeyStroke
0558: .getKeyStroke(Resources
0559: .getLocalString("italic_action_keystroke")));
0560: }
0561:
0562: public void actionPerformed(ActionEvent e) {
0563: super .actionPerformed(e);
0564: if (editor != null) {
0565: editor.requestFocus();
0566: }
0567: }
0568: }
0569:
0570: public class CutTextAction extends CutAction implements
0571: ContelligentAction {
0572: public CutTextAction() {
0573: super ();
0574: putValue(Action.NAME, "cut_action");
0575: putValue(Action.SMALL_ICON, Resources.cutIcon);
0576: putValue(ROLLOVER_ICON, Resources.cutIconRollOver);
0577: putValue(Action.SHORT_DESCRIPTION, "cut_action_description");
0578: putValue(TYPE, PUSH_ACTION);
0579: putValue(ACTION_TYPE, TEXT_ACTION);
0580: putValue(ACTION_GROUP, TEXT_COPYPASTE_GROUP);
0581: putValue(ACTION_POS, TEXT_COPYPASTE_CUT);
0582: putValue(MENU_TARGET, MENU);
0583: // putValue(BUTTON_TARGET, TOOLBAR);
0584: putValue(POPUP_TARGET, POPUP_MENU);
0585: putValue(Action.ACCELERATOR_KEY, KeyStroke
0586: .getKeyStroke(Resources
0587: .getLocalString("cut_action_keystroke")));
0588: }
0589:
0590: public void actionPerformed(ActionEvent e) {
0591: if (editor != null) {
0592: logger.log(Level.FINE, "Try to cut on editor: "
0593: + editor);
0594: editor.cut();
0595: editor.requestFocus();
0596: }
0597: }
0598: }
0599:
0600: public class CopyTextAction extends CopyAction implements
0601: ContelligentAction {
0602: public CopyTextAction() {
0603: super ();
0604: putValue(Action.NAME, "copy_action");
0605: putValue(Action.SMALL_ICON, Resources.copyIcon);
0606: putValue(ROLLOVER_ICON, Resources.copyIconRollOver);
0607: putValue(Action.SHORT_DESCRIPTION,
0608: "copy_action_description");
0609: putValue(TYPE, PUSH_ACTION);
0610: putValue(ACTION_TYPE, TEXT_ACTION);
0611: putValue(ACTION_GROUP, TEXT_COPYPASTE_GROUP);
0612: putValue(ACTION_POS, TEXT_COPYPASTE_COPY);
0613: putValue(MENU_TARGET, MENU);
0614: // putValue(BUTTON_TARGET, TOOLBAR);
0615: putValue(POPUP_TARGET, POPUP_MENU);
0616: putValue(Action.ACCELERATOR_KEY, KeyStroke
0617: .getKeyStroke(Resources
0618: .getLocalString("copy_action_keystroke")));
0619: }
0620:
0621: public void actionPerformed(ActionEvent e) {
0622: if (editor != null) {
0623: editor.copy();
0624: editor.requestFocus();
0625: }
0626: }
0627: }
0628:
0629: public class PasteTextAction extends PasteAction implements
0630: ContelligentAction {
0631: public PasteTextAction() {
0632: super ();
0633: putValue(Action.NAME, "paste_action");
0634: putValue(Action.SMALL_ICON, Resources.pasteIcon);
0635: putValue(ROLLOVER_ICON, Resources.pasteIconRollOver);
0636: putValue(Action.SHORT_DESCRIPTION,
0637: "paste_action_description");
0638: putValue(TYPE, PUSH_ACTION);
0639: putValue(ACTION_TYPE, TEXT_ACTION);
0640: putValue(ACTION_GROUP, TEXT_COPYPASTE_GROUP);
0641: putValue(ACTION_POS, TEXT_COPYPASTE_PASTE);
0642: putValue(MENU_TARGET, MENU);
0643: // putValue(BUTTON_TARGET, TOOLBAR);
0644: putValue(POPUP_TARGET, POPUP_MENU);
0645: putValue(Action.ACCELERATOR_KEY, KeyStroke
0646: .getKeyStroke(Resources
0647: .getLocalString("paste_action_keystroke")));
0648: }
0649:
0650: public void actionPerformed(ActionEvent e) {
0651: if (editor != null) {
0652: editor.paste();
0653: editor.requestFocus();
0654: if (textEditor != null) {
0655: textEditor.setResourceModified();
0656: }
0657: }
0658: }
0659: }
0660:
0661: public class LinkAction extends StyledTextAction implements
0662: ContelligentAction {
0663: public LinkAction() {
0664: super ("link_action");
0665: putValue(Action.SMALL_ICON, Resources.createLinkIcon);
0666: putValue(ROLLOVER_ICON, Resources.createLinkIconRollOver);
0667: putValue(Action.SHORT_DESCRIPTION,
0668: "link_action_description");
0669: putValue(TYPE, PUSH_ACTION);
0670: putValue(ACTION_TYPE, TEXT_ACTION);
0671: putValue(ACTION_GROUP, TEXT_MARKUP_GROUP);
0672: putValue(ACTION_POS, TEXT_MARKUP_LINK);
0673: putValue(MENU_TARGET, MENU);
0674: putValue(BUTTON_TARGET, TOOLBAR);
0675: putValue(POPUP_TARGET, POPUP_MENU);
0676: }
0677:
0678: public void actionPerformed(ActionEvent e) {
0679: if (editor == null) {
0680: return;
0681: }
0682: if (!ContelligentEditorKit.this
0683: .editTag(getStyledEditorKit(editor))) {
0684: String selectedText = editor.getSelectedText();
0685: CreateLinkOptionPane linkPane = new CreateLinkOptionPane(
0686: ContelligentEditorKit.this , view);
0687: if (selectedText == null) {
0688: linkPane.showDialog("", "", "", new HashMap(), "",
0689: editor.getCaretPosition(), 0, false);
0690: } else {
0691: selectedText = selectedText.replaceAll("\n",
0692: ContelligentTextParser.BR_MARKER);
0693: linkPane
0694: .showDialog(
0695: selectedText,
0696: "",
0697: "",
0698: new HashMap(),
0699: "",
0700: editor.getSelectionStart(),
0701: editor.getSelectionEnd()
0702: - editor
0703: .getSelectionStart(),
0704: false);
0705: }
0706: }
0707: editor.requestFocus();
0708: }
0709: }
0710:
0711: public void insertLink(AttributeSet tag, String content,
0712: int offset, int length, Integer type) {
0713: ContelligentStyledDocument document = (ContelligentStyledDocument) editor
0714: .getDocument();
0715: try {
0716: document.removeForce(offset, length);
0717: } catch (BadLocationException e) {
0718: logger.log(Level.SEVERE, "Could not remove selected text!",
0719: e);
0720: }
0721: document.insertTag(offset, tag, content,
0722: ContelligentStyledDocument.CONTENT_STATE, type);
0723: // now we have inserted a link be sure to set resource to modified (FIX
0724: // for bug #295)
0725: if (textEditor != null) {
0726: textEditor.setResourceModified();
0727: }
0728: }
0729:
0730: public void insertString(String content, int offset, int length) {
0731: ContelligentStyledDocument document = (ContelligentStyledDocument) editor
0732: .getDocument();
0733: try {
0734: document.removeForce(offset, length);
0735: document
0736: .insertString(offset, content, getInputAttributes());
0737: } catch (BadLocationException e) {
0738: logger.log(Level.SEVERE, "Could not remove selected text!",
0739: e);
0740: }
0741: if (textEditor != null) {
0742: textEditor.setResourceModified();
0743: }
0744: }
0745:
0746: public class ToggleTagAction extends StyledTextAction implements
0747: ContelligentAction {
0748: public ToggleTagAction() {
0749: super ("toggle_tag_action");
0750: putValue(Action.SMALL_ICON, Resources.toggleTagIcon);
0751: putValue(ROLLOVER_ICON, Resources.toggleTagIconRollOver);
0752: putValue(Action.SHORT_DESCRIPTION,
0753: "toggle_tag_action_description");
0754: putValue(TYPE, PUSH_ACTION);
0755: putValue(ACTION_TYPE, TEXT_ACTION);
0756: putValue(ACTION_GROUP, TEXT_MARKUP_GROUP);
0757: putValue(ACTION_POS, TEXT_MARKUP_TOGGLE);
0758: putValue(MENU_TARGET, MENU);
0759: putValue(BUTTON_TARGET, TOOLBAR);
0760: putValue(POPUP_TARGET, POPUP_MENU);
0761: }
0762:
0763: public void actionPerformed(ActionEvent event) {
0764: if (editor != null) {
0765: StyledEditorKit kit = getStyledEditorKit(editor);
0766: MutableAttributeSet attributes = kit
0767: .getInputAttributes();
0768: toggleTag(attributes);
0769: }
0770: }
0771: }
0772:
0773: public void toggleTag(AttributeSet attributes) {
0774: AttributeSet tag = (AttributeSet) attributes
0775: .getAttribute(ContelligentStyledDocument.TAG);
0776: String content = (String) attributes
0777: .getAttribute(ContelligentStyledDocument.CONTENT);
0778: Integer state = (Integer) attributes
0779: .getAttribute(ContelligentStyledDocument.STATE);
0780: Integer type = (Integer) attributes
0781: .getAttribute(ContelligentStyledDocument.TYPE);
0782: String visibleText = (String) attributes
0783: .getAttribute(ContelligentStyledDocument.VISIBLE_TEXT);
0784: if (visibleText != null) { // in case no tag is selected, do nothing
0785: int visibleTextLength = visibleText.length();
0786: ContelligentStyledDocument document = (ContelligentStyledDocument) editor
0787: .getDocument();
0788: String text = ((JTextPaneDND) editor).getVisibleText();
0789: int offset = text.indexOf(visibleText, editor
0790: .getCaretPosition()
0791: - visibleTextLength);
0792: try {
0793: document.removeForce(offset, visibleTextLength);
0794: if (type
0795: .equals(ContelligentStyledDocument.COMPONENT_REFERENCE)) {
0796: if (state
0797: .equals(ContelligentStyledDocument.CONTENT_STATE)) {
0798: if (!PreferencesModule
0799: .getPreferences()
0800: .getBoolean(
0801: PreferencesModule.ALLOW_DETAGGING,
0802: PreferencesModule.DEFAULT_ALLOW_DETAGGING)) {
0803: // old toggling behaviour
0804: document
0805: .insertTag(
0806: offset,
0807: tag,
0808: content,
0809: ContelligentStyledDocument.PREVIEW_STATE,
0810: type);
0811: } else {
0812: // detagify selection for editing
0813: document.insertString(offset,
0814: ContelligentStyledDocument
0815: .renderTag(tag),
0816: getInputAttributes());
0817: }
0818: } else {
0819: document
0820: .insertTag(
0821: offset,
0822: tag,
0823: content,
0824: ContelligentStyledDocument.CONTENT_STATE,
0825: type);
0826: }
0827: } else if (type
0828: .equals(ContelligentStyledDocument.INTERNAL_LINK)
0829: || type
0830: .equals(ContelligentStyledDocument.EXTERNAL_LINK)) {
0831: if (state
0832: .equals(ContelligentStyledDocument.CONTENT_STATE)) {
0833: if (!PreferencesModule
0834: .getPreferences()
0835: .getBoolean(
0836: PreferencesModule.ALLOW_DETAGGING,
0837: PreferencesModule.DEFAULT_ALLOW_DETAGGING)) {
0838: document
0839: .insertTag(
0840: offset,
0841: tag,
0842: content,
0843: ContelligentStyledDocument.TAG_STATE,
0844: type);
0845: } else {
0846: document.insertString(offset,
0847: ContelligentStyledDocument
0848: .renderTag(tag),
0849: getInputAttributes());
0850: }
0851: } else {
0852: document
0853: .insertTag(
0854: offset,
0855: tag,
0856: content,
0857: ContelligentStyledDocument.CONTENT_STATE,
0858: type);
0859: }
0860: }
0861: } catch (BadLocationException e) {
0862: e.printStackTrace();
0863: }
0864: editor.requestFocus();
0865: }
0866: }
0867:
0868: public class EditAction extends StyledTextAction implements
0869: ContelligentAction {
0870: private ContelligentComponent component;
0871:
0872: public EditAction() {
0873: this (null);
0874: }
0875:
0876: public void setComponent(ContelligentComponent component) {
0877: this .component = component;
0878: }
0879:
0880: public EditAction(ContelligentComponent component) {
0881: super ("edit_component_action");
0882: this .component = component;
0883: putValue(Action.SMALL_ICON, Resources.editTagIcon);
0884: putValue(ROLLOVER_ICON, Resources.editTagIconRollOver);
0885: putValue(Action.SHORT_DESCRIPTION,
0886: "edit_component_action_description");
0887: putValue(TYPE, PUSH_ACTION);
0888: putValue(ACTION_TYPE, TEXT_ACTION);
0889: putValue(ACTION_GROUP, TEXT_MARKUP_GROUP);
0890: putValue(ACTION_POS, TEXT_MARKUP_EDIT);
0891: putValue(MENU_TARGET, MENU);
0892: putValue(BUTTON_TARGET, TOOLBAR);
0893: putValue(POPUP_TARGET, POPUP_MENU);
0894: }
0895:
0896: public void actionPerformed(ActionEvent event) {
0897: if (!ContelligentEditorKit.this
0898: .editTag(getStyledEditorKit(editor))) {
0899: JOptionPane.showConfirmDialog(null, Resources
0900: .getLocalString("no_tag_selected"), Resources
0901: .getLocalString("no_tag_selected_title"),
0902: JOptionPane.CLOSED_OPTION,
0903: JOptionPane.ERROR_MESSAGE);
0904: }
0905: }
0906: }
0907:
0908: /**
0909: * Tag editing functionality used by LinkAction and EditAction
0910: *
0911: * @param kit
0912: * @return Whether a tag was found and edited. Note that this function also
0913: * returns true if no valid editor was found, since the actions
0914: * should quietly ignore that special situation.
0915: */
0916: protected boolean editTag(StyledEditorKit kit) {
0917: if (editor != null) {
0918: MutableAttributeSet attributes = kit.getInputAttributes();
0919: AttributeSet tag = (AttributeSet) attributes
0920: .getAttribute(ContelligentStyledDocument.TAG);
0921: if (tag != null) {
0922: ContelligentStyledDocument document = (ContelligentStyledDocument) editor
0923: .getDocument();
0924: Map tagAttributes = (Map) tag
0925: .getAttribute(ContelligentStyledDocument.TAG_ATTRIBUTES);
0926: String tagName = (String) tag
0927: .getAttribute(ContelligentStyledDocument.TAG_NAME);
0928: if (tagName != null && tagAttributes != null) {
0929: String selectedText = null;
0930: String targetWindow = null;
0931: String href = null;
0932: String name = null;
0933: boolean isInternalLink = false;
0934: Map parameterMap = new HashMap();
0935: if (tagName.toUpperCase().equals(
0936: ContelligentTextParser.A_TAG)) {
0937: selectedText = (String) attributes
0938: .getAttribute(ContelligentStyledDocument.CONTENT);
0939: targetWindow = (String) tagAttributes
0940: .get("target");
0941: href = (String) tagAttributes.get("href");
0942: name = (String) tagAttributes.get("name");
0943: if (href != null) {
0944: parameterMap = ContelligentTextParser
0945: .getRenderAttributes(href);
0946: } else {
0947: parameterMap = new HashMap();
0948: href = "";
0949: }
0950: } else if (tagName.toUpperCase().equals(
0951: ContelligentTextParser.RENDER_TAG
0952: .toUpperCase())) {
0953: isInternalLink = true;
0954: String path = (String) tagAttributes
0955: .get(ContelligentConstants.PATH_ATTRIBUTE);
0956: if (path != null
0957: && path.indexOf("mode=link") != -1) {
0958: // parse path parameters
0959: parameterMap = ContelligentTextParser
0960: .getRenderAttributes(path);
0961: selectedText = CharsetUtil
0962: .safeURLDecode((String) parameterMap
0963: .get("text"));
0964: targetWindow = (String) parameterMap
0965: .get("target");
0966: href = (String) parameterMap.get("path");
0967: }
0968: }
0969: if (selectedText != null) {
0970: int offset, length;
0971: if (attributes
0972: .isDefined(ContelligentStyledDocument.STATE)) {
0973: String visibleText;
0974: if (attributes
0975: .getAttribute(
0976: ContelligentStyledDocument.STATE)
0977: .equals(
0978: ContelligentStyledDocument.CONTENT_STATE)) {
0979: visibleText = (String) attributes
0980: .getAttribute(ContelligentStyledDocument.CONTENT);
0981: } else {
0982: visibleText = (String) attributes
0983: .getAttribute(ContelligentStyledDocument.VISIBLE_TEXT);
0984: }
0985: try {
0986: offset = document.getText(0,
0987: document.getLength()).indexOf(
0988: visibleText,
0989: editor.getCaretPosition()
0990: - visibleText.length());
0991: CreateLinkOptionPane linkPane = new CreateLinkOptionPane(
0992: ContelligentEditorKit.this ,
0993: view);
0994: linkPane.showDialog(selectedText, href,
0995: name, parameterMap,
0996: targetWindow, offset,
0997: visibleText.length(),
0998: isInternalLink);
0999: } catch (BadLocationException e) {
1000: logger.log(Level.SEVERE,
1001: "Could not find tag start", e);
1002: }
1003: }
1004: } else {
1005: return false;
1006: }
1007: }
1008: } else {
1009: return false;
1010: }
1011: editor.requestFocus();
1012: }
1013: return true;
1014: }
1015:
1016: public class UndoAction extends StyledTextAction implements
1017: ContelligentAction {
1018: public UndoAction() {
1019: super ("undo_action");
1020: putValue(Action.SMALL_ICON, Resources.undoIcon);
1021: putValue(ROLLOVER_ICON, Resources.undoIconRollOver);
1022: putValue(Action.SHORT_DESCRIPTION,
1023: "undo_action_description");
1024: putValue(TYPE, PUSH_ACTION);
1025: putValue(ACTION_TYPE, TEXT_ACTION);
1026: putValue(ACTION_GROUP, TEXT_UNDO_GROUP);
1027: putValue(ACTION_POS, TEXT_UNDO_UNDO);
1028: putValue(MENU_TARGET, MENU);
1029: putValue(BUTTON_TARGET, TOOLBAR);
1030: putValue(POPUP_TARGET, POPUP_MENU);
1031: putValue(Action.ACCELERATOR_KEY, KeyStroke
1032: .getKeyStroke(Resources
1033: .getLocalString("undo_action_keystroke")));
1034: }
1035:
1036: public void actionPerformed(ActionEvent event) {
1037: UndoManager undoManager = ((ContelligentStyledDocument) editor
1038: .getDocument()).getUndoManager();
1039: if (editor != null && undoManager != null) {
1040: if (undoManager.canUndo()) {
1041: undoManager.undo();
1042: } else {
1043: java.awt.Toolkit.getDefaultToolkit().beep();
1044: }
1045: }
1046: updateUndoRedo();
1047: editor.requestFocus();
1048: }
1049: }
1050:
1051: public class RedoAction extends StyledTextAction implements
1052: ContelligentAction {
1053: public RedoAction() {
1054: super ("redo_action");
1055: putValue(Action.SMALL_ICON, Resources.redoIcon);
1056: putValue(ROLLOVER_ICON, Resources.redoIconRollOver);
1057: putValue(Action.SHORT_DESCRIPTION,
1058: "redo_action_description");
1059: putValue(TYPE, PUSH_ACTION);
1060: putValue(ACTION_TYPE, TEXT_ACTION);
1061: putValue(ACTION_GROUP, TEXT_UNDO_GROUP);
1062: putValue(ACTION_POS, TEXT_UNDO_REDO);
1063: putValue(MENU_TARGET, MENU);
1064: putValue(BUTTON_TARGET, TOOLBAR);
1065: putValue(POPUP_TARGET, POPUP_MENU);
1066: putValue(Action.ACCELERATOR_KEY, KeyStroke
1067: .getKeyStroke(Resources
1068: .getLocalString("redo_action_keystroke")));
1069: }
1070:
1071: public void actionPerformed(ActionEvent event) {
1072: UndoManager undoManager = ((ContelligentStyledDocument) editor
1073: .getDocument()).getUndoManager();
1074: if (editor != null && undoManager != null) {
1075: if (undoManager.canRedo()) {
1076: undoManager.redo();
1077: } else {
1078: java.awt.Toolkit.getDefaultToolkit().beep();
1079: }
1080: }
1081: updateUndoRedo();
1082: editor.requestFocus();
1083: }
1084: }
1085:
1086: public class ReplaceAction extends StyledTextAction implements
1087: ContelligentAction {
1088: public ReplaceAction() {
1089: super ("replace_action");
1090: putValue(Action.SMALL_ICON, Resources.replaceIcon);
1091: putValue(Action.SHORT_DESCRIPTION,
1092: "replace_action_description");
1093: putValue(TYPE, PUSH_ACTION);
1094: putValue(ACTION_TYPE, TEXT_ACTION);
1095: putValue(ACTION_GROUP, TEXT_SEARCH_GROUP);
1096: putValue(ACTION_POS, TEXT_SEARCH_REPLACE);
1097: putValue(MENU_TARGET, MENU);
1098: putValue(BUTTON_TARGET, TOOLBAR);
1099: putValue(POPUP_TARGET, POPUP_MENU);
1100: putValue(
1101: Action.ACCELERATOR_KEY,
1102: KeyStroke
1103: .getKeyStroke(Resources
1104: .getLocalString("replace_action_keystroke")));
1105: }
1106:
1107: public void actionPerformed(ActionEvent event) {
1108: if (editor != null) {
1109: clearAllSearchMarks();
1110: replaceDialog = new ReplaceDialog(ContelligentEditorKit
1111: .getSearchString(), replaceString, true);
1112: int option;
1113: if ((option = replaceDialog.showReplaceDialog()) != JOptionPane.CANCEL_OPTION
1114: && getSearchString()) {
1115: orgPos = editor.getCaretPosition();
1116: replace(orgPos, option);
1117: }
1118: editor.requestFocus();
1119: }
1120: }
1121:
1122: private boolean getSearchString() {
1123: if (replaceDialog == null) {
1124: return false;
1125: }
1126: ContelligentEditorKit.setSearchString(replaceDialog
1127: .getSearchText());
1128: ContelligentEditorKit.setReplaceString(replaceDialog
1129: .getReplaceText());
1130: if (searchString.length() == 0) {
1131: java.awt.Toolkit.getDefaultToolkit().beep();
1132: return false;
1133: }
1134: return true;
1135: }
1136: }
1137:
1138: public class FindAction extends StyledTextAction implements
1139: ContelligentAction {
1140: public FindAction() {
1141: super ("find_action");
1142: putValue(Action.SMALL_ICON, Resources.findIcon);
1143: putValue(ROLLOVER_ICON, Resources.findIconRollOver);
1144: putValue(Action.SHORT_DESCRIPTION,
1145: "find_action_description");
1146: putValue(TYPE, PUSH_ACTION);
1147: putValue(ACTION_TYPE, TEXT_ACTION);
1148: putValue(ACTION_GROUP, TEXT_SEARCH_GROUP);
1149: putValue(ACTION_POS, TEXT_SEARCH_FIND);
1150: putValue(MENU_TARGET, MENU);
1151: putValue(BUTTON_TARGET, TOOLBAR);
1152: putValue(POPUP_TARGET, POPUP_MENU);
1153: putValue(Action.ACCELERATOR_KEY, KeyStroke
1154: .getKeyStroke(Resources
1155: .getLocalString("find_action_keystroke")));
1156: }
1157:
1158: public void actionPerformed(ActionEvent event) {
1159: if (editor != null) {
1160: clearAllSearchMarks();
1161: findDialog = new FindDialog();
1162: if (findDialog.showStringDialog(ContelligentEditorKit
1163: .getSearchString()) == JOptionPane.OK_OPTION
1164: && getSearchString()) {
1165: serachIndexFrom = 0;
1166: if (editor.isEditable()) {
1167: orgPos = editor.getCaretPosition();
1168: } else {
1169: orgPos = 0;
1170: }
1171: if (!find(false)) {
1172: java.awt.Toolkit.getDefaultToolkit().beep();
1173: } else {
1174: while (find(false))
1175: ;
1176: editor.setCaretPosition(orgPos);
1177: serachIndexFrom = orgPos;
1178: find(true);
1179: }
1180: }
1181: editor.requestFocus();
1182: }
1183: }
1184:
1185: private boolean getSearchString() {
1186: if (findDialog == null)
1187: return false;
1188: searchString = findDialog.getText();
1189: if (searchString.length() == 0) {
1190: java.awt.Toolkit.getDefaultToolkit().beep();
1191: return false;
1192: }
1193: return true;
1194: }
1195: }
1196:
1197: public class CancelSearchAction extends StyledTextAction implements
1198: ContelligentAction {
1199: public CancelSearchAction() {
1200: super ("cancel_search_action");
1201: // putValue(Action.SMALL_ICON, Resources.clearSearchIcon);
1202: // putValue(ROLLOVER_ICON, Resources.clearSearchIconRollOver);
1203: putValue(Action.SHORT_DESCRIPTION,
1204: "cancel_search_action_description");
1205: putValue(TYPE, PUSH_ACTION);
1206: putValue(ACTION_TYPE, TEXT_ACTION);
1207: putValue(ACTION_GROUP, TEXT_SEARCH_GROUP);
1208: putValue(ACTION_POS, TEXT_SEARCH_CANCEL);
1209: putValue(MENU_TARGET, MENU);
1210: // putValue(BUTTON_TARGET, TOOLBAR);
1211: putValue(POPUP_TARGET, POPUP_MENU);
1212: }
1213:
1214: public void actionPerformed(ActionEvent event) {
1215: if (editor != null) {
1216: String oldSearchString = ContelligentEditorKit
1217: .getSearchString();
1218: ContelligentEditorKit.setSearchString("");
1219: clearAllSearchMarks();
1220: editor.requestFocus();
1221: ContelligentEditorKit.setSearchString(oldSearchString);
1222: }
1223: }
1224: }
1225:
1226: public class FindAgainAction extends StyledTextAction implements
1227: ContelligentAction {
1228: public FindAgainAction() {
1229: super ("find_again_action");
1230: putValue(Action.SHORT_DESCRIPTION,
1231: "find_again_action_description");
1232: putValue(TYPE, PUSH_ACTION);
1233: putValue(ACTION_TYPE, TEXT_ACTION);
1234: putValue(ACTION_GROUP, TEXT_SEARCH_GROUP);
1235: putValue(ACTION_POS, TEXT_SEARCH_AGAIN);
1236: putValue(MENU_TARGET, MENU);
1237: putValue(POPUP_TARGET, POPUP_MENU);
1238: putValue(
1239: Action.ACCELERATOR_KEY,
1240: KeyStroke
1241: .getKeyStroke(Resources
1242: .getLocalString("find_again_action_keystroke")));
1243: }
1244:
1245: public void actionPerformed(ActionEvent event) {
1246: if (editor != null) {
1247: if (ContelligentEditorKit.getSearchString().length() == 0) {
1248: java.awt.Toolkit.getDefaultToolkit().beep();
1249: } else {
1250: serachIndexFrom = editor.getCaretPosition();
1251: if (!find(true)) {
1252: java.awt.Toolkit.getDefaultToolkit().beep();
1253: serachIndexFrom = 0;
1254: find(true);
1255: }
1256: editor.requestFocus();
1257: }
1258: }
1259: }
1260: }
1261:
1262: public int replace(int startPos, int option) {
1263: replaceOption = option;
1264: this .orgPos = startPos;
1265: serachIndexFrom = 0;
1266: if (option == ReplaceDialog.REPLACE_OPTION) {
1267: if (!find(false)) {
1268: java.awt.Toolkit.getDefaultToolkit().beep();
1269: } else {
1270: // first mark everything
1271: while (find(false))
1272: ;
1273: editor.setCaretPosition(0);
1274: serachIndexFrom = 0;
1275: // then ask for every mark
1276: while (find(true, true, true))
1277: ;
1278: option = replaceOption;
1279: clearAllSearchMarks();
1280: editor.setCaretPosition(orgPos);
1281: }
1282: } else if (option == ReplaceDialog.REPLACE_ALL_OPTION) {
1283: int foundCount = 0;
1284: while (find(false, true, false)) {
1285: foundCount++;
1286: }
1287: JOptionPane.showOptionDialog(null,
1288: Resources
1289: .getLocalString("replace_done",
1290: new String[] { String
1291: .valueOf(foundCount) }),
1292: Resources.getLocalString("replace_done_title"),
1293: JOptionPane.OK_OPTION,
1294: JOptionPane.INFORMATION_MESSAGE, null, OK_OPTIONS,
1295: OK_OPTIONS[0]);
1296: editor.setCaretPosition(orgPos);
1297: }
1298: return option;
1299: }
1300:
1301: private boolean find(boolean selectHit) {
1302: return find(selectHit, false, false);
1303: }
1304:
1305: private boolean find(boolean selectHit, boolean replace, boolean ask) {
1306: // if one of the characters in searchString is upper case, we presume
1307: // the search is meant to be case sensitve, otherwise case insensitive
1308: String text;
1309: String searchText;
1310: if (!ContelligentEditorKit.getSearchString().toLowerCase()
1311: .equals(ContelligentEditorKit.getSearchString())) {
1312: text = ((JTextPaneDND) editor).getVisibleText();
1313: searchText = ContelligentEditorKit.getSearchString();
1314: } else {
1315: text = (((JTextPaneDND) editor).getVisibleText())
1316: .toLowerCase();
1317: searchText = ContelligentEditorKit.getSearchString()
1318: .toLowerCase();
1319: }
1320: int index = text.indexOf(searchText, serachIndexFrom);
1321: if (index != -1) {
1322: int searchSelectionStart = index;
1323: int searchSelectionEnd = index
1324: + ContelligentEditorKit.getSearchString().length();
1325: serachIndexFrom = searchSelectionEnd;
1326: if (replace) {
1327: if (!ask) {
1328: replaceText(replaceString, searchSelectionStart,
1329: searchSelectionEnd);
1330: return true;
1331: } else {
1332: editor.setCaretPosition(searchSelectionStart);
1333: SimpleAttributeSet attr = new SimpleAttributeSet();
1334: StyleConstants.setBackground(attr, Color.RED);
1335: setAttr(attr, searchSelectionStart,
1336: searchSelectionEnd);
1337: boolean result = false;
1338: InteractiveReplaceDialog replaceDialog = new InteractiveReplaceDialog();
1339: replaceOption = replaceDialog.showReplaceDialog();
1340: if (replaceOption != InteractiveReplaceDialog.CANCEL_OPTION) {
1341: if (replaceOption == InteractiveReplaceDialog.SKIP_OPTION) {
1342: result = true;
1343: } else if (replaceOption == InteractiveReplaceDialog.REPLACE_OPTION) {
1344: attr = new SimpleAttributeSet();
1345: StyleConstants.setBackground(attr,
1346: Color.WHITE);
1347: setAttr(attr, searchSelectionStart,
1348: searchSelectionEnd);
1349: replaceText(replaceString,
1350: searchSelectionStart,
1351: searchSelectionEnd);
1352: return true;
1353: } else if (replaceOption == InteractiveReplaceDialog.REPLACE_ALL_OPTION) {
1354: // do not forget to replace text currently selected
1355: // when replacing all
1356: attr = new SimpleAttributeSet();
1357: StyleConstants.setBackground(attr,
1358: Color.WHITE);
1359: setAttr(attr, searchSelectionStart,
1360: searchSelectionEnd);
1361: replaceText(replaceString,
1362: searchSelectionStart,
1363: searchSelectionEnd);
1364: while (find(false, true, false))
1365: ;
1366: editor.setCaretPosition(orgPos);
1367: editor.requestFocus();
1368: }
1369: }
1370: attr = new SimpleAttributeSet();
1371: StyleConstants.setBackground(attr, Color.WHITE);
1372: setAttr(attr, searchSelectionStart,
1373: searchSelectionEnd);
1374: return result;
1375: }
1376: } else {
1377: // FIXME this would be nice but seems to make things slow
1378: // SimpleAttributeSet attr = new SimpleAttributeSet();
1379: // StyleConstants.setBackground(attr, SEARCH_HIGHLIGHT_COLOR);
1380: // setAttr(attr, searchSelectionStart, searchSelectionEnd);
1381: // searchSelections.add(new Integer(searchSelectionStart));
1382: // searchSelections.add(new Integer(searchSelectionEnd));
1383: }
1384: if (selectHit) {
1385: editor.setCaretPosition(searchSelectionStart);
1386: editor.moveCaretPosition(searchSelectionEnd);
1387: }
1388: return true;
1389: } else {
1390: return false;
1391: }
1392: }
1393:
1394: private void replaceText(String newText, int posS, int posE) {
1395: if (editor != null) {
1396: try {
1397: int oldLength = posE - posS;
1398: int additionalLength = newText.length() - oldLength;
1399: ContelligentStyledDocument doc = (ContelligentStyledDocument) editor
1400: .getDocument();
1401: // FIXME this would be nice but seems to make things slow
1402: SimpleAttributeSet attr = new SimpleAttributeSet(doc
1403: .getCharacterElement(posS).getAttributes());
1404: // StyleConstants.setBackground(attr, REPLACED_HIGHLIGHT_COLOR);
1405: try {
1406: doc.replace(posS, oldLength, newText, attr);
1407: serachIndexFrom += additionalLength;
1408: } catch (UnableToReplaceException utre) {
1409: serachIndexFrom += oldLength;
1410: }
1411: // FIXME this would be nice but seems to make things slow
1412: // searchSelections.add(new Integer(posS));
1413: // searchSelections.add(new Integer(posE + additionalLength));
1414: } catch (BadLocationException ble) {
1415: logger.log(Level.WARNING, "Could not replace text!",
1416: ble);
1417: }
1418: }
1419: }
1420:
1421: private void setAttr(AttributeSet attr, int posS, int posE) {
1422: if (editor != null) {
1423: ContelligentStyledDocument doc = (ContelligentStyledDocument) editor
1424: .getDocument();
1425: doc.setCharacterAttributes(posS, posE - posS, attr, false,
1426: false);
1427: }
1428: }
1429:
1430: private void clearAllSearchMarks() {
1431: // FIXME this would be nice but seems to make things slow
1432: /*
1433: * SimpleAttributeSet attr = new SimpleAttributeSet();
1434: * StyleConstants.setBackground(attr, Color.white); for (Iterator it =
1435: * searchSelections.iterator(); it.hasNext();) { int p0 = ((Integer)
1436: * it.next()).intValue(); int p1 = ((Integer) it.next()).intValue();
1437: * setAttr(attr, p0, p1); } searchSelections = new ArrayList();
1438: */
1439: }
1440:
1441: public void read(Reader in, Document doc, int pos)
1442: throws IOException, BadLocationException {
1443: ContelligentStyledDocument document = (ContelligentStyledDocument) doc;
1444: try {
1445: ContelligentTextParser parser = new ContelligentTextParser(
1446: featureSet);
1447: parser.parse(in, document, pos);
1448: } catch (Exception e) {
1449: e.printStackTrace();
1450: }
1451: }
1452:
1453: public void read(InputStream in, Document doc, int pos)
1454: throws IOException, BadLocationException {
1455: logger.log(Level.FINEST, "Reader2");
1456: super .read(in, doc, pos);
1457: }
1458:
1459: public void write(Writer out, Document doc, int pos, int len)
1460: throws IOException, BadLocationException {
1461: ContelligentStyledDocument document = (ContelligentStyledDocument) doc;
1462: boolean bold = false;
1463: boolean italic = false;
1464: boolean underline = false;
1465: // generate html-tags
1466: String text = document.getText(pos, len);
1467: StringBuffer buf = new StringBuffer();
1468: int mode = TEXT_MODE;
1469: for (int i = pos; i < (pos + len); i++) {
1470: // toggle all tags to tags!
1471: if ((featureSet & HANDLE_CONTELLIGENT_TAG) == HANDLE_CONTELLIGENT_TAG) {
1472: AttributeSet attributes = document.getCharacterElement(
1473: i).getAttributes();
1474: if (attributes
1475: .isDefined(ContelligentStyledDocument.STATE)) {
1476: String tag = ContelligentStyledDocument
1477: .renderTag((AttributeSet) attributes
1478: .getAttribute(ContelligentStyledDocument.TAG));
1479: String visibleText = (String) attributes
1480: .getAttribute(ContelligentStyledDocument.VISIBLE_TEXT);
1481: buf.append(tag);
1482: // "blue links" dont have visibleText set; use content
1483: // instead
1484: if (visibleText == null) {
1485: visibleText = (String) attributes
1486: .getAttribute(ContelligentStyledDocument.CONTENT);
1487: }
1488: i += visibleText.length() - 1;
1489: continue;
1490: }
1491: }
1492: // FIXME This is really bad code. Should be cleaned up:
1493: if ((featureSet & HANDLE_MARKUP) == HANDLE_MARKUP) {
1494: StringBuffer styleTag = new StringBuffer();
1495: Object boldAttribute = document.getCharacterElement(i)
1496: .getAttributes().getAttribute(
1497: StyleConstants.CharacterConstants.Bold);
1498: Object italicAttribute = document
1499: .getCharacterElement(i)
1500: .getAttributes()
1501: .getAttribute(
1502: StyleConstants.CharacterConstants.Italic);
1503: Object underlineAttribute = document
1504: .getCharacterElement(i)
1505: .getAttributes()
1506: .getAttribute(
1507: StyleConstants.CharacterConstants.Underline);
1508:
1509: // check for return and replace only if not inside tag
1510: char currentChar = document.getText(i, 1).toCharArray()[0];
1511:
1512: if (currentChar == '<') {
1513: mode = TAG_MODE;
1514: }
1515: if (currentChar == '>' && mode == TAG_MODE) {
1516: mode = TEXT_MODE;
1517: }
1518: if (currentChar == '\n' && mode == TEXT_MODE) {
1519: styleTag.append(ContelligentTextParser.BR_MARKER);
1520: }
1521: // reverse closing of tags
1522: if (underlineAttribute == null && underline == true) {
1523: styleTag.append("</u>");
1524: underline = false;
1525: } else if (underlineAttribute != null
1526: && !((Boolean) underlineAttribute)
1527: .booleanValue() && underline == true) {
1528: styleTag.append("</u>");
1529: underline = false;
1530: }
1531: if (italicAttribute == null && italic == true) {
1532: styleTag.append("</i>");
1533: italic = false;
1534: } else if (italicAttribute != null
1535: && !((Boolean) italicAttribute).booleanValue()
1536: && italic == true) {
1537: styleTag.append("</i>");
1538: italic = false;
1539: }
1540: if (boldAttribute == null && bold == true) {
1541: styleTag.append("</b>");
1542: bold = false;
1543: } else if (boldAttribute != null
1544: && !((Boolean) boldAttribute).booleanValue()
1545: && bold == true) {
1546: styleTag.append("</b>");
1547: bold = false;
1548: }
1549: // opening tags
1550: if (boldAttribute != null
1551: && ((Boolean) boldAttribute).booleanValue()
1552: && bold == false) {
1553: styleTag.append("<b>");
1554: bold = true;
1555: }
1556: if (italicAttribute != null
1557: && ((Boolean) italicAttribute).booleanValue()
1558: && italic == false) {
1559: styleTag.append("<i>");
1560: italic = true;
1561: }
1562: if (underlineAttribute != null
1563: && ((Boolean) underlineAttribute)
1564: .booleanValue() && underline == false) {
1565: styleTag.append("<u>");
1566: underline = true;
1567: }
1568: if (styleTag.length() > 0) {
1569: buf.append(styleTag.toString());
1570: }
1571: }
1572: char currentChar = text.charAt(i - pos);
1573: // Ignore characters not valid in XML
1574: // XXX: Due to Java constraints, the range 10000-10FFFF which is
1575: // allowed
1576: // in the XML standard is also supressed here.
1577: if ((currentChar == '\u0009')
1578: || (currentChar == '\n')
1579: || (currentChar == '\r')
1580: || ((currentChar >= '\u0020') && (currentChar <= '\uD7FF'))
1581: || ((currentChar >= '\uE000') && (currentChar <= '\uFFFD'))) {
1582: // Append character...
1583: buf.append(currentChar);
1584: }
1585: }
1586: // close all open tag at the end of the selection
1587: if ((featureSet & HANDLE_MARKUP) == HANDLE_MARKUP) {
1588: if (underline == true)
1589: buf.append("</u>");
1590: if (italic == true)
1591: buf.append("</i>");
1592: if (bold == true)
1593: buf.append("</b>");
1594: }
1595: String processedText = buf.toString();
1596: out.write(processedText.toCharArray(), 0, processedText
1597: .length());
1598: }
1599:
1600: public void write(OutputStream out, Document doc, int pos, int len)
1601: throws IOException, BadLocationException {
1602: logger.log(Level.FINEST, "Write2");
1603: super .write(out, doc, pos, len);
1604: }
1605:
1606: public Action[] getActions(ContelligentComponent component) {
1607: List actionList = new Vector();
1608: actionList.add(importAction);
1609: actionList.add(exportAction);
1610: if ((featureSet & HANDLE_MARKUP) == HANDLE_MARKUP) {
1611: actionList.add(linkAction);
1612: actionList.add(normalTextAction);
1613: actionList.add(boldTextAction);
1614: actionList.add(underlineTextAction);
1615: actionList.add(italicTextAction);
1616: }
1617: if ((featureSet & HANDLE_CONTELLIGENT_TAG) == HANDLE_CONTELLIGENT_TAG) {
1618: if ((featureSet & HANDLE_MARKUP) != HANDLE_MARKUP) {
1619: editAction.setComponent(component);
1620: actionList.add(editAction);
1621: }
1622: actionList.add(toggleTagAction);
1623: }
1624: actionList.add(cutTextAction);
1625: actionList.add(copyTextAction);
1626: actionList.add(pasteTextAction);
1627: actionList.add(findAction);
1628: actionList.add(replaceAction);
1629: actionList.add(findAgainAction);
1630: actionList.add(cancelAction);
1631: actionList.add(undoAction);
1632: actionList.add(redoAction);
1633: // actionList.add(spellCheckAction);
1634: // actionList.add(autoSpellCheckAction);
1635:
1636: Object[] objects = actionList.toArray();
1637: Action[] actions = new Action[actionList.size()];
1638: System.arraycopy(objects, 0, actions, 0, actionList.size());
1639: return actions;
1640: }
1641:
1642: /**
1643: * @return String
1644: */
1645: public static String getReplaceString() {
1646: return replaceString;
1647: }
1648:
1649: /**
1650: * @return String
1651: */
1652: public static String getSearchString() {
1653: return searchString;
1654: }
1655:
1656: /**
1657: * Sets the replaceString.
1658: *
1659: * @param replaceString
1660: * The replaceString to set
1661: */
1662: public static void setReplaceString(String replaceString) {
1663: ContelligentEditorKit.replaceString = replaceString;
1664: }
1665:
1666: /**
1667: * Sets the searchString.
1668: *
1669: * @param searchString
1670: * The searchString to set
1671: */
1672: public static void setSearchString(String searchString) {
1673: if (searchString.startsWith("*")) {
1674: searchString = searchString.substring(1);
1675: }
1676: if (searchString.endsWith("*")) {
1677: searchString = searchString.substring(0, searchString
1678: .length() - 1);
1679: }
1680: ContelligentEditorKit.searchString = searchString;
1681: }
1682:
1683: public boolean isFeatureRichEditor() {
1684: return isFeatureRichEditor;
1685: }
1686:
1687: public void setStateFeatureRich(boolean b) {
1688: if (b) {
1689: featureSet = featureSetRich;
1690: } else {
1691: featureSet = PLAIN_TEXT;
1692: }
1693: }
1694:
1695: public boolean isStateFeatureRich() {
1696: return PLAIN_TEXT != featureSet;
1697: }
1698:
1699: }
|