Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #41 from don-mccomb/bug1074822_PBrushCursorAlignment

[Fixes bug #1074822] Fix alignment of tool cursors.
  • Loading branch information...
commit 0fbf668ac6ff76a7c50571919e085cc539fb7f46 2 parents 34f4e9e + bb86fd6
@cameronwhite cameronwhite authored
View
181 Pinta.Core/Classes/BaseTool.cs
@@ -27,6 +27,7 @@
using System;
using Cairo;
using Gtk;
+using Gdk;
using System.IO;
using Mono.Unix;
using Mono.Addins;
@@ -40,7 +41,7 @@ public abstract class BaseTool
{
protected const int DEFAULT_BRUSH_WIDTH = 2;
- protected static Point point_empty = new Point (-500, -500);
+ protected static Cairo.Point point_empty = new Cairo.Point (-500, -500);
protected ToggleToolButton tool_item;
protected ToolItem tool_label;
@@ -251,7 +252,7 @@ protected virtual void OnDeactivated ()
protected virtual ToggleToolButton CreateToolButton ()
{
- Image i2 = new Image (PintaCore.Resources.GetIcon (Icon));
+ Gtk.Image i2 = new Gtk.Image (PintaCore.Resources.GetIcon (Icon));
i2.Show ();
ToggleToolButton tool_item = new ToggleToolButton ();
@@ -273,132 +274,88 @@ public void SetCursor (Gdk.Cursor cursor)
}
/// <summary>
- /// Create a cursor icon with an ellipse that visually represents the tool's thickness.
+ /// Create a cursor icon with a shape that visually represents the tool's thickness.
/// </summary>
- /// <param name="name">A string containing the name of the tool's icon to use.</param>
- /// <param name="brushWidth">The current thickness of the tool.</param>
- /// <param name="cursorWidth">The width of the tool's icon.</param>
- /// <param name="cursorHeight">The height of the tool's icon.</param>
- /// <param name="cursorOffsetX">The X position in the tool's icon where the center of the affected area will be.</param>
- /// <param name="cursorOffsetY">The Y position in the tool's icon where the center of the affected area will be.</param>
- /// <param name="ellipseColor1">The inner color of the ellipse.</param>
- /// <param name="ellipseColor2">The outer color of the ellipse.</param>
- /// <param name="ellipseThickness">The thickness of the ellipse that will be drawn.</param>
- /// <param name="iconOffsetX">The X position in the returned Pixbuf that will be the center of the new cursor icon.</param>
- /// <param name="iconOffsetY">The Y position in the returned Pixbuf that will be the center of the new cursor icon.</param>
- /// <returns>The new cursor icon with an ellipse that represents the tool's thickness.</returns>
- protected Gdk.Pixbuf CreateEllipticalThicknessIcon(string name, int brushWidth, int cursorWidth, int cursorHeight,
- int cursorOffsetX, int cursorOffsetY, Color ellipseColor1,
- Color ellipseColor2, int ellipseThickness,
- out int iconOffsetX, out int iconOffsetY)
- {
- double zoom = 1d;
-
- if (PintaCore.Workspace.HasOpenDocuments)
- {
- zoom = Math.Min(30d, PintaCore.Workspace.ActiveDocument.Workspace.Scale);
- }
-
- brushWidth = (int)Math.Min(800d, ((double)brushWidth) * zoom);
- cursorWidth = (int)((double)cursorWidth * zoom);
- cursorHeight = (int)((double)cursorHeight * zoom);
-
-
- int halfOfEllipseThickness = (int)Math.Ceiling(ellipseThickness / 2d);
- int halfOfBrushWidth = brushWidth / 2;
-
- int iconWidth = Math.Max(cursorWidth + cursorOffsetX + halfOfBrushWidth + halfOfEllipseThickness,
- brushWidth + ellipseThickness + (int)(16d / zoom));
- int iconHeight = Math.Max(cursorHeight + cursorOffsetY + halfOfBrushWidth + halfOfEllipseThickness,
- brushWidth + ellipseThickness + (int)(16d / zoom));
-
- iconOffsetX = Math.Max(cursorOffsetX, halfOfBrushWidth + halfOfEllipseThickness);
- iconOffsetY = Math.Max(cursorOffsetY, halfOfBrushWidth + halfOfEllipseThickness);
+ /// <param name="imgName">A string containing the name of the tool's icon image to use.</param>
+ /// <param name="shape">The shape to draw.</param>
+ /// <param name="shapeWidth">The width of the shape.</param>
+ /// <param name="imgToShapeX">The horizontal distance between the image's top-left corner and the shape center.</param>
+ /// <param name="imgToShapeX">The verical distance between the image's top-left corner and the shape center.</param>
+ /// <param name="shapeX">The X position in the returned Pixbuf that will be the center of the shape.</param>
+ /// <param name="shapeY">The Y position in the returned Pixbuf that will be the center of the shape.</param>
+ /// <returns>The new cursor icon with an shape that represents the tool's thickness.</returns>
+ protected Gdk.Pixbuf CreateIconWithShape(string imgName, CursorShape shape, int shapeWidth,
+ int imgToShapeX, int imgToShapeY,
+ out int shapeX, out int shapeY)
+ {
+ Gdk.Pixbuf img = PintaCore.Resources.GetIcon(imgName);
- ImageSurface i = new ImageSurface(Format.ARGB32, iconWidth, iconHeight);
-
- using (Context g = new Context(i))
- {
- g.DrawEllipse(new Rectangle(iconOffsetX - halfOfBrushWidth,
- iconOffsetY - halfOfBrushWidth,
- brushWidth,
- brushWidth),
- ellipseColor2, ellipseThickness);
-
- g.DrawEllipse(new Rectangle(iconOffsetX - halfOfBrushWidth + ellipseThickness,
- iconOffsetY - halfOfBrushWidth + ellipseThickness,
- brushWidth - ellipseThickness - 1,
- brushWidth - ellipseThickness - 1),
- ellipseColor1, ellipseThickness);
-
- g.DrawPixbuf(PintaCore.Resources.GetIcon(name),
- new Point(iconOffsetX - cursorOffsetX, iconOffsetY - cursorOffsetY));
- }
-
- return CairoExtensions.ToPixbuf(i);
- }
-
- /// <summary>
- /// Create a cursor icon with an rectangle that visually represents the tool's thickness.
- /// </summary>
- /// <param name="name">A string containing the name of the tool's icon to use.</param>
- /// <param name="brushWidth">The current thickness of the tool.</param>
- /// <param name="cursorWidth">The width of the tool's icon.</param>
- /// <param name="cursorHeight">The height of the tool's icon.</param>
- /// <param name="cursorOffsetX">The X position in the tool's icon where the center of the affected area will be.</param>
- /// <param name="cursorOffsetY">The Y position in the tool's icon where the center of the affected area will be.</param>
- /// <param name="rectangleColor1">The inner color of the rectangle.</param>
- /// <param name="rectangleColor2">The outer color of the rectangle.</param>
- /// <param name="rectangleThickness">The thickness of the rectangle that will be drawn.</param>
- /// <param name="iconOffsetX">The X position in the returned Pixbuf that will be the center of the new cursor icon.</param>
- /// <param name="iconOffsetY">The Y position in the returned Pixbuf that will be the center of the new cursor icon.</param>
- /// <returns>The new cursor icon with an rectangle that represents the tool's thickness.</returns>
- protected Gdk.Pixbuf CreateRectangularThicknessIcon(string name, int brushWidth, int cursorWidth, int cursorHeight,
- int cursorOffsetX, int cursorOffsetY, Color rectangleColor1,
- Color rectangleColor2, int rectangleThickness,
- out int iconOffsetX, out int iconOffsetY)
- {
double zoom = 1d;
-
if (PintaCore.Workspace.HasOpenDocuments)
{
zoom = Math.Min(30d, PintaCore.Workspace.ActiveDocument.Workspace.Scale);
}
- brushWidth = (int)Math.Min(800d, ((double)brushWidth) * zoom);
- cursorWidth = (int)((double)cursorWidth * zoom);
- cursorHeight = (int)((double)cursorHeight * zoom);
+ shapeWidth = (int)Math.Min(800d, ((double)shapeWidth) * zoom);
+ int halfOfShapeWidth = shapeWidth / 2;
+ // Calculate bounding boxes around the both image and shape
+ // relative to the image top-left corner.
+ Gdk.Rectangle imgBBox = new Gdk.Rectangle(0, 0, img.Width, img.Height);
+ Gdk.Rectangle shapeBBox = new Gdk.Rectangle(
+ imgToShapeX - halfOfShapeWidth,
+ imgToShapeY - halfOfShapeWidth,
+ shapeWidth,
+ shapeWidth);
- int halfOfRectangleThickness = (int)Math.Ceiling(rectangleThickness / 2d);
- int halfOfBrushWidth = brushWidth / 2;
+ // Inflate shape bounding box to allow for anti-aliasing
+ shapeBBox.Inflate(2, 2);
- int iconWidth = Math.Max(cursorWidth + cursorOffsetX + halfOfBrushWidth + halfOfRectangleThickness,
- brushWidth + rectangleThickness + (int)(16d / zoom));
- int iconHeight = Math.Max(cursorHeight + cursorOffsetY + halfOfBrushWidth + halfOfRectangleThickness,
- brushWidth + rectangleThickness + (int)(16d / zoom));
+ // To determine required size of icon,
+ // find union of the image and shape bounding boxes
+ // (still relative to image top-left corner)
+ Gdk.Rectangle iconBBox = imgBBox.Union (shapeBBox);
- iconOffsetX = Math.Max(cursorOffsetX, halfOfBrushWidth + halfOfRectangleThickness);
- iconOffsetY = Math.Max(cursorOffsetY, halfOfBrushWidth + halfOfRectangleThickness);
+ // Image top-left corner in icon co-ordinates
+ int imgX = imgBBox.Left - iconBBox.Left;
+ int imgY = imgBBox.Top - iconBBox.Top;
- ImageSurface i = new ImageSurface(Format.ARGB32, iconWidth, iconHeight);
+ // Shape center point in icon co-ordinates
+ shapeX = imgToShapeX - iconBBox.Left;
+ shapeY = imgToShapeY - iconBBox.Top;
+ ImageSurface i = new ImageSurface(Format.ARGB32, iconBBox.Width, iconBBox.Height);
using (Context g = new Context(i))
{
- g.DrawRectangle(new Rectangle(iconOffsetX - halfOfBrushWidth,
- iconOffsetY - halfOfBrushWidth,
- brushWidth,
- brushWidth),
- rectangleColor2, rectangleThickness);
-
- g.DrawRectangle(new Rectangle(iconOffsetX - halfOfBrushWidth + rectangleThickness,
- iconOffsetY - halfOfBrushWidth + rectangleThickness,
- brushWidth - rectangleThickness - 1,
- brushWidth - rectangleThickness - 1),
- rectangleColor1, rectangleThickness);
-
- g.DrawPixbuf(PintaCore.Resources.GetIcon(name),
- new Point(iconOffsetX - cursorOffsetX, iconOffsetY - cursorOffsetY));
+ // Don't show shape if shapeWidth less than 3,
+ if (shapeWidth > 3)
+ {
+ int diam = Math.Max (1, shapeWidth - 2);
+ Cairo.Rectangle shapeRect = new Cairo.Rectangle(shapeX - halfOfShapeWidth,
+ shapeY - halfOfShapeWidth,
+ diam,
+ diam);
+
+ Cairo.Color outerColor = new Cairo.Color (255, 255, 255, 0.5);
+ Cairo.Color innerColor = new Cairo.Color (0, 0, 0);
+
+ switch (shape)
+ {
+ case CursorShape.Ellipse:
+ g.DrawEllipse(shapeRect, outerColor, 1);
+ shapeRect = shapeRect.Inflate (-1, -1);
+ g.DrawEllipse(shapeRect, innerColor, 1);
+ break;
+ case CursorShape.Rectangle:
+ g.DrawRectangle(shapeRect, outerColor, 1);
+ shapeRect = shapeRect.Inflate (-1, -1);
+ g.DrawRectangle(shapeRect, innerColor, 1);
+ break;
+ }
+ }
+
+ // Draw the image
+ g.DrawPixbuf(img, new Cairo.Point(imgX, imgY));
}
return CairoExtensions.ToPixbuf(i);
View
36 Pinta.Core/Enumerations/CursorShape.cs
@@ -0,0 +1,36 @@
+//
+// CursorShape.cs
+//
+// Author:
+// Don McComb <don.mccomb@gmail.com>
+//
+// Copyright (c) 2012 Don McComb
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+
+namespace Pinta.Core
+{
+ public enum CursorShape
+ {
+ Ellipse,
+ Rectangle
+ }
+}
+
View
22 Pinta.Core/Extensions/CairoExtensions.cs
@@ -49,7 +49,7 @@ public static Rectangle DrawRectangle (this Context g, Rectangle r, Color color,
{
// Put it on a pixel line
if (lineWidth == 1)
- r = new Rectangle (r.X - 0.5, r.Y - 0.5, r.Width, r.Height);
+ r = new Rectangle (r.X + 0.5, r.Y + 0.5, r.Width-1, r.Height-1);
g.Save ();
@@ -456,8 +456,10 @@ public static void QuadraticCurveTo (this Context g, double x1, double y1, doubl
public static Rectangle DrawLine (this Context g, PointD p1, PointD p2, Color color, int lineWidth)
{
// Put it on a pixel line
- if (lineWidth == 1)
- p1 = new PointD (p1.X - 0.5, p1.Y - 0.5);
+ if (lineWidth == 1){
+ p1 = new PointD (p1.X + 0.5, p1.Y + 0.5);
+ p2 = new PointD (p2.X + 0.5, p2.Y + 0.5);
+ }
g.Save ();
@@ -900,6 +902,20 @@ public static double GetRight (this Rectangle rect)
}
/// <summary>
+ /// Creates a copy of the rectangle but with the side edges
+ /// moved out from the center by dx, and the top and bottom
+ /// edges moved out from the center by dy. Edges are moved
+ /// inwards when dx or dy are negative.
+ /// </summary>
+ /// <param name="dx">Dist to move sides from center.</param>
+ /// <param name="dy">Dist to move top & botom from center.</param>
+ /// <returns>The inflated (or deflated) rectangle.</returns>
+ public static Rectangle Inflate (this Rectangle rect, int dx, int dy)
+ {
+ return new Rectangle(rect.X - dx, rect.Y - dy, rect.Width + 2 * dx, rect.Height + 2 * dy);
+ }
+
+ /// <summary>
/// Determines if the requested pixel coordinate is within bounds.
/// </summary>
/// <param name="x">The x coordinate.</param>
View
29 Pinta.Core/Pinta.Core.csproj
@@ -54,23 +54,9 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
- <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
- <Package>gtk-sharp-2.0</Package>
- </Reference>
- <Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
- <Package>gtk-sharp-2.0</Package>
- </Reference>
+ <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
<Reference Include="System.Core" />
- <Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
- <Package>glib-sharp-2.0</Package>
- </Reference>
- <Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
- <Package>gtk-sharp-2.0</Package>
- </Reference>
<Reference Include="Mono.Posix" />
- <Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
- <Package>gtk-sharp-2.0</Package>
- </Reference>
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Mono.Cairo" />
@@ -80,6 +66,18 @@
<Reference Include="ICSharpCode.SharpZipLib">
<HintPath>..\lib\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference>
+ <Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
+ <Private>False</Private>
+ </Reference>
+ <Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
+ <Private>False</Private>
+ </Reference>
+ <Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
+ <Private>False</Private>
+ </Reference>
+ <Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
+ <Private>False</Private>
+ </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Actions\WindowActions.cs" />
@@ -211,6 +209,7 @@
<Compile Include="Widgets\ToolBarDropDownButton.cs" />
<Compile Include="Clipper\Clipper.cs" />
<Compile Include="Actions\AddinActions.cs" />
+ <Compile Include="Enumerations\CursorShape.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
View
6 Pinta.Gui.Widgets/Widgets/Canvas/PintaCanvas.cs
@@ -120,9 +120,9 @@ protected override bool OnExposeEvent (EventExpose e)
using (Cairo.Context g = CairoHelper.Create (GdkWindow)) {
// Draw our canvas drop shadow
- g.DrawRectangle (new Cairo.Rectangle (x, y, PintaCore.Workspace.CanvasSize.Width + 1, PintaCore.Workspace.CanvasSize.Height + 1), new Cairo.Color (.5, .5, .5), 1);
- g.DrawRectangle (new Cairo.Rectangle (x - 1, y - 1, PintaCore.Workspace.CanvasSize.Width + 3, PintaCore.Workspace.CanvasSize.Height + 3), new Cairo.Color (.8, .8, .8), 1);
- g.DrawRectangle (new Cairo.Rectangle (x - 2, y - 2, PintaCore.Workspace.CanvasSize.Width + 5, PintaCore.Workspace.CanvasSize.Height + 5), new Cairo.Color (.9, .9, .9), 1);
+ g.DrawRectangle (new Cairo.Rectangle (x - 1, y - 1, PintaCore.Workspace.CanvasSize.Width + 2, PintaCore.Workspace.CanvasSize.Height + 2), new Cairo.Color (.5, .5, .5), 1);
+ g.DrawRectangle (new Cairo.Rectangle (x - 2, y - 2, PintaCore.Workspace.CanvasSize.Width + 4, PintaCore.Workspace.CanvasSize.Height + 4), new Cairo.Color (.8, .8, .8), 1);
+ g.DrawRectangle (new Cairo.Rectangle (x - 3, y - 3, PintaCore.Workspace.CanvasSize.Width + 6, PintaCore.Workspace.CanvasSize.Height + 6), new Cairo.Color (.9, .9, .9), 1);
// Set up our clip rectangle
g.Rectangle (new Cairo.Rectangle (x, y, PintaCore.Workspace.CanvasSize.Width, PintaCore.Workspace.CanvasSize.Height));
View
6 Pinta.Tools/Tools/CloneStampTool.cs
@@ -49,9 +49,9 @@ public class CloneStampTool : BaseBrushTool
public override Gdk.Cursor DefaultCursor {
get {
int iconOffsetX, iconOffsetY;
- var icon = CreateEllipticalThicknessIcon ("Cursor.CloneStamp.png", BrushWidth, 16, 16, 6, 11,
- new Cairo.Color (0, 0, 0), new Cairo.Color (255, 255, 255, .5d), 1,
- out iconOffsetX, out iconOffsetY);
+ var icon = CreateIconWithShape ("Cursor.CloneStamp.png",
+ CursorShape.Ellipse, BrushWidth, 6, 11,
+ out iconOffsetX, out iconOffsetY);
return new Gdk.Cursor (PintaCore.Chrome.Canvas.Display, icon, iconOffsetX, iconOffsetY);
}
}
View
8 Pinta.Tools/Tools/ColorPickerTool.cs
@@ -1,4 +1,4 @@
-//
+//
// ColorPickerTool.cs
//
// Author:
@@ -72,9 +72,9 @@ public ColorPickerTool ()
public override Gdk.Cursor DefaultCursor {
get {
int iconOffsetX, iconOffsetY;
- var icon = CreateRectangularThicknessIcon ("Cursor.ColorPicker.png", SampleSize, 16, 16, 1, 16,
- new Cairo.Color (0, 0, 0), new Cairo.Color (255, 255, 255, .5d), 1,
- out iconOffsetX, out iconOffsetY);
+ var icon = CreateIconWithShape ("Cursor.ColorPicker.png",
+ CursorShape.Rectangle, SampleSize, 1, 16,
+ out iconOffsetX, out iconOffsetY);
return new Gdk.Cursor (PintaCore.Chrome.Canvas.Display, icon, iconOffsetX, iconOffsetY);
}
}
View
6 Pinta.Tools/Tools/EraserTool.cs
@@ -56,9 +56,9 @@ protected override void OnBuildToolBar(Toolbar tb)
public override Gdk.Cursor DefaultCursor {
get {
int iconOffsetX, iconOffsetY;
- var icon = CreateEllipticalThicknessIcon ("Tools.Eraser.png", BrushWidth, 16, 16, 0, 14,
- new Cairo.Color (0, 0, 0), new Cairo.Color (255, 255, 255, .5d), 1,
- out iconOffsetX, out iconOffsetY);
+ var icon = CreateIconWithShape ("Tools.Eraser.png",
+ CursorShape.Ellipse, BrushWidth, 0, 14,
+ out iconOffsetX, out iconOffsetY);
return new Gdk.Cursor (PintaCore.Chrome.Canvas.Display, icon, iconOffsetX, iconOffsetY);
}
}
View
6 Pinta.Tools/Tools/PaintBrushTool.cs
@@ -44,9 +44,9 @@ public class PaintBrushTool : BaseBrushTool
public override Gdk.Cursor DefaultCursor {
get {
int iconOffsetX, iconOffsetY;
- var icon = CreateEllipticalThicknessIcon ("Tools.Paintbrush.png", BrushWidth, 16, 16, 0, 16,
- new Cairo.Color (0, 0, 0), new Cairo.Color (255, 255, 255, .5d), 1,
- out iconOffsetX, out iconOffsetY);
+ var icon = CreateIconWithShape ("Tools.Paintbrush.png",
+ CursorShape.Ellipse, BrushWidth, 0, 16,
+ out iconOffsetX, out iconOffsetY);
return new Gdk.Cursor (PintaCore.Chrome.Canvas.Display, icon, iconOffsetX, iconOffsetY);
}
}
View
1  Pinta.Tools/Tools/TextTool.cs
@@ -599,6 +599,7 @@ protected override void OnMouseDown(DrawingArea canvas, ButtonPressEventArgs arg
// Start editing at the cursor location
clickPoint = pt;
CurrentTextEngine.Clear();
+ clickPoint.Offset (0, -CurrentTextEngine.FontHeight/2);
CurrentTextEngine.Origin = clickPoint;
StartEditing();
RedrawText(true, true);
Please sign in to comment.
Something went wrong with that request. Please try again.