Merge remote-tracking branch 'origin/tizen' into devel/new_mesh
[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     LEFT_SELECTION_HANDLE_EVENT,
51     RIGHT_SELECTION_HANDLE_EVENT
52   };
53
54   union Param
55   {
56     int mInt;
57     unsigned int mUint;
58     float mFloat;
59   };
60
61   Event( Type eventType )
62   : type( eventType )
63   {
64     p1.mInt = 0;
65     p2.mInt = 0;
66     p3.mInt = 0;
67   }
68
69   Type type;
70   Param p1;
71   Param p2;
72   Param p3;
73 };
74
75 struct CursorInfo
76 {
77   CursorInfo()
78   : primaryPosition(),
79     secondaryPosition(),
80     lineHeight( 0.f ),
81     primaryCursorHeight( 0.f ),
82     secondaryCursorHeight( 0.f ),
83     isSecondaryCursor( false )
84   {}
85
86   ~CursorInfo()
87   {}
88
89   Vector2 primaryPosition;       ///< The primary cursor's position.
90   Vector2 secondaryPosition;     ///< The secondary cursor's position.
91   float   lineHeight;            ///< The height of the line where the cursor is placed.
92   float   primaryCursorHeight;   ///< The primary cursor's height.
93   float   secondaryCursorHeight; ///< The secondary cursor's height.
94   bool    isSecondaryCursor;     ///< Whether the secondary cursor is valid.
95 };
96
97 struct EventData
98 {
99   enum State
100   {
101     INACTIVE,
102     SELECTING,
103     EDITING,
104     EDITING_WITH_POPUP
105   };
106
107   EventData( DecoratorPtr decorator );
108
109   ~EventData();
110
111   DecoratorPtr       mDecorator;               ///< Pointer to the decorator
112   std::string        mPlaceholderText;         ///< The plaxe holder text
113
114   /**
115    * This is used to delay handling events until after the model has been updated.
116    * The number of updates to the model is minimized to improve performance.
117    */
118   std::vector<Event> mEventQueue;              ///< The queue of touch events etc.
119
120   /**
121    * 0,0 means that the top-left corner of the layout matches the top-left corner of the UI control.
122    * Typically this will have a negative value with scrolling occurs.
123    */
124   Vector2            mScrollPosition;          ///< The text is offset by this position when scrolling.
125
126   State              mState;                   ///< Selection mode, edit mode etc.
127
128   CharacterIndex     mPrimaryCursorPosition;   ///< Index into logical model for primary cursor.
129   CharacterIndex     mLeftSelectionPosition;   ///< Index into logical model for left selection handle.
130   CharacterIndex     mRightSelectionPosition;  ///< Index into logical model for right selection handle.
131
132   bool mDecoratorUpdated                : 1;   ///< True if the decorator was updated during event processing.
133   bool mCursorBlinkEnabled              : 1;   ///< True if cursor should blink when active.
134   bool mGrabHandleEnabled               : 1;   ///< True if grab handle is enabled.
135   bool mGrabHandlePopupEnabled          : 1;   ///< True if the grab handle popu-up should be shown.
136   bool mSelectionEnabled                : 1;   ///< True if selection handles, highlight etc. are enabled.
137   bool mHorizontalScrollingEnabled      : 1;   ///< True if horizontal scrolling is enabled.
138   bool mVerticalScrollingEnabled        : 1;   ///< True if vertical scrolling is enabled.
139   bool mUpdateCursorPosition            : 1;   ///< True if the visual position of the cursor must be recalculated.
140   bool mUpdateLeftSelectionPosition     : 1;   ///< True if the visual position of the left selection handle must be recalculated.
141   bool mUpdateRightSelectionPosition    : 1;   ///< True if the visual position of the right selection handle must be recalculated.
142   bool mScrollAfterUpdateCursorPosition : 1;   ///< Whether to scroll after the cursor position is updated.
143 };
144
145 struct ModifyEvent
146 {
147   enum Type
148   {
149     REPLACE_TEXT, ///< Replace the entire text
150     INSERT_TEXT,  ///< Insert characters at the current cursor position
151     DELETE_TEXT   ///< Delete a character at the current cursor position
152   };
153
154   Type type;
155   std::string text;
156 };
157
158 struct FontDefaults
159 {
160   FontDefaults()
161   : mDefaultPointSize(0.0f),
162     mFontId(0u)
163   {
164   }
165
166   FontId GetFontId( TextAbstraction::FontClient& fontClient )
167   {
168     if( !mFontId )
169     {
170       Dali::TextAbstraction::PointSize26Dot6 pointSize = mDefaultPointSize*64;
171       mFontId = fontClient.GetFontId( mDefaultFontFamily, mDefaultFontStyle, pointSize );
172     }
173
174     return mFontId;
175   }
176
177   std::string mDefaultFontFamily;
178   std::string mDefaultFontStyle;
179   float mDefaultPointSize;
180   FontId mFontId;
181 };
182
183 struct Controller::Impl
184 {
185   Impl( ControlInterface& controlInterface )
186   : mControlInterface( controlInterface ),
187     mLogicalModel(),
188     mVisualModel(),
189     mFontDefaults( NULL ),
190     mEventData( NULL ),
191     mFontClient(),
192     mView(),
193     mLayoutEngine(),
194     mModifyEvents(),
195     mControlSize(),
196     mAlignmentOffset(),
197     mOperationsPending( NO_OPERATION ),
198     mMaximumNumberOfCharacters( 50 ),
199     mRecalculateNaturalSize( true )
200   {
201     mLogicalModel = LogicalModel::New();
202     mVisualModel  = VisualModel::New();
203
204     mFontClient = TextAbstraction::FontClient::Get();
205
206     mView.SetVisualModel( mVisualModel );
207
208     // Set the text properties to default
209     mVisualModel->SetTextColor( Color::WHITE );
210     mVisualModel->SetShadowOffset( Vector2::ZERO );
211     mVisualModel->SetShadowColor( Color::BLACK );
212     mVisualModel->SetUnderlineEnabled( false );
213     mVisualModel->SetUnderlineHeight( 0.0f );
214   }
215
216   ~Impl()
217   {
218     delete mEventData;
219   }
220
221   /**
222    * @brief Request a relayout using the ControlInterface.
223    */
224   void RequestRelayout();
225
226   /**
227    * @brief Helper to move the cursor, grab handle etc.
228    */
229   bool ProcessInputEvents();
230
231   void OnKeyboardFocus( bool hasFocus );
232
233   void OnCursorKeyEvent( const Event& event );
234
235   void HandleCursorKey( int keyCode );
236
237   void OnTapEvent( const Event& event );
238
239   void OnPanEvent( const Event& event );
240
241   void OnHandleEvent( const Event& event );
242
243   void RepositionSelectionHandles( float visualX, float visualY );
244
245   void ChangeState( EventData::State newState );
246
247   LineIndex GetClosestLine( float y ) const;
248
249   /**
250    * @brief Retrieves the cursor's logical position for a given touch point x,y
251    *
252    * @param[in] visualX The touch point x.
253    * @param[in] visualY The touch point y.
254    *
255    * @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.
256    */
257   CharacterIndex GetClosestCursorIndex( float visualX,
258                                         float visualY );
259
260   /**
261    * @brief Calculates the cursor's position for a given character index in the logical order.
262    *
263    * It retrieves as well the line's height and the cursor's height and
264    * if there is a valid alternative cursor, its position and height.
265    *
266    * @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.
267    * @param[out] cursorInfo The line's height, the cursor's height, the cursor's position and whether there is an alternative cursor.
268    */
269   void GetCursorPosition( CharacterIndex logical,
270                           CursorInfo& cursorInfo );
271
272   /**
273    * @brief Calculates the new cursor index.
274    *
275    * It takes into account that in some scripts multiple characters can form a glyph and all of them
276    * need to be jumped with one key event.
277    *
278    * @param[in] index The initial new index.
279    *
280    * @return The new cursor index.
281    */
282   CharacterIndex CalculateNewCursorIndex( CharacterIndex index ) const;
283
284   /**
285    * @brief Updates the cursor position.
286    *
287    * Retrieves the x,y position of the cursor logical position and sets it into the decorator.
288    * It sets the position of the secondary cursor if it's a valid one.
289    * Sets which cursors are active.
290    */
291   void UpdateCursorPosition();
292
293   /**
294    * @brief Updates the position of the given selection handle.
295    *
296    * @param[in] handleType One of the selection handles.
297    */
298   void UpdateSelectionHandle( HandleType handleType );
299
300   /**
301    * @biref Clamps the horizontal scrolling to get the control always filled with text.
302    *
303    * @param[in] actualSize The size of the laid out text.
304    */
305   void ClampHorizontalScroll( const Vector2& actualSize );
306
307   /**
308    * @biref Clamps the vertical scrolling to get the control always filled with text.
309    *
310    * @param[in] actualSize The size of the laid out text.
311    */
312   void ClampVerticalScroll( const Vector2& actualSize );
313
314   /**
315    * @brief Scrolls the text to make the cursor visible.
316    *
317    * This method is called after inserting, deleting or moving the cursor with the keypad.
318    */
319   void ScrollToMakeCursorVisible();
320
321   ControlInterface& mControlInterface;     ///< Reference to the text controller.
322   LogicalModelPtr mLogicalModel;           ///< Pointer to the logical model.
323   VisualModelPtr  mVisualModel;            ///< Pointer to the visual model.
324   FontDefaults* mFontDefaults;             ///< Avoid allocating this when the user does not specify a font.
325   EventData* mEventData;                   ///< Avoid allocating everything for text input until EnableTextInput().
326   TextAbstraction::FontClient mFontClient; ///< Handle to the font client.
327   View mView;                              ///< The view interface to the rendering back-end.
328   LayoutEngine mLayoutEngine;              ///< The layout engine.
329   std::vector<ModifyEvent> mModifyEvents;  ///< Temporary stores the text set until the next relayout.
330   Size mControlSize;                       ///< The size of the control.
331   Vector2 mAlignmentOffset;                ///< Vertical and horizontal offset of the whole text inside the control due to alignment.
332   OperationsMask mOperationsPending;       ///< Operations pending to be done to layout the text.
333   Length mMaximumNumberOfCharacters;       ///< Maximum number of characters that can be inserted.
334   bool mRecalculateNaturalSize:1;          ///< Whether the natural size needs to be recalculated.
335 };
336
337 } // namespace Text
338
339 } // namespace Toolkit
340
341 } // namespace Dali
342
343 #endif // __DALI_TOOLKIT_TEXT_CONTROLLER_H__