See: Description
Interface | Description |
---|---|
CamelCaseInterceptor |
An interceptor which is called when user use camel case action.
|
CamelCaseInterceptor.Factory |
The factory interface for registering
CamelCaseInterceptor s
in MimeLookup . |
DeletedTextInterceptor |
An interceptor which is called when user deletes text from a document.
|
DeletedTextInterceptor.Factory |
The factory interface for registering
DeletedTextInterceptor s
in MimeLookup . |
TypedBreakInterceptor |
An interceptor which is called when a line break is typed into a document.
|
TypedBreakInterceptor.Factory |
The factory interface for registering
TypedBreakInterceptor s
in MimeLookup . |
TypedTextInterceptor |
An interceptor which is called when text is typed into a document.
|
TypedTextInterceptor.Factory |
The factory interface for registering
TypedTextInterceptor s
in MimeLookup . |
Class | Description |
---|---|
CamelCaseInterceptor.MutableContext |
The context class providing information about the edited document, its
editor pane and the offset where the key event occurred.
|
DeletedTextInterceptor.Context |
The context class providing information about the edited document, its
editor pane and the offset where the delete key event occurred.
|
TypedBreakInterceptor.Context |
The context class providing information about the edited document, its
editor pane, caret offset, line break insertion offset and text.
|
TypedBreakInterceptor.MutableContext |
This context class allows to modify the insertion text and the caret position
after the text is inserted into a document.
|
TypedTextInterceptor.Context |
The context class providing information about the edited document, its
editor pane, insertion offset and text.
|
TypedTextInterceptor.MutableContext |
This context class allows to modify the insertion text and the caret position
after the text is inserted into a document.
|
The Typing Hooks SPI allows modules to intercept various key typed events
handled by the editor infrastructure. Historically, this was possible by subclassing
editor actions such as DefaultKeyTypedAction
or InsertBrakeAction
and overwriting their performAction
method. This however is not very
flexible approach. It's main drawback is that modules can't easily intercept
key typed events handled in editors (eg. EditorKit
s) that are provided
by other modules. The Typing Hooks SPI addresses these drawbacks while providing
semantically compatible functionality with what used to be possible by subclassing editor actions.
The editor actions superceded by Typing Hooks SPI are still available and the code that uses them should still work. But they will be deprecated and eventually removed.
Netbeans editor panes are ordinary JTextComponent
s and therefore
they fully follow keyboard events processing scheme defined by Swing (please read
more about Text Input in JTextComponent
's javadoc). For the
purpose of understanding Typing Hooks SPI it is important to note that
the SPI interceptors are at the very end of the KeyEvent
processing
pipeline, which means that some KeyEvent
s may never reach
them. However, in a typical environment these events will not present
printable characters that could be inserted in an edited document. Typically they are
shortcuts bound to special actions in the editor's Keymap
(newly
a pair of InputMap
, ActionMap
).
In general the SPI provides several different types of interceptors (interfaces) that clients can implement and register for a document type (mimetype) of their interest. Each interceptor type is meant to process different types of keyboard input. The interceptor types currently available are listed below.
TypedTextInterceptor
- processes KeyTyped
events
that would normally be processed by DefaultKeyTypedAction
registered
for a given editor type. Any other KeyEvent
that has an Action
associated
in the editor pane's keymap will trigger that Action
and will not reach
registered interceptors of this type.
TypedBreakInterceptor
- processes KeyTyped
events
that would normally result in inserting a line break in the edited document.
DeletedTextInterceptor
- processes KeyTyped
events
that would normally remove text from the edited document.
Interceptors are created by calling a factory implementation registered in
MimeLookup
. For example an implementation of TypedTextInterceptor
can be plugged in by registering TypedTextInterceptor.Factory
instance
for the appropriate mimetype in MimeLookup
. The snippet below shows
how this registration could look.
<folder name="Editors"> <folder name="text"> <folder name="x-something"> <file name="org-some-module-TTIFactory.instance" /> </folder> </folder> </folder>
The TTIFactory
class will simply return a new instance of
the module's implementation of TypedTextInterceptor
interface from its
createTypedTextInterceptor
method.
In general interceptors are created as they are needed. However, unlike in other editor SPIs where SPI implementation objects are short lived and get all their information in the form of a context object from the factory that created them, the interceptors are long lived objects that are created with a minimal context and reused many times. The reason for this is mostly performance considerations. Typically there are many keyboard events as users type and their processing has to be as fast as possible.
The interceptors are created for a document type or more precisely for a MimePath
of the document fragment, where a user is typing. This allows to call different interceptors
depending on where in the document a particular keyboard event happens. Therefore embedded
sections can use different interceptors than the main document.
The MimePath
is the only context that the interceptor factory gets from
the infrastructure and it is the only context that it is supposed to pass to interceptor
instances that it creates. All the other information needed for a particular interceptor type
to do its job will be provided at the time when an event happens and the interceptor is called
to process it. This makes it possible to reuse one interceptor implementation many times
for processing different events in different documents.
As explained earlier Netbeans editors follow swing concepts for handling keyboard events. All keyboard events processing and editor actions invocation in swing editors is done in the AWT thread, which means that events are processed in one thread only and in the order as they happened. The same applies for interceptors and Typing Hooks SPI in general.
In particular it is guaranteed that only one interceptor is used at a time and it's always called from AWT thread. Therefore a typical interceptor does not have to use any explicit synchronization code (unless it accesses a resource that can be simultaneously accessed from other threads of course).
However, interceptor types may define a specific protocol, which determines how interceptors of that type are chained, what methods are called first, if and what document locks are acquired prior calling the interceptor, conditions when the event processing can be interrupted, what happens with the rest of the queued interceptors, etc. Please see documentation of each interceptor type interface for detailed information.
Many languages need to automatically reindent lines as user types certain statements. For example in java language the 'case' statements in a 'switch' block should be aligned to the same column similarly as in the code snippet below. The java editor helps users to do that by automatically indenting the lines that contain 'case' statements as soon as a user types the double colon at the end of the statement.
switch(price) { case 100: // do something cheap break; case 1000: // do something more expensive break; }
This can easily be done by implementing
TypedTextInterceptor
and its afterInsert
method. The implementation can check the text
inserted in the document as a result of the key typed event processing and reindent
the line if its text matches required pattern.
Moreover, the Editor Indentation API
provides an implementation of TypedTextInterceptor
, which reindents lines that
match provided regular expressions. Please see AutomatedIndenting
class for more details.
It can safe a lot of typing if the editor correctly completes pair characters
such as ()
, {}
, ""
, ''
, etc.
For example when one of the pair character is typed or deleted the editor
automatically adds or removes its couterpart. Additionally, the editor may wrap selected text in
the pair characters such as quotes ""
if one of them is typed (eg. in java producing a string literal).
These features can be implemented by providing specialized
TypedTextInterceptor
and
DeletedTextInterceptor
implementations.