Removed the NSScrollView-based uIArea on OS X. We'll stick with our custom one.

This commit is contained in:
Pietro Gagliardi 2015-09-11 21:25:38 -04:00
parent 848eff27e7
commit d570440a9b
5 changed files with 0 additions and 603 deletions

View File

@ -1,12 +0,0 @@
// 8 september 2015
#import <Cocoa/Cocoa.h>
#import <stdint.h>
#import "ui.h"
extern uiArea *newArea(uiAreaHandler *ah);
extern uiDrawContext *newContext(CGContextRef);
extern NSView *areaView(uiArea *);
extern void areaUpdateScroll(uiArea *);

View File

@ -1,127 +0,0 @@
// 9 september 2015
#include "area.h"
// model:
// - drawing and events happen to the NSClipView
// - the document view is only used for scroll extents
@interface areaClipView : NSClipView {
uiArea *libui_a;
uiAreaHandler *libui_ah;
}
- (id)initWithFrame:(NSRect)r area:(uiArea *)a areaHandler:(uiAreaHandler *)ah;
@end
@interface areaDocumentView : NSView
@end
struct uiArea {
// uiDarwinControl c;
NSScrollView *view;
areaClipView *clipView;
areaDocumentView *documentView;
uiAreaHandler *ah;
};
@implementation areaClipView
- (id)initWithFrame:(NSRect)r area:(uiArea *)a areaHandler:(uiAreaHandler *)ah
{
self = [super initWithFrame:r];
if (self) {
self->libui_a = a;
self->libui_ah = ah;
}
return self;
}
- (void)drawRect:(NSRect)r
{
CGContextRef c;
uiAreaDrawParams dp;
[super drawRect:r];
c = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
dp.Context = newContext(c);
dp.ClientWidth = [self frame].size.width;
dp.ClientHeight = [self frame].size.height;
dp.ClipX = r.origin.x;
dp.ClipY = r.origin.y;
dp.ClipWidth = r.size.width;
dp.ClipHeight = r.size.height;
// TODO DPI
// TODO scroll position
(*(self->libui_ah->Draw))(self->libui_ah, self->libui_a, &dp);
}
- (BOOL)isFlipped
{
return YES;
}
// see http://stackoverflow.com/questions/11318987/black-background-when-overriding-drawrect-in-uiscrollview (for iOS but same idea)
// TODO there has to be a better way to set this; how does OS X do it for its default clip view?
/*- (BOOL)isOpaque
{
return NO;
}*/
@end
@implementation areaDocumentView
- (BOOL)isFlipped
{
return YES;
}
@end
uiArea *newArea(uiAreaHandler *ah)
{
uiArea *a;
// TODO
a = (uiArea *) malloc(sizeof (uiArea));
a->ah = ah;
a->view = [[NSScrollView alloc] initWithFrame:NSZeroRect];
a->clipView = [[areaClipView alloc] initWithFrame:NSZeroRect area:a areaHandler:ah];
a->documentView = [[areaDocumentView alloc] initWithFrame:NSZeroRect];
[a->view setContentView:a->clipView];
[a->view setDocumentView:a->documentView];
// TODO set up scroll view
// for some reason, without this line, NSLayoutConstraints complains about internal limits being exceeded
[a->view setDrawsBackground:YES];
//TODO [a->view setBackgroundColor:[NSColor controlColor]];
// set initial state
// TODO do this on other platforms?
areaUpdateScroll(a);
return a;
}
NSView *areaView(uiArea *a)
{
return a->view;
}
void areaUpdateScroll(uiArea *a)
{
NSRect frame;
frame.origin = NSMakePoint(0, 0);
frame.size.width = (*(a->ah->HScrollMax))(a->ah, a);
frame.size.height = (*(a->ah->VScrollMax))(a->ah, a);
[a->documentView setFrame:frame];
}

View File

@ -1,148 +0,0 @@
// 6 september 2015
#include "area.h"
// TODO some pixel thick lines aren't actually pixel thick
struct uiDrawContext {
CGContextRef c;
BOOL useRGBA;
CGFloat r;
CGFloat g;
CGFloat b;
CGFloat a;
};
uiDrawContext *newContext(CGContextRef ctxt)
{
uiDrawContext *c;
// TODO use uiNew
c = (uiDrawContext *) malloc(sizeof (uiDrawContext));
c->c = ctxt;
return c;
}
void uiDrawBeginPathRGB(uiDrawContext *c, uint8_t r, uint8_t g, uint8_t b)
{
c->useRGBA = YES;
c->r = ((CGFloat) r) / 255;
c->g = ((CGFloat) g) / 255;
c->b = ((CGFloat) b) / 255;
c->a = 1.0;
CGContextBeginPath(c->c);
}
void uiDrawBeginPathRGBA(uiDrawContext *c, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{
c->useRGBA = YES;
c->r = ((CGFloat) r) / 255;
c->g = ((CGFloat) g) / 255;
c->b = ((CGFloat) b) / 255;
c->a = ((CGFloat) a) / 255;
CGContextBeginPath(c->c);
}
// TODO 0.25 for retina? some say yes, some say no
// TODO same adjustment for cairo
#define topoint(x) (((CGFloat) x) + 0.5)
void uiDrawMoveTo(uiDrawContext *c, intmax_t x, intmax_t y)
{
CGContextMoveToPoint(c->c, topoint(x), topoint(y));
}
void uiDrawLineTo(uiDrawContext *c, intmax_t x, intmax_t y)
{
CGContextAddLineToPoint(c->c, topoint(x), topoint(y));
}
// TODO width-1/height-1? (also for cairo)
void uiDrawRectangle(uiDrawContext *c, intmax_t x, intmax_t y, intmax_t width, intmax_t height)
{
CGContextAddRect(c->c, CGRectMake(topoint(x), topoint(y), width, height));
}
void uiDrawArcTo(uiDrawContext *c, intmax_t xCenter, intmax_t yCenter, intmax_t radius, double startAngle, double endAngle, int lineFromCurrentPointToStart)
{
if (!lineFromCurrentPointToStart) {
// see http://stackoverflow.com/questions/31489157/extra-line-when-drawing-an-arc-in-swift
// TODO verify correctness
CGFloat x, y;
x = topoint(xCenter);
y = topoint(yCenter);
x += radius * cos(startAngle);
y -= radius * sin(startAngle);
CGContextMoveToPoint(c->c, x, y);
}
CGContextAddArc(c->c,
topoint(xCenter), topoint(yCenter),
radius,
startAngle, endAngle,
0);
}
void uiDrawBezierTo(uiDrawContext *c, intmax_t c1x, intmax_t c1y, intmax_t c2x, intmax_t c2y, intmax_t endX, intmax_t endY)
{
CGContextAddCurveToPoint(c->c,
topoint(c1x), topoint(c1y),
topoint(c2x), topoint(c2y),
topoint(endX), topoint(endY));
}
void uiDrawCloseFigure(uiDrawContext *c)
{
CGContextClosePath(c->c);
}
void uiDrawStroke(uiDrawContext *c, uiDrawStrokeParams *p)
{
switch (p->Cap) {
case uiDrawLineCapFlat:
CGContextSetLineCap(c->c, kCGLineCapButt);
break;
case uiDrawLineCapRound:
CGContextSetLineCap(c->c, kCGLineCapRound);
break;
case uiDrawLineCapSquare:
CGContextSetLineCap(c->c, kCGLineCapSquare);
break;
}
switch (p->Join) {
case uiDrawLineJoinMiter:
CGContextSetLineJoin(c->c, kCGLineJoinMiter);
CGContextSetMiterLimit(c->c, p->MiterLimit);
break;
case uiDrawLineJoinRound:
CGContextSetLineJoin(c->c, kCGLineJoinRound);
break;
case uiDrawLineJoinBevel:
CGContextSetLineJoin(c->c, kCGLineJoinBevel);
break;
}
CGContextSetLineWidth(c->c, p->Thickness);
if (c->useRGBA)
CGContextSetRGBStrokeColor(c->c, c->r, c->g, c->b, c->a);
else {
// TODO
}
CGContextStrokePath(c->c);
}
void uiDrawFill(uiDrawContext *c, uiDrawFillMode mode)
{
if (c->useRGBA)
CGContextSetRGBFillColor(c->c, c->r, c->g, c->b, c->a);
else {
// TODO
}
switch (mode) {
case uiDrawFillModeWinding:
CGContextFillPath(c->c);
break;
case uiDrawFillModeAlternate:
CGContextEOFillPath(c->c);
break;
}
}

View File

@ -1,177 +0,0 @@
// 4 september 2015
#define _GNU_SOURCE
#include "area.h"
#include <math.h>
// #qo LDFLAGS: -framework Foundation -framework AppKit -framework CoreGraphics
struct handler {
uiAreaHandler ah;
};
static uiArea *area;
static struct handler h;
//static NSTextField *nhspinb;
//static NSTextField *nvspinb;
static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *p)
{
uiDrawStrokeParams sp;
uiDrawBeginPathRGB(p->Context, 0xFF, 0x00, 0x00);
uiDrawMoveTo(p->Context, p->ClipX + 5, p->ClipY + 5);
uiDrawLineTo(p->Context, (p->ClipX + p->ClipWidth) - 5, (p->ClipY + p->ClipHeight) - 5);
sp.Cap = uiDrawLineCapFlat;
sp.Join = uiDrawLineJoinMiter;
sp.Thickness = 1;
sp.MiterLimit = uiDrawDefaultMiterLimit;
uiDrawStroke(p->Context, &sp);
uiDrawBeginPathRGB(p->Context, 0x00, 0x00, 0xC0);
uiDrawMoveTo(p->Context, p->ClipX, p->ClipY);
uiDrawLineTo(p->Context, p->ClipX + p->ClipWidth, p->ClipY);
uiDrawLineTo(p->Context, 50, 150);
uiDrawLineTo(p->Context, 50, 50);
uiDrawCloseFigure(p->Context);
sp.Cap = uiDrawLineCapFlat;
sp.Join = uiDrawLineJoinRound;
sp.Thickness = 5;
uiDrawStroke(p->Context, &sp);
uiDrawBeginPathRGBA(p->Context, 0x00, 0xC0, 0x00, 0x80);
uiDrawRectangle(p->Context, 120, 80, 50, 50);
uiDrawFill(p->Context, uiDrawFillModeWinding);
uiDrawBeginPathRGB(p->Context, 0x00, 0x80, 0x00);
uiDrawMoveTo(p->Context, 5, 10);
uiDrawLineTo(p->Context, 5, 50);
sp.Cap = uiDrawLineCapFlat;
sp.Join = uiDrawLineJoinMiter;
sp.Thickness = 1;
sp.MiterLimit = uiDrawDefaultMiterLimit;
uiDrawStroke(p->Context, &sp);
uiDrawBeginPathRGB(p->Context, 0x80, 0xC0, 0x00);
uiDrawMoveTo(p->Context, 400, 100);
uiDrawArcTo(p->Context,
400, 100,
50,
30. * (M_PI / 180.),
// note the end angle here
// in GDI, the second angle to AngleArc() is relative to the start, not to 0
330. * (M_PI / 180.),
1);
// TODO add a checkbox for this
uiDrawLineTo(p->Context, 400, 100);
uiDrawArcTo(p->Context,
510, 100,
50,
30. * (M_PI / 180.),
330. * (M_PI / 180.),
0);
uiDrawCloseFigure(p->Context);
sp.Cap = uiDrawLineCapFlat;
sp.Join = uiDrawLineJoinMiter;
sp.Thickness = 1;
sp.MiterLimit = uiDrawDefaultMiterLimit;
uiDrawStroke(p->Context, &sp);
uiDrawBeginPathRGB(p->Context, 0x00, 0x80, 0xC0);
uiDrawMoveTo(p->Context, 300, 300);
uiDrawBezierTo(p->Context,
350, 320,
310, 390,
435, 372);
sp.Cap = uiDrawLineCapFlat;
sp.Join = uiDrawLineJoinMiter;
sp.Thickness = 1;
sp.MiterLimit = uiDrawDefaultMiterLimit;
uiDrawStroke(p->Context, &sp);
}
static uintmax_t handlerHScrollMax(uiAreaHandler *a, uiArea *area)
{/* TODO
WCHAR c[50];
GetWindowTextW(nhspinb, c, 50);
return _wtoi(c);
*/}
static uintmax_t handlerVScrollMax(uiAreaHandler *a, uiArea *area)
{/* TODO
WCHAR c[50];
GetWindowTextW(nvspinb, c, 50);
return _wtoi(c);
*/}
static int handlerRedrawOnResize(uiAreaHandler *a, uiArea *area)
{
return 1;
}
// areaUpdateScroll(area);
@interface appDelegate : NSObject<NSApplicationDelegate, NSTextFieldDelegate>
@end
@implementation appDelegate
- (void)controlTextDidChange:(NSNotification *)note
{
areaUpdateScroll(area);
}
- (void)applicationDidFinishLaunching:(NSApplication *)app
{
NSWindow *mainwin;
NSView *contentView;
NSView *areav;
NSArray *constraints;
NSDictionary *views;
mainwin = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 500, 500)
styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)
backing:NSBackingStoreBuffered
defer:YES];
contentView = [mainwin contentView];
area = newArea((uiAreaHandler *) (&h));
areav = areaView(area);
[areav setTranslatesAutoresizingMaskIntoConstraints:NO];
[contentView addSubview:areav];
views = @{
@"areav": areav,
};
constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[areav]-|"
options:0
metrics:nil
views:views];
[contentView addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[areav]-|"
options:0
metrics:nil
views:views];
[contentView addConstraints:constraints];
[mainwin makeKeyAndOrderFront:nil];
}
@end
int main(void)
{
NSApplication *app;
h.ah.Draw = handlerDraw;
h.ah.HScrollMax = handlerHScrollMax;
h.ah.VScrollMax = handlerVScrollMax;
h.ah.RedrawOnResize = handlerRedrawOnResize;
app = [NSApplication sharedApplication];
[app setActivationPolicy:NSApplicationActivationPolicyRegular];
[app setDelegate:[appDelegate new]];
[app run];
return 0;
}

View File

@ -1,139 +0,0 @@
// 4 september 2015
typedef struct uiArea uiArea;
typedef struct uiAreaHandler uiAreaHandler;
typedef struct uiAreaDrawParams uiAreaDrawParams;
typedef struct uiDrawContext uiDrawContext;
struct uiAreaHandler {
void (*Draw)(uiAreaHandler *, uiArea *, uiAreaDrawParams *);
uintmax_t (*HScrollMax)(uiAreaHandler *, uiArea *);
uintmax_t (*VScrollMax)(uiAreaHandler *, uiArea *);
int (*RedrawOnResize)(uiAreaHandler *, uiArea *);
};
struct uiAreaDrawParams {
uiDrawContext *Context;
intmax_t ClientWidth;
intmax_t ClientHeight;
intmax_t ClipX;
intmax_t ClipY;
intmax_t ClipWidth;
intmax_t ClipHeight;
int DPIX;
int DPIY;
intmax_t HScrollPos;
intmax_t VScrollPos;
};
// TODO proper sources
// TODO dotting/dashing
typedef struct uiDrawStrokeParams uiDrawStrokeParams;
typedef enum uiDrawLineCap uiDrawLineCap;
typedef enum uiDrawLineJoin uiDrawLineJoin;
typedef enum uiDrawFillMode uiDrawFillMode;
enum uiDrawLineCap {
uiDrawLineCapFlat,
uiDrawLineCapRound,
uiDrawLineCapSquare,
};
enum uiDrawLineJoin {
uiDrawLineJoinMiter,
uiDrawLineJoinRound,
uiDrawLineJoinBevel,
};
// this is the default for botoh cairo and GDI
// Core Graphics doesn't explicitly specify a default, but NSBezierPath allows you to choose one, and this is the initial value
// so we're good to use it too!
#define uiDrawDefaultMiterLimit 10.0
enum uiDrawFillMode {
uiDrawFillModeWinding,
// TODO rename to EvenOdd?
uiDrawFillModeAlternate,
};
struct uiDrawStrokeParams {
uiDrawLineCap Cap;
uiDrawLineJoin Join;
intmax_t Thickness;
double MiterLimit;
};
void uiDrawBeginPathRGB(uiDrawContext *, uint8_t, uint8_t, uint8_t);
// TODO verify these aren't alpha premultiplied anywhere
void uiDrawBeginPathRGBA(uiDrawContext *, uint8_t, uint8_t, uint8_t, uint8_t);
void uiDrawMoveTo(uiDrawContext *, intmax_t, intmax_t);
void uiDrawLineTo(uiDrawContext *, intmax_t, intmax_t);
void uiDrawRectangle(uiDrawContext *, intmax_t, intmax_t, intmax_t, intmax_t);
// notes: angles are both relative to 0 and go counterclockwise
void uiDrawArcTo(uiDrawContext *, intmax_t, intmax_t, intmax_t, double, double, int);
// TODO behavior when there is no initial point on Windows and OS X
void uiDrawBezierTo(uiDrawContext *, intmax_t, intmax_t, intmax_t, intmax_t, intmax_t, intmax_t);
void uiDrawCloseFigure(uiDrawContext *);
void uiDrawStroke(uiDrawContext *, uiDrawStrokeParams *);
void uiDrawFill(uiDrawContext *, uiDrawFillMode);
// path functions
// cairo gdi core graphics
// move_to MoveToEx MoveToPoint
// line_to LineTo AddLineToPoint
// arc Arc/ArcTo/AngleArc/Pie AddArc/AddArcToPoint/AddEllipseInRect
// arc_negative Arc/ArcTo/AngleArc/Pie AddArc/AddArcToPoint
// curve_to PolyBezier/PolyBezierTo AddCurveToPoint
// rectangle Rectangle AddRect
// [arc functions?] Chord [arc functions?]
// [combination] RoundRect [same way as cairo?]
// [TODO pango] TextOut/ExtTextOut [TODO core text]
// [TODO] [TODO] AddQuadCurveToPoint
// on sources:
// cairo:
// - RGB
// - RGBA
// - images
// - linear gradients, RGB or RGBA
// - rounded gradients, RGB or RGBA
// gdi:
// - RGB
// - hatches
// - images
// we can create a linear gradient image, but RGB only, and of finite size
// core graphics:
// - arbitrary patterns
// - solid colors, arbitrary spaces
// - shadows
// arcs
// cairo_arc/arc_negative
// - parameters: center, radius, angle1 radians, angle2 radins
// - if angle2 < angle1, TODO
// - if angle2 > angle1, TODO
// - line segment from current point to beginning of arc
// - arc: clockwise, arc_negative: counterclockwise
// - circular
// GDI Arc/Pie
// - parameters: bounding box, start point, end point
// - current position not used/changed
// - either clockwise or counterclockwise
// - elliptical
// GDI ArcTo
// - same as Arc except line segment from current point to beginning of arc
// - there does not appear to be a PieTo
// GDI AngleArc
// - parameters: center, radius, angle1 degrees, angle2 degrees
// - line segment from current position to beginning of arc
// - counterclockwise
// - circular
// - can be used to draw pies too; MSDN example demonstrates