More OS X uiArea implementation work.
This commit is contained in:
parent
24c8c085a0
commit
7e0dae000f
|
@ -0,0 +1,12 @@
|
||||||
|
// 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 *);
|
|
@ -0,0 +1,117 @@
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 scoll view
|
||||||
|
|
||||||
|
// 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];
|
||||||
|
}
|
|
@ -23,7 +23,7 @@ uiDrawContext *newContext(CGContextRef ctxt)
|
||||||
|
|
||||||
void uiDrawBeginPathRGB(uiDrawContext *c, uint8_t r, uint8_t g, uint8_t b)
|
void uiDrawBeginPathRGB(uiDrawContext *c, uint8_t r, uint8_t g, uint8_t b)
|
||||||
{
|
{
|
||||||
c->useRGB = YES;
|
c->useRGBA = YES;
|
||||||
c->r = ((CGFloat) r) / 255;
|
c->r = ((CGFloat) r) / 255;
|
||||||
c->g = ((CGFloat) g) / 255;
|
c->g = ((CGFloat) g) / 255;
|
||||||
c->b = ((CGFloat) b) / 255;
|
c->b = ((CGFloat) b) / 255;
|
||||||
|
@ -33,7 +33,7 @@ void uiDrawBeginPathRGB(uiDrawContext *c, uint8_t r, uint8_t g, uint8_t b)
|
||||||
|
|
||||||
void uiDrawBeginPathRGBA(uiDrawContext *c, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
void uiDrawBeginPathRGBA(uiDrawContext *c, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||||
{
|
{
|
||||||
c->useRGB = YES;
|
c->useRGBA = YES;
|
||||||
c->r = ((CGFloat) r) / 255;
|
c->r = ((CGFloat) r) / 255;
|
||||||
c->g = ((CGFloat) g) / 255;
|
c->g = ((CGFloat) g) / 255;
|
||||||
c->b = ((CGFloat) b) / 255;
|
c->b = ((CGFloat) b) / 255;
|
||||||
|
@ -53,7 +53,7 @@ void uiDrawLineTo(uiDrawContext *c, intmax_t x, intmax_t y)
|
||||||
|
|
||||||
void uiDrawRectangle(uiDrawContext *c, intmax_t x, intmax_t y, intmax_t width, intmax_t height)
|
void uiDrawRectangle(uiDrawContext *c, intmax_t x, intmax_t y, intmax_t width, intmax_t height)
|
||||||
{
|
{
|
||||||
CGContextAddRect(c->c, TODO(x, y, width, height));
|
CGContextAddRect(c->c, CGRectMake(x, y, width, height));
|
||||||
}
|
}
|
||||||
|
|
||||||
void uiDrawArcTo(uiDrawContext *c, intmax_t xCenter, intmax_t yCenter, intmax_t radius, double startAngle, double endAngle, int lineFromCurrentPointToStart)
|
void uiDrawArcTo(uiDrawContext *c, intmax_t xCenter, intmax_t yCenter, intmax_t radius, double startAngle, double endAngle, int lineFromCurrentPointToStart)
|
||||||
|
@ -104,28 +104,28 @@ void uiDrawStroke(uiDrawContext *c, uiDrawStrokeParams *p)
|
||||||
}
|
}
|
||||||
switch (p->Join) {
|
switch (p->Join) {
|
||||||
case uiDrawLineJoinMiter:
|
case uiDrawLineJoinMiter:
|
||||||
CGContextSetLineJoin(c->cr, kCGLineJoinMiter);
|
CGContextSetLineJoin(c->c, kCGLineJoinMiter);
|
||||||
CGContextSetMiterLimit(c->c, p->MiterLimit);
|
CGContextSetMiterLimit(c->c, p->MiterLimit);
|
||||||
break;
|
break;
|
||||||
case uiDrawLineJoinRound:
|
case uiDrawLineJoinRound:
|
||||||
CGContextSetLineJoin(c->cr, kCGLineJoinRound);
|
CGContextSetLineJoin(c->c, kCGLineJoinRound);
|
||||||
break;
|
break;
|
||||||
case uiDrawLineJoinBevel:
|
case uiDrawLineJoinBevel:
|
||||||
CGContextSetLineJoin(c->cr, kCGLineJoinBevel);
|
CGContextSetLineJoin(c->c, kCGLineJoinBevel);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
CGContextSetLineWidth(c->c, p->Thickness);
|
CGContextSetLineWidth(c->c, p->Thickness);
|
||||||
if (c->useRGB)
|
if (c->useRGBA)
|
||||||
CGContextSetRGBStrokeColor(c->c, c->r, c->g, c->b, c->a);
|
CGContextSetRGBStrokeColor(c->c, c->r, c->g, c->b, c->a);
|
||||||
else {
|
else {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
CGContextStrokePath(c->cr);
|
CGContextStrokePath(c->c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void uiDrawFill(uiDrawContext *c, uiDrawFillMode mode)
|
void uiDrawFill(uiDrawContext *c, uiDrawFillMode mode)
|
||||||
{
|
{
|
||||||
if (c->useRGB)
|
if (c->useRGBA)
|
||||||
CGContextSetRGBFillColor(c->c, c->r, c->g, c->b, c->a);
|
CGContextSetRGBFillColor(c->c, c->r, c->g, c->b, c->a);
|
||||||
else {
|
else {
|
||||||
// TODO
|
// TODO
|
|
@ -0,0 +1,171 @@
|
||||||
|
// 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);
|
||||||
|
*/}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
app = [NSApplication sharedApplication];
|
||||||
|
[app setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||||
|
[app setDelegate:[appDelegate new]];
|
||||||
|
[app run];
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue