Defined in AcceptsTyping.Def Mixes in with Viewable
Mixin AcceptsTyping provides the basic functionality for all objects that can receive typing from keyboards. One major group of text classes inherits from mixin AcceptsTyping: class TextField and all its heirs.
Remember that if the documentation and the software (especially the definition files) disagree, always trust the software.
Since class AcceptsTyping is a mixin, you'll never use an AcceptsTyping object. Instead, you'll use objects of classes that mix in AcceptsTyping, like text fields.
Often, to use an object that accepts typing, you just tap in it. The object activates itself for typing, brings up the keyboard, and waits for your input. Type on the keyboard to send typing to the object.
Instantiate: never Subclass: always Call its methods: rarely
You'll call some of the methods of class AcceptTyping often: CurrentTypingTarget, SetCurrentTypingTarget, and DoneTyping are the ones you're likely to call. You'll set up your subclass by inheriting from mixin AcceptsTyping, overriding the important methods, then putting objects of your subclass into place in an object definition file.
The system has only one typing target at any time. If typing is a standard feature of your subclass, your user interface should make it obvious that an object of your subclass is awaiting typed characters. For examples, you can look at some built-in Magic Cap classes that inherit from AcceptsTyping, such as class TextField. Objects of class TextField display an insertion point or a highlighted selection when they're ready to accept typing.
Magic Cap defines an image for a text insertion caret that you can use. It's the indexical iInsertionSpot. It looks like this:
If you've figured out where to draw the insertion point, you can draw it with a call like this:
DrawImage(iInsertionSpot, canvas, clip, &caretDot);
The AcceptsTyping mixin defines the following methods:
Method | Description |
---|---|
AcceptTyping | Ask an object to become the current typing target |
Activate | Do extra setup before the user can type into your object |
CurrentTypingTarget | Return the current typing target by checking the global variable |
Deactivate | Do extra cleanup after the user is finished typing into your object |
DefaultKeyboard | Control which keyboard is used on this object |
DispatchKeys | Send typed keys to TypeKeys |
DispatchRetype | Send retyped keys to retype |
DoneTyping | Ask an object to stop being the current typing target |
Editable | Test if this object can be edited right now |
Retype | Send a deleteKey before sending the newly typed key |
SetCurrentTypingTarget | Set the current typing target |
TypeKeys | Handle typed keys |
When you mix in with class AcceptsTyping, you should override the following methods:
Method | How to override |
---|---|
TypeKeys | To define how your subclass processes typed keys |
In addition, you might override these other methods under the following circumstances:
Method | When to override |
---|---|
Activate | To do additional setup before the user types into your object |
Deactivate | To do additional cleanup after typing |
Class AcceptsTyping defines just one field, a global one:
Field | Type | Description |
---|---|---|
global currentTypingTarget | AcceptsTyping | The current typing target that should receive keyboard input |
You're more likely to use one of the many classes that inherit from AcceptsTyping than to create a subclass yourself. Those classes include class TextField and the classes that inherit from it, and class ListView and all its heirs. Look at class Calculator, in the sample calculator package included with Magic Developer, for an example of a class that mixes in directly with AcceptsTyping.
intrinsic CurrentTypingTarget(): AcceptsTyping, safe Call: sometimes Override: never
Call CurrentTypingTarget to get the system's current typing target.
intrinsic SetCurrentTypingTarget(newTarget: AcceptsTyping), safe Call: sometimes Override: never
Call SetCurrentTypingTarget to set the system's current typing target.
SetCurrentTypingTarget calls Deactivate on the old target. If the old target refuses to deactivate, SetCurrentTypingTarget won't change the target. If the deactivation was successful, SetCurrentTypingTarget calls Activate on the proposed new target. If the new target refuses to activate, SetCurrentTypingTarget sets the system's typing target to nilObject.
operation AcceptTyping(), noFail, safe Call: sometimes Override: never
Call AcceptTyping to set the current typing target to the current object. AcceptTyping just calls the intrinsic method SetCurrentTypingTarget.
The system's classes sometimes call SetCurrentTypingTarget instead of AcceptTyping. If you override this method, your override will not always be called when the systems makes your object the current typing target.
operation DoneTyping(), noFail, safe Call: rarely Override: rarely
Call DoneTyping to reset the current typing target to nilObject, thus ending any typing in the previous typing target. DoneTyping uses SetCurrentTypingTarget to do its work. It does nothing if the previous typing target wasn't the object DoneTyping was called on.
Call DoneTyping instead of SetCurrentTypingTarget(nilObject), to get the benefit of DoneTyping's extra typing target check.
attribute Editable: Boolean, readOnly, safe // operation Editable(): Boolean Call: sometimes Override: sometimes
Call Editable to check if an object that accepts typing can be changed.
AcceptsTyping_Editable always returns true. Override if objects of your subclass are sometimes not editable. For example, class TextField overrides Editable to check a text field flag and to see if its enclosing card is locked.
operation Activate(), noFail, scriptable Call: rarely Override: sometimes
The system calls Activate from SetCurrentTypingTarget to give the potential new target a chance to do any extra setup before the user begins to type in it.
AcceptsTyping_Activate does nothing. Override if your subclass needs to do any extra setup. For example, you could override Activate to refuse to accept typing in certain circumstances. If you do, make sure your method fails with the exception cannotActivate. Class TextField overrides Activate to do just that if Editable returns false. Class TextField also uses Activate to activate a keyboard and display any selection if necessary.
If your new class inherits from a subclass of class AcceptsTyping, you'll usually want to call the inherited method from your override.
operation Deactivate(), noFail, scriptable Call: rarely Override: sometimes
The system calls Deactivate from SetCurrentTypingTarget to give the old typing target a chance to refuse deactivation or to clean up before deactivation.
AcceptsTyping_Deactivate does nothing. Override if your subclass needs to clean up or refuse deactivation at times. For example, you could override Deactivate to refuse to yield to another typing target with the exception cannotDeactivate. Class TextField overrides Deactivate to put away the current keyboard if necessary and to hide any selections.
If your new class inherits from a subclass of class AcceptsTyping, you'll probably need to call the inherited method from your override.
intrinsic DispatchKeys(keys: CharacterPoint; count: Unsigned), safe Call: rarely Override: never
The system calls DispatchKeys to send keystrokes to the current typing target. If typing fails, DispatchKeys honks, and if the user persists in typing, announces that no typing target exists.
intrinsic DispatchRetype(newCharacter: Character), safe Call: sometimes Override: rarely
The system calls DispatchRetype to send retyped keystrokes to the current typing target. DispatchRetype calls Retype on the current typing target with the given character to be retyped.
overrides TypeKeys(keys: CharactersPointer; count: Unsigned): Unsigned Call: sometimes Override: always
The system calls TypeKeys from DispatchKeys to send typed keys to an object that accepts typing. AcceptsTyping_TypeKeys does nothing and just returns 0. You should override TypeKeys if you are mixing in AcceptsTyping with your new class.TypeKeys should process the characters in the keys parameter in some waythis method defines the accepts typing part of the AcceptsTyping mixin!
The keys parameter is the keys typed. The count parameter is the number of characters in the keys parameter. Your override of TypeKeys should return the number of keys accepted.
Here's how class ConfirmationDialog overrides TypeKeys:
#pragma unused (count) Character theChar = *characters; if (theChar == enterKey || theChar == returnKey) { Confirm(self); return 1; } else if (theChar == expandKey || theChar == deleteKey) { Hide(self); return 1; } return 0;
This override allows users to tap the Enter or Return key in lieu of tapping the accept key to confirm their changes. It only considers the first key the user types.
Class Calculator overrides TypeKeys this way:
switch (*keys) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': PushDigitButton(self, *keys - '0'); break; case '=': case returnKey: case enterKey: PushEqualsButton(self); break; case '.': PushDecimalButton(self); break; case '+': PushBinaryFnButton(self, kPlus); break; case '-': PushBinaryFnButton(self, kMinus); break; case '*': PushBinaryFnButton(self, kTimes); break; case divisionSignCharacter: case '/': PushBinaryFnButton(self, kDiv); break; case '%': PushPercentButton(self); break; case deleteKey: PushClearEntryButton(self); break; case 'C': PushClearButton(self); break; default: return InheritedTypeKeys(self, keys, count); } return 1;
Instead of handling the typing directly, as ConfirmationDialog_TypeKeys did, class Calculator defines some methods each of which handles one kind of key press.
You can find a list of named characters like "divisionSignCharacter" in the file CharacterCodes.h.
operation Retype(newCharacter: Character) Call: rarely Override: never
The DispatchRetype method calls Retype when the user is retyping some selected text. Retype sends a deleteKey and the new character to TypeKeys.
operation DefaultKeyboard() Call: sometimes Override: rarely
Call DefaultKeyboard to get the system's default keyboard, which is kept in the indexical iDefaultKeyboard.