8b6cf709f15a7bdd21f5d2aa77798bda9c3522a3
[platform/core/csapi/tizenfx.git] /
1 /*
2  * Copyright (c) 2019 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.ComponentBased.Common
21 {
22     /// <summary>
23     /// The class for supporting multi-components based application model.
24     /// </summary>
25     /// <since_tizen> 6 </since_tizen>
26     public abstract class ComponentBasedApplication : Application
27     {
28         private const string LogTag = "Tizen.Applications";
29         private Dictionary<Type, ComponentStateManger> _componentFactories = new Dictionary<Type, ComponentStateManger>();
30         private Interop.CBApplication.CBAppLifecycleCallbacks _callbacks;
31
32         /// <summary>
33         /// Initializes the ComponentBasedApplicationBase class.
34         /// </summary>
35         /// <param name="typeInfo">The component type information.
36         /// The key should be a class type of FrameComponent or SubComponent subclass.
37         /// The value should be a component id which is declared in tizen-manifest.xml.
38         /// </param>
39         /// <since_tizen> 6 </since_tizen>
40         public ComponentBasedApplication(IDictionary<Type, string> typeInfo)
41         {
42             _callbacks.OnInit = new Interop.CBApplication.CBAppInitCallback(OnInitNative);
43             _callbacks.OnFinished = new Interop.CBApplication.CBAppFiniCallback(OnFinishedNative);
44             _callbacks.OnRun = new Interop.CBApplication.CBAppRunCallback(OnRunNative);
45             _callbacks.OnExit = new Interop.CBApplication.CBAppExitCallback(OnExitNative);
46             _callbacks.OnCreate = new Interop.CBApplication.CBAppCreateCallback(OnCreateNative);
47             _callbacks.OnTerminate = new Interop.CBApplication.CBAppTerminateCallback(OnTerminateNative);
48
49             foreach (var component in typeInfo)
50             {
51                 RegisterComponent(component.Key, component.Value);
52             }
53         }
54
55         /// <summary>
56         /// Registers a component.
57         /// </summary>
58         /// <param name="compType">Class type</param>
59         /// <param name="compId">Component ID</param>
60         /// <exception cref="ArgumentException">Thrown when component type is already added or not sub-class of FrameComponent or ServiceComponent</exception>
61         /// <since_tizen> 6 </since_tizen>
62         public void RegisterComponent(Type compType, string compId)
63         {
64             if (_componentFactories.ContainsKey(compType))
65             {
66                 throw new ArgumentException("Already exist type");
67             }
68
69             foreach (var stateManager in _componentFactories)
70             {
71                 if (stateManager.Value.ComponentId == compId)
72                 {
73                     throw new ArgumentException("Already exist component ID(" + compId + ")");
74                 }
75             }
76
77             if (typeof(FrameComponent).IsAssignableFrom(compType))
78             {
79                 Log.Info(LogTag, "Add frame component");
80                 _componentFactories.Add(compType, new FrameComponentStateManager(compType, compId, this));
81             }
82             else if (typeof(ServiceComponent).IsAssignableFrom(compType))
83             {
84                 Log.Info(LogTag, "Add service component");
85                 _componentFactories.Add(compType, new ServiceComponentStateManager(compType, compId, this));
86             }
87             else if (typeof(WidgetComponent).IsAssignableFrom(compType))
88             {
89                 Log.Info(LogTag, "Add widget component");
90                 _componentFactories.Add(compType, new WidgetComponentStateManager(compType, compId, this));
91             }
92             else
93             {
94                 throw new ArgumentException("compType must be sub type of FrameComponent or ServiceComponent", "compType");
95             }
96         }
97
98         /// <summary>
99         /// Runs the application's main loop.
100         /// </summary>
101         /// <param name="args">Arguments from commandline.</param>
102         /// <exception cref="InvalidOperationException">Thrown when component type is already added to the component.</exception>
103         /// <since_tizen> 6 </since_tizen>
104         public override void Run(string[] args)
105         {
106             base.Run(args);
107
108             string[] argsClone = new string[args.Length + 1];
109             if (args.Length > 1)
110             {
111                 args.CopyTo(argsClone, 1);
112             }
113             argsClone[0] = string.Empty;
114
115             Interop.CBApplication.ErrorCode err = Interop.CBApplication.BaseMain(argsClone.Length, argsClone, ref _callbacks, IntPtr.Zero);
116             if (err != Interop.CBApplication.ErrorCode.None)
117             {
118                 Log.Error(LogTag, "Failed to run the application. Err = " + err);
119                 throw new InvalidOperationException("Fail to run application : err(" + err + ")");
120             }
121         }
122
123         /// <summary>
124         /// Exits the main loop of the application.
125         /// </summary>
126         /// <since_tizen> 6 </since_tizen>
127         public override void Exit()
128         {
129             Interop.CBApplication.BaseExit();
130         }
131
132         private IntPtr OnCreateNative(IntPtr data)
133         {
134             Log.Debug(LogTag, "On create");
135             IntPtr nativeComponentFactoryMap = IntPtr.Zero;
136             foreach (KeyValuePair<Type, ComponentStateManger> entry in _componentFactories)
137             {
138                 nativeComponentFactoryMap = entry.Value.Bind(nativeComponentFactoryMap);
139             }
140
141             return nativeComponentFactoryMap;
142         }
143
144         private void OnTerminateNative(IntPtr data)
145         {
146         }
147
148         private void OnRunNative(IntPtr data)
149         {
150             OnRun();
151         }
152
153         private void OnExitNative(IntPtr data)
154         {
155             OnExit();
156         }
157
158         private void OnInitNative(int argc, string[] argv, IntPtr userData)
159         {
160             OnInit(argv);
161         }
162
163         private void OnFinishedNative(IntPtr data)
164         {
165             OnFinished();
166         }
167
168         /// <summary>
169         /// This method will be called before running main-loop
170         /// </summary>
171         /// <param name="args"></param>
172         /// <since_tizen> 6 </since_tizen>
173         protected virtual void OnInit(string[] args)
174         {
175         }
176
177         /// <summary>
178         /// This method will be called after exiting main-loop
179         /// </summary>
180         /// <since_tizen> 6 </since_tizen>
181         protected virtual void OnFinished()
182         {
183         }
184
185         /// <summary>
186         /// This method will be called to start main-loop
187         /// </summary>
188         /// <since_tizen> 6 </since_tizen>
189         protected abstract void OnRun();
190
191         /// <summary>
192         /// This method will be called to exit main-loop
193         /// </summary>
194         /// <since_tizen> 6 </since_tizen>
195         protected virtual void OnExit()
196         {
197         }
198     }
199 }