Creating your own text tool

To create your own text tool, determine whether your tool will act on a standard text selection, on a text presenter state selection, or on some other kind of selection. For tools that operate on standard text selections and require no special behavior, you can often simply use TSimpleTextTool to instantiate your tool. To operate on other selections or to provide unique behavior, you must derive your own tool classes from the standard tool classes.

Using TSimpleTextTool

To create a cursor tool using TSimpleTextTool:

  1. Create the command the tool will issue.
  2. Instantiate TSimpleTextTool with the command.
For example, this code creates a cursor tool that makes selected text italic and bold:

      TStyleSet styles;
      styles.Add( TFontSlantAngleStyle( -0.2217 ) );
      styles.Add( TFontWeightStyle( 0.35 ) );
      TSimpleTextTool tool = new TSimpleTextTool( new TAddStylesCommand( styles ) );

Adding a tool to a menu

You can include new tools in the text editing interface by adding them to the text menus. To create a menu item to activate a text cursor tool, use the control state class TCursorToolSelectionState. This class, provided by the Desktop frameworks, adopts a specified cursor tool and activates it when a user selects the corresponding menu item.

For example, this code creates a menu item based on the tool created above in "Using TSimpleTextTool":

      TStandardText menuItemText( "Emphasize" );
      TMomentaryMenuItem* item = 
          new TMomentaryMenuItem( new TCursorToolSelectionState( tool ) );
      item->AdoptLabel( new TTextLabel( menuItemText ) );
      item->SetSeparator( MMenuItem::kBefore );
You could add this menu item to the default text Tool menu by overriding TTextMenu::CreateToolMenu, or add it to your own custom menu.

Deriving your own tool class

When you want to create a text tool that acts on a selection other than a text selection or a text tool that requires other special behavior, you need to:

  1. Derive a tool class from TSimpleMouseTool.
  2. Derive a corresponding interactor class from TToolInteractor and MMouseEventHandler. The CreateInteractor function of your tool class instantiates this interactor.
    The interactor actually does the work of the tool. Override the necessary MMouseEventHandler functions to create the selection and apply the appropriate command to that selection.
Following is sample code for the classes TSampleTextTool and TSampleTextToolInteractor. TSampleTextTool encapsulates a command and creates an instance of TSampleTextToolInteractor that tracks the mouse and issues the command against the selected text when the mouse is released. You can indicate a selection color or let the interactor use the target's current selection color.

TSampleTextTool declaration

      // Copyright (C) 1994 Taligent, Inc. All rights reserved.
      class TSampleTextTool : public TSimpleMouseTool {
      public:
          MCollectibleDeclarationsMacro (TSampleTextTool);
      
          TSampleTextTool( TCommandOn<MTextSelection>* commandToAdopt, 
                              TColor* highlightColorToAdopt = NIL,
                              MGraphic* cursorGraphicToAdopt = CreateHighlighterGraphic(),
                              MGraphic* paletteGraphicToAdopt = NIL,
                              TText* paletteTextToAdopt = NIL);
          TSampleTextTool(const TSampleTextTool&);
          virtual ~TSampleTextTool();
          TSampleTextTool& operator=(const TSampleTextTool&);
          
          virtual void            GetPaletteText(TText&) const;
          virtual MGraphic*       CreatePaletteGraphic() const;
          virtual MGraphic*       CreateCursorGraphic() const;
          virtual const TColor*   GetHighlightColor() const;
          
      
        virtual TToolInteractor*CreateInteractor(MToolTarget* adoptTarget) const;
      
          virtual TStream&        operator>>=(TStream&) const;
          virtual TStream&        operator<<=(TStream&);
      
          static MGraphic*        CreateHighlighterGraphic();
          
      protected:
                                  TSampleTextTool();
      
      private:
          void                    InternalDelete();
          void                    InternalCopy(const TSampleTextTool&);
      
      
        TCommandOn<MTextSelection>* fCommand;
          TColor*                 fHighlightColor;
          MGraphic*               fCursorGraphic;
          MGraphic*               fPaletteGraphic;
          TText*                  fPaletteText;
      
          enum EVersion { kOriginalVersion };
      };

TSampleTextTool implementation

      // Copyright (C) 1994 Taligent, Inc. All rights reserved.
      MCollectibleDefinitionsMacro(TSampleTextTool, kOriginalVersion);
      
      TTypeDescription gTargetType("TTextToolInteractionTarget");
      
      TSampleTextTool::TSampleTextTool()
        : TSimpleMouseTool(gTargetType),
          fCommand(NIL),
          fHighlightColor(NIL),
          fCursorGraphic(NIL),
          fPaletteGraphic(NIL),
          fPaletteText(NIL)
      {
      }
      
      // Copyright (C) 1994 Taligent, Inc. All rights reserved.
      TSampleTextTool::TSampleTextTool( TCommandOn<MTextSelection>* commandToAdopt,
          TColor* highlightColorToAdopt,
          MGraphic* cursorGraphicToAdopt,
          MGraphic* paletteGraphicToAdopt,
          TText* paletteTextToAdopt)
        : TSimpleMouseTool(gTargetType),
          fCommand(commandToAdopt),
          fHighlightColor(highlightColorToAdopt),
          fCursorGraphic(cursorGraphicToAdopt),
          fPaletteGraphic(paletteGraphicToAdopt),
          fPaletteText(paletteTextToAdopt)
      {
      
        Assertion(commandToAdopt != NIL);
      }
      
      TSampleTextTool::TSampleTextTool(const TSampleTextTool& source)
        : TSimpleMouseTool(source),
          fCommand(NIL),
          fHighlightColor(NIL),
          fCursorGraphic(NIL),
          fPaletteGraphic(NIL),
          fPaletteText(NIL)
      {
      
        InternalCopy(source);
      }
      
      TSampleTextTool::~TSampleTextTool()
      {
          InternalDelete();
      }
      
      TSampleTextTool&
      TSampleTextTool::operator=(const TSampleTextTool& source)
      {
          if (&source != this) {
              TTool::operator=(source);
      
              InternalDelete();
              InternalCopy(source);
          }
      
          return *this;
      }
      
      void
      TSampleTextTool::GetPaletteText(TText& text) const
      {
          if (fPaletteText) {
              text.Replace(*fPaletteText);
          }
      }
      
      MGraphic*
      TSampleTextTool::CreatePaletteGraphic() const
      {
          return ::CopyPointer(fPaletteGraphic);
      }
      
      // Copyright (C) 1994 Taligent, Inc. All rights reserved.
      MGraphic*
      TSampleTextTool::CreateCursorGraphic() const
      {
          return ::CopyPointer(fCursorGraphic);
      }
      
      const TColor*
      TSampleTextTool::GetHighlightColor() const
      {
          return fHighlightColor;
      }
      
      
    TToolInteractor*
      TSampleTextTool::CreateInteractor(MToolTarget* adoptTarget) const 
      {
          Assertion(fCommand != NIL);
      
          TSampleTextToolInteractor* interactor = NIL;
          
          TTextToolInteractionTarget *target = NIL; 
          ::DynamicCastTo(target, adoptTarget);
          
          if (target) {
              interactor = new TSampleTextToolInteractor(
                  ((TSampleTextTool*)this)->GetToolHandler(), target,
                      ::CopyPointer(fCommand), ::CopyPointer( GetHighlightColor() ) );
              interactor->SetCoordinateView( ( (TSampleTextTool*)this )->GetToolView() );
          } else {
              delete adoptTarget;
          }
      
          return interactor;
      }
      
      TStream&            
      TSampleTextTool::operator>>=(TStream& toStream) const
      {
          ::WriteVersion(toStream, kOriginalVersion);
      
          TTool::operator>>=(toStream);
      
          ::Flatten(fCommand, toStream);
          ::Flatten(fHighlightColor, toStream);
          ::Flatten(fCursorGraphic, toStream);
          ::Flatten(fPaletteGraphic, toStream);
          ::Flatten(fPaletteText, toStream);
      
          return toStream;
      }
      
      TStream&            
      TSampleTextTool::operator<<=(TStream& fromStream)
      {
          ::ReadVersion(fromStream, kOriginalVersion, kOriginalVersion);
          
          TTool::operator<<=(fromStream);
      
          InternalDelete();
      
          ::Resurrect(fCommand , fromStream);
          ::Resurrect(fHighlightColor, fromStream);
          ::Resurrect(fCursorGraphic, fromStream);
          ::Resurrect(fPaletteGraphic, fromStream);
          ::Resurrect(fPaletteText, fromStream);
      
          return fromStream;
      }
      
      MGraphic*
      TSampleTextTool::CreateHighlighterGraphic()
      {
          const TGPoint points[] = {
              TGPoint( 0,-4),
              TGPoint( 0, 4),
              TGPoint( 4, 8),
              TGPoint( 3,10),
              TGPoint( 3,12),
              TGPoint( 4,14),
              TGPoint( 7,17),
              TGPoint(17, 7),
              TGPoint(14, 4),
              TGPoint(12, 3),
              TGPoint(10, 3),
              TGPoint( 8, 4)
          };
          const int numPoints = sizeof(points)/sizeof(TGPoint);
      
          TGPolygon polygon(numPoints);
          for (int i = 0; i < numPoints; i++) {
              polygon.SetPoint(i, points[i]);
          }
          
          TRGBColor fillColor(0.75, 0.75, 0.75);
          TRGBColor frameColor(0, 0, 0);
          TGrafBundle* bundle = new TGrafBundle(fillColor, frameColor);
          bundle->AdoptFramePen(new TSolidPen(2.0, TPen::kOutsetFrame));
      
          return new TPolygon(polygon, bundle);
      }
      
      void
      TSampleTextTool::InternalCopy(const TSampleTextTool& source)
      {
          fCommand = ::CopyPointer(source.fCommand);
      
          fHighlightColor= ::CopyPointer(source.fHighlightColor);
          fCursorGraphic = ::CopyPointer(source.fCursorGraphic);
          fPaletteGraphic= ::CopyPointer(source.fPaletteGraphic);
          fPaletteText = ::CopyPointer(source.fPaletteText);
      }
                  
      void
      TSampleTextTool::InternalDelete()
      {
          delete fCommand; fCommand = NIL;
          delete fHighlightColor; fHighlightColor = NIL;
          delete fCursorGraphic; fCursorGraphic = NIL;
          delete fPaletteGraphic; fPaletteGraphic = NIL;
          delete fPaletteText; fPaletteText = NIL;
      }

TSampleTextToolInteractor declaration

      // Copyright (C) 1994 Taligent, Inc. All rights reserved.
      class TSampleTextToolInteractor : public TToolInteractor, public MMouseEventHandler {
      public:
          VersionDeclarationsMacro(TSampleTextToolInteractor);
      
          TSampleTextToolInteractor(MToolHandler* handlerAlias,
              TTextToolInteractionTarget* targetToAdopt,
              TCommandOn<MTextSelection>* commandToAdopt,
              TColor* selectionColorToAdopt = NIL,
      
            Boolean leaveSelectionAsInsertionPoint = TRUE);
      
          TSampleTextToolInteractor(const TSampleTextToolInteractor&);
          virtual ~TSampleTextToolInteractor();
      
          virtual Boolean MouseDown(TMouseDownEvent&);
          virtual Boolean MouseMoved(TMouseMovedEvent&);
          virtual Boolean MouseUp(TMouseUpEvent&);
      
      private:
          TTextToolInteractionTarget* fTarget;
          TCommandOn<MTextSelection>* fCommand;
          TColor*                     fSelectionColor;
      
          MTextSelection*             fSelection;
          TTextOffset                 fAnchor;
          TRGBColor                   fOldSelectionColor;
          Boolean                     fLeaveSelectionAsInsertionPoint;
      };

TSampleTextToolInteractor implementation

      // Copyright (C) 1994 Taligent, Inc. All rights reserved.
      VersionDefinitionsMacro(TSampleTextToolInteractor, 0);
      
      TSampleTextToolInteractor::TSampleTextToolInteractor( MToolHandler* handlerAlias,
          TTextToolInteractionTarget* targetToAdopt,
          TCommandOn<MTextSelection>* commandToAdopt,
          TColor* colorToAdopt,
          Boolean leaveSelectionAsInsertionPoint)
        : TToolInteractor(handlerAlias),
          MMouseEventHandler(),
          fSelection(NIL),
          fTarget(targetToAdopt),
          fCommand(commandToAdopt),
          fSelectionColor(colorToAdopt),
          fLeaveSelectionAsInsertionPoint(leaveSelectionAsInsertionPoint)
      {
      
        Assertion(handlerAlias != NIL);
          Assertion(targetToAdopt != NIL);
          Assertion(commandToAdopt != NIL);
      }
    TSampleTextToolInteractor::TSampleTextToolInteractor(const TSampleTextToolInteractor& source) : TToolInteractor(source), MMouseEventHandler(source), fSelection(NIL), fTarget(NIL), fCommand(NIL), fSelectionColor(NIL), fLeaveSelectionAsInsertionPoint(source.fLeaveSelectionAsInsertionPoint) { fTarget= ::CopyPointer(source.fTarget); fCommand = ::CopyPointer(source.fCommand); fSelectionColor= ::CopyPointer(source.fSelectionColor); } TSampleTextToolInteractor::~TSampleTextToolInteractor() { delete fSelection; delete fTarget; delete fCommand; delete fSelectionColor; } Boolean TSampleTextToolInteractor::MouseDown(TMouseDownEvent& mouseDown) { StartMouseMovedEvents(*mouseDown.GetMouseInputDevice()); TGPoint position = mouseDown.GetEventPosition(); fSelection = fTarget->CreateTextSelection(position, fAnchor); fTarget->AdoptTextSelection(::CopyPointer(fSelection)); if (fSelectionColor) { fTarget->GetTextSelectionColor(fOldSelectionColor); fTarget->SetTextSelectionColor(*fSelectionColor); } return TRUE; } Boolean TSampleTextToolInteractor::MouseMoved(TMouseMovedEvent& mouseMove) { TGPoint position = mouseMove.GetEventPosition(); fTarget->ExtendTextSelection(position, fAnchor, *fSelection); fTarget->AdoptTextSelection(::CopyPointer(fSelection)); return TRUE; } Boolean TSampleTextToolInteractor::MouseUp(TMouseUpEvent& mouseUp) { StopMouseMovedEvents(); if (fLeaveSelectionAsInsertionPoint) { MTextSelection* selection = ::CopyPointer(fSelection); TTextRange range; selection->GetFirstRange(range); TTextOffset finalOffset = range.GetEnd(); if (finalOffset == fAnchor) { finalOffset = range.GetBegin(); } selection->SetInsertionOffset(TInsertionOffset(finalOffset)); fTarget->AdoptTextSelection(selection); } TTextRepresentationWriteEntry entry(fSelection); TToolCommandBindingTo<MTextSelection>* binding = new TToolCommandBindingTo<MTextSelection>(fCommand, fSelection); AdoptAndDo(binding); fCommand = NIL; fSelection = NIL; if (fSelectionColor) { fTarget->SetTextSelectionColor(fOldSelectionColor); } SetDone(TRUE); return TRUE; }

[Contents] [Previous] [Next]
Click the icon to mail questions or corrections about this material to Taligent personnel.
Copyright©1995 Taligent,Inc. All rights reserved.

Generated with WebMaker