Creating a responsive text box

In this recipe we will learn how to create a text box that responds to the user's keystrokes. It will be active when pressed over by the mouse and inactive when the mouse is released outside the box.

Getting ready

Grab the following files from the recipe Creating an interactive object that responds to the mouse and add them to your project:

  • InteractiveObject.h
  • InteractiveObject.cpp

Create and add the following files to your project:

  • InteractiveTextBox.h
  • InteractiveTextBox.cpp

How to do it…

We will create an InteractiveTextBox class that inherits from InteractiveObject and adds text functionality.

  1. Go to the file InteractiveTextBox.h and add the #pragma once macro and include the necessary files.
    #pragma once
    
    #include "InteractiveObject.h"
    #include "cinder/Text.h"
    #include "cinder/gl/Texture.h"
    #include "cinder/app/KeyEvent.h"
    #include "cinder/app/AppBasic.h"
  2. Now declare the InteractiveTextBox class, making it a subclass of InteractiveObject with the following members and methods:
    class InteractiveTextBox: public InteractiveObject{
    public:
        InteractiveTextBox( const ci::Rectf& rect );
    
        virtual void draw();
        virtual void pressed();
        virtual void releasedOutside();
    
        void keyDown( ci::app::KeyEvent& event );
        protected:
            ci::TextBox mTextBox;
        std::string mText;
        bool mActive;
        bool mFirstText;
    };
  3. Now go to InteractiveTextBox.cpp and include the InteractiveTextBox.h file and add the following using statements:
    #include "InteractiveTextBox.h"
    
    using namespace std;
    using namespace ci;
    using namespace ci::app;
  4. Now let's implement the constructor by initializing the parent class and setting up the internal ci::TextBox.
    InteractiveTextBox::InteractiveTextBox( const Rectf& rect ):
    InteractiveObject( rect )
    {
      mActive = false;
      mText = "Write some text";
      mTextBox.setText( mText );
      mTextBox.setFont( Font( "Arial", 24 ) );
      mTextBox.setPremultiplied( true );
      mTextBox.setSize( Vec2i( rect.getWidth(), rect.getHeight() ) );
      mTextBox.setBackgroundColor( Color::white() );
      mTextBox.setColor( Color::black() );
      mFirstText = true;
    }
  5. In the InteractiveTextBox::draw method we will set the background color of mTextBox depending if it is active or not. We will also render mTextBox into ci::gl::Texture and draw it.
    void InteractiveTextBox::draw(){
     if( mActive ){
      mTextBox.setBackgroundColor( Color( 0.7f, 0.7f, 1.0f ) );
     } else {
      mTextBox.setBackgroundColor( Color::white() );
     }
     gl::color( Color::white() );
     gl::Texture texture = mTextBox.render();
     gl::draw( texture, rect );
    }
  6. Now let's implement the overridden methods pressed and releasedOutside to define the value of mActive.
    void InteractiveTextBox::pressed(){
      mActive = true;
    }
    
    void InteractiveTextBox::releasedOutside(){
      mActive = false;
    }
  7. Finally, we need to implement the keyPressed method.

    If mActive is false this method will simply return. Otherwise, we will remove the last letter of mText if the key released was the Backspace key, or, add the corresponding letter if any other key was pressed.

    void InteractiveTextBox::keyDown( KeyEvent& event ){
     if( mActive == false ) return;
     if( mFirstText ){
      mText = "";
      mFirstText = false;
     }
     if( event.getCode() == KeyEvent::KEY_BACKSPACE ){
      if( mText.size() > 0 ){
       mText = mText.substr( 0, mText.size()-1 );
      }
     } else {
      const char character = event.getChar();
      mText += string( &character, 1 );
     }
     mTextBox.setText( mText );
    }
  8. Now move to your application class source file and include the following file and the using statements:
    #include "InteractiveTextBox.h"
    
    using namespace ci;
    using namespace ci::app;
    using namespace std;
  9. In your application class declare the following member:
    shared_ptr<InteractiveTextBox> mTextBox;
  10. Let's initialize mTextBox in the setup method:
    Rectf rect( 100.0f, 100.0f, 300.0f, 200.0f );
    mTextBox = shared_ptr<InteractiveTextBox>( new InteractiveTextBox( rect ) );
  11. In the draw method we will clear the background with black, enable AlphaBlending, and draw our mTextBox:
      gl::enableAlphaBlending();
      gl::clear( Color( 0, 0, 0 ) );
      mTextBox->draw();
  12. We now need to declare the following mouse event handlers:
    void mouseDown( MouseEvent event );
    void mouseUp( MouseEvent event );
    void mouseDrag( MouseEvent event );
    void mouseMove( MouseEvent event );
  13. And implement them by calling the respective mouse event handler of mTextBox:
    void MyApp::mouseDown( MouseEvent event ){
      mTextBox->mouseDown( event );
    }
    
    void MyApp::mouseUp( MouseEvent event ){
      mTextBox->mouseUp( event );
    }
    
    void MyApp::mouseDrag( MouseEvent event ){
      mTextBox->mouseDrag( event );
    }
    
    void MyApp::mouseMove( MouseEvent event ){
      mTextBox->mouseMove( event );
    }
  14. Now we just need to do the same with the key released event handler. Start by declaring it:
    void keyDown( KeyEvent event );
  15. And in it's implementation we will call the keyUp method of mTextBox.
    void InteractiveObjectApp::keyDown( KeyEvent event ){
      mTextBox->keyDown( event );
    }
  16. Now build and run the application. You will see a white textbox with the phrase Write some text. Press the text box and write some text. Click outside the text box to set the textbox as inactive.

How it works…

Internally, our InteractiveTextBox uses a ci::TextBox object. This class manages the text inside a box with a specified width and height. We take advantage of that and update the text according to the keys that the user presses.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.115.154