///
/// 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.Collections;
using System.Drawing;
using System.Windows.Forms;
using JetBrains.DataStructures;
using SP.Windows;
namespace JetBrains.JetListViewLibrary
{
///
/// Shared code between single-line and multiline renderers.
///
internal abstract class RowRendererBase: IRowRenderer, IDisposable
{
protected JetListViewColumnCollection _columnCollection;
protected int _borderSize;
protected int _scrollOffset;
protected string _searchHighlightText;
private Control _ownerControl;
protected IControlPainter _controlPainter;
protected IControlMethodInvoker _methodInvoker;
protected bool _fullRowSelect = false;
private int _scrollRange;
protected int _rowHeight;
protected Header _headerControl;
protected RowRendererBase( JetListViewColumnCollection columnCollection )
{
_columnCollection = columnCollection;
_columnCollection.ColumnAdded += new ColumnEventHandler( HandleColumnAdded );
_columnCollection.ColumnRemoved += new ColumnEventHandler( HandleColumnRemoved );
foreach( JetListViewColumn col in _columnCollection )
{
HookColumn( col );
}
}
public virtual void Dispose()
{
_columnCollection.ColumnAdded -= new ColumnEventHandler( HandleColumnAdded );
_columnCollection.ColumnRemoved -= new ColumnEventHandler( HandleColumnRemoved );
foreach( JetListViewColumn col in _columnCollection )
{
UnhookColumn( col );
}
}
public event EventHandler ScrollRangeChanged;
public event EventHandler Invalidate;
public event RowHeightChangedEventHandler RowHeightChanged;
public event EventHandler AllRowsHeightChanged;
public event RequestScrollEventHandler RequestScroll;
public event ColumnEventHandler ColumnClick;
///
/// Occurs when the user drags the column splitter to change the size of the column.
///
public event EventHandler ColumnResized;
///
/// Occurs when the user drags the column header to change the order of the columns.
///
public event EventHandler ColumnOrderChanged;
///
/// The height of the line in the view.
///
public int RowHeight
{
get { return _rowHeight; }
set { _rowHeight = value; }
}
public int ScrollOffset
{
get { return _scrollOffset; }
set { _scrollOffset = value; }
}
public int BorderSize
{
get { return _borderSize; }
set { _borderSize = value; }
}
public string SearchHighlightText
{
get { return _searchHighlightText; }
set { _searchHighlightText = value; }
}
public IControlMethodInvoker MethodInvoker
{
get { return _methodInvoker; }
set { _methodInvoker = value; }
}
public Control OwnerControl
{
get { return _ownerControl; }
set { _ownerControl = value; }
}
public IControlPainter ControlPainter
{
get { return _controlPainter; }
set { _controlPainter = value; }
}
///
/// Gets or sets a value indicating whether the selection highlight covers all
/// columns in the list or just the first column.
///
public bool FullRowSelect
{
get { return _fullRowSelect; }
set { _fullRowSelect = value; }
}
public int ScrollRange
{
get { return _scrollRange; }
}
public Header HeaderControl
{
get { return _headerControl; }
set
{
if ( _headerControl != value )
{
if ( _headerControl != null )
{
UnhookHeaderControl();
}
_headerControl = value;
if ( _headerControl != null )
{
HookHeaderControl();
}
}
}
}
public MouseHandleResult HandleMouseDown( JetListViewNode node, int x, int y, MouseButtons button, Keys modifiers )
{
MouseHandleResult result = 0;
if ( button == MouseButtons.Left )
{
int deltaX, deltaY;
JetListViewColumn col = GetClickColumn( node, x, y, out deltaX, out deltaY );
if ( col != null )
{
result = col.HandleMouseDown( node, deltaX, deltaY );
if ( col == GetInPlaceEditColumn( node ) )
{
result |= MouseHandleResult.MayInPlaceEdit;
}
}
}
return result;
}
public bool HandleMouseUp( JetListViewNode node, int x, int y, MouseButtons button, Keys modifiers )
{
if ( button == MouseButtons.Left )
{
int deltaX, deltaY;
JetListViewColumn col = GetClickColumn( node, x, y, out deltaX, out deltaY );
if ( col != null )
{
return col.HandleMouseUp( node, deltaX, deltaY );
}
}
return false;
}
public bool HandleKeyDown( JetListViewNode node, KeyEventArgs e )
{
foreach( JetListViewColumn col in GetColumnEnumerable( node ) )
{
if ( col.HandleKeyDown( node, e ) )
{
return true;
}
}
return false;
}
public bool AcceptDoubleClick( JetListViewNode node, int x, int y )
{
JetListViewColumn col = GetColumnAt( node, x, y );
if ( col == null )
{
return false;
}
return col.AcceptColumnDoubleClick;
}
public void HandleDoubleClick( JetListViewNode node )
{
foreach( JetListViewColumn col in GetColumnEnumerable( node ) )
{
if ( col.HandleDoubleClick( node ) )
{
break;
}
}
}
protected JetListViewColumn GetClickColumn( JetListViewNode node, int x, int y,
out int deltaX, out int deltaY )
{
foreach( JetListViewColumn col in GetColumnEnumerable( node ) )
{
if ( col.HandleAllClicks )
{
Rectangle rc = GetColumnBounds( col, node );
deltaX = x - rc.Left;
deltaY = y - rc.Top;
return col;
}
}
return GetColumnAndDelta( node, x, y, out deltaX, out deltaY );
}
public JetListViewColumn GetColumnAt( JetListViewNode node, int x, int y )
{
int deltaX, deltaY;
return GetColumnAndDelta( node, x, y, out deltaX, out deltaY );
}
public JetListViewColumn GetInPlaceEditColumn( JetListViewNode node )
{
foreach( JetListViewColumn col in GetColumnEnumerable( node ) )
{
if ( IsValueColumn( col ) )
{
return col;
}
}
return null;
}
protected bool IsValueColumn( JetListViewColumn col )
{
return !col.FixedSize && !col.IsIndentColumn();
}
protected void OnInvalidate()
{
if ( Invalidate != null )
{
Invalidate( this, EventArgs.Empty );
}
}
protected void SetScrollRange( int width )
{
if ( _scrollRange != width )
{
_scrollRange = width;
if ( ScrollRangeChanged != null )
{
ScrollRangeChanged( this, EventArgs.Empty );
}
}
}
protected virtual void HandleColumnAdded( object sender, ColumnEventArgs e )
{
HookColumn( e.Column );
}
protected virtual void HandleColumnRemoved( object sender, ColumnEventArgs e )
{
UnhookColumn( e.Column );
}
protected virtual void HookColumn( JetListViewColumn col )
{
col.SortIconChanged += new EventHandler( HandleSortIconChanged );
}
protected virtual void UnhookColumn( JetListViewColumn col )
{
col.SortIconChanged -= new EventHandler( HandleSortIconChanged );
}
protected void OnColumnClick( JetListViewColumn col )
{
if ( ColumnClick != null )
{
ColumnClick( this, new ColumnEventArgs( col ) );
}
}
protected void OnColumnResized()
{
if ( ColumnResized != null )
{
ColumnResized( this, EventArgs.Empty );
}
}
protected void OnColumnOrderChanged()
{
if ( ColumnOrderChanged != null )
{
ColumnOrderChanged( this, EventArgs.Empty );
}
}
protected void OnRequestScroll( int coord )
{
if ( RequestScroll != null )
{
RequestScroll( this, new RequestScrollEventArgs( coord ) );
}
}
public abstract int GetRowHeight( JetListViewNode node );
public abstract int AllRowsHeight { get; }
public abstract void UpdateItem( object item );
public abstract void DrawRow( Graphics g, Rectangle rc, JetListViewNode itemNode, RowState rowState );
public abstract void SizeColumnsToContent( HashSet addedNodes, HashSet removedNodes, HashSet changedNodes );
public abstract void ProcessNodeExpanded( JetListViewNode node );
public abstract void ProcessNodeCollapsed( JetListViewNode node );
public abstract Rectangle GetColumnBounds( JetListViewColumn col, JetListViewNode node );
public abstract int VisibleWidth { get; set; }
protected abstract JetListViewColumn GetColumnAndDelta( JetListViewNode node, int x, int y, out int deltaX, out int deltaY );
protected abstract IEnumerable GetColumnEnumerable( JetListViewNode node );
protected abstract void HandleSortIconChanged( object sender, EventArgs e );
protected virtual void UnhookHeaderControl()
{
}
protected virtual void HookHeaderControl()
{
}
protected virtual void ScrollColumnInView( JetListViewColumn col, JetListViewNode node )
{
}
protected internal abstract Rectangle GetFocusRect( JetListViewNode itemNode, Rectangle rc );
protected void FillFullRowSelectBar( Graphics g, Rectangle rcFocus, RowState state )
{
Brush brush = null;
if ( (state & RowState.IncSearchMatch) != 0 )
{
brush = SystemBrushes.Control;
}
else if ( (state & RowState.ActiveSelected) != 0 )
{
brush = SystemBrushes.Highlight;
}
else if ( (state & RowState.InactiveSelected) != 0 )
{
brush = SystemBrushes.Control;
}
if ( brush != null )
{
g.FillRectangle( brush, rcFocus );
}
}
protected void ClearRowSelectState( ref RowState state, ref bool focusRow, ref bool dropTargetRow )
{
if ( _fullRowSelect )
{
if ( (state & RowState.Focused ) != 0 )
{
state &= ~RowState.Focused;
focusRow = true;
}
if ( (state & RowState.DropTarget) != 0 )
{
state &= ~RowState.DropTarget;
dropTargetRow = true;
}
}
}
protected void DrawRowSelectRect( Graphics g, Rectangle rcFocus, bool dropTargetRow, bool focusRow )
{
if ( _fullRowSelect )
{
if ( dropTargetRow )
{
JetListViewColumn.DrawDropTarget( g, rcFocus );
}
else if ( focusRow )
{
_controlPainter.DrawFocusRect( g, rcFocus );
}
}
}
protected void DrawColumnWithHighlight( Graphics g, Rectangle rcCol, JetListViewNode itemNode,
JetListViewColumn col, RowState state )
{
if ( (state & RowState.InPlaceEdit ) == 0 || col != GetInPlaceEditColumn( itemNode ) )
{
string highlightText = null;
if ( (state & RowState.IncSearchMatch) != 0 &&
col.MatchIncrementalSearch( itemNode, _searchHighlightText ) )
{
highlightText = _searchHighlightText;
}
col.DrawNode( g, rcCol, itemNode, state, highlightText );
}
}
public bool MatchIncrementalSearch( JetListViewNode node, string text )
{
foreach( JetListViewColumn col in GetColumnEnumerable( node ) )
{
if ( col.MatchIncrementalSearch( node, text ) )
{
ScrollColumnInView( col, node );
return true;
}
}
return false;
}
internal int GetAutoPreviewIndent( JetListViewNode node )
{
foreach( JetListViewColumn col in GetColumnEnumerable( node ) )
{
if ( !col.IsIndentColumn() && !col.FixedSize )
{
return GetColumnBounds( col, node ).Left;
}
}
return 0;
}
}
}