/* 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
///
/// Used to persist selection over a repaint, we set this when we clear the datagridview
///
private string previousSelectionKey;
private bool inLayout;
///
/// Whether the mouse is over the chevron
///
private bool chevronHot;
#endregion
#region Delegates and Events
///
/// Event for when the datagridview received focus
///
public event Action contentReceivedFocus;
///
/// Event for when the datagridview receives focus
///
public event Action contentChangedSelection;
public event Action 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 List;
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);
}
public void AddEntry(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;
AddRow(r);
}
public void AddEntry(string Key, string Value, List contextMenuItems)
{
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;
r.Tag = contextMenuItems;
AddRow(r);
}
public void AddEntry(string Key, string Value, List 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)
{
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;
r.Cells[1].Style.ForeColor = fontColor;
AddRow(r);
dataGridViewEx1.DefaultCellStyle = new DataGridViewCellStyle();
}
public void AddEntry(string Key, string Value, List contextMenuItems, Color fontColor)
{
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;
r.Cells[1].Style.ForeColor = fontColor;
r.Tag = contextMenuItems;
AddRow(r);
dataGridViewEx1.DefaultCellStyle = new DataGridViewCellStyle();
}
public void AddEntry(string Key, FolderListItem Value, List 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, List 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, List 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 UpdateEntryValueWithKey(string Key, string newValue)
{
List 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;
}
internal void fixFirstColumnWidth(int width)
{
dataGridViewEx1.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
dataGridViewEx1.Columns[0].Width = width;
}
///
/// 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()
///
public void ClearData()
{
if (dataGridViewEx1.SelectedRows.Count > 0)
previousSelectionKey = dataGridViewEx1.SelectedRows[0].Cells[0].Value.ToString();
dataGridViewEx1.Rows.Clear();
}
///
/// Restores selection to the row stored from the last ClearData() call
///
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();
}
}
}