477 lines
16 KiB
Racket
477 lines
16 KiB
Racket
#lang scribble/doc
|
|
@(require scribble/manual scribble/extract)
|
|
@(require (for-label framework))
|
|
@(require (for-label scheme/gui))
|
|
@title{Editor}
|
|
|
|
@definterface[editor:basic<%> (editor<%>)]{
|
|
Classes matching this interface support the basic
|
|
@scheme[editor<%>]
|
|
functionality required by the framework.
|
|
@defmethod*[(((has-focus?) boolean?))]{
|
|
This function returns @scheme[#t] when the editor has the keyboard
|
|
focus. It is implemented using:
|
|
@method[editor<%> on-focus]
|
|
|
|
}
|
|
@defmethod*[(((local-edit-sequence?) boolean?))]{
|
|
Indicates if this editor is in an edit sequence. Enclosing buffer's
|
|
edit-sequence status is not considered by this method.
|
|
|
|
See
|
|
@method[editor<%> begin-edit-sequence]
|
|
and
|
|
@method[editor<%> end-edit-sequence]
|
|
for more info about edit sequences.
|
|
|
|
}
|
|
@defmethod*[(((run-after-edit-sequence (thunk (-> void)) (tag (union symbol? #f) #f)) void))]{
|
|
This method is used to install callbacks that will be run after any
|
|
edit-sequence completes.
|
|
|
|
|
|
The procedure @scheme[thunk] will be called immediately if the edit is
|
|
not in an edit-sequence. If the edit is in an edit-sequence, it will
|
|
be called when the edit-sequence completes.
|
|
|
|
If @scheme[tag] is a symbol, the @scheme[thunk] is keyed on that symbol, and
|
|
only one thunk per symbol will be called after the
|
|
edit-sequence. Specifically, the last call to
|
|
@method[editor:basic<%> run-after-edit-sequence]'s argument will be called.
|
|
|
|
}
|
|
@defmethod*[(((get-top-level-window) (union #f (is-a?/c top-level-window<%>))))]{
|
|
Returns the
|
|
@scheme[top-level-window<%>]
|
|
currently associated with this buffer.
|
|
|
|
This does not work for embedded editors.
|
|
|
|
|
|
}
|
|
@defmethod*[(((save-file-out-of-date?) boolean?))]{
|
|
Returns @scheme[#t] if the file on disk has been modified, by some other program.
|
|
|
|
}
|
|
@defmethod*[(((save-file/gui-error (filename (union path #f) #f) (format (union (quote guess) (quote standard) (quote text) (quote text-force-cr) same copy) (quote same)) (show-errors? boolean |#t|)) boolean?))]{
|
|
This method is an alternative to
|
|
@method[editor<%> save-file]. Rather than showing errors via the original stdout, it
|
|
opens a dialog with an error message showing the error.
|
|
|
|
The result indicates if an error happened (the error has
|
|
already been shown to the user). It returns @scheme[#t] if
|
|
no error occurred and @scheme[#f] if an error occurred.
|
|
|
|
}
|
|
@defmethod*[(((load-file/gui-error (filename (union string #f) #f) (format (union (quote guess) (quote standard) (quote text) (quote text-force-cr) (quote same) (quote copy)) (quote guess)) (show-errors? boolean |#t|)) boolean?))]{
|
|
This method is an alternative to
|
|
@method[editor<%> load-file]. Rather than showing errors via the original stdout, it
|
|
opens a dialog with an error message showing the error.
|
|
|
|
The result indicates if an error happened (the error has
|
|
already been shown to the user). It returns @scheme[#t] if
|
|
no error occurred and @scheme[#f] if an error occurred.
|
|
|
|
}
|
|
@defmethod*[(((on-close) void))]{
|
|
|
|
This method is called when an editor is closed.
|
|
Typically, this method is called when the frame
|
|
containing the editor is closed, but in some cases an
|
|
editor is considered ``closed'' before the frame it is
|
|
in is closed (e.g., when a tab in DrRacket is closed), and
|
|
thus @method[editor:basic<%> on-close] will be called at that point.
|
|
|
|
|
|
See also
|
|
@method[editor:basic<%> can-close?]
|
|
and
|
|
@method[editor:basic<%> close].
|
|
|
|
|
|
Does nothing.
|
|
}
|
|
@defmethod*[(((can-close?) boolean?))]{
|
|
This method is called to query the editor if is okay to
|
|
close the editor. Although there is no visible effect
|
|
associated with closing an editor, there may be some cleanup
|
|
actions that need to be run when the user is finished with
|
|
the editor (asking if it should be saved, for example).
|
|
|
|
See also
|
|
@method[editor:basic<%> on-close] and
|
|
@method[editor:basic<%> close].
|
|
|
|
|
|
Returns @scheme[#t].
|
|
}
|
|
@defmethod*[(((close) boolean?))]{
|
|
This method is merely
|
|
@schemeblock[
|
|
(if (can-close?)
|
|
(begin (on-close) #t)
|
|
#f)]
|
|
|
|
It is intended as a shorthand, helper method for closing
|
|
an editor. See also
|
|
@method[editor:basic<%> can-close?]
|
|
and
|
|
@method[editor:basic<%> on-close].
|
|
|
|
}
|
|
@defmethod*[(((get-filename/untitled-name) string))]{
|
|
Returns the printed version of the filename for this
|
|
editor. If the editor doesn't yet have a filename, it
|
|
returns a symbolic name (something like "Untitled").
|
|
|
|
}
|
|
|
|
@defmethod[(get-pos/text [event (is-a?/c mouse-event%)])
|
|
(values (or/c false/c (is-a?/c editor<%>))
|
|
(or/c false/c number?))]{
|
|
|
|
This method's first result is @scheme[#f] when the mouse
|
|
event does not correspond to a location in the editor.
|
|
|
|
If the first result is an @scheme[text%] object, then the
|
|
second result will be a position in the editor and
|
|
otherwise the second result will be @scheme[#f].
|
|
|
|
The @scheme[editor<%>] object will always be the nearest
|
|
enclosing editor containing the mouse click.
|
|
}
|
|
}
|
|
@defmixin[editor:basic-mixin (editor<%>) (editor:basic<%>)]{
|
|
This provides the basic editor services required by the rest of the
|
|
framework.
|
|
|
|
The result of this mixin uses the same initialization arguments as the
|
|
mixin's argument.
|
|
|
|
Each instance of a class created with this mixin contains a private
|
|
@scheme[keymap%] that is chained to the global keymap via:
|
|
@scheme[(send keymap chain-to-keymap (keymap:get-global) #f)].
|
|
|
|
This installs the global keymap @scheme[keymap:get-global] to
|
|
handle keyboard and mouse mappings not handled by @scheme[keymap]. The
|
|
global keymap is created when the framework is invoked.
|
|
@defmethod*[#:mode augment (((can-save-file? (filename string) (format symbol?)) boolean?))]{
|
|
|
|
Checks to see if the file on the disk has been modified out
|
|
side of this editor, using
|
|
@method[editor:basic<%> save-file-out-of-date?].
|
|
If it has, this method prompts the user to be sure they want to save.
|
|
|
|
}
|
|
@defmethod*[#:mode augment (((after-save-file (success? boolean?)) void))]{
|
|
|
|
If the current filename is not a temporary filename, this method calls
|
|
@scheme[handler:add-to-recent]with the current filename.
|
|
|
|
to add the new filename to the list of recently opened files.
|
|
|
|
Additionally, updates a private instance variable with the
|
|
modification time of the file, for using in implementing
|
|
@method[editor:basic<%> save-file-out-of-date?].
|
|
|
|
}
|
|
@defmethod*[#:mode augment (((after-load-file (success? boolean?)) void))]{
|
|
|
|
Updates a private instance variable with the modification
|
|
time of the file, for using in implementing
|
|
@method[editor:basic<%> save-file-out-of-date?]
|
|
|
|
}
|
|
@defmethod*[#:mode override (((on-focus (on? boolean?)) void))]{
|
|
Manages the state to implement
|
|
@method[editor:basic<%> has-focus?]
|
|
|
|
}
|
|
@defmethod*[#:mode augment (((on-edit-sequence) boolean?))]{
|
|
|
|
Always returns @scheme[#t]. Updates a flag for
|
|
@method[editor:basic<%> local-edit-sequence?]
|
|
}
|
|
@defmethod*[#:mode augment (((after-edit-sequence) void))]{
|
|
|
|
Helps to implement
|
|
@method[editor:basic<%> run-after-edit-sequence].
|
|
}
|
|
@defmethod*[#:mode override (((on-new-box (type (union (quote pasteboard) (quote text)))) (instance editor-snip%)))]{
|
|
|
|
Creates instances of
|
|
@scheme[pasteboard:basic%]
|
|
or
|
|
@scheme[text:basic%]
|
|
instead of the built in
|
|
@scheme[pasteboard%]
|
|
and
|
|
@scheme[text%]
|
|
classes.
|
|
}
|
|
@defmethod[#:mode override (on-new-image-snip [filname (or/c path? false/c)]
|
|
[kind (one-of/c 'unknown 'gif 'jpeg 'xbm 'xpm 'bmp 'pict)]
|
|
[relative-path? any/c]
|
|
[inline? any/c])
|
|
(is-a?/c image-snip%)]{
|
|
@schemeblock[
|
|
(super on-new-image-snip
|
|
(if (eq? kind 'unknown) 'unknown/mask kind)
|
|
relative-path?
|
|
inline?)]
|
|
}
|
|
|
|
@defmethod*[#:mode override (((get-file (directory (or/c path-string? false/c))) string))]{
|
|
|
|
Uses
|
|
@scheme[finder:get-file]
|
|
to find a filename. Also, sets the parameter
|
|
@scheme[finder:dialog-parent-parameter]
|
|
to the result of
|
|
@method[editor:basic<%> get-top-level-window].
|
|
}
|
|
@defmethod*[#:mode override (((put-file (directory (or/c path? false/c)) (default-name (or/c path? false/c))) string))]{
|
|
|
|
Uses
|
|
@scheme[finder:put-file]
|
|
to find a filename. Also, sets the parameter
|
|
@scheme[finder:dialog-parent-parameter]
|
|
to the result of
|
|
@method[editor:basic<%> get-top-level-window].
|
|
}
|
|
}
|
|
@definterface[editor:standard-style-list<%> (editor<%>)]{
|
|
This interface is implemented by the results of
|
|
@scheme[editor:standard-style-list-mixin].
|
|
}
|
|
@defmixin[editor:standard-style-list-mixin (editor<%>) (editor:standard-style-list<%>)]{
|
|
The mixin adds code to the initialization
|
|
of the class that sets the editor's style
|
|
list (via
|
|
@method[editor<%> set-style-list])
|
|
to the result of
|
|
@scheme[editor:get-standard-style-list].
|
|
|
|
In addition, it calls
|
|
@method[editor<%> set-load-overwrites-styles]
|
|
with @scheme[#f].
|
|
This ensures that saved files with different
|
|
settings for the style list do not clobber
|
|
the shared style list.
|
|
}
|
|
@definterface[editor:keymap<%> (editor:basic<%>)]{
|
|
Classes matching this interface add support for mixing in multiple
|
|
keymaps. They provides an extensible interface to chained keymaps,
|
|
through the
|
|
@method[editor:keymap<%> get-keymaps]
|
|
method.
|
|
|
|
This editor is initialized by calling
|
|
@scheme[add-editor-keymap-functions],
|
|
@scheme[add-text-keymap-functions], and
|
|
@scheme[add-pasteboard-keymap-functions].
|
|
@defmethod*[(((get-keymaps) (list-of (instance keymap%))))]{
|
|
The keymaps returned from this method are chained to this
|
|
@scheme[editor<%>]'s keymap.
|
|
|
|
The result of this method should not change -- that is, it
|
|
should return the same list of keymaps each time it is
|
|
called.
|
|
|
|
See also @scheme[editor:add-after-user-keymap].
|
|
|
|
Defaultly returns @scheme[(list (keymap:get-user) (keymap:get-global))]
|
|
}
|
|
}
|
|
@defmixin[editor:keymap-mixin (editor:basic<%>) (editor:keymap<%>)]{
|
|
This provides a mixin that implements the
|
|
@scheme[editor:keymap<%>]
|
|
interface.
|
|
}
|
|
@definterface[editor:autowrap<%> (editor:basic<%>)]{
|
|
Classes implementing this interface keep the
|
|
@method[editor<%> auto-wrap]
|
|
state set based on the
|
|
@scheme['framework:auto-set-wrap?] preference
|
|
(see @scheme[preferences:get] for more information about preferences).
|
|
|
|
They install a preferences callback with
|
|
@scheme[preferences:add-callback]
|
|
that sets the state when the preference changes and
|
|
initialize the value of
|
|
@method[editor<%> auto-wrap]
|
|
to the current value of @scheme['framework:auto-set-wrap?]
|
|
via
|
|
@scheme[preferences:get].
|
|
}
|
|
@defmixin[editor:autowrap-mixin (editor:basic<%>) (editor:autowrap<%>)]{
|
|
See
|
|
@scheme[editor:autowrap<%>]
|
|
}
|
|
@definterface[editor:file<%> (editor:keymap<%>)]{
|
|
Objects supporting this interface are expected to support files.
|
|
@defmethod*[(((get-can-close-parent) (union false (is-a/c? frame%) (is-a/c? dialog%))))]{
|
|
The result of this method is used as the parent for the
|
|
dialog that asks about closing.
|
|
|
|
|
|
Defaultly returns @scheme[#f].
|
|
}
|
|
@defmethod*[(((update-frame-filename) void))]{
|
|
Attempts to find a frame that displays this editor. If it
|
|
does, it updates the frame's title based on a new filename
|
|
in the editor.
|
|
|
|
}
|
|
@defmethod*[(((allow-close-with-no-filename?) boolean?))]{
|
|
This method indicates if closing the file when it hasn't
|
|
been saved is a reason to alert the user. See also
|
|
@method[editor:file-mixin can-close?].
|
|
|
|
|
|
Defaultly returns @scheme[#f].
|
|
}
|
|
|
|
@defmethod[(user-saves-or-not-modified? [allow-cancel? #t]) boolean?]{
|
|
If the file has not been saved, this prompts the user about saving and,
|
|
if the user says to save, then it saves the file.
|
|
|
|
The result is @scheme[#t] if the save file is up to date, or if
|
|
the user says it is okay to continue without saving. Generally used
|
|
when closing the file or quiting the app.
|
|
}
|
|
}
|
|
@defmixin[editor:file-mixin (editor:keymap<%>) (editor:file<%>)]{
|
|
This editor locks itself when the file that is opened is read-only in
|
|
the filesystem.
|
|
|
|
The class that this mixin produces uses the same initialization
|
|
arguments as its input.
|
|
@defmethod*[#:mode override (((set-filename (name string) (temp? boolean #f)) void))]{
|
|
|
|
Updates the filename on each frame displaying this editor, for each
|
|
frame that matches
|
|
@scheme[frame:editor<%>].
|
|
}
|
|
@defmethod*[#:mode augment (((can-close?) boolean?))]{
|
|
|
|
If the
|
|
@method[editor:file<%> allow-close-with-no-filename?]
|
|
method returns @scheme[#f], this method checks to see if the file
|
|
has been saved at all yet. If not, it asks the user
|
|
about saving (and saves if they ask).
|
|
|
|
If the
|
|
@method[editor:file<%> allow-close-with-no-filename?]
|
|
method returns @scheme[#t], this method does as before,
|
|
except only asks if the editor's
|
|
@method[editor<%> get-filename]method returns a path.
|
|
|
|
Also calls inner.
|
|
}
|
|
@defmethod*[#:mode override (((get-keymaps) (list-of (instance keymap%))))]{
|
|
|
|
This returns a list containing the super-class's keymaps, plus the
|
|
result of
|
|
@scheme[keymap:get-file]
|
|
}
|
|
}
|
|
@definterface[editor:backup-autosave<%> (editor:basic<%>)]{
|
|
Classes matching this interface support backup files and autosaving.
|
|
@defmethod*[(((backup?) boolean?))]{
|
|
Indicates whether this
|
|
@scheme[editor<%>]
|
|
should be backed up.
|
|
|
|
|
|
Returns the value of the
|
|
@scheme[preferences:get]
|
|
applied to
|
|
@scheme['framework:backup-files?].
|
|
@index{'framework:backup-files?}
|
|
|
|
}
|
|
@defmethod*[(((autosave?) boolean?))]{
|
|
Indicates whether this
|
|
@scheme[editor<%>]
|
|
should be autosaved.
|
|
|
|
|
|
Returns @scheme[#t].
|
|
}
|
|
@defmethod*[(((do-autosave) (union #f string)))]{
|
|
This method is called to perform the autosaving.
|
|
See also
|
|
@scheme[autosave:register]
|
|
|
|
|
|
When the file has been modified since it was last saved and autosaving
|
|
it turned on (via the
|
|
@method[editor:backup-autosave<%> autosave?]
|
|
method) an autosave file is created for this
|
|
@scheme[editor<%>].
|
|
|
|
Returns the filename where the autosave took place, or
|
|
@scheme[#f] if none did.
|
|
}
|
|
@defmethod*[(((remove-autosave) void))]{
|
|
This method removes the autosave file associated with this
|
|
@scheme[editor<%>].
|
|
|
|
|
|
}
|
|
}
|
|
@defmixin[editor:backup-autosave-mixin (editor:basic<%>) (editor:backup-autosave<%> autosave:autosavable<%>)]{
|
|
This mixin adds backup and autosave functionality to an editor.
|
|
|
|
During initialization, this object is registered
|
|
with
|
|
@scheme[autosave:register].
|
|
|
|
The result of this mixin uses the same initialization arguments as the
|
|
mixin's argument.
|
|
|
|
@defmethod*[#:mode augment (((on-save-file (filename path?) (format (one-of/c (quote guess) (quote standard) (quote text) (quote text-force-cr) (quote same) (quote copy)))) bool))]{
|
|
|
|
If a backup file has not been created this session for this file,
|
|
deletes any existing backup file and copies the old save file into the
|
|
backup file. For the backup file's name, see
|
|
@scheme[path-utils:generate-backup-name]
|
|
}
|
|
@defmethod*[#:mode augment (((on-close) void))]{
|
|
|
|
Deletes the autosave file and turns off autosaving.
|
|
}
|
|
@defmethod*[#:mode augment (((on-change) void))]{
|
|
|
|
Sets a flag indicating that this @scheme[editor<%>] needs to be autosaved.
|
|
}
|
|
@defmethod*[#:mode override (((set-modified (modified? any/c)) void))]{
|
|
|
|
If the file is no longer modified, this method deletes the autosave
|
|
file. If it is, it updates a flag to indicate that the autosave file
|
|
is out of date.
|
|
}
|
|
}
|
|
@definterface[editor:info<%> (editor:basic<%>)]{
|
|
An
|
|
@scheme[editor<%>]
|
|
matching this interface provides information about its lock state to its
|
|
@scheme[top-level-window<%>].
|
|
}
|
|
@defmixin[editor:info-mixin (editor:basic<%>) (editor:info<%>)]{
|
|
This editor tells the frame when it is locked and unlocked.
|
|
See also
|
|
@scheme[frame:text-info<%>].
|
|
|
|
@defmethod*[#:mode override (((lock (lock? boolean?)) void))]{
|
|
|
|
Uses
|
|
@method[editor:basic<%> run-after-edit-sequence]
|
|
to call
|
|
@method[frame:info<%> lock-status-changed].
|
|
}
|
|
}
|
|
|
|
@(include-previously-extracted "main-extracts.ss" #rx"^editor:")
|