1
2
3
4
5
6 using System;
7 using System.IO;
8
9 namespace System.Windows
10 {
11 public enum SystemMetricsId : int
12 {
13 SM_ARRANGE = 56,
14 SM_CLEANBOOT = 67,
15 SM_CMONITORS = 80,
16 SM_CMOUSEBUTTONS = 43,
17 SM_CONVERTIBLESLATEMODE = 8195,
18 SM_CXBORDER = 5,
19 SM_CXCURSOR = 13,
20 SM_CXDLGFRAME = 7,
21 SM_CXDOUBLECLK = 36,
22 SM_CXDRAG = 68,
23 SM_CXEDGE = 45,
24 SM_CXFIXEDFRAME = 7,
25 SM_CXFOCUSBORDER = 83,
26 SM_CXFRAME = 32,
27 SM_CXFULLSCREEN = 16,
28 SM_CXHSCROLL = 21,
29 SM_CXHTHUMB = 10,
30 SM_CXICON = 11,
31 SM_CXICONSPACING = 38,
32 SM_CXMAXIMIZED = 61,
33 SM_CXMAXTRACK = 59,
34 SM_CXMENUCHECK = 71,
35 SM_CXMENUSIZE = 54,
36 SM_CXMIN = 28,
37 SM_CXMINIMIZED = 57,
38 SM_CXMINSPACING = 47,
39 SM_CXMINTRACK = 34,
40 SM_CXPADDEDBORDER = 92,
41 SM_CXSCREEN = 0,
42 SM_CXSIZE = 30,
43 SM_CXSIZEFRAME = 32,
44 SM_CXSMICON = 49,
45 SM_CXSMSIZE = 52,
46 SM_CXVIRTUALSCREEN = 78,
47 SM_CXVSCROLL = 2,
48 SM_CYBORDER = 6,
49 SM_CYCAPTION = 4,
50 SM_CYCURSOR = 14,
51 SM_CYDLGFRAME = 8,
52 SM_CYDOUBLECLK = 37,
53 SM_CYDRAG = 69,
54 SM_CYEDGE = 46,
55 SM_CYFIXEDFRAME = 8,
56 SM_CYFOCUSBORDER = 84,
57 SM_CYFRAME = 33,
58 SM_CYFULLSCREEN = 17,
59 SM_CYHSCROLL = 3,
60 SM_CYICON = 12,
61 SM_CYICONSPACING = 39,
62 SM_CYKANJIWINDOW = 18,
63 SM_CYMAXIMIZED = 62,
64 SM_CYMAXTRACK = 60,
65 SM_CYMENU = 15,
66 SM_CYMENUCHECK = 72,
67 SM_CYMENUSIZE = 55,
68 SM_CYMIN = 29,
69 SM_CYMINIMIZED = 58,
70 SM_CYMINSPACING = 48,
71 SM_CYMINTRACK = 35,
72 SM_CYSCREEN = 1,
73 SM_CYSIZE = 31,
74 SM_CYSIZEFRAME = 33,
75 SM_CYSMCAPTION = 51,
76 SM_CYSMICON = 50,
77 SM_CYSMSIZE = 53,
78 SM_CYVIRTUALSCREEN = 79,
79 SM_CYVSCROLL = 20,
80 SM_CYVTHUMB = 9,
81 SM_DBCSENABLED = 42,
82 SM_DEBUG = 22,
83 SM_DIGITIZER = 94,
84 SM_IMMENABLED = 82,
85 SM_MAXIMUMTOUCHES = 95,
86 SM_MEDIACENTER = 87,
87 SM_MENUDROPALIGNMENT = 40,
88 SM_MIDEASTENABLED = 74,
89 SM_MOUSEPRESENT = 19,
90 SM_MOUSEHORIZONTALWHEELPRESENT = 91,
91 SM_MOUSEWHEELPRESENT = 75,
92 SM_NETWORK = 63,
93 SM_PENWINDOWS = 41,
94 SM_REMOTECONTROL = 8193,
95 SM_REMOTESESSION = 4096,
96 SM_SAMEDISPLAYFORMAT = 81,
97 SM_SERVERR2 = 89,
98 SM_SHOWSOUNDS = 70,
99 SM_SHUTTINGDOWN = 8192,
100 SM_SLOWMACHINE = 73,
101 SM_STARTER = 88,
102 SM_SWAPBUTTON = 23,
103 SM_SYSTEMDOCKED = 8196,
104 SM_TABLETPC = 86,
105 SM_XVIRTUALSCREEN = 76,
106 SM_YVIRTUALSCREEN = 77
107 }
108
109 int GetSystemMetrics(SystemMetricsId id)
110 {
111 return WinGetSystemMetrics(cast<int>(id));
112 }
113
114 public const float inchMM = 25.400000f;
115 public const float pointMM = 0.351450f;
116
117 public inline float InchToMM(float inches)
118 {
119 return inches * inchMM;
120 }
121
122 public inline float MMToInch(float mm)
123 {
124 return mm / inchMM;
125 }
126
127 public inline float PointToMM(float points)
128 {
129 return points * pointMM;
130 }
131
132 public inline float MMToPoint(float mm)
133 {
134 return mm / pointMM;
135 }
136
137 public inline int MMToPixels(float mm, float dpi)
138 {
139 return cast<int>(mm * dpi / inchMM);
140 }
141
142 public inline float PixelsToMM(int pixels, float dpi)
143 {
144 return pixels * inchMM / dpi;
145 }
146
147 public inline double GoldenRatio()
148 {
149 return 1 + Sqrt(5) / 2;
150 }
151
152 public string GetDefaultMetricsFilePath()
153 {
154 string metricsFilePath;
155 string cmajorRootDir;
156 int stringHandle = RtmGetEnvironmentVariable("CMAJOR_ROOT");
157 if (stringHandle != -1)
158 {
159 cmajorRootDir = RtmGetString(stringHandle);
160 RtmFreeString(stringHandle);
161 }
162 if (!cmajorRootDir.IsEmpty())
163 {
164 metricsFilePath = Path.Combine(Path.Combine(cmajorRootDir, "config"), "metrics.xml");
165 }
166 return metricsFilePath;
167 }
168
169 public class SizeElement
170 {
171 public SizeElement(const string& name_) : name(name_)
172 {
173 }
174 public inline const SizeF& Get() const
175 {
176 return size;
177 }
178 public void Set(const SizeF& size_)
179 {
180 size = size_;
181 }
182 [nodiscard]
183 public Result<bool> Read(System.Xml.Element* parentElement)
184 {
185 Result<UniquePtr<System.XPath.NodeSet>> nodeSetResult = System.XPath.EvaluateToNodeSet(name, parentElement);
186 if (nodeSetResult.Error())
187 {
188 return Result<bool>(ErrorId(nodeSetResult.GetErrorId()));
189 }
190 System.XPath.NodeSet* nodeSet = nodeSetResult.Value().Get();
191 int n = nodeSet->Count();
192 if (n == 1)
193 {
194 System.Xml.Node* node = nodeSet->GetNode(0);
195 if (node->IsElementNode())
196 {
197 System.Xml.Element* sizeElement = cast<System.Xml.Element*>(node);
198 auto wresult = ParseFloat(sizeElement->GetAttribute("width"));
199 if (wresult.Error())
200 {
201 return Result<bool>(ErrorId(wresult.GetErrorId()));
202 }
203 size.w = wresult.Value();
204 auto hresult = ParseFloat(sizeElement->GetAttribute("height"));
205 if (hresult.Error())
206 {
207 return Result<bool>(ErrorId(hresult.GetErrorId()));
208 }
209 size.h = hresult.Value();
210 }
211 }
212 else
213 {
214 return Result<bool>(false);
215 }
216 return Result<bool>(true);
217 }
218 public void Write(System.Xml.Element* parentElement)
219 {
220 System.Xml.Element* sizeElement(System.Xml.MakeElement(name));
221 sizeElement->SetAttribute("width", ToString(size.w));
222 sizeElement->SetAttribute("height", ToString(size.h));
223 parentElement->AppendChild(sizeElement);
224 }
225 private string name;
226 private SizeF size;
227 }
228
229 public class Metrics
230 {
231 public Metrics() :
232 useDefaults(false), dpiX(96), dpiY(96),
233 defaultButtonSize(86, 25), defaultButtonSizeElement("button"),
234 defaultLabelSize(71, 19), defaultLabelSizeElement("label"),
235 defaultTextBoxSize(94, 14), defaultTextBoxSizeElement("textBox"),
236 defaultListBoxSize(120, 95), defaultListBoxSizeElement("listBox"),
237 defaultCheckBoxSize(80, 17), defaultCheckBoxSizeElement("checkBox"),
238 defaultControlSpacing(10, 10), defaultControlSpacingElement("controlSpacing")
239 {
240 SetElementValues();
241 }
242 public inline bool UseDefaults() const
243 {
244 return useDefaults;
245 }
246 public void SetUseDefaults(bool useDefaults_)
247 {
248 useDefaults = useDefaults_;
249 }
250 [nodiscard]
251 public Result<bool> LoadFromFile(const string& fileName, System.Lex.FileMap& fileMap)
252 {
253 auto existsResult = File.Exists(fileName);
254 if (existsResult.Error())
255 {
256 return Result<bool>(ErrorId(existsResult.GetErrorId()));
257 }
258 bool exists = existsResult.Value();
259 if (exists)
260 {
261 Result<UniquePtr<System.Xml.Document>> metricsDocResult = System.Xml.ParseXmlDocument(fileName, fileMap);
262 if (metricsDocResult.Error())
263 {
264 return Result<bool>(ErrorId(metricsDocResult.GetErrorId()));
265 }
266 System.Xml.Document* metricsDoc = metricsDocResult.Value().Get();
267 auto result = Read(metricsDoc->DocumentElement());
268 if (result.Error()) return result;
269 LogView* logView = Application.GetLogView();
270 if (logView != null)
271 {
272 auto result = logView->WriteLine("metrics loaded from \'" + fileName + "\'");
273 if (result.Error()) return result;
274 }
275 }
276 else
277 {
278 return Result<bool>(false);
279 }
280 return Result<bool>(true);
281 }
282 public void SetElementValues()
283 {
284 defaultButtonSizeElement.Set(SizeF(HorizontalPixelsToMM(defaultButtonSize.w), VerticalPixelsToMM(defaultButtonSize.h)));
285 defaultLabelSizeElement.Set(SizeF(HorizontalPixelsToMM(defaultLabelSize.w), VerticalPixelsToMM(defaultLabelSize.h)));
286 defaultTextBoxSizeElement.Set(SizeF(HorizontalPixelsToMM(defaultTextBoxSize.w), VerticalPixelsToMM(defaultTextBoxSize.h)));
287 defaultListBoxSizeElement.Set(SizeF(HorizontalPixelsToMM(defaultListBoxSize.w), VerticalPixelsToMM(defaultListBoxSize.h)));
288 defaultCheckBoxSizeElement.Set(SizeF(HorizontalPixelsToMM(defaultCheckBoxSize.w), VerticalPixelsToMM(defaultCheckBoxSize.h)));
289 defaultControlSpacingElement.Set(SizeF(HorizontalPixelsToMM(defaultControlSpacing.w), VerticalPixelsToMM(defaultControlSpacing.h)));
290 }
291 [nodiscard]
292 public Result<bool> SaveTofile(const string& fileName, bool setElementValues)
293 {
294 if (setElementValues)
295 {
296 SetElementValues();
297 }
298 System.Xml.Document metricsDoc;
299 metricsDoc.AppendChild(System.Xml.MakeElement("metrics"));
300 metricsDoc.DocumentElement()->AppendChild(System.Xml.MakeComment("metrics are in millimeters"));
301 metricsDoc.DocumentElement()->AppendChild(System.Xml.MakeText("\n "));
302 Write(metricsDoc.DocumentElement());
303 auto fileResult = File.CreateText(fileName);
304 if (fileResult.Error())
305 {
306 return Result<bool>(ErrorId(fileResult.GetErrorId()));
307 }
308 StreamWriter& writer = fileResult.Value();
309 System.Text.CodeFormatter formatter(writer);
310 formatter.SetIndentSize(1);
311 auto writeResult = metricsDoc.Write(formatter);
312 if (writeResult.Error())
313 {
314 return Result<bool>(ErrorId(writeResult.GetErrorId()));
315 }
316 LogView* logView = Application.GetLogView();
317 if (logView != null)
318 {
319 auto result = logView->WriteLine("metrics saved to \'" + fileName + "\'");
320 if (result.Error()) return result;
321 }
322 return Result<bool>(true);
323 }
324 [nodiscard]
325 public Result<bool> Read(System.Xml.Element* parentElement)
326 {
327 auto result = defaultButtonSizeElement.Read(parentElement);
328 if (result.Error()) return result;
329 result = defaultLabelSizeElement.Read(parentElement);
330 if (result.Error()) return result;
331 result = defaultTextBoxSizeElement.Read(parentElement);
332 if (result.Error()) return result;
333 result = defaultListBoxSizeElement.Read(parentElement);
334 if (result.Error()) return result;
335 result = defaultCheckBoxSizeElement.Read(parentElement);
336 if (result.Error()) return result;
337 result = defaultControlSpacingElement.Read(parentElement);
338 if (result.Error()) return result;
339 return Result<bool>(true);
340 }
341 public void Write(System.Xml.Element* parentElement)
342 {
343 defaultButtonSizeElement.Write(parentElement);
344 defaultLabelSizeElement.Write(parentElement);
345 defaultTextBoxSizeElement.Write(parentElement);
346 defaultListBoxSizeElement.Write(parentElement);
347 defaultCheckBoxSizeElement.Write(parentElement);
348 defaultControlSpacingElement.Write(parentElement);
349 }
350 public inline bool Calculated() const
351 {
352 return calculated;
353 }
354 public void Calculate(Graphics& graphics)
355 {
356 calculated = true;
357 dpiX = graphics.GetDpiX();
358 dpiY = graphics.GetDpiX();
359 if (useDefaults) return;
360 defaultButtonSize.w = MMToHorizontalPixels(defaultButtonSizeElement.Get().w);
361 defaultButtonSize.h = MMToVerticalPixels(defaultButtonSizeElement.Get().h);
362 defaultLabelSize.w = MMToHorizontalPixels(defaultLabelSizeElement.Get().w);
363 defaultLabelSize.h = MMToVerticalPixels(defaultLabelSizeElement.Get().h);
364 defaultTextBoxSize.w = MMToHorizontalPixels(defaultTextBoxSizeElement.Get().w);
365 defaultTextBoxSize.h = MMToVerticalPixels(defaultTextBoxSizeElement.Get().h);
366 defaultListBoxSize.w = MMToHorizontalPixels(defaultListBoxSizeElement.Get().w);
367 defaultListBoxSize.h = MMToVerticalPixels(defaultListBoxSizeElement.Get().h);
368 defaultCheckBoxSize.w = MMToHorizontalPixels(defaultCheckBoxSizeElement.Get().w);
369 defaultCheckBoxSize.h = MMToVerticalPixels(defaultCheckBoxSizeElement.Get().h);
370 defaultControlSpacing.w = MMToHorizontalPixels(defaultControlSpacingElement.Get().w);
371 defaultControlSpacing.h = MMToVerticalPixels(defaultControlSpacingElement.Get().h);
372 }
373 [nodiscard]
374 public Result<bool> PrintToLog()
375 {
376 LogView* logView = Application.GetLogView();
377 if (logView != null)
378 {
379 auto result = logView->WriteLine("DPIX=" + ToString(dpiX) + ", DPIY=" + ToString(dpiY));
380 if (result.Error()) return result;
381 result = logView->WriteLine("Button: " + defaultButtonSize.ToString() + " - (" + ToString(HorizontalPixelsToMM(defaultButtonSize.w)) + "mm, " +
382 ToString(VerticalPixelsToMM(defaultButtonSize.h)) + "mm)");
383 if (result.Error()) return result;
384 result = logView->WriteLine("Label: " + defaultLabelSize.ToString() + " - (" + ToString(HorizontalPixelsToMM(defaultLabelSize.w)) + "mm, " +
385 ToString(VerticalPixelsToMM(defaultLabelSize.h)) + "mm)");
386 if (result.Error()) return result;
387 result = logView->WriteLine("TextBox: " + defaultTextBoxSize.ToString() + " - (" + ToString(HorizontalPixelsToMM(defaultTextBoxSize.w)) + "mm, " +
388 ToString(VerticalPixelsToMM(defaultTextBoxSize.h)) + "mm)");
389 if (result.Error()) return result;
390 result = logView->WriteLine("ListBox: " + defaultListBoxSize.ToString() + " - (" + ToString(HorizontalPixelsToMM(defaultListBoxSize.w)) + "mm, " +
391 ToString(VerticalPixelsToMM(defaultListBoxSize.h)) + "mm)");
392 if (result.Error()) return result;
393 result = logView->WriteLine("CheckBox: " + defaultCheckBoxSize.ToString() + " - (" + ToString(HorizontalPixelsToMM(defaultCheckBoxSize.w)) + "mm, " +
394 ToString(VerticalPixelsToMM(defaultCheckBoxSize.h)) + "mm)");
395 if (result.Error()) return result;
396 result = logView->WriteLine("Spacing: " + defaultControlSpacing.ToString() + " - (" + ToString(HorizontalPixelsToMM(defaultControlSpacing.w)) + "mm, " +
397 ToString(VerticalPixelsToMM(defaultControlSpacing.h)) + "mm)");
398 if (result.Error()) return result;
399 }
400 return Result<bool>(true);
401 }
402 public inline float DpiX() const
403 {
404 return dpiX;
405 }
406 public inline float DpiY() const
407 {
408 return dpiY;
409 }
410 public inline int MMToHorizontalPixels(float mm) const
411 {
412 return MMToPixels(mm, dpiX);
413 }
414 public inline float HorizontalPixelsToMM(int pixels) const
415 {
416 return PixelsToMM(pixels, dpiX);
417 }
418 public inline int MMToVerticalPixels(float mm) const
419 {
420 return MMToPixels(mm, dpiY);
421 }
422 public inline float VerticalPixelsToMM(int pixels) const
423 {
424 return PixelsToMM(pixels, dpiY);
425 }
426 public inline const Size& DefaultButtonSize() const
427 {
428 return defaultButtonSize;
429 }
430 public void SetDefaultButtonSize(const Size& defaultButtonSize_)
431 {
432 defaultButtonSize = defaultButtonSize_;
433 }
434 public inline const Size& DefaultLabelSize() const
435 {
436 return defaultLabelSize;
437 }
438 public void SetDefaultLabelSize(const Size& defaultLabelSize_)
439 {
440 defaultLabelSize = defaultLabelSize_;
441 }
442 public inline const Size& DefaultTextBoxSize() const
443 {
444 return defaultTextBoxSize;
445 }
446 public void SetDefaultTextBoxSize(const Size& defaultTextBoxSize_)
447 {
448 defaultTextBoxSize = defaultTextBoxSize_;
449 }
450 public inline const Size& DefaultListBoxSize() const
451 {
452 return defaultListBoxSize;
453 }
454 public void SetDefaultListBoxSize(const Size& defaultListBoxSize_)
455 {
456 defaultListBoxSize = defaultListBoxSize_;
457 }
458 public inline const Size& DefaultCheckBoxSize() const
459 {
460 return defaultCheckBoxSize;
461 }
462 public void SetDefaultCheckBoxSize(const Size& defaultCheckBoxSize_)
463 {
464 defaultCheckBoxSize = defaultCheckBoxSize_;
465 }
466 public inline const Size& DefaultControlSpacing() const
467 {
468 return defaultControlSpacing;
469 }
470 public void SetDefaultControlSpacing(const Size& defaultControlSpacing_)
471 {
472 defaultControlSpacing = defaultControlSpacing_;
473 }
474 public SizeElement& DefaultButtonSizeElement()
475 {
476 return defaultButtonSizeElement;
477 }
478 public SizeElement& DefaultLabelSizeElement()
479 {
480 return defaultLabelSizeElement;
481 }
482 public SizeElement& DefaultTextBoxSizeElement()
483 {
484 return defaultTextBoxSizeElement;
485 }
486 public SizeElement& DefaultControlSpacingElement()
487 {
488 return defaultControlSpacingElement;
489 }
490 private bool useDefaults;
491 private bool calculated;
492 private float dpiX;
493 private float dpiY;
494 private Size defaultButtonSize;
495 private SizeElement defaultButtonSizeElement;
496 private Size defaultLabelSize;
497 private SizeElement defaultLabelSizeElement;
498 private Size defaultTextBoxSize;
499 private SizeElement defaultTextBoxSizeElement;
500 private Size defaultListBoxSize;
501 private SizeElement defaultListBoxSizeElement;
502 private Size defaultCheckBoxSize;
503 private SizeElement defaultCheckBoxSizeElement;
504 private Size defaultControlSpacing;
505 private SizeElement defaultControlSpacingElement;
506 }
507
508 public static class ScreenMetrics
509 {
510 public static ScreenMetrics() : metrics()
511 {
512 }
513 public static void SetUseDefaults(bool useDefaults)
514 {
515 metrics.SetUseDefaults(useDefaults);
516 }
517 public static Result<bool> Save(bool setElementValues)
518 {
519 string metricsFilePath = GetDefaultMetricsFilePath();
520 auto saveResult = metrics.SaveTofile(metricsFilePath, setElementValues);
521 if (saveResult.Error())
522 {
523 return Result<bool>(ErrorId(saveResult.GetErrorId()));
524 }
525 return Result<bool>(true);
526 }
527 public static Result<bool> Load(System.Lex.FileMap& fileMap)
528 {
529 string metricsFilePath = GetDefaultMetricsFilePath();
530 auto existsResult = File.Exists(metricsFilePath);
531 if (existsResult.Error())
532 {
533 return Result<bool>(ErrorId(existsResult.GetErrorId()));
534 }
535 bool exists = existsResult.Value();
536 if (exists)
537 {
538 auto result = metrics.LoadFromFile(metricsFilePath, fileMap);
539 if (result.Error())
540 {
541 return Result<bool>(ErrorId(result.GetErrorId()));
542 }
543 }
544 else
545 {
546 return Result<bool>(false);
547 }
548 return Result<bool>(true);
549 }
550 public static bool Calculated()
551 {
552 return metrics.Calculated();
553 }
554 public static Result<bool> Calculate(Graphics& graphics)
555 {
556 if (!metrics.UseDefaults())
557 {
558 auto result = Load(defaultFileMap);
559 if (result.Error())
560 {
561 return Result<bool>(ErrorId(result.GetErrorId()));
562 }
563 }
564 metrics.Calculate(graphics);
565 return Result<bool>(true);
566 }
567 public static const Metrics& Get()
568 {
569 return metrics;
570 }
571 public static void Set(const Metrics& metrics_)
572 {
573 metrics = metrics_;
574 }
575 public static Metrics metrics;
576 private static System.Lex.FileMap defaultFileMap;
577 }