Merge "Updates for Visual::SetSize removal" into devel/master
[platform/core/uifw/dali-demo.git] / examples / text-label / text-label-example.cpp
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 /**
19  * @file text-label-example.cpp
20  * @brief Basic usage of TextLabel control
21  */
22
23 // EXTERNAL INCLUDES
24 #include <dali-toolkit/dali-toolkit.h>
25 #include <iostream>
26
27 // INTERNAL INCLUDES
28 #include "shared/multi-language-strings.h"
29 #include "shared/view.h"
30
31 using namespace Dali;
32 using namespace Dali::Toolkit;
33 using namespace MultiLanguageStrings;
34
35 namespace
36 {
37 const char* const BACKGROUND_IMAGE = DEMO_IMAGE_DIR "grab-handle.png";
38
39 const unsigned int KEY_ZERO = 10;
40 const unsigned int KEY_ONE = 11;
41 const unsigned int KEY_F = 41;
42 const unsigned int KEY_H = 43;
43 const unsigned int KEY_V = 55;
44 const unsigned int KEY_M = 58;
45 const unsigned int KEY_L = 46;
46 const unsigned int KEY_S = 39;
47 const unsigned int KEY_PLUS = 21;
48 const unsigned int KEY_MINUS = 20;
49
50 const char* H_ALIGNMENT_STRING_TABLE[] =
51 {
52   "BEGIN",
53   "CENTER",
54   "END"
55 };
56
57 const unsigned int H_ALIGNMENT_STRING_COUNT = sizeof( H_ALIGNMENT_STRING_TABLE ) / sizeof( H_ALIGNMENT_STRING_TABLE[0u] );
58
59 const char* V_ALIGNMENT_STRING_TABLE[] =
60 {
61   "TOP",
62   "CENTER",
63   "BOTTOM"
64 };
65
66 const unsigned int V_ALIGNMENT_STRING_COUNT = sizeof( V_ALIGNMENT_STRING_TABLE ) / sizeof( V_ALIGNMENT_STRING_TABLE[0u] );
67
68 int ConvertToEven(int value)
69 {
70   return (value % 2 == 0) ? value : (value + 1);
71 }
72
73 struct HSVColorConstraint
74 {
75   HSVColorConstraint(float hue, float saturation, float value)
76   : hue(hue),
77     saturation(saturation),
78     value(value)
79   {
80   }
81
82   void operator()(Vector4& current, const PropertyInputContainer& inputs )
83   {
84     current = hsv2rgb(Vector4(inputs[0]->GetFloat(), saturation, value, current.a));
85   }
86
87   Vector4 hsv2rgb(Vector4 colorHSV)
88   {
89     float r=colorHSV.z*(1+colorHSV.y*(cos(colorHSV.x)-1));
90     float g=colorHSV.z*(1+colorHSV.y*(cos(colorHSV.x-2.09439)-1));
91     float b=colorHSV.z*(1+colorHSV.y*(cos(colorHSV.x+2.09439)-1));
92     return Vector4(r, g, b, colorHSV.a);
93   }
94   float hue;
95   float saturation;
96   float value;
97 };
98
99 } // anonymous namespace
100
101 /**
102  * @brief The main class of the demo.
103  */
104 class TextLabelExample : public ConnectionTracker
105 {
106 public:
107
108   TextLabelExample( Application& application )
109   : mApplication( application ),
110     mLabel(),
111     mContainer(),
112     mGrabCorner(),
113     mPanGestureDetector(),
114     mLayoutSize(),
115     mLanguageId( 0u ),
116     mAlignment( 0u ),
117     mHueAngleIndex( Property::INVALID_INDEX ),
118     mOverrideMixColorIndex( Property::INVALID_INDEX )
119   {
120     // Connect to the Application's Init signal
121     mApplication.InitSignal().Connect( this, &TextLabelExample::Create );
122   }
123
124   ~TextLabelExample()
125   {
126     // Nothing to do here.
127   }
128
129   /**
130    * One-time setup in response to Application InitSignal.
131    */
132   void Create( Application& application )
133   {
134     Stage stage = Stage::GetCurrent();
135
136     stage.KeyEventSignal().Connect(this, &TextLabelExample::OnKeyEvent);
137     Vector2 stageSize = stage.GetSize();
138
139     mContainer = Control::New();
140     mContainer.SetName( "Container" );
141     mContainer.SetParentOrigin( ParentOrigin::CENTER );
142     mLayoutSize = Vector2(stageSize.width*0.6f, stageSize.width*0.6f);
143     mContainer.SetSize( mLayoutSize );
144     mContainer.SetDrawMode( DrawMode::OVERLAY_2D );
145     stage.Add( mContainer );
146
147     // Resize the center layout when the corner is grabbed
148     mGrabCorner = ImageView::New( BACKGROUND_IMAGE );
149     mGrabCorner.SetName( "GrabCorner" );
150     mGrabCorner.SetAnchorPoint( AnchorPoint::TOP_CENTER );
151     mGrabCorner.SetParentOrigin( ParentOrigin::BOTTOM_RIGHT );
152     mGrabCorner.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
153     mContainer.Add( mGrabCorner );
154
155     mPanGestureDetector = PanGestureDetector::New();
156     mPanGestureDetector.Attach( mGrabCorner );
157     mPanGestureDetector.DetectedSignal().Connect( this, &TextLabelExample::OnPan );
158
159     mLabel = TextLabel::New( "A Quick Brown Fox Jumps Over The Lazy Dog" );
160     mLabel.SetName( "TextLabel" );
161     mLabel.SetAnchorPoint( AnchorPoint::TOP_LEFT );
162     mLabel.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
163     mLabel.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT );
164     mLabel.SetProperty( TextLabel::Property::MULTI_LINE, true );
165     mLabel.SetProperty( TextLabel::Property::TEXT_COLOR, Color::BLUE );
166     mLabel.SetProperty( TextLabel::Property::SHADOW_OFFSET, Vector2( 1.0f, 1.0f ) );
167     mLabel.SetProperty( TextLabel::Property::SHADOW_COLOR, Color::BLACK );
168     mLabel.SetBackgroundColor( Color::WHITE );
169     mContainer.Add( mLabel );
170
171     mHueAngleIndex = mLabel.RegisterProperty( "hue", 0.0f );
172     Renderer bgRenderer = mLabel.GetRendererAt(0);
173     mOverrideMixColorIndex = bgRenderer.GetPropertyIndex( ColorVisual::Property::MIX_COLOR );
174
175     Constraint constraint = Constraint::New<Vector4>( bgRenderer, mOverrideMixColorIndex, HSVColorConstraint(0.0f, 0.5f, 0.8f));
176     constraint.AddSource( Source( mLabel, mHueAngleIndex ) );
177     constraint.SetRemoveAction( Constraint::Discard );
178     constraint.Apply();
179
180     Animation anim = Animation::New(50.0f);
181     anim.AnimateTo(Property(mLabel, mHueAngleIndex), 6.28318f);
182     anim.SetLooping(true);
183     anim.Play();
184
185     Property::Value labelText = mLabel.GetProperty( TextLabel::Property::TEXT );
186     std::cout << "Displaying text: \"" << labelText.Get< std::string >() << "\"" << std::endl;
187   }
188
189   // Resize the text-label with pan gesture
190   void OnPan( Actor actor, const PanGesture& gesture )
191   {
192     // Reset mLayoutSize when the pan starts
193     if( gesture.state == Gesture::Started )
194     {
195       if( mLayoutSize.x < 2.0f )
196       {
197         mLayoutSize.x = 2.0f;
198       }
199
200       if( mLayoutSize.y < 2.0f )
201       {
202         mLayoutSize.y = 2.0f;
203       }
204     }
205
206     mLayoutSize.x += gesture.displacement.x * 2.0f;
207     mLayoutSize.y += gesture.displacement.y * 2.0f;
208
209     if( mLayoutSize.x >= 2.0f ||
210         mLayoutSize.y >= 2.0f )
211     {
212       // Avoid pixel mis-alignment issue
213       Vector2 clampedSize = Vector2( std::max( ConvertToEven( static_cast<int>( mLayoutSize.x )), 2 ),
214                                      std::max( ConvertToEven( static_cast<int>( mLayoutSize.y )), 2 ) );
215
216       mContainer.SetSize( clampedSize );
217     }
218   }
219
220   /**
221    * Main key event handler
222    */
223   void OnKeyEvent(const KeyEvent& event)
224   {
225     if(event.state == KeyEvent::Down)
226     {
227       if( IsKey( event, DALI_KEY_ESCAPE) || IsKey( event, DALI_KEY_BACK ) )
228       {
229         mApplication.Quit();
230       }
231       else if( event.IsCtrlModifier() )
232       {
233         switch( event.keyCode )
234         {
235           // Select rendering back-end
236           case KEY_ZERO: // fall through
237           case KEY_ONE:
238           {
239             mLabel.SetProperty( TextLabel::Property::RENDERING_BACKEND, event.keyCode - 10 );
240             break;
241           }
242           case KEY_F: // Fill vertically
243           {
244             if( ResizePolicy::DIMENSION_DEPENDENCY == mLabel.GetResizePolicy(Dimension::HEIGHT) )
245             {
246               mLabel.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT );
247             }
248             else
249             {
250               mLabel.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
251             }
252             break;
253           }
254           case KEY_H: // Horizontal alignment
255           {
256             if( ++mAlignment >= H_ALIGNMENT_STRING_COUNT )
257             {
258               mAlignment = 0u;
259             }
260
261             mLabel.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, H_ALIGNMENT_STRING_TABLE[ mAlignment ] );
262             break;
263           }
264           case KEY_V: // Vertical alignment
265           {
266             if( ++mAlignment >= V_ALIGNMENT_STRING_COUNT )
267             {
268               mAlignment = 0u;
269             }
270
271             mLabel.SetProperty( TextLabel::Property::VERTICAL_ALIGNMENT, V_ALIGNMENT_STRING_TABLE[ mAlignment ] );
272             break;
273           }
274           case KEY_M: // Multi-line
275           {
276             bool multiLine = mLabel.GetProperty<bool>( TextLabel::Property::MULTI_LINE );
277             mLabel.SetProperty( TextLabel::Property::MULTI_LINE, !multiLine );
278             break;
279           }
280           case KEY_L: // Language
281           {
282             const Language& language = LANGUAGES[ mLanguageId ];
283
284             mLabel.SetProperty( TextLabel::Property::TEXT, language.text );
285
286             if( ++mLanguageId >= NUMBER_OF_LANGUAGES )
287             {
288               mLanguageId = 0u;
289             }
290             break;
291           }
292           case KEY_S: // Shadow color
293           {
294             if( Color::BLACK == mLabel.GetProperty<Vector4>( TextLabel::Property::SHADOW_COLOR ) )
295             {
296               mLabel.SetProperty( TextLabel::Property::SHADOW_COLOR, Color::RED );
297             }
298             else
299             {
300               mLabel.SetProperty( TextLabel::Property::SHADOW_COLOR, Color::BLACK );
301             }
302             break;
303           }
304           case KEY_PLUS: // Increase shadow offset
305           {
306             mLabel.SetProperty( TextLabel::Property::SHADOW_OFFSET, mLabel.GetProperty<Vector2>( TextLabel::Property::SHADOW_OFFSET ) + Vector2( 1.0f, 1.0f ) );
307             break;
308           }
309           case KEY_MINUS: // Decrease shadow offset
310           {
311             mLabel.SetProperty( TextLabel::Property::SHADOW_OFFSET, mLabel.GetProperty<Vector2>( TextLabel::Property::SHADOW_OFFSET ) - Vector2( 1.0f, 1.0f ) );
312             break;
313           }
314
315         }
316       }
317     }
318   }
319
320 private:
321
322   Application& mApplication;
323
324   TextLabel mLabel;
325
326   Control mContainer;
327   Control mGrabCorner;
328
329   PanGestureDetector mPanGestureDetector;
330
331   Vector2 mLayoutSize;
332
333   unsigned int mLanguageId;
334   unsigned int mAlignment;
335   Property::Index mHueAngleIndex;
336   Property::Index mOverrideMixColorIndex;
337 };
338
339 void RunTest( Application& application )
340 {
341   TextLabelExample test( application );
342
343   application.MainLoop();
344 }
345
346 /** Entry point for Linux & Tizen applications */
347 int DALI_EXPORT_API main( int argc, char **argv )
348 {
349   Application application = Application::New( &argc, &argv, DEMO_THEME_PATH );
350
351   RunTest( application );
352
353   return 0;
354 }