PageRenderTime 30ms CodeModel.GetById 16ms app.highlight 10ms RepoModel.GetById 2ms app.codeStats 0ms

/src/NUnit/UiException/Controls/ErrorList.cs

#
C# | 263 lines | 197 code | 53 blank | 13 comment | 28 complexity | 9d85a6e0f791c7aa75cc66521c39dc18 MD5 | raw file
  1// ****************************************************************
  2// This is free software licensed under the NUnit license. You may
  3// obtain a copy of the license at http://nunit.org
  4// ****************************************************************
  5
  6using System;
  7using System.Collections.Generic;
  8using System.Text;
  9using System.Windows.Forms;
 10using System.Drawing;
 11using System.Diagnostics;
 12
 13namespace NUnit.UiException.Controls
 14{
 15    /// <summary>
 16    /// Displays a control which implements IStackTraceView.
 17    /// </summary>
 18    public class ErrorList :
 19        UserControl,
 20        IStackTraceView
 21    {
 22        public event EventHandler SelectedItemChanged;
 23
 24        private ErrorListOrderPolicy _listOrder;
 25        private ErrorItemCollection _items;
 26        private ErrorItem _selection;
 27        private string _stackTrace;
 28        protected IErrorListRenderer _renderer;
 29        protected Graphics _workingGraphics;
 30        protected int _hoveredIndex;
 31
 32        private Point _mouse;
 33        private bool _autoSelectFirstItem;
 34
 35        /// <summary>
 36        /// Builds a new instance of ErrorList.
 37        /// </summary>
 38        public ErrorList() :
 39            this(new DefaultErrorListRenderer())
 40        {
 41        }
 42
 43        /// <summary>
 44        /// Gives access to the item collection.
 45        /// </summary>
 46        public ErrorItemCollection Items
 47        {
 48            get { return (_items); }
 49        }
 50
 51        #region IStackTraceView Members
 52
 53        public bool AutoSelectFirstItem
 54        {
 55            get { return (_autoSelectFirstItem); }
 56            set { _autoSelectFirstItem = value; }
 57        }
 58
 59        public string StackTrace
 60        {
 61            get { return (_stackTrace); }
 62            set
 63            {
 64                ErrorItem candidate;
 65
 66                candidate = PopulateList(value);
 67
 68                if (!String.IsNullOrEmpty(value) &&
 69                    _items.Count == 0)
 70                    _items.Add(new ErrorItem(null, "Fail to parse stack trace", -1));
 71
 72                AutoScrollMinSize = _renderer.GetDocumentSize(_items, _workingGraphics);
 73
 74                _hoveredIndex = -1;
 75                SelectedItem = (AutoSelectFirstItem ? candidate : null);
 76                Invalidate();
 77
 78                return;
 79            }
 80        }
 81
 82        public ErrorItem SelectedItem
 83        {
 84            get { return (_selection); }
 85            set
 86            {
 87                bool fireEvent;
 88
 89                if (value != null &&
 90                    (!_items.Contains(value) || !value.HasSourceAttachment))
 91                    return;
 92
 93                fireEvent = (_selection != value);
 94                _selection = value;
 95
 96                if (fireEvent && SelectedItemChanged != null)
 97                    SelectedItemChanged(this, new EventArgs());
 98
 99                Invalidate();
100            }
101        }
102
103        public ErrorListOrderPolicy ListOrderPolicy
104        {
105            get { return (_listOrder); }
106            set
107            {
108                if (_listOrder == value)
109                    return;
110                _listOrder = value;
111                _items.Reverse();
112                Invalidate();
113            }
114        }
115
116        #endregion
117
118        protected ErrorList(IErrorListRenderer renderer)
119        {
120            UiExceptionHelper.CheckNotNull(renderer, "display");
121
122            SetStyle(ControlStyles.UserPaint, true);
123            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
124            DoubleBuffered = true;
125
126            _renderer = renderer;
127            _items = new ErrorItemCollection();
128            _stackTrace = null;
129            _selection = null;
130            _workingGraphics = CreateGraphics();
131            _hoveredIndex = -1;
132
133            _autoSelectFirstItem = false;
134            _listOrder = ErrorListOrderPolicy.InitialOrder;
135
136            return;
137        }
138
139        protected virtual void ItemEntered(int index)
140        {
141            Cursor = Cursors.Hand;
142        }
143
144        protected virtual void ItemLeaved(int index)
145        {
146            Cursor = Cursors.Default;
147        }
148
149        protected override void OnPaint(PaintEventArgs e)
150        {
151            Rectangle viewport;
152
153            base.OnPaint(e);
154
155            viewport = new Rectangle(-AutoScrollPosition.X, -AutoScrollPosition.Y, 
156                ClientRectangle.Width, ClientRectangle.Height);
157            _renderer.DrawToGraphics(_items, _selection, e.Graphics, viewport);
158
159            if (_hoveredIndex != -1)
160                _renderer.DrawItem(_items[_hoveredIndex], _hoveredIndex, true,
161                    _items[_hoveredIndex] == _selection, e.Graphics, viewport);
162
163            return;
164        }
165
166        protected override void OnMouseHover(EventArgs e)
167        {
168            base.OnMouseHover(e);
169            Focus();
170        }
171       
172        protected override void OnMouseDown(MouseEventArgs e)
173        {
174            base.OnMouseDown(e);
175            _mouse = new Point(e.X, e.Y - AutoScrollPosition.Y);
176        }
177
178        protected override void OnMouseMove(MouseEventArgs e)
179        {
180            ErrorItem item;
181            int itemIndex;
182
183            base.OnMouseMove(e);
184
185            item = _renderer.ItemAt(_items, _workingGraphics, new Point(e.X, e.Y - AutoScrollPosition.Y));
186
187            itemIndex = -1;
188            for (int i = 0; i < _items.Count; ++i)
189                if (Object.ReferenceEquals(_items[i], item))
190                {
191                    itemIndex = i;
192                    break;
193                }            
194
195            if (itemIndex != _hoveredIndex)
196            {
197                if (_hoveredIndex != -1)
198                    ItemLeaved(_hoveredIndex);
199
200                if (itemIndex != -1 && _items[itemIndex].HasSourceAttachment)
201                {
202                    ItemEntered(itemIndex);
203                    _hoveredIndex = itemIndex;
204                }
205                else
206                    _hoveredIndex = -1;
207                Invalidate();
208            }
209
210            return;
211        }
212
213        protected override void OnClick(EventArgs e)
214        {
215            base.OnClick(e);
216            OnClick(_mouse);
217
218            return;
219        }
220
221        protected override void OnFontChanged(EventArgs e)
222        {
223            this._renderer.Font = this.Font;
224
225            base.OnFontChanged(e);
226        }
227
228        protected void OnClick(Point point)
229        {
230            SelectedItem = _renderer.ItemAt(_items, _workingGraphics, point);
231
232            return;
233        }
234
235        protected override void OnSizeChanged(EventArgs e)
236        {
237            base.OnSizeChanged(e);
238            Invalidate();
239        }
240
241        private ErrorItem PopulateList(string stackTrace)
242        {
243            StackTraceParser parser = new StackTraceParser();
244            ErrorItem candidate;
245
246            _stackTrace = stackTrace;
247            parser.Parse(stackTrace);
248            if (_listOrder == ErrorListOrderPolicy.ReverseOrder)
249                parser.Items.Reverse();
250
251            candidate = null;
252            _items.Clear();
253            foreach (ErrorItem item in parser.Items)
254            {
255                if (candidate == null && item.HasSourceAttachment)
256                    candidate = item;
257                _items.Add(item);
258            }
259
260            return (candidate);
261        }
262    }
263}