06419e2685e44a7a60ab29ce086c42345b3cc38f
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / CustomView / Spin.cs
1 /*
2  * Copyright(c) 2017 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 Tizen.NUI;
21 using Tizen.NUI.UIComponents;
22 using Tizen.NUI.BaseComponents;
23
24 // A spin control (for continously changing values when users can easily predict a set of values)
25
26 namespace Tizen.NUI
27 {
28     ///<summary>
29     ///Spins the CustomView class.
30     /// </summary>
31     /// <since_tizen> 3 </since_tizen>
32     public class Spin : CustomView
33     {
34         private VisualBase _arrowVisual;
35         private TextField _textField;
36         private int _arrowVisualPropertyIndex;
37         private string _arrowImage;
38         private int _currentValue;
39         private int _minValue;
40         private int _maxValue;
41         private int _singleStep;
42         private bool _wrappingEnabled;
43         private int _pointSize;
44         private Color _textColor;
45         private Color _textBackgroundColor;
46         private int _maxTextLength;
47
48         // static constructor registers the control type (only runs once)
49         static Spin()
50         {
51             // ViewRegistry registers control type with DALi type registery
52             // also uses introspection to find any properties that need to be registered with type registry
53             CustomViewRegistry.Instance.Register(CreateInstance, typeof(Spin));
54         }
55
56         /// <summary>
57         /// Creates an initialized spin.
58         /// </summary>
59         /// <since_tizen> 3 </since_tizen>
60         public Spin() : base(typeof(Spin).FullName, CustomViewBehaviour.RequiresKeyboardNavigationSupport)
61         {
62         }
63
64         /// <summary>
65         /// Value to be set in the spin.
66         /// </summary>
67         /// <since_tizen> 3 </since_tizen>
68         [ScriptableProperty()]
69         // GetValue() is in BindableObject. It's different from this Value.
70         [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1721: Property names should not match get methods")]
71         public int Value
72         {
73             get
74             {
75                 return _currentValue;
76             }
77             set
78             {
79                 NUILog.Debug("Value set to " + value);
80                 _currentValue = value;
81
82                 // Make sure no invalid value is accepted
83                 if (_currentValue < _minValue)
84                 {
85                     _currentValue = _minValue;
86                 }
87
88                 if (_currentValue > _maxValue)
89                 {
90                     _currentValue = _maxValue;
91                 }
92
93                 _textField.Text = _currentValue.ToString();
94             }
95         }
96
97         /// <summary>
98         /// Minimum value of the spin value.
99         /// </summary>
100         /// <since_tizen> 3 </since_tizen>
101         [ScriptableProperty()]
102         public int MinValue
103         {
104             get
105             {
106                 return _minValue;
107             }
108             set
109             {
110                 _minValue = value;
111             }
112         }
113
114         /// <summary>
115         /// Maximum value of the spin value.
116         /// </summary>
117         /// <since_tizen> 3 </since_tizen>
118         [ScriptableProperty()]
119         public int MaxValue
120         {
121             get
122             {
123                 return _maxValue;
124             }
125             set
126             {
127                 _maxValue = value;
128             }
129         }
130
131         /// <summary>
132         /// Increasing, decreasing step of the spin value when up or down keys are pressed.
133         /// </summary>
134         /// <since_tizen> 3 </since_tizen>
135         [ScriptableProperty()]
136         public int Step
137         {
138             get
139             {
140                 return _singleStep;
141             }
142             set
143             {
144                 _singleStep = value;
145             }
146         }
147
148         /// <summary>
149         /// Wrapping enabled status.
150         /// </summary>
151         /// <since_tizen> 3 </since_tizen>
152         [ScriptableProperty()]
153         public bool WrappingEnabled
154         {
155             get
156             {
157                 return _wrappingEnabled;
158             }
159             set
160             {
161                 _wrappingEnabled = value;
162             }
163         }
164
165         /// <summary>
166         /// Text point size of the spin value.
167         /// </summary>
168         /// <since_tizen> 3 </since_tizen>
169         [ScriptableProperty()]
170         public int TextPointSize
171         {
172             get
173             {
174                 return _pointSize;
175             }
176             set
177             {
178                 _pointSize = value;
179                 _textField.PointSize = _pointSize;
180             }
181         }
182
183         /// <summary>
184         /// The color of the spin value.
185         /// </summary>
186         /// <since_tizen> 3 </since_tizen>
187         [ScriptableProperty()]
188         public Color TextColor
189         {
190             get
191             {
192                 return _textColor;
193             }
194             set
195             {
196                 if (value != null)
197                 {
198                     NUILog.Debug("TextColor set to " + value.R + "," + value.G + "," + value.B);
199                 }
200
201                 _textColor = value;
202                 _textField.TextColor = _textColor;
203             }
204         }
205
206         /// <summary>
207         /// Maximum text lengh of the spin value.
208         /// </summary>
209         /// <since_tizen> 3 </since_tizen>
210         [ScriptableProperty()]
211         public int MaxTextLength
212         {
213             get
214             {
215                 return _maxTextLength;
216             }
217             set
218             {
219                 _maxTextLength = value;
220                 _textField.MaxLength = _maxTextLength;
221             }
222         }
223
224         /// <summary>
225         /// Reference of TextField of the spin.
226         /// </summary>
227         /// <since_tizen> 3 </since_tizen>
228         public TextField SpinText
229         {
230             get
231             {
232                 return _textField;
233             }
234             set
235             {
236                 _textField = value;
237             }
238         }
239
240         /// <summary>
241         /// Show indicator image, for example, up or down arrow image.
242         /// </summary>
243         /// <since_tizen> 3 </since_tizen>
244         public string IndicatorImage
245         {
246             get
247             {
248                 return _arrowImage;
249             }
250             set
251             {
252                 _arrowImage = value;
253                 var ptMap = new PropertyMap();
254                 var temp = new PropertyValue((int)Visual.Type.Image);
255                 ptMap.Add(Visual.Property.Type, temp);
256                 temp.Dispose();
257
258                 temp = new PropertyValue(_arrowImage);
259                 ptMap.Add(ImageVisualProperty.URL, temp);
260                 temp.Dispose();
261
262                 temp = new PropertyValue(150);
263                 ptMap.Add(ImageVisualProperty.DesiredHeight, temp);
264                 temp.Dispose();
265
266                 temp = new PropertyValue(150);
267                 ptMap.Add(ImageVisualProperty.DesiredWidth, temp);
268                 temp.Dispose();
269
270                 _arrowVisual = VisualFactory.Instance.CreateVisual(ptMap);
271                 ptMap.Dispose();
272
273                 RegisterVisual(_arrowVisualPropertyIndex, _arrowVisual);
274             }
275         }
276
277         // Called by DALi Builder if it finds a Spin control in a JSON file
278         static CustomView CreateInstance()
279         {
280             return new Spin();
281         }
282
283         /// <summary>
284         /// Overrides the method of OnInitialize() for the CustomView class.<br />
285         /// This method is called after the control has been initialized.<br />
286         /// Derived classes should do any second phase initialization by overriding this method.<br />
287         /// </summary>
288         /// <since_tizen> 3 </since_tizen>
289         public override void OnInitialize()
290         {
291             // Initialize the propertiesControl
292             _arrowImage = Tizen.Applications.Application.Current.DirectoryInfo.Resource + "picture.png";
293             _textBackgroundColor = new Color(0.6f, 0.6f, 0.6f, 1.0f);
294             _currentValue = 0;
295             _minValue = 0;
296             _maxValue = 0;
297             _singleStep = 1;
298             _maxTextLength = 0;
299
300             // Create image visual for the arrow keys
301             var temp = new PropertyValue(_arrowImage);
302             _arrowVisualPropertyIndex = RegisterProperty("ArrowImage", temp, Tizen.NUI.PropertyAccessMode.ReadWrite);
303             temp.Dispose();
304
305             var ptMap = new PropertyMap();
306             temp = new PropertyValue((int)Visual.Type.Image);
307             ptMap.Add(Visual.Property.Type, temp);
308             temp.Dispose();
309
310             temp = new PropertyValue(_arrowImage);
311             ptMap.Add(ImageVisualProperty.URL, temp);
312             temp.Dispose();
313
314             temp = new PropertyValue(150);
315             ptMap.Add(ImageVisualProperty.DesiredHeight, temp);
316             temp.Dispose();
317
318             temp = new PropertyValue(150);
319             ptMap.Add(ImageVisualProperty.DesiredWidth, temp);
320             temp.Dispose();
321
322             _arrowVisual = VisualFactory.Instance.CreateVisual(ptMap);
323             ptMap.Dispose();
324             RegisterVisual(_arrowVisualPropertyIndex, _arrowVisual);
325
326             // Create a text field
327             _textField = new TextField();
328             _textField.PivotPoint = Tizen.NUI.PivotPoint.Center;
329             _textField.WidthResizePolicy = ResizePolicyType.SizeRelativeToParent;
330             _textField.HeightResizePolicy = ResizePolicyType.SizeRelativeToParent;
331             _textField.SizeModeFactor = new Vector3(1.0f, 0.45f, 1.0f);
332             _textField.PlaceholderText = "----";
333             _textField.BackgroundColor = _textBackgroundColor;
334             _textField.HorizontalAlignment = HorizontalAlignment.Center;
335             _textField.VerticalAlignment = VerticalAlignment.Center;
336             _textField.Focusable = (true);
337             _textField.Name = "_textField";
338             _textField.Position2D = new Position2D(0, 40);
339
340             this.Add(_textField);
341
342             _textField.FocusGained += TextFieldKeyInputFocusGained;
343             _textField.FocusLost += TextFieldKeyInputFocusLost;
344         }
345
346         /// <summary>
347         /// Overrides the method of GetNaturalSize() for the CustomView class.<br />
348         /// Returns the natural size of the actor.<br />
349         /// </summary>
350         /// <returns> Natural size of this spin itself.</returns>
351         /// <since_tizen> 3 </since_tizen>
352         public override Size2D GetNaturalSize()
353         {
354             return new Size2D(150, 150);
355         }
356
357         /// <summary>
358         /// An event handler is used when the TextField in the spin gets the key focus.<br />
359         /// Make sure when the current spin that takes input focus, also takes the keyboard focus.<br />
360         /// For example, when you tap the spin directly.<br />
361         /// </summary>
362         /// <param name="source">Sender of this event.</param>
363         /// <param name="e">Event arguments.</param>
364         /// <since_tizen> 3 </since_tizen>
365         public void TextFieldKeyInputFocusGained(object source, EventArgs e)
366         {
367             FocusManager.Instance.SetCurrentFocusView(_textField);
368         }
369
370         /// <summary>
371         /// An event handler when the TextField in the spin looses it's key focus.
372         /// </summary>
373         /// <param name="source"></param>
374         /// <param name="e"></param>
375         /// <since_tizen> 3 </since_tizen>
376         public void TextFieldKeyInputFocusLost(object source, EventArgs e)
377         {
378             int previousValue = _currentValue;
379
380             // If the input value is invalid, change it back to the previous valid value
381             if (int.TryParse(_textField.Text, out _currentValue))
382             {
383                 if (_currentValue < _minValue || _currentValue > _maxValue)
384                 {
385                     _currentValue = previousValue;
386                 }
387             }
388             else
389             {
390                 _currentValue = previousValue;
391             }
392
393             // Otherwise take the new value
394             this.Value = _currentValue;
395         }
396
397         /// <summary>
398         /// Overrides the method of GetNextKeyboardFocusableView() for the CustomView class.<br />
399         /// Gets the next key focusable view in this view towards the given direction.<br />
400         /// A view needs to override this function in order to support two-dimensional key navigation.<br />
401         /// </summary>
402         /// <param name="currentFocusedView">The current focused view.</param>
403         /// <param name="direction">The direction to move the focus towards.</param>
404         /// <param name="loopEnabled">Whether the focus movement should be looped within the control.</param>
405         /// <returns>The next keyboard focusable view in this control or an empty handle if no view can be focused.</returns>
406         /// <since_tizen> 3 </since_tizen>
407         public override View GetNextFocusableView(View currentFocusedView, View.FocusDirection direction, bool loopEnabled)
408         {
409             // Respond to Up/Down keys to change the value while keeping the current spin focused
410             View nextFocusedView = currentFocusedView;
411             if (direction == View.FocusDirection.Up)
412             {
413                 this.Value += this.Step;
414                 nextFocusedView = _textField;
415             }
416             else if (direction == View.FocusDirection.Down)
417             {
418                 this.Value -= this.Step;
419                 nextFocusedView = _textField;
420             }
421             else
422             {
423                 // Return null
424                 return null;
425             }
426
427             return nextFocusedView;
428         }
429     }
430 }