OSDN Git Service

e012eb58b65cb6c773780cbe42cbc5e38794db98
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / View / MainWindow / 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.Collections.Generic;\r
17 using System.Drawing;\r
18 using System.Linq;\r
19 using System.Windows.Forms;\r
20 using KancolleSniffer.Model;\r
21 \r
22 namespace KancolleSniffer.View.MainWindow\r
23 {\r
24     public class QuestPanel : PanelWithToolTip\r
25     {\r
26         private const int TopMargin = 5;\r
27         private const int LeftMargin = 2;\r
28         private const int LabelHeight = 12;\r
29         private const int LineHeight = 14;\r
30         private QuestLabels[] _labels;\r
31         private QuestStatus[] _questList = new QuestStatus[0];\r
32         private ListScroller _listScroller;\r
33         private int _lines;\r
34 \r
35         public int MinLines { get; set; } = 4;\r
36 \r
37         private class QuestLabels : ControlsArranger\r
38         {\r
39             public Label Color { get; set; }\r
40             public Label Name { get; set; }\r
41             public Label Count { get; set; }\r
42             public Label Progress { get; set; }\r
43 \r
44             public override Control[] Controls => new Control[] {Color, Count, Progress, Name};\r
45         }\r
46 \r
47         public void CreateLabels(int lines)\r
48         {\r
49             _lines = LimitLines(lines);\r
50             _labels = new QuestLabels[_lines];\r
51             SuspendLayout();\r
52             Height = Scaler.ScaleHeight(TopMargin * 2 + LineHeight * _lines);\r
53             for (var i = 0; i < _lines; i++)\r
54             {\r
55                 var y = TopMargin + i * LineHeight;\r
56                 _labels[i] = new QuestLabels\r
57                 {\r
58                     Color = new Label\r
59                     {\r
60                         Location = new Point(LeftMargin, y + 1),\r
61                         Size = new Size(4, LabelHeight - 1)\r
62                     },\r
63                     Name = new Label\r
64                     {\r
65                         Location = new Point(LeftMargin + 4, y),\r
66                         Size = new Size(193, LabelHeight)\r
67                     },\r
68                     Count = new GrowLeftLabel\r
69                     {\r
70                         Location = new Point(LeftMargin + 189, y),\r
71                         GrowLeft = true\r
72                     },\r
73                     Progress = new Label\r
74                     {\r
75                         Location = new Point(LeftMargin + 186, y),\r
76                         Size = new Size(29, LabelHeight),\r
77                         TextAlign = ContentAlignment.MiddleRight\r
78                     }\r
79                 };\r
80                 _labels[i].Arrange(this);\r
81                 _labels[i].Scale();\r
82             }\r
83             ResumeLayout();\r
84             SetupListScroller();\r
85         }\r
86 \r
87         private int LimitLines(int lines)\r
88         {\r
89             const int max = 7;\r
90             return Math.Min(Math.Max(lines, MinLines), max);\r
91         }\r
92 \r
93         private void SetupListScroller()\r
94         {\r
95             _listScroller = new ListScroller(this, _labels[0].Controls, _labels[_lines - 1].Controls)\r
96             {\r
97                 Lines = _lines,\r
98                 Padding = TopMargin\r
99             };\r
100             _listScroller.Update += ShowQuestList;\r
101             _listScroller.StartScroll += () => { ToolTip.Active = false; };\r
102             _listScroller.EndScroll += () => { ToolTip.Active = true; };\r
103         }\r
104 \r
105         public void Update(QuestStatus[] quests)\r
106         {\r
107             _listScroller.DataCount = quests.Length;\r
108             _listScroller.Position = CalcScrollPosition(quests);\r
109             _questList = quests.Select(q => q.Clone()).ToArray();\r
110             ShowQuestList();\r
111         }\r
112 \r
113         private int CalcScrollPosition(QuestStatus[] newQuests)\r
114         {\r
115             if (newQuests.Length <= _lines)\r
116                 return 0;\r
117             var current = _listScroller.Position;\r
118             var bottomIndex = current + _lines - 1;\r
119             if (newQuests.Length < _questList.Length)\r
120                 return bottomIndex >= newQuests.Length ? newQuests.Length - _lines : current;\r
121             var changedIndex = 0;\r
122             if (newQuests.Length > _questList.Length)\r
123             {\r
124                 changedIndex = _questList.TakeWhile((q, i) => q.Id == newQuests[i].Id).Count();\r
125             }\r
126             else if (newQuests.Length == _questList.Length)\r
127             {\r
128                 changedIndex = _questList.TakeWhile((q, i) => q.Count.Equals(newQuests[i].Count)).Count();\r
129                 if (changedIndex == _questList.Length) // unchanged\r
130                     return current;\r
131             }\r
132             if (changedIndex < current)\r
133                 return changedIndex;\r
134             if (changedIndex > bottomIndex)\r
135                 return current + changedIndex - bottomIndex;\r
136             return current;\r
137         }\r
138 \r
139         private void ShowQuestList()\r
140         {\r
141             SuspendLayout();\r
142             for (var i = 0; i < _lines; i++)\r
143             {\r
144                 var labels = _labels[i];\r
145                 if (i >= _questList.Length)\r
146                 {\r
147                     ClearQuest(labels);\r
148                     ClearCount(labels.Count);\r
149                     continue;\r
150                 }\r
151                 var quest = _questList[i + _listScroller.Position];\r
152                 SetQuest(labels, quest);\r
153                 if (quest.Count.Id == 0)\r
154                 {\r
155                     ClearCount(labels.Count);\r
156                     continue;\r
157                 }\r
158                 SetCount(labels.Count, quest.Count);\r
159             }\r
160             ResumeLayout(true);\r
161             _listScroller.DrawMark();\r
162         }\r
163 \r
164         private void ClearQuest(QuestLabels labels)\r
165         {\r
166             labels.Color.BackColor = DefaultBackColor;\r
167             labels.Name.Text = labels.Progress.Text = "";\r
168             ToolTip.SetToolTip(labels.Name, "");\r
169         }\r
170 \r
171         private void ClearCount(Label label)\r
172         {\r
173             label.Text = "";\r
174             label.ForeColor = Color.Black;\r
175             ToolTip.SetToolTip(label, "");\r
176         }\r
177 \r
178         private void SetQuest(QuestLabels labels, QuestStatus quest)\r
179         {\r
180             labels.Color.BackColor = quest.Color;\r
181             labels.Name.Text = quest.Name;\r
182             labels.Progress.Text = $"{quest.Progress:D}%";\r
183             ToolTip.SetToolTip(labels.Name, quest.ToToolTip());\r
184         }\r
185 \r
186         private void SetCount(Label label, QuestCount count)\r
187         {\r
188             label.Text = " " + count;\r
189             label.ForeColor = count.Cleared ? CUDColors.Red : Color.Black;\r
190             ToolTip.SetToolTip(label, count.ToToolTip());\r
191         }\r
192 \r
193         public IEnumerable<string> QuestNameList => _labels.Select(l => l.Name.Text); // for testing\r
194     }\r
195 }