This is HRulerView.m in view mode; [Download] [Up]
// // Time-stamp: <95/12/08 22:57:29 stephan> // // HRulerView.m // Project: Rulers // // Stephan Wacker // 93-02-11 #import "HRulerView.h" #import "HRulerControl.h" #import "RulerPreferencesControl.h" #import "math.h" // ceil() @implementation HRulerView - initFrame: (const NXRect *) frameRect // Initialize yourself after instance has been created. { NXSize offset; [super initFrame: frameRect]; // Move origin (from left bottom corner) to the right // by 20% of frame width (truncated to an integer). offset.width = floor( 0.2 * NX_WIDTH( frameRect ) ); offset.height = 0.0; [self moveOrigin: &offset]; // Initially, the ``valid'' cached image is a rectangle of zero width // at the very left edge of the ruler view. validRect.size.height = NX_HEIGHT( frameRect ); imageOrigin.x = origin.x; return self; } - drawMarks: (const NXRect *) aRect // Draw the marks in the cachedImage. // aRect is given in Ruler coordinates. // Background is drawn by super. // Drawing is lockFocused in cachedImage. { NXCoord x; int k; char str[40]; NXCoord tick_baselength, tick_length; const TickMark *mark; BOOL displayLabels = [control labelsMode]; int marksPosition = [control hMarksMode]; int posNumDirection = [control hPosNumMode]; NXFontMetrics *metrics = [markFont metrics]; // font dimensions float capHeight = metrics->capHeight * [markFont pointSize]; NXSetColor( [control marksColor] ); PSsetlinewidth( 0.25 ); // thin lines tick_baselength = 18.0; // main mark length [markFont set]; // Process every set of marks. // for( mark = [self tickMarkSystem]; mark->distance > 0.0; mark++ ) { tick_length = mark->length * tick_baselength; // start with // x = k * mark->distance + imageOrigin.x, // x < NX_X(&bounds) for( k = (int) ceil( (NX_X(aRect)-imageOrigin.x)/mark->distance ) - 1, x = k * mark->distance + imageOrigin.x + 0.25, k *= mark->value; x < NX_MAXX(aRect) + mark->distance; k += mark->value, x += mark->distance ) { if( marksPosition & HMARKS_BOTTOM ) { PSmoveto( x, NX_Y(&bounds) ); PSrlineto( 0.0, tick_length ); // a tick mark } if( marksPosition & HMARKS_TOP ) { PSmoveto( x, NX_MAXY(&bounds) ); PSrlineto( 0.0, -tick_length ); // a tick mark } if( displayLabels ) { if( mark->value > 0 ) { sprintf( str, "%d", k < 0 ? ((posNumDirection & POSNUM_LEFT ) ? -k : k) : ((posNumDirection & POSNUM_RIGHT) ? k : -k) ); PSmoveto( x - 0.5 * ([markFont getWidthOf: str]-1.0), 0.5 * (NX_HEIGHT(&bounds) - (capHeight + 0.0)) ); PSshow( str ); } else if( mark->value < 0 ) { // display a fraction like `3/8' // !toDo! } } } // for k, x } // for mark PSstroke(); // draw all tick marks return self; } - (NXCoord) constrainDistance: (NXCoord) distance frame: (NXRect *) frameRect // PRIVATE // Change the frameRect's width by distance. // Observe minimum and maximum sizes. // Answer actual width change. { NXSize minSize, maxSize; NXCoord minDist, maxDist; NXCoord result = distance + off; [window getMinSize: &minSize]; [window getMaxSize: &maxSize]; maxDist = maxSize.width - NX_WIDTH( frameRect ); minDist = minSize.width - NX_WIDTH( frameRect ); off = 0; if( result < minDist ) { off = result - minDist; result = minDist; } if( result > maxDist ) { off = result - maxDist; result = maxDist; } if( result * distance < 0.0 ) // cancel opposite direction { off += result; result = 0.0; } NX_WIDTH( frameRect ) += result; return result; } - sizeRight: (const NXSize *) delta // Change the window's width by delta (to the right). // Positive distance increases width. { NXCoord distance = delta->width; if( !(distance = [self constrainDistance: distance frame: &rubberRect]) ) return nil; // size is not changed [self drawRubberband]; return self; } - sizeLeft: (const NXSize *) delta // Change the window's width by delta (to the left). // Positive distance decreases width. { NXCoord distance = -delta->width; if( !(distance = [self constrainDistance: distance frame: &rubberRect]) ) return nil; // size is not changed NX_X( &rubberRect ) -= distance; // move left edge origin.x += distance; // adjust local origin [self drawRubberband]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.