using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using NaGet.Packages;
using NaGet.Packages.Install;
namespace AppliStation
{
///
/// Description of PackagesInstallConfirmForm.
///
public partial class InstallationConfirmForm : Form
{
private Installation[] requiredInstallations = null;
private Installation[] selectedInstallations = null;
private PackageListsManager pkgListMan;
public IEnumerable Installations {
get {
return NaGet.Utils.MergeEnumerable(requiredInstallations, selectedInstallations);
}
set {
requiredInstallations = null;
selectedInstallations = NaGet.Utils.IEnumerable2Array(value);
updateInstsListView();
}
}
public PackageListsManager PkgListsManager {
get { return pkgListMan; }
set {
pkgListMan = value;
updateInstsListView();
}
}
public InstallationConfirmForm()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
// 管理者権限で動いているならばrunasが必要にはならないので表示しない
if (NaGet.Utils.IsAdministrators()) {
runasCheckBox.Checked = false;
runasCheckBox.Visible = false;
}
// ListViewの効果
AppliStation.Util.NativeMethods.ListView_EnableVistaExplorerTheme(instsListView);
AppliStation.Util.NativeMethods.ListView_SetDoubleBuffer(instsListView, true);
}
#region インストールリスト表示処理部
#region インストールリストの反映
///
/// インストールリストを更新したなどで、リストの表示を更新する
///
private void updateInstsListView()
{
if (instsListView.Items.Count > 0) {
instsListView.Items.Clear();
}
addInstsListItemPerGroup(requiredInstallations, instsListView.Groups["requires"], true);
addInstsListItemPerGroup(selectedInstallations, instsListView.Groups["install"], false);
InstsListViewItemChecked(instsListView, null);
instsListView.Refresh();
}
///
/// 指定したグループのリストの表示を更新する。
///
/// インストールリスト
/// 対象のグループ
/// 先頭に追加するか
private void addInstsListItemPerGroup(IEnumerable insts, ListViewGroup group, bool firstAppend)
{
// まず所属グループのアイテムをすべて削除する
if (insts == null) return;
List itemsToAdd = new List();
foreach (Installation inst in insts) {
Package pkg = inst.InstalledPackage;
string[] itemData = new string[instsListView.Columns.Count];
itemData[nameColumnHeader.Index] = pkg.Name;
inst.Silent = true; // silent install as possible!
Package curPkg = null;
if (pkgListMan != null) {
curPkg = pkgListMan.InstalledPkgList.GetPackageForName(pkg.Name) ??
pkgListMan.SystemInstalledPkgList.GetPackageForName(pkg.Name);
}
itemData[versionColumnHeader.Index] = pkg.Version;
itemData[currentVersionColumnHeader.Index] = (curPkg != null)? curPkg.Version : "-";
// itemData[silentInstColumnHeader.Index] の設定は instViewUpdateSilentInstallView で
itemData[pkgListNameColumnHeader.Index] = pkg.PackageListName;
ListViewItem item = new ListViewItem(itemData);
item.Tag = inst;
item.ToolTipText = pkg.Summary;
item.Checked = true;
item.Group = group;
instViewUpdateSilentInstallView(item);
itemsToAdd.Add(item);
}
if (firstAppend) {
for (int i = 0; i < itemsToAdd.Count; i++) {
instsListView.Items.Insert(i, itemsToAdd[i]);
}
} else {
instsListView.Items.AddRange(itemsToAdd.ToArray());
}
}
#endregion
///
/// アイテムのサイレントインストール部分の表示の更新を行う。
///
/// 対象のインストーラのリストアイテム
private void instViewUpdateSilentInstallView(ListViewItem item)
{
Installation inst = (Installation) item.Tag;
item.SubItems[silentInstColumnHeader.Index].Text =
(inst.SupportsSilentOnly)? "サイレントインストールのみサポート" :
(inst.Silent)? "サイレントインストール" :
(inst.IsSupportsSilent)? "手動でインストール" :
"サイレントインストールできませんので、手動でインストールします";
}
#region instsListViewのオーナードドロー関連
void InstsListViewDrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
if (e.Header == silentInstColumnHeader) {
Installation inst = ((Installation) e.Item.Tag);
//e.DrawBackground();
e.Graphics.Clip.Intersect(e.Bounds);
if (inst.Silent) {
AppliStation.Util.GUIUtils.Graphics_DrawCenterImage(
e.Graphics,
instListViewSilentInstallImageList.Images[0],
e.Bounds, null);
} else if (inst.IsSupportsSilent) {
AppliStation.Util.GUIUtils.Graphics_DrawCenterImage(
e.Graphics,
instListViewSilentInstallImageList.Images[0],
e.Bounds,
AppliStation.Util.GUIUtils.GetImageAttributeToGrayOut(0.5f));
}
} else {
e.DrawDefault = true;
}
}
void InstsListViewDrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
{
if (e.Header == silentInstColumnHeader) {
e.DrawBackground();
e.Graphics.Clip.Intersect(e.Bounds);
AppliStation.Util.GUIUtils.Graphics_DrawCenterImage(
e.Graphics,
instListViewSilentInstallImageList.Images[0],
e.Bounds, null);
} else {
e.DrawDefault = true;
}
}
#endregion
#endregion
void InstsListViewItemChecked(object sender, ItemCheckedEventArgs e)
{
System.Windows.Forms.ListView.CheckedListViewItemCollection checkeds = instsListView.CheckedItems;
runasCheckBox.Checked = GetShouldUseRunas();
updateUseRunas();
okButton.Enabled = (checkeds != null) && (checkeds.Count > 0);
checkUnselectedDependencies();
}
void InstsListViewContextMenuStripOpening(object sender, System.ComponentModel.CancelEventArgs e)
{
System.Windows.Forms.ListView.CheckedIndexCollection chkIdxes = instsListView.CheckedIndices;
System.Windows.Forms.ListView.SelectedIndexCollection selIdxes = instsListView.SelectedIndices;
silentInstallStripMenuItem.Visible = selIdxes.Count > 0;
if (selIdxes.Count > 0) {
Installation inst0th = ((Installation) instsListView.Items[selIdxes[0]].Tag);
bool bChecked = inst0th.Silent;
bool bEnabled = (inst0th.IsSupportsSilent && (!inst0th.SupportsSilentOnly));
silentInstallStripMenuItem.Checked = bChecked;
silentInstallStripMenuItem.Enabled = bEnabled;
for (int i = 1; i < selIdxes.Count; i++) {
Installation inst = ((Installation) instsListView.Items[selIdxes[i]].Tag);
if ( (bChecked != inst.Silent) ||
(bEnabled != (inst.IsSupportsSilent && (!inst.SupportsSilentOnly))) ) {
silentInstallStripMenuItem.CheckState = CheckState.Indeterminate;
silentInstallStripMenuItem.Enabled = false;
break;
}
}
}
instListToolStripSeparator.Visible = selIdxes.Count > 0;
selectAllInstsStripMenuItem.Enabled = chkIdxes.Count < instsListView.Items.Count;
unselectAllInstsStripMenuItem.Enabled = chkIdxes.Count > 0;
}
void SilentInstallStripMenuItemClick(object sender, EventArgs e)
{
bool silent = ! silentInstallStripMenuItem.Checked;
foreach (ListViewItem item in instsListView.SelectedItems) {
((Installation) item.Tag).Silent = silent;
instViewUpdateSilentInstallView(item);
}
}
void SelectAllInstsStripMenuItemClick(object sender, EventArgs e)
{
foreach (ListViewItem item in instsListView.Items) {
item.Checked = true;
}
instsListView.Refresh();
}
void UnselectAllInstsStripMenuItemClick(object sender, EventArgs e)
{
foreach (ListViewItem item in instsListView.CheckedItems) {
item.Checked = false;
}
instsListView.Refresh();
}
void InstallationConfirmFormShown(object sender, EventArgs e)
{
if (InvokeRequired) {
Invoke(new MethodInvoker(resolveDependecies));
} else {
resolveDependecies();
}
}
///
/// 依存関係を解決する
///
private void resolveDependecies()
{
if (requiredInstallations == null) {
Installation[] resolved, dependencies;
DependeciesResolver.ResolveInstallations(
selectedInstallations,
pkgListMan,
out resolved,
out dependencies);
requiredInstallations = dependencies;
addInstsListItemPerGroup(requiredInstallations, instsListView.Groups["requires"], true);
InstsListViewItemChecked(instsListView, null);
instsListView.Refresh();
}
}
///
/// 依存関係を確認してGUIに反映させる。
/// 選択されていないが依存関係上必要なソフトを探し出す。
///
/// 選択されていないが依存関係上必要なソフトの個数(何もない場合はゼロ)
private uint checkUnselectedDependencies()
{
uint retVal = 0;
List instPkgs = new List();
foreach (Installation inst in Installations) {
instPkgs.Add(inst.InstalledPackage);
}
List pkg = new List();
foreach (Installation inst in DependeciesResolver.CreateRequiresInstallations(CheckedInstallations, pkgListMan, instPkgs)) {
pkg.Add(inst.InstalledPackage);
}
foreach (ListViewItem item in instsListView.Items) {
if ((pkg.IndexOf(((Installation) item.Tag).InstalledPackage) >= 0) && !item.Checked) {
item.ForeColor = Color.Red;
retVal++;
} else {
item.ForeColor = Color.Empty;
}
}
return retVal;
}
///
/// インストールするよう選択されたパッケージの配列
///
public Installation[] CheckedInstallations {
get {
List insts = new List();
foreach (ListViewItem item in instsListView.CheckedItems) {
insts.Add((Installation) item.Tag);
}
return insts.ToArray();
}
}
#region runas関連
///
/// runasで実行するか否か
///
public bool UseRunas {
set {
runasCheckBox.Checked = (! NaGet.Utils.IsAdministrators()) && value;
updateUseRunas();
}
get {
return runasCheckBox.Checked;
}
}
///
/// 選択されたパッケージを調査して、Runasを使うべきかいなかを返す
///
public bool GetShouldUseRunas()
{
if (NaGet.Utils.IsAdministrators()) {
// 管理者権限で動いている場合は不要
return false;
} else if (NaGet.Utils.IsUACEnabled()) {
// UACが適用されている場合は標準では不要とする
return false;
}
// ひとつでもPCターゲットなインストーラがあれば必要とする
foreach (Installation inst in CheckedInstallations) {
if (inst.TargetPC) return true;
}
// それ以外は不要
return false;
}
void RunasCheckBoxCheckedChanged(object sender, EventArgs e)
{
updateUseRunas();
}
private void updateUseRunas()
{
if (UseRunas) {
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(InstallationConfirmForm));
okButton.Image = ((System.Drawing.Bitmap)(resources.GetObject("okButton.Image")));
} else {
okButton.Image = null;
}
}
#endregion
}
}