|
|
1.1 ! root 1: #if 0 ! 2: ! 3: PressureView.m -- Pressure sensitive View subclass for painting ! 4: ! 5: by Peter Graffagnino, NeXT Computer Inc. ! 6: ! 7: PressureView is a view subclass responsible for: ! 8: ! 9: - maintaining a special trackingrect to inform the low-level event ! 10: system of its interest in pressure and event coalescing. ! 11: - maintaining an NXImage backingstore for the View. ! 12: - implementing a mouseDown: painting loop and using a Brush object for ! 13: painting ! 14: - handling flagsChanged: events to update pen proximity state ! 15: ! 16: You may freely copy, distribute, and reuse the code in this example. ! 17: NeXT disclaims any warranty of any kind, expressed or implied, as to its ! 18: fitness for any particular use. ! 19: ! 20: #endif ! 21: ! 22: #import <appkit/appkit.h> ! 23: #include <math.h> ! 24: #include <dpsclient/wraps.h> ! 25: #import "PressureView.h" ! 26: #import "Brush.h" ! 27: #import "pressurerect.h" ! 28: ! 29: @implementation PressureView : View ! 30: ! 31: - initFrame:(const NXRect *)r ! 32: { ! 33: self = [super initFrame:r]; ! 34: [self allocateGState]; ! 35: backingImage = [[NXImage alloc] initSize: &r->size]; ! 36: [backingImage setBackgroundColor: NX_COLORWHITE]; ! 37: coalesceState = YES; ! 38: pressureState = YES; ! 39: [self clear: self]; ! 40: return self; ! 41: } ! 42: ! 43: - free ! 44: { ! 45: [backingImage free]; ! 46: return [super free]; ! 47: } ! 48: ! 49: - clear:sender ! 50: { ! 51: if (! [backingImage lockFocus]) return self; ! 52: NXSetColor(NX_COLORWHITE); ! 53: NXRectFill(&bounds); ! 54: [backingImage unlockFocus]; ! 55: [self display]; ! 56: return self; ! 57: } ! 58: ! 59: - drawSelf:(const NXRect *)rects :(int)rectCount ! 60: { ! 61: [backingImage composite: NX_COPY fromRect: rects toPoint: &rects->origin]; ! 62: return self; ! 63: } ! 64: ! 65: - sizeTo: (NXCoord) x : (NXCoord) y ! 66: { ! 67: NXSize size; ! 68: [super sizeTo: x : y]; ! 69: size.width = x; ! 70: size.height = y; ! 71: [backingImage setSize: &size]; ! 72: return self; ! 73: } ! 74: ! 75: - mouseDown:(NXEvent *)e ! 76: { ! 77: NXPoint p; ! 78: NXRect dirty; ! 79: int emask=[window addToEventMask:(NX_MOUSEUPMASK | NX_MOUSEDRAGGEDMASK)]; ! 80: ! 81: if( ! [backingImage lockFocus] ) return self; ! 82: ! 83: p = e->location; ! 84: [self convertPoint: &p fromView: nil]; ! 85: p.x += .5; p.y += .5; ! 86: [brush brushMoveTo: p.x : p.y withPressure: e->data.mouse.pressure/255.0 ! 87: dirtyRect: &dirty]; ! 88: [self display: &dirty : 1]; ! 89: while(1) { ! 90: e=[NXApp getNextEvent:(NX_MOUSEUPMASK | NX_MOUSEDRAGGEDMASK)]; ! 91: if(e->type == NX_MOUSEUP) ! 92: break; ! 93: p = e->location; ! 94: [self convertPoint: &p fromView: nil]; ! 95: p.x += .5; p.y += .5; ! 96: [brush brushLineTo: p.x : p.y withPressure: ! 97: e->data.mouse.pressure/255.0 ! 98: dirtyRect: &dirty]; ! 99: [self display: &dirty : 1]; ! 100: NXPing(); ! 101: } ! 102: [backingImage unlockFocus]; ! 103: [window setEventMask:emask]; ! 104: return self; ! 105: } ! 106: ! 107: ! 108: - (BOOL) acceptsFirstResponder ! 109: { ! 110: return YES; ! 111: } ! 112: ! 113: - awakeFromNib ! 114: { ! 115: [window addToEventMask:NX_FLAGSCHANGEDMASK]; ! 116: return self; ! 117: } ! 118: ! 119: /* ! 120: * we implement flagsChanged in order to receive proximity events from the ! 121: * tablet. We just use this to update a status field. ! 122: */ ! 123: ! 124: - flagsChanged:(NXEvent *)e ! 125: { ! 126: BOOL proximity; ! 127: ! 128: proximity = e->flags & NX_STYLUSPROXIMITYMASK; ! 129: [proximityText setStringValue: ! 130: proximity ? ! 131: NXLocalString("in proximity", NULL, NULL) : ! 132: NXLocalString ("out of proximity", NULL, NULL)]; ! 133: return self; ! 134: } ! 135: ! 136: ! 137: /* ! 138: * Target/Action methods used to control the special tracking rect options ! 139: * (pressure and coalescing). ! 140: */ ! 141: ! 142: - setCoalesceState:sender ! 143: { ! 144: coalesceState = [sender state]; ! 145: [self setPressureRect]; ! 146: return self; ! 147: } ! 148: ! 149: - setPressureState:sender ! 150: { ! 151: pressureState = [sender state]; ! 152: [self setPressureRect]; ! 153: return self; ! 154: } ! 155: ! 156: /* ! 157: * resetCursorRects will be called to give the view an opportunity to ! 158: * re-establish its tracking rects after the relative geometry between the ! 159: * Window and the View has changed. We use this opportunity to set up oue ! 160: * special tracking rects for pressure and coalescing. ! 161: */ ! 162: ! 163: - resetCursorRects ! 164: { ! 165: return [self setPressureRect]; ! 166: } ! 167: ! 168: - setPressureRect ! 169: { ! 170: NXRect visibleRect; ! 171: ! 172: [self lockFocus]; ! 173: [self getVisibleRect: &visibleRect]; ! 174: ! 175: /* ! 176: * Setup the pressure rect. Use our object address as the trackingrect ! 177: * tag. ! 178: */ ! 179: ! 180: set_pressure_rect(visibleRect.origin.x, ! 181: visibleRect.origin.y, ! 182: visibleRect.size.width, ! 183: visibleRect.size.height, ! 184: coalesceState, ! 185: pressureState, ! 186: (int) self); ! 187: ! 188: [self unlockFocus]; ! 189: return self; ! 190: } ! 191: ! 192: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.