001: /*
002: * JEditTextArea.java - jEdit's text component
003: * :tabSize=8:indentSize=8:noTabs=false:
004: * :folding=explicit:collapseFolds=1:
005: *
006: * Copyright (C) 1999, 2005 Slava Pestov
007: * Portions copyright (C) 2000 Ollie Rutherfurd
008: *
009: * This program is free software; you can redistribute it and/or
010: * modify it under the terms of the GNU General Public License
011: * as published by the Free Software Foundation; either version 2
012: * of the License, or any later version.
013: *
014: * This program is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
017: * GNU General Public License for more details.
018: *
019: * You should have received a copy of the GNU General Public License
020: * along with this program; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
022: */
023:
024: package org.gjt.sp.jedit.textarea;
025:
026: //{{{ Imports
027: import java.awt.*;
028: import java.awt.event.MouseEvent;
029:
030: import org.gjt.sp.jedit.*;
031:
032: import javax.swing.*;
033:
034: //}}}
035:
036: /**
037: * jEdit's text component.<p>
038: *
039: * Unlike most other text editors, the selection API permits selection and
040: * concurrent manipulation of multiple, non-contiguous regions of text.
041: * Methods in this class that deal with selecting text rely upon classes derived
042: * the {@link Selection} class.
043: *
044: * @author Slava Pestov
045: * @author John Gellene (API documentation)
046: * @version $Id: JEditTextArea.java 9893 2007-07-01 02:01:45Z k_satoda $
047: */
048: public class JEditTextArea extends TextArea {
049: //{{{ JEditTextArea constructor
050: /**
051: * Creates a new JEditTextArea.
052: */
053: public JEditTextArea(View view) {
054: super (view);
055: enableEvents(AWTEvent.FOCUS_EVENT_MASK
056: | AWTEvent.KEY_EVENT_MASK);
057: popupEnabled = true;
058: this .view = view;
059: } //}}}
060:
061: //{{{ smartHome() method
062: /**
063: * On subsequent invocations, first moves the caret to the first
064: * non-whitespace character of the line, then the beginning of the
065: * line, then to the first visible line.
066: * @since jEdit 2.7pre2
067: */
068: public void smartHome(boolean select) {
069: Macros.Recorder recorder = view.getMacroRecorder();
070:
071: switch (view.getInputHandler().getLastActionCount()) {
072: case 1:
073: if (recorder != null)
074: recorder.record("textArea.goToStartOfWhiteSpace("
075: + select + ");");
076:
077: goToStartOfWhiteSpace(select);
078: break;
079: case 2:
080: if (recorder != null)
081: recorder.record("textArea.goToStartOfLine(" + select
082: + ");");
083:
084: goToStartOfLine(select);
085: break;
086: default: //case 3:
087: if (recorder != null)
088: recorder.record("textArea.goToFirstVisibleLine("
089: + select + ");");
090:
091: goToFirstVisibleLine(select);
092: break;
093: }
094: } //}}}
095:
096: //{{{ smartEnd() method
097: /**
098: * On subsequent invocations, first moves the caret to the last
099: * non-whitespace character of the line, then the end of the
100: * line, then to the last visible line.
101: * @since jEdit 2.7pre2
102: */
103: public void smartEnd(boolean select) {
104: Macros.Recorder recorder = view.getMacroRecorder();
105:
106: switch (view.getInputHandler().getLastActionCount()) {
107: case 1:
108: if (recorder != null)
109: recorder.record("textArea.goToEndOfWhiteSpace("
110: + select + ");");
111:
112: goToEndOfWhiteSpace(select);
113: break;
114: case 2:
115: if (recorder != null)
116: recorder.record("textArea.goToEndOfLine(" + select
117: + ");");
118:
119: goToEndOfLine(select);
120: break;
121: default: //case 3:
122: if (recorder != null)
123: recorder.record("textArea.goToLastVisibleLine("
124: + select + ");");
125: goToLastVisibleLine(select);
126: break;
127: }
128: } //}}}
129:
130: //{{{ showGoToLineDialog() method
131: /**
132: * Displays the 'go to line' dialog box, and moves the caret to the
133: * specified line number.
134: * @since jEdit 2.7pre2
135: */
136: public void showGoToLineDialog() {
137: String line = GUIUtilities.input(view, "goto-line", null);
138: if (line == null)
139: return;
140:
141: try {
142: int lineNumber = Integer.parseInt(line) - 1;
143: setCaretPosition(getLineStartOffset(lineNumber));
144: } catch (Exception e) {
145: getToolkit().beep();
146: }
147: } //}}}
148:
149: //{{{ userInput() method
150: /**
151: * Handles the insertion of the specified character. It performs the
152: * following operations in addition to TextArea#userInput(char):
153: * <ul>
154: * <li>Inserting a space with automatic abbrev expansion enabled will
155: * try to expand the abbrev
156: * </ul>
157: *
158: * @param ch The character
159: * @since jEdit 2.7pre3
160: */
161: public void userInput(char ch) {
162: if (ch == ' ' && Abbrevs.getExpandOnInput()
163: && Abbrevs.expandAbbrev(view, false))
164: return;
165:
166: super .userInput(ch);
167: } //}}}
168:
169: //{{{ addExplicitFold() method
170: /**
171: * Surrounds the selection with explicit fold markers.
172: * @since jEdit 4.0pre3
173: */
174: public void addExplicitFold() {
175: try {
176: super .addExplicitFold();
177: } catch (TextAreaException e) {
178: GUIUtilities.error(view, "folding-not-explicit", null);
179: }
180: } //}}}
181:
182: //{{{ formatParagraph() method
183: /**
184: * Formats the paragraph containing the caret.
185: * @since jEdit 2.7pre2
186: */
187: public void formatParagraph() {
188: try {
189: super .formatParagraph();
190: } catch (TextAreaException e) {
191: GUIUtilities.error(view, "format-maxlinelen", null);
192: }
193: } //}}}
194:
195: //{{{ doWordCount() method
196: protected static void doWordCount(View view, String text) {
197: char[] chars = text.toCharArray();
198: int characters = chars.length;
199: int words = 0;
200: int lines = 1;
201:
202: boolean word = true;
203: for (int i = 0; i < chars.length; i++) {
204: switch (chars[i]) {
205: case '\r':
206: case '\n':
207: lines++;
208: case ' ':
209: case '\t':
210: word = true;
211: break;
212: default:
213: if (word) {
214: words++;
215: word = false;
216: }
217: break;
218: }
219: }
220:
221: Object[] args = { characters, words, lines };
222: GUIUtilities.message(view, "wordcount", args);
223: } //}}}
224:
225: //{{{ showWordCountDialog() method
226: /**
227: * Displays the 'word count' dialog box.
228: * @since jEdit 2.7pre2
229: */
230: public void showWordCountDialog() {
231: String selection = getSelectedText();
232: if (selection != null) {
233: doWordCount(view, selection);
234: return;
235: }
236:
237: doWordCount(view, buffer.getText(0, buffer.getLength()));
238: } //}}}
239:
240: //{{{ Getters and setters
241:
242: //{{{ getView() method
243: /**
244: * Returns this text area's view.
245: * @since jEdit 4.2pre5
246: */
247: public View getView() {
248: return view;
249: } //}}}
250:
251: //}}}
252:
253: //{{{ Private members
254:
255: //{{{ Instance variables
256: private View view;
257: private JPopupMenu popup;
258: private boolean popupEnabled;
259:
260: //}}}
261: //}}}
262:
263: //{{{ isRightClickPopupEnabled() method
264: /**
265: * Returns if the right click popup menu is enabled. The Gestures
266: * plugin uses this API.
267: * @since jEdit 4.2pre13
268: */
269: public boolean isRightClickPopupEnabled() {
270: return popupEnabled;
271: } //}}}
272:
273: //{{{ setRightClickPopupEnabled() method
274: /**
275: * Sets if the right click popup menu is enabled. The Gestures
276: * plugin uses this API.
277: * @since jEdit 4.2pre13
278: */
279: public void setRightClickPopupEnabled(boolean popupEnabled) {
280: this .popupEnabled = popupEnabled;
281: } //}}}
282:
283: //{{{ getRightClickPopup() method
284: /**
285: * Returns the right click popup menu.
286: */
287: public final JPopupMenu getRightClickPopup() {
288: return popup;
289: } //}}}
290:
291: //{{{ setRightClickPopup() method
292: /**
293: * Sets the right click popup menu.
294: * @param popup The popup
295: */
296: public final void setRightClickPopup(JPopupMenu popup) {
297: this .popup = popup;
298: } //}}}
299:
300: //{{{ handlePopupTrigger() method
301: /**
302: * Do the same thing as right-clicking on the text area. The Gestures
303: * plugin uses this API.
304: * @since jEdit 4.2pre13
305: */
306: public void handlePopupTrigger(MouseEvent evt) {
307: if (popup.isVisible())
308: popup.setVisible(false);
309: else {
310: int x = evt.getX();
311: int y = evt.getY();
312:
313: int dragStart = xyToOffset(x, y, !(painter
314: .isBlockCaretEnabled() || isOverwriteEnabled()));
315:
316: if (getSelectionCount() == 0 || multi)
317: moveCaretPosition(dragStart, false);
318: GUIUtilities.showPopupMenu(popup, painter, x, y);
319: }
320: } //}}}
321:
322: //{{{ showPopupMenu() method
323: /**
324: * Shows the popup menu below the current caret position.
325: * @since 4.3pre10
326: */
327: public void showPopupMenu() {
328: if (!popup.isVisible() && hasFocus()) {
329: Point caretPos = offsetToXY(getCaretPosition());
330: if (caretPos != null) {
331: // Open the context menu below the caret
332: int charHeight = getPainter().getFontMetrics()
333: .getHeight();
334: GUIUtilities.showPopupMenu(popup, painter, caretPos.x,
335: caretPos.y + charHeight, true);
336: }
337: }
338: } //}}}
339:
340: }
|