[Drawkit] Questions on control knobs

Brad Larson larson at sonoplot.com
Wed Jun 25 13:32:29 PDT 2008


On Jun 25, 2008, at 1:07 AM, Graham Cox wrote:

>
> On 25 Jun 2008, at 12:52 pm, Brad Larson wrote:
>
>> I'm not quite sure how or where to set up and use the DKKnobs in my  
>> custom subclass.  Attached is my fumbling attempt at creating an  
>> arc subclass that has three control points: center, starting point,  
>> and ending point.  The idea is that you could drag around the  
>> center point to set the radius (it would need to be constrained to  
>> be equidistant from the starting and ending points), and the  
>> starting and ending points to set the starting and ending angle.   
>> After dragging one of the points, the internal Bezier path would be  
>> regenerated to fit the new values.  centerPoint, startingPoint, and  
>> endingPoint are NSPoint properties, and startingPointKnobPartCode  
>> and endingPointKnobPartCode are integer properties.
>>
>> I can display my custom control points at the right place by  
>> overriding drawControlPointsOfPath:usingKnobs: , draw the shape  
>> properly using the arcCreateLoop: method (called from a custom  
>> drawing tool), and adjust the control point properties using  
>> moveByX:byY: on the movement of the whole object.  However, I can't  
>> figure out how to assign a partcode to my custom center point and  
>> retrieve the existing partcodes within the Bezier path for the  
>> control points present at the beginning and ending of the path.  I  
>> tried using hitPart: using the starting and ending point  
>> coordinates at the end of the arcCreateLoop: method, but that  
>> returns -1.  If I had those partcodes, I believe that I could  
>> change the control point properties in mouseDraggedAtPoint:  
>> inPart:event: in response to dragging on the control points.
>>
>> Am I going about this the right way in my subclass or are there  
>> other methods that I should be overriding to achieve this behavior?
>
> I'll attach my attempt below. It is pretty unpolished, but works by  
> and large. It should help you understand what needs to be overridden  
> (at this stage slightly more than would be ideal). Since I've done  
> this now I may add it to DK as a native object in future once all  
> the bugs have been worked out. (One that is a nuisance right now is  
> that the radius knob, which is drawn halfway between the two end  
> points, jumps 180° out of phase at certain positions. My brain must  
> suffering from coffee withdrawal or something because I couldn't  
> quite put my finger on a fix for that immediately). Also, as with  
> yours, the knobs sometimes don't get refreshed if they go outside  
> the bounds, but that's a relatively minor glitch - returning a  
> bounds that always includes all control points will fix that.
>
> To test this, you can modify the standard registered Arc tool to use  
> a DKArcPath instance as its prototype.
>
> Hope this helps - do let me know if you need any clarification, etc.

Excellent.  I had to tweak a few things here and there, such as  
changing the name of kDKDrawingEntireObjectPart to  
kGCDrawingEntireObjectPart, adding the DEGREES_TO_RADIANS and  
RADIANS_TO_DEGREES macro, and changing the name of pathCreationMode to  
pathEditingMode, to match it up with the heavily patched Beta 3  
version of DrawKit that I have here, but it works like just like what  
I was attempting.  I like your implementation of the 80% radius  
control point better than than just using the center (0% radius), it's  
a lot easier to line up and size an arc that way.

As far as the radius knob jumping out of alignment, I tracked it down  
to the averaging you were doing.  Right now, you have it checking to  
see if only one of the angles is negative, and adding Pi to the radian  
average of the angles if true.  This causes the angle to just to  
unexpected values for certain angle cases.  To fix this, I used the  
following

case kDKArcPathRadiusPart:
	angle = ( mEndAngle + mStartAngle ) * 0.5f;
	radius = mRadius * 0.8;
	if (mEndAngle < mStartAngle)
		angle += pi;
	break;

in knobPointForPartcode:, which should catch the cases you were trying  
for, while not freaking out on the others.  It works smoothly for me.

Also, I added the following:

if([[self class] displaysSizeInfoWhenDragging])
{			
	float rad = [[self drawing] convertLength:mRadius];
	float angle = RADIANS_TO_DEGREES( mEndAngle - mStartAngle );
			
	if ( angle < 0 )
		angle = 360.0 + angle;
	NSString*		abbrUnits = [[self drawing] abbreviatedDrawingUnits];
	[[self layer] showInfoWindowWithString:[NSString  
stringWithFormat:@"radius: %.2f %@\nangle: %.1f%C", rad, abbrUnits,  
angle, 0xB0] atPoint:mp];
}

in mouseDraggedAtPoint: inPart: event: to give the ability to display  
the radius and angle popup when editing the arc.

Thanks a lot for the help, this should take care of the arc custom  
shape and I can use this as a basis for the remaining two custom  
shapes I need to complete the primary features of our draw program.


______________________
Brad Larson
SonoPlot, Inc.
3030 Laura Lane, Suite 120
Middleton, WI 53562





More information about the Drawkit mailing list