001: /*
002: * Mode.java
003: *
004: * Copyright (C) 1998-2003 Peter Graves
005: * $Id: Mode.java,v 1.9 2003/06/30 17:00:41 piso Exp $
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: */
021:
022: package org.armedbear.j;
023:
024: import java.awt.Color;
025: import java.awt.event.MouseEvent;
026: import javax.swing.JPopupMenu;
027:
028: /**
029: * Mode is an interface for defining modes. A mode is a set of rules that
030: * define how the editor behaves. Different behaviors are desireable when
031: * editing different kinds of files. As an example, a user expects
032: * different behavior/functionality when editing a C++ file than what she
033: * expects when editing a Lisp file.
034: * <p>
035: * Users should not implement Mode directly, they should instead extend
036: * {@link AbstractMode AbstractMode}.
037: *
038: * @see AbstractMode
039: */
040: public interface Mode {
041: /**
042: * Returns the unique identifier of this mode. All identifiers should
043: * be defined in <code>Constants</code>.
044: *
045: * @return the unique identifier for this mode
046: * @see Constants
047: */
048: public int getId();
049:
050: /**
051: * Returns the display name of this mode. All display names should be
052: * defined in <code>Constants</code>.
053: *
054: * @return the display name of this mode
055: * @see Constants
056: */
057: public String getDisplayName();
058:
059: public Buffer createBuffer(File file);
060:
061: /**
062: * Returns a <code>Formatter</code> for the given <code>Buffer</code>.
063: *
064: * @param buffer the <code>Buffer</code> that is to be formatted
065: * according to this mode
066: * @return a <code>Formatter</code> for the given mode.
067: */
068: public Formatter getFormatter(Buffer buffer);
069:
070: /**
071: * Returns a non-null <code>KeyMap</code> that may define custom
072: * <code>KeyMapping</code>s for this Mode. If there are no custom
073: * <code>KeyMapping</code>s for this Mode, then an empty
074: * <code>KeyMap</code> is returned.
075: *
076: * @return a non-null KeyMap
077: * @see KeyMapping
078: */
079: public KeyMap getKeyMap();
080:
081: /**
082: * Returns the file that defines a custom <code>KeyMap</code> for
083: * this Mode, if any.
084: *
085: * @return the <code>KeyMap</code> file, or <code>null</code> if there is
086: * none.
087: * @see #getKeyMap
088: * @see KeyMap
089: * @see KeyMapping
090: */
091: public File getKeyMapFile();
092:
093: public void useDefaultKeyMap();
094:
095: public void deleteKeyMap();
096:
097: /**
098: * Returns an identifier for the <code>MenuBar</code> that is to
099: * be used for this mode.
100: * Override this method to return a unique name if you override
101: * {@link #createMenuBar(Frame) createMenuBar} to have a
102: * custom menu.
103: *
104: * @return an identifier for the <code>MenuBar</code> that is returned
105: * by calling <code>createMenuBar</code>.
106: */
107: public String getMenuName();
108:
109: /**
110: * Returns the MenuBar that is to be used for this mode.
111: * Override to return a custom <code>MenuBar</code> for this mode.
112: * If this method is overriden, then you must also override
113: * {@link #getMenuName() getMenuName} to return a unique identifier,
114: * otherwise the default is fine.
115: *
116: * @param frame the frame that the <code>MenuBar</code> will be
117: * attached to
118: * @return a <code>MenuBar</code> for the specified frame
119: */
120: public MenuBar createMenuBar(Frame frame);
121:
122: /**
123: * Populates the given <code>Menu</code> with appropriate menu items.
124: * Unless there is a compelling reason not to, classes that override
125: * this method should call <code>super.createMenuBar(editor, menu)</code>
126: * when they are done putting in their own entries.
127: *
128: * @param editor the current <code>Editor</code>.
129: * @param menu the <code>Menu</code> that is to be populated with
130: * entries for this mode.
131: */
132: public void populateMenu(Editor editor, Menu menu);
133:
134: public void populateModeMenu(Editor editor, Menu menu);
135:
136: /**
137: * Returns a context menu populated with entries specific to the given
138: * mode and the current location in the specified <code>Editor</code>.
139: *
140: * @param editor the current <code>Editor</code>
141: * @return a menu filled with context sensitive goodies.
142: */
143: public JPopupMenu getContextMenu(Editor editor);
144:
145: /**
146: * Returns a <code>ToolBar</code> for the specified <code>Frame</code>.
147: *
148: * @param frame the <code>Frame</code>
149: * @return the <code>ToolBar</code>
150: */
151: public ToolBar getToolBar(Frame frame);
152:
153: /**
154: * Returns a navigation component for the specified <code>Editor</code>,
155: * or <code>null</code> if there is no navigation component for this mode.
156: * <p>
157: * The navigation component appears in the lower pane of the sidebar.
158: *
159: * @param editor the <code>Editor</code>
160: * @return the navigation component, or <code>null</code>
161: */
162: public NavigationComponent getSidebarComponent(Editor editor);
163:
164: /**
165: * Most useful for programming language modes, this method returns
166: * either a <code>Tagger</code> for this mode, or <code>null</code>. If a
167: * <code>Tagger</code> is returned, then
168: * {@link #isTaggable() isTaggable()} must return <code>true</code>.
169: * Otherwise it should return <code>false</code>.
170: *
171: * @param buffer the current buffer
172: * @return a <code>Tagger</code> specific for this mode or
173: * <code>null</code> if a <code>Tagger</code> is not
174: * applicable.
175: */
176: public Tagger getTagger(SystemBuffer buffer);
177:
178: /**
179: * Returns whether or not this mode has a {@link Tagger Tagger}
180: * associated with it. This returns <code>false</code> if
181: * {@link #getTagger(SystemBuffer) getTagger()} returns <code>null</code>,
182: * and <code>true</code> otherwise.
183: *
184: * @return Whether or not this mode is taggable. Which is the same as
185: * whether or not <code>getTagger</code> returns <code>null</code>.
186: */
187: public boolean isTaggable();
188:
189: /**
190: * Returns <code>true</code> if the mode's underlying programming language
191: * supports qualified names. (For example, Java, C++ and Perl do; C does
192: * not.)
193: *
194: * @return <code>true</code> if the mode supports qualified names.
195: * @since 0.16.1
196: */
197: public boolean hasQualifiedNames();
198:
199: /**
200: * Returns <code>true</code> if the string in question is a qualified name
201: * in the mode's underlying programming language.
202: *
203: * @return <code>true</code> if the string is a qualified name.
204: * @since 0.16.1
205: */
206: public boolean isQualifiedName(String s);
207:
208: /**
209: * Returns whether or not this mode will potentially perform context
210: * sensitive indentation on a given <code>Line</code> in a given
211: * <code>Buffer</code>. This returns <code>true</code> if
212: * {@link #getCorrectIndentation(Line, Buffer) getCorrectIndentation()}
213: * might return something other than zero, <code>false</code> otherwise.
214: *
215: * @return <code>true</code> if this mode supports context-sensitive
216: * indentation.
217: *
218: */
219: public boolean canIndent();
220:
221: /**
222: * Returns whether or not this mode will potentially perform context
223: * sensitive indentation for a paste operation. This returns
224: * <code>true</code> if
225: * {@link #getCorrectIndentation(Line, Buffer) getCorrectIndentation()}
226: * might return something other than zero, <code>false</code> otherwise.
227: *
228: * @return <code>true<code> if this mode supports context-sensitive
229: * indentation of pasted text.
230: */
231: public boolean canIndentPaste();
232:
233: public boolean acceptsLinePaste(Editor editor);
234:
235: /**
236: * Returns the amount of indentation (in columns) needed to indent the
237: * specified <code>Line</code> in the context of the given
238: * <code>Buffer</code>.
239: * <p>
240: * If this mode does not support automatic context-sensitive indentation,
241: * that is if {@link #canIndent() canIndent()} returns <code>false</code>,
242: * then this method returns zero.
243: *
244: * @param line the line to be indented
245: * @param buffer the buffer which contains the line
246: * @return the amount of indentation required, in columns.
247: */
248: public int getCorrectIndentation(Line line, Buffer buffer);
249:
250: /**
251: * Returns a <code>SyntaxIterator</code> specific for this mode that
252: * is situated at the given <code>Position</code>.
253: *
254: * @param pos where to situate the <code>SyntaxIterator</code>.
255: * @return a <code>SyntaxIterator</code> for this mode.
256: */
257: public SyntaxIterator getSyntaxIterator(Position pos);
258:
259: /**
260: * Returns a string that signifies the start of a comment for the
261: * given mode, or <code>null</code> if the concept of comments is
262: * not applicable to this mode.
263: *
264: * @return the token to start a comment, or <code>null<code> if not
265: * applicable.
266: */
267: public String getCommentStart();
268:
269: /**
270: * Returns a string that signifies the end of a comment for the
271: * given mode, or <code>null</code> if the concept of comments is
272: * not applicable to this mode or the comment does not require an
273: * end token.
274: *
275: * @return the token to end a comment, or <code>null<code> if not
276: * applicable.
277: */
278: public String getCommentEnd();
279:
280: /**
281: * Looks in all mode and non-mode specific properties/preferences and
282: * returns the value attached to the given key, or the default value
283: * given in <code>property</code> if the key is not found. The property
284: * and preferences lists are searched in an manner which gives precedence
285: * in the following order: mode specific preferences, mode specific
286: * properties, global preferences.
287: *
288: * @param property the key to look for with the default value to return
289: * if the key is not found.
290: * @return the value of the given property, or the default in the
291: * given <code>Property</code> if the property's key is
292: * not found.
293: */
294: public boolean getBooleanProperty(Property property);
295:
296: /**
297: * Looks in all mode and non-mode specific properties/preferences and
298: * returns the value attached to the given key, or the default value
299: * given in <code>property</code> if the key is not found. The property
300: * and preferences lists are searched in an manner which gives precedence
301: * in the following order: mode specific preferences, mode specific
302: * properties, global preferences.
303: *
304: * @param property the key to look for with the default value to return
305: * if the key is not found.
306: * @return the value of the given property, or the default in the
307: * given <code>Property</code> if the property's key is
308: * not found.
309: */
310: public int getIntegerProperty(Property property);
311:
312: /**
313: * Looks in all mode and non-mode specific properties/preferences and
314: * returns the value attached to the given key, or the default value
315: * given in <code>property</code> if the key is not found. The property
316: * and preferences lists are searched in an manner which gives precedence
317: * in the following order: mode specific preferences, mode specific
318: * properties, global preferences.
319: *
320: * @param property the key to look for with the default value to return
321: * if the key is not found.
322: * @return the value of the given property, or the default in the
323: * given <code>Property</code> if the property's key is
324: * not found.
325: */
326: public String getStringProperty(Property property);
327:
328: /**
329: * Looks in all mode and non-mode specific properties/preferences and
330: * returns the value attached to the given key, or the default value
331: * given in <code>property</code> if the key is not found. The property
332: * and preferences lists are searched in an manner which gives precedence
333: * in the following order: mode specific preferences, mode specific
334: * properties, global preferences.
335: *
336: * @param property the key to look for with the default value to return
337: * if the key is not found.
338: * @return the value of the given property, or the default in the
339: * given <code>Property</code> if the property's key is
340: * not found.
341: */
342: public Color getColorProperty(Property property);
343:
344: public void setProperty(Property property, String value);
345:
346: public void setProperty(Property property, boolean value);
347:
348: public void setProperty(Property property, int value);
349:
350: /**
351: * Returns whether or not this mode is willing to accept the given
352: * file name.
353: *
354: * @param filename the name of the file that is to be checked for
355: * validity for this mode.
356: * @return <code>true</code> if the given filename can be handled
357: * by this mode.
358: */
359: public boolean accepts(String filename);
360:
361: /**
362: * Checks the given character against a list of characters that are
363: * legal identifier starts. Some languages have different requirements
364: * for the beginning of an identifier than the rest of that identifier.
365: * Such a case is Java which allows digits in an identifier name, but
366: * does not allow them to be the first character.
367: *
368: * @param char the character to be checked for validity.
369: * @return <code>true</code> if <code>c</code> is one of the
370: * legal identifier start characters for this mode.
371: */
372: public boolean isIdentifierStart(char c);
373:
374: /**
375: * Checks the given character against a list of characters that are
376: * legal identifier parts (not the first character). Some languages
377: * have different requirements for the beginning of an identifier than
378: * the rest of that identifier. Such a case is Java which allows digits
379: * in an identifier part, but does not allow a digit to be the first
380: * character.
381: *
382: * @param char the character to be checked for validity.
383: * @return <code>true</code> if <code>c</code> is one of the
384: * legal identifier parts for this mode.
385: */
386: public boolean isIdentifierPart(char c);
387:
388: /**
389: * Returns <code>true</code> if the specified position is inside a quoted
390: * string.
391: *
392: * @param buffer the <code>Buffer</code> containing the specified
393: * position
394: * @param pos the position
395: * @return <code>true</code> if <code>pos</code> is inside a
396: * quoted string.
397: */
398: public boolean isInQuote(Buffer buffer, Position pos);
399:
400: /**
401: * Returns <code>true</code> if the specified position is inside a comment.
402: *
403: * @param buffer the <code>Buffer</code> containing the specified
404: * position
405: * @param pos the position
406: * @return <code>true</code> if <code>pos</code> is inside a
407: * comment.
408: */
409: public boolean isInComment(Buffer buffer, Position pos);
410:
411: /**
412: * Returns whether or not the given <code>Line</code> is a comment.
413: *
414: * @param line the <code>Line</code> to check to see if it is a
415: * comment.
416: * @return <code>true</code> if <code>line</code> qualifies as
417: * a comment for this mode.
418: */
419: public boolean isCommentLine(Line line);
420:
421: /**
422: * Examines <code>c</code> and returns the equivalent character but
423: * possibly with a different case (upper or lower) as the rules of
424: * this mode dictate. This is primarily used in programming language
425: * modes where the language is case-insensitive and the user wants
426: * certain identifiers to have a certain casing style (all upper, all
427: * lower).
428: *
429: * @param editor the <code>Editor</code> for context.
430: * @param c the character in question.
431: * @return the character represented by <code>c</code> as the
432: * proper case given the context of <code>editor</code>
433: * and the case rules of this mode.
434: */
435: public char fixCase(Editor editor, char c);
436:
437: /**
438: * Returns a string that describes something about the current caret
439: * position that is suitable to be displayed in the <code>StatusBar</code>.
440: *
441: * @param editor the <code>Editor</code> for context.
442: * @param verbose whether or not to return more information.
443: * @return information relevant to the current caret position.
444: */
445: public String getContextString(Editor editor, boolean verbose);
446:
447: /**
448: * Returns a string that describes something about the current mouse
449: * position that is suitable to be displayed in the <code>StatusBar</code>,
450: * or <code>null</code> if there is none.
451: *
452: * @param editor the <code>Editor</code> for context.
453: * @return information relevant to the current mouse position.
454: */
455: public String getMouseMovedContextString(Editor editor, Position pos);
456:
457: /**
458: * Returns a string that describes something about the current mouse
459: * position that is suitable to be displayed as a tool tip, or
460: * <code>null</code> if there is none.
461: *
462: * @param editor the <code>Editor</code> for context.
463: * @return information relevant to the current mouse position.
464: */
465: public String getToolTipText(Editor editor, MouseEvent e);
466:
467: /**
468: * If this mode needs to do any special processing on a file in order to
469: * load it into the buffer, e.g. the file is an archive, that
470: * processing is to be done here. This method is called from the
471: * protected {@link Buffer#loadFile(File) loadFile} method in
472: * <code>Buffer</code> when loading a file. It is also called from
473: * the {@link Buffer#reload() reload} method in <code>Buffer</code>.
474: *
475: * @param buffer the <code>Buffer</code> that the file is to be loaded
476: * into.
477: * @param file the input source.
478: */
479: public void loadFile(Buffer buffer, File file);
480:
481: /**
482: * Allows this mode to confirm the closing of a <code>Buffer</code>, and
483: * can cancel it by returning <code>false</code>. <code>confirmClose</code>
484: * allows for this mode to do things such as make sure the user wants to
485: * close a <code>Buffer</code> even though it has been modified.
486: *
487: * @param editor the <code>Editor</code> for context.
488: * @param buffer the <code>Buffer</code> that is to be closed.
489: * @return <code>true</code> to allow the <code>Buffer</code> to
490: * close.
491: */
492: public boolean confirmClose(Editor editor, Buffer buffer);
493:
494: /**
495: * Checks the given string against a list of keywords for this mode, and
496: * returns <code>true</code> if the string is on that list.
497: *
498: * @param s the keyword to test.
499: * @return <code>true</code> if <code>s</code> is a valid keyword
500: * for this mode.
501: */
502: public boolean isKeyword(String s);
503:
504: /**
505: * Returns the expression at the current location of the caret in the
506: * specified editor.
507: *
508: * @param editor the editor in question
509: * @param exact a hint to the implementation: if true, return the
510: * expression at the exact location of the caret; if
511: * false, look for a suitable expression on the same line
512: * @return the expression, or <code>null</code> if no expression
513: * is found.
514: * @since 0.16.1
515: */
516: public Expression getExpressionAtDot(Editor editor, boolean exact);
517:
518: /**
519: * Returns the identifier at the specified position.
520: *
521: * @param pos the position
522: * @return the identifier at the specified position, or
523: * <code>null</code> if no identifier is found.
524: * @since 0.16.1
525: */
526: public String getIdentifier(Position pos);
527:
528: /**
529: * Returns the identifier at the specified line and offset.
530: *
531: * @param line the line
532: * @param offset the offset
533: * @return the identifier at the specified line and offset, or
534: * <code>null</code> if no identifier is found.
535: * @since 0.16.1
536: */
537: public String getIdentifier(Line line, int offset);
538:
539: /**
540: * Returns the position of the start of the identifier at the specified
541: * line and offset.
542: *
543: * @param line the line
544: * @param offset the offset
545: * @return the position of the start of the identifier at the
546: * specified line and offset or <code>null</code> if no
547: * identifier is found.
548: * @since 0.16.1
549: */
550: public Position findIdentifierStart(Line line, int offset);
551: }
|