2013-06-24 13:41:48 +02:00
|
|
|
|
/* Copyright (c) Citrix Systems Inc.
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* Redistribution and use in source and binary forms,
|
|
|
|
|
* with or without modification, are permitted provided
|
|
|
|
|
* that the following conditions are met:
|
|
|
|
|
*
|
|
|
|
|
* * Redistributions of source code must retain the above
|
|
|
|
|
* copyright notice, this list of conditions and the
|
|
|
|
|
* following disclaimer.
|
|
|
|
|
* * Redistributions in binary form must reproduce the above
|
|
|
|
|
* copyright notice, this list of conditions and the
|
|
|
|
|
* following disclaimer in the documentation and/or other
|
|
|
|
|
* materials provided with the distribution.
|
|
|
|
|
*
|
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
|
|
|
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
|
|
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
|
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
|
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
|
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
|
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
|
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
|
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
|
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Collections.ObjectModel;
|
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
using XenAdmin.Actions;
|
|
|
|
|
using XenAdmin.Commands;
|
|
|
|
|
using XenAdmin.Controls;
|
|
|
|
|
using XenAdmin.Core;
|
|
|
|
|
using XenAdmin.Dialogs;
|
|
|
|
|
using XenAdmin.Network;
|
|
|
|
|
using XenAdmin.Network.StorageLink;
|
|
|
|
|
using XenAdmin.StorageLinkAPI;
|
|
|
|
|
using XenAPI;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
using XenAdmin.Properties;
|
|
|
|
|
|
|
|
|
|
namespace XenAdmin.Wizards.NewSRWizard_Pages.Frontends
|
|
|
|
|
{
|
|
|
|
|
public partial class CSLG : XenTabPage
|
|
|
|
|
{
|
|
|
|
|
#region Private fields
|
|
|
|
|
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
|
|
|
|
private IStorageLinkObject _storageLinkObject;
|
|
|
|
|
private ReadOnlyCollection<CslgSystemStorage> _storages;
|
|
|
|
|
private SR _srToReattach;
|
|
|
|
|
private bool _disasterRecoveryTask;
|
|
|
|
|
private int _storageSystemComboLastSelectedIndex = -1;
|
|
|
|
|
|
|
|
|
|
private const string ADAPTER_ID = "adapterid";
|
|
|
|
|
private const string STORAGE_SYSTEM_ID = "storageSystemId";
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
public CSLG()
|
|
|
|
|
{
|
|
|
|
|
InitializeComponent();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region Accessors
|
|
|
|
|
|
|
|
|
|
public StorageLinkAdapterBoston SelectedStorageAdapter { get { return comboBoxStorageSystem.SelectedItem as StorageLinkAdapterBoston; } }
|
|
|
|
|
|
|
|
|
|
public CslgSystemStorage SelectedStorageSystem { get { return comboBoxStorageSystem.SelectedItem as CslgSystemStorage; } }
|
|
|
|
|
|
|
|
|
|
public ReadOnlyCollection<CslgStoragePool> StoragePools { get; private set; }
|
|
|
|
|
|
|
|
|
|
public bool NetAppSelected
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
var item = comboBoxStorageSystem.SelectedItem as string;
|
|
|
|
|
return item != null && item == Messages.CSLG_NETAPP_DIRECT;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool DellSelected
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
var item = comboBoxStorageSystem.SelectedItem as string;
|
|
|
|
|
return item != null && item == Messages.CSLG_DELL_DIRECT;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Dictionary<string, string> DeviceConfigParts
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
var dconf = new Dictionary<string, string>();
|
2015-10-26 17:01:55 +01:00
|
|
|
|
var adapter = comboBoxStorageSystem.SelectedItem as StorageLinkAdapterBoston;
|
|
|
|
|
if (adapter != null)
|
|
|
|
|
dconf[ADAPTER_ID] = adapter.Id;
|
2013-06-24 13:41:48 +02:00
|
|
|
|
return dconf;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public SrWizardType SrWizardType
|
|
|
|
|
{
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
_srToReattach = value.SrToReattach;
|
|
|
|
|
_disasterRecoveryTask = value.DisasterRecoveryTask;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
private static List<StorageLinkCredentials> GetAllValidStorageLinkCreds()
|
|
|
|
|
{
|
|
|
|
|
var credsList = new List<StorageLinkCredentials>();
|
|
|
|
|
|
2015-10-26 17:01:55 +01:00
|
|
|
|
foreach (IXenConnection c in ConnectionsManager.XenConnectionsCopy.FindAll(c => c.IsConnected && !Helpers.FeatureForbidden(c, Host.RestrictStorageChoices)))
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
|
|
|
|
var p = Helpers.GetPoolOfOne(c);
|
|
|
|
|
credsList.Add(p.GetStorageLinkCredentials());
|
|
|
|
|
credsList.AddRange(Array.ConvertAll(p.Connection.Cache.PBDs, pbd => pbd.GetStorageLinkCredentials()));
|
|
|
|
|
}
|
|
|
|
|
credsList.RemoveAll(cc => cc == null || !cc.IsValid);
|
|
|
|
|
return credsList;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetStorageLinkObject(IStorageLinkObject storageLinkObject)
|
|
|
|
|
{
|
|
|
|
|
_storageLinkObject = storageLinkObject;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Performs a scan of the CSLG host specified in the textboxes.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>True, if the scan succeeded, otherwise False.</returns>
|
|
|
|
|
public bool PerformStorageSystemScan()
|
|
|
|
|
{
|
|
|
|
|
var items = new List<object>();
|
|
|
|
|
|
2015-10-26 17:01:55 +01:00
|
|
|
|
if (_storageLinkObject != null || (Connection.IsConnected && !Helpers.FeatureForbidden(Connection, Host.RestrictStorageChoices)))
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
|
|
|
|
if (_srToReattach == null || _srToReattach.type == "cslg")
|
|
|
|
|
{
|
2015-10-26 17:01:55 +01:00
|
|
|
|
var action = new SrCslgAdaptersScanAction(Connection);
|
|
|
|
|
var dialog = new ActionProgressDialog(action, ProgressBarStyle.Marquee);
|
|
|
|
|
// never show the error message if it fails.
|
|
|
|
|
action.Completed += s =>
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
2015-10-26 17:01:55 +01:00
|
|
|
|
if (!action.Succeeded)
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
2015-10-26 17:01:55 +01:00
|
|
|
|
Program.Invoke(dialog, dialog.Close);
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
2015-10-26 17:01:55 +01:00
|
|
|
|
};
|
2013-06-24 13:41:48 +02:00
|
|
|
|
|
2015-10-26 17:01:55 +01:00
|
|
|
|
dialog.ShowDialog(this);
|
|
|
|
|
if (action.Succeeded)
|
|
|
|
|
{
|
|
|
|
|
var adapters = action.GetAdapters();
|
|
|
|
|
items.AddRange(Util.PopulateList<object>(adapters));
|
|
|
|
|
items.Sort((x, y) => x.ToString().CompareTo(y.ToString()));
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
2015-10-26 17:01:55 +01:00
|
|
|
|
else
|
|
|
|
|
return false;
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool bostonHasDell = false;
|
|
|
|
|
bool bostonHasNetapp = false;
|
2015-10-26 17:01:55 +01:00
|
|
|
|
if (items != null)
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
|
|
|
|
bostonHasDell = (items.Find(item => ((StorageLinkAdapterBoston)item).Id == "DELL_EQUALLOGIC") != null);
|
|
|
|
|
bostonHasNetapp = (items.Find(item => ((StorageLinkAdapterBoston)item).Id == "NETAPP") != null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
comboBoxStorageSystem.Items.Clear();
|
|
|
|
|
|
|
|
|
|
if (_storageLinkObject != null)
|
|
|
|
|
{
|
2015-10-26 17:01:55 +01:00
|
|
|
|
;
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
|
|
|
|
else if (_srToReattach != null)
|
|
|
|
|
{
|
|
|
|
|
if (_srToReattach.type == "equal")
|
|
|
|
|
{
|
|
|
|
|
// a direct-connect Equallogic is being reattached. Only add this item.
|
|
|
|
|
comboBoxStorageSystem.Items.Add(Messages.CSLG_DELL_DIRECT);
|
|
|
|
|
}
|
|
|
|
|
else if (_srToReattach.type == "netapp")
|
|
|
|
|
{
|
|
|
|
|
// a direct-connect NetApp is being reattached. Only add this item.
|
|
|
|
|
comboBoxStorageSystem.Items.Add(Messages.CSLG_NETAPP_DIRECT);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// a pool or host was selected in the mainwindow tree when the wizard was launched.
|
2015-10-26 17:01:55 +01:00
|
|
|
|
if (!bostonHasDell || !bostonHasNetapp)
|
|
|
|
|
comboBoxStorageSystem.Items.Add(new NonSelectableComboBoxItem(Messages.CSLG_DIRECT_CONNECTION, true));
|
2013-06-24 13:41:48 +02:00
|
|
|
|
|
|
|
|
|
if (!bostonHasDell)
|
|
|
|
|
comboBoxStorageSystem.Items.Add(Messages.CSLG_DELL_DIRECT);
|
|
|
|
|
if (!bostonHasNetapp)
|
|
|
|
|
comboBoxStorageSystem.Items.Add(Messages.CSLG_NETAPP_DIRECT);
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-26 17:01:55 +01:00
|
|
|
|
if (items != null && items.Count > 0)
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
|
|
|
|
if (!bostonHasDell || !bostonHasNetapp)
|
|
|
|
|
comboBoxStorageSystem.Items.Add(new NonSelectableComboBoxItem(Messages.CSLG_STORAGELINK_ADAPTERS, true));
|
|
|
|
|
comboBoxStorageSystem.Items.AddRange(items.ToArray());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (comboBoxStorageSystem.SelectedIndex < 0 && comboBoxStorageSystem.Items.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
// select the first selectable item if nothing's already been selected.
|
|
|
|
|
comboBoxStorageSystem.SelectedItem = Util.PopulateList<object>(comboBoxStorageSystem.Items).Find(s => !(s is NonSelectableComboBoxItem));
|
2015-10-26 17:01:55 +01:00
|
|
|
|
if (_srToReattach != null && _srToReattach.type == "cslg")
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
|
|
|
|
comboBoxStorageSystem.SelectedItem =
|
|
|
|
|
Util.PopulateList<object>(comboBoxStorageSystem.Items).Find(s =>
|
|
|
|
|
{
|
|
|
|
|
var bostonadapter = s as StorageLinkAdapterBoston;
|
|
|
|
|
if (bostonadapter != null)
|
|
|
|
|
{
|
|
|
|
|
// sm_config["md_svid"] looks like "DELL__EQUALLOGIC__{GUID}"
|
|
|
|
|
// bostonadapter.Id looks like "DELL_EQUALLOGIC"
|
|
|
|
|
// Additionally, EMC__CLARIION is always SMI-S (CA-72968)
|
|
|
|
|
if (_srToReattach.sm_config.ContainsKey("md_svid"))
|
|
|
|
|
{
|
|
|
|
|
var svid = _srToReattach.sm_config["md_svid"];
|
|
|
|
|
if (svid.Replace("__", "_").StartsWith(bostonadapter.Id))
|
|
|
|
|
return true;
|
|
|
|
|
if (bostonadapter.Id == "SMIS_STORAGE_SYSTEM" && svid.StartsWith("EMC__CLARIION"))
|
|
|
|
|
return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool PerformStoragePoolScan()
|
|
|
|
|
{
|
2015-10-26 17:01:55 +01:00
|
|
|
|
StorageLinkCredentials credentials = null;
|
2013-06-24 13:41:48 +02:00
|
|
|
|
|
|
|
|
|
var scanAction = new SrCslgStoragePoolScanAction(Connection, Program.StorageLinkConnections.GetCopy(), credentials.Host,
|
|
|
|
|
credentials.Username, credentials.PasswordSecret, SelectedStorageSystem.StorageSystemId);
|
|
|
|
|
|
|
|
|
|
ActionProgressDialog dialog = new ActionProgressDialog(scanAction, ProgressBarStyle.Marquee);
|
|
|
|
|
dialog.ShowDialog(this);
|
|
|
|
|
|
|
|
|
|
if (scanAction.Succeeded)
|
|
|
|
|
StoragePools = scanAction.CslgStoragePools;
|
|
|
|
|
|
|
|
|
|
return scanAction.Succeeded;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region XenTabPage overrides
|
|
|
|
|
|
|
|
|
|
public override void PageLeave(PageLoadedDirection direction, ref bool cancel)
|
|
|
|
|
{
|
|
|
|
|
if (direction == PageLoadedDirection.Forward && SelectedStorageSystem != null)
|
|
|
|
|
cancel = !PerformStoragePoolScan();
|
|
|
|
|
|
|
|
|
|
base.PageLeave(direction, ref cancel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void PopulatePage()
|
|
|
|
|
{
|
2015-10-26 17:01:55 +01:00
|
|
|
|
labelAdapter.Visible = true;
|
|
|
|
|
labelSystem.Visible = flowLayoutPanel1.Visible = false;
|
|
|
|
|
labelStorageSystem.Text = Messages.CSLG_STORAGEADAPTER;
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string Text
|
|
|
|
|
{
|
2015-10-26 17:01:55 +01:00
|
|
|
|
get { return Messages.STORAGE_ADAPTER; }
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string PageTitle
|
|
|
|
|
{
|
2015-10-26 17:01:55 +01:00
|
|
|
|
get { return Messages.NEWSR_CSLG_ADAPTER_PAGE_TITLE; }
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string HelpID
|
|
|
|
|
{
|
2015-10-26 17:01:55 +01:00
|
|
|
|
get { return "SL_System"; }
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override bool EnableNext()
|
|
|
|
|
{
|
|
|
|
|
return comboBoxStorageSystem.SelectedItem != null &&
|
|
|
|
|
!(comboBoxStorageSystem.SelectedItem is NonSelectableComboBoxItem);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override bool EnablePrevious()
|
|
|
|
|
{
|
|
|
|
|
if (_disasterRecoveryTask && _srToReattach == null)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region NonSelectableComboBoxItem class
|
|
|
|
|
|
|
|
|
|
private class NonSelectableComboBoxItem
|
|
|
|
|
{
|
|
|
|
|
public string Text { get; private set; }
|
|
|
|
|
public bool Bold { get; private set; }
|
|
|
|
|
|
|
|
|
|
public NonSelectableComboBoxItem(string text, bool bold)
|
|
|
|
|
{
|
|
|
|
|
Text = text;
|
|
|
|
|
Bold = bold;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
|
|
|
|
return Text;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Event handlers
|
|
|
|
|
|
|
|
|
|
private void comboBoxStorageSystem_SelectedIndexChanged(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (comboBoxStorageSystem.SelectedItem is NonSelectableComboBoxItem)
|
|
|
|
|
{
|
2015-10-26 17:01:55 +01:00
|
|
|
|
if (comboBoxStorageSystem.SelectedIndex < comboBoxStorageSystem.Items.Count - 1 &&
|
2013-06-24 13:41:48 +02:00
|
|
|
|
(_storageSystemComboLastSelectedIndex < comboBoxStorageSystem.SelectedIndex || comboBoxStorageSystem.SelectedIndex == 0))
|
|
|
|
|
{
|
|
|
|
|
_storageSystemComboLastSelectedIndex = comboBoxStorageSystem.SelectedIndex;
|
|
|
|
|
comboBoxStorageSystem.SelectedIndex++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_storageSystemComboLastSelectedIndex = comboBoxStorageSystem.SelectedIndex;
|
|
|
|
|
comboBoxStorageSystem.SelectedIndex--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_storageSystemComboLastSelectedIndex = comboBoxStorageSystem.SelectedIndex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OnPageUpdated();
|
|
|
|
|
|
|
|
|
|
if (comboBoxStorageSystem.SelectedIndex >= 0)
|
|
|
|
|
{
|
|
|
|
|
if (_storageLinkObject != null)
|
|
|
|
|
{
|
|
|
|
|
// The user has changed which SL object to use using the storage-system combo-box so update that here.
|
|
|
|
|
|
|
|
|
|
if (_storageLinkObject is StorageLinkServer || _storageLinkObject is StorageLinkSystem)
|
|
|
|
|
{
|
|
|
|
|
_storageLinkObject = ((CslgSystemStorage)comboBoxStorageSystem.SelectedItem).StorageLinkSystem;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
StorageLinkPool storageLinkPool = (StorageLinkPool)_storageLinkObject;
|
|
|
|
|
|
|
|
|
|
if (storageLinkPool.StorageLinkSystem != ((CslgSystemStorage)comboBoxStorageSystem.SelectedItem).StorageLinkSystem)
|
|
|
|
|
{
|
|
|
|
|
_storageLinkObject = ((CslgSystemStorage)comboBoxStorageSystem.SelectedItem).StorageLinkSystem;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void comboBoxStorageSystem_DrawItem(object sender, DrawItemEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
ComboBox comboBox = (ComboBox)sender;
|
|
|
|
|
if (e.Index > -1)
|
|
|
|
|
{
|
|
|
|
|
var item = comboBox.Items[e.Index];
|
|
|
|
|
var storageSystem = item as CslgSystemStorage;
|
|
|
|
|
var nonSelectable = item as NonSelectableComboBoxItem;
|
|
|
|
|
bool edit = (e.State & DrawItemState.ComboBoxEdit) != 0;
|
|
|
|
|
const int imageWidth = 16;
|
|
|
|
|
int indent = edit ? 0 : (imageWidth / 2);
|
|
|
|
|
|
|
|
|
|
e.DrawBackground();
|
|
|
|
|
|
|
|
|
|
var textRect = new Rectangle(e.Bounds.X + indent + imageWidth, e.Bounds.Y, e.Bounds.Width - imageWidth - indent, e.Bounds.Height);
|
|
|
|
|
|
|
|
|
|
if (storageSystem != null)
|
|
|
|
|
{
|
|
|
|
|
e.Graphics.DrawImageUnscaled(Resources.sl_system_16, new Point(e.Bounds.X + indent, e.Bounds.Y + 1));
|
|
|
|
|
Drawing.DrawText(e.Graphics, item.ToString(), e.Font, textRect, e.ForeColor, TextFormatFlags.VerticalCenter | TextFormatFlags.EndEllipsis);
|
|
|
|
|
}
|
|
|
|
|
else if (nonSelectable != null)
|
|
|
|
|
{
|
|
|
|
|
// bold headings
|
|
|
|
|
Drawing.DrawText(e.Graphics, item.ToString(), new Font(e.Font, FontStyle.Bold), e.Bounds, e.ForeColor, TextFormatFlags.VerticalCenter | TextFormatFlags.EndEllipsis);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// dell and netapp direction connection.
|
|
|
|
|
textRect = new Rectangle(e.Bounds.X + indent, e.Bounds.Y, e.Bounds.Width - indent, e.Bounds.Height);
|
|
|
|
|
Drawing.DrawText(e.Graphics, item.ToString(), e.Font, textRect, e.ForeColor, TextFormatFlags.VerticalCenter | TextFormatFlags.EndEllipsis);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((e.State & DrawItemState.NoFocusRect) == 0)
|
|
|
|
|
{
|
|
|
|
|
e.DrawFocusRectangle();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
}
|
|
|
|
|
}
|