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 byId in\r
39                 (from item in itemList\r
40                     where item.Spec.Id != -1\r
41                     orderby item.Spec.Type, item.Spec.Id, item.Alv, item.Level descending, item.Ship.Spec.Id\r
42                     group item by new {item.Spec.Id, item.Alv, item.Level})\r
43                 group byId by byId.First().Spec.Type;\r
44             var root = new TreeNode();\r
45             foreach (var byType in grouped)\r
46             {\r
47                 var typeName = byType.First().First().Spec.TypeName;\r
48                 var typeNode = new TreeNode();\r
49                 typeNode.Name = typeNode.Text = typeName;\r
50                 root.Nodes.Add(typeNode);\r
51                 foreach (var byItem in byType)\r
52                 {\r
53                     var item = byItem.First();\r
54                     var itemNode = new TreeNode();\r
55                     itemNode.Name = itemNode.Text = item.Spec.Name +\r
56                                                     (item.Alv == 0 ? "" : "+" + item.Alv) +\r
57                                                     (item.Level == 0 ? "" : "★" + item.Level);\r
58                     typeNode.Nodes.Add(itemNode);\r
59 \r
60                     var shipGroup = (from i in byItem group i.Ship by i.Ship.Id).ToArray();\r
61                     foreach (var name in\r
62                         from grp in shipGroup\r
63                         where grp.Key != -1\r
64                         let ship = grp.First()\r
65                         select (ship.Fleet != -1 ? ship.Fleet + 1 + " " : "") +\r
66                                ship.Name + "Lv" + ship.Level + "×" + grp.Count())\r
67                     {\r
68                         itemNode.Nodes.Add(name, name);\r
69                     }\r
70                     foreach (var name in (from grp in shipGroup where grp.Key == -1 select "未装備×" + grp.Count()))\r
71                     {\r
72                         itemNode.Nodes.Add(name, name);\r
73                     }\r
74                 }\r
75             }\r
76             return root;\r
77         }\r
78 \r
79         private ItemStatus CloneItemStatus(ItemStatus org)\r
80         {\r
81             return new ItemStatus\r
82             {\r
83                 Level = org.Level,\r
84                 Spec = org.Spec,\r
85                 Ship = new ShipStatus {Id = org.Ship.Id, Fleet = org.Ship.Fleet}\r
86             };\r
87         }\r
88 \r
89         private class ItemStatusComparer : IEqualityComparer<ItemStatus>\r
90         {\r
91             public bool Equals(ItemStatus x, ItemStatus y)\r
92                 => x.Level == y.Level && x.Spec == y.Spec && x.Ship.Id == y.Ship.Id && x.Ship.Fleet == y.Ship.Fleet;\r
93 \r
94             public int GetHashCode(ItemStatus obj) => obj.Level + obj.Spec.GetHashCode() + obj.Ship.GetHashCode();\r
95         }\r
96 \r
97         [DllImport("user32.dll")]\r
98         private static extern int GetScrollPos(IntPtr hWnd, int nBar);\r
99 \r
100         [DllImport("user32.dll")]\r
101         private static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);\r
102 \r
103         private void SetNodes(TreeNode root)\r
104         {\r
105             var y = GetScrollPos(Handle, 1);\r
106             BeginUpdate();\r
107             var save = SaveTreeViewState(Nodes);\r
108             Nodes.Clear();\r
109             foreach (TreeNode child in root.Nodes)\r
110                 Nodes.Add(child);\r
111             RestoreTreeViewState(Nodes, save.Nodes);\r
112             EndUpdate();\r
113             SetScrollPos(Handle, 1, y, true);\r
114         }\r
115 \r
116         private TreeNode SaveTreeViewState(IEnumerable nodes)\r
117         {\r
118             var result = new TreeNode();\r
119             foreach (TreeNode child in nodes)\r
120             {\r
121                 var copy = SaveTreeViewState(child.Nodes);\r
122                 if (child.IsExpanded)\r
123                     copy.Expand();\r
124                 copy.Name = child.Name;\r
125                 result.Nodes.Add(copy);\r
126             }\r
127             return result;\r
128         }\r
129 \r
130         private void RestoreTreeViewState(TreeNodeCollection dst, TreeNodeCollection src)\r
131         {\r
132             foreach (TreeNode d in dst)\r
133             {\r
134                 var s = src[d.Name];\r
135                 if (s == null)\r
136                     continue;\r
137                 if (s.IsExpanded)\r
138                     d.Expand();\r
139                 RestoreTreeViewState(d.Nodes, s.Nodes);\r
140             }\r
141         }\r
142     }\r
143 }