From b339b8208b5242909d3419c82620a107f50b674d Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Sun, 13 Dec 2015 12:52:16 -0500 Subject: [PATCH] Started the Area code. --- areahandler.go | 73 ++++++++++++++++++++++++++++ draw.go | 129 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 202 insertions(+) create mode 100644 areahandler.go create mode 100644 draw.go diff --git a/areahandler.go b/areahandler.go new file mode 100644 index 0000000..0998f56 --- /dev/null +++ b/areahandler.go @@ -0,0 +1,73 @@ +// 13 december 2015 +package main + +// #include "ui.h" +// extern void doAreaHandlerDraw(uiAreaHandler *, uiArea *, uiAreaDrawParams *); +// static inline void uiAreaHandler *allocAreaHandler(void) +// { +// uiAreaHandler *ah; +// +// ah = (uiAreaHandler *) malloc(sizeof (uiAreaHandler)); +// if (ah == NULL) +// return NULL; +// ah->Draw = doAreaHandlerDraw; +// return ah; +// } +// static inline void freeAreaHandler(uiAreaHandler *ah) +// { +// free(ah); +// } +import "C" + +// no need to lock this; only the GUI thread can access it +var areahandlers = make(map[*C.uiAreaHandler]AreaHandler) + +// AreaHandler defines the functionality needed for handling events +// from an Area. +type AreaHandler interface { + // TODO document all these + Draw(a *Area, dp *AreaDrawParams) +} + +func registerHandler(ah AreaHandler) *C.uiAreaHandler { + uah := C.allocAreaHandler() + areahandlers[uah] = ah + return uah +} + +func unregisterAreaHandler(uah *C.uiAreaHandler) { + delete(areahandlers, uah) + C.freeAreaHandler(uah) +} + +// AreaDrawParams defines the TODO. +type AreaDrawParams struct { + // TODO document all these + Context *DrawContext + ClientWidth float64 + ClientHeight float64 + ClipX float64 + ClipY float64 + ClipWidth float64 + ClipHeight float64 + HScrollPos int + VScrollPos int +} + +// export doAreaHandlerDraw +func doAreaHandlerDraw(uah *C.uiAreaHandler, ua *C.uiArea, udp *C.uiAreaDrawParams) { + ah := areahandlers[uah] + a := areas[ua] + dp := &AreaDrawParams{ + Context: &DrawContext{udp.Context}, + ClientWidth: float64(udp.ClientWidth), + ClientHeight: float64(udp.ClientHeight), + ClipX: float64(udp.ClipX), + ClipY: float64(udp.ClipY), + ClipWidth: float64(udp.ClipWidth), + ClipHeight: float64(udp.ClipHeight), + HScrollPos: int(udp.HScrollPos), + VScrollPos: int(udp.VScrollPos), + } + ah.Draw(a, dp) +} diff --git a/draw.go b/draw.go new file mode 100644 index 0000000..462cbb6 --- /dev/null +++ b/draw.go @@ -0,0 +1,129 @@ +// 13 december 2015 + +package main + +// #include "ui.h" +import "C" + +// Path represents a geometric path in a drawing context. +// This is the basic unit of drawing: all drawing operations consist of +// forming a path, then stroking, filling, or clipping to that path. +// A path is an OS resource; you must explicitly free it when finished. +// Paths consist of multiple figures. Once you have added all the +// figures to a path, you must "end" the path to make it ready to draw +// with. +// TODO rewrite all that +// +// Or more visually, the lifecycle of a Path is +// p := NewPath() +// for every figure { +// p.NewFigure(...) // or NewFigureWithArc +// p.LineTo(...) // any number of these in any order +// p.ArcTo(...) +// p.BezierTo(...) +// if figure should be closed { +// p.CloseFigure() +// } +// } +// p.End() +// // ... +// dp.Context.Stroke(p, ...) // any number of these in any order +// dp.Context.Fill(p, ...) +// dp.Context.Clip(p) +// // ... +// p.Free() // when done with the path +type Path struct { + p *C.uiDrawPath +} + +// NewPath creates a new Path. +func NewPath() *Path { + return &Path{ + p: C.uiDrawNewPath(), + } +} + +// Free destroys a Path. After calling Free the Path cannot be used. +func (p *Path) Free() { + C.uiDrawFreePath(p.p) +} + +// NewFigure starts a new figure in the Path. The current point +// is set to the given point. +func (p *Path) NewFigure(x float64, y float64) { + C.uiDrawPathNewFigure(p.p, C.double(x), C.double(y)) +} + +// NewFigureWithArc starts a new figure in the Path and adds an arc +// as the first element of the figure. Unlike ArcTo, NewFigureWithArc +// does not draw an initial line segment. Otherwise, see ArcTo. +func (p *Path) NewFigureWithArc(xCenter float64, yCenter float64, radius float64, startAngle float64, sweep float64, isNegative bool) { + C.uiDrawPathNewFigureWithArc(p.p, + C.double(xCenter), C.double(yCenter), + C.double(radius), + C.double(startAngle), C.double(sweep), + frombool(isNegative)) +} + +// LineTo adds a line to the current figure of the Path starting from +// the current point and ending at the given point. The current point +// is set to the ending point. +func (p *Path) LineTo(x float64, y float64) { + C.uiDrawPathLineTo(p.p, C.double(x), C.double(y)) +} + +// ArcTo adds a circular arc to the current figure of the Path. +// You pass it the center of the arc, its radius in radians, the starting +// angle (couterclockwise) in radians, and the number of radians the +// arc should sweep (counterclockwise). A line segment is drawn from +// the current point to the start of the arc. The current point is set to +// the end of the arc. +func (p *Path) ArcTo(xCenter float64, yCenter float64, radius float64, startAngle float64, sweep float64, isNegative bool) { + C.uiDrawPathArcTo(p.p, + C.double(xCenter), C.double(yCenter), + C.double(radius), + C.double(startAngle), C.double(sweep), + frombool(isNegative)) +} + +// BezierTo adds a cubic Bezier curve to the current figure of the Path. +// Its start point is the current point. c1x and c1y are the first control +// point. c2x and c2y are the second control point. endX and endY +// are the end point. The current point is set to the end point. +func (p *Path) BezierTo(c1x float64, c1y float64, c2x float64, c2y float64, endX float64, endY float64) { + C.uiDrawPathBezierTo(p.p, + C.double(c1x), C.double(c1y), + C.double(c2x), C.double(c2y), + C.double(endX), C.double(endY)) +} + +// CloseFigure draws a line segment from the current point of the +// current figure of the Path back to its initial point. After calling this, +// the current figure is over and you must either start a new figure +// or end the Path. If this is not called and you start a new figure or +// end the Path, then the current figure will not have this closing line +// segment added to it (but the figure will still be over). +func (p *Path) CloseFigure() { + C.uiDrawPathCloseFigure(p.p) +} + +// AddRectangle creates a new figure in the Path that consists entirely +// of a rectangle whose top-left corner is at the given point and whose +// size is the given size. The rectangle is a closed figure; you must +// either start a new figure or end the Path after calling this method. +func (p *Path) AddRectangle(x float64, y float64, width float64, height float64) { + C.uiDrawPathAddRectangle(p.p, C.double(x), C.double(y), C.double(width), C.double(height)) +} + +// End ends the current Path. You cannot add figures to a Path that has +// been ended. You cannot draw with a Path that has not been ended. +func (p *Path) End() { + C.uiDrawPathEnd(p.p) +} + +// DrawContext represents a drawing surface that you can draw to. +// At present the only DrawContexts are surfaces associated with +// Areas and are provided by package ui; see AreaDrawParams. +type DrawContext struct { + c *C.uiDrawContext +}