/// Copyright 2016 Kopano b.v. /// /// 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, /// as published by the Free Software Foundation. /// /// This program is distributed in the hope that it will be useful, /// but WITHOUT ANY WARRANTY; without even the implied warranty of /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the /// GNU Affero General Public License for more details. /// /// You should have received a copy of the GNU Affero General Public License /// along with this program.If not, see. /// /// Consult LICENSE file for details using Acacia.Native; using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Windows.Forms.VisualStyles; namespace Acacia.Controls { internal class KTreeRendererVisualStyles : KTreeRenderer { // From vsstyle.h // enum TREEVIEWPARTS // { // TVP_TREEITEM = 1, // TVP_GLYPH = 2, // TVP_BRANCH = 3, // TVP_HOTGLYPH = 4, // }; // enum TREEITEMSTATES // { // TREIS_NORMAL = 1, // TREIS_HOT = 2, // TREIS_SELECTED = 3, // TREIS_DISABLED = 4, // TREIS_SELECTEDNOTFOCUS = 5, // TREIS_HOTSELECTED = 6, // }; // // enum GLYPHSTATES // { // GLPS_CLOSED = 1, // GLPS_OPENED = 2, // }; private const string TREEVIEW = "Explorer::TreeView"; private readonly VisualStyleRenderer _treeViewItemNormal = new VisualStyleRenderer(TREEVIEW, 1, 1); private readonly VisualStyleRenderer _treeViewItemHot = new VisualStyleRenderer(TREEVIEW, 1, 2); private readonly VisualStyleRenderer _treeViewItemSelected = new VisualStyleRenderer(TREEVIEW, 1, 3); private readonly VisualStyleRenderer _treeViewItemDisabled = new VisualStyleRenderer(TREEVIEW, 1, 4); private readonly VisualStyleRenderer _treeViewItemSelectedNotFocus = new VisualStyleRenderer(TREEVIEW, 1, 5); private readonly VisualStyleRenderer _treeViewItemHotSelected = new VisualStyleRenderer(TREEVIEW, 1, 6); private readonly VisualStyleRenderer _treeViewGlyphClosed = new VisualStyleRenderer(TREEVIEW, 2, 1); private readonly VisualStyleRenderer _treeViewGlyphOpened = new VisualStyleRenderer(TREEVIEW, 2, 2); private readonly VisualStyleRenderer _treeViewGlyphHotClosed = new VisualStyleRenderer(TREEVIEW, 4, 1); private readonly VisualStyleRenderer _treeViewGlyphHotOpened = new VisualStyleRenderer(TREEVIEW, 4, 2); private Size? _glyphSize; protected override Size GetExpanderSize(Graphics graphics, KTreeNode node) { // Get glyph size if needed if (!_glyphSize.HasValue) _glyphSize = _treeViewGlyphOpened.GetPartSize(graphics, ThemeSizeType.True); return _glyphSize.Value; } internal protected override void RenderNodeExpander(Graphics graphics, KTreeNode node, Rectangle rect, KTreeNodeMeasurements.Part? highlight) { if (highlight != null && highlight.Value == KTreeNodeMeasurements.Part.Expander) { if (node.IsExpanded) _treeViewGlyphHotOpened.DrawBackground(graphics, rect); else _treeViewGlyphHotClosed.DrawBackground(graphics, rect); } else { if (node.IsExpanded) _treeViewGlyphOpened.DrawBackground(graphics, rect); else _treeViewGlyphClosed.DrawBackground(graphics, rect); } } private VisualStyleRenderer GetStyle(KTreeNode node, KTreeNodeMeasurements.Part? highlight) { if (!_tree.Enabled) { return _treeViewItemDisabled; } else if (highlight != null) { if (node.IsSelected) return _treeViewItemHotSelected; else return _treeViewItemHot; } else { if (node.IsSelected) { if (_tree.Focused) return _treeViewItemSelected; else return _treeViewItemSelectedNotFocus; } else return _treeViewItemNormal; } } 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 Rectangle highlightRect = new Rectangle(rect.X, rect.Y, rect.Width, rect.Height + 1); if (_tree.ActiveNode == node && _tree.Focused) { if (node.IsSelected) _treeViewItemHotSelected.DrawBackground(graphics, highlightRect); else _treeViewItemNormal.DrawBackground(graphics, highlightRect); } else if (node.IsSelected || highlight != null) { GetStyle(node, highlight).DrawBackground(graphics, highlightRect); } } protected override void RenderNodeText(Graphics graphics, KTreeNode node, Rectangle rect, KTreeNodeMeasurements.Part? highlight) { Color foreColor = GetStyle(node, highlight).GetColor(ColorProperty.TextColor); TextRenderer.DrawText(graphics, node.Text, _tree.Font, rect, foreColor, Color.Transparent, TextFormatFlags.Left | TextFormatFlags.VerticalCenter); } public override void RenderControlBorder(Graphics graphics, Rectangle rect) { Color color = (_tree.Enabled ? _treeViewItemNormal : _treeViewItemDisabled).GetColor(ColorProperty.BorderColor); using (Pen pen = new Pen(_tree.Enabled ? Color.Black : SystemColors.GrayText)) { graphics.DrawRectangle(pen, new Rectangle(rect.X, rect.Y, rect.Width - 1, rect.Height - 1)); } } } }