mirror of
https://github.com/Kopano-dev/kopano-ol-extension.git
synced 2023-10-10 13:37:40 +02:00
[KOE-125] Added focused border to tree control
This commit is contained in:
parent
b17ebb2ec4
commit
008c27026d
@ -1,6 +1,6 @@
|
|||||||
/// Project : Kopano OL Extension
|
/// Project : Kopano OL Extension
|
||||||
///
|
///
|
||||||
/// Copyright 2016 Kopano b.v.
|
/// Copyright 2017 Kopano b.v.
|
||||||
///
|
///
|
||||||
/// This program is free software: you can redistribute it and/or modify
|
/// This program is free software: you can redistribute it and/or modify
|
||||||
/// it under the terms of the GNU Affero General Public License, version 3,
|
/// it under the terms of the GNU Affero General Public License, version 3,
|
||||||
@ -138,6 +138,13 @@ namespace Acacia.Controls
|
|||||||
set { _nodeIdent = value; Rerender(); }
|
set { _nodeIdent = value; Rerender(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int BorderThickness
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return BorderStyle == BorderStyle.FixedSingle ? 1 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Images
|
#region Images
|
||||||
@ -416,6 +423,8 @@ namespace Acacia.Controls
|
|||||||
{
|
{
|
||||||
if (newHighlight != _highlightNode || _highlightPart != newPart)
|
if (newHighlight != _highlightNode || _highlightPart != newPart)
|
||||||
{
|
{
|
||||||
|
bool oldFocused = Focused;
|
||||||
|
|
||||||
KTreeNode old = _highlightNode;
|
KTreeNode old = _highlightNode;
|
||||||
|
|
||||||
if (newHighlight != null && !newHighlight.IsSelectable)
|
if (newHighlight != null && !newHighlight.IsSelectable)
|
||||||
@ -429,6 +438,10 @@ namespace Acacia.Controls
|
|||||||
_highlightPart = newPart;
|
_highlightPart = newPart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the border if required
|
||||||
|
if (oldFocused != Focused)
|
||||||
|
RedrawBorder();
|
||||||
|
|
||||||
// Render old node without highlight
|
// Render old node without highlight
|
||||||
if (old != null)
|
if (old != null)
|
||||||
Rerender(old);
|
Rerender(old);
|
||||||
@ -612,21 +625,6 @@ namespace Acacia.Controls
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Columns
|
|
||||||
// TODO
|
|
||||||
/*
|
|
||||||
private readonly TreeViewColumnCollection _columns;
|
|
||||||
|
|
||||||
[Category("Columns")]
|
|
||||||
[Browsable(true)]
|
|
||||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
|
||||||
public TreeViewColumnCollection Columns
|
|
||||||
{
|
|
||||||
get { return _columns; }
|
|
||||||
}*/
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Rendering
|
#region Rendering
|
||||||
|
|
||||||
private KTreeRenderer _renderer;
|
private KTreeRenderer _renderer;
|
||||||
@ -864,6 +862,10 @@ namespace Acacia.Controls
|
|||||||
e.Graphics.FillRectangle(SystemBrushes.Control,
|
e.Graphics.FillRectangle(SystemBrushes.Control,
|
||||||
ClientSize.Width - VerticalScrollBarWidth, ClientSize.Height - HorizontalScrollBarHeight,
|
ClientSize.Width - VerticalScrollBarWidth, ClientSize.Height - HorizontalScrollBarHeight,
|
||||||
VerticalScrollBarWidth, HorizontalScrollBarHeight);
|
VerticalScrollBarWidth, HorizontalScrollBarHeight);
|
||||||
|
|
||||||
|
// The scrollbars sometimes get lost, force a repaint
|
||||||
|
_verticalScrollBar.Refresh();
|
||||||
|
_horizontalScrollBar.Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -1081,20 +1083,69 @@ namespace Acacia.Controls
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Focus
|
#region Border
|
||||||
|
|
||||||
|
public override bool Focused
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return base.Focused || _highlightNode != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnGotFocus(EventArgs e)
|
protected override void OnGotFocus(EventArgs e)
|
||||||
{
|
{
|
||||||
base.OnGotFocus(e);
|
base.OnGotFocus(e);
|
||||||
Invalidate();
|
RedrawBorder();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnLostFocus(EventArgs e)
|
protected override void OnLostFocus(EventArgs e)
|
||||||
{
|
{
|
||||||
base.OnLostFocus(e);
|
base.OnLostFocus(e);
|
||||||
Invalidate();
|
RedrawBorder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnEnabledChanged(EventArgs e)
|
||||||
|
{
|
||||||
|
base.OnEnabledChanged(e);
|
||||||
|
RedrawBorder();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void WndProc(ref Message m)
|
||||||
|
{
|
||||||
|
if (m.Msg == (int)WM.NCPAINT)
|
||||||
|
{
|
||||||
|
IntPtr hDC = User32.GetWindowDC(m.HWnd);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (Graphics g = Graphics.FromHdc(hDC))
|
||||||
|
{
|
||||||
|
_renderer.RenderControlBorder(g, new Rectangle(0, 0, Width, Height));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
User32.ReleaseDC(m.HWnd, hDC);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
base.WndProc(ref m);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnResize(EventArgs e)
|
||||||
|
{
|
||||||
|
base.OnResize(e);
|
||||||
|
RedrawBorder();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RedrawBorder()
|
||||||
|
{
|
||||||
|
// Force NCPaint update
|
||||||
|
User32.RedrawWindow(this.Handle, IntPtr.Zero, IntPtr.Zero,
|
||||||
|
User32.RedrawWindowFlags.Frame | User32.RedrawWindowFlags.Invalidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Winforms Autogenerated
|
#region Winforms Autogenerated
|
||||||
@ -1111,56 +1162,5 @@ namespace Acacia.Controls
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Disabled state
|
|
||||||
|
|
||||||
protected override void OnEnabledChanged(EventArgs e)
|
|
||||||
{
|
|
||||||
base.OnEnabledChanged(e);
|
|
||||||
RedrawBorder();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void WndProc(ref Message m)
|
|
||||||
{
|
|
||||||
if (m.Msg == (int)WM.NCPAINT)
|
|
||||||
{
|
|
||||||
WmNcPaint(ref m);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
base.WndProc(ref m);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WmNcPaint(ref Message m)
|
|
||||||
{
|
|
||||||
if (BorderStyle == BorderStyle.None)
|
|
||||||
return;
|
|
||||||
|
|
||||||
IntPtr hDC = User32.GetWindowDC(m.HWnd);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (Graphics g = Graphics.FromHdc(hDC))
|
|
||||||
{
|
|
||||||
_renderer.RenderControlBorder(g, new Rectangle(0, 0, Width, Height));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
User32.ReleaseDC(m.HWnd, hDC);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnResize(EventArgs e)
|
|
||||||
{
|
|
||||||
base.OnResize(e);
|
|
||||||
RedrawBorder();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RedrawBorder()
|
|
||||||
{
|
|
||||||
// Force NCPaint update
|
|
||||||
User32.RedrawWindow(this.Handle, IntPtr.Zero, IntPtr.Zero,
|
|
||||||
User32.RedrawWindowFlags.Frame | User32.RedrawWindowFlags.Invalidate /*| User32.RedrawWindowFlags.UpdateNow*/);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,6 +117,8 @@ namespace Acacia.Controls
|
|||||||
Rectangle containerRect = dims.NodeRect;
|
Rectangle containerRect = dims.NodeRect;
|
||||||
containerRect.X = _clientRect.X;
|
containerRect.X = _clientRect.X;
|
||||||
containerRect.Width = Math.Max(_totalRect.Width, _clientRect.Width);
|
containerRect.Width = Math.Max(_totalRect.Width, _clientRect.Width);
|
||||||
|
// Overlap the rectangle with the control border, to prevent duplicate lines
|
||||||
|
containerRect = containerRect.Expand(new Padding(_tree.BorderThickness));
|
||||||
|
|
||||||
// Selection background
|
// Selection background
|
||||||
RenderNodeOutline(graphics, node, _tree.FullRowSelect ? containerRect : dims.NodeRect, highlight);
|
RenderNodeOutline(graphics, node, _tree.FullRowSelect ? containerRect : dims.NodeRect, highlight);
|
||||||
|
@ -66,6 +66,11 @@ namespace Acacia.Controls
|
|||||||
private readonly VisualStyleRenderer _treeViewGlyphHotClosed = new VisualStyleRenderer(TREEVIEW, 4, 1);
|
private readonly VisualStyleRenderer _treeViewGlyphHotClosed = new VisualStyleRenderer(TREEVIEW, 4, 1);
|
||||||
private readonly VisualStyleRenderer _treeViewGlyphHotOpened = new VisualStyleRenderer(TREEVIEW, 4, 2);
|
private readonly VisualStyleRenderer _treeViewGlyphHotOpened = new VisualStyleRenderer(TREEVIEW, 4, 2);
|
||||||
|
|
||||||
|
// We use the combo box styles for the outline
|
||||||
|
private readonly VisualStyleRenderer _treeViewBorderNormal = new VisualStyleRenderer("COMBOBOX", 4, 1);
|
||||||
|
private readonly VisualStyleRenderer _treeViewBorderFocus = new VisualStyleRenderer("COMBOBOX", 4, 2);
|
||||||
|
private readonly VisualStyleRenderer _treeViewBorderDisabled = new VisualStyleRenderer("COMBOBOX", 4, 4);
|
||||||
|
|
||||||
private Size? _glyphSize;
|
private Size? _glyphSize;
|
||||||
|
|
||||||
protected override Size GetExpanderSize(Graphics graphics, KTreeNode node)
|
protected override Size GetExpanderSize(Graphics graphics, KTreeNode node)
|
||||||
@ -124,8 +129,10 @@ namespace Acacia.Controls
|
|||||||
protected override void RenderNodeOutline(Graphics graphics, KTreeNode node, Rectangle rect, KTreeNodeMeasurements.Part? highlight)
|
protected override void RenderNodeOutline(Graphics graphics, KTreeNode node, Rectangle rect, KTreeNodeMeasurements.Part? highlight)
|
||||||
{
|
{
|
||||||
// Draw one pixel too far, to overlap top and bottom borders for a continuous selection
|
// Draw one pixel too far, to overlap top and bottom borders for a continuous selection
|
||||||
|
|
||||||
Rectangle highlightRect = new Rectangle(rect.X, rect.Y, rect.Width, rect.Height + 1);
|
Rectangle highlightRect = new Rectangle(rect.X, rect.Y, rect.Width, rect.Height + 1);
|
||||||
|
// If full-row selecting, compensate for shifted rectangle.
|
||||||
|
if (_tree.FullRowSelect)
|
||||||
|
highlightRect.Height -= 2 * _tree.BorderThickness;
|
||||||
if (_tree.ActiveNode == node && _tree.Focused)
|
if (_tree.ActiveNode == node && _tree.Focused)
|
||||||
{
|
{
|
||||||
if (node.IsSelected)
|
if (node.IsSelected)
|
||||||
@ -148,11 +155,20 @@ namespace Acacia.Controls
|
|||||||
|
|
||||||
public override void RenderControlBorder(Graphics graphics, Rectangle rect)
|
public override void RenderControlBorder(Graphics graphics, Rectangle rect)
|
||||||
{
|
{
|
||||||
Color color = (_tree.Enabled ? _treeViewItemNormal : _treeViewItemDisabled).GetColor(ColorProperty.BorderColor);
|
VisualStyleRenderer style;
|
||||||
using (Pen pen = new Pen(_tree.Enabled ? Color.Black : SystemColors.GrayText))
|
if (_tree.Enabled)
|
||||||
{
|
{
|
||||||
graphics.DrawRectangle(pen, new Rectangle(rect.X, rect.Y, rect.Width - 1, rect.Height - 1));
|
if (_tree.Focused)
|
||||||
|
style = _treeViewBorderFocus;
|
||||||
|
else
|
||||||
|
style = _treeViewBorderNormal;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
style = _treeViewBorderDisabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
style.DrawBackground(graphics, rect, graphics.ClipBounds.ToRectangle());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,6 +131,11 @@ namespace Acacia.Controls
|
|||||||
return new Point(_this.Left, _this.Top);
|
return new Point(_this.Left, _this.Top);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Rectangle ToRectangle(this RectangleF _this)
|
||||||
|
{
|
||||||
|
return new Rectangle((int)_this.X, (int)_this.Y, (int)_this.Width, (int)_this.Height);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/// Copyright 2016 Kopano b.v.
|
/// Copyright 2017 Kopano b.v.
|
||||||
///
|
///
|
||||||
/// This program is free software: you can redistribute it and/or modify
|
/// This program is free software: you can redistribute it and/or modify
|
||||||
/// it under the terms of the GNU Affero General Public License, version 3,
|
/// it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user