/* * Copyright 2019 by its authors. See AUTHORS. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Runtime.InteropServices; using System.Threading; using System.Diagnostics.CodeAnalysis; using System.Collections.Generic; using static Efl.UnsafeNativeMethods; namespace Efl.Csharp { /// The components to be initialized. /// Since EFL 1.23. /// [Flags] public enum Components : Int32 { // Base flags. /// /// Initialize nothing. /// Since EFL 1.24. /// None = 0x0, ///Basic components: Eina, Eo, Ecore, Evas and DBus. /// Since EFL 1.24. /// Basic = 0x1, /// /// Elementary Widget toolkit: Elm. /// it's depend of . /// Since EFL 1.24. /// Ui = Basic | 0x2, // Combined flags. /// /// Enable all components, equals to . /// Since EFL 1.24. /// All = int.MaxValue, } /// /// This represents the entry point for the EFL framework /// You can use this class to implement the 4 abstract methods which will then be called accordingly /// All subsystems of efl are booted up correctly when the abstract methods of this class are called. /// Since EFL 1.23. /// /// /// Calls to efl outside those efl-callbacks or outside the mainloop are not allowed and will lead to issues /// /// /// /// UserApp is the class that implements the Application abstract /// /// public static void Main() /// { /// UserApp editor = new UserApp(); /// editor.Launch(editor); /// } /// /// public abstract class Application { //the initializied components private static Components initComponents = Components.All; //what follows are 3 private functions to boot up the internals of efl private static void Init(Efl.Csharp.Components components = Components.All) { if (components == Components.None) { return; } initComponents = components; if ((initComponents & Components.Basic) == Components.Basic) { Eina.Config.Init(); Efl.Eo.Config.Init(); ecore_init(); ecore_init_ex(0, IntPtr.Zero); evas_init(); eldbus.Config.Init(); } if ((initComponents & Components.Ui) == Components.Ui) { #if WIN32 // TODO Support elm command line arguments // Not a native define, we define it in our build system // Ecore_Win32 uses OleInitialize, which requires single thread apartments if (System.Threading.Thread.CurrentThread.GetApartmentState() != ApartmentState.STA) { throw new InvalidOperationException("UI Applications require STAThreadAttribute in Main()"); } #endif elm_init(0, IntPtr.Zero); Efl.Ui.Win.ExitOnAllWindowsClosed = new Eina.Value(0); } } private static void Shutdown() { // Try to cleanup everything before actually shutting down. System.GC.Collect(); System.GC.WaitForPendingFinalizers(); if (initComponents == Components.None) { return; } if ((initComponents & Components.Ui) == Components.Ui) { elm_shutdown(); } if ((initComponents & Components.Basic) == Components.Basic) { eldbus.Config.Shutdown(); evas_shutdown(); ecore_shutdown(); Efl.Eo.Config.Shutdown(); Eina.Config.Shutdown(); } } /// /// Called when the application is started. Arguments from the command line are passed here. /// Since EFL 1.23. /// /// Arguments passed from command line. protected abstract void OnInitialize(string[] args); /// /// Arguments are passed here, Additional calls to this function may occure, /// but then the initialization flag is set to false. /// Since EFL 1.23. /// /// /// When Initialize is true then OnInitialize is also called /// /// Argsuments passed from command line protected virtual void OnArguments(Efl.LoopArguments args) { } /// /// Called when the application is not going to be displayed, or is not used by a user for some time. /// Since EFL 1.23. /// protected virtual void OnPause() { } /// /// Called before an application is used again after a call to OnPause(). /// Since EFL 1.23. /// protected virtual void OnResume() { } /// /// Called before starting the shutdown of the application. /// Since EFL 1.23. /// protected virtual void OnTerminate() { } /// /// This function initializices everything in EFL and runs your application. /// This call will result in a call to OnInitialize(), which you application should override. /// Since EFL 1.23. /// /// The to run the application. public void Launch(Efl.Csharp.Components components = Components.All) { Init(components); Efl.App app = Efl.App.AppMain; var command_line = new List(); //command_line.Add(List.ConvertAll(Environment.GetCommandLineArgs(), s => (Eina.Stringshare)s)); //command_line.AddRange(Environment.GetCommandLineArgs()); #if EFL_BETA app.SetCommandArray(command_line); #endif app.ArgumentsEvent += (object sender, LoopArgumentsEventArgs evt) => { if (evt.arg.Initialization) { var evtArgv = evt.arg.Argv; int n = evtArgv.Count; var argv = new string[n]; for (int i = 0; i < n; ++i) { argv[i] = evtArgv[i]; } OnInitialize(argv); } OnArguments(evt.arg); }; app.PauseEvent += (object sender, EventArgs e) => { OnPause(); }; app.ResumeEvent += (object sender, EventArgs e) => { OnResume(); }; app.TerminateEvent += (object sender, EventArgs e) => { OnTerminate(); }; app.Begin(); Shutdown(); } } }