Skip to content

Commit

Permalink
Merge pull request #2316 from cwensley/curtis/drawable-cell-upside-down
Browse files Browse the repository at this point in the history
Mac: Fix flipped graphics with DrawableCell
  • Loading branch information
cwensley authored Sep 20, 2022
2 parents 230762d + cb1aa7c commit 4c4d823
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 104 deletions.
2 changes: 1 addition & 1 deletion lib/monomac
Submodule monomac updated 1 files
+25 −0 src/appkit.cs
108 changes: 14 additions & 94 deletions src/Eto.Mac/Drawing/GraphicsHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ public class GraphicsHandler : GraphicsBase, Graphics.IHandler
#if OSX
NSGraphicsContext graphicsContext;
bool disposeContext;
readonly NSView view;
#endif
float height;
bool isOffset;
Expand Down Expand Up @@ -92,55 +91,13 @@ public GraphicsHandler()
}

#if OSX

public GraphicsHandler(NSView view)
{
this.view = view;
graphicsContext = NSGraphicsContext.FromWindow(view.Window);
graphicsContext = graphicsContext.IsFlipped ? graphicsContext : NSGraphicsContext.FromGraphicsPort(graphicsContext.GraphicsPortHandle, true);
disposeContext = true;
Control = graphicsContext.GraphicsPort;

view.PostsFrameChangedNotifications = true;
AddObserver(NSView.FrameChangedNotification, FrameDidChange, view);

// if control is in a scrollview, we need to trap when it's scrolled as well
var parent = view.Superview;
while (parent != null)
{
var scroll = parent as NSScrollView;
if (scroll != null)
{
scroll.ContentView.PostsBoundsChangedNotifications = true;
AddObserver(NSView.BoundsChangedNotification, FrameDidChange, scroll.ContentView);
}
parent = parent.Superview;
}

SetDefaults();
InitializeContext(view.IsFlipped);
}

static void FrameDidChange(ObserverActionEventArgs e)
{
var h = e.Handler as GraphicsHandler;
if (h != null && h.Control != null)
{
h.RewindAll();

h.Control.RestoreState();

h.InitializeContext(h.view.IsFlipped);
}
}

public GraphicsHandler(NSView view, NSGraphicsContext graphicsContext, float height, bool flipped)
public GraphicsHandler(NSView view, NSGraphicsContext graphicsContext, float height)
{
DisplayView = view;
this.height = height;
this.graphicsContext = flipped != graphicsContext.IsFlipped ? graphicsContext : NSGraphicsContext.FromGraphicsPort(graphicsContext.GraphicsPortHandle, true);
Control = this.graphicsContext.GraphicsPort;
SetDefaults();
var flipped = view?.IsFlipped ?? false;
this.graphicsContext = graphicsContext.IsFlipped ? graphicsContext : NSGraphicsContext.FromCGContext(graphicsContext.CGContext, true);
Control = this.graphicsContext.CGContext;
InitializeContext(!flipped);
}

Expand All @@ -152,8 +109,7 @@ public GraphicsHandler(NSView view, CGContext context, nfloat height)
this.height = (float)height;
this.Control = context;

SetDefaults();
InitializeContext(false);
InitializeContext(true);
}

protected override void Dispose(bool disposing)
Expand Down Expand Up @@ -238,9 +194,9 @@ public void CreateFromImage(Bitmap image)
graphicsContext = NSGraphicsContext.FromBitmap(rep);
}

graphicsContext = graphicsContext.IsFlipped ? graphicsContext : NSGraphicsContext.FromGraphicsPort(graphicsContext.GraphicsPortHandle, true);
graphicsContext = graphicsContext.IsFlipped ? graphicsContext : NSGraphicsContext.FromCGContext(graphicsContext.CGContext, true);
disposeContext = true;
Control = graphicsContext.GraphicsPort;
Control = graphicsContext.CGContext;
PointsPerPixel = (float)(rep.PixelsWide / handler.Control.Size.Width);
#elif IOS
var cgimage = handler.Control.CGImage;
Expand All @@ -249,7 +205,6 @@ public void CreateFromImage(Bitmap image)
#endif

height = image.Size.Height;
SetDefaults();
InitializeContext(true);
if (DrawingImage != null && SourceImage != null)
{
Expand All @@ -274,23 +229,7 @@ public void Flush()
#endif
}

#if OSX
public float ViewHeight
{
get { return (float)(view != null ? view.Bounds.Height : height); }
}
#elif IOS
public float ViewHeight
{
get { return height; }
}
#endif

void SetDefaults()
{
Control.InterpolationQuality = CGInterpolationQuality.Default;
Control.SetAllowsSubpixelPositioning(false);
}
public float ViewHeight => (float)height;

#if OSX
CGSize? phase;
Expand All @@ -316,36 +255,17 @@ public void SetPhase()
}
#endif

void InitializeContext(bool viewFlipped)
void InitializeContext(bool flipCoordinates)
{
Control.SaveState();
Control.InterpolationQuality = CGInterpolationQuality.Default;
Control.SetAllowsSubpixelPositioning(false);

#if OSX
// os x has different flipped states (depending on layers, etc), so compensate to make 0,0 at the top-left
if (view != null)
{
// we have a view (drawing directly to the screen), so adjust to where it is
Control.ClipToRect(view.ConvertRectToView(view.VisibleRect(), null));
var pos = view.ConvertPointToView(CGPoint.Empty, null);
if (!viewFlipped)
pos.Y += view.Frame.Height;
Control.ConcatCTM(new CGAffineTransform(1, 0, 0, -1, (float)pos.X, (float)pos.Y));
}
else
{
// drawing to a bitmap or during a drawRect operation
if (viewFlipped)
Control.ConcatCTM(new CGAffineTransform(1, 0, 0, -1, 0, ViewHeight));
}
if (flipCoordinates)
Control.ConcatCTM(new CGAffineTransform(1, 0, 0, -1, 0, ViewHeight));

#if OSX
phase = null;

#elif IOS
if (viewFlipped)
{
// on ios, we flip the context if we're drawing on a bitmap otherwise we don't need to
Control.ConcatCTM(new CGAffineTransform(1, 0, 0, -1, 0, ViewHeight));
}
#endif

ApplyAll();
Expand Down
8 changes: 4 additions & 4 deletions src/Eto.Mac/Forms/Cells/DrawableCellHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,13 @@ public override void DrawInteriorWithFrame(CGRect cellFrame, NSView inView)

if (DrawsBackground)
{
var context = nscontext.GraphicsPort;
var context = nscontext.CGContext;
context.SetFillColor(BackgroundColor.ToCG());
context.FillRect(cellFrame);
}

var handler = Handler;
var graphicsHandler = new GraphicsHandler(null, nscontext, (float)cellFrame.Height, flipped: true);
var graphicsHandler = new GraphicsHandler(inView, nscontext, (float)cellFrame.Height);
using (var graphics = new Graphics(graphicsHandler))
{
var state = Highlighted ? CellStates.Selected : CellStates.None;
Expand Down Expand Up @@ -162,7 +162,7 @@ public override void DrawRect(CGRect dirtyRect)

if (DrawsBackground)
{
var context = nscontext.GraphicsPort;
var context = nscontext.CGContext;
context.SetFillColor(BackgroundColor.ToCG());
context.FillRect(dirtyRect);
}
Expand All @@ -171,7 +171,7 @@ public override void DrawRect(CGRect dirtyRect)
var handler = Handler;
if (handler == null)
return;
var graphicsHandler = new GraphicsHandler(null, nscontext, (float)cellFrame.Height, flipped: true);
var graphicsHandler = new GraphicsHandler(this, nscontext, (float)cellFrame.Height);
using (var graphics = new Graphics(graphicsHandler))
{
var rowView = this.Superview as NSTableRowView;
Expand Down
11 changes: 7 additions & 4 deletions src/Eto.Mac/Forms/Controls/DrawableHandler.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using Eto.Drawing;
using Eto.Forms;
using Eto.Mac.Drawing;
Expand All @@ -9,9 +10,9 @@ public class DrawableHandler : MacPanel<DrawableHandler.EtoDrawableView, Drawabl
Brush backgroundBrush;
Color backgroundColor;

public bool SupportsCreateGraphics { get { return true; } }
public bool SupportsCreateGraphics => false;

public override NSView ContainerControl { get { return Control; } }
public override NSView ContainerControl => Control;

public class EtoDrawableView : MacPanelView
{
Expand All @@ -33,6 +34,8 @@ public override void DrawRect(CGRect dirtyRect)
ApplicationHandler.QueueResizing = false;
}

// public override bool IsFlipped => true; // uncomment to test flipped views with GraphicsHandler.

public bool CanFocus { get; set; }

public override bool AcceptsFirstResponder() => CanFocus;
Expand All @@ -52,7 +55,7 @@ public override NSView HitTest(CGPoint aPoint)

public Graphics CreateGraphics()
{
return new Graphics(new GraphicsHandler(Control));
throw new NotSupportedException();
}

public override Color BackgroundColor
Expand Down Expand Up @@ -111,7 +114,7 @@ void DrawRegion(Rectangle rect)
var context = NSGraphicsContext.CurrentContext;
if (context != null)
{
var handler = new GraphicsHandler(Control, context, (float)Control.Frame.Height, Control.IsFlipped);
var handler = new GraphicsHandler(Control, context, (float)Control.Frame.Height);
using (var graphics = new Graphics(handler))
{
if (backgroundBrush != null)
Expand Down
2 changes: 1 addition & 1 deletion src/Eto.Mac/Forms/Printing/PrintDocumentHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public override void DrawRect(CGRect dirtyRect)
var height = Frame.Height;
var pageRect = RectForPage(operation.CurrentPage);

using (var graphics = new Graphics(new GraphicsHandler(this, context, (float)height, IsFlipped)))
using (var graphics = new Graphics(new GraphicsHandler(this, context, (float)height)))
{
graphics.TranslateTransform((float)pageRect.X, (float)(height-pageRect.Y-pageRect.Height));
Handler.Callback.OnPrintPage(Handler.Widget, new PrintPageEventArgs(graphics, operation.PrintInfo.ImageablePageBounds.Size.ToEto(), (int)operation.CurrentPage - 1));
Expand Down

0 comments on commit 4c4d823

Please sign in to comment.