mirror of
https://github.com/xcp-ng/xenadmin.git
synced 2024-12-30 07:40:13 +01:00
89a337ee85
The Free license never expires and is confusing to see "Unlicensed" or "Unsupported" hosts with expiry date "Never". Added the ability to add "hidden" entries to the General tab sections and to update their visibility when needed without regenerating the whole section. Signed-off-by: Mihaela Stoica <mihaela.stoica@citrix.com>
540 lines
18 KiB
C#
540 lines
18 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;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Drawing;
|
|
using System.Windows.Forms;
|
|
using XenAdmin.Controls.DataGridViewEx;
|
|
using XenAdmin.Core;
|
|
using XenAdmin.Properties;
|
|
using System.Linq;
|
|
using XenAdmin.Commands;
|
|
|
|
|
|
namespace XenAdmin.Controls
|
|
{
|
|
public partial class PDSection : UserControl
|
|
{
|
|
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
|
|
|
#region Private fields
|
|
|
|
/// <summary>
|
|
/// Used to persist selection over a repaint, we set this when we clear the datagridview
|
|
/// </summary>
|
|
private string previousSelectionKey;
|
|
|
|
private bool inLayout;
|
|
|
|
/// <summary>
|
|
/// Whether the mouse is over the chevron
|
|
/// </summary>
|
|
private bool chevronHot;
|
|
|
|
#endregion
|
|
|
|
#region Delegates and Events
|
|
|
|
/// <summary>
|
|
/// Event for when the datagridview received focus
|
|
/// </summary>
|
|
public event Action<PDSection> contentReceivedFocus;
|
|
|
|
/// <summary>
|
|
/// Event for when the datagridview receives focus
|
|
/// </summary>
|
|
public event Action<PDSection> contentChangedSelection;
|
|
|
|
public event Action<PDSection> ExpandedChanged;
|
|
|
|
#endregion
|
|
|
|
public PDSection()
|
|
{
|
|
InitializeComponent();
|
|
SetDefaultValues();
|
|
Contract();
|
|
MinimumSize = new Size(0, Height);
|
|
dataGridViewEx1.LostFocus += dataGridViewEx1_LostFocus;
|
|
dataGridViewEx1.GotFocus += dataGridViewEx1_GotFocus;
|
|
|
|
if (!Application.RenderWithVisualStyles)
|
|
{
|
|
panel1.BackColor = SystemColors.Control;
|
|
this.BackColor = SystemColors.ControlDark;
|
|
}
|
|
}
|
|
|
|
#region Accessors
|
|
|
|
[Browsable(false)]
|
|
public bool DisableFocusEvent { private get; set; }
|
|
|
|
[DefaultValue("Title")]
|
|
[Browsable(true)]
|
|
[Localizable(true)]
|
|
public string SectionTitle
|
|
{
|
|
get { return label1.Text; }
|
|
set { label1.Text = value; }
|
|
}
|
|
|
|
[Browsable(false)]
|
|
public bool IsEmpty()
|
|
{
|
|
return dataGridViewEx1.Rows.Count == 0;
|
|
}
|
|
|
|
[DefaultValue(true)]
|
|
[Browsable(false)]
|
|
public bool IsExpanded { get; private set; }
|
|
|
|
[Browsable(false)]
|
|
public bool HasNoSelection()
|
|
{
|
|
return dataGridViewEx1.SelectedRows.Count <= 0;
|
|
}
|
|
|
|
[Browsable(false)]
|
|
public Rectangle SelectedRowBounds
|
|
{
|
|
get
|
|
{
|
|
if (HasNoSelection())
|
|
return new Rectangle(0, 0, 0, 0);
|
|
|
|
int x = dataGridViewEx1.Location.X;
|
|
int y = dataGridViewEx1.RowDepth(dataGridViewEx1.SelectedRows[0].Index) + dataGridViewEx1.Location.Y;
|
|
int w = dataGridViewEx1.Width;
|
|
int h = dataGridViewEx1.SelectedRows[0].Height;
|
|
return new Rectangle(x, y, w, h);
|
|
}
|
|
}
|
|
|
|
[Browsable(false)]
|
|
public bool ShowCellToolTips
|
|
{
|
|
get { return dataGridViewEx1.ShowCellToolTips; }
|
|
set { dataGridViewEx1.ShowCellToolTips = value; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
protected override void OnGotFocus(EventArgs e)
|
|
{
|
|
base.OnGotFocus(e);
|
|
|
|
// For keyboard access
|
|
if (DisableFocusEvent)
|
|
return;
|
|
|
|
if (!IsExpanded)
|
|
Expand();
|
|
}
|
|
|
|
#region Control Event Handlers
|
|
|
|
private void dataGridViewEx1_CellContentClick(object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
if (e.ColumnIndex >= 0 && e.RowIndex >= 0)
|
|
ExecuteCellCommandOrAction(dataGridViewEx1.Rows[e.RowIndex].Cells[e.ColumnIndex]);
|
|
}
|
|
|
|
private void dataGridViewEx1_KeyPress(object sender, KeyPressEventArgs e)
|
|
{
|
|
if (e.KeyChar == (char)Keys.Enter)
|
|
ExecuteCellCommandOrAction(dataGridViewEx1.CurrentCell);
|
|
}
|
|
|
|
private void dataGridViewEx1_LostFocus(object sender, EventArgs e)
|
|
{
|
|
dataGridViewEx1.HideSelection = true;
|
|
}
|
|
|
|
private void dataGridViewEx1_GotFocus(object sender, EventArgs e)
|
|
{
|
|
dataGridViewEx1.HideSelection = false;
|
|
if (contentReceivedFocus != null)
|
|
contentReceivedFocus(this);
|
|
}
|
|
|
|
private void dataGridViewEx1_SelectionChanged(object sender, EventArgs e)
|
|
{
|
|
if (inLayout)
|
|
return;
|
|
|
|
if (contentChangedSelection != null)
|
|
contentChangedSelection(this);
|
|
}
|
|
|
|
private void dataGridViewEx1_MouseClick(object sender, MouseEventArgs e)
|
|
{
|
|
if (e.Button != MouseButtons.Right)
|
|
return;
|
|
|
|
DataGridView.HitTestInfo i = dataGridViewEx1.HitTest(e.X, e.Y);
|
|
|
|
if (i.RowIndex < 0 || i.RowIndex > dataGridViewEx1.RowCount)
|
|
return;
|
|
if (i.ColumnIndex < 0 || i.ColumnIndex > dataGridViewEx1.ColumnCount)
|
|
return;
|
|
|
|
dataGridViewEx1.Focus();
|
|
var row = dataGridViewEx1.Rows[i.RowIndex];
|
|
row.Selected = true;
|
|
|
|
contextMenuStrip1.Items.Clear();
|
|
contextMenuStrip1.Items.Add(copyToolStripMenuItem);
|
|
|
|
var menuItems = row.Tag as IEnumerable<ToolStripMenuItem>;
|
|
if (menuItems != null)
|
|
{
|
|
contextMenuStrip1.Items.Add(new ToolStripSeparator());
|
|
contextMenuStrip1.Items.AddRange(menuItems.ToArray());
|
|
}
|
|
contextMenuStrip1.Show(dataGridViewEx1, dataGridViewEx1.PointToClient(MousePosition));
|
|
}
|
|
|
|
|
|
private void CopyMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
Clipboard.SetDataObject(dataGridViewEx1.SelectedRows[0].Cells[1].Value);
|
|
}
|
|
|
|
|
|
private void panel1_MouseDoubleClick(object sender, MouseEventArgs e)
|
|
{
|
|
if (IsExpanded)
|
|
Contract();
|
|
else
|
|
{
|
|
Expand();
|
|
dataGridViewEx1.Focus();
|
|
}
|
|
}
|
|
|
|
private void chevron_Click(object sender, EventArgs e)
|
|
{
|
|
if (IsExpanded)
|
|
Contract();
|
|
else
|
|
{
|
|
Expand();
|
|
dataGridViewEx1.Focus();
|
|
}
|
|
}
|
|
|
|
private void chevron_MouseEnter(object sender, EventArgs e)
|
|
{
|
|
chevronHot = true;
|
|
RefreshChevron();
|
|
}
|
|
|
|
private void chevron_MouseLeave(object sender, EventArgs e)
|
|
{
|
|
chevronHot = false;
|
|
RefreshChevron();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Private Methods
|
|
|
|
private void SetDefaultValues()
|
|
{
|
|
SectionTitle = Messages.PDSECTION_TITLE;
|
|
IsExpanded = true;
|
|
}
|
|
|
|
private void ExecuteCellCommandOrAction(DataGridViewCell cell)
|
|
{
|
|
if (cell == null)
|
|
return;
|
|
|
|
var command = cell.Tag as Command;
|
|
if (command != null)
|
|
command.Execute();
|
|
|
|
var action = cell.Tag as Action;
|
|
if (action != null)
|
|
action.Invoke();
|
|
}
|
|
|
|
private void RefreshHeight()
|
|
{
|
|
if (IsExpanded)
|
|
{
|
|
int newHeight = dataGridViewEx1.Rows.GetRowsHeight(DataGridViewElementStates.Visible);
|
|
|
|
int valueColWidth = dataGridViewEx1.Width - dataGridViewEx1.Columns[KeyColumn.Index].Width;
|
|
int preferredValueColWidth =
|
|
dataGridViewEx1.Columns[ValueColumn.Index].GetPreferredWidth(
|
|
DataGridViewAutoSizeColumnMode.AllCells, true);
|
|
|
|
int horizontalScrollBarHeight = preferredValueColWidth - 1 >= valueColWidth
|
|
? dataGridViewEx1.HorizontalScrollBarHeight
|
|
: 0;
|
|
|
|
// 3px added so we have a border (one at top of control, one between title and grid, one at bottom)
|
|
Height = panel1.Height + newHeight + horizontalScrollBarHeight + 3;
|
|
// this correction is needed because the anchor property of the grid drags it to fill the space we want to be a border
|
|
// when we go from contracted (2 borders) to expanded (3 borders)
|
|
}
|
|
else
|
|
{
|
|
Height = panel1.Height + 2;
|
|
}
|
|
}
|
|
|
|
private void RefreshChevron()
|
|
{
|
|
if (IsExpanded)
|
|
{
|
|
chevron.Image = chevronHot ? Resources.PDChevronUpOver : Resources.PDChevronUp;
|
|
}
|
|
else
|
|
{
|
|
chevron.Image = chevronHot ? Resources.PDChevronDownOver : Resources.PDChevronDown;
|
|
}
|
|
}
|
|
|
|
private void AddRow(DataGridViewRow r)
|
|
{
|
|
dataGridViewEx1.Rows.Add(r);
|
|
if (inLayout)
|
|
return;
|
|
|
|
RefreshHeight();
|
|
}
|
|
|
|
private void ToggleExpandedState(bool expand)
|
|
{
|
|
if (IsExpanded == expand)
|
|
return;
|
|
|
|
IsExpanded = expand;
|
|
dataGridViewEx1.Visible = expand;
|
|
RefreshHeight();
|
|
RefreshChevron();
|
|
|
|
if (ExpandedChanged != null)
|
|
ExpandedChanged(this);
|
|
}
|
|
|
|
#endregion
|
|
|
|
public void Contract()
|
|
{
|
|
ToggleExpandedState(false);
|
|
}
|
|
|
|
public void Expand()
|
|
{
|
|
ValueColumn.MinimumWidth = 5;
|
|
HelpersGUI.ResizeLastGridViewColumn(ValueColumn);
|
|
ToggleExpandedState(true);
|
|
}
|
|
|
|
private DataGridViewExRow CreateRow(string Key, string Value)
|
|
{
|
|
if (!String.IsNullOrEmpty(Key))
|
|
Key += Messages.GENERAL_PAGE_KVP_SEPARATOR;
|
|
DataGridViewExRow r = new DataGridViewExRow();
|
|
r.CreateCells(dataGridViewEx1);
|
|
r.Cells[0].Value = Key;
|
|
r.Cells[1].Value = Value;
|
|
return r;
|
|
}
|
|
public void AddEntry(string Key, string Value)
|
|
{
|
|
var r = CreateRow(Key, Value);
|
|
AddRow(r);
|
|
}
|
|
|
|
public void AddEntry(string Key, string Value, ToolStripMenuItem contextMenuItem)
|
|
{
|
|
AddEntry(Key, Value, new[] { contextMenuItem });
|
|
}
|
|
|
|
public void AddEntry(string Key, string Value, IEnumerable<ToolStripMenuItem> contextMenuItems)
|
|
{
|
|
var r = CreateRow(Key, Value);
|
|
r.Tag = contextMenuItems;
|
|
AddRow(r);
|
|
}
|
|
|
|
public void AddEntry(string Key, string Value, IEnumerable<ToolStripMenuItem> contextMenuItems, string toolTipText)
|
|
{
|
|
AddEntry(Key, Value, contextMenuItems);
|
|
if (toolTipText != Key)
|
|
dataGridViewEx1.Rows[dataGridViewEx1.RowCount - 1].Cells[0].ToolTipText = toolTipText;
|
|
}
|
|
|
|
public void AddEntry(string Key, string Value, Color fontColor)
|
|
{
|
|
var r = CreateRow(Key, Value);
|
|
r.Cells[1].Style.ForeColor = fontColor;
|
|
AddRow(r);
|
|
dataGridViewEx1.DefaultCellStyle = new DataGridViewCellStyle();
|
|
}
|
|
|
|
public void AddEntry(string Key, string Value, IEnumerable<ToolStripMenuItem> contextMenuItems, Color fontColor)
|
|
{
|
|
var r = CreateRow(Key, Value);
|
|
r.Cells[1].Style.ForeColor = fontColor;
|
|
r.Tag = contextMenuItems;
|
|
AddRow(r);
|
|
dataGridViewEx1.DefaultCellStyle = new DataGridViewCellStyle();
|
|
}
|
|
|
|
public void AddEntry(string Key, FolderListItem Value, IEnumerable<ToolStripMenuItem> contextMenuItems)
|
|
{
|
|
// Special case for folders: CA-33311
|
|
|
|
if (!String.IsNullOrEmpty(Key))
|
|
Key += Messages.GENERAL_PAGE_KVP_SEPARATOR;
|
|
DataGridViewExRow r = new DataGridViewExRow();
|
|
r.Cells.Add(new DataGridViewTextBoxCell());
|
|
r.Cells[0].Value = Key;
|
|
r.Cells.Add(new FolderCell(Value));
|
|
r.Tag = contextMenuItems;
|
|
AddRow(r);
|
|
}
|
|
|
|
internal void AddEntryLink(string Key, string Value, IEnumerable<ToolStripMenuItem> contextMenuItems, Command command)
|
|
{
|
|
if (!String.IsNullOrEmpty(Key))
|
|
Key += Messages.GENERAL_PAGE_KVP_SEPARATOR;
|
|
DataGridViewExRow r = new DataGridViewExRow();
|
|
r.CreateCells(dataGridViewEx1);
|
|
r.Cells[0].Value = Key;
|
|
r.Cells[1] = new DataGridViewLinkCell();
|
|
r.Cells[1].Value = Value;
|
|
r.Cells[1].Tag = command;
|
|
r.Tag = contextMenuItems;
|
|
AddRow(r);
|
|
}
|
|
|
|
internal void AddEntryLink(string Key, string Value, IEnumerable<ToolStripMenuItem> contextMenuItems, Action action)
|
|
{
|
|
if (!String.IsNullOrEmpty(Key))
|
|
Key += Messages.GENERAL_PAGE_KVP_SEPARATOR;
|
|
DataGridViewExRow r = new DataGridViewExRow();
|
|
r.CreateCells(dataGridViewEx1);
|
|
r.Cells[0].Value = Key;
|
|
r.Cells[1] = new DataGridViewLinkCell();
|
|
r.Cells[1].Value = Value;
|
|
r.Cells[1].Tag = action;
|
|
r.Tag = contextMenuItems;
|
|
AddRow(r);
|
|
}
|
|
|
|
public void AddEntry(string Key, string Value, ToolStripMenuItem contextMenuItem, bool visible)
|
|
{
|
|
AddEntry(Key, Value, new[] { contextMenuItem }, visible);
|
|
}
|
|
|
|
public void AddEntry(string Key, string Value, IEnumerable<ToolStripMenuItem> contextMenuItems, bool visible)
|
|
{
|
|
var r = CreateRow(Key, Value);
|
|
r.Tag = contextMenuItems;
|
|
r.Visible = visible;
|
|
AddRow(r);
|
|
}
|
|
|
|
public void UpdateEntryValueWithKey(string Key, string newValue, bool visible)
|
|
{
|
|
List<DataGridViewExRow> matchingRows = (from DataGridViewExRow row in dataGridViewEx1.Rows
|
|
where row.Cells[0].Value.ToString().Contains(Key)
|
|
select row).ToList();
|
|
|
|
if (matchingRows.Count != 1 || matchingRows[0].Cells.Count < 2)
|
|
return;
|
|
|
|
matchingRows[0].Cells[1].Value = newValue;
|
|
|
|
if (matchingRows[0].Visible != visible)
|
|
{
|
|
matchingRows[0].Visible = visible;
|
|
RefreshHeight();
|
|
}
|
|
}
|
|
|
|
internal void fixFirstColumnWidth(int width)
|
|
{
|
|
dataGridViewEx1.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
|
|
dataGridViewEx1.Columns[0].Width = width;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clears the rows in the data grid view. If performing a repaint, you can attempt to restore the previous selection with a call to RestoreSelection()
|
|
/// </summary>
|
|
public void ClearData()
|
|
{
|
|
if (dataGridViewEx1.SelectedRows.Count > 0)
|
|
previousSelectionKey = dataGridViewEx1.SelectedRows[0].Cells[0].Value.ToString();
|
|
|
|
dataGridViewEx1.Rows.Clear();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Restores selection to the row stored from the last ClearData() call
|
|
/// </summary>
|
|
public void RestoreSelection()
|
|
{
|
|
if (string.IsNullOrEmpty(previousSelectionKey))
|
|
return;
|
|
|
|
foreach (DataGridViewRow r in dataGridViewEx1.Rows)
|
|
{
|
|
if (r.Cells[0].Value.ToString() == previousSelectionKey)
|
|
{
|
|
r.Cells[0].Selected = true;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void PauseLayout()
|
|
{
|
|
inLayout = true;
|
|
}
|
|
|
|
public void StartLayout()
|
|
{
|
|
inLayout = false;
|
|
RefreshHeight();
|
|
}
|
|
}
|
|
}
|