1 // =================================
  2 // Copyright (c) 2024 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         int stringHandle = RtmGetEnvironmentVariable("CMAJOR_ROOT");
 15         if (stringHandle != -1)
 16         {
 17             cmajorRootDir = RtmGetString(stringHandle);
 18             RtmFreeString(stringHandle);
 19         }
 20         if (cmajorRootDir.IsEmpty())
 21         {
 22             WinFatalError("please set \'CMAJOR_ROOT\' environment variable to contain /path/to/cmajor directory.");
 23         }
 24         return cmajorRootDir;
 25     }
 26 
 27     public string LogDir()
 28     {
 29         string cmajorRootDir = CmajorRootDir();
 30         string logDir = Path.Combine(cmajorRootDir"log");
 31         Directory.CreateDirectories(logDir);
 32         return logDir;
 33     }
 34 
 35     public string ApplicationLogFilePath()
 36     {
 37         return Path.Combine(LogDir()"application.log");
 38     }
 39 
 40     public delegate bool MessageProcessorFunction(void* windowHandleuint msgulong wparamlong lparamlong& resultvoid*& originalWndProc);
 41 
 42     public class RunModalGuard
 43     {
 44         public RunModalGuard()
 45         {
 46             Application.SetRunningModal();
 47         }
 48         public ~RunModalGuard()
 49         {
 50             Application.ResetRunningModal();
 51         }
 52     }
 53 
 54     public static class Application
 55     {
 56         static Application() : logView(null)activeWindow(null)runningModal(false)errorId(0)
 57         {
 58             MessageProcessorFunction messageProcessorFunction = ProcessMessage;
 59             ModelessWindowKeyPreviewFunction keyPreviewFunction = ModelessWindowKeyPreview;
 60             void* messageProcessorFunctionAddress = cast<void*>(messageProcessorFunction);
 61             void* keyPreviewFunctionAddress = cast<void*>(keyPreviewFunction);
 62             WinInit(messageProcessorFunctionAddresskeyPreviewFunctionAddress);
 63         }
 64         public static void Init()
 65         {
 66         }
 67         public static int Run(Window& mainWindow)
 68         {
 69             mainWindow.SetAsMainWindow();
 70             SetMainWindow(&mainWindow);
 71             switch (mainWindow.GetWindowState())
 72             {
 73                 case WindowState.normal:
 74                 {
 75                     auto result = mainWindow.ShowWindow(ShowCommand.SW_SHOWNORMAL);
 76                     if (result.Error())
 77                     {
 78                         errorId = result.GetErrorId();
 79                         return 1;
 80                     }
 81                     break;
 82                 }
 83                 case WindowState.minimized:
 84                 {
 85                     auto result = mainWindow.ShowWindow(ShowCommand.SW_MINIMIZE);
 86                     if (result.Error())
 87                     {
 88                         errorId = result.GetErrorId();
 89                         return 1;
 90                     }
 91                     break;
 92                 }
 93                 case WindowState.maximized:
 94                 {
 95                     auto result = mainWindow.ShowWindow(ShowCommand.SW_MAXIMIZE);
 96                     if (result.Error())
 97                     {
 98                         errorId = result.GetErrorId();
 99                         return 1;
100                     }
101                     break;
102                 }
103             }
104             auto result = mainWindow.Show();
105             if (result.Error())
106             {
107                 errorId = result.GetErrorId();
108                 return 1;
109             }
110             mainWindow.Update();
111             int exitCode = WinRun();
112             return exitCode;
113         }
114         public static void RunModal()
115         {
116             RunModalGuard guard;
117             WinRunModal();
118         }
119         public static void EndModal()
120         {
121             WinPostMessage(MainWindow()->Handle()CM_ENDMODAL0u0);
122         }
123         public static void Exit(int exitCode)
124         {
125             WinPostQuitMessage(exitCode);
126         }
127         public static void Exit()
128         {
129             Exit(0);
130         }
131         public static void ProcessMessages()
132         {
133             int retval = WinApplicationMessageLoop();
134         }
135         private static bool ProcessMessage(void* windowHandleuint msgulong wparamlong lparamlong& resultvoid*& originalWndProc)
136         {
137             Control* window = windowManager.GetWindow(windowHandle);
138             if (window != null)
139             {
140                 if (Debug.Messages())
141                 {
142                     System.IO.LogWriter writer(ApplicationLogFilePath());
143                     writer << GetCurrentDateTime().ToString() << endl();
144                     auto messageNameResult = MessageNameMap.Instance().GetMessageName(msg);
145                     if (!messageNameResult.Error())
146                     {
147                         writer << ">" << messageNameResult.Value() << endl();
148                     }
149                 }
150                 Message message(windowHandlemsgwparamlparamresult);
151                 Result<bool> handledResult = window->ProcessMessageInternal(message);
152                 if (handledResult.Error())
153                 {
154                     #if (DEBUG)
155                     auto result = MessageBox.Show(handledResult.GetErrorMessage()"error");
156                     if (result.Error())
157                     {
158                         System.IO.LogWriter writer(ApplicationLogFilePath());
159                         writer << GetCurrentDateTime().ToString() << result.GetErrorMessage() << endl();
160                     }
161                     #endif
162                     return false;
163                 }
164                 bool handled = handledResult.Value();
165                 if (message.originalWndProc != null)
166                 {
167                     originalWndProc = message.originalWndProc;
168                 }
169                 if (handled)
170                 {
171                     result = message.result;
172                 }
173                 if (Debug.Messages())
174                 {
175                     System.IO.LogWriter writer(ApplicationLogFilePath());
176                     auto messageNameResult = MessageNameMap.Instance().GetMessageName(msg);
177                     if (!messageNameResult.Error())
178                     {
179                         writer << "<" << messageNameResult.Value() << endl();
180                     }
181                 }
182                 return handled;
183             }
184             return false;
185         }
186         public static WindowManager& GetWindowManager()
187         {
188             return windowManager;
189         }
190         public static ResourceManager& GetResourceManager()
191         {
192             return resourceManager;
193         }
194         public static LogView* GetLogView()
195         {
196             return logView;
197         }
198         public static void SetLogView(LogView* logView_)
199         {
200             logView = logView_;
201         }
202         public static Control* GetFocusedControl() const
203         {
204             void* focusedWindowHandle = WinGetFocus();
205             if (focusedWindowHandle == null)
206             {
207                 return null;
208             }
209             Control* focusedControl = windowManager.GetWindow(focusedWindowHandle);
210             return focusedControl;
211         }
212         public static Window* GetActiveWindow()
213         {
214             return activeWindow;
215         }
216         public static void SetActiveWindow(Window* activeWindow_)
217         {
218             activeWindow = activeWindow_;
219         }
220         public static Window* MainWindow()
221         {
222             return mainWindow;
223         }
224         public static void SetMainWindow(Window* w)
225         {
226             mainWindow = w;
227         }
228         internal static void SetRunningModal()
229         {
230             runningModal = true;
231         }
232         internal static void ResetRunningModal()
233         {
234             runningModal = false;
235         }
236         public static bool RunningModal()
237         {
238             return runningModal;
239         }
240         public static bool Error()
241         {
242             return errorId != 0;
243         }
244         public static int ErrorId()
245         {
246             return errorId;
247         }
248         private static WindowManager windowManager;
249         private static ResourceManager resourceManager;
250         private static LogView* logView;
251         private static Window* activeWindow;
252         private static Window* mainWindow;
253         private static bool runningModal;
254         private static int errorId;
255     }