/GarminFitnessPlugin/Controller/Utils.cs

http://garminworkouts.googlecode.com/ · C# · 483 lines · 399 code · 73 blank · 11 comment · 49 complexity · 55e4bbc06c8a0d86170dc149619c8ef0 MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Drawing;
  5. using System.Globalization;
  6. using System.IO;
  7. using System.Runtime.InteropServices;
  8. using System.Text;
  9. using System.Threading;
  10. using System.Windows.Forms;
  11. using System.Xml;
  12. using ZoneFiveSoftware.Common.Data.Fitness;
  13. using ZoneFiveSoftware.Common.Data.Measurement;
  14. using GarminFitnessPlugin.Data;
  15. using GarminFitnessPlugin.View;
  16. namespace GarminFitnessPlugin.Controller
  17. {
  18. class Utils
  19. {
  20. [DllImport("gdi32.dll")]
  21. private static extern int BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight,
  22. IntPtr hdcSrc, int nXSrc, int nYSrc, Int32 dwRop);
  23. [DllImport("gdi32.dll")]
  24. private static extern IntPtr CreateCompatibleDC(IntPtr hDC);
  25. [DllImport("gdi32.dll")]
  26. private static extern bool DeleteDC(IntPtr hdc);
  27. [DllImport("gdi32.dll")]
  28. private static extern bool DeleteObject(IntPtr hObject);
  29. [DllImport("gdi32.dll")]
  30. private static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
  31. static public void RenderBitmapToGraphics(Bitmap source, Graphics destination, Rectangle destinationRect)
  32. {
  33. try
  34. {
  35. IntPtr destHdc = destination.GetHdc();
  36. IntPtr bitmapHdc = CreateCompatibleDC(destHdc);
  37. IntPtr hBitmap = source.GetHbitmap();
  38. IntPtr oldHdc = SelectObject(bitmapHdc, hBitmap);
  39. BitBlt(destHdc,
  40. destinationRect.Left, destinationRect.Top,
  41. destinationRect.Width, destinationRect.Height,
  42. bitmapHdc, 0, 0, 0x00CC0020);
  43. destination.ReleaseHdc(destHdc);
  44. SelectObject(bitmapHdc, oldHdc);
  45. DeleteDC(bitmapHdc);
  46. DeleteObject(hBitmap);
  47. }
  48. catch//(System.DllNotFoundException e)
  49. {
  50. // Mono/Linux - Just go on right now
  51. //throw e;
  52. }
  53. }
  54. public static void HijackMainWindow()
  55. {
  56. Control viewControl = PluginMain.GetApplication().ActiveView.CreatePageControl();
  57. Control mainWindow = viewControl.TopLevelControl;
  58. for (int i = 0; i < mainWindow.Controls.Count; ++i)
  59. {
  60. mainWindow.Controls[i].Enabled = false;
  61. }
  62. mainWindow.Cursor = Cursors.WaitCursor;
  63. }
  64. public static void ReleaseMainWindow()
  65. {
  66. Control viewControl = PluginMain.GetApplication().ActiveView.CreatePageControl();
  67. Control mainWindow = viewControl.TopLevelControl;
  68. for (int i = 0; i < mainWindow.Controls.Count; ++i)
  69. {
  70. mainWindow.Controls[i].Enabled = true;
  71. }
  72. mainWindow.Cursor = Cursors.Default;
  73. }
  74. public static IActivityCategory FindCategoryByID(string categoryID)
  75. {
  76. return FindCategoryByIDInList(categoryID, PluginMain.GetApplication().Logbook.ActivityCategories);
  77. }
  78. public static IActivityCategory FindCategoryByIDSafe(string categoryID)
  79. {
  80. IActivityCategory category = FindCategoryByID(categoryID);
  81. if (category != null)
  82. {
  83. return category;
  84. }
  85. // We didn't find the old category, place it in the first one
  86. Debug.Assert(PluginMain.GetApplication().Logbook.ActivityCategories.Count > 0);
  87. return GetDefaultCategory();
  88. }
  89. private static IActivityCategory FindCategoryByIDInList(string categoryID, IEnumerable<IActivityCategory> list)
  90. {
  91. foreach (IActivityCategory category in list)
  92. {
  93. if (category.ReferenceId == categoryID)
  94. {
  95. return category;
  96. }
  97. else if (category.SubCategories.Count > 0)
  98. {
  99. IActivityCategory child = FindCategoryByIDInList(categoryID, category.SubCategories);
  100. if (child != null)
  101. {
  102. return child;
  103. }
  104. }
  105. }
  106. return null;
  107. }
  108. public static IZoneCategory FindZoneCategoryByID(IZoneCategoryList list, string categoryID)
  109. {
  110. for (int i = 0; i < list.Count; ++i)
  111. {
  112. if (list[i].ReferenceId == categoryID)
  113. {
  114. return list[i];
  115. }
  116. }
  117. return list[0];
  118. }
  119. public static bool NamedZoneStillExists(IZoneCategoryList list, INamedLowHighZone zone)
  120. {
  121. for (int i = 0; i < list.Count; ++i)
  122. {
  123. IZoneCategory currentZoneCategory = list[i];
  124. for (int j = 0; j < currentZoneCategory.Zones.Count; ++j)
  125. {
  126. if (currentZoneCategory.Zones[j] == zone)
  127. {
  128. return true;
  129. }
  130. }
  131. }
  132. return false;
  133. }
  134. public static bool ZoneCategoryStillExists(IZoneCategoryList list, IZoneCategory zone)
  135. {
  136. for (int i = 0; i < list.Count; ++i)
  137. {
  138. if (list[i] == zone)
  139. {
  140. return true;
  141. }
  142. }
  143. return false;
  144. }
  145. public static IActivityCategory GetDefaultCategory()
  146. {
  147. return PluginMain.GetApplication().Logbook.ActivityCategories[0];
  148. }
  149. public static void SaveDataToLogbook()
  150. {
  151. // Save Workouts to logbook
  152. MemoryStream stream = new MemoryStream();
  153. // Data version number
  154. stream.Write(Encoding.UTF8.GetBytes(Constants.DataHeaderIdString), 0, Encoding.UTF8.GetByteCount(Constants.DataHeaderIdString));
  155. stream.WriteByte(Constants.CurrentVersion.VersionNumber);
  156. Options.Instance.Serialize(stream);
  157. GarminWorkoutManager.Instance.Serialize(stream);
  158. GarminProfileManager.Instance.Serialize(stream);
  159. PluginMain.GetApplication().Logbook.SetExtensionData(GUIDs.PluginMain, stream.GetBuffer());
  160. PluginMain.GetApplication().Logbook.Modified = true;
  161. stream.Close();
  162. }
  163. public static bool IsTextIntegerInRange(string text, Int32 minRange, Int32 maxRange)
  164. {
  165. Int32 value;
  166. if (Int32.TryParse(text, out value))
  167. {
  168. if (value >= minRange && value <= maxRange)
  169. {
  170. return true;
  171. }
  172. }
  173. return false;
  174. }
  175. public static bool IsTextIntegerInRange(string text, UInt32 minRange, UInt32 maxRange)
  176. {
  177. UInt32 value;
  178. if (UInt32.TryParse(text, out value))
  179. {
  180. if (value >= minRange && value <= maxRange)
  181. {
  182. return true;
  183. }
  184. }
  185. return false;
  186. }
  187. public static bool IsTextIntegerInRange(string text, UInt16 minRange, UInt16 maxRange)
  188. {
  189. UInt16 value;
  190. if (UInt16.TryParse(text, out value))
  191. {
  192. if (value >= minRange && value <= maxRange)
  193. {
  194. return true;
  195. }
  196. }
  197. return false;
  198. }
  199. public static bool IsTextInteger(string text)
  200. {
  201. UInt64 value;
  202. return UInt64.TryParse(text, out value);
  203. }
  204. public static bool IsTextFloatInRange(string text, double minRange, double maxRange)
  205. {
  206. return IsTextFloatInRange(text, minRange, maxRange, GarminFitnessView.UICulture);
  207. }
  208. public static bool IsTextFloatInRange(string text, double minRange, double maxRange, CultureInfo culture)
  209. {
  210. double value;
  211. if (double.TryParse(text, NumberStyles.Float, culture.NumberFormat, out value))
  212. {
  213. if (value >= minRange && value <= maxRange)
  214. {
  215. return true;
  216. }
  217. }
  218. return false;
  219. }
  220. public static bool IsTextTimeInRange(string text, double minRange, double maxRange)
  221. {
  222. try
  223. {
  224. float value = TimeToFloat(text);
  225. if (value < minRange || value > maxRange)
  226. {
  227. return false;
  228. }
  229. return true;
  230. }
  231. catch (Exception)
  232. {
  233. return false;
  234. }
  235. }
  236. public static float TimeToFloat(string time)
  237. {
  238. if (time.IndexOf(':') != -1)
  239. {
  240. string minutes = time.Substring(0, time.IndexOf(':'));
  241. string seconds = time.Substring(time.IndexOf(':') + 1);
  242. float value = 0;
  243. if (minutes != String.Empty)
  244. {
  245. value += float.Parse(minutes);
  246. }
  247. value += float.Parse(seconds) / Constants.SecondsPerMinute;
  248. return value;
  249. }
  250. else
  251. {
  252. // We only have minutes
  253. return float.Parse(time);
  254. }
  255. }
  256. public static string DoubleToTimeString(double time)
  257. {
  258. UInt16 min, sec;
  259. DoubleToTime(time, out min, out sec);
  260. return String.Format("{0:00}:{1:00}", min, sec);
  261. }
  262. public static void DoubleToTime(double timeInMinutes, out UInt16 minutes, out UInt16 seconds)
  263. {
  264. minutes = (UInt16)(timeInMinutes);
  265. seconds = (UInt16)Math.Round((timeInMinutes - (UInt16)timeInMinutes) * Constants.SecondsPerMinute, MidpointRounding.AwayFromZero);
  266. if(seconds == Constants.SecondsPerMinute)
  267. {
  268. minutes++;
  269. seconds = 0;
  270. }
  271. }
  272. public static double SpeedToPace(double speed)
  273. {
  274. return Constants.MinutesPerHour / speed;
  275. }
  276. public static double PaceToSpeed(double pace)
  277. {
  278. return Constants.MinutesPerHour / pace;
  279. }
  280. public static bool GetStepInfo(IStep step, List<IStep> referenceList, out List<IStep> owningList, out UInt16 index)
  281. {
  282. owningList = null;
  283. index = 0;
  284. for (UInt16 i = 0; i < referenceList.Count; ++i)
  285. {
  286. IStep currentStep = referenceList[i];
  287. if (currentStep == step)
  288. {
  289. owningList = referenceList;
  290. index = i;
  291. return true;
  292. }
  293. else if (currentStep.Type == IStep.StepType.Repeat)
  294. {
  295. RepeatStep concreteStep = (RepeatStep)currentStep;
  296. if (GetStepInfo(step, concreteStep.StepsToRepeat, out owningList, out index))
  297. {
  298. return true;
  299. }
  300. }
  301. }
  302. return false;
  303. }
  304. public static void SerializeSTZoneInfoXML(IStep step, IZoneCategory categoryZones, INamedLowHighZone zone, XmlDocument document)
  305. {
  306. int index = categoryZones.Zones.IndexOf(zone);
  307. if (index != -1)
  308. {
  309. XmlNode extensionNode;
  310. XmlNode categoryNode;
  311. XmlNode valueNode;
  312. extensionNode = document.CreateElement("TargetOverride");
  313. // Step Id node
  314. valueNode = document.CreateElement("StepId");
  315. extensionNode.AppendChild(valueNode);
  316. valueNode.AppendChild(document.CreateTextNode(step.ParentWorkout.GetStepExportId(step).ToString()));
  317. // Category node
  318. categoryNode = document.CreateElement("Category");
  319. extensionNode.AppendChild(categoryNode);
  320. // RefId
  321. GarminFitnessString categoryRefID = new GarminFitnessString(categoryZones.ReferenceId);
  322. categoryRefID.Serialize(categoryNode, "Id", document);
  323. // Zone index
  324. GarminFitnessInt32Range zoneIndex = new GarminFitnessInt32Range(index);
  325. zoneIndex.Serialize(categoryNode, "Index", document);
  326. step.ParentWorkout.AddSportTracksExtension(extensionNode);
  327. }
  328. }
  329. public static string GetWorkoutFilename(IWorkout workout, GarminWorkoutManager.FileFormats format)
  330. {
  331. string fileName = workout.Name;
  332. // Replace invalid characters by underscores
  333. fileName = fileName.Replace('\\', '_');
  334. fileName = fileName.Replace('/', '_');
  335. fileName = fileName.Replace(':', '_');
  336. fileName = fileName.Replace('*', '_');
  337. fileName = fileName.Replace('?', '_');
  338. fileName = fileName.Replace('"', '_');
  339. fileName = fileName.Replace('<', '_');
  340. fileName = fileName.Replace('>', '_');
  341. fileName = fileName.Replace('|', '_');
  342. fileName = fileName.Replace('.', '_');
  343. fileName = fileName.Replace('&', '_');
  344. fileName = fileName.Replace('%', '_');
  345. if (format == GarminWorkoutManager.FileFormats.TCX)
  346. {
  347. fileName += ".tcx";
  348. }
  349. else if (format == GarminWorkoutManager.FileFormats.FIT)
  350. {
  351. fileName += ".fit";
  352. }
  353. else
  354. {
  355. Debug.Assert(false);
  356. }
  357. return fileName;
  358. }
  359. public static FITSports GetFITSport(GarminCategories category)
  360. {
  361. if (category == GarminCategories.Biking)
  362. {
  363. return FITSports.Cycling;
  364. }
  365. else if (category == GarminCategories.Running)
  366. {
  367. return FITSports.Running;
  368. }
  369. return FITSports.Other;
  370. }
  371. public static string GetFITSportName(GarminCategories sport)
  372. {
  373. switch(sport)
  374. {
  375. case GarminCategories.Running:
  376. {
  377. return "Running";
  378. }
  379. case GarminCategories.Biking:
  380. {
  381. return "Cycling";
  382. }
  383. default:
  384. {
  385. return "Other";
  386. }
  387. }
  388. }
  389. public static double Clamp(double value, double min, double max)
  390. {
  391. return Math.Max(Math.Min(value, max), min);
  392. }
  393. public static bool IsMetric(Length.Units unit)
  394. {
  395. return (int)unit <= (int)Length.Units.Kilometer;
  396. }
  397. public static bool IsStatute(Length.Units unit)
  398. {
  399. return !IsMetric(unit);
  400. }
  401. }
  402. }