OSDN Git Service

任務一覧をスクロール可能にする
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / View / QuestPanel.cs
1 // Copyright (C) 2019 Kazuhiro Fujieda <fujieda@users.osdn.me>\r
2 //\r
3 // Licensed under the Apache License, Version 2.0 (the "License");\r
4 // you may not use this file except in compliance with the License.\r
5 // You may obtain a copy of the License at\r
6 //\r
7 //    http://www.apache.org/licenses/LICENSE-2.0\r
8 //\r
9 // Unless required by applicable law or agreed to in writing, software\r
10 // distributed under the License is distributed on an "AS IS" BASIS,\r
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
12 // See the License for the specific language governing permissions and\r
13 // limitations under the License.\r
14 \r
15 using System;\r
16 using System.Drawing;\r
17 using System.Windows.Forms;\r
18 using KancolleSniffer.Model;\r
19 \r
20 namespace KancolleSniffer.View\r
21 {\r
22     public class QuestLabels\r
23     {\r
24         public Label Color { get; set; }\r
25         public Label Name { get; set; }\r
26         public ShipLabel Count { get; set; }\r
27         public Label Progress { get; set; }\r
28 \r
29         public Label[] Labels => new[] {Color, Count, Progress, Name};\r
30     }\r
31 \r
32     public class QuestPanel : PanelWithToolTip\r
33     {\r
34         const int TopMargin = 5;\r
35         const int LeftMargin = 2;\r
36         const int LineHeight = 14;\r
37         private const int Lines = 6;\r
38         private readonly QuestLabels[] _labels = new QuestLabels[Lines];\r
39         private QuestStatus[] _questList = new QuestStatus[0];\r
40         private int _listPosition;\r
41 \r
42         public QuestPanel()\r
43         {\r
44             const int height = 12;\r
45 \r
46             SuspendLayout();\r
47             for (var i = 0; i < Lines; i++)\r
48             {\r
49                 var y = TopMargin + i * LineHeight;\r
50                 _labels[i] = new QuestLabels\r
51                 {\r
52                     Color = new Label\r
53                     {\r
54                         Location = new Point(LeftMargin, y + 1),\r
55                         Size = new Size(4, height - 1)\r
56                     },\r
57                     Name = new Label\r
58                     {\r
59                         Location = new Point(LeftMargin + 4, y),\r
60                         AutoSize = true\r
61                     },\r
62                     Count = new ShipLabel\r
63                     {\r
64                         Location = new Point(LeftMargin + 189, y),\r
65                         AutoSize = true,\r
66                         AnchorRight = true\r
67                     },\r
68                     Progress = new Label\r
69                     {\r
70                         Location = new Point(LeftMargin + 186, y),\r
71                         Size = new Size(29, height),\r
72                         TextAlign = ContentAlignment.MiddleRight\r
73                     }\r
74                 };\r
75                 _labels[i].Name.DoubleClick += NameLabelDoubleClickHandler;\r
76                 // ReSharper disable once CoVariantArrayConversion\r
77                 Controls.AddRange(_labels[i].Labels);\r
78             }\r
79             ResumeLayout();\r
80             SetScrollEventHandlers();\r
81         }\r
82 \r
83         private void SetScrollEventHandlers()\r
84         {\r
85             foreach (var label in _labels[0].Labels)\r
86             {\r
87                 label.MouseEnter += TopLineOnMouseEnter;\r
88                 label.MouseLeave += TopLineOnMouseLeave;\r
89             }\r
90             foreach (var label in _labels[Lines - 1].Labels)\r
91             {\r
92                 label.MouseEnter += BottomLineOnMouseEnter;\r
93                 label.MouseLeave += BottomLineOnMouseLeave;\r
94             }\r
95             _topScrollRepeatTimer.Tick += TopLineOnMouseEnter;\r
96             _bottomScrollRepeatTimer.Tick += BottomLineOnMouseEnter;\r
97         }\r
98 \r
99         private readonly Timer _topScrollRepeatTimer = new Timer {Interval = 100};\r
100         private readonly Timer _bottomScrollRepeatTimer = new Timer {Interval = 100};\r
101 \r
102         private void TopLineOnMouseEnter(object sender, EventArgs e)\r
103         {\r
104             if (_listPosition == 0)\r
105                 return;\r
106             _listPosition--;\r
107             ShowQuestList();\r
108             _topScrollRepeatTimer.Start();\r
109         }\r
110 \r
111         private void TopLineOnMouseLeave(object sender, EventArgs e)\r
112         {\r
113             _topScrollRepeatTimer.Stop();\r
114         }\r
115 \r
116         private void BottomLineOnMouseEnter(object sender, EventArgs e)\r
117         {\r
118             if (_listPosition + Lines >= _questList.Length)\r
119                 return;\r
120             _listPosition++;\r
121             ShowQuestList();\r
122             _bottomScrollRepeatTimer.Start();\r
123         }\r
124 \r
125         private void BottomLineOnMouseLeave(object sender, EventArgs e)\r
126         {\r
127             _bottomScrollRepeatTimer.Stop();\r
128         }\r
129 \r
130         public void Update(QuestStatus[] quests)\r
131         {\r
132             _questList = quests;\r
133             if (quests.Length <= Lines)\r
134                 _listPosition = 0;\r
135             ShowQuestList();\r
136         }\r
137 \r
138         public void ShowQuestList()\r
139         {\r
140             SuspendLayout();\r
141             for (var i = 0; i < Lines; i++)\r
142             {\r
143                 var labels = _labels[i];\r
144                 if (i >= _questList.Length)\r
145                 {\r
146                     ClearQuest(labels);\r
147                     ClearCount(labels.Count);\r
148                     continue;\r
149                 }\r
150                 var quest = _questList[i + _listPosition];\r
151                 SetQuest(labels, quest);\r
152                 if (quest.Count.Id == 0)\r
153                 {\r
154                     ClearCount(labels.Count);\r
155                     continue;\r
156                 }\r
157                 SetCount(labels.Count, quest.Count);\r
158             }\r
159             ResumeLayout(true);\r
160             DrawMark();\r
161         }\r
162 \r
163         private void ClearQuest(QuestLabels labels)\r
164         {\r
165             labels.Color.BackColor = DefaultBackColor;\r
166             labels.Name.Text = labels.Count.Text = labels.Progress.Text = "";\r
167         }\r
168 \r
169         private void ClearCount(Label label)\r
170         {\r
171             label.Text = "";\r
172             label.ForeColor = Color.Black;\r
173             ToolTip.SetToolTip(label, "");\r
174         }\r
175 \r
176         private void SetQuest(QuestLabels labels, QuestStatus quest)\r
177         {\r
178             labels.Color.BackColor = quest.Color;\r
179             labels.Name.Text = quest.Name;\r
180             labels.Progress.Text = $"{quest.Progress:D}%";\r
181             ToolTip.SetToolTip(labels.Name, quest.ToToolTip());\r
182         }\r
183 \r
184         private void SetCount(Label label, QuestCount count)\r
185         {\r
186             label.Text = " " + count;\r
187             label.ForeColor = count.Cleared ? CUDColors.Red : Color.Black;\r
188             ToolTip.SetToolTip(label, count.ToToolTip());\r
189         }\r
190 \r
191         private void NameLabelDoubleClickHandler(object sender, EventArgs e)\r
192         {\r
193             NameLabelDoubleClick?.Invoke(sender, e);\r
194         }\r
195 \r
196         public event EventHandler NameLabelDoubleClick;\r
197 \r
198         protected override void OnPaint(PaintEventArgs e)\r
199         {\r
200             base.OnPaint(e);\r
201             DrawMark();\r
202         }\r
203 \r
204         private void DrawMark()\r
205         {\r
206             using (var g = CreateGraphics())\r
207             {\r
208                 var topBrush = _listPosition > 0 ? Brushes.Black : new SolidBrush(BackColor);\r
209                 g.FillPolygon(topBrush,\r
210                     new[]\r
211                     {\r
212                         new PointF(Width * 0.45f, TopMargin), new PointF(Width * 0.55f, TopMargin),\r
213                         new PointF(Width * 0.5f, 0), new PointF(Width * 0.45f, TopMargin)\r
214                     });\r
215                 var bottomBrush = _listPosition + Lines < _questList.Length\r
216                     ? Brushes.Black\r
217                     : new SolidBrush(BackColor);\r
218                 g.FillPolygon(bottomBrush,\r
219                     new[]\r
220                     {\r
221                         new PointF(Width * 0.45f, Height - TopMargin - 2),\r
222                         new PointF(Width * 0.55f, Height - TopMargin - 2),\r
223                         new PointF(Width * 0.5f, Height - 2), new PointF(Width * 0.45f, Height - TopMargin - 2)\r
224                     });\r
225             }\r
226         }\r
227     }\r
228 }