1a0dbde152d59beb2ad39ea3827769237fb725b0
[platform/core/csapi/tizenfx.git] / src / Tizen.Applications.WatchfaceComplication / Tizen.Applications / EditablesContainer.cs
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
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 using System;
18 using System.Collections.Generic;
19
20 namespace Tizen.Applications.WatchfaceComplication
21 {
22     /// <summary>
23     /// Represents the EditablesContainer class for the watch application.
24     /// </summary>
25     /// <since_tizen> 6 </since_tizen>
26     public abstract class EditablesContainer : IDisposable
27     {
28         internal IList<DesignElement> _deList = new List<DesignElement>();
29         internal IList<Complication> _compList = new List<Complication>();
30         internal IntPtr _container = IntPtr.Zero;
31         private Interop.WatchfaceComplication.EditableUpdateRequestedCallback _editableUpdatedCallback;
32         private bool _disposed = false;
33         private static string _logTag = "WatchfaceComplication";
34
35         /// <summary>
36         /// Initializes the EditablesContainer class.
37         /// </summary>
38         /// <exception cref="ArgumentException">Thrown when some parameter are invalid.</exception>
39         /// <exception cref="InvalidOperationException">Thrown when the method failed due to invalid operation.</exception>
40         /// <exception cref="NotSupportedException">Thrown when the watchface complication is not supported.</exception>
41         /// <since_tizen> 6 </since_tizen>
42         protected EditablesContainer()
43         {
44             ComplicationError err = Interop.WatchfaceComplication.AddEditReadyCallback(EditReady, IntPtr.Zero);
45             if (err != ComplicationError.None)
46                 ErrorFactory.ThrowException(err, "Fail to add edit ready callback");
47             Log.Debug(_logTag, "Edit container ready");
48         }
49
50         /// <summary>
51         /// Destructor of the EditablesContainer class.
52         /// </summary>
53         ~EditablesContainer()
54         {
55             Dispose(false);
56         }
57
58         /// <summary>
59         /// Adds the DesignElement to edit list.
60         /// </summary>
61         /// <param name="de">The DesignElement object.</param>
62         /// <param name="editableId">The editable id.</param>
63         /// <exception cref="ArgumentException">Thrown when the invalid parameter is passed.</exception>
64         /// <exception cref="InvalidOperationException">Thrown when the method failed due to invalid operation.</exception>
65         /// <since_tizen> 6 </since_tizen>
66         public void Add(DesignElement de, int editableId)
67         {
68             if (de == null)
69                 ErrorFactory.ThrowException(ComplicationError.InvalidParam);
70             if (IsExist(editableId))
71                 ErrorFactory.ThrowException(ComplicationError.ExistID);
72
73             IEditable e = de;
74             e.EditableId = editableId;
75             _deList.Add(de);
76         }
77
78         /// <summary>
79         /// Adds the Complication to edit list.
80         /// </summary>
81         /// <param name="comp">The Complication object.</param>
82         /// <param name="editableId">The editable id.</param>
83         /// <exception cref="ArgumentException">Thrown when the invalid parameter is passed.</exception>
84         /// <exception cref="InvalidOperationException">Thrown when the method failed due to invalid operation.</exception>
85         /// <since_tizen> 6 </since_tizen>
86         public void Add(Complication comp, int editableId)
87         {
88             if (comp == null)
89                 ErrorFactory.ThrowException(ComplicationError.InvalidParam);
90             if (IsExist(editableId))
91                 ErrorFactory.ThrowException(ComplicationError.ExistID);
92
93             IEditable e = comp;
94             e.EditableId = editableId;
95             _compList.Add(comp);
96         }
97
98         /// <summary>
99         /// Removes the editable from edit list.
100         /// </summary>
101         /// <param name="editableId">The editable id.</param>
102         /// <exception cref="ArgumentException">Thrown when the invalid parameter is passed.</exception>
103         /// <example>
104         /// <code>
105         /// if (myContainer.IsExist(_colorEditId)
106         ///     myContainer.Remove(_colorEditId);
107         /// </code>
108         /// </example>
109         /// <since_tizen> 6 </since_tizen>
110         public void Remove(int editableId)
111         {
112             foreach (DesignElement de in _deList)
113             {
114                 if (((IEditable)de).EditableId == editableId)
115                 {
116                     _deList.Remove(de);
117                     return;
118                 }
119             }
120
121             foreach (Complication comp in _compList)
122             {
123                 if (((IEditable)comp).EditableId == editableId)
124                 {
125                     _compList.Remove(comp);
126                     return;
127                 }
128             }
129
130             ErrorFactory.ThrowException(ComplicationError.InvalidParam, "invalid editable ID");
131         }
132
133         internal IEditable GetEditable(int editableId)
134         {
135             foreach (IEditable ed in _deList)
136             {
137                 if (ed.EditableId == editableId)
138                     return ed;
139             }
140
141             foreach (IEditable ed in _compList)
142             {
143                 if (ed.EditableId == editableId)
144                     return ed;
145             }
146
147             return null;
148         }
149
150         internal DesignElement GetDesignElement(int editableId)
151         {
152             foreach (DesignElement de in _deList)
153             {
154                 IEditable ed = de;
155                 if (ed.EditableId == editableId)
156                     return de;
157             }
158
159             return null;
160         }
161
162         /// <summary>
163         /// Checks the editable with editableId is already exists in edit list.
164         /// </summary>
165         /// <param name="editableId">The target editable Id.</param>
166         /// <returns>true if the editable is already exists in edit list, otherwise false</returns>
167         /// <since_tizen> 6 </since_tizen>
168         public bool IsExist(int editableId)
169         {
170             return (GetEditable(editableId) != null);
171         }
172
173         private void EditReady(IntPtr container, string editorAppid, IntPtr userData)
174         {
175             OnEditReady(editorAppid);
176         }
177
178
179         private void EditableUpdatedCallback(IntPtr handle, int selectedIdx,
180             int state, IntPtr userData)
181         {
182             int editableId;
183             ComplicationError err = Interop.WatchfaceComplication.GetEditableId(handle, out editableId);
184             if (err != ComplicationError.None)
185                 ErrorFactory.ThrowException(err, "fail to get current index");
186
187             int currentIdx;
188             err = Interop.WatchfaceComplication.GetCurrentIdx(handle, out currentIdx);
189             if (err != ComplicationError.None)
190                 ErrorFactory.ThrowException(err, "fail to get current index");
191
192             DesignElement de = GetDesignElement(editableId);
193             if (de != null)
194             {
195                 de.SetCurrentDataIndex(currentIdx);
196                 de.NotifyUpdate(currentIdx, (State)state);
197             }
198         }
199
200         /// <summary>
201         /// Requests edit to editor application.
202         /// </summary>
203         /// <privilege>http://tizen.org/privilege/datasharing</privilege>
204         /// <exception cref="InvalidOperationException">Thrown when the method failed due to invalid operation.</exception>
205         /// <exception cref="NotSupportedException">Thrown when the watchface complication is not supported.</exception>
206         /// <exception cref="UnauthorizedAccessException">Thrown when the application does not have privilege to access this method.</exception>
207         /// <example>
208         /// <code>
209         /// public class MyContainer : EditablesContainer {
210         ///     public MyContainer() : base()
211         ///     {
212         ///     }
213         ///     protected override void OnEditReady(string editorId)
214         ///     {
215         ///         this.RequestEdit();
216         ///     }
217         /// }
218         /// </code>
219         /// </example>
220         /// <since_tizen> 6 </since_tizen>
221         public void RequestEdit()
222         {
223             Log.Debug(_logTag, "request edit");
224             ComplicationError ret;
225
226             Interop.WatchfaceComplication.GetEditableContainer(out _container);
227             if (_container == IntPtr.Zero)
228             {
229                 ErrorFactory.ThrowException(ComplicationError.EditNotReady, "Editor not ready");
230             }
231
232             if (_editableUpdatedCallback == null)
233                 _editableUpdatedCallback = new Interop.WatchfaceComplication.EditableUpdateRequestedCallback(EditableUpdatedCallback);
234
235             foreach (Complication comp in _compList)
236             {
237                 IEditable e = comp;
238                 IntPtr hi = IntPtr.Zero;
239                 if (e.Highlight != null && e.Highlight.Raw != IntPtr.Zero)
240                     hi = e.Highlight.Raw;
241                 Interop.WatchfaceComplication.AddComplication(_container, e.EditableId, comp._handle, hi);
242             }
243
244             foreach (DesignElement de in _deList)
245             {
246                 IEditable e = de;
247                 IntPtr candidates;
248                 Interop.WatchfaceComplication.CreateCandidatesList(out candidates);
249                 foreach (Bundle b in de.Candidates)
250                 {
251                     Interop.WatchfaceComplication.AddCandidatesListItem(candidates, b.SafeBundleHandle);
252                 }
253
254                 IntPtr hi = IntPtr.Zero;
255                 if (e.Highlight != null && e.Highlight.Raw != IntPtr.Zero)
256                     hi = e.Highlight.Raw;
257                 Interop.WatchfaceComplication.AddDesignElement(_container, e.EditableId, e.GetCurrentDataIndex(), candidates, hi, e.Name);
258                 Log.Debug(_logTag, "Add design element done :" + e.Name);
259             }
260
261             ret = Interop.WatchfaceComplication.RequestEdit(_container, _editableUpdatedCallback, IntPtr.Zero);
262             if (ret != ComplicationError.None)
263             {
264                 ErrorFactory.ThrowException(ret, "Request edit fail");
265             }
266         }
267
268         /// <summary>
269         /// Overrides this method if you want to handle the behavior when the editor is ready to edit.
270         /// </summary>
271         /// <param name="editorId">The appid of ready to edit editor.</param>
272         /// <since_tizen> 6 </since_tizen>
273         protected abstract void OnEditReady(string editorId);
274
275         /// <summary>
276         /// Loads the editable's current data.
277         /// </summary>
278         /// <returns>The editable's latest data that selected by editor.</returns>
279         /// <exception cref="ArgumentException">Thrown when some parameter are invalid.</exception>
280         /// <exception cref="InvalidOperationException">Thrown when the method failed due to invalid operation.</exception>
281         /// <exception cref="NotSupportedException">Thrown when the watchface complication is not supported.</exception>
282         /// <remarks>
283         /// This API loads editable's last current data which is updated by editor application.
284         /// </remarks>
285         /// <param name="editableId">The id of the editable.</param>
286         /// <example>
287         /// <code>
288         /// internal void InitEditables()
289         /// {
290         ///     _container = new MyContainer();
291         ///     Bundle curData = EditablesContainer.LoadCurrentData(_colorEditId);
292         ///     List&lt;Bundle&gt; candidatesList = new List&lt;Bundle&gt;();
293         ///     int curIdx = 0;
294         ///     int i = 0;
295         ///     foreach (string str in _colorArr)
296         ///     {
297         ///         Bundle data = new Bundle();
298         ///         data.AddItem(_colorKey, str);
299         ///         candidatesList.Add(data);
300         ///         if (curData != null &amp;&amp; curData.GetItem(_colorKey) != null
301         ///             &amp;&amp; curData.GetItem(_colorKey).Equals(str))
302         ///         {
303         ///             curIdx = i;
304         ///         }
305         ///         i++;
306         ///    }
307         ///    ColorDesign colorEdit = new ColorDesign(candidatesList, curIdx, "COLOR", _complicationBtn);
308         ///    colorEdit.Highlight = new Highlight(ShapeType.Circle, 0, 40, 10, 10);
309         ///    _container.Add(colorEdit, _colorEditId);
310         /// }
311         /// </code>
312         /// </example>
313         /// <since_tizen> 6 </since_tizen>
314         public static Bundle LoadCurrentData(int editableId)
315         {
316             SafeBundleHandle handle;
317             ComplicationError err = Interop.WatchfaceComplication.LoadCurrentData(editableId, out handle);
318             if (err == ComplicationError.None)
319                 return new Bundle(handle);
320
321             return null;
322         }
323
324         /// <summary>
325         /// Releases the unmanaged resources used by the EditablesContainer class specifying whether to perform a normal dispose operation.
326         /// </summary>
327         /// <param name="disposing">true for a normal dispose operation; false to finalize the handle.</param>
328         /// <since_tizen> 3 </since_tizen>
329         protected virtual void Dispose(bool disposing)
330         {
331             if (!_disposed)
332             {
333                 Interop.WatchfaceComplication.RemoveEditReadyCallback(EditReady);
334                 _disposed = true;
335             }
336         }
337
338         /// <summary>
339         /// Releases all resources used by the EditablesContainer class.
340         /// </summary>
341         /// <since_tizen> 3 </since_tizen>
342         public void Dispose()
343         {
344             Dispose(true);
345             GC.SuppressFinalize(this);
346         }
347     };
348 }