You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

MenuViewController.cs 17 kB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. using Shadowsocks.Controller;
  2. using Shadowsocks.Model;
  3. using Shadowsocks.Properties;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Diagnostics;
  7. using System.Drawing;
  8. using System.Text;
  9. using System.Windows.Forms;
  10. namespace Shadowsocks.View
  11. {
  12. public class MenuViewController
  13. {
  14. // yes this is just a menu view controller
  15. // when config form is closed, it moves away from RAM
  16. // and it should just do anything related to the config form
  17. private ShadowsocksController controller;
  18. private UpdateChecker updateChecker;
  19. private NotifyIcon _notifyIcon;
  20. private ContextMenu contextMenu1;
  21. private bool _isFirstRun;
  22. private MenuItem enableItem;
  23. private MenuItem AutoStartupItem;
  24. private MenuItem ShareOverLANItem;
  25. private MenuItem SeperatorItem;
  26. private MenuItem ConfigItem;
  27. private MenuItem menuItem4;
  28. private MenuItem editPACFileItem;
  29. private MenuItem QRCodeItem;
  30. private MenuItem ShowLogItem;
  31. private MenuItem aboutItem;
  32. private MenuItem ServersItem;
  33. private MenuItem menuItem3;
  34. private MenuItem quitItem;
  35. private MenuItem menuItem1;
  36. private MenuItem modeItem;
  37. private MenuItem globalModeItem;
  38. private MenuItem PACModeItem;
  39. private ConfigForm configForm;
  40. public MenuViewController(ShadowsocksController controller)
  41. {
  42. this.controller = controller;
  43. LoadMenu();
  44. controller.EnableStatusChanged += controller_EnableStatusChanged;
  45. controller.ConfigChanged += controller_ConfigChanged;
  46. controller.PACFileReadyToOpen += controller_PACFileReadyToOpen;
  47. controller.ShareOverLANStatusChanged += controller_ShareOverLANStatusChanged;
  48. controller.EnableGlobalChanged += controller_EnableGlobalChanged;
  49. controller.Errored += controller_Errored;
  50. _notifyIcon = new NotifyIcon();
  51. UpdateTrayIcon();
  52. _notifyIcon.Visible = true;
  53. _notifyIcon.ContextMenu = contextMenu1;
  54. _notifyIcon.DoubleClick += notifyIcon1_DoubleClick;
  55. this.updateChecker = new UpdateChecker();
  56. updateChecker.NewVersionFound += updateChecker_NewVersionFound;
  57. LoadCurrentConfiguration();
  58. updateChecker.CheckUpdate();
  59. if (controller.GetConfiguration().isDefault)
  60. {
  61. _isFirstRun = true;
  62. ShowConfigForm();
  63. }
  64. }
  65. void controller_Errored(object sender, System.IO.ErrorEventArgs e)
  66. {
  67. MessageBox.Show(e.GetException().ToString(), String.Format(I18N.GetString("Shadowsocks Error: {0}"), e.GetException().Message));
  68. }
  69. private void UpdateTrayIcon()
  70. {
  71. int dpi;
  72. Graphics graphics = Graphics.FromHwnd(IntPtr.Zero);
  73. dpi = (int)graphics.DpiX;
  74. graphics.Dispose();
  75. Bitmap icon = null;
  76. if (dpi < 97)
  77. {
  78. // dpi = 96;
  79. icon = Resources.ss16;
  80. }
  81. else if (dpi < 121)
  82. {
  83. // dpi = 120;
  84. icon = Resources.ss20;
  85. }
  86. else
  87. {
  88. icon = Resources.ss24;
  89. }
  90. bool enabled = controller.GetConfiguration().enabled;
  91. if (!enabled)
  92. {
  93. Bitmap iconCopy = new Bitmap(icon);
  94. for (int x = 0; x < iconCopy.Width; x++)
  95. {
  96. for (int y = 0; y < iconCopy.Height; y++)
  97. {
  98. Color color = icon.GetPixel(x, y);
  99. iconCopy.SetPixel(x, y , Color.FromArgb((byte)(color.A / 1.25), color.R, color.G, color.B));
  100. }
  101. }
  102. icon = iconCopy;
  103. }
  104. _notifyIcon.Icon = Icon.FromHandle(icon.GetHicon());
  105. _notifyIcon.Text = I18N.GetString("Shadowsocks") + " " + UpdateChecker.Version + "\n" + (enabled ? I18N.GetString("Enabled") : I18N.GetString("Disabled")) + "\n" + controller.GetCurrentServer().FriendlyName;
  106. }
  107. private void LoadMenu()
  108. {
  109. this.contextMenu1 = new System.Windows.Forms.ContextMenu();
  110. this.enableItem = new System.Windows.Forms.MenuItem();
  111. this.modeItem = new System.Windows.Forms.MenuItem();
  112. this.PACModeItem = new System.Windows.Forms.MenuItem();
  113. this.globalModeItem = new System.Windows.Forms.MenuItem();
  114. this.AutoStartupItem = new System.Windows.Forms.MenuItem();
  115. this.ShareOverLANItem = new System.Windows.Forms.MenuItem();
  116. this.ServersItem = new System.Windows.Forms.MenuItem();
  117. this.SeperatorItem = new System.Windows.Forms.MenuItem();
  118. this.ConfigItem = new System.Windows.Forms.MenuItem();
  119. this.menuItem4 = new System.Windows.Forms.MenuItem();
  120. this.editPACFileItem = new System.Windows.Forms.MenuItem();
  121. this.QRCodeItem = new System.Windows.Forms.MenuItem();
  122. this.ShowLogItem = new System.Windows.Forms.MenuItem();
  123. this.aboutItem = new System.Windows.Forms.MenuItem();
  124. this.menuItem3 = new System.Windows.Forms.MenuItem();
  125. this.quitItem = new System.Windows.Forms.MenuItem();
  126. this.menuItem1 = new System.Windows.Forms.MenuItem();
  127. //
  128. // contextMenu1
  129. //
  130. this.contextMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
  131. this.enableItem,
  132. this.modeItem,
  133. this.ServersItem,
  134. this.menuItem1,
  135. this.AutoStartupItem,
  136. this.ShareOverLANItem,
  137. this.editPACFileItem,
  138. this.menuItem4,
  139. this.QRCodeItem,
  140. this.ShowLogItem,
  141. this.aboutItem,
  142. this.menuItem3,
  143. this.quitItem});
  144. //
  145. // enableItem
  146. //
  147. this.enableItem.Index = 0;
  148. this.enableItem.Text = I18N.GetString("Enable");
  149. this.enableItem.Click += new System.EventHandler(this.EnableItem_Click);
  150. //
  151. // modeMenu
  152. //
  153. this.modeItem.Index = 1;
  154. this.modeItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
  155. this.PACModeItem,
  156. this.globalModeItem});
  157. this.modeItem.Text = I18N.GetString("Mode");
  158. //
  159. // PACModeItem
  160. //
  161. this.PACModeItem.Index = 0;
  162. this.PACModeItem.Text = I18N.GetString("PAC");
  163. this.PACModeItem.Click += new System.EventHandler(this.PACModeItem_Click);
  164. //
  165. // globalModeItem
  166. //
  167. this.globalModeItem.Index = 1;
  168. this.globalModeItem.Text = I18N.GetString("Global");
  169. this.globalModeItem.Click += new System.EventHandler(this.GlobalModeItem_Click);
  170. //
  171. // ServersItem
  172. //
  173. this.ServersItem.Index = 2;
  174. this.ServersItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
  175. this.SeperatorItem,
  176. this.ConfigItem});
  177. this.ServersItem.Text = I18N.GetString("Servers");
  178. //
  179. // SeperatorItem
  180. //
  181. this.SeperatorItem.Index = 0;
  182. this.SeperatorItem.Text = "-";
  183. //
  184. // ConfigItem
  185. //
  186. this.ConfigItem.Index = 1;
  187. this.ConfigItem.Text = I18N.GetString("Edit Servers...");
  188. this.ConfigItem.Click += new System.EventHandler(this.Config_Click);
  189. //
  190. // menuItem1
  191. //
  192. this.menuItem1.Index = 3;
  193. this.menuItem1.Text = "-";
  194. //
  195. // AutoStartupItem
  196. //
  197. this.AutoStartupItem.Index = 4;
  198. this.AutoStartupItem.Text = I18N.GetString("Start on Boot");
  199. this.AutoStartupItem.Click += new System.EventHandler(this.AutoStartupItem_Click);
  200. //
  201. // ShareOverLANItem
  202. //
  203. this.ShareOverLANItem.Index = 5;
  204. this.ShareOverLANItem.Text = I18N.GetString("Share over LAN");
  205. this.ShareOverLANItem.Click += new System.EventHandler(this.ShareOverLANItem_Click);
  206. //
  207. // editPACFileItem
  208. //
  209. this.editPACFileItem.Index = 6;
  210. this.editPACFileItem.Text = I18N.GetString("Edit PAC File...");
  211. this.editPACFileItem.Click += new System.EventHandler(this.EditPACFileItem_Click);
  212. //
  213. // menuItem4
  214. //
  215. this.menuItem4.Index = 7;
  216. this.menuItem4.Text = "-";
  217. //
  218. // QRCodeItem
  219. //
  220. this.QRCodeItem.Index = 8;
  221. this.QRCodeItem.Text = I18N.GetString("Show QRCode...");
  222. this.QRCodeItem.Click += new System.EventHandler(this.QRCodeItem_Click);
  223. //
  224. // ShowLogItem
  225. //
  226. this.ShowLogItem.Index = 9;
  227. this.ShowLogItem.Text = I18N.GetString("Show Logs...");
  228. this.ShowLogItem.Click += new System.EventHandler(this.ShowLogItem_Click);
  229. //
  230. // aboutItem
  231. //
  232. this.aboutItem.Index = 10;
  233. this.aboutItem.Text = I18N.GetString("About...");
  234. this.aboutItem.Click += new System.EventHandler(this.AboutItem_Click);
  235. //
  236. // menuItem3
  237. //
  238. this.menuItem3.Index = 11;
  239. this.menuItem3.Text = "-";
  240. //
  241. // quitItem
  242. //
  243. this.quitItem.Index = 12;
  244. this.quitItem.Text = I18N.GetString("Quit");
  245. this.quitItem.Click += new System.EventHandler(this.Quit_Click);
  246. }
  247. private void controller_ConfigChanged(object sender, EventArgs e)
  248. {
  249. LoadCurrentConfiguration();
  250. UpdateTrayIcon();
  251. }
  252. private void controller_EnableStatusChanged(object sender, EventArgs e)
  253. {
  254. enableItem.Checked = controller.GetConfiguration().enabled;
  255. }
  256. void controller_ShareOverLANStatusChanged(object sender, EventArgs e)
  257. {
  258. ShareOverLANItem.Checked = controller.GetConfiguration().shareOverLan;
  259. }
  260. void controller_EnableGlobalChanged(object sender, EventArgs e)
  261. {
  262. globalModeItem.Checked = controller.GetConfiguration().global;
  263. PACModeItem.Checked = !globalModeItem.Checked;
  264. }
  265. void controller_PACFileReadyToOpen(object sender, ShadowsocksController.PathEventArgs e)
  266. {
  267. string argument = @"/select, " + e.Path;
  268. System.Diagnostics.Process.Start("explorer.exe", argument);
  269. }
  270. void updateChecker_NewVersionFound(object sender, EventArgs e)
  271. {
  272. _notifyIcon.BalloonTipTitle = String.Format(I18N.GetString("Shadowsocks {0} Update Found"), updateChecker.LatestVersionNumber);
  273. _notifyIcon.BalloonTipText = I18N.GetString("Click here to download");
  274. _notifyIcon.BalloonTipIcon = ToolTipIcon.Info;
  275. _notifyIcon.BalloonTipClicked += notifyIcon1_BalloonTipClicked;
  276. _notifyIcon.ShowBalloonTip(5000);
  277. _isFirstRun = false;
  278. }
  279. void notifyIcon1_BalloonTipClicked(object sender, EventArgs e)
  280. {
  281. System.Diagnostics.Process.Start(updateChecker.LatestVersionURL);
  282. }
  283. private void LoadCurrentConfiguration()
  284. {
  285. Configuration config = controller.GetConfiguration();
  286. UpdateServersMenu();
  287. enableItem.Checked = config.enabled;
  288. globalModeItem.Checked = config.global;
  289. PACModeItem.Checked = !config.global;
  290. ShareOverLANItem.Checked = config.shareOverLan;
  291. AutoStartupItem.Checked = AutoStartup.Check();
  292. }
  293. private void UpdateServersMenu()
  294. {
  295. var items = ServersItem.MenuItems;
  296. items.Clear();
  297. Configuration configuration = controller.GetConfiguration();
  298. for (int i = 0; i < configuration.configs.Count; i++)
  299. {
  300. Server server = configuration.configs[i];
  301. MenuItem item = new MenuItem(server.FriendlyName);
  302. item.Tag = i;
  303. item.Click += AServerItem_Click;
  304. items.Add(item);
  305. }
  306. items.Add(SeperatorItem);
  307. items.Add(ConfigItem);
  308. if (configuration.index >= 0 && configuration.index < configuration.configs.Count)
  309. {
  310. items[configuration.index].Checked = true;
  311. }
  312. }
  313. private void ShowConfigForm()
  314. {
  315. if (configForm != null)
  316. {
  317. configForm.Focus();
  318. }
  319. else
  320. {
  321. configForm = new ConfigForm(controller);
  322. configForm.Show();
  323. configForm.FormClosed += configForm_FormClosed;
  324. }
  325. }
  326. void configForm_FormClosed(object sender, FormClosedEventArgs e)
  327. {
  328. configForm = null;
  329. Util.Util.ReleaseMemory();
  330. ShowFirstTimeBalloon();
  331. }
  332. private void Config_Click(object sender, EventArgs e)
  333. {
  334. ShowConfigForm();
  335. }
  336. private void Quit_Click(object sender, EventArgs e)
  337. {
  338. controller.Stop();
  339. _notifyIcon.Visible = false;
  340. Application.Exit();
  341. }
  342. private void ShowFirstTimeBalloon()
  343. {
  344. if (_isFirstRun)
  345. {
  346. _notifyIcon.BalloonTipTitle = I18N.GetString("Shadowsocks is here");
  347. _notifyIcon.BalloonTipText = I18N.GetString("You can turn on/off Shadowsocks in the context menu");
  348. _notifyIcon.BalloonTipIcon = ToolTipIcon.Info;
  349. _notifyIcon.ShowBalloonTip(0);
  350. _isFirstRun = false;
  351. }
  352. }
  353. private void AboutItem_Click(object sender, EventArgs e)
  354. {
  355. Process.Start("https://github.com/clowwindy/shadowsocks-csharp");
  356. }
  357. private void notifyIcon1_DoubleClick(object sender, EventArgs e)
  358. {
  359. ShowConfigForm();
  360. }
  361. private void EnableItem_Click(object sender, EventArgs e)
  362. {
  363. controller.ToggleEnable(!enableItem.Checked);
  364. }
  365. private void GlobalModeItem_Click(object sender, EventArgs e)
  366. {
  367. controller.ToggleGlobal(true);
  368. }
  369. private void PACModeItem_Click(object sender, EventArgs e)
  370. {
  371. controller.ToggleGlobal(false);
  372. }
  373. private void ShareOverLANItem_Click(object sender, EventArgs e)
  374. {
  375. ShareOverLANItem.Checked = !ShareOverLANItem.Checked;
  376. controller.ToggleShareOverLAN(ShareOverLANItem.Checked);
  377. }
  378. private void EditPACFileItem_Click(object sender, EventArgs e)
  379. {
  380. controller.TouchPACFile();
  381. }
  382. private void AServerItem_Click(object sender, EventArgs e)
  383. {
  384. MenuItem item = (MenuItem)sender;
  385. controller.SelectServerIndex((int)item.Tag);
  386. }
  387. private void ShowLogItem_Click(object sender, EventArgs e)
  388. {
  389. string argument = Logging.LogFile;
  390. System.Diagnostics.Process.Start("notepad.exe", argument);
  391. }
  392. private void QRCodeItem_Click(object sender, EventArgs e)
  393. {
  394. QRCodeForm qrCodeForm = new QRCodeForm(controller.GetQRCodeForCurrentServer());
  395. //qrCodeForm.Icon = this.Icon;
  396. // TODO
  397. qrCodeForm.Show();
  398. }
  399. private void AutoStartupItem_Click(object sender, EventArgs e) {
  400. AutoStartupItem.Checked = !AutoStartupItem.Checked;
  401. if (!AutoStartup.Set(AutoStartupItem.Checked)) {
  402. MessageBox.Show("Failed to edit registry");
  403. }
  404. }
  405. }
  406. }