Dali C# binding - Implement the pure C# classes
[platform/core/uifw/dali-toolkit.git] / plugins / dali-swig / examples / spin-control.cs
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 using System;
19 using System.Runtime.InteropServices;
20 using Dali;
21
22 namespace MyCSharpExample
23 {
24     // A spin control (for continously changing values when users can easily predict a set of values)
25     class Spin : CustomView
26     {
27         private VisualBase _arrowVisual;
28         private TextField _textField;
29         private int _arrowVisualPropertyIndex;
30         private string _arrowImage;
31         private int _currentValue;
32         private int _minValue;
33         private int _maxValue;
34         private int _singleStep;
35         private bool _wrappingEnabled;
36         private string _fontFamily;
37         private string _fontStyle;
38         private int _pointSize;
39         private Color _textColor;
40         private Color _textBackgroundColor;
41         private int _maxTextLength;
42
43         public Spin() : base(ViewWrapperImpl.CustomViewBehaviour.REQUIRES_KEYBOARD_NAVIGATION_SUPPORT | ViewWrapperImpl.CustomViewBehaviour.DISABLE_STYLE_CHANGE_SIGNALS)
44         {
45         }
46
47         public override void OnInitialize()
48         {
49             // Initialize the properties
50             _arrowImage = "./images/arrow.png";
51             _textBackgroundColor = new Color(0.6f, 0.6f, 0.6f, 1.0f);
52             _currentValue = 0;
53             _minValue = 0;
54             _maxValue = 0;
55             _singleStep = 1;
56             _maxTextLength = 0;
57
58             // Create image visual for the arrow keys
59             _arrowVisualPropertyIndex = RegisterProperty("ArrowImage", new Dali.Property.Value(_arrowImage), Dali.Property.AccessMode.READ_WRITE);
60             _arrowVisual =  VisualFactory.Get().CreateVisual( _arrowImage, new Uint16Pair(150, 150) );
61             RegisterVisual( _arrowVisualPropertyIndex, _arrowVisual );
62
63             // Create a text field
64             _textField = new TextField();
65             _textField.ParentOrigin = NDalic.ParentOriginCenter;
66             _textField.AnchorPoint = NDalic.AnchorPointCenter;
67             _textField.WidthResizePolicy = "SIZE_RELATIVE_TO_PARENT";
68             _textField.HeightResizePolicy = "SIZE_RELATIVE_TO_PARENT";
69             _textField.SizeModeFactor = new Vector3( 1.0f, 0.45f, 1.0f );
70             _textField.PlaceholderText = "----";
71             _textField.BackgroundColor = _textBackgroundColor;
72             _textField.HorizontalAlignment = "Center";
73             _textField.VerticalAlignment = "Center";
74             _textField.SetKeyboardFocusable(true);
75             _textField.Name = "_textField";
76
77             this.Add(_textField);
78
79             _textField.KeyInputFocusGained += TextFieldKeyInputFocusGained;
80             _textField.KeyInputFocusLost += TextFieldKeyInputFocusLost;
81         }
82
83         public override Vector3 GetNaturalSize()
84         {
85             return new Vector3(150.0f, 150.0f, 0.0f);
86         }
87
88         public void TextFieldKeyInputFocusGained(object source, KeyInputFocusGainedEventArgs e)
89         {
90             // Make sure when the current spin that takes input focus also takes the keyboard focus
91             // For example, when you tap the spin directly
92             KeyboardFocusManager.Get().SetCurrentFocusActor(_textField);
93         }
94
95         public void TextFieldKeyInputFocusLost(object source, KeyInputFocusLostEventArgs e)
96         {
97             int previousValue = _currentValue;
98
99             // If the input value is invalid, change it back to the previous valid value
100             if(int.TryParse(_textField.Text, out _currentValue))
101             {
102                 if (_currentValue < _minValue || _currentValue > _maxValue)
103                 {
104                     _currentValue = previousValue;
105                 }
106             }
107             else
108             {
109                 _currentValue = previousValue;
110             }
111
112             // Otherwise take the new value
113             this.Value = _currentValue;
114         }
115
116         public override Actor GetNextKeyboardFocusableActor(Actor currentFocusedActor, View.KeyboardFocus.Direction direction, bool loopEnabled)
117         {
118             // Respond to Up/Down keys to change the value while keeping the current spin focused
119             Actor nextFocusedActor = currentFocusedActor;
120             if (direction == View.KeyboardFocus.Direction.UP)
121             {
122                 this.Value += this.Step;
123                 nextFocusedActor = _textField;
124             }
125             else if (direction == View.KeyboardFocus.Direction.DOWN)
126             {
127                 this.Value -= this.Step;
128                 nextFocusedActor = _textField;
129             }
130             else
131             {
132                 // Return a native empty handle as nothing can be focused in the left or right
133                 nextFocusedActor = new Actor();
134                 nextFocusedActor.Reset();
135             }
136
137             return nextFocusedActor;
138         }
139
140         // Value property of type int:
141         public int Value
142         {
143             get
144             {
145                 return _currentValue;
146             }
147             set
148             {
149                 _currentValue = value;
150
151                 // Make sure no invalid value is accepted
152                 if (_currentValue < _minValue)
153                 {
154                     _currentValue = _minValue;
155                 }
156
157                 if (_currentValue > _maxValue)
158                 {
159                     _currentValue = _maxValue;
160                 }
161
162                 _textField.Text = _currentValue.ToString();
163             }
164         }
165
166         // MinValue property of type int:
167         public int MinValue
168         {
169             get
170             {
171                 return _minValue;
172             }
173             set
174             {
175               _minValue = value;
176             }
177         }
178
179         // MaxValue property of type int:
180         public int MaxValue
181         {
182             get
183             {
184                 return _maxValue;
185             }
186             set
187             {
188               _maxValue = value;
189             }
190         }
191
192         // Step property of type int:
193         public int Step
194         {
195             get
196             {
197                 return _singleStep;
198             }
199             set
200             {
201               _singleStep = value;
202             }
203         }
204
205         // WrappingEnabled property of type bool:
206         public bool WrappingEnabled
207         {
208             get
209             {
210                 return _wrappingEnabled;
211             }
212             set
213             {
214               _wrappingEnabled = value;
215             }
216         }
217
218         // TextPointSize property of type int:
219         public int TextPointSize
220         {
221             get
222             {
223                 return _pointSize;
224             }
225             set
226             {
227               _pointSize = value;
228               _textField.PointSize = _pointSize;
229             }
230         }
231
232         // TextColor property of type Color:
233         public Color TextColor
234         {
235             get
236             {
237                 return _textColor;
238             }
239             set
240             {
241               _textColor = value;
242               _textField.TextColor = _textColor;
243             }
244         }
245
246         // MaxTextLength property of type int:
247         public int MaxTextLength
248         {
249             get
250             {
251                 return _maxTextLength;
252             }
253             set
254             {
255                 _maxTextLength = value;
256                 _textField.MaxLength = _maxTextLength;
257             }
258         }
259
260         public TextField SpinText
261         {
262             get
263             {
264                 return _textField;
265             }
266             set
267             {
268                 _textField = value;
269             }
270         }
271
272         // Indicator property of type string:
273         public string IndicatorImage
274         {
275             get
276             {
277                 return _arrowImage;
278             }
279             set
280             {
281               _arrowImage = value;
282               _arrowVisual =  VisualFactory.Get().CreateVisual( _arrowImage, new Uint16Pair(150, 150) );
283               RegisterVisual( _arrowVisualPropertyIndex, _arrowVisual );
284             }
285         }
286     }
287
288     class Example
289     {
290         private Dali.Application _application;
291         private FlexContainer _container;
292         private Spin _spinYear;
293         private Spin _spinMonth;
294         private Spin _spinDay;
295
296         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
297         delegate void CallbackDelegate();
298
299         public Example(Dali.Application application)
300         {
301             _application = application;
302             _application.Initialized += Initialize;
303         }
304
305         public void Initialize(object source, AUIApplicationInitEventArgs e)
306         {
307             Stage stage = Stage.GetCurrent();
308             stage.BackgroundColor = Color.White;
309
310             // Create a container for the spins
311             _container = new FlexContainer();
312
313             _container.ParentOrigin = NDalic.ParentOriginCenter;
314             _container.AnchorPoint = NDalic.AnchorPointCenter;
315             _container.FlexDirection = (int)FlexContainer.FlexDirectionType.ROW;
316             _container.Size = new Vector3(480.0f, 150.0f, 0.0f);
317
318             stage.Add(_container);
319
320             // Create a Spin control for year
321             _spinYear = new Spin();
322             _spinYear.ParentOrigin = NDalic.ParentOriginCenter;
323             _spinYear.AnchorPoint = NDalic.AnchorPointCenter;
324             _spinYear.Flex = 0.3f;
325             _spinYear.FlexMargin = new Vector4(5.0f, 0.0f, 5.0f, 0.0f);
326             _container.Add(_spinYear);
327
328             _spinYear.MinValue = 1900;
329             _spinYear.MaxValue = 2100;
330             _spinYear.Value = 2016;
331             _spinYear.Step = 1;
332             _spinYear.MaxTextLength = 4;
333             _spinYear.TextPointSize = 26;
334             _spinYear.TextColor = Color.White;
335             _spinYear.SetKeyboardFocusable(true);
336             _spinYear.Name = "_spinYear";
337
338             // Create a Spin control for month
339             _spinMonth = new Spin();
340             _spinMonth.ParentOrigin = NDalic.ParentOriginCenter;
341             _spinMonth.AnchorPoint = NDalic.AnchorPointCenter;
342             _spinMonth.Flex = 0.3f;
343             _spinMonth.FlexMargin = new Vector4(5.0f, 0.0f, 5.0f, 0.0f);
344             _container.Add(_spinMonth);
345
346             _spinMonth.MinValue = 1;
347             _spinMonth.MaxValue = 12;
348             _spinMonth.Value = 10;
349             _spinMonth.Step = 1;
350             _spinMonth.MaxTextLength = 2;
351             _spinMonth.TextPointSize = 26;
352             _spinMonth.TextColor = Color.White;
353             _spinMonth.SetKeyboardFocusable(true);
354             _spinMonth.Name = "_spinMonth";
355
356             // Create a Spin control for day
357             _spinDay = new Spin();
358             _spinDay.ParentOrigin = NDalic.ParentOriginCenter;
359             _spinDay.AnchorPoint = NDalic.AnchorPointCenter;
360             _spinDay.Flex = 0.3f;
361             _spinDay.FlexMargin = new Vector4(5.0f, 0.0f, 5.0f, 0.0f);
362             _container.Add(_spinDay);
363
364             _spinDay.MinValue = 1;
365             _spinDay.MaxValue = 31;
366             _spinDay.Value = 26;
367             _spinDay.Step = 1;
368             _spinDay.MaxTextLength = 2;
369             _spinDay.TextPointSize = 26;
370             _spinDay.TextColor = Color.White;
371             _spinDay.SetKeyboardFocusable(true);
372             _spinDay.Name = "_spinDay";
373
374             KeyboardFocusManager keyboardFocusManager = KeyboardFocusManager.Get();
375             keyboardFocusManager.PreFocusChange += OnKeyboardPreFocusChange;
376             keyboardFocusManager.FocusedActorEnterKeyPressed += OnFocusedActorEnterKeyPressed;
377
378         }
379
380         private Actor OnKeyboardPreFocusChange(object source, KeyboardFocusManager.PreFocusChangeEventArgs e)
381         {
382             Actor nextFocusActor = e.Proposed;
383
384             // When nothing has been focused initially, focus the text field in the first spin
385             if (!e.Current && !e.Proposed)
386             {
387                 nextFocusActor = _spinYear.SpinText;
388             }
389             else if(e.Direction == View.KeyboardFocus.Direction.LEFT)
390             {
391                 // Move the focus to the spin in the left of the current focused spin
392                 if(e.Current == _spinMonth.SpinText)
393                 {
394                     nextFocusActor = _spinYear.SpinText;
395                 }
396                 else if(e.Current == _spinDay.SpinText)
397                 {
398                     nextFocusActor = _spinMonth.SpinText;
399                 }
400             }
401             else if(e.Direction == View.KeyboardFocus.Direction.RIGHT)
402             {
403                 // Move the focus to the spin in the right of the current focused spin
404                 if(e.Current == _spinYear.SpinText)
405                 {
406                     nextFocusActor = _spinMonth.SpinText;
407                 }
408                 else if(e.Current == _spinMonth.SpinText)
409                 {
410                     nextFocusActor = _spinDay.SpinText;
411                 }
412             }
413
414             return nextFocusActor;
415         }
416
417         private void OnFocusedActorEnterKeyPressed(object source, KeyboardFocusManager.FocusedActorEnterKeyEventArgs e)
418         {
419             // Make the text field in the current focused spin to take the key input
420             KeyInputFocusManager manager = KeyInputFocusManager.Get();
421
422             if (e.Actor == _spinYear.SpinText)
423             {
424                 if (manager.GetCurrentFocusControl() != _spinYear.SpinText)
425                 {
426                     manager.SetFocus(_spinYear.SpinText);
427                 }
428             }
429             else if (e.Actor == _spinMonth.SpinText)
430             {
431                 if (manager.GetCurrentFocusControl() != _spinMonth.SpinText)
432                 {
433                     manager.SetFocus(_spinMonth.SpinText);
434                 }
435             }
436             else if (e.Actor == _spinDay.SpinText)
437             {
438                 if (manager.GetCurrentFocusControl() != _spinDay.SpinText)
439                 {
440                     manager.SetFocus(_spinDay.SpinText);
441                 }
442             }
443         }
444
445         public void MainLoop()
446         {
447             _application.MainLoop ();
448         }
449
450         /// <summary>
451         /// The main entry point for the application.
452         /// </summary>
453         [STAThread]
454         static void Main(string[] args)
455         {
456             Example example = new Example(Application.NewApplication());
457             example.MainLoop ();
458         }
459     }
460 }