/* 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 IEnumerable; 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 contextMenuItems) { var r = CreateRow(Key, Value); r.Tag = contextMenuItems; AddRow(r); } public void AddEntry(string Key, string Value, IEnumerable 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 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 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 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 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 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 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; } /// /// 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(); } } }