ftp.nice.ch/pub/next/developer/resources/classes/MOKit.1.0.0.s.tar.gz#/MOKit_1.0.0/Palettes/MORegexPalette/MORegexTextCellInspector.m

This is MORegexTextCellInspector.m in view mode; [Download] [Up]

// MORegexTextCellInspector.m
//
// by Mike Ferris
// Part of MOKit - MORegexPalette
// Copyright 1993, all rights reserved.


// ABOUT MOKit
// by Mike Ferris (mike@lorax.com)
//
// MOKit is a collection of useful and general objects.  Permission is 
// granted by the author to use MOKit in your own programs in any way 
// you see fit.  All other rights pertaining to the kit are reserved by the 
// author including the right to sell these objects as objects,  as part 
// of a LIBRARY, or as SOURCE CODE.  In plain English, I wish to retain 
// rights to these objects as objects, but allow the use of the objects 
// as pieces in a fully functional program.  Permission is also granted to 
// redistribute the source code of MOKit for FREE as long as this copyright 
// notice is left intact and unchanged.  NO WARRANTY is expressed or implied.  
// The author will under no circumstances be held responsible for ANY 
// consequences from the use of these objects.  Since you don't have to pay 
// for them, and full source is provided, I think this is perfectly fair.

#import "MORegexTextCellInspector.h"
#import "MOKit/MORegexTextCell.h"
#import "MOKit/MOString.h"
#import <objc/objc-runtime.h>

#define CLASS_VERSION	0
#define CLASS_NAME		"MORegexTextCellInspector"

#define ADD_TAG			0
#define CHANGE_TAG		1
#define REMOVE_TAG		2

#define BG_NONE_TAG		0
#define BG_BLACK_TAG	1
#define BG_DKGRAY_TAG	2
#define BG_LTGRAY_TAG	3
#define BG_WHITE_TAG	4

#define TG_BLACK_TAG	0
#define TG_DKGRAY_TAG	1
#define TG_LTGRAY_TAG	2
#define TG_WHITE_TAG	3

#define ALIGN_LEFT_TAG		0
#define ALIGN_CENTER_TAG	1
#define ALIGN_RIGHT_TAG		2

#define BORDER_NONE_TAG		0
#define BORDER_LINE_TAG		1
#define BORDER_BEZEL_TAG	2

#define EDITABLE_CB_TAG		0
#define SELECTABLE_CB_TAG	1
#define SCROLLABLE_CB_TAG	2

#define BUNDLE_TYPE							"bundle"
#define MOREGEXTEXTCELL_CLASS_NAME			"MORegexTextCell"

#define NIB_TYPE							"nib"
#define NIB_NAME							"MORegexTextCellInspector"

@interface MORegexTextCellInspector(Private)

+ (Class)MO_loadClassBundle:(const char *)className;

@end

@implementation MORegexTextCellInspector

static id MORegexTextCellClass;

+ (Class)MO_loadClassBundle:(const char *)className
// Finds the bundle of the same name as the class, grabs it and loads the
// class from it and returns the named class.
{
	char pathBuff[MAXPATHLEN+1];
	id classBundle = nil;
	Class class = nil;
	
	// Load the bundle
	if ((class = objc_lookUpClass(className)) == nil)  {
		// class is not already loaded... load it.
		
		// Look for the bundle in the main bundle first, 
		// else try in this class's bundle.
		if (![[NXBundle mainBundle] getPath:pathBuff forResource:className 
					ofType:BUNDLE_TYPE])  {
			if (![[NXBundle bundleForClass:[self class]] getPath:pathBuff 
						forResource:className ofType:BUNDLE_TYPE])  {
				NXLogError("[%s loadClassBundle] failed to "
						"find %s class bundle.", [self name], className);
				return nil;
			}
		}
		classBundle = [[NXBundle allocFromZone:[self zone]] 
					initForDirectory:pathBuff];
		if (!classBundle)  {
			NXLogError("[%s loadClassBundle] failed to "
						"create bundle for class %s.", [self name], className);
			return nil;
		}
		if ((class = [classBundle classNamed:className]) == nil)  {
			NXLogError("[%s loadClassBundle] failed to "
						"load %s class from bundle.", [self name], className);
			return nil;
		}
	}
	
	return class;
}

+ initialize
// Set the version.
{
	if (self == objc_lookUpClass(CLASS_NAME))  {
		[self setVersion:CLASS_VERSION];

		// Load the MORegexTextCell class if necessary
		MORegexTextCellClass = 
					[self MO_loadClassBundle:MOREGEXTEXTCELL_CLASS_NAME];
	}
	return self;
}

- init
// Load our nib file.
{
	char buf[MAXPATHLEN+1];
	id bundle;
	
	[super init];
	
	// load our nib file.
	bundle = [NXBundle bundleForClass:[self class]];
	[bundle getPath:buf forResource:NIB_NAME ofType:NIB_TYPE];
	[NXApp loadNibFile:buf owner:self withNames:NO fromZone:[self zone]];
	
	[patternText setDelegate:self];
	[patternText setCharFilter:NXFieldFilter];
	[patternText setFont:[Font userFixedPitchFontOfSize:0 
				matrix:NX_FLIPPEDMATRIX]];
	
	return self;
}

- (int)browserSelectedRow
// Return the row that is selected in the patternBrowser or -1 if none is.
{
	return [[patternBrowser matrixInColumn:0] selectedRow];
}

- (const char *)getPatternText
{
	static char *text=NULL;
	
	if (text) NX_FREE(text);
	NX_MALLOC(text, char, [patternText byteLength]+1);
	[patternText getSubstring:text start:0 length:[patternText textLength]+1];
	return text;
}

- enablePatternButtons
// Enables or disables the add, change, remove buttons as appropriate for
// the current state of the inspector.
{
	if ([self browserSelectedRow] == -1)  {
		[[patternButtonMatrix cellAt:0 :CHANGE_TAG] setEnabled:NO];
		[[patternButtonMatrix cellAt:0 :REMOVE_TAG] setEnabled:NO];
	}  else  {
		[[patternButtonMatrix cellAt:0 :CHANGE_TAG] setEnabled:YES];
		[[patternButtonMatrix cellAt:0 :REMOVE_TAG] setEnabled:YES];
	}
	
	if (strlen([self getPatternText])>0)  {
		[[patternButtonMatrix cellAt:0 :ADD_TAG] setEnabled:YES];
	}  else  {
		[[patternButtonMatrix cellAt:0 :ADD_TAG] setEnabled:NO];
		[[patternButtonMatrix cellAt:0 :CHANGE_TAG] setEnabled:NO];
	}
	return self;
}

- browserAction:sender
// Copies the string of the currently selected pattern to the pattern text
// field for editing.
{
	int row = [self browserSelectedRow];
	
	// put the text of the selected row's pattern in the patternField.
	if (row >= 0)  {
		[patternText setText:[object regexStrAt:row]];
	}  else  {
		[patternText setText:""];
	}
	[patternText sizeToFit];
	[patternText setSel:0 :[patternText textLength]];
	[self enablePatternButtons];
    return self;
}

- patternButtonAction:sender
// Adds the text of patternField to the cell's patterns, or changes the pattern
// currently selected in the patternBrowser to the text in patternField, or 
// removes the pattern in the selected row of the patternBrowser from the
// cell's patterns.
{
	int tag = [[sender selectedCell] tag];
	const char *pattern = [self getPatternText];
	char *pcpy;
	int row = [self browserSelectedRow];
	id matrix = [patternBrowser matrixInColumn:0];
	
	NX_MALLOC(pcpy, char, strlen(pattern)+1);
	strcpy(pcpy, pattern);
	
	if (tag==ADD_TAG)  {
		// add the string in patternField to the object's patterns.
		if ((!pattern) || (!*pattern) || 
					(![MORegexTextCellClass isValidRegex:pattern]))  {
			NXRunAlertPanel("Regexp Error", "'%s' is not a valid regular "
						"expression.", "OK", NULL, NULL, pattern);
			NX_FREE(pcpy);
			return self;
		}
		[object addRegexStr:pattern];
	}  else if (tag==CHANGE_TAG)  {
		// change the pattern at the index of the selected row in the 
		// browser to the string in patternField.
		id string = [[object regexStrList] objectAt:row];
		if ((!pattern) || (!*pattern) || 
					(![MORegexTextCellClass isValidRegex:pattern]))  {
			NXRunAlertPanel("Regexp Error", "'%s' is not a valid regular "
						"expression.", "OK", NULL, NULL, pattern);
			NX_FREE(pcpy);
			return self;
		}
		[string setStringValue:pattern];
	}  else if (tag==REMOVE_TAG)  {
		// remove the pattern at the index of the selected row in the browser.
		[object removeRegexStrAt:row];
		NX_FREE(pcpy);
		pcpy = NULL;
		pattern = [[matrix cellAt:((row==0)?1:row-1) :0] stringValue];
		if (pattern)  {
			NX_MALLOC(pcpy, char, strlen(pattern)+1);
			strcpy(pcpy, pattern);
		}
	}
	[patternBrowser reloadColumn:0];
	if (pcpy)  {
		char *buff;
		NX_MALLOC(buff, char, strlen(pcpy)+2);
		sprintf(buff, "/%s", pcpy);
		[patternBrowser setPath:buff];
		NX_FREE(buff);
	}
	NX_FREE(pcpy);
	[self browserAction:patternBrowser];
	
	[self enablePatternButtons];
	[self touch:self];
	
    return self;
}

- optionsCheckboxAction:sender
{
	id selCell = [sender selectedCell];
	int selTag = [selCell tag];
	
	if (selTag == EDITABLE_CB_TAG)  {
		id selectableCB = [optionsCheckboxMatrix cellAt:SELECTABLE_CB_TAG:0];
		if ([selCell state])  {
			[selectableCB setState:YES];
			[selectableCB setEnabled:NO];
		}  else  {
			[selectableCB setEnabled:YES];
		}
	}
	[optionsCheckboxMatrix display];
	if ([[optionsCheckboxMatrix cellAt:EDITABLE_CB_TAG:0] state])  {
		[object setEditable:YES];
	}  else  {
		[object setEditable:NO];
		if ([[optionsCheckboxMatrix cellAt:SELECTABLE_CB_TAG:0] state])  {
			[object setSelectable:YES];
		}  else  {
			[object setSelectable:NO];
		}
	}
	[object setScrollable:[[optionsCheckboxMatrix 
				cellAt:0:SCROLLABLE_CB_TAG] state]];
	return self;
}

- ok:sender
// set the text field-ish stuff and the allowEmptyString attribute.  
// The patternButtonAction takes care of the regex stuff.  The 
// optionCheckboxAction takes care of editable, selectable, scrollable.
{
	int bgTag = [backgroundGrayMatrix selectedTag];
	int tgTag = [textGrayMatrix selectedTag];
	int alTag = [alignmentMatrix selectedTag];
	int boTag = [borderMatrix selectedTag];
	
	if (bgTag == BG_NONE_TAG)  {
		[object setBackgroundGray:-1.0];
	}  else if (bgTag == BG_BLACK_TAG)  {
		[object setBackgroundGray:NX_BLACK];
	}  else if (bgTag == BG_DKGRAY_TAG)  {
		[object setBackgroundGray:NX_DKGRAY];
	}  else if (bgTag == BG_LTGRAY_TAG)  {
		[object setBackgroundGray:NX_LTGRAY];
	}  else  {
		[object setBackgroundGray:NX_WHITE];
	}
	if (tgTag == TG_BLACK_TAG)  {
		[object setTextGray:NX_BLACK];
	}  else if (tgTag == TG_DKGRAY_TAG)  {
		[object setTextGray:NX_DKGRAY];
	}  else if (tgTag == TG_LTGRAY_TAG)  {
		[object setTextGray:NX_LTGRAY];
	}  else  {
		[object setTextGray:NX_WHITE];
	}
	if (alTag == ALIGN_LEFT_TAG)  {
		[object setAlignment:NX_LEFTALIGNED];
	}  else if (alTag == ALIGN_CENTER_TAG)  {
		[object setAlignment:NX_CENTERED];
	}  else  {
		[object setAlignment:NX_RIGHTALIGNED];
	}
	if (boTag == BORDER_NONE_TAG)  {
		[object setBordered:NO];
		[object setBezeled:NO];
	}  else if (boTag == BORDER_LINE_TAG)  {
		[object setBordered:YES];
	}  else  {
		[object setBezeled:YES];
	}

	[object setTag:[tagForm intValueAt:0]];
	[object setAllowEmptyString:[allowEmptyStringButton state]];
	return [super ok:sender];
}

- revert:sender
// fill in the inspector with the attributes of "object"
{
	id matrix;
	
	float bg = [object backgroundGray], tg = [object textGray];
	int alignment = [object alignment];
	BOOL isBordered = [object isBordered], isBezeled = [object isBezeled];
	
	if (bg < 0)  {
		[backgroundGrayMatrix selectCellAt:0:BG_NONE_TAG];
	}  else  if ((bg >= 0) && (bg < .2))  {
		[backgroundGrayMatrix selectCellAt:0:BG_BLACK_TAG];
	}  else  if ((bg >= .2) && (bg < .45))  {
		[backgroundGrayMatrix selectCellAt:0:BG_DKGRAY_TAG];
	}  else  if ((bg >= .45) && (bg < .8))  {
		[backgroundGrayMatrix selectCellAt:0:BG_LTGRAY_TAG];
	}  else  if (bg >= .8)  {
		[backgroundGrayMatrix selectCellAt:0:BG_WHITE_TAG];
	}
	[backgroundGrayMatrix display];
	if (tg < .2)  {
		[textGrayMatrix selectCellAt:0:TG_BLACK_TAG];
	}  else  if ((tg >= .2) && (tg < .45))  {
		[textGrayMatrix selectCellAt:0:TG_DKGRAY_TAG];
	}  else  if ((tg >= .45) && (tg < .8))  {
		[textGrayMatrix selectCellAt:0:TG_LTGRAY_TAG];
	}  else  if (tg >= .8)  {
		[textGrayMatrix selectCellAt:0:TG_WHITE_TAG];
	}
	[textGrayMatrix display];
	if (alignment == NX_LEFTALIGNED)  {
		[alignmentMatrix selectCellAt:0:ALIGN_LEFT_TAG];
	}  else if (alignment == NX_CENTERED)  {
		[alignmentMatrix selectCellAt:0:ALIGN_CENTER_TAG];
	}  else  {
		[alignmentMatrix selectCellAt:0:ALIGN_RIGHT_TAG];
	}
	[alignmentMatrix display];
	if (isBezeled)  {
		[borderMatrix selectCellAt:0:BORDER_BEZEL_TAG];
	}  else if (isBordered)  {
		[borderMatrix selectCellAt:0:BORDER_LINE_TAG];
	}  else  {
		[borderMatrix selectCellAt:0:BORDER_NONE_TAG];
	}
	[optionsCheckboxMatrix setState:[object isEditable] 
				at:EDITABLE_CB_TAG:0];
	[optionsCheckboxMatrix setState:[object isSelectable] 
				at:SELECTABLE_CB_TAG:0];
	[optionsCheckboxMatrix setState:[object isScrollable] 
				at:SCROLLABLE_CB_TAG:0];

	[allowEmptyStringButton setState:[object doesAllowEmptyString]];
	[tagForm setIntValue:[object tag] at:0];
	
	// browser
	[patternBrowser loadColumnZero];
	
	matrix = [patternBrowser matrixInColumn:0];
	if ([matrix cellCount] > 0)  {
		const char *pattern = [[matrix cellAt:0:0] stringValue];
		char *buff;
		NX_MALLOC(buff, char, strlen(pattern)+2);
		sprintf(buff, "/%s", pattern);
		[patternBrowser setPath:buff];
		NX_FREE(buff);
	}
	[self browserAction:patternBrowser];
	
	[self enablePatternButtons];
	[patternButtonMatrix display];
	
	return [super revert:sender];
}

- (BOOL)wantsButtons
// Our inspector does not have OK or Revert buttons.
{
	return NO;
}

- (int)browser:sender fillMatrix:matrix inColumn:(int)column
// Fill the browser with the pattern strings from the cell.
{
	int i, c = [object regexStrCount];
	
	for (i=0; i<c; i++)  {
		[matrix renewRows:i+1 cols:1];
		[[matrix cellAt:i :0] setStringValue:[object regexStrAt:i]];
		[[matrix cellAt:i :0] setLoaded:YES];
		[[matrix cellAt:i :0] setLeaf:YES];
	}
	
	return i;
}

- textDidGetKeys:sender isEmpty:(BOOL)flag
// Having text in the patternField affects what buttons to enable.
{
	if (sender==patternText)  {
		[self enablePatternButtons];
		[patternButtonMatrix display];
	}
	return self;
}

- textDidChange:sender;
// The patternField shouldn't be passed on.
{
	if (sender==patternText)  {
		return self;
	}  else  {
		return [super textDidChange:sender];
	}
}

@end

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.