mirror of
https://github.com/xcp-ng/xenadmin.git
synced 2024-12-22 16:36:03 +01:00
7c0bc50b4a
Inc. Signed-off-by: Gabor Apati-Nagy<gabor.apati-nagy@citrix.com>
176 lines
6.1 KiB
C#
176 lines
6.1 KiB
C#
/* 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.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Windows.Forms;
|
|
using XenAdmin.Controls.Ballooning;
|
|
using XenAdmin.Core;
|
|
using XenAPI;
|
|
|
|
namespace XenAdmin.Controls.GPU
|
|
{
|
|
public partial class GpuShinyBar : ShinyBar
|
|
{
|
|
public GpuShinyBar()
|
|
{
|
|
InitializeComponent();
|
|
}
|
|
|
|
public PGPU PGPU { get; private set; }
|
|
|
|
private List<VGPU> vGPUs;
|
|
private Dictionary<VGPU, VM> vms;
|
|
private long capacity;
|
|
private long maxCapacity;
|
|
|
|
public void Initialize(PGPU pGPU)
|
|
{
|
|
this.PGPU = pGPU;
|
|
|
|
vGPUs = pGPU.Connection.ResolveAll(pGPU.resident_VGPUs);
|
|
|
|
vms = new Dictionary<VGPU, VM>();
|
|
foreach (VGPU vgpu in vGPUs)
|
|
vms[vgpu] = vgpu.Connection.Resolve(vgpu.VM);
|
|
|
|
maxCapacity = 1;
|
|
if (!Helpers.FeatureForbidden(pGPU, Host.RestrictVgpu) && pGPU.HasVGpu && pGPU.supported_VGPU_max_capacities != null)
|
|
{
|
|
foreach (var n in pGPU.supported_VGPU_max_capacities.Values)
|
|
{
|
|
if (n > maxCapacity)
|
|
maxCapacity = n;
|
|
}
|
|
}
|
|
|
|
capacity = vGPUs.Count > 0 && pGPU.supported_VGPU_max_capacities.ContainsKey(vGPUs[0].type)
|
|
? pGPU.supported_VGPU_max_capacities[vGPUs[0].type] : maxCapacity;
|
|
}
|
|
|
|
protected override void OnPaint(PaintEventArgs e)
|
|
{
|
|
if (PGPU == null || vGPUs == null)
|
|
return;
|
|
|
|
Graphics g = e.Graphics;
|
|
Rectangle barArea = barRect;
|
|
|
|
// Grid
|
|
if (maxCapacity > 1)
|
|
DrawGrid(g, barArea, barArea.Width);
|
|
|
|
double left = barArea.Left;
|
|
|
|
// A bar for each vGPU
|
|
int i = 0;
|
|
vGPUs.Sort();
|
|
|
|
long segmentLength = barArea.Width / (capacity > 0 ? capacity : maxCapacity);
|
|
foreach (VGPU vgpu in vGPUs)
|
|
{
|
|
VM vm = vms[vgpu];
|
|
if (vm != null)
|
|
{
|
|
var vGpuType = PGPU.Connection.Resolve(vgpu.type);
|
|
|
|
DrawSegment(g, segmentLength, vm.Name, vGpuType != null ? vGpuType.model_name : "",
|
|
GpuShinyBarColors.GpuShinyBar_VMs[i++ % GpuShinyBarColors.GpuShinyBar_VMs.Length],
|
|
ref left);
|
|
}
|
|
}
|
|
|
|
// One final bar for free space
|
|
Rectangle rectFree = new Rectangle((int)left, barArea.Top, barArea.Right - (int)left, barArea.Height);
|
|
DrawToTarget(g, barArea, rectFree, GpuShinyBarColors.GpuShinyBar_Unused);
|
|
}
|
|
|
|
private void DrawGrid(Graphics g, Rectangle barArea, long max)
|
|
{
|
|
const int line_height = 12;
|
|
|
|
int line_bottom = barArea.Top + barArea.Height / 2;
|
|
int line_top = barArea.Top - line_height;
|
|
|
|
long incr = max / (capacity > 0 ? capacity : maxCapacity);
|
|
|
|
// Draw the grid
|
|
using (Pen pen = new Pen(GpuShinyBarColors.Grid))
|
|
{
|
|
for (long x = 0; x <= max; x += incr)
|
|
{
|
|
// Tick
|
|
int pos = barArea.Left + (int)((double)x);
|
|
g.DrawLine(pen, pos, line_top, pos, line_bottom);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DrawSegment(Graphics g, long width, string name, string description, Color color, ref double left)
|
|
{
|
|
if (width < 0)
|
|
return;
|
|
|
|
var rect = new Rectangle((int)left, barRect.Top,
|
|
(int)(left + width) - (int)left, // this is not necessarily the same as (int)width, which can leave a 1 pixel gap
|
|
barRect.Height);
|
|
var caption = name + "\n" + description;
|
|
DrawToTarget(g, barRect, rect, color, caption, GpuShinyBarColors.GpuShinyBar_Text, HorizontalAlignment.Center, caption);
|
|
left += width;
|
|
}
|
|
|
|
protected override int barHeight
|
|
{
|
|
get
|
|
{
|
|
return 40;
|
|
}
|
|
}
|
|
|
|
protected override Rectangle barRect
|
|
{
|
|
get
|
|
{
|
|
return new Rectangle(10, 20, this.Width - 25, barHeight);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static class GpuShinyBarColors
|
|
{
|
|
public static Color[] GpuShinyBar_VMs = { Color.FromArgb(83, 39, 139), Color.FromArgb(157, 115, 215) };
|
|
public static Color GpuShinyBar_Unused = Color.Black;
|
|
public static Color GpuShinyBar_Text = Color.White;
|
|
|
|
public static Color Grid = Color.DarkGray;
|
|
}
|
|
}
|