OSDN Git Service

AppliStation-GUI,ソート後に対象列を削除すると異常終了する不具合を修正
[applistation/AppliStation.git] / AppliStation / PackageListView.cs
1 using System;\r
2 using System.Drawing;\r
3 using System.Windows.Forms;\r
4 using System.Collections.Generic;\r
5 using System.ComponentModel;\r
6 using NaGet.Packages;\r
7 using NaGet.Packages.Install;\r
8 \r
9 namespace AppliStation\r
10 {\r
11         /// <summary>\r
12         /// PackageListViewの表示フィルタ\r
13         /// </summary>\r
14         [Flags]\r
15         public enum PackageListViewPkgTypeFilter\r
16         {\r
17                 None = 0,\r
18                 NotInstalled = 1,\r
19                 InstalledAS = 2,\r
20                 InstalledSys = 4,\r
21                 All = NotInstalled | InstalledAS | InstalledSys\r
22         }\r
23         \r
24         public class PackageListView : ListView\r
25         {\r
26 \r
27                 PackageListsManager pkgListMan = null;\r
28                 \r
29                 PackageListViewPkgTypeFilter filteringType = PackageListViewPkgTypeFilter.All;\r
30                 \r
31                 string filteringKeyword = null;\r
32                 \r
33                 AppliStation.Util.ListViewItemSortComparer sortComparer;\r
34                 \r
35                 [Category("Action")]\r
36                 public event EventHandler FilterUpdated;\r
37                 \r
38                 public PackageListView()\r
39                 {\r
40                         ListViewItemSorter = sortComparer = new AppliStation.Util.ListViewItemSortComparer();\r
41                 }\r
42                 \r
43                 /// <summary>\r
44                 /// パッケージリストのデータを設定・取得する。\r
45                 /// </summary>\r
46                 [Category("Behavior")]\r
47                 [DefaultValue(null)]\r
48                 public PackageListsManager Data\r
49                 {\r
50                         get {   return this.pkgListMan; }\r
51                         set {\r
52                                 this.pkgListMan = value;\r
53                                 \r
54                                 if (this.Visible) {\r
55                                         UpdateItems();\r
56                                 }\r
57                         }\r
58                 }\r
59                 \r
60                 /// <summary>\r
61                 /// 表示パッケージ種類フィルタを設定・取得する。\r
62                 /// </summary>\r
63                 [Category("Behavior")]\r
64                 [DefaultValue(PackageListViewPkgTypeFilter.All)]\r
65                 public PackageListViewPkgTypeFilter FilteringType {\r
66                         get { return filteringType; }\r
67                         set {\r
68                                 if (filteringType != value) {\r
69                                         filteringType = value;\r
70                                         \r
71                                         if (this.Visible) {\r
72                                                 UpdateItems();\r
73                                         }\r
74                                         \r
75                                         OnFilterUpdated(new EventArgs());\r
76                                 }\r
77                         }\r
78                 }\r
79                 \r
80                 /// <summary>\r
81                 /// 表示の際のフィルタリングキーワード\r
82                 /// </summary>\r
83                 [Category("Behavior")]\r
84                 [DefaultValue(typeof(string), null)]\r
85                 public string FilteringKeyword {\r
86                         get { return filteringKeyword; }\r
87                         set {\r
88                                 if (filteringKeyword != value) {\r
89                                         filteringKeyword = value;\r
90                                         \r
91                                         if (this.Visible) {\r
92                                                 UpdateItems();\r
93                                         }\r
94                                         \r
95                                         OnFilterUpdated(new EventArgs());\r
96                                 }\r
97                         }\r
98                 }\r
99                                 \r
100                 /// <summary>\r
101                 /// 選択されたパッケージを1つ返す\r
102                 /// </summary>\r
103                 public Package SelectedPackage {\r
104                         get {\r
105                                 if (SelectedItems.Count > 0) {\r
106                                         return (Package) (SelectedItems[0].Tag);\r
107                                 } else {\r
108                                         return null;\r
109                                 }\r
110                         }\r
111                 }\r
112                 \r
113                 /// <summary>\r
114                 /// 選択されたパッケージをイテレータとして返す\r
115                 /// </summary>\r
116                 public IEnumerable<Package> SelectedPackages {\r
117                         get {\r
118                                 foreach (ListViewItem item in SelectedItems) {\r
119                                         yield return (Package) item.Tag;\r
120                                 }\r
121                         }\r
122                 }\r
123                 \r
124                 #region データ領域作成メソッド群\r
125                 \r
126                 private ListViewItem createListViewItemForPackage(Package pkg, ImageCategory imageKey)\r
127                 {\r
128                         string[] labels = new string[this.Columns.Count];\r
129                         foreach (ColumnHeader header in this.Columns) {\r
130                                 string tag = header.Tag as string;\r
131                                 if (tag == "Name")                              labels[header.Index] = pkg.Name;\r
132                                 if (tag == "Version")                   labels[header.Index] = pkg.Version;\r
133                                 if (tag == "Summary")                   labels[header.Index] = pkg.Summary;\r
134                                 if (tag == "PackageListName")   labels[header.Index] = pkg.PackageListName;\r
135                         }\r
136                         \r
137                         ListViewItem item = new ListViewItem(labels);\r
138                         item.Tag = pkg;\r
139                         item.ToolTipText = pkg.Summary;\r
140                         item.ImageKey = ImageCategory_ToString(imageKey);\r
141                         \r
142                         return item;\r
143                 }\r
144                 \r
145                 public void UpdateItems()\r
146                 {\r
147                         string ImageKeyAvailable = ImageCategory_ToString(ImageCategory.Available);\r
148                         string ImageKeyAvailableNew = ImageCategory_ToString(ImageCategory.AvailableNew);\r
149                         string ImageKeyInstalled = ImageCategory_ToString(ImageCategory.Installed);\r
150                         string ImageKeySystem = ImageCategory_ToString(ImageCategory.System);\r
151                         string keyword = filteringKeyword ?? string.Empty;\r
152                         \r
153                         this.BeginUpdate();\r
154                         this.Items.Clear();\r
155                         \r
156                         // ソフトリストの中身のパッケージ\r
157                         if ((filteringType & PackageListViewPkgTypeFilter.NotInstalled) != 0) {\r
158                                 foreach (Package pkg in pkgListMan.AvailablePkgList.Search(keyword)) {\r
159                                         if (Installation.GetPreferInstallerIndex(pkg) >= 0) { // インストール可能\r
160                                                 bool isInstalledAS = (pkgListMan.InstalledPkgList.GetPackageForName(pkg.Name) != null);\r
161                                                 bool isInstalledSys = (pkgListMan.SystemInstalledPkgList.GetPackageForName(pkg.Name) != null);\r
162                                                 \r
163                                                 // インストールされていて、インストール済みソフトを表示しないならば、次のループへ\r
164                                                 if ((((filteringType & PackageListViewPkgTypeFilter.InstalledAS) == 0) && isInstalledAS) ||\r
165                                                     (((filteringType & PackageListViewPkgTypeFilter.InstalledSys) == 0) && isInstalledSys)) {\r
166                                                         continue;\r
167                                                 }\r
168                                                 \r
169                                                 ImageCategory cat = (isInstalledAS || isInstalledSys)? ImageCategory.Available : ImageCategory.AvailableNew;\r
170                                                 Items.Add(createListViewItemForPackage(pkg, cat));\r
171                                         }\r
172                                 }\r
173                         }\r
174                         \r
175                         // AppliStationにインストール済みのパッケージ\r
176                         if ((filteringType & PackageListViewPkgTypeFilter.InstalledAS) != 0) {\r
177                                 foreach (Package pkg in pkgListMan.InstalledPkgList.Search(keyword)) {\r
178                                         Items.Add(createListViewItemForPackage(pkg, ImageCategory.Installed));\r
179                                 }\r
180                         }\r
181                         \r
182                         // PCにインストール済みのパッケージ\r
183                         if ((filteringType & PackageListViewPkgTypeFilter.InstalledSys) != 0) {\r
184                                 foreach (Package pkg in pkgListMan.SystemInstalledPkgList.Search(keyword)) {\r
185                                         Items.Add(createListViewItemForPackage(pkg, ImageCategory.System));\r
186                                 }\r
187                         }\r
188                         \r
189                         this.EndUpdate();\r
190                         \r
191                         this.Refresh();\r
192                 }\r
193                 \r
194                 protected enum ImageCategory {\r
195                         Available,\r
196                         AvailableNew,\r
197                         Installed,\r
198                         System,\r
199                 };\r
200                 \r
201                 protected static string ImageCategory_ToString(ImageCategory cat)\r
202                 {\r
203                         switch (cat) {\r
204                         case ImageCategory.Available:           return "available";\r
205                         case ImageCategory.AvailableNew:        return "available-new";\r
206                         case ImageCategory.Installed:           return "installed";\r
207                         case ImageCategory.System:                      return "sys";\r
208                         default:                                                        return string.Empty;\r
209                         }\r
210                 }\r
211                 \r
212                 #endregion\r
213                 \r
214                 protected virtual void OnFilterUpdated(EventArgs e)\r
215                 {\r
216                         if (FilterUpdated != null) {\r
217                                 FilterUpdated(this, e);\r
218                         }\r
219                 }\r
220                 \r
221                 #region Sort関連\r
222                 \r
223                 protected void sortColumn(ColumnHeader column)\r
224                 {\r
225                         int columnIndex = column.Index;\r
226                         SortOrder order = SortOrder.None;\r
227                         \r
228                         if (sortComparer.ColumnIndex == columnIndex) {\r
229                                 order = (sortComparer.Order == SortOrder.Ascending)? SortOrder.Descending : SortOrder.Ascending;\r
230                                         \r
231                                 sortComparer.Order = order;\r
232                         } else {\r
233                                 order = SortOrder.Ascending;\r
234                                 sortComparer.Column = column;\r
235                         }\r
236                         Sort();\r
237                         \r
238                         AppliStation.Util.NativeMethods.ColumnHeader_SetSortState(this, columnIndex, order);\r
239                         \r
240                         // ソート対象列の色付け\r
241                         try {\r
242                                 // SendMessage(hWnd, LVM_SETSELECTEDCOLUMN, columnIndex, NULL);\r
243                                 AppliStation.Util.NativeMethods.SendMessage(this.Handle, 0x1000+140, new IntPtr(columnIndex), IntPtr.Zero);\r
244                         } catch (Exception) {   \r
245                         }\r
246                 }\r
247                 \r
248                 protected override void OnColumnClick(ColumnClickEventArgs e)\r
249                 {\r
250                         if (this.HeaderStyle == ColumnHeaderStyle.Clickable) {\r
251                                 sortColumn(this.Columns[e.Column]);\r
252                         }\r
253                         \r
254                         base.OnColumnClick(e);\r
255                 }\r
256                 \r
257                 #endregion\r
258         }\r
259 }\r