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.Ship\r
46                         orderby ship.Level descending, ship.Spec.SortNo\r
47                         group item by item.Ship.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().Ship;\r
69                         var name = byShip.Key == -1\r
70                             ? "未装備x" + byShip.Count()\r
71                             : (ship.Fleet != -1 ? ship.Fleet + 1 + " " : "") +\r
72                               ship.Name + "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                 Ship = new ShipStatus {Id = org.Ship.Id, Fleet = org.Ship.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.Ship.Id == y.Ship.Id && x.Ship.Fleet == y.Ship.Fleet;\r
94 \r
95             public int GetHashCode(ItemStatus obj) => obj.Level + obj.Spec.GetHashCode() + obj.Ship.GetHashCode();\r
96         }\r
97 \r
98         [DllImport("user32.dll")]\r
99         private static extern int GetScrollPos(IntPtr hWnd, int nBar);\r
100 \r
101         [DllImport("user32.dll")]\r
102         private static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);\r
103 \r
104         private void SetNodes(TreeNode root)\r
105         {\r
106             var y = GetScrollPos(Handle, 1);\r
107             BeginUpdate();\r
108             var save = SaveTreeViewState(Nodes);\r
109             Nodes.Clear();\r
110             foreach (TreeNode child in root.Nodes)\r
111                 Nodes.Add(child);\r
112             RestoreTreeViewState(Nodes, save.Nodes);\r
113             EndUpdate();\r
114             SetScrollPos(Handle, 1, y, true);\r
115         }\r
116 \r
117         private TreeNode SaveTreeViewState(IEnumerable nodes)\r
118         {\r
119             var result = new TreeNode();\r
120             foreach (TreeNode child in nodes)\r
121             {\r
122                 var copy = SaveTreeViewState(child.Nodes);\r
123                 if (child.IsExpanded)\r
124                     copy.Expand();\r
125                 copy.Name = child.Name;\r
126                 result.Nodes.Add(copy);\r
127             }\r
128             return result;\r
129         }\r
130 \r
131         private void RestoreTreeViewState(TreeNodeCollection dst, TreeNodeCollection src)\r
132         {\r
133             foreach (TreeNode d in dst)\r
134             {\r
135                 var s = src[d.Name];\r
136                 if (s == null)\r
137                     continue;\r
138                 if (s.IsExpanded)\r
139                     d.Expand();\r
140                 RestoreTreeViewState(d.Nodes, s.Nodes);\r
141             }\r
142         }\r
143     }\r
144 }