/// /// Copyright © 2003-2008 JetBrains s.r.o. /// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder). /// using System; using System.Drawing; using System.Windows.Forms; using JetBrains.DataStructures; using SP.Windows; namespace JetBrains.JetListViewLibrary { /// /// Decorator around a base row renderer which adds an auto-preview row to it. /// internal class AutoPreviewRowRenderer: IRowRenderer { private readonly RowRendererBase _baseRowRenderer; private readonly JetListViewPreviewColumn _previewColumn; public AutoPreviewRowRenderer( RowRendererBase baseRowRenderer, JetListViewPreviewColumn previewColumn, JetListViewColumnCollection columnCollection ) { _baseRowRenderer = baseRowRenderer; _baseRowRenderer.ScrollRangeChanged += new EventHandler( HandleBaseScrollRangeChanged ); _baseRowRenderer.Invalidate += new EventHandler( HandleBaseInvalidate ); _baseRowRenderer.RequestScroll += new RequestScrollEventHandler( HandleBaseRequestScroll ); _previewColumn = previewColumn; _previewColumn.Owner = columnCollection; _previewColumn.RowHeightChanged += new RowHeightChangedEventHandler( HandlePreviewRowHeightChanged ); _previewColumn.AllRowsHeightChanged += new EventHandler( HandlePreviewAllRowsHeightChanged ); } public int GetRowHeight( JetListViewNode node ) { return _baseRowRenderer.GetRowHeight( node ) + _previewColumn.GetAutoPreviewHeight( node ); } public int AllRowsHeight { get { return -1; } } public void DrawRow( Graphics g, Rectangle rc, JetListViewNode itemNode, RowState rowState ) { bool focusRow = false; bool dropTargetRow = false; if ( ( rowState & RowState.Focused) != 0 && _baseRowRenderer.SearchHighlightText != null && _baseRowRenderer.SearchHighlightText.Length > 0 ) { rowState |= RowState.IncSearchMatch; } if ( _baseRowRenderer.FullRowSelect ) { focusRow = ((rowState & RowState.Focused ) != 0); dropTargetRow = ((rowState & RowState.DropTarget ) != 0); rowState &= ~(RowState.Focused | RowState.DropTarget); } int baseHeight = _baseRowRenderer.GetRowHeight( itemNode ); Rectangle rcBase = new Rectangle( rc.Left, rc.Top, rc.Width, baseHeight ); _baseRowRenderer.DrawRow( g, rcBase, itemNode, rowState ); int indent = _baseRowRenderer.GetAutoPreviewIndent( itemNode ); int previewWidth = _baseRowRenderer.ScrollRange - _baseRowRenderer.ScrollOffset; if ( previewWidth == 0 ) { previewWidth = _baseRowRenderer.VisibleWidth; } Rectangle rcPreview = new Rectangle( indent, rc.Top + baseHeight, previewWidth + _baseRowRenderer.BorderSize - indent, rc.Height - baseHeight ); Rectangle rcFocus = _baseRowRenderer.GetFocusRect( itemNode, rc ); if ( rcPreview.Height > 0 ) { if ( _baseRowRenderer.FullRowSelect ) { if ( (rowState & RowState.IncSearchMatch) != 0 && ((rowState & RowState.ActiveSelected) != 0) ) { rowState &= ~RowState.ActiveSelected; rowState |= RowState.InactiveSelected; } } // in multiline view, the rectangle which must be painted with the auto-preview // background color is wider than the rectangle containing the column text Rectangle rcPreviewBackground = new Rectangle( rcFocus.Left, rcPreview.Top, rcFocus.Width, rcPreview.Height ); _previewColumn.DrawItemBackground( g, rcPreviewBackground, rcPreviewBackground, itemNode, rowState, null ); _previewColumn.DrawNode( g, rcPreview, itemNode, rowState, null ); } if ( dropTargetRow || focusRow ) { if ( dropTargetRow ) { JetListViewColumn.DrawDropTarget( g, rcFocus ); } else if ( focusRow ) { _baseRowRenderer.ControlPainter.DrawFocusRect( g, rcFocus ); } } } public MouseHandleResult HandleMouseDown( JetListViewNode node, int x, int y, MouseButtons button, Keys modifiers ) { int baseHeight = _baseRowRenderer.GetRowHeight( node ); if ( y < baseHeight ) { return _baseRowRenderer.HandleMouseDown( node, x, y, button, modifiers ); } return _previewColumn.HandleMouseDown( node, x, y - baseHeight ); } public bool HandleMouseUp( JetListViewNode node, int x, int y, MouseButtons button, Keys modifiers ) { int baseHeight = _baseRowRenderer.GetRowHeight( node ); if ( y < baseHeight ) { return _baseRowRenderer.HandleMouseUp( node, x, y, button, modifiers ); } return _previewColumn.HandleMouseUp( node, x, y - baseHeight ); } public bool HandleKeyDown( JetListViewNode node, KeyEventArgs e ) { return _baseRowRenderer.HandleKeyDown( node, e ); } public bool AcceptDoubleClick( JetListViewNode node, int x, int y ) { int baseHeight = _baseRowRenderer.GetRowHeight( node ); if ( y < baseHeight ) { return _baseRowRenderer.AcceptDoubleClick( node, x, y ); } return _previewColumn.AcceptColumnDoubleClick; } public void HandleDoubleClick( JetListViewNode node ) { _baseRowRenderer.HandleDoubleClick( node ); } public void SizeColumnsToContent( HashSet addedNodes, HashSet removedNodes, HashSet changedNodes ) { _baseRowRenderer.SizeColumnsToContent( addedNodes, removedNodes, changedNodes ); } public void ProcessNodeExpanded( JetListViewNode node ) { _baseRowRenderer.ProcessNodeExpanded( node ); } public void ProcessNodeCollapsed( JetListViewNode node ) { _baseRowRenderer.ProcessNodeCollapsed( node ); } public int ScrollOffset { get { return _baseRowRenderer.ScrollOffset; } set { _baseRowRenderer.ScrollOffset = value; } } public string SearchHighlightText { get { return _baseRowRenderer.SearchHighlightText; } set { _baseRowRenderer.SearchHighlightText = value; } } public Header HeaderControl { get { return _baseRowRenderer.HeaderControl; } set { _baseRowRenderer.HeaderControl = value; } } public JetListViewColumn GetColumnAt( JetListViewNode node, int x, int y ) { int baseHeight = _baseRowRenderer.GetRowHeight( node ); if ( y < baseHeight ) { return _baseRowRenderer.GetColumnAt( node, x, y ); } return _previewColumn; } public Rectangle GetColumnBounds( JetListViewColumn col, JetListViewNode node ) { if ( col == _previewColumn ) { int startX = _baseRowRenderer.BorderSize - _baseRowRenderer.ScrollOffset; int endX = _baseRowRenderer.ScrollRange - _baseRowRenderer.BorderSize; return new Rectangle( startX, _baseRowRenderer.GetRowHeight( node ), endX - startX, _previewColumn.GetAutoPreviewHeight( node ) ); } return _baseRowRenderer.GetColumnBounds( col, node ); } public JetListViewColumn GetInPlaceEditColumn( JetListViewNode node ) { return _baseRowRenderer.GetInPlaceEditColumn( node ); } public bool MatchIncrementalSearch( JetListViewNode node, string text ) { return _baseRowRenderer.MatchIncrementalSearch( node, text ); } public void UpdateItem( object item ) { _baseRowRenderer.UpdateItem( item ); _previewColumn.UpdateItem( item ); } public int ScrollRange { get { return _baseRowRenderer.ScrollRange; } } public int VisibleWidth { get { return _baseRowRenderer.VisibleWidth; } set { _baseRowRenderer.VisibleWidth = value; } } public int BorderSize { get { return _baseRowRenderer.BorderSize; } set { _baseRowRenderer.BorderSize = value; } } public Control OwnerControl { get { return _baseRowRenderer.OwnerControl; } set { _baseRowRenderer.OwnerControl = value; } } public IControlMethodInvoker MethodInvoker { get { return _baseRowRenderer.MethodInvoker; } set { _baseRowRenderer.MethodInvoker = value; } } public IControlPainter ControlPainter { get { return _baseRowRenderer.ControlPainter; } set { _baseRowRenderer.ControlPainter = value; } } public bool FullRowSelect { get { return _baseRowRenderer.FullRowSelect; } set { _baseRowRenderer.FullRowSelect = value; } } public event EventHandler ScrollRangeChanged; public event EventHandler Invalidate; public event RowHeightChangedEventHandler RowHeightChanged; public event EventHandler AllRowsHeightChanged; public event RequestScrollEventHandler RequestScroll; private void HandleBaseScrollRangeChanged( object sender, EventArgs e ) { if ( ScrollRangeChanged != null ) { ScrollRangeChanged( this, EventArgs.Empty ); } } private void HandleBaseInvalidate( object sender, EventArgs e ) { if ( Invalidate != null ) { Invalidate( this, EventArgs.Empty ); } } private void HandleBaseRequestScroll( object sender, RequestScrollEventArgs e ) { if ( RequestScroll != null ) { RequestScroll( this, e ); } } private void HandlePreviewRowHeightChanged( object sender, RowHeightChangedEventArgs e ) { if ( RowHeightChanged != null ) { int baseHeight = _baseRowRenderer.GetRowHeight( e.Row ); RowHeightChanged( this, new RowHeightChangedEventArgs( e.Row, e.OldHeight + baseHeight, e.NewHeight + baseHeight ) ); } } private void HandlePreviewAllRowsHeightChanged( object sender, EventArgs e ) { if ( AllRowsHeightChanged != null ) { AllRowsHeightChanged( this, EventArgs.Empty ); } } } }