This is Box.m in view mode; [Download] [Up]
/* Implementation of Box class * * Copyright (C) 1993, 1994, 1995 The Board of Trustees of * The Leland Stanford Junior University. All Rights Reserved. * * Authors: Scott Francis, Paul Kunz, Imran Qureshi, and Libing Wang * * This file is part of an Objective-C class library for a window system * * Box.m,v 1.38 1995/06/26 23:02:15 fedor Exp */ #include "Box.h" #include <objc/List.h> #include "TextFieldCell.h" #include "graphics.h" #include "stdmacros.h" #include <objc/typedstream2.h> extern char * BoxInstanceName(void); @interface View(WidgetSet) - _setOffsets:(NXSize *)offsets; @end @interface Box(WidgetSet) - _init; - _setBorderType:(int)borderType; - _managedBy:parent wid:(void *)widget; @end @implementation Box - initFrame:(const NXRect *)frameRect { View *aView; NXRect rect; offsets.width = DEF_OFFSET; offsets.height = DEF_OFFSET; [super initFrame:frameRect]; instancename = BoxInstanceName(); /* inherit class from VIEW. it should be xmBulletinBoardWidgetClass */ borderRect = *frameRect; rect.origin.x = DEF_OFFSET; rect.origin.y = DEF_OFFSET; rect.size.width = borderRect.size.width - DEF_OFFSET*2; rect.size.height = borderRect.size.height - DEF_OFFSET*2; aView = [[View alloc] initFrame:&rect]; [self setContentView:aView]; titleRect.size.height = 25; titleRect.size.width = 50; titleRect.origin.x = titleRect.origin.y = 0; cell = NULL; [self setTitlePosition:NX_ATTOP]; [self setTitle:"Title"]; [self setBorderType:NX_RIDGE]; return self; } - awake { /* lets instantiate the appropriate title cell widget, but let the title cell do the work */ [super awake]; if (!cell && (bFlags.titlePosition != NX_NOTITLE)) { cell = [[TextFieldCell alloc] init]; [cell _setFrame:&titleRect inView:(Control *)self]; [cell setStringValue:title]; } return self; } // - free; - (int)borderType { return bFlags.borderType; } - (int)titlePosition { return bFlags.titlePosition; } - setBorderType:(int)borderType { [self _setBorderType:borderType]; return self; } - setTitlePosition:(int)pos { NXRect temp; if (cell) { [cell _getFrame:&titleRect]; } /* x value is the same for all: centered horizontally */ titleRect.origin.x = frame.origin.x + (frame.size.width / 2) - (titleRect.size.width / 2); if (pos == NX_NOTITLE && cell) { [cell free]; } else if (pos != NX_NOTITLE && !cell) { cell = [[TextFieldCell alloc] init]; [cell _setFrame:&titleRect inView:(Control *)self]; } switch (pos) { case (NX_NOTITLE): break; /* original code with Motif y coordinate * case (NX_ABOVETOP): * titleRect.origin.y = frame.origin.y; // at very top * borderRect.size.height = frame.size.height - titleRect.size.height; * borderRect.origin.y = frame.origin.y + titleRect.size.height; * break; * case (NX_ATTOP): * titleRect.origin.y = frame.origin.y; * borderRect.size.height =frame.size.height-(titleRect.size.height/2); * borderRect.origin.y = frame.origin.y + (titleRect.size.height/2); * break; * case (NX_BELOWTOP): * titleRect.origin.y = frame.origin.y; * borderRect.size.height = frame.size.height; * borderRect.origin.y = frame.origin.y; * break; * case (NX_ABOVEBOTTOM): * titleRect.origin.y = frame.size.height - titleRect.size.height; * borderRect.origin.y = frame.origin.y; * borderRect.size.height = frame.size.height; * break; * case (NX_ATBOTTOM): * titleRect.origin.y = frame.size.height - titleRect.size.height; * borderRect.origin.y = frame.origin.y; * borderRect.size.height = frame.size.height-titleRect.size.height/2; * break; * case (NX_BELOWBOTTOM): * titleRect.origin.y = frame.size.height - titleRect.size.height; * borderRect.origin.y = frame.origin.y; * borderRect.size.height = frame.size.height - titleRect.size.height; * break; */ case (NX_ABOVETOP): titleRect.origin.y = frame.size.height - titleRect.size.height; borderRect.size.height = frame.size.height - titleRect.size.height; borderRect.origin.y = frame.origin.y; break; case (NX_ATTOP): titleRect.origin.y = frame.size.height - titleRect.size.height/1; borderRect.size.height =frame.size.height-(titleRect.size.height/2); borderRect.origin.y = frame.origin.y; break; case (NX_BELOWTOP): titleRect.origin.y = frame.origin.y - titleRect.size.height; borderRect.size.height = frame.size.height; borderRect.origin.y = frame.origin.y; break; case (NX_ABOVEBOTTOM): titleRect.origin.y = frame.origin.y; borderRect.origin.y = frame.origin.y; borderRect.size.height = frame.size.height; break; case (NX_ATBOTTOM): titleRect.origin.y = frame.origin.y; borderRect.origin.y = frame.origin.y + titleRect.size.height/2; borderRect.size.height = frame.size.height - titleRect.size.height/2; break; case (NX_BELOWBOTTOM): titleRect.origin.y = frame.origin.y; borderRect.origin.y = frame.origin.y + titleRect.size.height; borderRect.size.height = frame.size.height - titleRect.size.height; break; default: return self; } [cell _setFrame:&titleRect inView:(Control *)self]; bFlags.titlePosition = pos; temp.size.width = borderRect.size.width - offsets.width*2; temp.size.height = borderRect.size.height - offsets.height*2; [contentView sizeTo:temp.size.width :temp.size.height]; [self _setBorder:&borderRect]; return self; } - (const char *)title { const char *cellTitle; cellTitle = [cell stringValue]; return ((cellTitle) ? cellTitle : "Title") ; } - setTitle:(const char *)aString { if (!aString) return self; [cell setStringValue:aString]; // sets the title [self sizeToFit]; // size the box to fit this title // and size its subviews, etc return self; } - cell { return cell; } - font { return nil; } - setFont:fontObj { return self; } - getOffsets:(NXSize *)theSize { theSize->width = offsets.width; theSize->height = offsets.height; return self; } - setOffsets:(NXCoord)horizontal :(NXCoord)vertical { offsets.width = horizontal; offsets.height = vertical; [borderView _setOffsets:&offsets]; [self sizeToFit]; return self; } - sizeTo:(NXCoord)width :(NXCoord)height { NXSize newSize; // for the contentview NXCoord dw, dh; dw = frame.size.width - width; dh = frame.size.height - height; [super sizeTo:width :height]; // now adjust the borderRect and the box widget... borderRect.size.width -= dw; borderRect.size.height -= dh; [borderView sizeTo:borderRect.size.width :borderRect.size.height]; // now resize the contentview. newSize.width = borderRect.size.width - offsets.width*2; newSize.height = borderRect.size.height - offsets.height*2; [contentView sizeTo:newSize.width :newSize.height]; // move the cell to new position according to bFlags.titlePosition if (bFlags.titlePosition > NX_BELOWTOP) { [cell _moveTo:(titleRect.origin.x-(dw/2)) :(titleRect.origin.y+dh)]; } else if (bFlags.titlePosition) { [cell _moveTo:(titleRect.origin.x - (dw/2)) :titleRect.origin.y]; } return self; } - sizeToFit /* This method tries to do a lot of work... Designed to wrap the box around the contentview and title box. If either has become too large, we must resize to be larger. */ { NXRect cview, tbox; if ([contentView respondsTo:@selector(sizeToFit)]) { [(Box *)contentView sizeToFit]; } // should resize contentview if it can't do itself, but I'm // not sure how to proceed for this... [contentView getFrame:&cview]; [cell _getFrame:&tbox]; if ((borderRect.size.width >= cview.size.width + 2*offsets.width) || (borderRect.size.height >= cview.size.height + 2*offsets.height) || (borderRect.size.width >= tbox.size.width) || (NX_MAXY(&frame) >= NX_MAXY(&tbox))) { return self; } borderRect.origin.x = cview.origin.x - offsets.width; borderRect.origin.y = cview.origin.y - offsets.height; borderRect.size.width = MAX((NX_MAXX(&cview) + offsets.width), (tbox.size.width)); borderRect.size.height = (NX_MAXY(&cview) + offsets.height); frame.origin.x = borderRect.origin.x; frame.size.width = borderRect.size.width; switch (bFlags.titlePosition) { /* old code with Motif y coordinate * case (NX_NOTITLE): * case (NX_BELOWTOP): * frame.origin.y = titleRect.origin.y; * frame.size.height = borderRect.size.height; * break; * case (NX_ABOVETOP): * frame.origin.y = tbox.origin.y; * frame.size.height = borderRect.size.height + tbox.size.height; * break; * case (NX_ATTOP): * frame.origin.y = tbox.origin.y; * frame.size.height = borderRect.size.height + tbox.size.height/2; * break; * case (NX_ABOVEBOTTOM): * frame.origin.y = borderRect.origin.y; * frame.size.height = borderRect.size.height; * break; * case (NX_ATBOTTOM): * frame.origin.y = borderRect.origin.y; * frame.size.height = borderRect.size.height + tbox.size.height/2; * break; * case (NX_BELOWBOTTOM): * frame.origin.y = borderRect.origin.y; * frame.size.height = borderRect.size.height+tbox.size.height; * break; * default: * fprintf(stderr, "Error: erroneous title position\n"); * break; * } */ case (NX_NOTITLE): case (NX_BELOWTOP): frame.origin.y = borderRect.origin.y; frame.size.height = borderRect.size.height; break; case (NX_ABOVETOP): frame.origin.y = borderRect.origin.y; frame.size.height = borderRect.size.height + tbox.size.height; break; case (NX_ATTOP): frame.origin.y = borderRect.origin.y; frame.size.height = borderRect.size.height + tbox.size.height/2; break; case (NX_ABOVEBOTTOM): frame.origin.y = borderRect.origin.y; frame.size.height = borderRect.size.height; break; case (NX_ATBOTTOM): frame.origin.y = borderRect.origin.y - tbox.size.height/2; frame.size.height = borderRect.size.height + tbox.size.height/2; break; case (NX_BELOWBOTTOM): frame.origin.y = borderRect.origin.y - tbox.size.height; frame.size.height = borderRect.size.height+tbox.size.height; break; default: fprintf(stderr, "Error: erroneous title position\n"); break; } /* frame.size.height = (NX_MAXY(&frame) > NX_MAXY(&tbox)) ? frame.size.height : NX_MAXY(&tbox) - frame.origin.y; */ [self _setBorder:&borderRect]; return self; } - setFrameFromContentFrame:(const NXRect *)contentFrame { return self; } - contentView { return contentView; } - setContentView:aView { View *oldContentView = nil; int dh; /* Well, this should really resize the view before adding it to the box, in order to stay with NeXT compliance. For now scrap that until done debugging box. Okay, here is the resizing! */ dh = [self heightAdjust]; [aView sizeTo:(borderRect.size.width - offsets.width*2) :(borderRect.size.height) - offsets.height*2 - dh]; if ( contentView ) { oldContentView = [super replaceSubview:contentView with:aView]; contentView = aView; } else { oldContentView = nil; [self addSubview:aView]; } // we need something to redraw the text label of the box here // return oldContentView; } - addSubview:aView { [contentView addSubview:aView]; [self sizeToFit]; return self; } - replaceSubview:oldView with:newView { return [contentView replaceSubview:oldView with:newView]; } // - drawSelf:(const NXRect *)rects :(int)rectCount // - write:(NXTypedStream *)stream; - read:(TypedStream *)ts { int border,titlePosition; [super read:ts]; objc_read_string(ts, &title); objc_read_type(ts, "i", &border); // this step is for backward bFlags.borderType = border; // compatibility. objc_read_type(ts, "i", &titlePosition); // one should really write bFlags.titlePosition = titlePosition; // the entire bFlags struct. objc_read_type(ts, "i", &(offsets.width)); objc_read_type(ts, "i", &(offsets.height)); NXReadRect(ts, &borderRect); NXReadRect(ts, &titleRect); contentView = [subviews objectAt:0]; return self; } // obsolete methods // + newFrame:(const NXRect *)frameRect; /* Methods not in NeXTSTEP */ - (int)heightAdjust { int dh; switch (bFlags.titlePosition) { case (NX_ABOVETOP): case (NX_BELOWBOTTOM): dh = titleRect.size.height; break; case (NX_ATTOP): case (NX_ATBOTTOM): dh = titleRect.size.height/2; break; default: dh = 0; break; } return dh; } /* Sometimes we need to change the border. This is where you do it. Notice that since it does motif work it starts with the underscore in the method name. Don't call sizeToFit:: because this should only be called internally, when we should know whether or not we want to sizeToFit:: or not. Notice we use the borderRect to set the bounds of the widget, though the logical space of the box is as large as its frame Rect (and its physical size is as large as title widget + bulletin board widget) Note that this changes the _boxwid widget, because we want its border to be thus set, not the border of the outer widget, or container widget. */ - _setBorder:(NXRect *)aBorder { [borderView _setBorderRect:aBorder]; return self; } - (void *)_widget { return [borderView _widget]; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.