1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 using System.Windows.API;
  8 
  9 namespace System.Windows
 10 {
 11     public string CmajorRootDir()
 12     {
 13         string cmajorRootDir;
 14         const char* cmajorRootEnv = RtGetEnvironmentVariable("CMAJOR_ROOT");
 15         if (cmajorRootEnv != null && *cmajorRootEnv != '\0')
 16         {
 17             cmajorRootDir = cmajorRootEnv;
 18         }
 19         if (cmajorRootDir.IsEmpty())
 20         {
 21             throw Exception("please set 'CMAJOR_ROOT' environment variable to contain /path/to/cmajor directory.");
 22         }
 23         return cmajorRootDir;
 24     }
 25 
 26     public string LogDir()
 27     {
 28         string cmajorRootDir = CmajorRootDir();
 29         string logDir = Path.Combine(cmajorRootDir"log");
 30         Directory.CreateDirectories(logDir);
 31         return logDir;
 32     }
 33 
 34     public string ApplicationLogFilePath()
 35     {
 36         return Path.Combine(LogDir()"application.log");
 37     }
 38 
 39     public delegate bool MessageProcessorFunction(void* windowHandleuint msguint wparamlong lparamlong& resultvoid*& originalWndProc);
 40 
 41     public class RunModalGuard
 42     {
 43         public nothrow RunModalGuard()
 44         {
 45             Application.SetRunningModal();
 46         }
 47         public ~RunModalGuard()
 48         {
 49             Application.ResetRunningModal();
 50         }
 51     }
 52 
 53     public static class Application
 54     {
 55         static Application() : logView(null)activeWindow(null)runningModal(false)
 56         {
 57             RtSetThreadId('M');
 58             MessageProcessorFunction messageProcessorFunction = ProcessMessage;
 59             ModelessWindowKeyPreviewFunction keyPreviewFunction = ModelessWindowKeyPreview;
 60             void* messageProcessorFunctionAddress = cast<void*>(messageProcessorFunction);
 61             void* keyPreviewFunctionAddress = cast<void*>(keyPreviewFunction);
 62             int result = WinInit(messageProcessorFunctionAddresskeyPreviewFunctionAddress);
 63             CheckGraphicsStatus(cast<GraphicsStatus>(result));
 64         }
 65         public static void Init()
 66         {
 67             if (!RtIsUserAssertionFailureFunctionSet())
 68             {
 69                 RtSetUserAssertionFailureFunction(WindowsAssertionFailureFunction);
 70             }
 71         }
 72         public static int Run(Window& mainWindow)
 73         {
 74             mainWindow.SetAsMainWindow();
 75             SetMainWindow(&mainWindow);
 76             switch (mainWindow.GetWindowState())
 77             {
 78                 case WindowState.normal:
 79                 {
 80                     mainWindow.ShowWindow(ShowCommand.SW_SHOWNORMAL);
 81                     break;
 82                 }
 83                 case WindowState.minimized:
 84                 {
 85                     mainWindow.ShowWindow(ShowCommand.SW_MINIMIZE);
 86                     break;
 87                 }
 88                 case WindowState.maximized:
 89                 {
 90                     mainWindow.ShowWindow(ShowCommand.SW_MAXIMIZE);
 91                     break;
 92                 }
 93             }
 94             mainWindow.Show();
 95             mainWindow.Update();
 96             int exitCode = WinRun();
 97             return exitCode;
 98         }
 99         public static void RunModal()
100         {
101             RunModalGuard guard;
102             WinRunModal();
103         }
104         public static nothrow void EndModal()
105         {
106             WinPostMessage(MainWindow()->Handle()CM_ENDMODAL0u0);
107         }
108         public static void Exit(int exitCode)
109         {
110             WinPostQuitMessage(exitCode);
111         }
112         public static void Exit()
113         {
114             Exit(0);
115         }
116         public static void ProcessMessages()
117         {
118             int retval = WinApplicationMessageLoop();
119         }
120         private static bool ProcessMessage(void* windowHandleuint msguint wparamlong lparamlong& resultvoid*& originalWndProc)
121         {
122             Control* window = windowManager.GetWindow(windowHandle);
123             if (window != null)
124             {
125                 if (Debug.Messages())
126                 {
127                     System.IO.LogWriter writer(ApplicationLogFilePath());
128                     writer << GetCurrentTimestamp().ToString() << endl();
129                     writer << ">" << MessageNameMap.Instance().GetMessageName(msg) << endl();
130                 }
131                 RtWindowsMessage(cast<int>(msg));
132                 Message message(windowHandlemsgwparamlparamresult);
133                 bool handled = window->ProcessMessageInternal(message);
134                 if (message.originalWndProc != null)
135                 {
136                     originalWndProc = message.originalWndProc;
137                 }
138                 if (handled)
139                 {
140                     result = message.result;
141                 }
142                 if (Debug.Messages())
143                 {
144                     System.IO.LogWriter writer(ApplicationLogFilePath());
145                     writer << "<" << MessageNameMap.Instance().GetMessageName(msg) << endl();
146                 }
147                 return handled;
148             }
149             return false;
150         }
151         public static nothrow WindowManager& GetWindowManager()
152         {
153             return windowManager;
154         }
155         public static nothrow ResourceManager& GetResourceManager()
156         {
157             return resourceManager;
158         }
159         public static nothrow LogView* GetLogView()
160         {
161             return logView;
162         }
163         public static nothrow void SetLogView(LogView* logView_)
164         {
165             logView = logView_;
166         }
167         public static Control* GetFocusedControl() const
168         {
169             void* focusedWindowHandle = WinGetFocus();
170             if (focusedWindowHandle == null)
171             {
172                 return null;
173             }
174             Control* focusedControl = windowManager.GetWindow(focusedWindowHandle);
175             return focusedControl;
176         }
177         public static nothrow Window* GetActiveWindow()
178         {
179             return activeWindow;
180         }
181         public static nothrow void SetActiveWindow(Window* activeWindow_)
182         {
183             activeWindow = activeWindow_;
184         }
185         public static nothrow Window* MainWindow()
186         {
187             return mainWindow;
188         }
189         public static nothrow void SetMainWindow(Window* w)
190         {
191             mainWindow = w;
192         }
193         internal static nothrow void SetRunningModal()
194         {
195             runningModal = true;
196         }
197         internal static nothrow void ResetRunningModal()
198         {
199             runningModal = false;
200         }
201         public static nothrow bool RunningModal()
202         {
203             return runningModal;
204         }
205         private static WindowManager windowManager;
206         private static ResourceManager resourceManager;
207         private static LogView* logView;
208         private static Window* activeWindow;
209         private static Window* mainWindow;
210         private static bool runningModal;
211     }
212 }