mirror of
https://github.com/xcp-ng/xenadmin.git
synced 2024-11-24 22:06:59 +01:00
d7b519a53c
Signed-off-by: Konstantina Chremmou <Konstantina.Chremmou@cloud.com>
241 lines
8.6 KiB
C#
241 lines
8.6 KiB
C#
/* Copyright (c) Cloud Software Group, Inc.
|
|
*
|
|
* 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.Windows.Forms;
|
|
using System.Drawing;
|
|
using System.Runtime.InteropServices;
|
|
using XenCenterLib;
|
|
|
|
namespace XenAdmin.Controls
|
|
{
|
|
public class FlickerFreeListBox : ListBox
|
|
{
|
|
/// <summary>
|
|
/// These flicker free list boxes must be owner drawn.
|
|
/// </summary>
|
|
public FlickerFreeListBox()
|
|
{
|
|
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
|
this.SetStyle(ControlStyles.ResizeRedraw, true);
|
|
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
|
|
this.SetStyle(ControlStyles.UserPaint, true);
|
|
this.DoubleBuffered = true;
|
|
this.IntegralHeight = false;
|
|
this.DrawMode = DrawMode.OwnerDrawFixed;
|
|
}
|
|
|
|
/// <summary>
|
|
/// The last seen value of the horizontal scrollbar position (offset in pixels from the lhs).
|
|
/// </summary>
|
|
private int _scrollLeft = 0;
|
|
/// <summary>
|
|
/// The handle of the horizontal scrollbar of this ListBox
|
|
/// </summary>
|
|
private IntPtr _hScrollbarHandle = IntPtr.Zero;
|
|
|
|
public Func<Message, bool> CancelWndProc = msg => false;
|
|
|
|
protected override void WndProc(ref Message msg)
|
|
{
|
|
if (msg.Msg == Win32.WM_HSCROLL)
|
|
{
|
|
// Store the handle for use in Invalidate()
|
|
_hScrollbarHandle = msg.HWnd;
|
|
// Collect info about the position of the horizontal scrollbar
|
|
Win32.ScrollInfo si = new Win32.ScrollInfo();
|
|
si.fMask = (int)Win32.ScrollInfoMask.SIF_ALL;
|
|
si.cbSize = (uint)Marshal.SizeOf(si);
|
|
Win32.GetScrollInfo(msg.HWnd, 0, ref si);
|
|
|
|
if ((msg.WParam.ToInt32() & 0xFF) == Win32.SB_THUMBTRACK)
|
|
{
|
|
// If the user is in the middle of dragging the scrollbar, we're interested in
|
|
// the 'track' position
|
|
_scrollLeft = si.nTrackPos;
|
|
}
|
|
else
|
|
{
|
|
// Otherwise just the regular scrollbar position
|
|
_scrollLeft = si.nPos;
|
|
}
|
|
// Force repaint
|
|
base.Invalidate();
|
|
}
|
|
|
|
if (!CancelWndProc(msg))
|
|
base.WndProc(ref msg);
|
|
}
|
|
|
|
public new void Invalidate()
|
|
{
|
|
if (_hScrollbarHandle != IntPtr.Zero)
|
|
{
|
|
// If we've been invalidated, update our drawing code to the new horizontal scrollbar
|
|
// position (which is sometimes spontaneously reset to zero and can't be programmatically
|
|
// set to its former value) - see CA-11405.
|
|
Win32.ScrollInfo si = new Win32.ScrollInfo();
|
|
si.fMask = (int)Win32.ScrollInfoMask.SIF_ALL;
|
|
si.cbSize = (uint)Marshal.SizeOf(si);
|
|
Win32.GetScrollInfo(_hScrollbarHandle, 0, ref si);
|
|
_scrollLeft = si.nTrackPos; // often zero
|
|
}
|
|
base.Invalidate();
|
|
}
|
|
|
|
protected override void OnMouseWheel(MouseEventArgs e)
|
|
{
|
|
Invalidate();
|
|
base.OnMouseWheel(e);
|
|
}
|
|
|
|
private ContextMenuStrip _contextMenuStrip;
|
|
|
|
public override ContextMenuStrip ContextMenuStrip
|
|
{
|
|
get => _contextMenuStrip;
|
|
set => _contextMenuStrip = value;
|
|
}
|
|
|
|
protected override void OnKeyUp(KeyEventArgs e)
|
|
{
|
|
base.OnKeyUp(e);
|
|
|
|
if (e.KeyCode == Keys.Apps && _contextMenuStrip != null)
|
|
{
|
|
if (SelectedIndex < 0 || SelectedIndex >= Items.Count)
|
|
return;
|
|
|
|
Rectangle r = GetItemRectangle(SelectedIndex);
|
|
Point p = new Point(r.X + 1, r.Bottom + 1);
|
|
ContextMenuStrip.Show(this, p);
|
|
}
|
|
}
|
|
|
|
protected override void OnMouseUp(MouseEventArgs e)
|
|
{
|
|
base.OnMouseUp(e);
|
|
|
|
if (e.Button == MouseButtons.Right && _contextMenuStrip != null)
|
|
{
|
|
int i = IndexFromPoint(e.Location);
|
|
if (i == ListBox.NoMatches)
|
|
return;
|
|
|
|
SelectedIndex = i;
|
|
|
|
ContextMenuStrip.Show(this, e.Location);
|
|
}
|
|
}
|
|
|
|
protected override void OnPaint(PaintEventArgs e)
|
|
{
|
|
Graphics g = e.Graphics;
|
|
|
|
if(Enabled)
|
|
{
|
|
using (SolidBrush backBrush = new SolidBrush(BackColor))
|
|
{
|
|
g.FillRectangle(backBrush, g.ClipBounds);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
g.FillRectangle(SystemBrushes.Control, g.ClipBounds);
|
|
}
|
|
|
|
int top = 0;
|
|
|
|
for (int i = 0; i < TopIndex; i++)
|
|
{
|
|
if (i < Items.Count)
|
|
top += base.GetItemHeight(i);
|
|
}
|
|
|
|
Rectangle t = new Rectangle(-_scrollLeft, -top, ClientSize.Width, ItemHeight);
|
|
|
|
for (int i = 0; i < this.Items.Count; i++)
|
|
{
|
|
int itemHeight = GetItemHeight(i);
|
|
Rectangle bounds = new Rectangle(t.Left, t.Top, t.Width, itemHeight);
|
|
|
|
// if selected
|
|
if (SelectedIndices.Contains(i))
|
|
{
|
|
// Enabled & Focused = blue
|
|
// Enabled & !Focused = control
|
|
// !Enabled = dark grey
|
|
|
|
if(!Enabled)
|
|
OnDrawItem(new DrawItemEventArgs(g, Font, bounds, i,
|
|
DrawItemState.Disabled, SystemColors.HighlightText,
|
|
SystemColors.ControlDark));
|
|
else if (!Focused)
|
|
OnDrawItem(new DrawItemEventArgs(g, Font, bounds, i,
|
|
DrawItemState.Inactive, SystemColors.ControlText,
|
|
SystemColors.Control));
|
|
else
|
|
OnDrawItem(new DrawItemEventArgs(g, Font, bounds, i,
|
|
DrawItemState.Selected, SystemColors.HighlightText,
|
|
SystemColors.Highlight));
|
|
}
|
|
else
|
|
{
|
|
// If not selected, then we just care if the control is enabled
|
|
|
|
OnDrawItem(new DrawItemEventArgs(g, Font, bounds, i,
|
|
DrawItemState.Default, SystemColors.ControlText,
|
|
Enabled ? BackColor : SystemColors.Control));
|
|
}
|
|
|
|
t.Offset(0, itemHeight);
|
|
}
|
|
}
|
|
|
|
protected override void OnSelectedIndexChanged(EventArgs e)
|
|
{
|
|
base.OnSelectedIndexChanged(e);
|
|
Refresh();
|
|
}
|
|
|
|
protected override void OnGotFocus(EventArgs e)
|
|
{
|
|
base.OnGotFocus(e);
|
|
this.Refresh();
|
|
}
|
|
|
|
protected override void OnLostFocus(EventArgs e)
|
|
{
|
|
base.OnLostFocus(e);
|
|
this.Refresh();
|
|
}
|
|
}
|
|
}
|