This is InspectAxes.m in view mode; [Download] [Up]
/* InspectAxes.m by Paul Rensing Nov. 1992 * Controls axis frills * * Copyright (C) 1992 The Board of Trustees of * The Leland Stanford Junior University. All Rights Reserved. */ #import "HGraphicView.h" #import "InspectAxes.h" const char InspectAxes_h_rcsid[] = INSPECTAXES_H_ID; const char InspectAxes_m_rcsid[] = "$Id: InspectAxes.m,v 2.30.2.3 1994/02/08 20:29:06 rensing Exp $"; #import "FineSlider.h" #import "NewInspector.h" #import "Plot.h" #import <float.h> #define RB_HIGH 0 #define RB_LOW 1 #define RB_WIDTH 2 #define RB_OFF 3 #define MAXBINS 500 #define DEFAULT_BINS 50 #define SCALE_FACTOR 5.0 /* * bug fix: FLT_MIN=1.17549435e-38 is actually 0 */ #undef FLT_MIN #define FLT_MIN 2e-38f @implementation InspectAxes static BOOL checkDisplay( display disp, binding_t axis, float *low, float *high, int *num ) { graphtype_t type; BOOL checkBins; type = h_getDispType( disp ); if (( type == COLORPLOT && (axis == XAXIS || axis == YAXIS)) || type == LEGOPLOT || (type == HISTOGRAM && axis == XAXIS)) { checkBins = YES; } else { checkBins = NO; } if ( checkBins ) *num = h_getBinNum(disp, axis); h_getRange( disp, axis, low, high ); return checkBins; } - initInspFor:aDraw { NXBundle *bundle; char buffer[MAXPATHLEN+1]; unsigned int i; [super initInspFor:aDraw]; bundle = [NXBundle bundleForClass:[self class]]; if ( [bundle getPath:buffer forResource:"InspectAxes" ofType:"nib"] ) { [NXApp loadNibFile:buffer owner:self withNames:NO fromZone:[self zone]]; } [theInspector addView:[contentBox contentView] withName:"Axis Options" withSupervisor:self]; /* make sure the tag are set to something consistent */ axis = XAXIS; [self setTags]; /* * we've got to do the following nonsense because can't stretch out spacing * of slider from IB */ rbSlider[0] = rbSlider0; rbSlider[1] = rbSlider1; rbSlider[2] = rbSlider2; rbSlider[3] = rbSlider3; for ( i = 0; i < 4; i++ ) { [rbSlider[i] setScaleFactor:SCALE_FACTOR]; } numLimitCheck = [limitCheckButton state]; currentDim = 1; prevIndex = -1; prevValue = 999.999; return self; } /* Action methods */ - tickOption:sender { plotloc_t loc=0; if ([[TickMatrix findCellWithTag:PLOTBOTTOM] state] == 1) loc += PLOTBOTTOM; if ([[TickMatrix findCellWithTag:PLOTTOP] state] == 1) loc += PLOTTOP; if ([[TickMatrix findCellWithTag:PLOTLEFT] state] == 1) loc += PLOTLEFT; if ([[TickMatrix findCellWithTag:PLOTRIGHT] state] == 1) loc += PLOTRIGHT; [graphicView graphicsPerform:@selector(setTickLocation:to:) with:(id)&axis with:(id)&loc andDraw:YES]; [[graphicView window] flushWindow]; return self; } - scaleOption:sender { plotloc_t loc; loc = [[sender selectedCell] tag ]; [graphicView graphicsPerform:@selector(setScaleLocation:to:) with:(id)&axis with:(id)&loc andDraw:YES]; [[graphicView window] flushWindow]; return self; } - labelOption:sender { plotloc_t loc; loc = [[sender selectedCell] tag ]; [graphicView graphicsPerform:@selector(setLabelLocation:to:) with:(id)&axis with:(id)&loc andDraw:YES]; [[graphicView window] flushWindow]; return self; } /* * Respond to the appropriate x axis matrix */ - scaleFontSize:sender { float fontSize; fontSize = [sender floatValue]; [graphicView graphicsPerform:@selector(setScaleFontSize:to:) with:(id)&axis with:(id)&fontSize andDraw:YES]; [[graphicView window] flushWindow]; return self; } - tickLength:sender { float len; len = [sender floatValue]; [graphicView graphicsPerform:@selector(setTickLength:to:) with:(id)&axis with:(id)&len andDraw:YES]; [[graphicView window] flushWindow]; return self; } - axisSelection:sender { axis = [[sender selectedCell] tag ]; [self setTags]; [self updateView]; return self; } - limitCheck:sender { numLimitCheck = [limitCheckButton state]; return self; } - rebin:sender { NXPoint p; float svalue, toff, tlow, thigh, delta, deltaoff; float plo, phi; double dnum; int i; int slider_index; BOOL re_display = NO; BOOL logAxis, checkBins=NO; display adisplay = [firstPlot histDisplay]; BOOL zpmode; slider_index = -1; for (i = 0; i < 4; i++) { if (sender == rbSlider[i]) { slider_index = i; break; } } svalue = [sender floatValue]; h_getRange(adisplay, axis, &plo, &phi ); zpmode = [zpbutton state]; if ( (i < 4) && ((slider_index != prevIndex) || (svalue != prevValue))) { prevIndex = slider_index; prevValue = svalue; if (( graphtype == COLORPLOT && (axis == XAXIS || axis == YAXIS)) || graphtype == LEGOPLOT || (graphtype == HISTOGRAM && axis == XAXIS)) { checkBins = YES; } else { checkBins = NO; } logAxis = h_getLogAxis(adisplay, axis); switch (slider_index) { case RB_HIGH: if (logAxis && svalue <= 0.0) svalue = 2*FLT_MIN; if (checkBins) { thigh = MAX( svalue, low + 2.0*width ); delta = thigh - high; if (ABS(delta) > width) { i = (delta > 0) ? delta / width : delta / width + 1; num = num + i; if ( zpmode ) num = num + i; num = [self limitCheck:num against: MAXBINS ]; high = high + i * width; if ( zpmode ) low = low - i*width; high = MAX(high, low + width); re_display = YES; } } else { high = MAX(svalue,low*(1.0+2.0*FLT_EPSILON)); if (zpmode) low = plo - (high - phi); re_display = YES; } if (re_display) [rbForm setFloatValue:high at:RB_HIGH]; break; case RB_LOW: if (logAxis && svalue <= 0.0) svalue = 2*FLT_MIN; if (checkBins) { tlow = MIN(svalue, high - 2 * width); delta = low - tlow; if (ABS(delta) > width) { i = delta / width; if ( !zpmode ) { num = num + i; num = [self limitCheck:num against: MAXBINS ]; } low = low - i * width; if (zpmode) high = high - i*width; low = MIN(low, high - width); re_display = YES; } } else { low = MIN(svalue,high*(1.0-2.0*FLT_EPSILON)); if ( zpmode ) high = phi + ( low - plo ); re_display = YES; } if (re_display) [rbForm setFloatValue:low at:RB_LOW]; break; case RB_WIDTH: if (checkBins) { /* * Given width, adjust nbins and high to closest values * giving an integral number of bins */ width = [rbSlider[RB_WIDTH] floatValue]; dnum = (high - low) / width; if (dnum > (((float)floor(dnum) + (float)ceil(dnum))/2.0)) { num = ceil(dnum); } else { num = floor(dnum); } num = [self limitCheck:num against: MAXBINS ]; high = low + num * width; [rbForm setFloatValue:width at:RB_WIDTH]; [rbForm setFloatValue:high at:RB_HIGH]; re_display = YES; } break; case RB_OFF: toff = svalue; /* slider value */ deltaoff = toff - offset; low = low + width * deltaoff; high = high + width * deltaoff; offset = toff; [rbForm setFloatValue:high at:RB_HIGH]; [rbForm setFloatValue:low at:RB_LOW]; [rbForm setFloatValue:offset at:RB_OFF]; re_display = YES; break; } if (re_display == YES) { p.x = low; p.y = high; [graphicView graphicsPerform:@selector(setNumBins:to:) with:(id)&axis with :(id)&num andDraw:NO]; [graphicView graphicsPerform:@selector(setRange:to:) with:(id)&axis with:(id)&p andDraw:YES]; [autoScaleButton setState:NO]; if (zpmode) { if ( slider_index == RB_HIGH ) { [rbForm setFloatValue:low at:RB_LOW]; } else if ( slider_index == RB_LOW ) { [rbForm setFloatValue:high at:RB_HIGH]; } } width = (high - low) / (num); } } if ( re_display == YES ) { [[[graphicView window] flushWindow] makeKeyWindow]; } return self; } - rebinForm:sender { NXPoint p; double dnum; float thigh, tlow, twidth=0.0, toff; int sel; BOOL re_display = NO; BOOL logAxis, checkBins; display adisplay = [firstPlot histDisplay]; sel = [rbForm selectedIndex]; logAxis = h_getLogAxis(adisplay, axis); if ( ((graphtype == COLORPLOT|| graphtype == LEGOPLOT) && (axis == XAXIS || axis == YAXIS)) || (graphtype == HISTOGRAM && axis == XAXIS)) { checkBins = YES; } else { checkBins = NO; } thigh = [rbForm floatValueAt:RB_HIGH]; tlow = [rbForm floatValueAt:RB_LOW]; if (checkBins) { if (sel == RB_WIDTH) { twidth = [rbForm floatValueAt:RB_WIDTH]; dnum = (thigh - tlow) / twidth; if (dnum > ((floor(dnum) + ceil(dnum)) / 2.0)) { num = ceil(dnum); } else { num = floor(dnum); } num = MAX(num, 2); num = [self limitCheck:num against:MAXBINS]; if (sel == RB_HIGH) tlow = thigh - num * twidth; else thigh = tlow + num * twidth; } else { num = h_getBinNum(adisplay, axis); } } if (logAxis && tlow <= 0.0) tlow = 2 * FLT_MIN; if (tlow >= thigh) { if (checkBins) thigh = tlow + twidth; else thigh = tlow * (1.0 + 2.0 * FLT_EPSILON) + 2.0 * FLT_MIN; } if ((high != thigh) || (sel == RB_HIGH)) { re_display = YES; high = thigh; } if ((low != tlow) || (sel == RB_LOW)) { re_display = YES; low = tlow; } if ((twidth != width) || (sel == RB_WIDTH)) { if (checkBins) { re_display = YES; width = twidth; } } toff = [rbForm floatValueAt:RB_OFF]; if (toff != offset) { re_display = YES; toff = MIN(toff, 1.0); toff = MAX(toff, -1.0); high -= offset * width; low -= offset * width; offset = toff; high += offset * width; low += offset * width; } if ( re_display == YES ) { p.x = low; p.y = high; [graphicView graphicsPerform:@selector(setRange:to:) with:(id)&axis with:(id)&p andDraw:NO]; [graphicView graphicsPerform: @selector(setNumBins:to:) with:(id)&axis with:(id)&num andDraw:YES]; width = (high - low)/num; [rbForm setFloatValue:width at:RB_WIDTH]; } [[[graphicView window] flushWindow] makeKeyWindow]; return self; } - scaleType:sender { /* called when the AutoScale or logScale button is clicked */ SEL theMethod = 0; int theState; theState = [sender state]; switch ([sender tag]) { case 0: /* AutoScale X-axis */ theMethod = @selector(setAutoScale:to:); break; case 2: /* Log Scale X-axis */ theMethod = @selector(setLogScale:to:); break; } [graphicView graphicsPerform:theMethod with:&axis with :(id)&theState andDraw:YES]; [[[graphicView window] flushWindow] makeKeyWindow]; return self; } - mouseMoved:(const NXPoint *)point in:sender withKey:(int)flag { display disp; binding_t xaxis = XAXIS, yaxis = YAXIS, zaxis = ZAXIS; NXPoint p; float lo, hi; int no; float diff, range; BOOL checkBins, logAxis; if ( selectedPlot ) { disp = [selectedPlot histDisplay]; } else { disp = [selectedPlot histDisplay]; } if ( !disp ) return self; logAxis = h_getLogAxis(disp, XAXIS); checkBins = checkDisplay( disp, XAXIS, &lo, &hi, &no ); range = hi - lo; diff = 2.0 * range; p.y = hi - point->x * diff / 100; if ( logAxis && lo <= range ) { diff = 10.0 * lo - 0.1 * lo; } p.x = lo - point->x * diff / 100; [graphicView graphicsPerform:@selector(setRange:to:) with:(id)&xaxis with:(id)&p andDraw:YES]; logAxis = h_getLogAxis(disp, YAXIS); checkBins = checkDisplay( disp, YAXIS, &lo, &hi, &no ); range = hi - lo; diff = 2.0 * range; p.y = hi - point->y * diff / 100; if ( logAxis && lo <= range ) { diff = 10.0 * lo - 0.1 * lo; } p.x = lo - point->y * diff / 100; [graphicView graphicsPerform:@selector(setRange:to:) with:(id)&yaxis with:(id)&p andDraw:YES]; logAxis = h_getLogAxis(disp, ZAXIS); checkBins = checkDisplay( disp, ZAXIS, &lo, &hi, &no ); range = hi - lo; diff = 2.0 * range; p.y = hi - point->x * diff / 100; if ( logAxis && lo <= range ) { diff = 10.0 * lo - 0.1 * lo; } p.x = lo - point->x * diff / 100; [graphicView graphicsPerform:@selector(setRange:to:) with:(id)&zaxis with:(id)&p andDraw:YES]; [[[graphicView window] flushWindow] makeKeyWindow]; return self; } /* Internal methods */ - setTags { if (axis == XAXIS) { [[TickMatrix cellAt:0 :0] setTitle:"Bottom"]; [TickMatrix setTag:PLOTBOTTOM at:0 :0]; [[ScaleMatrix cellAt:0 :0] setTitle:"Bottom"]; [ScaleMatrix setTag:PLOTBOTTOM at:0 :0]; [[LabelMatrix cellAt:0 :0] setTitle:"Bottom"]; [LabelMatrix setTag:PLOTBOTTOM at:0 :0]; [[TickMatrix cellAt:0 :1] setTitle:"Top"]; [TickMatrix setTag:PLOTTOP at:0 :1]; [[ScaleMatrix cellAt:0 :1] setTitle:"Top"]; [ScaleMatrix setTag:PLOTTOP at:0 :1]; [[LabelMatrix cellAt:0 :1] setTitle:"Top"]; [LabelMatrix setTag:PLOTTOP at:0 :1]; } else if (axis == YAXIS) { [[TickMatrix cellAt:0 :0] setTitle:"Left"]; [TickMatrix setTag:PLOTLEFT at:0 :0]; [[ScaleMatrix cellAt:0 :0] setTitle:"Left"]; [ScaleMatrix setTag:PLOTLEFT at:0 :0]; [[LabelMatrix cellAt:0 :0] setTitle:"Left"]; [LabelMatrix setTag:PLOTLEFT at:0 :0]; [[TickMatrix cellAt:0 :1] setTitle:"Right"]; [TickMatrix setTag:PLOTRIGHT at:0 :1]; [[ScaleMatrix cellAt:0 :1] setTitle:"Right"]; [ScaleMatrix setTag:PLOTRIGHT at:0 :1]; [[LabelMatrix cellAt:0 :1] setTitle:"Right"]; [LabelMatrix setTag:PLOTRIGHT at:0 :1]; } return self; } - titleForm:sender { const char *string; string = [titleForm stringValueAt:0]; switch (axis) { case XAXIS: [graphicView graphicsPerform:@selector(NameAxisX:) with:(id)string andDraw:YES]; break; case YAXIS: [graphicView graphicsPerform:@selector(NameAxisY:) with:(id)string andDraw:YES]; break; case ZAXIS: [graphicView graphicsPerform:@selector(NameAxisZ:) with:(id)string andDraw:YES]; break; default : string = NULL; break; } [[graphicView window] flushWindow]; return self; } - resetTitle:sender { const char *string; display disp; if ( !selectedPlot ) { return self; } switch (axis) { case XAXIS: string = "%x"; [graphicView graphicsPerform:@selector(NameAxisX:) with:(id)string andDraw:YES]; break; case YAXIS : disp = [selectedPlot histDisplay]; if ( h_getDispType(disp) == HISTOGRAM ) { string = "Entries / %dx bin"; } else { string = "%y"; } [graphicView graphicsPerform:@selector(NameAxisY:) with:(id)string andDraw:YES]; break; case ZAXIS : string = "%z"; [graphicView graphicsPerform:@selector(NameAxisZ:) with:(id)string andDraw:YES]; break; default : string = NULL; break; } [titleForm setStringValue:string at:0]; [[graphicView window] flushWindow]; return self; } - updateView { display disp; int pos; plotloc_t loc; float f; if ( selectedPlot ) disp = [ selectedPlot histDisplay ]; else if (firstPlot ) disp = [ firstPlot histDisplay ]; else { lastPlot = nil; return self; } /* * set the axis title */ switch (axis) { case XAXIS: [titleForm setStringValue:h_getAxisLabel(disp,XAXIS) at:0]; break; case YAXIS: [titleForm setStringValue:h_getAxisLabel(disp,YAXIS) at:0]; break; case ZAXIS: [titleForm setStringValue:h_getAxisLabel(disp,ZAXIS) at:0]; break; default : [titleForm setStringValue:"" at:0]; break; } /* * set the tick buttons */ loc = h_getTickLocation( disp, axis ); for (pos = 1; pos <= 16; pos <<= 1) { if (loc & pos) [TickMatrix selectCellWithTag:pos]; } /* * set the scale radio buttons */ loc = h_getScaleLocation( disp, axis ); [ScaleMatrix selectCellWithTag:(int)loc]; /* * set the scale radio buttons */ loc = h_getLabelLocation( disp, axis ); [LabelMatrix selectCellWithTag:(int)loc]; /* * set the font size field */ f = h_getScaleFontSize( disp, axis ); [ScaleFontSize setFloatValue: f]; f = h_getTickLength( disp, axis ); [TickLength setFloatValue: f]; [self updateOptions]; [self updateSliders]; if ( lastPlot != firstPlot) { prevIndex = -1; prevValue = 999.999; } lastPlot = firstPlot; return self; } - updateOptions { display disp; BOOL enable; if (!selectedPlot) disp = [selectedPlot histDisplay]; else disp = [firstPlot histDisplay]; graphtype = h_getDispType(disp); if (graphtype == HISTOGRAM) currentDim = 1; else currentDim = 2; if (graphtype == LEGOPLOT || graphtype == THREEDSCATTER || graphtype == COLORPLOT || (graphtype == HISTOGRAM && axis == XAXIS)) { enable = NO; } else { enable = YES; } [logScaleButton setEnabled:enable]; [autoScaleButton setState:h_getAutoScale(disp, axis)]; [logScaleButton setState:h_getLogAxis(disp, axis)]; return self; } - updateSliders { float range; BOOL logAxis, checkBins; display disp; if (!selectedPlot) disp = [selectedPlot histDisplay]; else disp = [firstPlot histDisplay]; logAxis = h_getLogAxis(disp, axis); checkBins = checkDisplay( disp, axis, &low, &high, &num ); if (checkBins) { width = (high - low) / num; [rbForm setFloatValue:width at: RB_WIDTH]; [rbSlider[RB_WIDTH] setMinValue:(width * 0.5)]; [rbSlider[RB_WIDTH] setMaxValue:(width * 1.5)]; [rbSlider[RB_WIDTH] setFloatValue:width]; [rbSlider[RB_WIDTH] setEnabled:YES]; [[rbForm cellAt:RB_WIDTH :0] setEnabled:YES]; } else { width = 0.0; [rbForm setStringValue:"" at:RB_WIDTH]; [rbSlider[RB_WIDTH] setEnabled:NO]; [[rbForm cellAt:RB_WIDTH :0] setEnabled:NO]; } range = high - low; [rbForm setFloatValue:high at:RB_HIGH]; [rbForm setFloatValue:low at:RB_LOW]; [rbSlider[RB_HIGH] setMinValue:(double) (low + width)]; [rbSlider[RB_HIGH] setMaxValue:(double) (high + range)]; [rbSlider[RB_HIGH] setFloatValue:high]; if (logAxis) { if (low <= range) { [rbSlider[RB_LOW] setMinValue:(double) low/10.0]; [rbSlider[RB_LOW] setMaxValue:(double) low*10.0]; } else { [rbSlider[RB_LOW] setMinValue:(double) (low - range)]; [rbSlider[RB_LOW] setMaxValue:(double) (high - width)]; } } else { [rbSlider[RB_LOW] setMinValue:(double) (low - range)]; [rbSlider[RB_LOW] setMaxValue:(double) (high - width)]; } [rbSlider[RB_LOW] setFloatValue:low]; if (checkBins) { [rbForm setFloatValue:0. at:RB_OFF ]; [rbSlider[RB_OFF] setMinValue:-1.]; [rbSlider[RB_OFF] setMaxValue: 1.]; [rbSlider[RB_OFF] setFloatValue: 0.]; [rbSlider[RB_OFF] setEnabled:YES]; [[rbForm cellAt:RB_OFF :0] setEnabled:YES]; } else { [rbForm setStringValue:"" at:RB_OFF]; [rbSlider[RB_OFF] setEnabled:NO]; [[rbForm cellAt:RB_OFF :0] setEnabled:NO]; } offset = 0.0; return self; } - (int) limitCheck:(int) nbins against:(int)maxbins { int irc; static int prevnbins=0; if ( numLimitCheck == NO ) return nbins; if ( nbins > maxbins && numLimitCheck == YES ) { if (nbins == prevnbins) { nbins = maxbins; return nbins; /* ignore double events */ } prevnbins = nbins; irc = NXRunAlertPanel( "Alert", "Greater than %d bins may cause performace problems", "Cancel", "Proceed", NULL, maxbins ); if ( irc == NX_ALERTDEFAULT ) { nbins = maxbins; } else { numLimitCheck = NO; [ limitCheckButton setState: NO ]; } } return nbins; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.