xenadmin/XenAdmin/Controls/CustomGridView/GridHeaderItem.cs

254 lines
9.3 KiB
C#
Raw Normal View History

/* 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.Text;
using System.Drawing;
using System.Windows.Forms;
namespace XenAdmin.Controls.CustomGridView
{
public class GridHeaderItem : GridStringItem
{
public const int ResizeGutter = 3; // the space between the columns within which we resize the columns rather than dragging them
private static readonly Image AscendingTriangle = Properties.Resources.ascending_triangle;
private static readonly Image DescendingTriangle = Properties.Resources.descending_triangle;
private static readonly Font SortFont = new Font(Program.DefaultFont.FontFamily, 7.0f);
private static readonly Pen LinePen = Pens.LightSteelBlue;
public readonly int MinimumWidth;
private readonly SortOrder defaultSortOrder;
public SortOrder Sort = SortOrder.None;
public int SortPriority = -1;
public bool IsDefaultSortColumn;
public bool GreyOut;
public bool Immovable;
public bool UnSizable;
private int width;
private String columnName;
public GridHeaderItem(HorizontalAlignment hAlign, VerticalAlignment vAlign, Brush foreBrush,
Font font, String text, SortOrder defaultSortOrder, int width, int minwidth, Brush hotbrush)
: base(text, hAlign, vAlign, false, false, foreBrush, font, hotbrush, font)
{
this.defaultSortOrder = defaultSortOrder;
this.width = width;
MinimumWidth = minwidth;
}
public String ColumnName
{
get
{
return columnName;
}
set
{
columnName = value;
}
}
public int Width
{
get
{
return width;
}
set
{
width = value;
}
}
public override void OnPaint(ItemPaintArgs itemPaintArgs)
{
if (!string.IsNullOrEmpty(sortdata.ToString()))
{
base.OnPaint(itemPaintArgs);
DrawGlyphs(itemPaintArgs);
}
}
public void DrawGlyphs(ItemPaintArgs itemPaintArgs)
{
Graphics g = itemPaintArgs.Graphics;
if (SortPriority > -1 && itemPaintArgs.Rectangle.Width - (AscendingTriangle.Width + 16) > 0)
{
// Draw the number showing the precedence of sorting in this column versus sorting in other columns
g.DrawString((SortPriority + 1).ToString(), SortFont, foreBrush, itemPaintArgs.Rectangle.Right - (AscendingTriangle.Width + 15), itemPaintArgs.Rectangle.Top + ((itemPaintArgs.Rectangle.Height / 2) - 7));
}
if (Sort != SortOrder.None && itemPaintArgs.Rectangle.Width - (AscendingTriangle.Width + 5) > 0)
{
// Draw the triangle showing ascending/descending sort order
DrawTriangle(g, Sort == SortOrder.Ascending ? AscendingTriangle : DescendingTriangle, itemPaintArgs);
}
DrawSideLine(g, itemPaintArgs, itemPaintArgs.Rectangle.Left - 1);
DrawSideLine(g, itemPaintArgs, itemPaintArgs.Rectangle.Right - 1);
}
private void DrawSideLine(Graphics g, ItemPaintArgs itemPaintArgs, int x)
{
g.DrawLine(LinePen, x, itemPaintArgs.Rectangle.Top, x, itemPaintArgs.Rectangle.Bottom - 1);
}
private void DrawTriangle(Graphics g, Image triangle, ItemPaintArgs itemPaintArgs)
{
g.DrawImageUnscaled(triangle, itemPaintArgs.Rectangle.Right - triangle.Width - 5, itemPaintArgs.Rectangle.Top + ((itemPaintArgs.Rectangle.Height - triangle.Height) / 2), triangle.Width, triangle.Height);
}
public override void OnEnter(Point p)
{
if (!Immovable && !string.IsNullOrEmpty(sortdata.ToString()))
{
Hot = true;
Row.GridView.Refresh();
}
}
public override void OnMouseMove(Point p)
{
if ((!UnSizable && (p.X >= CurrentRectangle.Width - ResizeGutter && p.X <= CurrentRectangle.Width)) || (!PreviousUnsizable() && (p.X < ResizeGutter && p.X >= 0)))
Row.Cursor = Cursors.SizeWE;
else
Row.Cursor = Cursors.Hand;
}
private bool PreviousUnsizable()
{
GridHeaderRow hr = (GridHeaderRow)Row;
int tindex = hr.Columns.IndexOf(ColumnName);
if (tindex <= 0)
return true;
string tother = hr.Columns[tindex - 1];
GridItemBase prevItem;
if (!hr.Items.TryGetValue(tother, out prevItem))
return true;
GridHeaderItem prevHeader = prevItem as GridHeaderItem;
if (prevHeader == null)
return true;
return prevHeader.UnSizable;
}
public override void OnLeave()
{
if (!string.IsNullOrEmpty(sortdata.ToString()))
{
Row.Cursor = Cursors.Default;
Hot = false;
Row.GridView.Refresh();
}
}
public override void OnClick(Point p)
{
if (!string.IsNullOrEmpty(sortdata.ToString()))
{
NextSort();
Row.GridView.Sort();
Row.GridView.Refresh();
}
}
/// <summary>
/// Changes the sort order of this column to the next value
/// </summary>
private void NextSort()
{
switch (Sort)
{
case SortOrder.None:
SetSort(defaultSortOrder);
break;
case SortOrder.Ascending:
SetSort(defaultSortOrder == SortOrder.Ascending ? SortOrder.Descending : SortOrder.None);
break;
case SortOrder.Descending:
SetSort(defaultSortOrder == SortOrder.Ascending ? SortOrder.None : SortOrder.Ascending);
break;
}
}
private void SetSort(SortOrder sortOrder)
{
GridHeaderRow ghr = (GridHeaderRow)Row;
int oldPriority = SortPriority;
SortOrder oldSort = Sort;
Sort = sortOrder;
if (Sort == SortOrder.None) // removing sorting from this column
{
SortPriority = -1;
foreach (GridHeaderItem other in ghr.Items.Values)
{
if (other != this && other.SortPriority > oldPriority)
other.SortPriority--;
}
}
else if (oldSort == SortOrder.None) // starting to apply sorting to this column
{
SortPriority = 0;
foreach (GridHeaderItem other in ghr.Items.Values)
{
if (other != this && other.SortPriority > -1)
other.SortPriority++;
}
}
ghr.UpdateCompareOrder();
}
// When using this function, it is the caller's responsibility to
// make sure all the columns have a consistent set of priorities
internal void SetSort(int priority, SortOrder sortOrder)
{
SortPriority = priority;
Sort = sortOrder;
}
// When using this function, it is the caller's responsibility to
// make sure all the columns have a consistent set of priorities
internal void UnsetSort()
{
SortPriority = -1;
Sort = SortOrder.None;
}
}
}