Skip to content

Commit

Permalink
Changes:
Browse files Browse the repository at this point in the history
   Updated SharpDX binaries.
   Render selection rectangle using direct2d instead of GDI (fixed few visual artifacts).
  • Loading branch information
abeckus committed Jan 6, 2016
1 parent cd818b1 commit a214783
Show file tree
Hide file tree
Showing 25 changed files with 391 additions and 794 deletions.
2 changes: 2 additions & 0 deletions Framework/Atf.Gui.WinForms/Atf.Gui.WinForms.vs2010.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,8 @@
</Compile>
<Compile Include="Controls\Adaptable\D2dAnnotationAdapter.cs" />
<Compile Include="Controls\Adaptable\D2dGridAdapter.cs" />
<Compile Include="Controls\Adaptable\D2dRectangleDragRenderer.cs" />
<Compile Include="Controls\Adaptable\D2dRectangleDragSelector.cs" />
<Compile Include="Controls\Adaptable\DiagramExpander.cs" />
<Compile Include="Controls\Adaptable\DiagramLabel.cs" />
<Compile Include="Controls\Adaptable\DiagramPin.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
//Copyright © 2014 Sony Computer Entertainment America LLC. See License.txt.

using System;
using System.Drawing;
using Sce.Atf.Direct2D;
using Sce.Atf.VectorMath;

namespace Sce.Atf.Controls.Adaptable
{
/// <summary>
/// Adapter that works with D2dRectangleDragSelector, to render the selection rectangle.
/// Two classes are needed instead of one because the selection rectangle needs to appear
/// on top of all other circuit elements but should receive mouse events at a lower priority.</summary>
public class D2dRectangleDragRenderer : DraggingControlAdapter
{
public D2dRectangleDragRenderer(D2dRectangleDragSelector selector)
{
Selector = selector;
}

public D2dRectangleDragSelector Selector { get; private set; }

/// <summary>
/// Gets or sets the color of the border of the selection rectangle.</summary>
public Color SelectionBorderColor = Color.DodgerBlue;

/// <summary>
/// Gets or sets the color used to fill the selection rectangle.</summary>
public Color SelectionFillColor = Color.FromArgb(64, Color.DodgerBlue);//25% opaque

/// <summary>
/// Binds the adapter to the adaptable control. Called in the order that the adapters
/// were defined on the control.</summary>
/// <param name="control">Adaptable control. Must be a D2dAdaptableControl.</param>
protected override void Bind(AdaptableControl control)
{
m_transformAdapter = control.As<ITransformAdapter>();

var d2dControl = (D2dAdaptableControl)control;
d2dControl.DrawingD2d += control_DrawingD2d;

base.Bind(control);
}

/// <summary>
/// Unbinds the adapter from the adaptable control</summary>
/// <param name="control">Adaptable control</param>
protected override void Unbind(AdaptableControl control)
{
var d2dControl = (D2dAdaptableControl)control;
d2dControl.DrawingD2d -= control_DrawingD2d;

base.Unbind(control);
}

private void control_DrawingD2d(object sender, EventArgs e)
{
if (Selector.IsSelecting)
{
var d2dControl = (D2dAdaptableControl)sender;
D2dGraphics g = d2dControl.D2dGraphics;

// Replace transform and anti-aliasing setting.
Matrix3x2F xform = d2dControl.D2dGraphics.Transform;
d2dControl.D2dGraphics.Transform = Matrix3x2F.Identity;
D2dAntialiasMode oldAA = d2dControl.D2dGraphics.AntialiasMode;
d2dControl.D2dGraphics.AntialiasMode = D2dAntialiasMode.Aliased;

// Draw the selection rectangle.
Rectangle rect = MakeSelectionRect(
ClientToCanvas(Selector.CurrentPoint), ClientToCanvas(Selector.FirstPoint));
rect.Intersect(AdaptedControl.ClientRectangle);
var rectF = new RectangleF(rect.X, rect.Y, rect.Width, rect.Height);
g.DrawRectangle(rectF, SelectionBorderColor, 1.0f, null);
g.FillRectangle(rectF, SelectionFillColor);

// Restore D2dGraphics settings.
d2dControl.D2dGraphics.Transform = xform;
d2dControl.D2dGraphics.AntialiasMode = oldAA;
}
}

// Makes a rectangle in canvas (world) coordinates, given points in Windows Client coordinates.
private Rectangle MakeSelectionRect(PointF p1, PointF p2)
{
Rectangle rect = GdiUtil.MakeRectangle(
new Point((int)p1.X, (int)p1.Y),
new Point((int)p2.X, (int)p2.Y));

if (m_transformAdapter != null)
rect = GdiUtil.Transform(m_transformAdapter.Transform, rect);

return rect;
}

private PointF ClientToCanvas(PointF p)
{
if (m_transformAdapter != null)
p = GdiUtil.InverseTransform(m_transformAdapter.Transform, p);
return p;
}

private ITransformAdapter m_transformAdapter;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
//Copyright © 2014 Sony Computer Entertainment America LLC. See License.txt.

using System;
using System.Drawing;
using System.Windows.Forms;

namespace Sce.Atf.Controls.Adaptable
{
/// <summary>
/// Adapter that allows users to drag-select rectangular regions on the
/// adapted control to modify the selection. The AdaptableControl must be
/// a D2dAdaptableControl. Use with a D2dRectangleDragRenderer.</summary>
public class D2dRectangleDragSelector : DraggingControlAdapter, IDragSelector
{
/// <summary>
/// Gets or sets the modifier keys that indicate a drag operation</summary>
public Keys ModifierKeys
{
get { return m_modifierKeys; }
set { m_modifierKeys = value; }
}
private Keys m_modifierKeys = Keys.Shift | Keys.Control;

/// <summary>
/// Event that is raised after a selection is made</summary>
public event EventHandler<DragSelectionEventArgs> Selected;

/// <summary>
/// Gets or sets the color of the border of the selection rectangle.</summary>
public Color SelectionBorderColor = Color.DodgerBlue;

/// <summary>
/// Gets or sets the color used to fill the selection rectangle.</summary>
public Color SelectionFillColor = Color.FromArgb(64, Color.DodgerBlue);//25% opaque

/// <summary>
/// Gets whether the user is actively creating a selection rectangle by clicking and
/// dragging on the canvas.</summary>
public bool IsSelecting { get; private set; }

/// <summary>
/// Performs custom operations when a selection is made</summary>
/// <param name="e">Event args</param>
protected virtual void OnSelected(DragSelectionEventArgs e)
{
}

/// <summary>
/// Binds the adapter to the adaptable control. Called in the order that the adapters
/// were defined on the control.</summary>
/// <param name="control">Adaptable control. Must be a D2dAdaptableControl.</param>
protected override void Bind(AdaptableControl control)
{
m_transformAdapter = control.As<ITransformAdapter>();
m_autoTranslateAdapter = control.As<IAutoTranslateAdapter>();

base.Bind(control);
}

/// <summary>
/// Unbinds the adapter from the adaptable control</summary>
/// <param name="control">Adaptable control</param>
protected override void Unbind(AdaptableControl control)
{
base.Unbind(control);
}

/// <summary>
/// Performs custom actions when performing a mouse dragging operation</summary>
/// <param name="e">Mouse event args</param>
protected override void OnDragging(MouseEventArgs e)
{
m_modifiers = Control.ModifierKeys;
if (e.Button == MouseButtons.Left &&
((m_modifiers & ~m_modifierKeys) == 0))
{
// make sure we can capture the mouse
if (!AdaptedControl.Capture)
{
m_firstCanvasPoint = m_currentCanvasPoint = ClientToCanvas(FirstPoint);

IsSelecting = true;

AdaptedControl.Capture = true;
m_saveCursor = AdaptedControl.Cursor;
AdaptedControl.Cursor = Cursors.Cross;

if (m_autoTranslateAdapter != null)
m_autoTranslateAdapter.Enabled = true;
}
}

if (IsSelecting)
{
AdaptedControl.Invalidate();
m_currentCanvasPoint = ClientToCanvas(CurrentPoint);
}
}

/// <summary>
/// Performs custom actions on adaptable control MouseUp events; base method should
/// be called first</summary>
/// <param name="sender">Adaptable control</param>
/// <param name="e">Event args</param>
protected override void OnMouseUp(object sender, MouseEventArgs e)
{
base.OnMouseUp(sender, e);

if (IsSelecting)
{
Rectangle rect = MakeSelectionRect(m_currentCanvasPoint, m_firstCanvasPoint);
RaiseSelected(rect, m_modifiers);

IsSelecting = false;
AdaptedControl.Cursor = m_saveCursor;
AdaptedControl.Capture = false;

if (m_autoTranslateAdapter != null)
m_autoTranslateAdapter.Enabled = false;

// In case nothing was selected, we need to make sure that the rectangle is cleared.
AdaptedControl.Invalidate();
}
}

private void RaiseSelected(Rectangle bounds, Keys modifiers)
{
var e = new DragSelectionEventArgs(bounds, modifiers);
OnSelected(e);
Selected.Raise(this, e);
}

// Makes a rectangle in canvas (world) coordinates, given points in Windows Client coordinates.
private Rectangle MakeSelectionRect(PointF p1, PointF p2)
{
Rectangle rect = GdiUtil.MakeRectangle(
new Point((int)p1.X, (int)p1.Y),
new Point((int)p2.X, (int)p2.Y));

if (m_transformAdapter != null)
rect = GdiUtil.Transform(m_transformAdapter.Transform, rect);

return rect;
}

private PointF ClientToCanvas(PointF p)
{
if (m_transformAdapter != null)
p = GdiUtil.InverseTransform(m_transformAdapter.Transform, p);
return p;
}

private IAutoTranslateAdapter m_autoTranslateAdapter;
private ITransformAdapter m_transformAdapter;
private Cursor m_saveCursor;
private Keys m_modifiers;
private PointF m_firstCanvasPoint;
private PointF m_currentCanvasPoint;
}
}
43 changes: 36 additions & 7 deletions Framework/Atf.Gui.WinForms/Controls/CanvasControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -458,14 +458,12 @@ protected override void OnMouseMove(MouseEventArgs e)
if (m_autoScroll && !VisibleClientRectangle.Contains(m_currentPoint) && !m_autoScrollTimer.Enabled)
m_autoScrollTimer.Start();

if (m_isMultiSelecting)
if (m_isMultiSelecting && DrawSelectionRectangleUsingGdi)
{
Rectangle rect;

rect = MakeSelectionRect(m_last, m_firstPoint);
Rectangle rect = MakeSelectionRect(LastMouseDragPoint, FirstMouseDragPoint);
ControlPaint.DrawReversibleFrame(rect, BackColor, FrameStyle.Dashed);

rect = MakeSelectionRect(m_currentPoint, m_firstPoint);
rect = MakeSelectionRect(CurrentMouseDragPoint, FirstMouseDragPoint);
ControlPaint.DrawReversibleFrame(rect, BackColor, FrameStyle.Dashed);
}
else if (m_isScrolling)
Expand Down Expand Up @@ -493,6 +491,37 @@ protected override void OnMouseMove(MouseEventArgs e)
base.OnMouseMove(e);
}

/// <summary>
/// Gets the current mouse cursor position during a drag operation, in client coordinates
/// (relative to the upper left corner of the form). Comes from MouseEventArgs.</summary>
protected Point CurrentMouseDragPoint
{
get { return m_currentPoint; }
}

/// <summary>
/// Gets the previous mouse cursor position during a drag operation, in client coordinates
/// (relative to the upper left corner of the form). Comes from MouseEventArgs.</summary>
protected Point LastMouseDragPoint
{
get { return m_last; }
}

/// <summary>
/// Gets the first mouse cursor position during a drag operation, in client coordinates
/// (relative to the upper left corner of the form). Comes from MouseEventArgs.</summary>
protected Point FirstMouseDragPoint
{
get { return m_firstPoint; }
}

/// <summary>
/// Gets or sets whether this class should draw the selection rectangle, which will be
/// done with GDI calls. If a derived class uses Direct2D, then set this property to
/// false and make use of IsMultiSelecting, FirstMouseDragPoint, and CurrentMouseDragPoint
/// to draw the selection rectangle during a paint event.</summary>
protected bool DrawSelectionRectangleUsingGdi = true;

/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.MouseUp"></see> event</summary>
/// <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs"></see> that contains the event data</param>
Expand Down Expand Up @@ -678,7 +707,7 @@ private void autoScrollTimer_Tick(object sender, EventArgs e)
m_autoScrollTimer.Stop();
if (!VisibleClientRectangle.Contains(m_currentPoint))
{
if (m_isMultiSelecting)
if (m_isMultiSelecting && DrawSelectionRectangleUsingGdi)
{
Rectangle selectionRect = MakeSelectionRect(m_currentPoint, m_firstPoint);
ControlPaint.DrawReversibleFrame(selectionRect, BackColor, FrameStyle.Dashed);
Expand Down Expand Up @@ -710,7 +739,7 @@ private void autoScrollTimer_Tick(object sender, EventArgs e)
OnAutoScroll();
base.Update(); // without this, the selection rect doesn't draw correctly

if (m_isMultiSelecting)
if (m_isMultiSelecting && DrawSelectionRectangleUsingGdi)
{
Rectangle rect = MakeSelectionRect(m_currentPoint, m_firstPoint);
ControlPaint.DrawReversibleFrame(rect, BackColor, FrameStyle.Dashed);
Expand Down
Loading

0 comments on commit a214783

Please sign in to comment.