OSDN Git Service

艦娘一覧で艦種を表示するとレベル順に並ばないことがあるのを直す
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / View / ShipListPanel.cs
index 1acc87a..10d29f8 100644 (file)
@@ -78,10 +78,10 @@ namespace KancolleSniffer.View
                 ScrollBar.Value - e.Delta * SystemInformation.MouseWheelScrollLines / 120));\r
         }\r
 \r
-        public void Update(Sniffer sniffer, string mode, ListForm.SortOrder sortOrder, bool byShipType)\r
+        public void Update(Sniffer sniffer, string mode, ShipListConfig config)\r
         {\r
             _mode = mode;\r
-            CreateShipList(sniffer, sortOrder, byShipType);\r
+            CreateShipList(sniffer, config);\r
             SuspendDrawing();\r
             SetupLabels();\r
             SetShipLabels();\r
@@ -104,26 +104,23 @@ namespace KancolleSniffer.View
             Refresh();\r
         }\r
 \r
-        private void CreateShipList(Sniffer sniffer, ListForm.SortOrder sortOrder, bool byShipType)\r
+        private void CreateShipList(Sniffer sniffer, ShipListConfig config)\r
         {\r
-            var ships = _mode == "修復" ? sniffer.RepairList : FilterByGroup(sniffer.ShipList, _mode).ToArray();\r
-            var order = _mode == "修復" ? ListForm.SortOrder.Repair : sortOrder;\r
-            if (!byShipType)\r
+            var ships = FilterByShipTypes(\r
+                _mode == "修復" ? sniffer.RepairList : FilterByGroup(sniffer.ShipList, _mode),\r
+                config.ShipCategories).ToArray();\r
+            var order = _mode == "修復" ? ListForm.SortOrder.Repair : config.SortOrder;\r
+            if (!config.ShipType)\r
             {\r
                 _shipList = ships.OrderBy(s => s, new CompareShip(false, order)).ToArray();\r
                 return;\r
             }\r
-            var types = ships.Select(s => new {Id = s.Spec.ShipType, Name = s.Spec.ShipTypeName})\r
-                .Distinct()\r
-                .Select(stype =>\r
-                    new ShipStatus\r
-                    {\r
-                        Spec = new ShipSpec {Name = stype.Name, ShipType = stype.Id},\r
-                        Level = 1000,\r
-                        NowHp = -1000,\r
-                        Cond = -1000\r
-                    });\r
-            _shipList = ships.Concat(types).OrderBy(s => s, new CompareShip(true, order)).ToArray();\r
+            _shipList = ships.Select(ship => new {Id = ship.Spec.ShipType, Name = ship.Spec.ShipTypeName})\r
+                .Distinct().Select(type => new ShipStatus\r
+                {\r
+                    Spec = new ShipSpec { Name = type.Name, ShipType = type.Id},\r
+                    Level = 1000,\r
+                }).Concat(ships).OrderBy(ship => ship, new CompareShip(true, order)).ToArray();\r
         }\r
 \r
         private IEnumerable<ShipStatus> FilterByGroup(IEnumerable<ShipStatus> ships, string group)\r
@@ -134,6 +131,73 @@ namespace KancolleSniffer.View
             return from s in ships where GroupSettings[g].Contains(s.Id) select s;\r
         }\r
 \r
+        private static readonly int[][] ShipTypeIds =\r
+        {\r
+            new[] // 戦艦\r
+            {\r
+                8, // 巡洋戦艦\r
+                9, // 戦艦\r
+                10 // 航空戦艦\r
+            },\r
+            new[] // 空母\r
+            {\r
+                18, // 装甲空母\r
+                11, // 正規空母\r
+                7 // 軽空母\r
+            },\r
+            new[] // 重巡\r
+            {\r
+                5, // 重巡洋艦\r
+                6 // 航空巡洋艦\r
+            },\r
+            new[] // 軽巡\r
+            {\r
+                3, // 軽巡洋艦\r
+                4, // 重雷装巡洋艦\r
+                21 // 練習巡洋艦\r
+            },\r
+            new[] // 駆逐\r
+            {\r
+                2 // 駆逐艦\r
+            },\r
+            new[] // 海防\r
+            {\r
+                1 // 海防艦\r
+            },\r
+            new[] // 潜水\r
+            {\r
+                13, // 潜水艦\r
+                14 // 潜水空母\r
+            },\r
+            new[] // 補助\r
+            {\r
+                16, // 水上機母艦\r
+                17, // 揚陸艦\r
+                19, // 工作艦\r
+                20, // 潜水母艦\r
+                22 // 補給艦\r
+            }\r
+        };\r
+\r
+        private static readonly int[] ShipTypeSortIds = CreateShipTypeSortIds();\r
+\r
+        private static int[] CreateShipTypeSortIds()\r
+        {\r
+            var ids = ShipTypeIds.SelectMany(x => x).ToArray();\r
+            var res = new int[ids.Max() + 1];\r
+            for (var i = 0; i < ids.Length; i++)\r
+                res[ids[i]] = i;\r
+            return res;\r
+        }\r
+\r
+        private IEnumerable<ShipStatus> FilterByShipTypes(IEnumerable<ShipStatus> ships, ShipCategory shipTypes)\r
+        {\r
+            var ids = Enumerable.Range(0, ShipTypeIds.Length)\r
+                .Where(type => ((int)shipTypes & (1 << type)) != 0)\r
+                .SelectMany(type => ShipTypeIds[type]).ToArray();\r
+            return ships.Where(ship => ids.Contains(ship.Spec.ShipType));\r
+        }\r
+\r
         public IEnumerable<ShipStatus> CurrentShipList => _shipList.Where(ship => ship.Level != 1000);\r
 \r
         private class CompareShip : IComparer<ShipStatus>\r
@@ -154,7 +218,7 @@ namespace KancolleSniffer.View
                 if (_shipType)\r
                 {\r
                     if (a.Spec.ShipType != b.Spec.ShipType)\r
-                        return a.Spec.ShipType - b.Spec.ShipType;\r
+                        return ShipTypeSortIds[a.Spec.ShipType] - ShipTypeSortIds[b.Spec.ShipType];\r
                     if (a.Level != b.Level)\r
                     {\r
                         if (a.Level == 1000)\r
@@ -178,8 +242,7 @@ namespace KancolleSniffer.View
                         return b.Level - a.Level;\r
                     if (_order == ListForm.SortOrder.ExpToNextDescend)\r
                         return a.Level - b.Level;\r
-                    if (!_shipType) // Condが同じかSortOrder.Noneで艦種なし\r
-                        return b.Level - a.Level;\r
+                    return b.Level - a.Level;\r
                 }\r
                 if (a.ExpToNext != b.ExpToNext)\r
                 {\r
@@ -188,8 +251,8 @@ namespace KancolleSniffer.View
                     if (_order == ListForm.SortOrder.ExpToNextDescend)\r
                         return b.ExpToNext - a.ExpToNext;\r
                 }\r
-                if (a.Spec.SortNo != b.Spec.SortNo)\r
-                    return a.Spec.SortNo - b.Spec.SortNo;\r
+                if (a.Spec.SortId != b.Spec.SortId)\r
+                    return a.Spec.SortId - b.Spec.SortId;\r
                 return a.Id - b.Id;\r
             }\r
         }\r
@@ -202,12 +265,6 @@ namespace KancolleSniffer.View
                 CreateRepairLabels(i);\r
                 CreateShipLabels(i);\r
             }\r
-            for (var i = 0; i * LineHeight < Height; i++)\r
-            {\r
-                _labelPanelList[i].Visible = InShipStatus(_mode);\r
-                _groupingPanelList[i].Visible = _mode == "分類";\r
-                _repairPanelList[i].Visible = _mode == "修復";\r
-            }\r
             SetupScrollBar();\r
         }\r
 \r
@@ -233,15 +290,15 @@ namespace KancolleSniffer.View
         private void CreateGroupingComponents(int i)\r
         {\r
             var y = LineHeight * i + 1;\r
-            var cfgp = new Panel\r
+            var panel = new Panel\r
             {\r
                 Location = new Point(0, y),\r
                 Size = new Size(ListForm.PanelWidth, LineHeight),\r
                 BackColor = ShipLabel.ColumnColors[(i + 1) % 2]\r
             };\r
-            cfgp.Scale(ShipLabel.ScaleFactor);\r
-            cfgp.Tag = cfgp.Location.Y;\r
-            var cfgl = new[]\r
+            panel.Scale(ShipLabel.ScaleFactor);\r
+            panel.Tag = panel.Location.Y;\r
+            var labels = new[]\r
             {\r
                 new ShipLabel\r
                 {\r
@@ -266,15 +323,16 @@ namespace KancolleSniffer.View
                 cb[j].Scale(ShipLabel.ScaleFactor);\r
                 cb[j].CheckedChanged += checkboxGroup_CheckedChanged;\r
             }\r
-            _groupingLabelList.Add(cfgl);\r
+            _groupingLabelList.Add(labels);\r
             _checkBoxesList.Add(cb);\r
-            _groupingPanelList.Add(cfgp);\r
+            _groupingPanelList.Add(panel);\r
             // ReSharper disable CoVariantArrayConversion\r
-            cfgp.Controls.AddRange(cfgl);\r
-            cfgp.Controls.AddRange(cb);\r
+            panel.Controls.AddRange(labels);\r
+            panel.Controls.AddRange(cb);\r
             // ReSharper restore CoVariantArrayConversion\r
-            Controls.Add(cfgp);\r
-            foreach (var label in cfgl)\r
+            Controls.Add(panel);\r
+            var unused = panel.Handle; // create handle\r
+            foreach (var label in labels)\r
             {\r
                 label.Scale();\r
                 label.PresetColor =\r
@@ -302,15 +360,15 @@ namespace KancolleSniffer.View
         {\r
             var y = LineHeight * i + 1;\r
             const int height = LabelHeight;\r
-            var rpp = new Panel\r
+            var panel = new Panel\r
             {\r
                 Location = new Point(0, y),\r
                 Size = new Size(ListForm.PanelWidth, LineHeight),\r
                 BackColor = ShipLabel.ColumnColors[(i + 1) % 2]\r
             };\r
-            rpp.Scale(ShipLabel.ScaleFactor);\r
-            rpp.Tag = rpp.Location.Y;\r
-            var rpl = new[]\r
+            panel.Scale(ShipLabel.ScaleFactor);\r
+            panel.Tag = panel.Location.Y;\r
+            var labels = new[]\r
             {\r
                 new ShipLabel\r
                 {\r
@@ -332,34 +390,35 @@ namespace KancolleSniffer.View
                 new ShipLabel {Location = new Point(10, 2), AutoSize = true},\r
                 new ShipLabel {Location = new Point(1, 2), AutoSize = true}\r
             };\r
-            _repairLabelList.Add(rpl);\r
-            _repairPanelList.Add(rpp);\r
+            _repairLabelList.Add(labels);\r
+            _repairPanelList.Add(panel);\r
             // ReSharper disable once CoVariantArrayConversion\r
-            rpp.Controls.AddRange(rpl);\r
-            Controls.Add(rpp);\r
-            foreach (var label in rpl)\r
+            panel.Controls.AddRange(labels);\r
+            Controls.Add(panel);\r
+            var unused = panel.Handle; // create handle\r
+            foreach (var label in labels)\r
             {\r
                 label.Scale();\r
                 label.PresetColor =\r
                     label.BackColor = ShipLabel.ColumnColors[(i + 1) % 2];\r
             }\r
             if (_hpPercent)\r
-                rpl[0].ToggleHpPercent();\r
-            _hpLabels.Add(rpl[0]);\r
-            rpl[0].DoubleClick += HpLabelClickHandler;\r
+                labels[0].ToggleHpPercent();\r
+            _hpLabels.Add(labels[0]);\r
+            labels[0].DoubleClick += HpLabelClickHandler;\r
         }\r
 \r
         private void CreateShipLabels(int i)\r
         {\r
             var y = LineHeight * i + 1;\r
             const int height = LabelHeight;\r
-            var lbp = new Panel\r
+            var panel = new Panel\r
             {\r
                 Location = new Point(0, y),\r
                 Size = new Size(ListForm.PanelWidth, LineHeight),\r
                 BackColor = ShipLabel.ColumnColors[(i + 1) % 2]\r
             };\r
-            lbp.Scale(ShipLabel.ScaleFactor);\r
+            panel.Scale(ShipLabel.ScaleFactor);\r
             var labels = new[]\r
             {\r
                 new ShipLabel\r
@@ -393,10 +452,11 @@ namespace KancolleSniffer.View
                 new ShipLabel {Location = new Point(1, 2), AutoSize = true}\r
             };\r
             _labelList.Add(labels);\r
-            _labelPanelList.Add(lbp);\r
+            _labelPanelList.Add(panel);\r
             // ReSharper disable once CoVariantArrayConversion\r
-            lbp.Controls.AddRange(labels);\r
-            Controls.Add(lbp);\r
+            panel.Controls.AddRange(labels);\r
+            Controls.Add(panel);\r
+            var unused = panel.Handle; // create handle\r
             foreach (var label in labels)\r
             {\r
                 label.Scale();\r
@@ -413,6 +473,9 @@ namespace KancolleSniffer.View
         {\r
             for (var i = 0; i < (Height + LineHeight - 1) / LineHeight; i++)\r
             {\r
+                HidePanels(i);\r
+                if (i + ScrollBar.Value >= _shipList.Length)\r
+                    continue;\r
                 if (InShipStatus(_mode))\r
                     SetShipStatus(i);\r
                 if (_mode == "分類")\r
@@ -422,16 +485,15 @@ namespace KancolleSniffer.View
             }\r
         }\r
 \r
+        private void HidePanels(int i)\r
+        {\r
+            _labelPanelList[i].Visible = _groupingPanelList[i].Visible = _repairPanelList[i].Visible = false;\r
+        }\r
+\r
         private bool InShipStatus(string mode) => Array.Exists(new[] {"全艦", "A", "B", "C", "D"}, x => mode == x);\r
 \r
         private void SetShipStatus(int i)\r
         {\r
-            var panel = _labelPanelList[i];\r
-            if (i + ScrollBar.Value >= _shipList.Length)\r
-            {\r
-                panel.Visible = false;\r
-                return;\r
-            }\r
             var s = _shipList[i + ScrollBar.Value];\r
             var labels = _labelList[i];\r
             if (s.Level == 1000) // 艦種の表示\r
@@ -445,7 +507,7 @@ namespace KancolleSniffer.View
             labels[3].SetExpToNext(s);\r
             labels[4].SetName(s, ShipNameWidth.ShipList);\r
             labels[5].SetFleet(s);\r
-            panel.Visible = true;\r
+            _labelPanelList[i].Visible = true;\r
         }\r
 \r
         private void SetShipType(int i)\r
@@ -464,18 +526,10 @@ namespace KancolleSniffer.View
 \r
         private void SetGrouping(int i)\r
         {\r
-            var panel = _groupingPanelList[i];\r
-            if (i + ScrollBar.Value >= _shipList.Length)\r
-            {\r
-                panel.Visible = false;\r
-                _labelPanelList[i].Visible = false;\r
-                return;\r
-            }\r
             var s = _shipList[i + ScrollBar.Value];\r
             var labels = _groupingLabelList[i];\r
             if (s.Level == 1000)\r
             {\r
-                panel.Visible = false;\r
                 SetShipType(i);\r
                 return;\r
             }\r
@@ -485,33 +539,25 @@ namespace KancolleSniffer.View
             var cb = _checkBoxesList[i];\r
             for (var j = 0; j < cb.Length; j++)\r
                 cb[j].Checked = GroupSettings[j].Contains(s.Id);\r
-            panel.Visible = true;\r
+            _groupingPanelList[i].Visible = true;\r
         }\r
 \r
         private void SetRepairList(int i)\r
         {\r
-            var panel = _repairPanelList[i];\r
-            if (i + ScrollBar.Value >= _shipList.Length)\r
-            {\r
-                panel.Visible = false;\r
-                _labelPanelList[i].Visible = false;\r
-                return;\r
-            }\r
             var s = _shipList[i + ScrollBar.Value];\r
             if (s.Level == 1000)\r
             {\r
-                panel.Visible = false;\r
                 SetShipType(i);\r
                 return;\r
             }\r
-            var rpl = _repairLabelList[i];\r
-            rpl[0].SetHp(s);\r
-            rpl[1].SetLevel(s);\r
-            rpl[2].SetRepairTime(s);\r
-            rpl[3].Text = s.RepairTimePerHp.ToString(@"mm\:ss");\r
-            rpl[4].SetName(s, ShipNameWidth.RepairListFull);\r
-            rpl[5].SetFleet(s);\r
-            panel.Visible = true;\r
+            var labels = _repairLabelList[i];\r
+            labels[0].SetHp(s);\r
+            labels[1].SetLevel(s);\r
+            labels[2].SetRepairTime(s);\r
+            labels[3].Text = s.RepairTimePerHp.ToString(@"mm\:ss");\r
+            labels[4].SetName(s, ShipNameWidth.RepairListFull);\r
+            labels[5].SetFleet(s);\r
+            _repairPanelList[i].Visible = true;\r
         }\r
 \r
         public event Action HpLabelClick;\r
@@ -530,6 +576,8 @@ namespace KancolleSniffer.View
 \r
         public void ShowShip(int id)\r
         {\r
+            if (!ScrollBar.Visible)\r
+                return;\r
             var i = Array.FindIndex(_shipList, s => s.Id == id);\r
             if (i == -1)\r
                 return;\r