001: package snow.texteditor;
002:
003: import java.io.File;
004: import snow.utils.storage.FileUtils;
005: import tide.editor.EditorDocument;
006: import java.awt.EventQueue;
007: import snow.datatransfer.ClipboardUtils;
008: import snow.utils.StringUtils;
009: import tide.editor.Accelerators;
010: import tide.editor.SharedUtils;
011: import java.awt.Font;
012: import javax.swing.text.*;
013: import java.util.*;
014: import java.awt.event.*;
015: import java.awt.BorderLayout;
016: import javax.swing.*;
017:
018: /** Search: CTRL+F.
019: * Highlight all Occurences: CTRL+K or double click.
020: */
021: public final class SimpleEditor extends JFrame {
022: protected UndoableDocument doc = new UndoableDocument();
023: protected JTextPane pane = new JTextPane(doc);
024: protected final JScrollPane scrollPane;
025: protected final SearchPanel searchPanel = new SearchPanel(pane, doc);
026: protected final JPanel linePanel = new JPanel();
027:
028: // Cool and useful: double clicking on words selects all same words.
029: final ArrayList<Object> selectedWordTags = new ArrayList<Object>();
030:
031: public SimpleEditor(String title, boolean editable,
032: boolean standalone) {
033: super (title);
034: if (standalone)
035: this .setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
036:
037: pane.setEditable(editable);
038: pane
039: .setFont(new Font("Lucida Sans Typewriter", Font.PLAIN,
040: 11));
041: scrollPane = new JScrollPane(pane);
042: scrollPane.setBorder(null);
043: scrollPane.getViewport().setBorder(null); // [Oct2007]
044:
045: add(linePanel, BorderLayout.NORTH);
046: add(scrollPane, BorderLayout.CENTER);
047: add(searchPanel, BorderLayout.SOUTH);
048: searchPanel.setVisible(true);
049:
050: setSize(600, 700);
051: setLocationRelativeTo(null);
052: setVisible(true);
053:
054: pane.addMouseListener(new MouseAdapter() {
055: @Override
056: public void mousePressed(MouseEvent me) {
057: if (me.isPopupTrigger()) {
058: showPopup(me);
059: }
060: }
061:
062: @Override
063: public void mouseReleased(MouseEvent me) {
064: if (me.isPopupTrigger()) {
065: showPopup(me);
066: }
067: }
068:
069: @Override
070: public void mouseClicked(MouseEvent me) {
071: if (!me.isPopupTrigger()) {
072: clearAutoSelectedWords();
073: if (me.getClickCount() == 2) {
074: doubleClicked(me);
075: } else {
076: lineClicked(me);
077: }
078: }
079: }
080: });
081:
082: if (!editable) {
083: // pane is not editable, but we let ctrl+V (useful for pasting traces)
084: pane.registerKeyboardAction(new ActionListener() {
085: public void actionPerformed(ActionEvent ae) {
086: String txt = ClipboardUtils
087: .getClipboardStringContent();
088: if (txt != null && txt.length() > 0) {
089: doc.append("\r\n" + txt);
090: }
091: }
092: }, "paste", Accelerators.paste,
093: JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
094: } // else already defined
095:
096: pane.registerKeyboardAction(
097: new ActionListener() {
098: public void actionPerformed(ActionEvent ae) {
099: String selectedText = "";
100: if ((pane.getSelectionEnd() - pane
101: .getSelectionStart()) > 0) {
102: selectedText = pane.getSelectedText();
103: } else {
104: // detect the word at the cursor
105: selectedText = DocumentUtils.getWordAt(doc,
106: pane.getCaretPosition());
107: }
108: if (selectedText != null) {
109: clearAutoSelectedWords();
110: autoSelectWords(selectedText);
111: }
112: }
113: }, "Highlight all words",
114: Accelerators.highlightAllOccurences,
115: JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
116:
117: } // Constr
118:
119: /** @return all the text.
120: */
121: public String getText() {
122: return doc.getText(); // ok.
123: }
124:
125: public void setEditable(boolean is) {
126: pane.setEditable(is);
127: }
128:
129: public void setText(String txt) {
130: pane.setText(txt);
131: }
132:
133: public void setText(File f) throws Exception {
134: pane.setText(FileUtils.getFileStringContent(f));
135: }
136:
137: /** Resets the caret to the top of the pane and scrolls.
138: */
139: public void setCaret0() {
140: pane.setCaretPosition(0);
141: }
142:
143: public void setCaretPosition(int p) {
144: pane.setCaretPosition(p);
145: }
146:
147: /** Sets the caret to the end pane and scrolls.
148: */
149: public void setCaretEnd() {
150: if (EventQueue.isDispatchThread()) {
151: pane.setCaretPosition(doc.getLength());
152: } else {
153: EventQueue.invokeLater(new Runnable() {
154: public void run() {
155: pane.setCaretPosition(doc.getLength());
156: }
157: });
158: }
159: }
160:
161: /** Override this to create custom behaviour.
162: */
163: protected void lineClicked(MouseEvent me) {
164: }
165:
166: /** Override this to create custom behaviour. Now selecting all same words.
167: */
168: protected void doubleClicked(MouseEvent me) {
169: int sl = pane.getSelectionEnd() - pane.getSelectionStart();
170: if (sl > 0 && sl < 1000) {
171: String sel = pane.getSelectedText();
172: // highlight them all !
173: autoSelectWords(sel);
174: }
175: }
176:
177: private void clearAutoSelectedWords() {
178: //System.out.println("Clearing "+selectedWordTags.size()+" sel tags");
179: for (Object o : selectedWordTags) {
180: pane.getHighlighter().removeHighlight(o);
181: }
182: selectedWordTags.clear();
183: searchPanel.setInfoText("");
184: }
185:
186: private void autoSelectWords(String w) {
187: try {
188: int[] visibleBounds = DocumentUtils.getVisibleDocPosBounds(
189: pane, scrollPane);
190:
191: // the quick part first:
192: String part = pane.getText(visibleBounds[0],
193: visibleBounds[1] - visibleBounds[0]);
194: int pos = -1;
195: while ((pos = part.indexOf(w, pos + 1)) >= 0) {
196: selectedWordTags.add(pane.getHighlighter()
197: .addHighlight(pos + visibleBounds[0],
198: pos + visibleBounds[0] + w.length(),
199: doc.autoSelectHighlighter));
200: }
201:
202: // the whole document now (ignoring already performed part)
203:
204: part = doc.getText();
205: //pane.getText(0, doc.getLength()); /// AAAAAAHHH textPane.getText() gives different content!
206: pos = -1;
207: while ((pos = part.indexOf(w, pos + 1)) >= 0) {
208: if (pos <= visibleBounds[0] || pos >= visibleBounds[1]) {
209: selectedWordTags.add(pane.getHighlighter()
210: .addHighlight(pos, pos + w.length(),
211: doc.autoSelectHighlighter));
212: }
213: }
214:
215: searchPanel.setInfoText("" + selectedWordTags.size()
216: + " occurence"
217: + (selectedWordTags.size() == 1 ? "" : "s")
218: + " of \""
219: + StringUtils.shortFormForDisplay(w, 30) + "\"");
220:
221: //System.out.println(""+selectedWordTags.size()+" found, l="+part.length());
222: } catch (Exception e) {
223: e.printStackTrace();
224: }
225: }
226:
227: protected Object actualHighlightTag = null;
228:
229: protected void setHighlightedElementOnly(final Element lineElt) {
230: if (actualHighlightTag != null) {
231: pane.getHighlighter().removeHighlight(actualHighlightTag);
232: }
233:
234: if (lineElt != null) {
235: try {
236: actualHighlightTag = pane.getHighlighter()
237: .addHighlight(lineElt.getStartOffset(),
238: lineElt.getEndOffset(),
239: EditorDocument.errorHighlighter);
240: } catch (Exception e) {
241: e.printStackTrace();
242: }
243: }
244: }
245:
246: public void showPopup(MouseEvent me) {
247: JPopupMenu popup = createPopupBase(me);
248: popup.show(pane, me.getX(), me.getY());
249:
250: }
251:
252: /** Defines copy paste ops very useful to paste stacktraces
253: from client exceptions for example...
254: */
255: protected JPopupMenu createPopupBase(MouseEvent me) {
256:
257: JPopupMenu popup = new JPopupMenu("");
258:
259: // the menu is accessed through the context menu (right click) and maybe at another location
260: // than the caret => use the clicked point position to detect the work (if no selection)
261: final int clickedPos = pane.viewToModel(me.getPoint());
262:
263: // copy, paste, paste history
264: SharedUtils.addStandardPopupDocumentActions(popup, doc,
265: searchPanel, pane, clickedPos, true);
266:
267: String selectedText = "";
268: if ((pane.getSelectionEnd() - pane.getSelectionStart()) > 0) {
269: selectedText = pane.getSelectedText();
270: } else {
271: // detect the word at the cursot
272: selectedText = DocumentUtils.getWordAt(doc, clickedPos);
273: }
274:
275: if (selectedText != null && selectedText.length() < 1000) {
276: final String fSel = selectedText;
277: JMenuItem ht = new JMenuItem("Highlight all \""
278: + StringUtils.shortFormForDisplay(selectedText, 70)
279: + "\"");
280: ht.setAccelerator(Accelerators.highlightAllOccurences);
281: popup.addSeparator();
282: popup.add(ht);
283: ht.addActionListener(new ActionListener() {
284: public void actionPerformed(ActionEvent ae) {
285: clearAutoSelectedWords();
286: autoSelectWords(fSel);
287: }
288: });
289: }
290:
291: return popup;
292: }
293:
294: public static void main(String[] args) {
295: new SimpleEditor("Hello", true, true)
296: .setText("aa aa aa AA BB bb\n\n\nAA");
297: }
298:
299: }
|