private void DrawingArea_MouseDownOrMove(object sender, MouseEventArgs e)
        {
            if (sender == null || !(sender is Canvas))
            {
                throw new ArgumentException("expected only Canvas", "sender");
            }

            var    canvas = (Canvas)sender;
            double x      = e.GetPosition(canvas).X;
            double y      = e.GetPosition(canvas).Y;

            if (!bitmapArray.IsInBounds((int)x, (int)y))
            {
                return;
            }

            switch (tool)
            {
            case Tools.Filtering:
            {
                // brush border
                if (Shape != BrushShapes.Fill)
                {
                    if (DrawingBrush.Visibility != Visibility.Visible)
                    {
                        DrawingBrush.Visibility = Visibility.Visible;
                    }
                    double half = ((double)sizeOfBrush) / 2;
                    DrawingBrush.Margin = new Thickness(x - half, y - half, 0, 0);
                }

                //System.Text.StringBuilder s = new System.Text.StringBuilder();
                //s.Append("left click at: ").Append(new Point(x, y));
                //s.Append(' ').Append(Filter).Append(' ').Append(Shape);
                //s.Append(' ').Append((int)BrushSize.Value);
                //MessageBox.Show(s.ToString(), sender.GetType().ToString());

                // get filter instance using reflection
                var         typeName = new StringBuilder("GraphicsManipulation.Filters.").Append(Filter).Append("Filter").ToString();
                FilterBrush brush    = (FilterBrush)filtersAssembly.CreateInstance(typeName);

                if (brush is CustomFilter)
                {
                    ((CustomFilter)brush).FilterFunction = latestCustomFilter;
                }

                brush.ApplyAt(bitmapArray, Shape, new Point(x, y), (int)SizeOfBrush, mask);

                if (Shape == BrushShapes.Fill)
                {
                    bitmapArray.RefreshBitmap(Mask.Disabled);
                }
                else
                {
                    bitmapArray.RefreshBitmap(Mask.Rectangle);
                }
            } break;

            case Tools.Line:
            {
                int startX = (int)currentLineStart.X;
                int startY = (int)currentLineStart.Y;
                int endX   = (int)x;
                int endY   = (int)y;

                if (currentLineStart != currentLineEnd)
                {
                    int minX = (int)Math.Min(currentLineStart.X, currentLineEnd.X);
                    int maxX = (int)Math.Max(currentLineStart.X, currentLineEnd.X);
                    int minY = (int)Math.Min(currentLineStart.Y, currentLineEnd.Y);
                    int maxY = (int)Math.Max(currentLineStart.Y, currentLineEnd.Y);
                    bitmapArray.CopyArea(bitmapArrayTemp, minX, minY, maxX, maxY);
                }
                currentLineEnd = new Point(x, y);

                bitmapArray.DrawLine(startX, startY, endX, endY,
                                     lineColor.ScR, lineColor.ScG, lineColor.ScB);
                bitmapArray.RefreshBitmap(Mask.Rectangle);
            } break;
            }
        }