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.