Index: Source/ETBrushStyle.m
===================================================================
--- Source/ETBrushStyle.m	(revision 0)
+++ Source/ETBrushStyle.m	(revision 0)
@@ -0,0 +1,51 @@
+#import "ETBrushStyle.h"
+#import <AppKit/AppKit.h>
+
+/**
+ * Implements a basic bitmap brush.
+ *
+ * Currently only stamps the brush bitmap at the location of each input event, so
+ * looks very ugly (need to interpolate between the input events).
+ *
+ * Everything is also hardcoded for now :)
+ *
+ */
+@implementation ETBrushStyle
+
+- (void) render: (NSMutableDictionary *)inputValues 
+     layoutItem: (ETLayoutItem *)item 
+	  dirtyRect: (NSRect)dirtyRect;
+{
+	[NSGraphicsContext saveGraphicsState];
+	
+	NSPoint origin = [[inputValues valueForKey:@"origin"] pointValue];
+	NSAffineTransform *xform = [NSAffineTransform transform];
+	[xform translateXBy: origin.x yBy: origin.y];
+	[xform concat];
+	
+	
+	NSBezierPath *path = [inputValues valueForKey: @"path"];
+	NSArray *pressures = [inputValues valueForKey: @"pressures"];
+	NSGradient *gradient = [[NSGradient alloc] initWithStartingColor: [NSColor blueColor] endingColor: [NSColor clearColor]];
+	
+	if (path != nil && pressures != nil)
+	{
+		NSPoint points[3];
+		NSPoint last = NSZeroPoint;
+		for (unsigned int i=0; i<[path elementCount]; i++)
+		{
+			if ([path elementAtIndex: i associatedPoints: points] == NSLineToBezierPathElement)
+			{
+				float pressure =  [[pressures objectAtIndex: i-1] floatValue];
+				float radius = 10.0 * pressure;
+				
+				[gradient drawInRect: NSMakeRect(points[0].x - radius, points[0].y - radius, 2*radius, 2*radius) relativeCenterPosition: NSMakePoint(0.0,0.0)];
+				last = points[0];
+			}
+		}
+	}
+	
+	[NSGraphicsContext restoreGraphicsState];
+}
+
+@end
Index: Source/ETBrushTool.m
===================================================================
--- Source/ETBrushTool.m	(revision 0)
+++ Source/ETBrushTool.m	(revision 0)
@@ -0,0 +1,101 @@
+/*
+ Copyright (C) 2008 Quentin Mathe
+ 
+ Author:  Quentin Mathe <qmathe@club-internet.fr>
+ Date:  December 2008
+ License:  Modified BSD (see COPYING)
+ */
+
+#import <EtoileFoundation/Macros.h>
+#import "ETBrushTool.h"
+#import "ETShape.h"
+#import "ETDrawingStrokeShape.h"
+#import "ETApplication.h"
+#import "ETEvent.h"
+#import "ETLayoutItem.h"
+#import "ETCompatibility.h"
+#import "ETGeometry.h"
+
+@implementation ETBrushTool
+
++ (NSString *) baseClassName
+{
+	return @"Tool";
+}
+
+- (id) init
+{
+	SUPERINIT
+	return self;
+}
+
+- (void) dealloc
+{
+    [super dealloc];
+}
+
+
+- (void) mouseDown: (ETEvent *)anEvent
+{
+	NSLog(@"ETBrushTool mousedown. %@\n %@\n %@", [self targetItem],  [anEvent layoutItem], [[self targetItem] itemsIncludingAllDescendants]);
+	
+	NSPoint startPoint = [anEvent locationInLayoutItem];
+	NSRect startRect = NSMakeRect(startPoint.x, startPoint.y, 10.0, 10.0);
+	
+	NSRect r = [[self targetItem] convertRect:startRect fromItem: [anEvent layoutItem]];
+	NSRect r2 = [[anEvent layoutItem] convertRect:startRect toItem:[self targetItem]];
+	
+	NSLog(@"r1: %@ r2: %@", NSStringFromRect(r), NSStringFromRect(r2));
+	// FIXME: why aren't r and r2 equal
+	NSRect locInTargetContent = [[self targetItem] convertRectToContent: r2];
+
+	_startInTargetContainer = locInTargetContent.origin;
+	
+	_start = [anEvent location]; // store position in window
+	
+	_brushStroke = [[[ETLayoutItem alloc] init] autorelease];
+	_drawingStrokeShape = [[ETDrawingStrokeShape alloc] init];
+	[_drawingStrokeShape addPoint: NSMakePoint(0.0, 0.0) withPressure: [(NSEvent *)[anEvent backendEvent] pressure]];
+	[_brushStroke setStyle: _drawingStrokeShape];
+	[_brushStroke setFrame: locInTargetContent];
+	
+	[[self targetItem] addItem: _brushStroke];
+	[_brushStroke setNeedsDisplay: YES];
+}
+
+- (void) mouseUp: (ETEvent *)anEvent
+{
+	NSLog(@"ETBrushTool mouseup. %@ %@", [self targetItem], [anEvent layoutItem]);
+}
+
+- (void) mouseDragged: (ETEvent *)anEvent
+{
+	//NSLog(@"ETBrushTool mousedragged %@ %@. %f", [self targetItem], [anEvent locationInLayoutItem], [(NSEvent *)[anEvent backendEvent] pressure]);
+	
+	// coordinates of the mouse pointer relative to where the drag was initiated
+	NSPoint dragPosition = NSMakePoint([anEvent location].x - _start.x, [anEvent location].y - _start.y);
+	
+	// coordinates dragged to in the container's coordinate system
+	NSRect dragPositionInTargetContainer;
+	dragPositionInTargetContainer.origin = ETSumPoint(_startInTargetContainer, dragPosition);
+	dragPositionInTargetContainer.size = NSMakeSize(1.0, 1.0);
+	
+	// set the new frame of the layout item.
+	[_brushStroke setFrame: NSUnionRect([_brushStroke frame], ETStandardizeRect(dragPositionInTargetContainer))];
+	
+	NSPoint drawPositionRelativeToStartPosition;
+	drawPositionRelativeToStartPosition.x = MAX(0.0, _startInTargetContainer.x - [_brushStroke frame].origin.x);
+	drawPositionRelativeToStartPosition.y = MAX(0.0, _startInTargetContainer.y - [_brushStroke frame].origin.y);
+	[_drawingStrokeShape setDrawingOrigin: drawPositionRelativeToStartPosition];
+	
+	
+	[_drawingStrokeShape addPoint: dragPosition
+					 withPressure: [(NSEvent *)[anEvent backendEvent] pressure]];
+	
+	[[self targetItem] setNeedsDisplay: YES];
+	[[self targetItem] displayIfNeeded];
+}
+
+
+
+@end
Index: Source/ETPenStyle.m
===================================================================
--- Source/ETPenStyle.m	(revision 0)
+++ Source/ETPenStyle.m	(revision 0)
@@ -0,0 +1,21 @@
+#import "ETPenStyle.h"
+
+@implementation ETPenStyle
+
+- (void) render: (NSMutableDictionary *)inputValues 
+     layoutItem: (ETLayoutItem *)item 
+	  dirtyRect: (NSRect)dirtyRect;
+{
+	[NSGraphicsContext saveGraphicsState];
+	
+	NSPoint origin = [[inputValues valueForKey:@"origin"] pointValue];
+	NSAffineTransform *xform = [NSAffineTransform transform];
+	[xform translateXBy: origin.x yBy: origin.y];
+	[xform concat];
+	
+	[[inputValues valueForKey: @"path"] stroke];
+
+	[NSGraphicsContext restoreGraphicsState];
+}
+
+@end
\ No newline at end of file
Index: Source/ETDrawingStrokeShape.m
===================================================================
--- Source/ETDrawingStrokeShape.m	(revision 0)
+++ Source/ETDrawingStrokeShape.m	(revision 0)
@@ -0,0 +1,80 @@
+#import "ETDrawingStrokeShape.h"
+#import "ETLayoutItem.h"
+#import "ETCompatibility.h"
+#import "ETBrushStyle.h"
+#import "ETPenStyle.h"
+
+#import <EtoileFoundation/Macros.h>
+
+@implementation ETDrawingStrokeShape
+
+- (id) init
+{
+	self = [super initWithBezierPath: [NSBezierPath bezierPath]];
+	if (nil == self)
+	{
+		return nil;
+	}
+	[_path moveToPoint: NSZeroPoint];
+	_pressures = [[NSMutableArray alloc] initWithCapacity:1000];
+	
+	// Change this to ETPenStyle to get a vector pen tool instead..
+	_brushStyle = [[ETBrushStyle alloc] init];
+	_origin = NSMakePoint(0.0, 0.0);
+	return self;
+}
+
+- (void) dealloc
+{
+	[_brushStyle release];
+	[_pressures release];
+	[super dealloc];
+}
+
+- (void) addPoint: (NSPoint)point withPressure: (float)pressure
+{
+	[_path lineToPoint: point];
+	[_pressures addObject: [NSNumber numberWithFloat:pressure]];
+	[self didChangeItemBounds: [[self path] bounds]];
+}
+
+- (void) render: (NSMutableDictionary *)inputValues 
+     layoutItem: (ETLayoutItem *)item 
+	  dirtyRect: (NSRect)dirtyRect;
+{
+	// FIXME: May be we should better support dirtyRect. The next drawing 
+	// methods don't take in account it and simply redraw all their content.
+	
+	NSMutableDictionary *newInputValues = [D([self path], @"path",
+											_pressures, @"pressures",
+										   [NSValue valueWithPoint: _origin], @"origin") mutableCopy];
+	[newInputValues addEntriesFromDictionary: inputValues];
+	
+	[[self brushStyle] render: newInputValues
+				   layoutItem: item
+					dirtyRect: dirtyRect];
+	
+	if ([item isSelected])
+		[self drawSelectionIndicatorInRect: [item drawingFrame]];
+	
+	//[super render: inputValues layoutItem: item dirtyRect: dirtyRect];
+}
+
+- (ETStyle *) brushStyle
+{
+	return _brushStyle;
+}
+- (void) setBrushStyle: (ETStyle *)style;
+{
+	ASSIGN(_brushStyle, style);
+	// TODO: redraw?
+}
+
+
+- (void) setDrawingOrigin: (NSPoint)origin
+{
+	_origin = origin;
+}
+
+
+@end
Index: Headers/ETBrushStyle.h
===================================================================
--- Headers/ETBrushStyle.h	(revision 0)
+++ Headers/ETBrushStyle.h	(revision 0)
@@ -0,0 +1,7 @@
+#import "ETStyle.h"
+
+@interface ETBrushStyle : ETStyle
+{
+}
+
+@end
Index: Headers/ETBrushTool.h
===================================================================
--- Headers/ETBrushTool.h	(revision 0)
+++ Headers/ETBrushTool.h	(revision 0)
@@ -0,0 +1,27 @@
+/** <title>ETBrushTool</title>
+ 
+ <abstract>An instrument class which implements the paintbrush tool 
+ tool present in many graphics-oriented applications.</abstract>
+ 
+ Copyright (C) 2009 Eric Wasylishen
+ 
+ Author:  Eric Wasylishen <ewasylishen@gmail.com>
+ Date:  July 2009
+ License:  Modified BSD (see COPYING)
+ */
+
+#import <Foundation/Foundation.h>
+#import <AppKit/AppKit.h>
+#import <EtoileUI/ETInstrument.h>
+#import <EtoileUI/ETDrawingStrokeShape.h>
+
+@interface ETBrushTool : ETInstrument
+{
+	ETLayoutItem *_brushStroke;
+	ETDrawingStrokeShape *_drawingStrokeShape;
+	NSPoint _start;
+	NSPoint _startInTargetContainer;
+}
+
+
+@end
Index: Headers/ETPenStyle.h
===================================================================
--- Headers/ETPenStyle.h	(revision 0)
+++ Headers/ETPenStyle.h	(revision 0)
@@ -0,0 +1,12 @@
+#import "ETStyle.h"
+
+/**
+ * This style draws a vector path of possibly varying thickness,
+ * emulating a flat-nibbed ink pen.
+ * (ideally varying color/opacity, but that seems difficult to do..?)
+ */
+@interface ETPenStyle : ETStyle
+{
+}
+
+@end
\ No newline at end of file
Index: Headers/ETDrawingStrokeShape.h
===================================================================
--- Headers/ETDrawingStrokeShape.h	(revision 0)
+++ Headers/ETDrawingStrokeShape.h	(revision 0)
@@ -0,0 +1,19 @@
+#import <EtoileUI/ETShape.h>
+
+@interface ETDrawingStrokeShape : ETShape
+{
+	NSMutableArray *_pressures;
+	ETStyle *_brushStyle;
+	NSPoint _origin;
+}
+
+// maybe all the tablet paramaters should be passed in a dictionary?
+//- (void) addPenPosition: (NSPoint)point withPressure: (float)pressure tilt:(NSPoint)tilt rotation:(float)rotation barrelPressure:(float)barrelPressure atTime: (NSTimeInterval)timestamp;
+- (void) addPoint: (NSPoint)point withPressure: (float)pressure; 
+
+- (ETStyle *) brushStyle;
+- (void) setBrushStyle: (ETStyle *)style;
+
+- (void) setDrawingOrigin: (NSPoint)origin;
+
+@end
\ No newline at end of file
