OSDN Git Service

装備の種別が不明でも例外にならないようにする
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / ItemTreeView.cs
1 // Copyright (C) 2014, 2015 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;\r
17 using System.Collections.Generic;\r
18 using System.Linq;\r
19 using System.Runtime.InteropServices;\r
20 using System.Windows.Forms;\r
21 \r
22 namespace KancolleSniffer\r
23 {\r
24     public class ItemTreeView : DbTreeView\r
25     {\r
26         private ItemStatus[] _prevItemList;\r
27 \r
28         public void SetNodes(ItemStatus[] itemList)\r
29         {\r
30             if (_prevItemList != null && _prevItemList.SequenceEqual(itemList, new ItemStatusComparer()))\r
31                 return;\r
32             _prevItemList = itemList.Select(CloneItemStatus).ToArray();\r
33             SetNodes(CreateItemNodes(itemList));\r
34         }\r
35 \r
36         private TreeNode CreateItemNodes(IEnumerable<ItemStatus> itemList)\r
37         {\r
38             var grouped = from byItem in (from item in itemList\r
39                 where item.Spec.Id != -1\r
40                 orderby item.Spec.Type, item.Spec.Id, item.Alv, item.Level descending\r
41                 group item by new {item.Spec.Id, item.Alv, item.Level}\r
42                 into grp\r
43                 from byShip in\r
44                     (from item in grp\r
45                         let ship = item.Holder\r
46                         orderby ship.Level descending, ship.Spec.SortNo\r
47                         group item by item.Holder.Id)\r
48                 group byShip by grp.Key)\r
49                 group byItem by byItem.First().First().Spec.Type;\r
50 \r
51             var root = new TreeNode();\r
52             foreach (var byType in grouped)\r
53             {\r
54                 var typeName = byType.First().First().First().Spec.TypeName;\r
55                 var typeNode = new TreeNode();\r
56                 typeNode.Name = typeNode.Text = typeName;\r
57                 root.Nodes.Add(typeNode);\r
58                 foreach (var byItem in byType)\r
59                 {\r
60                     var item = byItem.First().First();\r
61                     var itemNode = new TreeNode();\r
62                     itemNode.Name = itemNode.Text = item.Spec.Name +\r
63                                                     (item.Alv == 0 ? "" : "+" + item.Alv) +\r
64                                                     (item.Level == 0 ? "" : "★" + item.Level);\r
65                     typeNode.Nodes.Add(itemNode);\r
66                     foreach (var byShip in byItem)\r
67                     {\r
68                         var ship = byShip.First().Holder;\r
69                         var name = byShip.Key == -1\r
70                             ? "未装備x" + byShip.Count()\r
71                             : (ship.Fleet != -1 ? ship.Fleet + 1 + " " : "") +\r
72                               ship.Name + (ship.Level > 0 ? "Lv" + ship.Level : "") + "×" + byShip.Count();\r
73                         itemNode.Nodes.Add(name, name);\r
74                     }\r
75                 }\r
76             }\r
77             return root;\r
78         }\r
79 \r
80         private ItemStatus CloneItemStatus(ItemStatus org)\r
81         {\r
82             return new ItemStatus\r
83             {\r
84                 Level = org.Level,\r
85                 Spec = org.Spec,\r
86                 Holder = new ShipStatus {Id = org.Holder.Id, Fleet = org.Holder.Fleet}\r
87             };\r
88         }\r
89 \r
90         private class ItemStatusComparer : IEqualityComparer<ItemStatus>\r
91         {\r
92             public bool Equals(ItemStatus x, ItemStatus y)\r
93                 => x.Level == y.Level && x.Spec == y.Spec && x.Holder.Id == y.Holder.Id &&\r
94                    x.Holder.Fleet == y.Holder.Fleet;\r
95 \r
96             public int GetHashCode(ItemStatus obj) => obj.Level + obj.Spec.GetHashCode() + obj.Holder.GetHashCode();\r
97         }\r
98 \r
99         [DllImport("user32.dll")]\r
100         private static extern int GetScrollPos(IntPtr hWnd, int nBar);\r
101 \r
102         [DllImport("user32.dll")]\r
103         private static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);\r
104 \r
105         private void SetNodes(TreeNode root)\r
106         {\r
107             var y = GetScrollPos(Handle, 1);\r
108             BeginUpdate();\r
109             var save = SaveTreeViewState(Nodes);\r
110             Nodes.Clear();\r
111             foreach (TreeNode child in root.Nodes)\r
112                 Nodes.Add(child);\r
113             RestoreTreeViewState(Nodes, save.Nodes);\r
114             EndUpdate();\r
115             SetScrollPos(Handle, 1, y, true);\r
116         }\r
117 \r
118         private TreeNode SaveTreeViewState(IEnumerable nodes)\r
119         {\r
120             var result = new TreeNode();\r
121             foreach (TreeNode child in nodes)\r
122             {\r
123                 var copy = SaveTreeViewState(child.Nodes);\r
124                 if (child.IsExpanded)\r
125                     copy.Expand();\r
126                 copy.Name = child.Name;\r
127                 result.Nodes.Add(copy);\r
128             }\r
129             return result;\r
130         }\r
131 \r
132         private void RestoreTreeViewState(TreeNodeCollection dst, TreeNodeCollection src)\r
133         {\r
134             foreach (TreeNode d in dst)\r
135             {\r
136                 var s = src[d.Name];\r
137                 if (s == null)\r
138                     continue;\r
139                 if (s.IsExpanded)\r
140                     d.Expand();\r
141                 RestoreTreeViewState(d.Nodes, s.Nodes);\r
142             }\r
143         }\r
144     }\r
145 }