[Tizen.Applications.ComponentBased][TCSACR-265][Add] Add ComponentBased application...
[platform/core/csapi/tizenfx.git] / src / Tizen.Applications.ComponentBased / Tizen.Applications.ComponentBased.Common / ComponentBasedApplication.cs
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.ComponentBasedApplicationBase";
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             if (typeof(FrameComponent).IsAssignableFrom(compType))
70             {
71                 Log.Info(LogTag, "Add frame component");
72                 _componentFactories.Add(compType, new FrameComponentStateManager(compType, compId, this));
73             }
74             else if (typeof(ServiceComponent).IsAssignableFrom(compType))
75             {
76                 Log.Info(LogTag, "Add service component");
77                 _componentFactories.Add(compType, new ServiceComponentStateManager(compType, compId, this));
78             }
79             else
80             {
81                 throw new ArgumentException("compType must be sub type of FrameComponent or ServiceComponent", "compType");
82             }
83         }
84
85         /// <summary>
86         /// Runs the application's main loop.
87         /// </summary>
88         /// <param name="args">Arguments from commandline.</param>
89         /// <exception cref="InvalidOperationException">Thrown when component type is already added to the component.</exception>
90         /// <since_tizen> 6 </since_tizen>
91         public override void Run(string[] args)
92         {
93             base.Run(args);
94
95             string[] argsClone = new string[args.Length + 1];
96             if (args.Length > 1)
97             {
98                 args.CopyTo(argsClone, 1);
99             }
100             argsClone[0] = string.Empty;
101
102             Interop.CBApplication.ErrorCode err = Interop.CBApplication.BaseMain(argsClone.Length, argsClone, ref _callbacks, IntPtr.Zero);
103             if (err != Interop.CBApplication.ErrorCode.None)
104             {
105                 Log.Error(LogTag, "Failed to run the application. Err = " + err);
106                 throw new InvalidOperationException("Fail to run application : err(" + err + ")");
107             }
108         }
109
110         /// <summary>
111         /// Exits the main loop of the application.
112         /// </summary>
113         /// <since_tizen> 6 </since_tizen>
114         public override void Exit()
115         {
116             Interop.CBApplication.BaseExit();
117         }
118
119         private IntPtr OnCreateNative(IntPtr data)
120         {
121             Log.Debug(LogTag, "On create");
122             IntPtr nativeComponentFactoryMap = IntPtr.Zero;
123             foreach (KeyValuePair<Type, ComponentStateManger> entry in _componentFactories)
124             {
125                 nativeComponentFactoryMap = entry.Value.Bind(nativeComponentFactoryMap);
126             }
127
128             return nativeComponentFactoryMap;
129         }
130
131         private void OnTerminateNative(IntPtr data)
132         {
133         }
134
135         private void OnRunNative(IntPtr data)
136         {
137             OnRun();
138         }
139
140         private void OnExitNative(IntPtr data)
141         {
142             OnExit();
143         }
144
145         private void OnInitNative(int argc, string[] argv, IntPtr userData)
146         {
147             OnInit(argv);
148         }
149
150         private void OnFinishedNative(IntPtr data)
151         {
152             OnFinished();
153         }
154
155         /// <summary>
156         /// This method will be called before running main-loop
157         /// </summary>
158         /// <param name="args"></param>
159         /// <since_tizen> 6 </since_tizen>
160         protected virtual void OnInit(string[] args)
161         {
162         }
163
164         /// <summary>
165         /// This method will be called after exiting main-loop
166         /// </summary>
167         /// <since_tizen> 6 </since_tizen>
168         protected virtual void OnFinished()
169         {
170         }
171
172         /// <summary>
173         /// This method will be called to start main-loop
174         /// </summary>
175         /// <since_tizen> 6 </since_tizen>
176         protected abstract void OnRun();
177
178         /// <summary>
179         /// This method will be called to exit main-loop
180         /// </summary>
181         /// <since_tizen> 6 </since_tizen>
182         protected virtual void OnExit()
183         {
184         }
185     }
186 }