Added interface for queuing input events in TextController 68/35968/11
authorPaul Wisbey <p.wisbey@samsung.com>
Thu, 26 Feb 2015 19:00:32 +0000 (19:00 +0000)
committerPaul Wisbey <p.wisbey@samsung.com>
Fri, 27 Feb 2015 14:08:38 +0000 (14:08 +0000)
Change-Id: I66c96382884a6fa607eea5a6eb87a8f929366362

14 files changed:
dali-toolkit/dali-toolkit.h
dali-toolkit/internal/controls/text-controls/text-field-impl.cpp
dali-toolkit/internal/controls/text-controls/text-field-impl.h
dali-toolkit/internal/controls/text-controls/text-label-impl.cpp
dali-toolkit/internal/controls/text-controls/text-label-impl.h
dali-toolkit/public-api/controls/text-controls/text-field.cpp
dali-toolkit/public-api/controls/text-controls/text-field.h
dali-toolkit/public-api/file.list
dali-toolkit/public-api/text/decorator/text-decorator.cpp
dali-toolkit/public-api/text/decorator/text-decorator.h
dali-toolkit/public-api/text/text-control-interface.cpp [new file with mode: 0644]
dali-toolkit/public-api/text/text-control-interface.h [new file with mode: 0644]
dali-toolkit/public-api/text/text-controller.cpp
dali-toolkit/public-api/text/text-controller.h

index a0e075c..ddadae0 100644 (file)
@@ -74,6 +74,7 @@
 #include <dali-toolkit/public-api/controls/slider/slider.h>
 #include <dali-toolkit/public-api/controls/super-blur-view/super-blur-view.h>
 #include <dali-toolkit/public-api/controls/table-view/table-view.h>
+#include <dali-toolkit/public-api/controls/text-controls/text-field.h>
 #include <dali-toolkit/public-api/controls/text-controls/text-label.h>
 #include <dali-toolkit/public-api/controls/tool-bar/tool-bar.h>
 #include <dali-toolkit/public-api/controls/view/view.h>
index 79a6545..3e23e2e 100644 (file)
@@ -48,6 +48,7 @@ const Property::Index TextField::PROPERTY_SECONDARY_CURSOR_COLOR( Internal::Text
 const Property::Index TextField::PROPERTY_ENABLE_CURSOR_BLINK(    Internal::TextField::TEXTFIELD_PROPERTY_START_INDEX + 5 );
 const Property::Index TextField::PROPERTY_CURSOR_BLINK_INTERVAL(  Internal::TextField::TEXTFIELD_PROPERTY_START_INDEX + 6 );
 const Property::Index TextField::PROPERTY_CURSOR_BLINK_DURATION(  Internal::TextField::TEXTFIELD_PROPERTY_START_INDEX + 7 );
+const Property::Index TextField::PROPERTY_GRAB_HANDLE_IMAGE(      Internal::TextField::TEXTFIELD_PROPERTY_START_INDEX + 8 );
 
 namespace Internal
 {
@@ -71,6 +72,7 @@ PropertyRegistration property5( mType, "secondary-cursor-color", Toolkit::TextFi
 PropertyRegistration property6( mType, "enable-cursor-blink",    Toolkit::TextField::PROPERTY_ENABLE_CURSOR_BLINK,    Property::BOOLEAN, &TextField::SetProperty, &TextField::GetProperty );
 PropertyRegistration property7( mType, "cursor-blink-interval",  Toolkit::TextField::PROPERTY_CURSOR_BLINK_INTERVAL,  Property::FLOAT,   &TextField::SetProperty, &TextField::GetProperty );
 PropertyRegistration property8( mType, "cursor-blink-duration",  Toolkit::TextField::PROPERTY_CURSOR_BLINK_DURATION,  Property::FLOAT,   &TextField::SetProperty, &TextField::GetProperty );
+PropertyRegistration property9( mType, "grab-handle-image",      Toolkit::TextField::PROPERTY_GRAB_HANDLE_IMAGE,      Property::STRING,  &TextField::SetProperty, &TextField::GetProperty );
 
 } // namespace
 
@@ -170,6 +172,16 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
         }
         break;
       }
+      case Toolkit::TextField::PROPERTY_GRAB_HANDLE_IMAGE:
+      {
+        ResourceImage image = ResourceImage::New( value.Get< std::string >() );
+
+        if( impl.mDecorator )
+        {
+          impl.mDecorator->SetGrabHandleImage( image );
+        }
+        break;
+      }
     }
   }
 }
@@ -245,6 +257,18 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde
         }
         break;
       }
+      case Toolkit::TextField::PROPERTY_GRAB_HANDLE_IMAGE:
+      {
+        if( impl.mDecorator )
+        {
+          ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetCursorImage() );
+          if( image )
+          {
+            value = image.GetUrl();
+          }
+        }
+        break;
+      }
     }
   }
 
@@ -253,11 +277,16 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde
 
 void TextField::OnInitialize()
 {
-  mDecorator = Text::Decorator::New( *this );
+  mController = Text::Controller::New( *this );
+
+  mDecorator = Text::Decorator::New( *this, *mController );
 
-  mController = Text::Controller::New();
   mController->GetLayoutEngine().SetLayout( LayoutEngine::SINGLE_LINE_BOX );
-  //mController->EnableTextInput( mDecorator ); TODO
+
+  mController->EnableTextInput( mDecorator );
+
+  // Forward input events to controller
+  EnableGestureDetection( Gesture::Tap );
 }
 
 void TextField::OnRelayout( const Vector2& size, ActorSizeContainer& container )
@@ -282,6 +311,16 @@ void TextField::OnRelayout( const Vector2& size, ActorSizeContainer& container )
   }
 }
 
+void TextField::OnTap( const TapGesture& tap )
+{
+  mController->TapEvent( tap.localPoint.x, tap.localPoint.y );
+}
+
+void TextField::RequestTextRelayout()
+{
+  RelayoutRequest();
+}
+
 TextField::TextField()
 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_NONE ) )
 {
index 3dbec59..4e18eb2 100644 (file)
@@ -22,6 +22,7 @@
 #include <dali-toolkit/public-api/controls/control-impl.h>
 #include <dali-toolkit/public-api/controls/text-controls/text-field.h>
 #include <dali-toolkit/public-api/text/decorator/text-decorator.h>
+#include <dali-toolkit/public-api/text/text-control-interface.h>
 #include <dali-toolkit/public-api/text/text-controller.h>
 
 namespace Dali
@@ -36,7 +37,7 @@ namespace Internal
 /**
  * @brief A control which renders a short text string.
  */
-class TextField : public Control
+class TextField : public Control, public Text::ControlInterface
 {
 public:
 
@@ -87,13 +88,17 @@ private: // From Control
    */
   virtual void OnRelayout( const Vector2& size, ActorSizeContainer& container );
 
-private: // Implementation
+  /**
+   * @copydoc Control::OnTap()
+   */
+  virtual void OnTap( const TapGesture& tap );
 
   /**
-   * Helper for SetProperty.
-   * @param[in] text The new "text" property value.
+   * @copydoc Text::ControlInterface::RequestTextRelayout()
    */
-  void SetText( const std::string& text );
+  virtual void RequestTextRelayout();
+
+private: // Implementation
 
   /**
    * Construct a new TextField.
index 93c5500..073b02b 100644 (file)
@@ -127,7 +127,7 @@ Property::Value TextLabel::GetProperty( BaseObject* object, Property::Index inde
 
 void TextLabel::OnInitialize()
 {
-  mController = Text::Controller::New();
+  mController = Text::Controller::New( *this );
 }
 
 Vector3 TextLabel::GetNaturalSize()
@@ -186,6 +186,11 @@ void TextLabel::SetMultiLine( bool multiLine )
   }
 }
 
+void TextLabel::RequestTextRelayout()
+{
+  RelayoutRequest();
+}
+
 TextLabel::TextLabel()
 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_NONE ) )
 {
index ab29fc9..913d820 100644 (file)
@@ -35,7 +35,7 @@ namespace Internal
 /**
  * @brief A control which renders a short text string.
  */
-class TextLabel : public Control
+class TextLabel : public Control, public Text::ControlInterface
 {
 public:
 
@@ -96,6 +96,11 @@ private: // From Control
    */
   virtual float GetHeightForWidth( float width );
 
+  /**
+   * @copydoc Text::ControlInterface::RequestTextRelayout()
+   */
+  virtual void RequestTextRelayout();
+
 private: // Implementation
 
   /**
index 4d7a7ea..d891302 100644 (file)
@@ -35,6 +35,7 @@ const std::string TextField::SECONDARY_CURSOR_COLOR_PROPERTY_NAME("secondary-cur
 const std::string TextField::ENABLE_CURSOR_BLINK_PROPERTY_NAME("enable-cursor-blink");
 const std::string TextField::CURSOR_BLINK_INTERVAL_PROPERTY_NAME("cursor-blink-interval");
 const std::string TextField::CURSOR_BLINK_DURATION_PROPERTY_NAME("cursor-blink-duration");
+const std::string TextField::GRAB_HANDLE_IMAGE_PROPERTY_NAME("grab-handle-image");
 
 TextField TextField::New()
 {
index 1ce8b7a..1f9b6f8 100644 (file)
@@ -49,6 +49,7 @@ public:
   static const Property::Index PROPERTY_ENABLE_CURSOR_BLINK;    ///< name "enable-cursor-blink",    type BOOLEAN
   static const Property::Index PROPERTY_CURSOR_BLINK_INTERVAL;  ///< name "cursor-blink-interval",  type FLOAT
   static const Property::Index PROPERTY_CURSOR_BLINK_DURATION;  ///< name "cursor-blink-duration",  type FLOAT
+  static const Property::Index PROPERTY_GRAB_HANDLE_IMAGE;      ///< name "grab-handle-image",      type STRING
 
   // Property names
   static const std::string PLACEHOLDER_TEXT_PROPERTY_NAME;       ///< Property, name "placeholder-text",       type STRING
@@ -59,6 +60,7 @@ public:
   static const std::string ENABLE_CURSOR_BLINK_PROPERTY_NAME;    ///< Property, name "enable-cursor-blink",    type BOOLEAN
   static const std::string CURSOR_BLINK_INTERVAL_PROPERTY_NAME;  ///< Property, name "cursor-blink-interval",  type FLOAT
   static const std::string CURSOR_BLINK_DURATION_PROPERTY_NAME;  ///< Property, name "cursor-blink-duration",  type FLOAT
+  static const std::string GRAB_HANDLE_IMAGE_PROPERTY_NAME;      ///< Property, name "grab-handle-image",      type STRING
 
   /**
    * Create the TextField control.
index f686339..5dd397e 100755 (executable)
@@ -101,6 +101,7 @@ public_api_src_files = \
   $(public_api_src_dir)/text/script.cpp \
   $(public_api_src_dir)/text/segmentation.cpp \
   $(public_api_src_dir)/text/shaper.cpp \
+  $(public_api_src_dir)/text/text-control-interface.cpp \
   $(public_api_src_dir)/text/text-controller.cpp \
   $(public_api_src_dir)/text/text-view.cpp \
   $(public_api_src_dir)/text/text-view-interface.cpp \
@@ -239,6 +240,7 @@ public_api_text_header_files = \
   $(public_api_src_dir)/text/script-run.h \
   $(public_api_src_dir)/text/segmentation.h \
   $(public_api_src_dir)/text/shaper.h \
+  $(public_api_src_dir)/text/text-control-interface.h \
   $(public_api_src_dir)/text/text-controller.h \
   $(public_api_src_dir)/text/text-definitions.h \
   $(public_api_src_dir)/text/text-view.h \
index 2dc5e72..4a7f666 100644 (file)
@@ -52,8 +52,9 @@ struct Decorator::Impl
     Vector4 color;
   };
 
-  Impl(Dali::Toolkit::Internal::Control& parent)
+  Impl(Dali::Toolkit::Internal::Control& parent, Observer& observer)
   : mParent(parent),
+    mObserver(observer),
     mActiveCursor(ACTIVE_CURSOR_NONE),
     mCursorBlinkInterval(0.5f),
     mCursorBlinkDuration(0.0f)
@@ -66,20 +67,22 @@ struct Decorator::Impl
   }
 
   Internal::Control& mParent;
+  Observer& mObserver;
 
   unsigned int mActiveCursor;
 
   CursorImpl mCursor[CURSOR_COUNT];
 
   Image mCursorImage;
+  Image mGrabHandleImage;
 
   float mCursorBlinkInterval;
   float mCursorBlinkDuration;
 };
 
-DecoratorPtr Decorator::New(Internal::Control& parent)
+DecoratorPtr Decorator::New( Internal::Control& parent, Observer& observer )
 {
-  return DecoratorPtr( new Decorator(parent) );
+  return DecoratorPtr( new Decorator(parent, observer) );
 }
 
 void Decorator::Relayout( const Vector2& size )
@@ -161,15 +164,25 @@ float Decorator::GetCursorBlinkDuration() const
   return mImpl->mCursorBlinkDuration;
 }
 
+void Decorator::SetGrabHandleImage( Dali::Image image )
+{
+  mImpl->mGrabHandleImage = image;
+}
+
+Dali::Image Decorator::GetGrabHandleImage() const
+{
+  return mImpl->mGrabHandleImage;
+}
+
 Decorator::~Decorator()
 {
   delete mImpl;
 }
 
-Decorator::Decorator(Dali::Toolkit::Internal::Control& parent)
+Decorator::Decorator(Dali::Toolkit::Internal::Control& parent, Observer& observer)
 : mImpl( NULL )
 {
-  mImpl = new Decorator::Impl(parent);
+  mImpl = new Decorator::Impl(parent, observer);
 }
 
 } // namespace Text
index d2d1feb..3ebc588 100644 (file)
@@ -59,23 +59,57 @@ enum ActiveCursor
   ACTIVE_CURSOR_BOTH     ///< Both primary and secondary cursor are active
 };
 
+// The state information for grab handle events
+enum GrabHandleState
+{
+  GRAB_HANDLE_MOVING,
+  GRAB_HANDLE_RELEASED
+};
+
 /**
  * @brief A Text Decorator is used to display cursors, handles, selection highlights and pop-ups.
  *
  * The decorator is responsible for clipping decorations which are positioned outside of the parent area.
  * In some cases the decorations will be moved or flipped around, to maintain visibility on-screen.
+ *
+ * Decorator components forward input events to a controller class through an observer interface.
+ * The controller is responsible for selecting which components are active.
  */
 class Decorator : public RefObject
 {
 public:
 
+  class Observer
+  {
+  public:
+
+    /**
+     * @brief Constructor.
+     */
+    Observer() {};
+
+    /**
+     * @brief Virtual destructor.
+     */
+    virtual ~Observer() {};
+
+    /**
+     * @brief An input event from the grab handle.
+     *
+     * @param[in] state The grab handle state.
+     * @param[in] x The x position relative to the top-left of the parent control.
+     */
+    virtual void GrabHandleEvent( GrabHandleState state, float x ) = 0;
+  };
+
   /**
    * @brief Create a new instance of a Decorator.
    *
    * @param[in] parent Decorations will be added to this parent control.
+   * @param[in] observer A class which receives input events from Decorator components.
    * @return A pointer to a new Decorator.
    */
-  static DecoratorPtr New( Dali::Toolkit::Internal::Control& parent );
+  static DecoratorPtr New( Dali::Toolkit::Internal::Control& parent, Observer& observer );
 
   /**
    * @brief The decorator waits until a relayout before creating actors etc.
@@ -93,7 +127,7 @@ public:
   void SetActiveCursor( ActiveCursor activeCursor );
 
   /**
-   * @brief Sets whether a cursor should be visible.
+   * @brief Query which of the cursors are active.
    *
    * @return  Which of the cursors are active (if any).
    */
@@ -187,6 +221,35 @@ public:
    */
   float GetCursorBlinkDuration() const;
 
+  /**
+   * @brief Sets whether the grab handle is active.
+   *
+   * @note The grab handle follows the cursor position set with SetPosition(Cursor, ...)
+   * @param[in] active True if the grab handle should be active.
+   */
+  void SetGrabHandleActive( bool active );
+
+  /**
+   * @brief Query whether the grab handle is active.
+   *
+   * @return True if the grab handle should be active.
+   */
+  bool IsGrabHandleActive() const;
+
+  /**
+   * @brief Sets the image for the grab handle.
+   *
+   * @param[in] image The image to use.
+   */
+  void SetGrabHandleImage( Dali::Image image );
+
+  /**
+   * @brief Retrieves the image for the grab handle.
+   *
+   * @return The grab handle image.
+   */
+  Dali::Image GetGrabHandleImage() const;
+
 protected:
 
   /**
@@ -199,8 +262,9 @@ private:
   /**
    * @brief Private constructor.
    * @param[in] parent Decorations will be added to this parent control.
+   * @param[in] observer A class which receives input events from Decorator components.
    */
-  Decorator(Dali::Toolkit::Internal::Control& parent);
+  Decorator(Dali::Toolkit::Internal::Control& parent, Observer& observer );
 
   // Undefined
   Decorator( const Decorator& handle );
diff --git a/dali-toolkit/public-api/text/text-control-interface.cpp b/dali-toolkit/public-api/text/text-control-interface.cpp
new file mode 100644 (file)
index 0000000..79ddca1
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/public-api/text/text-control-interface.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+ControlInterface::ControlInterface()
+{
+}
+
+ControlInterface::~ControlInterface()
+{
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/public-api/text/text-control-interface.h b/dali-toolkit/public-api/text/text-control-interface.h
new file mode 100644 (file)
index 0000000..3eb26b6
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef __DALI_TOOLKIT_TEXT_CONTROL_INTERFACE_H__
+#define __DALI_TOOLKIT_TEXT_CONTROL_INTERFACE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+/**
+ * @brief An interface that the Text::Controller uses to request a text relayout.
+ */
+class ControlInterface
+{
+public:
+
+  /**
+   * @brief Constructor.
+   */
+  ControlInterface();
+
+  /**
+   * @brief Virtual destructor.
+   */
+  virtual ~ControlInterface();
+
+  /**
+   * @brief Called to request a text relayout.
+   */
+  virtual void RequestTextRelayout() = 0;
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_CONTROL_INTERFACE_H__
index d759497..4582944 100644 (file)
@@ -42,12 +42,55 @@ namespace Toolkit
 namespace Text
 {
 
+struct Controller::TextInput
+{
+  // Used to queue input events until DoRelayout()
+  enum EventType
+  {
+    KEYBOARD_FOCUS_GAIN_EVENT,
+    KEYBOARD_FOCUS_LOST_EVENT,
+    TAP_EVENT,
+    GRAB_HANDLE_EVENT
+  };
+
+  union Param
+  {
+    int mInt;
+    float mFloat;
+  };
+
+  struct Event
+  {
+    Event( EventType eventType )
+    : type( eventType )
+    {
+      p1.mInt = 0;
+      p2.mInt = 0;
+    }
+
+    EventType type;
+    Param p1;
+    Param p2;
+  };
+
+  TextInput( DecoratorPtr decorator )
+  : mDecorator( decorator )
+  {
+  }
+
+  DecoratorPtr mDecorator;
+
+  std::vector<Event> mEventQueue;
+};
+
 struct Controller::Impl
 {
-  Impl()
-  : mNewText(),
+  Impl( ControlInterface& controlInterface )
+  : mControlInterface( controlInterface ),
+    mNewText(),
     mOperations( NO_OPERATION ),
-    mControlSize()
+    mControlSize(),
+    mTextInput( NULL )
   {
     mLogicalModel = LogicalModel::New();
     mVisualModel  = VisualModel::New();
@@ -57,6 +100,13 @@ struct Controller::Impl
     mFontClient = TextAbstraction::FontClient::Get();
   }
 
+  ~Impl()
+  {
+    delete mTextInput;
+  }
+
+  ControlInterface& mControlInterface;
+
   std::string mNewText;
 
   LogicalModelPtr mLogicalModel;
@@ -71,11 +121,14 @@ struct Controller::Impl
   OperationsMask mOperations;
 
   Size mControlSize;
+
+  // Avoid allocating everything for text input until EnableTextInput()
+  Controller::TextInput* mTextInput;
 };
 
-ControllerPtr Controller::New()
+ControllerPtr Controller::New( ControlInterface& controlInterface )
 {
-  return ControllerPtr( new Controller() );
+  return ControllerPtr( new Controller( controlInterface ) );
 }
 
 void Controller::SetText( const std::string& text )
@@ -83,6 +136,22 @@ void Controller::SetText( const std::string& text )
   // Keep until size negotiation
   mImpl->mNewText = text;
   mImpl->mOperations = ALL_OPERATIONS;
+
+  if( mImpl->mTextInput )
+  {
+    // Cancel previously queued events
+    mImpl->mTextInput->mEventQueue.clear();
+
+    // TODO - Hide selection decorations
+  }
+}
+
+void Controller::EnableTextInput( DecoratorPtr decorator )
+{
+  if( !mImpl->mTextInput )
+  {
+    mImpl->mTextInput = new TextInput( decorator );
+  }
 }
 
 bool Controller::Relayout( const Vector2& size )
@@ -239,6 +308,8 @@ bool Controller::DoRelayout( const Vector2& size, OperationsMask operations )
     viewUpdated = true;
   }
 
+  // TODO - process input events to move grab handle
+
   return viewUpdated;
 }
 
@@ -309,15 +380,74 @@ LayoutEngine& Controller::GetLayoutEngine()
   return mImpl->mLayoutEngine;
 }
 
+void Controller::RequestRelayout()
+{
+  mImpl->mControlInterface.RequestTextRelayout();
+}
+
+void Controller::KeyboardFocusGainEvent()
+{
+  DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected KeyboardFocusGainEvent" );
+
+  if( mImpl->mTextInput )
+  {
+    TextInput::Event event( TextInput::KEYBOARD_FOCUS_GAIN_EVENT );
+    mImpl->mTextInput->mEventQueue.push_back( event );
+
+    RequestRelayout();
+  }
+}
+
+void Controller::KeyboardFocusLostEvent()
+{
+  DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected KeyboardFocusLostEvent" );
+
+  if( mImpl->mTextInput )
+  {
+    TextInput::Event event( TextInput::KEYBOARD_FOCUS_LOST_EVENT );
+    mImpl->mTextInput->mEventQueue.push_back( event );
+
+    RequestRelayout();
+  }
+}
+
+void Controller::TapEvent( float x, float y)
+{
+  DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected TapEvent" );
+
+  if( mImpl->mTextInput )
+  {
+    TextInput::Event event( TextInput::TAP_EVENT );
+    event.p1.mFloat = x;
+    event.p2.mFloat = y;
+
+    RequestRelayout();
+  }
+}
+
+void Controller::GrabHandleEvent( GrabHandleState state, float x )
+{
+  DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected GrabHandleEvent" );
+
+  if( mImpl->mTextInput )
+  {
+    TextInput::Event event( TextInput::GRAB_HANDLE_EVENT );
+    event.p1.mInt   = state;
+    event.p2.mFloat = x;
+
+    RequestRelayout();
+  }
+}
+
 Controller::~Controller()
 {
   delete mImpl;
 }
 
-Controller::Controller()
+Controller::Controller( ControlInterface& controlInterface )
 : mImpl( NULL )
 {
-  mImpl = new Controller::Impl();
+  mImpl = new Controller::Impl( controlInterface );
 }
 
 } // namespace Text
index 92bc417..d2c9117 100644 (file)
@@ -19,6 +19,8 @@
  */
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/public-api/text/decorator/text-decorator.h>
+#include <dali-toolkit/public-api/text/text-control-interface.h>
 #include <dali-toolkit/public-api/text/text-view.h>
 
 // EXTERNAL INCLUDES
@@ -41,14 +43,18 @@ class Controller;
 class LayoutEngine;
 
 typedef IntrusivePtr<Controller> ControllerPtr;
+typedef Dali::Toolkit::Text::ControlInterface ControlInterface;
 
 /**
  * @brief A Text Controller is used by UI Controls which display text.
  *
  * It manipulates the Logical & Visual text models on behalf of the UI Controls.
  * It provides a view of the text that can be used by rendering back-ends.
+ *
+ * For selectable/editable UI controls, the controller handles input events from the UI control
+ * and decorations (grab handles etc) via an observer interface.
  */
-class Controller : public RefObject
+class Controller : public RefObject, public Decorator::Observer
 {
 private:
 
@@ -77,9 +83,10 @@ public:
   /**
    * @brief Create a new instance of a Controller.
    *
+   * @param[in] controlInterface An interface used to request a text relayout.
    * @return A pointer to a new Controller.
    */
-  static ControllerPtr New();
+  static ControllerPtr New( ControlInterface& controlInterface );
 
   /**
    * @brief Replaces any text previously set.
@@ -90,6 +97,14 @@ public:
   void SetText( const std::string& text );
 
   /**
+   * @brief Called to enable text input.
+   *
+   * @note Only selectable or editable controls should calls this.
+   * @param[in] decorator Used to create cursor, selection handle decorations etc.
+   */
+  void EnableTextInput( DecoratorPtr decorator );
+
+  /**
    * @brief Triggers a relayout which updates View (if necessary).
    *
    * @note UI Controls are expected to minimize calls to this method e.g. call once after size negotiation.
@@ -127,6 +142,26 @@ public:
    */
   View& GetView();
 
+  /**
+   * @brief Caller by editable UI controls when keyboard focus is gained.
+   */
+  void KeyboardFocusGainEvent();
+
+  /**
+   * @brief Caller by editable UI controls when focus is lost.
+   */
+  void KeyboardFocusLostEvent();
+
+  /**
+   * @brief Caller by editable UI controls when focus is lost.
+   */
+  void TapEvent( float x, float y );
+
+  /**
+   * @copydoc Dali::Toolkit::Text::Decorator::Observer::GrabHandleEvent()
+   */
+  virtual void GrabHandleEvent( GrabHandleState state, float x );
+
 protected:
 
   /**
@@ -137,14 +172,14 @@ protected:
 private:
 
   /**
-   * @brief Private constructor.
+   * @brief Request a relayout using the ControlInterface.
    */
-  Controller();
+  void RequestRelayout();
 
   /**
-   * @brief Populates the visual model.
+   * @brief Private constructor.
    */
-  void UpdateVisualModel();
+  Controller( ControlInterface& controlInterface );
 
   // Undefined
   Controller( const Controller& handle );
@@ -156,6 +191,9 @@ private:
 
   struct Impl;
   Impl* mImpl;
+
+  // Avoid allocating this for non-editable controls
+  struct TextInput;
 };
 
 } // namespace Text