06e94632144f14f87f12ef528c23ef03fd9ed9e0
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / text-controller-impl.h
1 #ifndef __DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_H__
2 #define __DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_H__
3
4 /*
5  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // EXTERNAL INCLUDES
22 #include <dali/public-api/text-abstraction/font-client.h>
23
24 // INTERNAL INCLUDES
25 #include <dali-toolkit/internal/text/layouts/layout-engine.h>
26 #include <dali-toolkit/internal/text/logical-model-impl.h>
27 #include <dali-toolkit/internal/text/text-controller.h>
28 #include <dali-toolkit/internal/text/visual-model-impl.h>
29
30 namespace Dali
31 {
32
33 namespace Toolkit
34 {
35
36 namespace Text
37 {
38
39 struct Event
40 {
41   // Used to queue input events until DoRelayout()
42   enum Type
43   {
44     KEYBOARD_FOCUS_GAIN_EVENT,
45     KEYBOARD_FOCUS_LOST_EVENT,
46     CURSOR_KEY_EVENT,
47     TAP_EVENT,
48     PAN_EVENT,
49     GRAB_HANDLE_EVENT
50   };
51
52   union Param
53   {
54     int mInt;
55     unsigned int mUint;
56     float mFloat;
57   };
58
59   Event( Type eventType )
60   : type( eventType )
61   {
62     p1.mInt = 0;
63     p2.mInt = 0;
64   }
65
66   Type type;
67   Param p1;
68   Param p2;
69   Param p3;
70 };
71
72 struct CursorInfo
73 {
74   CursorInfo()
75   : primaryPosition(),
76     secondaryPosition(),
77     lineHeight( 0.f ),
78     primaryCursorHeight( 0.f ),
79     secondaryCursorHeight( 0.f ),
80     isSecondaryCursor( false )
81   {}
82
83   ~CursorInfo()
84   {}
85
86   Vector2 primaryPosition;       ///< The primary cursor's position.
87   Vector2 secondaryPosition;     ///< The secondary cursor's position.
88   float   lineHeight;            ///< The height of the line where the cursor is placed.
89   float   primaryCursorHeight;   ///< The primary cursor's height.
90   float   secondaryCursorHeight; ///< The secondary cursor's height.
91   bool    isSecondaryCursor;     ///< Whether the secondary cursor is valid.
92 };
93
94 struct EventData
95 {
96   enum State
97   {
98     INACTIVE,
99     SELECTING,
100     EDITING,
101     EDITING_WITH_POPUP
102   };
103
104   EventData( DecoratorPtr decorator );
105
106   ~EventData();
107
108   DecoratorPtr mDecorator;
109   std::string  mPlaceholderText;
110
111   /**
112    * This is used to delay handling events until after the model has been updated.
113    * The number of updates to the model is minimized to improve performance.
114    */
115   std::vector<Event> mEventQueue; ///< The queue of touch events etc.
116
117   /**
118    * 0,0 means that the top-left corner of the layout matches the top-left corner of the UI control.
119    * Typically this will have a negative value with scrolling occurs.
120    */
121   Vector2 mScrollPosition; ///< The text is offset by this position when scrolling.
122
123   State mState; ///< Selection mode, edit mode etc.
124
125   CharacterIndex mPrimaryCursorPosition;   ///< Index into logical model for primary cursor
126   CharacterIndex mSecondaryCursorPosition; ///< Index into logical model for secondary cursor
127
128   bool mDecoratorUpdated           : 1; ///< True if the decorator was updated during event processing
129   bool mCursorBlinkEnabled         : 1; ///< True if cursor should blink when active
130   bool mGrabHandleEnabled          : 1; ///< True if grab handle is enabled
131   bool mGrabHandlePopupEnabled     : 1; ///< True if the grab handle popu-up should be shown
132   bool mSelectionEnabled           : 1; ///< True if selection handles, highlight etc. are enabled
133   bool mHorizontalScrollingEnabled : 1; ///< True if horizontal scrolling is enabled
134   bool mVerticalScrollingEnabled   : 1; ///< True if vertical scrolling is enabled
135   bool mUpdateCursorPosition       : 1; ///< True if the visual position of the cursor must be recalculated
136 };
137
138 struct ModifyEvent
139 {
140   enum Type
141   {
142     REPLACE_TEXT, ///< Replace the entire text
143     INSERT_TEXT,  ///< Insert characters at the current cursor position
144     DELETE_TEXT   ///< Delete a character at the current cursor position
145   };
146
147   Type type;
148   std::string text;
149 };
150
151 struct FontDefaults
152 {
153   FontDefaults()
154   : mDefaultPointSize(0.0f),
155     mFontId(0u)
156   {
157   }
158
159   FontId GetFontId( TextAbstraction::FontClient& fontClient )
160   {
161     if( !mFontId )
162     {
163       Dali::TextAbstraction::PointSize26Dot6 pointSize = mDefaultPointSize*64;
164       mFontId = fontClient.GetFontId( mDefaultFontFamily, mDefaultFontStyle, pointSize );
165     }
166
167     return mFontId;
168   }
169
170   std::string mDefaultFontFamily;
171   std::string mDefaultFontStyle;
172   float mDefaultPointSize;
173   FontId mFontId;
174 };
175
176 struct Controller::Impl
177 {
178   Impl( ControlInterface& controlInterface )
179   : mControlInterface( controlInterface ),
180     mLogicalModel(),
181     mVisualModel(),
182     mFontDefaults( NULL ),
183     mEventData( NULL ),
184     mFontClient(),
185     mView(),
186     mLayoutEngine(),
187     mModifyEvents(),
188     mControlSize(),
189     mAlignmentOffset(),
190     mOperationsPending( NO_OPERATION ),
191     mRecalculateNaturalSize( true )
192   {
193     mLogicalModel = LogicalModel::New();
194     mVisualModel  = VisualModel::New();
195
196     mFontClient = TextAbstraction::FontClient::Get();
197
198     mView.SetVisualModel( mVisualModel );
199
200     // Set the text properties to default
201     mVisualModel->SetTextColor( Color::WHITE );
202     mVisualModel->SetShadowOffset( Vector2::ZERO );
203     mVisualModel->SetShadowColor( Color::BLACK );
204     mVisualModel->SetUnderlineEnabled( false );
205     mVisualModel->SetUnderlineHeight( 0.0f );
206   }
207
208   ~Impl()
209   {
210     delete mEventData;
211   }
212
213   /**
214    * @brief Request a relayout using the ControlInterface.
215    */
216   void RequestRelayout();
217
218
219   /**
220    * @brief Helper to move the cursor, grab handle etc.
221    */
222   bool ProcessInputEvents();
223
224   void OnKeyboardFocus( bool hasFocus );
225
226   void OnCursorKeyEvent( const Event& event );
227
228   void HandleCursorKey( int keyCode );
229
230   void OnTapEvent( const Event& event );
231
232   void OnPanEvent( const Event& event );
233
234   void OnGrabHandleEvent( const Event& event );
235
236   void RepositionSelectionHandles( float visualX, float visualY );
237
238   void ChangeState( EventData::State newState );
239
240   LineIndex GetClosestLine( float y ) const;
241
242   /**
243    * @brief Retrieves the cursor's logical position for a given touch point x,y
244    *
245    * @param[in] visualX The touch point x.
246    * @param[in] visualY The touch point y.
247    *
248    * @return The logical cursor position (in characters). 0 is just before the first character, a value equal to the number of characters is just after the last character.
249    */
250   CharacterIndex GetClosestCursorIndex( float visualX,
251                                         float visualY );
252
253   /**
254    * @brief Calculates the cursor's position for a given character index in the logical order.
255    *
256    * It retrieves as well the line's height and the cursor's height and
257    * if there is a valid alternative cursor, its position and height.
258    *
259    * @param[in] logical The logical cursor position (in characters). 0 is just before the first character, a value equal to the number of characters is just after the last character.
260    * @param[out] cursorInfo The line's height, the cursor's height, the cursor's position and whether there is an alternative cursor.
261    */
262   void GetCursorPosition( CharacterIndex logical,
263                           CursorInfo& cursorInfo );
264
265   /**
266    * @brief Calculates the new cursor index.
267    *
268    * It takes into account that in some scripts multiple characters can form a glyph and all of them
269    * need to be jumped with one key event.
270    *
271    * @param[in] index The initial new index.
272    *
273    * @return The new cursor index.
274    */
275   CharacterIndex CalculateNewCursorIndex( CharacterIndex index ) const;
276
277   void UpdateCursorPosition();
278
279   ControlInterface& mControlInterface;     ///< Reference to the text controller.
280   LogicalModelPtr mLogicalModel;           ///< Pointer to the logical model.
281   VisualModelPtr  mVisualModel;            ///< Pointer to the visual model.
282   FontDefaults* mFontDefaults;             ///< Avoid allocating this when the user does not specify a font.
283   EventData* mEventData;                   ///< Avoid allocating everything for text input until EnableTextInput().
284   TextAbstraction::FontClient mFontClient; ///< Handle to the font client.
285   View mView;                              ///< The view interface to the rendering back-end.
286   LayoutEngine mLayoutEngine;              ///< The layout engine.
287   std::vector<ModifyEvent> mModifyEvents;  ///< Temporary stores the text set until the next relayout.
288   Size mControlSize;                       ///< The size of the control.
289   Vector2 mAlignmentOffset;                ///< Vertical and horizontal offset of the whole text inside the control due to alignment.
290   OperationsMask mOperationsPending;       ///< Operations pending to be done to layout the text.
291   bool mRecalculateNaturalSize:1;          ///< Whether the natural size needs to be recalculated.
292 };
293
294 } // namespace Text
295
296 } // namespace Toolkit
297
298 } // namespace Dali
299
300 #endif // __DALI_TOOLKIT_TEXT_CONTROLLER_H__