previous chapter contents page top page next chapter

AcceptsTyping

April 1, 1994
last modified February 14, 1995

Defined in AcceptsTyping.Def
Mixes in with Viewable

Class Description

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.

Using an AcceptsTyping Object

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.

Programming Information

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);

Methods defined by class AcceptsTyping

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

Methods you might override

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

Fields defined by class AcceptsTyping

Class AcceptsTyping defines just one field, a global one:

Field Type Description
global currentTypingTarget AcceptsTyping The current typing target that should receive keyboard input

Related Classes

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.

Method Descriptions

Managing the typing target

CurrentTypingTarget

intrinsic CurrentTypingTarget(): AcceptsTyping, safe

Call: sometimes
Override: never

Call CurrentTypingTarget to get the system's current typing target.

SetCurrentTypingTarget

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.

AcceptTyping

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.

DoneTyping

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.

Editable

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.

Activating the target

Activate

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.

Deactivate

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.

Typing

DispatchKeys

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.

DispatchRetype

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.

TypeKeys

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.

Retype

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.

DefaultKeyboard

operation DefaultKeyboard()

Call: sometimes
Override: rarely

Call DefaultKeyboard to get the system's default keyboard, which is kept in the indexical iDefaultKeyboard.