/* 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.Windows.Forms; using XenAdmin.Core; using System.Drawing; using System.Linq; using XenAPI; namespace XenAdmin.Controls { public class VgpuComboBox : NonSelectableComboBox { public VgpuComboBox() { DrawMode = DrawMode.OwnerDrawVariable; DropDownStyle = ComboBoxStyle.DropDownList; } protected override void OnDrawItem(DrawItemEventArgs e) { if (e.Index > -1) { e.DrawBackground(); GpuTuple obj = Items[e.Index] as GpuTuple; if (obj == null) return; if (IsHeaderItem(obj)) { Drawing.DrawText(e.Graphics, obj.ToString(), Program.DefaultFontBold, e.Bounds, SystemColors.ControlText, TextFormatFlags.VerticalCenter | TextFormatFlags.EndEllipsis); } else if (!obj.Enabled) { string text = (obj.IsVgpuSubitem ? " " : string.Empty) + obj; Drawing.DrawText(e.Graphics, text, Program.DefaultFont, e.Bounds, Color.DarkGray, TextFormatFlags.VerticalCenter | TextFormatFlags.EndEllipsis); } else { var textColor = e.ForeColor; if ((e.State & DrawItemState.Disabled) != 0) textColor = SystemColors.GrayText; string indentedText = obj.ToString(); if (obj.IsVgpuSubitem) indentedText = " " + obj; Drawing.DrawText(e.Graphics, indentedText, Program.DefaultFont, e.Bounds, textColor, TextFormatFlags.VerticalCenter | TextFormatFlags.EndEllipsis); e.DrawFocusRectangle(); } } base.OnDrawItem(e); } protected bool IsHeaderItem(object obj) { return obj is GpuTuple tuple && tuple.IsGpuHeaderItem; } protected override bool IsItemNonSelectable(object obj) { return obj is GpuTuple tuple && (tuple.IsGpuHeaderItem || !tuple.Enabled); } } public class GpuTuple : IEquatable { public readonly GPU_group GpuGroup; public readonly VGPU_type[] VgpuTypes; public readonly bool IsGpuHeaderItem; public readonly bool IsVgpuSubitem; public readonly bool Enabled = true; private string displayName = string.Empty; /// /// Create a GpuTuple that refers to a vGPU type which is a sub-item of a GPU group /// public GpuTuple(GPU_group gpuGroup, VGPU_type vgpuType, VGPU_type[] disabledVGpuTypes) { GpuGroup = gpuGroup; VgpuTypes = vgpuType == null ? null : new[] {vgpuType}; if (vgpuType != null) { IsVgpuSubitem = gpuGroup.HasVGpu(); if (disabledVGpuTypes != null && disabledVGpuTypes.Select(t => t.opaque_ref).Contains(vgpuType.opaque_ref)) Enabled = false; } UpdateDisplayName(); } /// /// Create a GpuTuple that refers to a non-selectable GPU group header item /// public GpuTuple(GPU_group gpuGroup, VGPU_type[] vgpuTypes) { GpuGroup = gpuGroup; VgpuTypes = vgpuTypes; IsGpuHeaderItem = true; UpdateDisplayName(); } private void UpdateDisplayName() { if (GpuGroup == null) { //this refers to the item "None" displayName = Messages.GPU_NONE; } else if (VgpuTypes == null || VgpuTypes.Length == 0 || VgpuTypes[0] == null) { //this refers to an item mapping a GPU with only pass-through type displayName = GpuGroup.Name(); } else if (IsVgpuSubitem) { //this refers to vGPU type which is a sub-item of a GPU group displayName = VgpuTypes[0].Description(); } else { //this refers to a non-selectable GPU group header item displayName = GpuGroup.Name(); } } public bool Equals(GpuTuple other) { if (other == null) return false; if (GpuGroup == null && other.GpuGroup == null) return true; if (GpuGroup == null || other.GpuGroup == null) return false; bool result = GpuGroup.Equals(other.GpuGroup); if (result) { if ((VgpuTypes == null || VgpuTypes.Length == 0) && (other.VgpuTypes == null || other.VgpuTypes.Length == 0)) return true; if ((VgpuTypes == null || VgpuTypes.Length == 0) || (other.VgpuTypes == null || other.VgpuTypes.Length == 0)) return false; if (VgpuTypes.Length != other.VgpuTypes.Length) return false; for (int i = 0; i < VgpuTypes.Length; i++) { if (!VgpuTypes[i].Equals(other.VgpuTypes[i])) return false; } if ((IsGpuHeaderItem && other.IsVgpuSubitem) || (IsVgpuSubitem && other.IsGpuHeaderItem)) return false; } return result; } public override string ToString() { return displayName; } } }