OSDN Git Service

設定ダイアログで音声ファイルを設定するUIを変更する
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / MainForm.cs
1 // Copyright (C) 2013, 2014 Kazuhiro Fujieda <fujieda@users.sourceforge.jp>\r
2 // \r
3 // This program is part of KancolleSniffer.\r
4 //\r
5 // KancolleSniffer is free software: you can redistribute it and/or modify\r
6 // it under the terms of the GNU General Public License as published by\r
7 // the Free Software Foundation, either version 3 of the License, or\r
8 // (at your option) any later version.\r
9 //\r
10 // This program is distributed in the hope that it will be useful,\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 // GNU General Public License for more details.\r
14 //\r
15 // You should have received a copy of the GNU General Public License\r
16 // along with this program; if not, see <http://www.gnu.org/licenses/>.\r
17 \r
18 using System;\r
19 using System.Collections.Generic;\r
20 using System.Drawing;\r
21 using System.IO;\r
22 using System.Linq;\r
23 using System.Text.RegularExpressions;\r
24 using System.Windows.Forms;\r
25 using Codeplex.Data;\r
26 using Fiddler;\r
27 \r
28 namespace KancolleSniffer\r
29 {\r
30     public partial class MainForm : Form\r
31     {\r
32         private readonly Sniffer _sniffer = new Sniffer();\r
33         private readonly dynamic _wmp = Activator.CreateInstance(Type.GetTypeFromProgID("WMPlayer.OCX.7"));\r
34         private readonly Config _config = new Config();\r
35         private readonly ConfigDialog _configDialog;\r
36         private int _labelRightDistance;\r
37         private int _currentFleet;\r
38         private readonly Label[] _labelCheckFleets;\r
39         private readonly Label[][] _shipInfoLabels = new Label[ShipInfo.MemberCount][];\r
40         private readonly Label[][] _damagedShipList = new Label[14][];\r
41         private readonly Label[] _akashiTimers = new Label[ShipInfo.MemberCount];\r
42         private readonly Label[][] _ndockLabels = new Label[DockInfo.DockCount][];\r
43         private readonly Queue<string[]> _akashiTimerNoticeQueue = new Queue<string[]>();\r
44         private bool _started;\r
45 \r
46         public MainForm()\r
47         {\r
48             InitializeComponent();\r
49             FiddlerApplication.BeforeRequest += FiddlerApplication_BeforeRequest;\r
50             FiddlerApplication.BeforeResponse += FiddlerApplication_BeforeResponse;\r
51             _wmp.PlayStateChange += new EventHandler(_wmp_PlayStateChange);\r
52             _configDialog = new ConfigDialog(_config, this);\r
53             _labelCheckFleets = new[] {labelCheckFleet1, labelCheckFleet2, labelCheckFleet3, labelCheckFleet4};\r
54 \r
55             var i = 0;\r
56             foreach (var label in new[] {labelFleet1, labelFleet2, labelFleet3, labelFleet4})\r
57                 label.Tag = i++;\r
58             CreateShipInfoLabels();\r
59             CreateDamagedShipList();\r
60             CreateAkashiTimers();\r
61             CreateNDockLabels();\r
62         }\r
63 \r
64         private void FiddlerApplication_BeforeRequest(Session oSession)\r
65         {\r
66             var path = oSession.PathAndQuery;\r
67             var proxy = _config.Proxy;\r
68             if (proxy.UseUpstream && (path.StartsWith("/kcsapi/api_") ||\r
69                                       path.StartsWith("/kcs/resources/") || path.StartsWith("/kcs/sound/")))\r
70                 // この二つはMyFleetGirlsに必要\r
71                 oSession["x-overrideGateway"] = string.Format("localhost:{0:D}", proxy.UpstreamPort); // 上流プロキシを設定する\r
72             if (!path.StartsWith("/kcsapi/api_")) // 艦これのAPI以外は無視する\r
73             {\r
74                 oSession.Ignore();\r
75                 return;\r
76             }\r
77             // 戦闘開始のタイミングのずれを防ぐためにバッファする\r
78             if (_sniffer.IsBattleAPI(path))\r
79                 oSession.bBufferResponse = true;\r
80         }\r
81 \r
82         private void FiddlerApplication_BeforeResponse(Session oSession)\r
83         {\r
84             if (!oSession.bHasResponse || !oSession.uriContains("/kcsapi/api_"))\r
85                 return;\r
86             Invoke(new Action<Session>(ProcessRequest), oSession);\r
87         }\r
88 \r
89         private void ProcessRequest(Session session)\r
90         {\r
91             var response = session.GetResponseBodyAsString();\r
92             if (!response.StartsWith("svdata="))\r
93                 return;\r
94             response = response.Remove(0, "svdata=".Length);\r
95             var json = DynamicJson.Parse(response);\r
96             var request = session.GetRequestBodyAsString();\r
97             var update = (Sniffer.Update)_sniffer.Sniff(session.url, request, json);\r
98             if (update == Sniffer.Update.Start)\r
99             {\r
100                 labelLogin.Visible = false;\r
101                 _started = true;\r
102                 return;\r
103             }\r
104             if (!_started)\r
105                 return;\r
106             if ((update & Sniffer.Update.Item) != 0)\r
107                 UpdateItemInfo();\r
108             if ((update & Sniffer.Update.Timer) != 0)\r
109                 UpdateTimers();\r
110             if ((update & Sniffer.Update.NDock) != 0)\r
111                 UpdateNDocLabels();\r
112             if ((update & Sniffer.Update.Mission) != 0)\r
113                 UpdateMissionLabels();\r
114             if ((update & Sniffer.Update.QuestList) != 0)\r
115                 UpdateQuestList();\r
116             if ((update & Sniffer.Update.Ship) != 0)\r
117                 UpdateShipInfo();\r
118             if ((update & Sniffer.Update.Battle) != 0)\r
119                 UpdateBattleInfo();\r
120         }\r
121 \r
122         private void MainForm_Load(object sender, EventArgs e)\r
123         {\r
124             _config.Load();\r
125             ApplyConfig();\r
126             ApplyLogSetting();\r
127             _sniffer.LoadState();\r
128             StartProxy();\r
129         }\r
130 \r
131         private void StartProxy()\r
132         {\r
133             if (_config.Proxy.Auto)\r
134                 FiddlerApplication.Startup(0, FiddlerCoreStartupFlags.RegisterAsSystemProxy);\r
135             else\r
136                 FiddlerApplication.Startup(_config.Proxy.Listen, FiddlerCoreStartupFlags.None);\r
137         }\r
138 \r
139         private void MainForm_FormClosing(object sender, FormClosingEventArgs e)\r
140         {\r
141             _config.Location = (WindowState == FormWindowState.Normal ? Bounds : RestoreBounds).Location;\r
142             _config.Save();\r
143             _sniffer.SaveState();\r
144             ShutdownProxy();\r
145         }\r
146 \r
147         private void ShutdownProxy()\r
148         {\r
149             FiddlerApplication.Shutdown();\r
150         }\r
151 \r
152         private void labelHP_SizeChanged(object sender, EventArgs e)\r
153         {\r
154             var label = (Label)sender;\r
155             label.Location = new Point(label.Parent.Width - _labelRightDistance - label.Width, label.Top);\r
156         }\r
157 \r
158         private void notifyIconMain_MouseDoubleClick(object sender, MouseEventArgs e)\r
159         {\r
160             if (WindowState == FormWindowState.Minimized)\r
161                 WindowState = FormWindowState.Normal;\r
162             Activate();\r
163         }\r
164 \r
165         private void ExitToolStripMenuItem_Click(object sender, EventArgs e)\r
166         {\r
167             Application.Exit();\r
168         }\r
169 \r
170         private void ConfigToolStripMenuItem_Click(object sender, EventArgs e)\r
171         {\r
172             if (_configDialog.ShowDialog(this) == DialogResult.OK)\r
173                 ApplyConfig();\r
174         }\r
175 \r
176         private void ApplyConfig()\r
177         {\r
178             TopMost = _config.TopMost;\r
179             _sniffer.Item.MarginShips = _config.MarginShips;\r
180             _sniffer.Achievement.ResetHours = _config.ResetHours;\r
181 \r
182             if (_config.Location.X == int.MinValue)\r
183                 return;\r
184             var newBounds = Bounds;\r
185             newBounds.Location = _config.Location;\r
186             if (IsVisibleOnAnyScreen(newBounds))\r
187                 Location = _config.Location;\r
188             _config.Location = new Point(int.MinValue, int.MinValue); // 二回目以降は無視させる\r
189         }\r
190 \r
191         public void ApplyLogSetting()\r
192         {\r
193             _sniffer.LogFile = _config.Logging ? _config.LogFile : null;\r
194         }\r
195 \r
196         public void ApplyProxySetting()\r
197         {\r
198             ShutdownProxy();\r
199             StartProxy();\r
200         }\r
201 \r
202         private bool IsVisibleOnAnyScreen(Rectangle rect)\r
203         {\r
204             return Screen.AllScreens.Any(screen => screen.WorkingArea.IntersectsWith(rect));\r
205         }\r
206 \r
207         private void timerMain_Tick(object sender, EventArgs e)\r
208         {\r
209             if (_started)\r
210                 UpdateTimers();\r
211         }\r
212 \r
213         private void UpdateItemInfo()\r
214         {\r
215             UpdateNumOfShips();\r
216             var item = _sniffer.Item;\r
217             labelNumOfEquips.Text = string.Format("{0:D}/{1:D}", item.NowItems, item.MaxItems);\r
218             labelNumOfBuckets.Text = item.MaterialHistory[(int)Material.Bucket].Now.ToString("D");\r
219             UpdateBucketHistory();\r
220             var ac = _sniffer.Achievement.Value;\r
221             if (ac >= 10000)\r
222                 ac = 9999;\r
223             labelAchievement.Text = ac >= 1000 ? ac.ToString("D") : ac.ToString("F1");\r
224             UpdateMaterialHistry();\r
225         }\r
226 \r
227         private void UpdateNumOfShips()\r
228         {\r
229             var item = _sniffer.Item;\r
230             labelNumOfShips.Text = string.Format("{0:D}/{1:D}", item.NowShips, item.MaxShips);\r
231             labelNumOfShips.ForeColor = item.TooManyShips ? Color.Red : Color.Black;\r
232             if (item.NeedRing)\r
233             {\r
234                 var message = string.Format("残り{0:D}隻", _sniffer.Item.MaxShips - _sniffer.Item.NowShips);\r
235                 Ring("艦娘が多すぎます", message, _config.MaxShipsSoundFile);\r
236                 item.NeedRing = false;\r
237             }\r
238         }\r
239 \r
240         private void UpdateBucketHistory()\r
241         {\r
242             var count = _sniffer.Item.MaterialHistory[(int)Material.Bucket];\r
243             var day = count.Now - count.BegOfDay;\r
244             var week = count.Now - count.BegOfWeek;\r
245             if (day >= 1000)\r
246                 day = 999;\r
247             if (week >= 1000)\r
248                 week = 999;\r
249             labelBucketHistory.Text = string.Format("{0:+#;-#;±0} 今日\n{1:+#;-#;±0} 今週", day, week);\r
250         }\r
251 \r
252         private void UpdateMaterialHistry()\r
253         {\r
254             var labels = new[] {labelFuelHistory, labelBulletHistory, labelSteelHistory, labelBouxiteHistory};\r
255             var text = new[] {"燃料", "弾薬", "鋼材", "ボーキ"};\r
256             for (var i = 0; i < labels.Length; i++)\r
257             {\r
258                 var count = _sniffer.Item.MaterialHistory[i];\r
259                 var day = count.Now - count.BegOfDay;\r
260                 if (day >= 100000)\r
261                     day = 99999;\r
262                 var week = count.Now - count.BegOfWeek;\r
263                 if (week >= 100000)\r
264                     week = 99999;\r
265                 labels[i].Text = string.Format("{0}\n{1:+#;-#;±0}\n{2:+#;-#;±0}", text[i], day, week);\r
266             }\r
267         }\r
268 \r
269         private void CreateShipInfoLabels()\r
270         {\r
271             var parent = panelFleet1;\r
272             parent.SuspendLayout();\r
273             for (var i = 0; i < _shipInfoLabels.Length; i++)\r
274             {\r
275                 var y = 20 + 16 * i;\r
276                 const int height = 12;\r
277                 parent.Controls.AddRange(_shipInfoLabels[i] = new[]\r
278                 {\r
279                     new Label {Location = new Point(130, y), AutoSize = true},\r
280                     new Label\r
281                     {\r
282                         Location = new Point(136, y),\r
283                         Size = new Size(23, height),\r
284                         TextAlign = ContentAlignment.MiddleRight\r
285                     },\r
286                     new Label\r
287                     {\r
288                         Location = new Point(170, y),\r
289                         Size = new Size(23, height),\r
290                         TextAlign = ContentAlignment.MiddleRight\r
291                     },\r
292                     new Label\r
293                     {\r
294                         Location = new Point(195, y),\r
295                         Size = new Size(41, height),\r
296                         TextAlign = ContentAlignment.MiddleRight\r
297                     },\r
298                     new Label {Location = new Point(2, y), AutoSize = true} // 名前のZ-orderを下に\r
299                 });\r
300                 _shipInfoLabels[i][0].SizeChanged += labelHP_SizeChanged;\r
301             }\r
302             _labelRightDistance = parent.Width - _shipInfoLabels[0][0].Right;\r
303             parent.ResumeLayout();\r
304         }\r
305 \r
306         private void UpdateShipInfo()\r
307         {\r
308             var statuses = _sniffer.GetShipStatuses(_currentFleet);\r
309             var empty = new ShipStatus();\r
310             for (var i = 0; i < _shipInfoLabels.Length; i++)\r
311             {\r
312                 var labels = _shipInfoLabels[i];\r
313                 var stat = i < statuses.Length ? statuses[i] : empty;\r
314                 SetShipName(labels[4], stat.Name);\r
315                 SetHpLabel(labels[0], stat);\r
316                 if (stat == empty)\r
317                 {\r
318                     // SetCondLabelでは背景色が赤になってしまう\r
319                     labels[1].Text = "0";\r
320                     labels[1].BackColor = DefaultBackColor;\r
321                 }\r
322                 else\r
323                     SetCondLabel(labels[1], stat.Cond);\r
324                 labels[2].Text = stat.Level.ToString("D");\r
325                 labels[3].Text = stat.ExpToNext.ToString("D");\r
326             }\r
327             if (_sniffer.Battle.HasDamagedShip)\r
328                 Ring("大破した艦娘がいます", string.Join(" ", _sniffer.Battle.DamagedShipNames), _config.DamagedShipSoundFile);\r
329             labelAirSuperiority.Text = _sniffer.GetAirSuperiority(_currentFleet).ToString("D");\r
330             UpdateChargeInfo();\r
331             UpdateCondTimers();\r
332             UpdateAkashiTimer();\r
333             UpdateDamagedShipList();\r
334         }\r
335 \r
336         private void UpdateBattleInfo()\r
337         {\r
338             labelFormation.Text = "";\r
339             labelEnemyAirSuperiority.Text = "";\r
340             panelBattleInfo.Visible = _sniffer.Battle.InBattle;\r
341             if (!_sniffer.Battle.InBattle)\r
342                 return;\r
343             var t = new Timer {Interval = 2000}; // 艦隊が表示されるまで遅延させる\r
344             t.Tick += (sender, args) =>\r
345             {\r
346                 labelFormation.Text = _sniffer.Battle.Formation;\r
347                 labelEnemyAirSuperiority.Text = _sniffer.Battle.EnemyAirSuperiority.ToString("D");\r
348                 t.Stop();\r
349             };\r
350             t.Start();\r
351         }\r
352 \r
353         private void UpdateChargeInfo()\r
354         {\r
355             var fuel = new[] {labelFuel1, labelFuel2, labelFuel3, labelFuel4};\r
356             var bull = new[] {labelBull1, labelBull2, labelBull3, labelBull4};\r
357 \r
358             for (var i = 0; i < fuel.Length; i++)\r
359             {\r
360                 var stat = _sniffer.ChargeStatuses[i];\r
361                 fuel[i].ImageIndex = stat.Fuel;\r
362                 bull[i].ImageIndex = stat.Bull;\r
363             }\r
364         }\r
365 \r
366         private void SetShipName(Label label, string name)\r
367         {\r
368             var lu = name != null && new Regex(@"^\p{Lu}").IsMatch(name);\r
369             if (lu && label.Font.Equals(DefaultFont))\r
370             {\r
371                 label.Location += new Size(0, -1);\r
372                 label.Font = new Font("Tahoma", 8);\r
373             }\r
374             else if (!lu && !label.Font.Equals(DefaultFont))\r
375             {\r
376                 label.Location += new Size(0, 1);\r
377                 label.Font = DefaultFont;\r
378             }\r
379             label.Text = name;\r
380         }\r
381 \r
382         private void SetHpLabel(Label label, ShipStatus status)\r
383         {\r
384             SetHpLabel(label, status.NowHp, status.MaxHp);\r
385         }\r
386 \r
387         private void SetHpLabel(Label label, int now, int max)\r
388         {\r
389             var colors = new[] {DefaultBackColor, Color.FromArgb(255, 240, 240, 100), Color.Orange, Color.Red};\r
390             label.Text = string.Format("{0:D}/{1:D}", now, max);\r
391             label.BackColor = colors[(int)ShipStatus.CalcDamage(now, max)];\r
392         }\r
393 \r
394         private void SetCondLabel(Label label, int cond)\r
395         {\r
396             label.Text = cond.ToString("D");\r
397             label.BackColor = cond >= 50\r
398                 ? Color.Yellow\r
399                 : cond >= 30\r
400                     ? DefaultBackColor\r
401                     : cond >= 20 ? Color.Orange : Color.Red;\r
402         }\r
403 \r
404         private void CreateNDockLabels()\r
405         {\r
406             var parent = panelDock;\r
407             for (var i = 0; i < _ndockLabels.Length; i++)\r
408             {\r
409                 var y = 3 + i * 15;\r
410                 parent.Controls.AddRange(\r
411                     _ndockLabels[i] = new[]\r
412                     {\r
413                         new Label {Location = new Point(106, y), AutoSize = true, Text = "00:00:00"},\r
414                         new Label {Location = new Point(30, y), AutoSize = true} // 名前のZ-orderを下に\r
415                     });\r
416             }\r
417         }\r
418 \r
419         private void UpdateNDocLabels()\r
420         {\r
421             for (var i = 0; i < _ndockLabels.Length; i++)\r
422                 SetShipName(_ndockLabels[i][1], _sniffer.NDock[i].Name);\r
423         }\r
424 \r
425         private void UpdateMissionLabels()\r
426         {\r
427             foreach (var entry in\r
428                 new[] {labelMissionName1, labelMissionName2, labelMissionName3}.Zip(_sniffer.Missions,\r
429                     (label, mission) => new {label, mission.Name}))\r
430                 entry.label.Text = entry.Name;\r
431         }\r
432 \r
433         private void UpdateTimers()\r
434         {\r
435             foreach (var entry in\r
436                 new[] {labelMission1, labelMission2, labelMission3}.Zip(_sniffer.Missions,\r
437                     (label, mission) => new {label, mission.Name, mission.Timer}))\r
438             {\r
439                 entry.Timer.Update();\r
440                 SetTimerLabel(entry.label, entry.Timer);\r
441                 if (!entry.Timer.NeedRing)\r
442                     continue;\r
443                 Ring("遠征が終わりました", entry.Name, _config.MissionSoundFile);\r
444                 entry.Timer.NeedRing = false;\r
445             }\r
446             for (var i = 0; i < _ndockLabels.Length; i++)\r
447             {\r
448                 var entry = _sniffer.NDock[i];\r
449                 entry.Timer.Update();\r
450                 SetTimerLabel(_ndockLabels[i][0], entry.Timer);\r
451                 if (!entry.Timer.NeedRing)\r
452                     continue;\r
453                 Ring("入渠が終わりました", entry.Name, _config.NDockSoundFile);\r
454                 entry.Timer.NeedRing = false;\r
455             }\r
456             var kdock = new[] {labelConstruct1, labelConstruct2, labelConstruct3, labelConstruct4};\r
457             for (var i = 0; i < kdock.Length; i++)\r
458             {\r
459                 var timer = _sniffer.KDock[i];\r
460                 timer.Update();\r
461                 SetTimerLabel(kdock[i], timer);\r
462                 if (!timer.NeedRing)\r
463                     continue;\r
464                 Ring("建造が終わりました", string.Format("第{0:D}ドック", i + 1), _config.KDockSoundFile);\r
465                 timer.NeedRing = false;\r
466             }\r
467             UpdateCondTimers();\r
468             UpdateAkashiTimer();\r
469         }\r
470 \r
471         private void SetTimerLabel(Label label, RingTimer timer)\r
472         {\r
473             label.ForeColor = timer.IsFinished ? Color.Red : Color.Black;\r
474             label.Text = timer.ToString();\r
475         }\r
476 \r
477         private void UpdateCondTimers()\r
478         {\r
479             foreach (var entry in\r
480                 new[] {labelCondTimer1, labelCondTimer2, labelCondTimer3}.Zip(\r
481                     _sniffer.GetConditionTimers(_currentFleet), (label, timer) => new {label, timer}))\r
482                 entry.label.Text = entry.timer;\r
483         }\r
484 \r
485         private void CreateAkashiTimers()\r
486         {\r
487             var parent = panelFleet1;\r
488             parent.SuspendLayout();\r
489             for (var i = 0; i < _akashiTimers.Length; i++)\r
490             {\r
491                 const int width = 31, height = 12;\r
492                 const int x = 56;\r
493                 var y = 20 + 16 * i;\r
494                 parent.Controls.Add(\r
495                     _akashiTimers[i] =\r
496                         new Label {Location = new Point(x, y), Size = new Size(width, height), Visible = false});\r
497                 parent.Controls.SetChildIndex(_akashiTimers[i], 0);\r
498             }\r
499             parent.ResumeLayout();\r
500         }\r
501 \r
502         private void UpdateAkashiTimer()\r
503         {\r
504             var timers = _sniffer.GetAkashiTimers(_currentFleet);\r
505             var statuses = _sniffer.GetShipStatuses(_currentFleet);\r
506             for (var i = 0; i < _akashiTimers.Length; i++)\r
507             {\r
508                 var label = _akashiTimers[i];\r
509                 var labelHp = _shipInfoLabels[i][0];\r
510                 if (timers == null || i >= timers.Length || timers[i].Span == TimeSpan.MinValue)\r
511                 {\r
512                     label.Visible = false;\r
513                     labelHp.ForeColor = DefaultForeColor;\r
514                     continue;\r
515                 }\r
516                 var timer = timers[i];\r
517                 var stat = statuses[i];\r
518                 label.Visible = true;\r
519                 label.Text = timer.Span.ToString(@"mm\:ss");\r
520                 if (timer.Diff == 0)\r
521                 {\r
522                     labelHp.ForeColor = DefaultForeColor;\r
523                     continue;\r
524                 }\r
525                 labelHp.ForeColor = Color.DimGray;\r
526                 SetHpLabel(labelHp, stat.NowHp + timer.Diff, stat.MaxHp);\r
527             }\r
528             var msgs = _sniffer.GetAkashiTimerNotice();\r
529             var fn = new[] {"第一艦隊", "第二艦隊", "第三艦隊", "第四艦隊"};\r
530             for (var i = 0; i < fn.Length; i++)\r
531             {\r
532                 if (msgs[i] == "")\r
533                     continue;\r
534                 var sound = msgs[i] == "20分経過しました。" ? _config.Akashi20MinSoundFile : _config.AkashiProgressSoundFile;\r
535                 _akashiTimerNoticeQueue.Enqueue(new[] {"泊地修理 " + fn[i], msgs[i], sound});\r
536                 _akashiTimerNoticeQueue.Enqueue(new[] {""}); //連続する通知の間隔をあける\r
537                 _akashiTimerNoticeQueue.Enqueue(new[] {""});\r
538             }\r
539             if (_akashiTimerNoticeQueue.Count == 0)\r
540                 return;\r
541             var e = _akashiTimerNoticeQueue.Dequeue();\r
542             if (e[0] == "")\r
543                 return;\r
544             Ring(e[0], e[1], e[2]);\r
545         }\r
546 \r
547         public void CreateDamagedShipList()\r
548         {\r
549             var parent = panelDamagedShipList;\r
550             parent.SuspendLayout();\r
551             for (var i = 0; i < _damagedShipList.Length; i++)\r
552             {\r
553                 var y = 3 + i * 16;\r
554                 const int height = 12;\r
555                 parent.Controls.AddRange(_damagedShipList[i] = new[]\r
556                 {\r
557                     new Label {Location = new Point(1, y), Size = new Size(11, height)},\r
558                     new Label {Location = new Point(79, y), Size = new Size(45, height)},\r
559                     new Label {Location = new Point(123, y), Size = new Size(5, height - 1)},\r
560                     new Label {Location = new Point(10, y), AutoSize = true}\r
561                 });\r
562             }\r
563             parent.ResumeLayout();\r
564         }\r
565 \r
566         private void UpdateDamagedShipList()\r
567         {\r
568             const int fleet = 0, name = 3, time = 1, damage = 2;\r
569             var parent = panelDamagedShipList;\r
570             var list = _sniffer.DamagedShipList;\r
571             var num = Math.Min(list.Length, _damagedShipList.Length);\r
572             const int width = 134;\r
573             if (num == 0)\r
574             {\r
575                 parent.Size = new Size(width, 19);\r
576                 var labels = _damagedShipList[0];\r
577                 labels[fleet].Text = "";\r
578                 SetShipName(labels[name], "なし");\r
579                 labels[time].Text = "";\r
580                 labels[damage].BackColor = DefaultBackColor;\r
581                 return;\r
582             }\r
583             parent.Size = new Size(width, num * 16 + 3);\r
584             var fn = new[] {"", "1", "2", "3", "4"};\r
585             var colors = new[] {DefaultBackColor, Color.FromArgb(255, 225, 225, 21), Color.Orange, Color.Red};\r
586             for (var i = 0; i < num; i++)\r
587             {\r
588                 var e = list[i];\r
589                 var labels = _damagedShipList[i];\r
590                 labels[fleet].Text = fn[e.Fleet + 1];\r
591                 SetShipName(labels[name], e.Name);\r
592                 var t = e.RepairTime;\r
593                 labels[time].Text = string.Format(@"{0:d2}:{1:mm\:ss}", (int)t.TotalHours, t);\r
594                 labels[damage].BackColor = colors[(int)e.DamageLevel];\r
595             }\r
596         }\r
597 \r
598         private void UpdateQuestList()\r
599         {\r
600             var name = new[] {labelQuest1, labelQuest2, labelQuest3, labelQuest4, labelQuest5};\r
601             var progress = new[] {labelProgress1, labelProgress2, labelProgress3, labelProgress4, labelProgress5};\r
602 \r
603             for (var i = 0; i < name.Length; i++)\r
604             {\r
605                 if (i < _sniffer.Quests.Length)\r
606                 {\r
607                     name[i].Text = _sniffer.Quests[i].Name;\r
608                     progress[i].Text = string.Format("{0:D}%", _sniffer.Quests[i].Progress);\r
609                 }\r
610                 else\r
611                 {\r
612                     name[i].Text = progress[i].Text = "";\r
613                 }\r
614             }\r
615         }\r
616 \r
617         private void Ring(string baloonTitle, string baloonMessage, string soundFile)\r
618         {\r
619             if (_config.FlashWindow)\r
620                 Win32API.FlashWindow(Handle);\r
621             if (_config.ShowBaloonTip)\r
622                 notifyIconMain.ShowBalloonTip(20000, baloonTitle, baloonMessage, ToolTipIcon.Info);\r
623             if (_config.PlaySound)\r
624                 PlaySound(soundFile, _config.SoundVolume);\r
625         }\r
626 \r
627         public void PlaySound(string file, int volume)\r
628         {\r
629             if (!File.Exists(file))\r
630                 return;\r
631             _wmp.settings.volume = volume;\r
632             _wmp.URL = file;\r
633             _wmp.controls.play();\r
634         }\r
635 \r
636         private void _wmp_PlayStateChange(object sender, EventArgs e)\r
637         {\r
638             if (_wmp.playState == 8) // MediaEnded\r
639                 _wmp.URL = ""; // 再生したファイルが差し替えできなくなるのを防ぐ。\r
640         }\r
641 \r
642         private void labelFleet_Click(object sender, EventArgs e)\r
643         {\r
644             var fleet = (int)((Label)sender).Tag;\r
645             if (_currentFleet == fleet)\r
646                 return;\r
647             _currentFleet = fleet;\r
648             foreach (var label in _labelCheckFleets)\r
649                 label.Visible = false;\r
650             _labelCheckFleets[fleet].Visible = true;\r
651             if (!_started)\r
652                 return;\r
653             UpdateShipInfo();\r
654         }\r
655 \r
656         private void labelBucketHistoryButton_Click(object sender, EventArgs e)\r
657         {\r
658             if (labelBucketHistory.Visible)\r
659             {\r
660                 labelBucketHistory.Visible = false;\r
661                 labelBucketHistoryButton.BackColor = DefaultBackColor;\r
662             }\r
663             else\r
664             {\r
665                 labelBucketHistory.Visible = true;\r
666                 labelBucketHistoryButton.BackColor = SystemColors.ActiveCaption;\r
667             }\r
668         }\r
669 \r
670         private void labelMaterialHistoryButton_Click(object sender, EventArgs e)\r
671         {\r
672             if (panelMaterialHistory.Visible)\r
673             {\r
674                 panelMaterialHistory.Visible = false;\r
675                 labelMaterialHistoryButton.BackColor = DefaultBackColor;\r
676             }\r
677             else\r
678             {\r
679                 panelMaterialHistory.Visible = true;\r
680                 labelMaterialHistoryButton.BackColor = SystemColors.ActiveCaption;\r
681             }\r
682         }\r
683 \r
684         public void ResetAchievemnt()\r
685         {\r
686             _sniffer.Achievement.Reset();\r
687             UpdateItemInfo();\r
688         }\r
689 \r
690         private void labelDamgedShipListButton_Click(object sender, EventArgs e)\r
691         {\r
692             if (panelDamagedShipList.Visible)\r
693             {\r
694                 panelDamagedShipList.Visible = false;\r
695                 labelDamgedShipListButton.BackColor = DefaultBackColor;\r
696             }\r
697             else\r
698             {\r
699                 panelDamagedShipList.Visible = true;\r
700                 labelDamgedShipListButton.BackColor = SystemColors.ActiveCaption;\r
701             }\r
702         }\r
703     }\r
704 }