ConfigOption.h 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245
  1. #pragma once
  2. #pragma warning(push)
  3. #pragma warning(disable: 4947)
  4. #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
  5. // Windows Header Files
  6. #include <windows.h>
  7. #include <string>
  8. #include <fstream>
  9. #include <vector>
  10. #include <msclr\marshal_cppstd.h>
  11. #include "PluginConfigApi.h"
  12. #include "IniReader.h"
  13. using namespace System;
  14. using namespace System::Windows::Forms;
  15. float BaseScaleSize = 96;
  16. int Col1Width = 110;
  17. int Col2Left = 140;
  18. int Col2Width = 90;
  19. int ConfigBtnLeft = 120;
  20. int ControlSpacing = 6;
  21. // declare this early (actual definitions below)
  22. class ConfigOptionBase;
  23. Panel^ MakePanel(int width, int height, std::vector<ConfigOptionBase*> &cfg, ToolTip^ tooltip, bool* hasChanged);
  24. #define RESOPT_MATCH_WINDOW_TEXT "Match Window"
  25. #define RESOPT_MATCH_SCREEN_TEXT "Match Screen"
  26. #define RESOPT_DEFAULT_TEXT "Default"
  27. ref class ComboboxValidation
  28. {
  29. public:
  30. ComboBox^ cb;
  31. ComboboxValidation(ComboBox^ combobox)
  32. {
  33. cb = combobox;
  34. }
  35. System::Void CheckNumberLeave(System::Object^ sender, System::EventArgs^ e)
  36. {
  37. System::String^ text = cb->Text;
  38. cli::array<Char>^ digitsarray = gcnew cli::array<Char>{ L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7', L'8', L'9' };
  39. System::Collections::Generic::List<Char>^ digitslist = gcnew System::Collections::Generic::List<Char>(digitsarray);
  40. if (text->Length <= 0)
  41. return;
  42. while (text->Length > 0 && text[0] != L'-' && !digitslist->Contains(text[0]))
  43. {
  44. text = text->Remove(0, 1);
  45. }
  46. if (text->Length <= 1) // can discard up to 1 now because first digit is known good
  47. {
  48. cb->Text = text;
  49. return;
  50. }
  51. for (int i = 1; i < text->Length; i++)
  52. {
  53. if (!digitslist->Contains(text[i]))
  54. {
  55. text = text->Remove(i, 1);
  56. i--; // negate the upcoming ++
  57. }
  58. }
  59. cb->Text = text;
  60. }
  61. System::Void CheckResolutionLeave(System::Object^ sender, System::EventArgs^ e)
  62. {
  63. System::String^ text = cb->Text;
  64. if (text == RESOPT_MATCH_WINDOW_TEXT || text == RESOPT_MATCH_SCREEN_TEXT || text == RESOPT_DEFAULT_TEXT)
  65. return;
  66. cli::array<Char>^ digitsarray = gcnew cli::array<Char>{ L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7', L'8', L'9' };
  67. System::Collections::Generic::List<Char>^ digitslist = gcnew System::Collections::Generic::List<Char>(digitsarray);
  68. int numX = 0;
  69. while (text->Length > 0 && text[0] != L'x' && !digitslist->Contains(text[0]))
  70. {
  71. text = text->Remove(0, 1);
  72. }
  73. if (text->Length <= 0)
  74. {
  75. cb->Text = "x";
  76. return;
  77. }
  78. if (text[0] == L'x')
  79. {
  80. numX++;
  81. }
  82. if (text->Length <= 1) // can discard up to 1 now because first digit is known good
  83. {
  84. if (numX == 0) // if that digit wasn't an x though, add one
  85. {
  86. text += "x";
  87. }
  88. cb->Text = text;
  89. return;
  90. }
  91. for (int i = 1; i < text->Length; i++)
  92. {
  93. if (!digitslist->Contains(text[i]) && !(numX == 0 && text[i] == L'x' && ++numX))
  94. {
  95. text = text->Remove(i, 1);
  96. i--; // negate the upcoming ++
  97. }
  98. }
  99. if (numX == 0)
  100. {
  101. text += "x";
  102. }
  103. cb->Text = text;
  104. }
  105. };
  106. ref class PluginConfigHandler
  107. {
  108. public:
  109. Form^ form;
  110. PluginConfigHandler(Panel^ optspanel, String^ title, float btnScaleSize)
  111. {
  112. form = gcnew Form();
  113. form->Text = title;
  114. form->FormBorderStyle = FormBorderStyle::FixedDialog;
  115. form->StartPosition = FormStartPosition::CenterScreen;
  116. form->MaximizeBox = false;
  117. form->MinimizeBox = false;
  118. form->ShowInTaskbar = false;
  119. form->ShowIcon = false;
  120. //form->TopMost = true;
  121. form->BackColor = Drawing::Color::FromArgb(64, 64, 64);
  122. form->ForeColor = Drawing::Color::White;
  123. form->Font = optspanel->Font;
  124. optspanel->Left = 0;
  125. optspanel->Top = 0;
  126. Button^ OkBtn = gcnew Button();
  127. OkBtn->Scale(btnScaleSize);
  128. OkBtn->Text = L"OK";
  129. OkBtn->Left = 4;
  130. OkBtn->Top = optspanel->Bottom + 4;
  131. OkBtn->AutoSize = true;
  132. OkBtn->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
  133. form->ClientSize = Drawing::Size(optspanel->Width, OkBtn->Bottom + 4);
  134. form->Controls->Add(optspanel);
  135. form->Controls->Add(OkBtn);
  136. form->AcceptButton = OkBtn;
  137. form->FormClosing += gcnew System::Windows::Forms::FormClosingEventHandler(this, &PluginConfigHandler::FormClosing);
  138. OkBtn->Click += gcnew EventHandler(this, &PluginConfigHandler::OkClick);
  139. }
  140. System::Void OpenForm(System::Object^ sender, System::EventArgs^ e)
  141. {
  142. // ShowDialog seems to prevent disposal by copying the panel...
  143. // which would be fine if I didn't rely on using the control handles
  144. // MessageBox::Show(form->Controls[0]->Handle.ToString());
  145. //Application::OpenForms[0]->Enabled = false;
  146. form->Owner = Application::OpenForms[0];
  147. if (form->Visible)
  148. form->Hide();
  149. form->Show();
  150. }
  151. System::Void FormClosing(System::Object^ sender, FormClosingEventArgs^ e)
  152. {
  153. if (e->CloseReason == CloseReason::UserClosing)
  154. {
  155. form->Hide();
  156. //Application::OpenForms[0]->Enabled = true;
  157. e->Cancel = true;
  158. }
  159. }
  160. System::Void OkClick(System::Object^ sender, System::EventArgs^ e)
  161. {
  162. form->Close();
  163. }
  164. };
  165. ref class ChangeHandler
  166. {
  167. public:
  168. bool* changebool;
  169. ChangeHandler(bool* onchangebool)
  170. {
  171. changebool = onchangebool;
  172. }
  173. System::Void SetChanged(System::Object^ sender, System::EventArgs^ e)
  174. {
  175. *changebool = true;
  176. }
  177. };
  178. ref class CustomFuncHandler
  179. {
  180. public:
  181. void(*_func)();
  182. CustomFuncHandler(void(*func)())
  183. {
  184. _func = func;
  185. }
  186. System::Void RunFunc(System::Object^ sender, System::EventArgs^ e)
  187. {
  188. _func();
  189. }
  190. };
  191. class ConfigOptionBase
  192. {
  193. public:
  194. LPCWSTR _iniVarName;
  195. LPCWSTR _iniSectionName;
  196. LPCWSTR _iniFilePath;
  197. LPCWSTR _friendlyName;
  198. LPCWSTR _description;
  199. System::IntPtr mainControlHandle;
  200. bool* hasChanged;
  201. virtual int AddToPanel(Panel^ panel, unsigned int left, unsigned int top, ToolTip^ tooltip)
  202. {
  203. return 0;
  204. }
  205. virtual void SaveOption()
  206. {
  207. return;
  208. }
  209. };
  210. class OptionMetaGroupStart : public ConfigOptionBase
  211. {
  212. public:
  213. int _height;
  214. OptionMetaGroupStart(LPCWSTR friendlyName, int height)
  215. {
  216. _friendlyName = friendlyName;
  217. _height = height;
  218. }
  219. };
  220. class OptionMetaGroupEnd : public ConfigOptionBase
  221. {
  222. public:
  223. OptionMetaGroupEnd()
  224. {
  225. }
  226. };
  227. class OptionMetaSectionLabel : public ConfigOptionBase
  228. {
  229. public:
  230. OptionMetaSectionLabel(LPCWSTR friendlyName)
  231. {
  232. _friendlyName = friendlyName;
  233. }
  234. virtual int AddToPanel(Panel^ panel, unsigned int left, unsigned int top, ToolTip^ tooltip)
  235. {
  236. Label^ lab = gcnew Label();
  237. lab->Text = gcnew String(_friendlyName);
  238. lab->Left = left + 2;
  239. lab->Top = top;
  240. lab->Font = gcnew System::Drawing::Font(lab->Font->Name, 12.0f, System::Drawing::FontStyle::Bold);
  241. lab->AutoSize = true;
  242. Form^ RootForm = panel->FindForm();
  243. float ScaleWidth = 1.0f;
  244. float ScaleHeight = 1.0f;
  245. if (RootForm)
  246. {
  247. Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
  248. ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
  249. ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
  250. }
  251. lab->Scale(ScaleWidth, ScaleHeight);
  252. panel->Controls->Add(lab);
  253. mainControlHandle = lab->Handle;
  254. int ControlHeight = lab->Font->Height / ScaleHeight;
  255. return ControlHeight + ControlSpacing;
  256. }
  257. };
  258. class OptionMetaSpacer : public ConfigOptionBase
  259. {
  260. public:
  261. int _height;
  262. OptionMetaSpacer(int height)
  263. {
  264. _height = height;
  265. }
  266. virtual int AddToPanel(Panel^ panel, unsigned int left, unsigned int top, ToolTip^ tooltip)
  267. {
  268. return _height;
  269. }
  270. };
  271. class OptionMetaSeparator : public ConfigOptionBase
  272. {
  273. public:
  274. OptionMetaSeparator()
  275. {
  276. }
  277. virtual int AddToPanel(Panel^ panel, unsigned int left, unsigned int top, ToolTip^ tooltip)
  278. {
  279. Label^ lab = gcnew Label();
  280. lab->Text = "_____________________________________";
  281. lab->Left = left + 2;
  282. lab->Top = top;
  283. lab->AutoSize = true;
  284. Form^ RootForm = panel->FindForm();
  285. float ScaleWidth = 1.0f;
  286. float ScaleHeight = 1.0f;
  287. if (RootForm)
  288. {
  289. Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
  290. ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
  291. ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
  292. }
  293. lab->Scale(ScaleWidth, ScaleHeight);
  294. panel->Controls->Add(lab);
  295. mainControlHandle = lab->Handle;
  296. int ControlHeight = lab->Font->Height / ScaleHeight;
  297. return ControlHeight + ControlSpacing;
  298. }
  299. };
  300. class BooleanOption : public ConfigOptionBase
  301. {
  302. public:
  303. bool _defaultVal;
  304. bool _saveAsString;
  305. BooleanOption(LPCWSTR iniVarName, LPCWSTR iniSectionName, LPCWSTR iniFilePath, LPCWSTR friendlyName, LPCWSTR description, bool defaultVal, bool saveAsString)
  306. {
  307. _iniVarName = iniVarName;
  308. _iniSectionName = iniSectionName;
  309. _iniFilePath = iniFilePath;
  310. _friendlyName = friendlyName;
  311. _description = description;
  312. _defaultVal = defaultVal;
  313. _saveAsString = saveAsString;
  314. }
  315. virtual int AddToPanel(Panel^ panel, unsigned int left, unsigned int top, ToolTip^ tooltip)
  316. {
  317. CheckBox^ cb = gcnew CheckBox();
  318. cb->Text = gcnew String(_friendlyName);
  319. cb->Checked = GetIniBool(_iniSectionName, _iniVarName, _defaultVal, _iniFilePath);
  320. cb->Left = left + 2;
  321. cb->Top = top;
  322. cb->AutoSize = true;
  323. cb->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
  324. // hack to ensure high contrast
  325. cb->BackColor = System::Drawing::Color::FromArgb(0, 127, 127, 127);
  326. Form^ RootForm = panel->FindForm();
  327. float ScaleWidth = 1.0f;
  328. float ScaleHeight = 1.0f;
  329. if (RootForm)
  330. {
  331. Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
  332. ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
  333. ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
  334. }
  335. cb->Scale(ScaleWidth, ScaleHeight);
  336. tooltip->SetToolTip(cb, gcnew String(_description));
  337. if (hasChanged == nullptr)
  338. hasChanged = new bool(false);
  339. ChangeHandler^ changehandler = gcnew ChangeHandler(hasChanged);
  340. cb->CheckedChanged += gcnew System::EventHandler(changehandler, &ChangeHandler::SetChanged);
  341. panel->Controls->Add(cb);
  342. mainControlHandle = cb->Handle;
  343. int ControlHeight = cb->Font->Height / ScaleHeight;
  344. return ControlHeight + ControlSpacing;
  345. }
  346. virtual void SaveOption()
  347. {
  348. SetIniBool(_iniSectionName, _iniVarName, ((CheckBox^)CheckBox::FromHandle(mainControlHandle))->Checked, _iniFilePath, _saveAsString);
  349. }
  350. };
  351. class NumericOption : public ConfigOptionBase
  352. {
  353. public:
  354. int _defaultVal;
  355. int _minVal;
  356. int _maxVal;
  357. NumericOption(LPCWSTR iniVarName, LPCWSTR iniSectionName, LPCWSTR iniFilePath, LPCWSTR friendlyName, LPCWSTR description, int defaultVal, int minVal, int maxVal)
  358. {
  359. _iniVarName = iniVarName;
  360. _iniSectionName = iniSectionName;
  361. _iniFilePath = iniFilePath;
  362. _friendlyName = friendlyName;
  363. _description = description;
  364. _defaultVal = defaultVal;
  365. _minVal = minVal;
  366. _maxVal = maxVal;
  367. }
  368. virtual int AddToPanel(Panel^ panel, unsigned int left, unsigned int top, ToolTip^ tooltip)
  369. {
  370. Label^ label = gcnew Label();
  371. NumericUpDown^ numberbox = gcnew NumericUpDown();
  372. label->Text = gcnew String(_friendlyName);
  373. label->Left = left;
  374. label->Top = top + 3;
  375. label->Width = Col1Width;
  376. label->AutoSize = true;
  377. label->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
  378. numberbox->Minimum = _minVal;
  379. numberbox->Maximum = _maxVal;
  380. numberbox->Value = GetIniInt(_iniSectionName, _iniVarName, _defaultVal, _iniFilePath);
  381. numberbox->Left = left + Col2Left;
  382. numberbox->Top = top;
  383. numberbox->Width = Col2Width;
  384. numberbox->AutoSize = true;
  385. Form^ RootForm = panel->FindForm();
  386. float ScaleWidth = 1.0f;
  387. float ScaleHeight = 1.0f;
  388. if (RootForm)
  389. {
  390. Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
  391. ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
  392. ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
  393. }
  394. label->Scale(ScaleWidth, ScaleHeight);
  395. numberbox->Scale(ScaleWidth, ScaleHeight);
  396. tooltip->SetToolTip(label, gcnew String(_description));
  397. tooltip->SetToolTip(numberbox, gcnew String(_description));
  398. if (hasChanged == nullptr)
  399. hasChanged = new bool(false);
  400. ChangeHandler^ changehandler = gcnew ChangeHandler(hasChanged);
  401. numberbox->ValueChanged += gcnew System::EventHandler(changehandler, &ChangeHandler::SetChanged);
  402. panel->Controls->Add(label);
  403. panel->Controls->Add(numberbox);
  404. mainControlHandle = numberbox->Handle;
  405. int ControlHeight = numberbox->Height / ScaleHeight;
  406. return ControlHeight + ControlSpacing;
  407. }
  408. virtual void SaveOption()
  409. {
  410. SetIniInt(_iniSectionName, _iniVarName, Convert::ToInt32(((NumericUpDown^)NumericUpDown::FromHandle(mainControlHandle))->Value), _iniFilePath);
  411. }
  412. };
  413. class StringOption : public ConfigOptionBase
  414. {
  415. public:
  416. LPCWSTR _defaultVal;
  417. bool _useUtf8;
  418. StringOption(LPCWSTR iniVarName, LPCWSTR iniSectionName, LPCWSTR iniFilePath, LPCWSTR friendlyName, LPCWSTR description, LPCWSTR defaultVal, bool useUtf8)
  419. {
  420. _iniVarName = iniVarName;
  421. _iniSectionName = iniSectionName;
  422. _iniFilePath = iniFilePath;
  423. _friendlyName = friendlyName;
  424. _description = description;
  425. _defaultVal = defaultVal;
  426. _useUtf8 = useUtf8;
  427. }
  428. virtual int AddToPanel(Panel^ panel, unsigned int left, unsigned int top, ToolTip^ tooltip)
  429. {
  430. Label^ label = gcnew Label();
  431. TextBox^ textbox = gcnew TextBox();
  432. const wchar_t* stringBuf;
  433. label->Text = gcnew String(_friendlyName);
  434. label->Left = left;
  435. label->Top = top + 3;
  436. label->Width = Col1Width;
  437. label->AutoSize = true;
  438. label->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
  439. stringBuf = GetIniString(_iniSectionName, _iniVarName, _defaultVal, _iniFilePath, _useUtf8);
  440. textbox->Text = gcnew String(stringBuf);
  441. textbox->Left = left + Col2Left;
  442. textbox->Top = top;
  443. textbox->Width = Col2Width;
  444. textbox->AutoSize = true;
  445. Form^ RootForm = panel->FindForm();
  446. float ScaleWidth = 1.0f;
  447. float ScaleHeight = 1.0f;
  448. if (RootForm)
  449. {
  450. Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
  451. ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
  452. ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
  453. }
  454. label->Scale(ScaleWidth, ScaleHeight);
  455. textbox->Scale(ScaleWidth, ScaleHeight);
  456. // disable editing for utf8 mode because the ANSI hack used may not work correctly
  457. //if (_useUtf8) {
  458. // textbox->Enabled = false;
  459. //}
  460. tooltip->SetToolTip(label, gcnew String(_description));
  461. tooltip->SetToolTip(textbox, gcnew String(_description));
  462. if (hasChanged == nullptr)
  463. hasChanged = new bool(false);
  464. ChangeHandler^ changehandler = gcnew ChangeHandler(hasChanged);
  465. textbox->TextChanged += gcnew System::EventHandler(changehandler, &ChangeHandler::SetChanged);
  466. panel->Controls->Add(label);
  467. panel->Controls->Add(textbox);
  468. mainControlHandle = textbox->Handle;
  469. int ControlHeight = textbox->Height / ScaleHeight;
  470. return ControlHeight + ControlSpacing;
  471. }
  472. virtual void SaveOption()
  473. {
  474. // disable saving for utf8 mode because the ANSI hack used may not work correctly
  475. //if (_useUtf8)
  476. // return;
  477. System::String^ tempSysStr;
  478. std::wstring tempWStr;
  479. tempSysStr = ((TextBox^)TextBox::FromHandle(mainControlHandle))->Text;
  480. tempWStr = msclr::interop::marshal_as<std::wstring>(tempSysStr);
  481. SetIniString(_iniSectionName, _iniVarName, tempWStr.c_str(), _iniFilePath, _useUtf8);
  482. }
  483. };
  484. class DropdownOption : public ConfigOptionBase
  485. {
  486. public:
  487. int _defaultVal;
  488. int _indexOffset;
  489. std::vector<LPCWSTR> _valueStrings;
  490. DropdownOption(LPCWSTR iniVarName, LPCWSTR iniSectionName, LPCWSTR iniFilePath, LPCWSTR friendlyName, LPCWSTR description, int defaultVal, std::vector<LPCWSTR> valueStrings, int indexOffset=0)
  491. {
  492. _iniVarName = iniVarName;
  493. _iniSectionName = iniSectionName;
  494. _iniFilePath = iniFilePath;
  495. _friendlyName = friendlyName;
  496. _description = description;
  497. _defaultVal = defaultVal;
  498. _valueStrings = valueStrings;
  499. _indexOffset = indexOffset;
  500. }
  501. virtual int AddToPanel(Panel^ panel, unsigned int left, unsigned int top, ToolTip^ tooltip)
  502. {
  503. Label^ label = gcnew Label();
  504. ComboBox^ combobox = gcnew ComboBox();
  505. label->Text = gcnew String(_friendlyName);
  506. label->Left = left;
  507. label->Top = top + 3;
  508. label->Width = Col1Width;
  509. label->AutoSize = true;
  510. label->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
  511. for (LPCWSTR& choice : _valueStrings) {
  512. combobox->Items->Add(msclr::interop::marshal_as<System::String^>(choice));
  513. }
  514. combobox->SelectedIndex = GetIniInt(_iniSectionName, _iniVarName, _defaultVal, _iniFilePath)-_indexOffset;
  515. combobox->Left = left + Col2Left;
  516. combobox->Top = top;
  517. combobox->Width = Col2Width;
  518. combobox->AutoSize = true;
  519. combobox->FlatStyle = System::Windows::Forms::FlatStyle::System;
  520. combobox->DropDownStyle = ComboBoxStyle::DropDownList;
  521. Form^ RootForm = panel->FindForm();
  522. float ScaleWidth = 1.0f;
  523. float ScaleHeight = 1.0f;
  524. if (RootForm)
  525. {
  526. Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
  527. ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
  528. ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
  529. }
  530. label->Scale(ScaleWidth, ScaleHeight);
  531. combobox->Scale(ScaleWidth, ScaleHeight);
  532. tooltip->SetToolTip(label, gcnew String(_description));
  533. tooltip->SetToolTip(combobox, gcnew String(_description));
  534. if (hasChanged == nullptr)
  535. hasChanged = new bool(false);
  536. ChangeHandler^ changehandler = gcnew ChangeHandler(hasChanged);
  537. combobox->SelectedIndexChanged += gcnew System::EventHandler(changehandler, &ChangeHandler::SetChanged);
  538. panel->Controls->Add(label);
  539. panel->Controls->Add(combobox);
  540. mainControlHandle = combobox->Handle;
  541. int ControlHeight = combobox->Height / ScaleHeight;
  542. return ControlHeight + ControlSpacing;
  543. }
  544. virtual void SaveOption()
  545. {
  546. SetIniInt(_iniSectionName, _iniVarName, Convert::ToInt32(((ComboBox^)ComboBox::FromHandle(mainControlHandle))->SelectedIndex+_indexOffset), _iniFilePath);
  547. }
  548. };
  549. class DropdownTextOption : public ConfigOptionBase
  550. {
  551. public:
  552. LPCWSTR _defaultVal;
  553. std::vector<LPCWSTR> _valueStrings;
  554. bool _editable;
  555. bool _useUtf8;
  556. DropdownTextOption(LPCWSTR iniVarName, LPCWSTR iniSectionName, LPCWSTR iniFilePath, LPCWSTR friendlyName, LPCWSTR description, LPCWSTR defaultVal, std::vector<LPCWSTR> valueStrings, bool editable, bool useUtf8)
  557. {
  558. _iniVarName = iniVarName;
  559. _iniSectionName = iniSectionName;
  560. _iniFilePath = iniFilePath;
  561. _friendlyName = friendlyName;
  562. _description = description;
  563. _defaultVal = defaultVal;
  564. _valueStrings = valueStrings;
  565. _editable = editable;
  566. _useUtf8 = useUtf8;
  567. }
  568. virtual int AddToPanel(Panel^ panel, unsigned int left, unsigned int top, ToolTip^ tooltip)
  569. {
  570. Label^ label = gcnew Label();
  571. ComboBox^ combobox = gcnew ComboBox();
  572. const wchar_t* stringBuf;
  573. label->Text = gcnew String(_friendlyName);
  574. label->Left = left;
  575. label->Top = top + 3;
  576. label->Width = Col1Width;
  577. label->AutoSize = true;
  578. label->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
  579. for (LPCWSTR& choice : _valueStrings) {
  580. combobox->Items->Add(msclr::interop::marshal_as<System::String^>(choice));
  581. }
  582. stringBuf = GetIniString(_iniSectionName, _iniVarName, _defaultVal, _iniFilePath, _useUtf8);
  583. combobox->Text = gcnew String(stringBuf);
  584. combobox->Left = left + Col2Left;
  585. combobox->Top = top;
  586. combobox->Width = Col2Width;
  587. combobox->AutoSize = true;
  588. combobox->FlatStyle = System::Windows::Forms::FlatStyle::System;
  589. if (_editable)
  590. combobox->DropDownStyle = ComboBoxStyle::DropDown;
  591. else
  592. combobox->DropDownStyle = ComboBoxStyle::DropDownList;
  593. Form^ RootForm = panel->FindForm();
  594. float ScaleWidth = 1.0f;
  595. float ScaleHeight = 1.0f;
  596. if (RootForm)
  597. {
  598. Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
  599. ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
  600. ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
  601. }
  602. label->Scale(ScaleWidth, ScaleHeight);
  603. combobox->Scale(ScaleWidth, ScaleHeight);
  604. // disable editing for utf8 mode because the ANSI hack used may not work correctly
  605. //if (_useUtf8) {
  606. // label->Enabled = false;
  607. // combobox->Enabled = false;
  608. //}
  609. tooltip->SetToolTip(label, gcnew String(_description));
  610. tooltip->SetToolTip(combobox, gcnew String(_description));
  611. if (hasChanged == nullptr)
  612. hasChanged = new bool(false);
  613. ChangeHandler^ changehandler = gcnew ChangeHandler(hasChanged);
  614. if (_editable)
  615. combobox->TextChanged += gcnew System::EventHandler(changehandler, &ChangeHandler::SetChanged);
  616. else
  617. combobox->SelectedIndexChanged += gcnew System::EventHandler(changehandler, &ChangeHandler::SetChanged);
  618. panel->Controls->Add(label);
  619. panel->Controls->Add(combobox);
  620. mainControlHandle = combobox->Handle;
  621. int ControlHeight = combobox->Height / ScaleHeight;
  622. return ControlHeight + ControlSpacing;
  623. }
  624. virtual void SaveOption()
  625. {
  626. // disable saving for utf8 mode because the ANSI hack used may not work correctly
  627. //if (_useUtf8)
  628. // return;
  629. System::String^ tempSysStr;
  630. std::wstring tempWStr;
  631. tempSysStr = ((ComboBox^)ComboBox::FromHandle(mainControlHandle))->Text;
  632. tempWStr = msclr::interop::marshal_as<std::wstring>(tempSysStr);
  633. SetIniString(_iniSectionName, _iniVarName, tempWStr.c_str(), _iniFilePath, _useUtf8);
  634. }
  635. };
  636. class DropdownNumberOption : public ConfigOptionBase
  637. {
  638. public:
  639. int _defaultVal;
  640. std::vector<int> _valueInts;
  641. bool _editable;
  642. DropdownNumberOption(LPCWSTR iniVarName, LPCWSTR iniSectionName, LPCWSTR iniFilePath, LPCWSTR friendlyName, LPCWSTR description, int defaultVal, std::vector<int> valueInts, bool editable)
  643. {
  644. _iniVarName = iniVarName;
  645. _iniSectionName = iniSectionName;
  646. _iniFilePath = iniFilePath;
  647. _friendlyName = friendlyName;
  648. _description = description;
  649. _defaultVal = defaultVal;
  650. _valueInts = valueInts;
  651. _editable = editable;
  652. }
  653. virtual int AddToPanel(Panel^ panel, unsigned int left, unsigned int top, ToolTip^ tooltip)
  654. {
  655. Label^ label = gcnew Label();
  656. ComboBox^ combobox = gcnew ComboBox();
  657. System::String^ tempSysStr;
  658. label->Text = gcnew String(_friendlyName);
  659. label->Left = left;
  660. label->Top = top + 3;
  661. label->Width = Col1Width;
  662. label->AutoSize = true;
  663. label->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
  664. for (int& choice : _valueInts) {
  665. combobox->Items->Add(Convert::ToInt32(choice).ToString());
  666. }
  667. tempSysStr = Convert::ToInt32(GetIniInt(_iniSectionName, _iniVarName, _defaultVal, _iniFilePath)).ToString();
  668. combobox->Text = gcnew String(tempSysStr);
  669. combobox->Left = left + Col2Left;
  670. combobox->Top = top;
  671. combobox->Width = Col2Width;
  672. combobox->AutoSize = true;
  673. combobox->FlatStyle = System::Windows::Forms::FlatStyle::System;
  674. if (_editable)
  675. combobox->DropDownStyle = ComboBoxStyle::DropDown;
  676. else
  677. combobox->DropDownStyle = ComboBoxStyle::DropDownList;
  678. Form^ RootForm = panel->FindForm();
  679. float ScaleWidth = 1.0f;
  680. float ScaleHeight = 1.0f;
  681. if (RootForm)
  682. {
  683. Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
  684. ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
  685. ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
  686. }
  687. label->Scale(ScaleWidth, ScaleHeight);
  688. combobox->Scale(ScaleWidth, ScaleHeight);
  689. tooltip->SetToolTip(label, gcnew String(_description));
  690. tooltip->SetToolTip(combobox, gcnew String(_description));
  691. ComboboxValidation^ validation = gcnew ComboboxValidation(combobox);
  692. combobox->Leave += gcnew System::EventHandler(validation, &ComboboxValidation::CheckNumberLeave);
  693. if (hasChanged == nullptr)
  694. hasChanged = new bool(false);
  695. ChangeHandler^ changehandler = gcnew ChangeHandler(hasChanged);
  696. if (_editable)
  697. combobox->TextChanged += gcnew System::EventHandler(changehandler, &ChangeHandler::SetChanged);
  698. else
  699. combobox->SelectedIndexChanged += gcnew System::EventHandler(changehandler, &ChangeHandler::SetChanged);
  700. panel->Controls->Add(label);
  701. panel->Controls->Add(combobox);
  702. mainControlHandle = combobox->Handle;
  703. int ControlHeight = combobox->Height / ScaleHeight;
  704. return ControlHeight + ControlSpacing;
  705. }
  706. virtual void SaveOption()
  707. {
  708. System::String^ tempSysStr;
  709. std::wstring tempWStr;
  710. tempSysStr = ((ComboBox^)ComboBox::FromHandle(mainControlHandle))->Text;
  711. tempWStr = msclr::interop::marshal_as<std::wstring>(tempSysStr);
  712. SetIniString(_iniSectionName, _iniVarName, tempWStr.c_str(), _iniFilePath, false);
  713. }
  714. };
  715. enum ResolutionOptionOpts
  716. {
  717. RESOPT_NONE,
  718. RESOPT_INCLUDE_MATCH_WINDOW,
  719. RESOPT_INCLUDE_MATCH_SCREEN,
  720. RESOPT_INCLUDE_DEFAULT = 4
  721. };
  722. class ResolutionOption : public ConfigOptionBase
  723. {
  724. public:
  725. LPCWSTR _iniVarName2;
  726. resolution _defaultVal;
  727. std::vector<resolution> _valueResolutions;
  728. bool _editable;
  729. ResolutionOptionOpts _opts;
  730. ResolutionOption(LPCWSTR iniVarName, LPCWSTR iniVarName2, LPCWSTR iniSectionName, LPCWSTR iniFilePath, LPCWSTR friendlyName, LPCWSTR description, resolution defaultVal, std::vector<resolution> valueResolutions, bool editable, ResolutionOptionOpts opts)
  731. {
  732. _iniVarName = iniVarName;
  733. _iniVarName2 = iniVarName2;
  734. _iniSectionName = iniSectionName;
  735. _iniFilePath = iniFilePath;
  736. _friendlyName = friendlyName;
  737. _description = description;
  738. _defaultVal = defaultVal;
  739. _valueResolutions = valueResolutions;
  740. _editable = editable;
  741. _opts = opts;
  742. }
  743. virtual int AddToPanel(Panel^ panel, unsigned int left, unsigned int top, ToolTip^ tooltip)
  744. {
  745. Label^ label = gcnew Label();
  746. ComboBox^ combobox = gcnew ComboBox();
  747. System::String^ tempSysStr;
  748. label->Text = gcnew String(_friendlyName);
  749. label->Left = left;
  750. label->Top = top + 3;
  751. label->Width = Col1Width;
  752. label->AutoSize = true;
  753. label->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
  754. if (_opts & RESOPT_INCLUDE_MATCH_WINDOW)
  755. combobox->Items->Add(RESOPT_MATCH_WINDOW_TEXT);
  756. else if (_opts & RESOPT_INCLUDE_MATCH_SCREEN)
  757. combobox->Items->Add(RESOPT_MATCH_SCREEN_TEXT);
  758. else if (_opts & RESOPT_INCLUDE_DEFAULT)
  759. combobox->Items->Add(RESOPT_DEFAULT_TEXT);
  760. for (resolution& choice : _valueResolutions) {
  761. tempSysStr = Convert::ToInt32(choice.width).ToString() + L"x" + Convert::ToInt32(choice.height).ToString();
  762. combobox->Items->Add(tempSysStr);
  763. }
  764. int width = GetIniInt(_iniSectionName, _iniVarName, -39, _iniFilePath);
  765. int height = GetIniInt(_iniSectionName, _iniVarName2, -39, _iniFilePath);
  766. if (width == -39 || height == -39) {
  767. if (_defaultVal.width == -1 || _defaultVal.height == -1)
  768. width = -1;
  769. else
  770. {
  771. tempSysStr = Convert::ToInt32(_defaultVal.width).ToString() + L"x" + Convert::ToInt32(_defaultVal.height).ToString();
  772. combobox->Text = tempSysStr;
  773. }
  774. }
  775. if (width == -1 || height == -1) { // -1 -> Match window/screen
  776. if (_opts & RESOPT_INCLUDE_MATCH_WINDOW)
  777. combobox->Text = RESOPT_MATCH_WINDOW_TEXT;
  778. else if (_opts & RESOPT_INCLUDE_MATCH_SCREEN)
  779. combobox->Text = RESOPT_MATCH_SCREEN_TEXT;
  780. else if (_opts & RESOPT_INCLUDE_DEFAULT)
  781. combobox->Text = RESOPT_DEFAULT_TEXT;
  782. }
  783. else {
  784. tempSysStr = Convert::ToInt32(width).ToString() + L"x" + Convert::ToInt32(height).ToString();
  785. combobox->Text = tempSysStr;
  786. }
  787. combobox->Left = left + Col2Left;
  788. combobox->Top = top;
  789. combobox->Width = Col2Width;
  790. combobox->AutoSize = true;
  791. combobox->FlatStyle = System::Windows::Forms::FlatStyle::System;
  792. if (_editable)
  793. combobox->DropDownStyle = ComboBoxStyle::DropDown;
  794. else
  795. combobox->DropDownStyle = ComboBoxStyle::DropDownList;
  796. Form^ RootForm = panel->FindForm();
  797. float ScaleWidth = 1.0f;
  798. float ScaleHeight = 1.0f;
  799. if (RootForm)
  800. {
  801. Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
  802. ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
  803. ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
  804. }
  805. label->Scale(ScaleWidth, ScaleHeight);
  806. combobox->Scale(ScaleWidth, ScaleHeight);
  807. tooltip->SetToolTip(label, gcnew String(_description));
  808. tooltip->SetToolTip(combobox, gcnew String(_description));
  809. if (hasChanged == nullptr)
  810. hasChanged = new bool(false);
  811. ChangeHandler^ changehandler = gcnew ChangeHandler(hasChanged);
  812. if (_editable)
  813. combobox->TextChanged += gcnew System::EventHandler(changehandler, &ChangeHandler::SetChanged);
  814. else
  815. combobox->SelectedIndexChanged += gcnew System::EventHandler(changehandler, &ChangeHandler::SetChanged);
  816. ComboboxValidation^ validation = gcnew ComboboxValidation(combobox);
  817. combobox->Leave += gcnew System::EventHandler(validation, &ComboboxValidation::CheckResolutionLeave);
  818. panel->Controls->Add(label);
  819. panel->Controls->Add(combobox);
  820. mainControlHandle = combobox->Handle;
  821. int ControlHeight = combobox->Height / ScaleHeight;
  822. return ControlHeight + ControlSpacing;
  823. }
  824. virtual void SaveOption()
  825. {
  826. System::String^ tempSysStr;
  827. std::wstring tempWStr;
  828. cli::array<String^>^ resolutionArray;
  829. tempSysStr = ((ComboBox^)ComboBox::FromHandle(mainControlHandle))->Text;
  830. // Match window/screen -> -1x-1
  831. if (tempSysStr == RESOPT_MATCH_WINDOW_TEXT || tempSysStr == RESOPT_MATCH_SCREEN_TEXT || tempSysStr == RESOPT_DEFAULT_TEXT)
  832. tempSysStr = "-1x-1";
  833. resolutionArray = tempSysStr->Split('x');
  834. tempSysStr = resolutionArray[0];
  835. tempWStr = msclr::interop::marshal_as<std::wstring>(tempSysStr);
  836. SetIniString(_iniSectionName, _iniVarName, tempWStr.c_str(), _iniFilePath, false);
  837. tempSysStr = resolutionArray[1];
  838. tempWStr = msclr::interop::marshal_as<std::wstring>(tempSysStr);
  839. SetIniString(_iniSectionName, _iniVarName2, tempWStr.c_str(), _iniFilePath, false);
  840. }
  841. };
  842. class ButtonOption : public ConfigOptionBase
  843. {
  844. public:
  845. void(*_func)();
  846. ButtonOption(LPCWSTR friendlyName, LPCWSTR description, void(*func)())
  847. {
  848. _friendlyName = friendlyName;
  849. _description = description;
  850. _func = func;
  851. }
  852. virtual int AddToPanel(Panel^ panel, unsigned int left, unsigned int top, ToolTip^ tooltip)
  853. {
  854. Button^ button = gcnew Button();
  855. button->Text = gcnew String(_friendlyName);
  856. button->Left = left;
  857. button->Top = top;
  858. button->AutoSize = true;
  859. button->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
  860. Form^ RootForm = panel->FindForm();
  861. float ScaleWidth = 1.0f;
  862. float ScaleHeight = 1.0f;
  863. if (RootForm)
  864. {
  865. Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
  866. ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
  867. ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
  868. }
  869. button->Scale(ScaleWidth, ScaleHeight);
  870. tooltip->SetToolTip(button, gcnew String(_description));
  871. CustomFuncHandler^ funchandler = gcnew CustomFuncHandler(_func);
  872. button->Click += gcnew System::EventHandler(funchandler, &CustomFuncHandler::RunFunc);
  873. panel->Controls->Add(button);
  874. int ControlHeight = button->Height / ScaleHeight;
  875. return ControlHeight + ControlSpacing;
  876. }
  877. };
  878. class PluginOption : public ConfigOptionBase
  879. {
  880. public:
  881. bool _defaultVal;
  882. std::vector<ConfigOptionBase*> _configopts;
  883. PluginOption(LPCWSTR iniVarName, LPCWSTR iniSectionName, LPCWSTR iniFilePath, LPCWSTR friendlyName, LPCWSTR description, bool defaultVal, std::vector<ConfigOptionBase*> configopts)
  884. {
  885. _iniVarName = iniVarName;
  886. _iniSectionName = iniSectionName;
  887. _iniFilePath = iniFilePath;
  888. _friendlyName = friendlyName;
  889. _description = description;
  890. _defaultVal = defaultVal;
  891. _configopts = configopts;
  892. }
  893. virtual int AddToPanel(Panel^ panel, unsigned int left, unsigned int top, ToolTip^ tooltip)
  894. {
  895. CheckBox^ cb = gcnew CheckBox();
  896. Button^ button = gcnew Button();
  897. cb->Text = gcnew String(_friendlyName);
  898. cb->Checked = GetIniBool(_iniSectionName, _iniVarName, _defaultVal, _iniFilePath);
  899. cb->Left = left + 2;
  900. cb->Top = top + 3;
  901. cb->AutoSize = true;
  902. cb->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
  903. // hack to ensure high contrast
  904. cb->BackColor = System::Drawing::Color::FromArgb(0, 127, 127, 127);
  905. button->Text = L"Config";
  906. button->Left = left + ConfigBtnLeft;
  907. button->Top = top;
  908. button->AutoSize = true;
  909. button->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
  910. Form^ RootForm = panel->FindForm();
  911. float ScaleWidth = 1.0f;
  912. float ScaleHeight = 1.0f;
  913. if (RootForm)
  914. {
  915. Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
  916. ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
  917. ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
  918. }
  919. cb->Scale(ScaleWidth, ScaleHeight);
  920. button->Scale(ScaleWidth, ScaleHeight);
  921. tooltip->SetToolTip(cb, gcnew String(_description));
  922. if (hasChanged == nullptr)
  923. hasChanged = new bool(false);
  924. ChangeHandler^ changehandler = gcnew ChangeHandler(hasChanged);
  925. cb->CheckedChanged += gcnew System::EventHandler(changehandler, &ChangeHandler::SetChanged);
  926. panel->Controls->Add(cb);
  927. mainControlHandle = cb->Handle;
  928. if (_configopts.size() > 0)
  929. {
  930. ToolTip^ paneltooltip = gcnew ToolTip();
  931. Panel^ configPanel = MakePanel((Col2Left + Col2Width + 76), 250, _configopts, paneltooltip, hasChanged);
  932. configPanel->Scale(ScaleWidth, ScaleHeight);
  933. if (RootForm)
  934. configPanel->Font = RootForm->Font;
  935. PluginConfigHandler^ confighandler = gcnew PluginConfigHandler(configPanel, gcnew String(_friendlyName) + " Options", ScaleHeight);
  936. button->Click += gcnew System::EventHandler(confighandler, &PluginConfigHandler::OpenForm);
  937. panel->Controls->Add(button);
  938. }
  939. int ControlHeight = button->Height / ScaleHeight;
  940. return ControlHeight + ControlSpacing;
  941. }
  942. virtual void SaveOption()
  943. {
  944. SetIniBool(_iniSectionName, _iniVarName, ((CheckBox^)CheckBox::FromHandle(mainControlHandle))->Checked, _iniFilePath, false);
  945. for (ConfigOptionBase* opt : _configopts)
  946. {
  947. opt->SaveOption();
  948. }
  949. }
  950. };
  951. Panel^ MakePanel(int width, int height, std::vector<ConfigOptionBase*> &cfg, ToolTip^ tooltip, bool* hasChanged)
  952. {
  953. Panel^ outpanel = gcnew Panel();
  954. outpanel->Width = width;
  955. outpanel->Height = height;
  956. outpanel->AutoScroll = true;
  957. Form^ RootForm = outpanel->FindForm();
  958. float ScaleWidth = 1.0f;
  959. float ScaleHeight = 1.0f;
  960. if (RootForm)
  961. {
  962. Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
  963. ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
  964. ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
  965. }
  966. int curX = 12;
  967. int curY = 3;
  968. for (int i = 0; i < cfg.size(); i++)
  969. {
  970. if (typeid(*cfg[i]).hash_code() == typeid(OptionMetaGroupEnd).hash_code())
  971. continue;
  972. if (typeid(*cfg[i]).hash_code() == typeid(OptionMetaGroupStart).hash_code())
  973. {
  974. OptionMetaGroupStart* groupData = (OptionMetaGroupStart*)(cfg[i]);
  975. GroupBox^ groupbox = gcnew GroupBox();
  976. groupbox->Width = width - (ScaleWidth * 28);
  977. groupbox->Height = ScaleHeight * (groupData->_height);
  978. groupbox->Left = ScaleWidth * 4;
  979. groupbox->Top = ScaleHeight * curY;
  980. groupbox->Text = gcnew String(groupData->_friendlyName);
  981. groupbox->ForeColor = Drawing::Color::White;
  982. // find the end of this group by simple iteration keeping track of indent level
  983. int level = 1;
  984. int endidx;
  985. for (endidx = i + 1; endidx < cfg.size(); endidx++)
  986. {
  987. if (typeid(*cfg[endidx]).hash_code() == typeid(OptionMetaGroupStart).hash_code())
  988. level++;
  989. if (typeid(*cfg[endidx]).hash_code() == typeid(OptionMetaGroupEnd).hash_code())
  990. level--;
  991. if (level == 0)
  992. break;
  993. }
  994. Panel^ groupPanel = MakePanel(groupbox->Width - (ScaleWidth * 12), groupbox->Height - (ScaleHeight * 20), std::vector<ConfigOptionBase*>(&(cfg[i + 1]), &(cfg[endidx])), tooltip, hasChanged);
  995. groupPanel->Left = ScaleWidth * 2;
  996. groupPanel->Top = ScaleHeight * 14;
  997. groupbox->Controls->Add(groupPanel);
  998. outpanel->Controls->Add(groupbox);
  999. i = endidx;
  1000. curY += groupData->_height;
  1001. }
  1002. else
  1003. {
  1004. cfg[i]->hasChanged = hasChanged;
  1005. curY += cfg[i]->AddToPanel(outpanel, curX, curY, tooltip);
  1006. }
  1007. }
  1008. return outpanel;
  1009. }
  1010. #pragma warning(pop)