diff --git a/ChangeLog b/ChangeLog index 823ed01ec..5a90fd12c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,52 @@ +Wed Dec 3 14:12:35 1997 Ovidiu Predescu + + Added the code to support the loading of model files (similar to nib + files under OPENSTEP). The model file is a human readable and + modifiable file which is portable across many OpenStep implementations. + * Model: New directory. + * Model/GMAppKit.h: New file. + * Model/GMAppKit.m: Likewise. + * Model/GNUmakefile: Likewise. + * Model/IBClasses.h: Likewise. + * Model/IBClasses.m: Likewise. + * Model/IMConnectors.h: Likewise. + * Model/IMConnectors.m: Likewise. + * Model/IMCustomObject.h: Likewise. + * Model/IMCustomObject.m: Likewise. + * Model/IMLoading.h: Likewise. + * Model/IMLoading.m: Likewise. + * Model/Translator.h: Likewise. + * Model/Translator.m: Likewise. + * Model/nib2gmodel.m: Likewise. + * Model/test.nib: Likewise. + * Model/test.m: Likewise. + * Model/test.gmodel: Likewise. + * Model/Controller.h: Likewise. + * Model/Controller.m: Likewise. + + Support the standard OpenStep images in NSImage: + * Images/nsmapping.strings: New file. It contains the mapping between + the OpenStep name to the GNUstep file name that contains the image. + * Images/GNUmakefile: Added nsmapping.strings to the list of files that + get installed. + * Source/NSImage.m: Support the above modification. + + * Headers/gnustep/gui/NSView.h + (_unconditionallyResetNeedsDisplayInAllViews): Define the method. + (setAutoDisplay:): Fixed typo. + * Source/NSView.m: New method that unconditionally sets the additional + pointers needed for display and flush in NSView. + * Source/NSApplication.m (nextEventMatchingMask:untilDate:inMode: + dequeue:): Flush the communication channel after the while loop ends. + * Source/NSMenu.m: Changed the definition of MAX. + (_resizeMenuForCellSize): Resize the menu cells matrix to fit all the + cells. + (sizeToFit): Call _resizeMenuForCellSize to resize the cells matrix. + * Source/NSTextField.m (selectedCell): New method. + * Source/NSWindow.m: Include . + (dealloc, setContentView:): Clean up the code. + (setAutodisplay): Fixed typo. + Fri Nov 14 09:34:45 1997 Scott Christley * Headers/gnustep/gui/NSApplication.h (-getNextEvent): Method @@ -67,6 +116,15 @@ Thu Oct 30 15:51:43 1997 Scott Christley * Tools/GNUmakefile.postamble: Install after instead of before. * Tools/GNUmakefile.preamble: Add directory and library. +Wed Oct 29 13:02:53 1997 Ovidiu Predescu + + * Source/NSView.m (_removeSubviewFromViewsThatNeedDisplay:): New + method to remove a view from its super view linked list of views that + need display. + (removeFromSuperview): Invoke the above method to remove itself from + the list of views that need display. + (replaceSubview:with:): Likewise. + Wed Oct 29 12:22:22 1997 Ovidiu Predescu Bug fixes for NSForm and NSFormCell from Benhur Stein diff --git a/Headers/gnustep/gui/NSMenu.h b/Headers/gnustep/gui/NSMenu.h index 8cca74eb6..7d78767c9 100644 --- a/Headers/gnustep/gui/NSMenu.h +++ b/Headers/gnustep/gui/NSMenu.h @@ -102,7 +102,8 @@ - (BOOL)menuChangedMessagesEnabled; - (void)sizeToFit; -/* Getting the menu title */ +/* Getting and setting the menu title */ +- (void)setTitle:(NSString*)aTitle; - (NSString*)title; /* Getting the menu cells matrix */ diff --git a/Headers/gnustep/gui/NSView.h b/Headers/gnustep/gui/NSView.h index b19eb4f06..c4f164f65 100644 --- a/Headers/gnustep/gui/NSView.h +++ b/Headers/gnustep/gui/NSView.h @@ -356,6 +356,7 @@ enum { - (void)_recursivelyResetNeedsDisplayInAllViews; - (void)_removeSubviewFromViewsThatNeedDisplay:(NSView*)view; - (void)_displayNeededViews; +- (void)_unconditionallyResetNeedsDisplayInAllViews; /* Collects into `array' the invalid rectangles that need to be displayed. All the rectangles are expressed in the window coordinates and not of the views diff --git a/Headers/gnustep/gui/NSWindow.h b/Headers/gnustep/gui/NSWindow.h index 25167fdae..04cf7a258 100644 --- a/Headers/gnustep/gui/NSWindow.h +++ b/Headers/gnustep/gui/NSWindow.h @@ -259,7 +259,7 @@ extern NSSize NSTokenSize; - (void)flushWindowIfNeeded; - (BOOL)isAutodisplay; - (BOOL)isFlushWindowDisabled; -- (void)setAutoDisplay:(BOOL)flag; +- (void)setAutodisplay:(BOOL)flag; - (void)setViewsNeedDisplay:(BOOL)flag; - (void)update; - (void)useOptimizedDrawing:(BOOL)flag; diff --git a/Images/GNUmakefile b/Images/GNUmakefile index 69bc7d9bb..54934d30b 100644 --- a/Images/GNUmakefile +++ b/Images/GNUmakefile @@ -51,7 +51,8 @@ common_SwitchOff.tiff \ common_SliderHoriz.tiff \ common_SliderVert.tiff \ common_Dimple.tiff \ -common_ret.tiff +common_ret.tiff \ +nsmapping.strings -include GNUmakefile.preamble diff --git a/Images/nsmapping.strings b/Images/nsmapping.strings new file mode 100644 index 000000000..d1a1fd4ea --- /dev/null +++ b/Images/nsmapping.strings @@ -0,0 +1,8 @@ +/* This file contains the mapping of the OPENSTEP names of the images to the + actual files where the GNUstep keeps them. The format is the "strings" + format and content is trivial. */ + +NSSwitch = common_SwitchOff; +NSHighlightedSwitch = common_SwitchOn; +NSRadioButton = common_RadioOff; +NSHighlightedRadioButton = common_RadioOn; diff --git a/Model/.cvsignore b/Model/.cvsignore new file mode 100644 index 000000000..1d1f68c29 --- /dev/null +++ b/Model/.cvsignore @@ -0,0 +1,9 @@ +GNUmakefile.local +*obj +*.app +*.debug +*.profile +.gdbinit +*.nib~ +*.iconheader + diff --git a/Model/Controller.h b/Model/Controller.h new file mode 100644 index 000000000..6f420412d --- /dev/null +++ b/Model/Controller.h @@ -0,0 +1,8 @@ +#import + +@interface Controller : NSObject +{ + id textField; +} +- (void)buttonPressed:(id)sender; +@end diff --git a/Model/Controller.m b/Model/Controller.m new file mode 100644 index 000000000..995705df5 --- /dev/null +++ b/Model/Controller.m @@ -0,0 +1,13 @@ +#import "Controller.h" + +@implementation Controller + +- (void)buttonPressed:(id)sender +{ + NSString* text + = [NSString stringWithFormat:@"\"%@\" button pressed", [sender title]]; + + [textField setStringValue:text]; +} + +@end diff --git a/Model/GMAppKit.h b/Model/GMAppKit.h new file mode 100644 index 000000000..838b3816d --- /dev/null +++ b/Model/GMAppKit.h @@ -0,0 +1,71 @@ +/* + GMAppKit.h + + Copyright (C) 1996 Free Software Foundation, Inc. + + Author: Ovidiu Predescu + Date: November 1997 + + This file is part of the GNUstep GUI Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _GNUstep_H_GMAppKit +#define _GNUstep_H_GMAppKit + +#include +#import + +@interface NSApplication (GMArchiverMethods) +@end + +@interface NSButton (GMArchiverMethods) +@end + +@interface NSCell (GMArchiverMethods) +@end + +@interface NSColor (GMArchiverMethods) +@end + +@interface NSControl (GMArchiverMethods) +@end + +@interface NSFont (GMArchiverMethods) +@end + +@interface NSImage (GMArchiverMethods) +@end + +@interface NSMenuItem (GMArchiverMethods) +@end + +@interface NSMenu (GMArchiverMethods) +@end + +@interface NSResponder (GMArchiverMethods) +@end + +@interface NSTextField (GMArchiverMethods) +@end + +@interface NSView (GMArchiverMethods) +@end + +@interface NSWindow (GMArchiverMethods) +@end + +#endif /* _GNUstep_H_GMAppKit */ diff --git a/Model/GMAppKit.m b/Model/GMAppKit.m new file mode 100644 index 000000000..a4e88ed1c --- /dev/null +++ b/Model/GMAppKit.m @@ -0,0 +1,733 @@ +/* + GMAppKit.m + + Copyright (C) 1996 Free Software Foundation, Inc. + + Author: Ovidiu Predescu + Date: November 1997 + + This file is part of the GNUstep GUI Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#import +#import +#include "GMAppKit.h" + +void __dummy_GMAppKit_functionForLinking() {} + +@implementation NSApplication (GMArchiverMethods) + +- (void)encodeWithModelArchiver:(GMArchiver*)archiver +{ +#if NeXT_GUI_LIBRARY + NSArray* windows1 = [self windows]; + NSMutableArray* windows2 = [NSMutableArray array]; + int i, count = [windows1 count]; + + for (i = 0; i < count; i++) { + NSWindow* window = [windows1 objectAtIndex:i]; + + if (![window isKindOfClass:[NSMenu class]]) + [windows2 addObject:window]; + } + [archiver encodeObject:windows2 withName:@"windows"]; + +#else + [archiver encodeObject:[self windows] withName:@"windows"]; +#endif + [archiver encodeObject:[self keyWindow] withName:@"keyWindow"]; + [archiver encodeObject:[self mainWindow] withName:@"mainWindow"]; + [archiver encodeObject:[self mainMenu] withName:@"mainMenu"]; +} + +- (id)initWithModelUnarchiver:(GMUnarchiver*)unarchiver +{ + NSArray* windows; + NSWindow* keyWindow; + NSWindow* mainWindow; + NSMenu* mainMenu; + +#if GNU_GUI_LIBRARY + mainMenu = [unarchiver decodeObjectWithName:@"mainMenu"]; + [self setMainMenu:mainMenu]; +#endif + + windows = [unarchiver decodeObjectWithName:@"windows"]; + keyWindow = [unarchiver decodeObjectWithName:@"keyWindow"]; + mainWindow = [unarchiver decodeObjectWithName:@"mainWindow"]; + +#if NeXT_GUI_LIBRARY + mainMenu = [unarchiver decodeObjectWithName:@"mainMenu"]; + [self setMainMenu:mainMenu]; +#endif + + [keyWindow makeKeyWindow]; + [mainWindow makeMainWindow]; + + return self; +} + +- (void)awakeFromModel +{ + NSMenu* mainMenu = [self mainMenu]; + + [mainMenu update]; +#if XDPS_BACKEND_LIBRARY + [mainMenu display]; +#endif + +} + ++ (id)createObjectForModelUnarchiver:(GMUnarchiver*)unarchiver +{ + return [NSApplication sharedApplication]; +} + +- (Class)classForModelArchiver +{ + return [NSApplication class]; +} + +@end /* NSApplication (GMArchiverMethods) */ + + +@implementation NSButton (GMArchiverMethods) + +- (void)encodeWithModelArchiver:(GMArchiver*)archiver +{ + float delay, interval; + id theCell = [self cell]; + + [self getPeriodicDelay:&delay interval:&interval]; + [archiver encodeInt:[self state] withName:@"state"]; + [archiver encodeFloat:delay withName:@"delay"]; + [archiver encodeFloat:interval withName:@"interval"]; + [archiver encodeString:[self title] withName:@"title"]; + [archiver encodeString:[self alternateTitle] withName:@"alternateTitle"]; + [archiver encodeObject:[self image] withName:@"image"]; + [archiver encodeObject:[self alternateImage] withName:@"alternateImage"]; + [archiver encodeInt:[self imagePosition] withName:@"imagePosition"]; + [archiver encodeBOOL:[self isBordered] withName:@"isBordered"]; + [archiver encodeBOOL:[self isTransparent] withName:@"isTransparent"]; + [archiver encodeString:[self keyEquivalent] withName:@"keyEquivalent"]; + [archiver encodeInt:[theCell highlightsBy] withName:@"highlightsBy"]; + [archiver encodeInt:[theCell showsStateBy] withName:@"showsStateBy"]; + + [super encodeWithModelArchiver:archiver]; +} + +- (id)initWithModelUnarchiver:(GMUnarchiver*)unarchiver +{ + float delay, interval; + id theCell = [self cell]; + + self = [super initWithModelUnarchiver:unarchiver]; + + [self setState:[unarchiver decodeIntWithName:@"state"]]; + + delay = [unarchiver decodeFloatWithName:@"delay"]; + interval = [unarchiver decodeFloatWithName:@"interval"]; + [self setPeriodicDelay:delay interval:interval]; + + [self setTitle:[unarchiver decodeStringWithName:@"title"]]; + [self setAlternateTitle:[unarchiver decodeStringWithName:@"alternateTitle"]]; + [self setImage:[unarchiver decodeObjectWithName:@"image"]]; + [self setAlternateImage:[unarchiver decodeObjectWithName:@"alternateImage"]]; + [self setImagePosition:[unarchiver decodeIntWithName:@"imagePosition"]]; + [self setBordered:[unarchiver decodeBOOLWithName:@"isBordered"]]; + [self setTransparent:[unarchiver decodeBOOLWithName:@"isTransparent"]]; + [self setKeyEquivalent:[unarchiver decodeStringWithName:@"keyEquivalent"]]; + [theCell setHighlightsBy:[unarchiver decodeIntWithName:@"highlightsBy"]]; + [theCell setShowsStateBy:[unarchiver decodeIntWithName:@"showsStateBy"]]; + + return self; +} + +- (Class)classForModelArchiver +{ + return [NSButton class]; +} + +@end /* NSButton (GMArchiverMethods) */ + + +@implementation NSCell (GMArchiverMethods) + +- (void)encodeWithModelArchiver:(GMArchiver*)archiver +{ + [archiver encodeObject:[self font] withName:@"font"]; +} + +- (id)initWithModelUnarchiver:(GMUnarchiver*)unarchiver +{ + NSFont* font = [unarchiver decodeObjectWithName:@"font"]; + if (!font) + font = [NSFont userFontOfSize:0]; + + [self setFont:font]; + return self; +} + +- (Class)classForModelArchiver +{ + return [NSCell class]; +} + +@end /* NSCell (GMArchiverMethods) */ + + +@implementation NSColor (GMArchiverMethods) + +- (void)encodeWithModelArchiver:(GMArchiver*)archiver +{ + NSString* colorSpaceName = [self colorSpaceName]; + + [archiver encodeString:colorSpaceName withName:@"colorSpaceName"]; + + if ([colorSpaceName isEqual:@"NSDeviceCMYKColorSpace"]) { + [archiver encodeFloat:[self cyanComponent] withName:@"cyan"]; + [archiver encodeFloat:[self magentaComponent] withName:@"magenta"]; + [archiver encodeFloat:[self yellowComponent] withName:@"yellow"]; + [archiver encodeFloat:[self blackComponent] withName:@"black"]; + [archiver encodeFloat:[self alphaComponent] withName:@"alpha"]; + } + else if ([colorSpaceName isEqual:@"NSDeviceWhiteColorSpace"] + || [colorSpaceName isEqual:@"NSCalibratedWhiteColorSpace"]) { + [archiver encodeFloat:[self whiteComponent] withName:@"white"]; + [archiver encodeFloat:[self alphaComponent] withName:@"alpha"]; + } + else if ([colorSpaceName isEqual:@"NSDeviceRGBColorSpace"] + || [colorSpaceName isEqual:@"NSCalibratedRGBColorSpace"]) { + [archiver encodeFloat:[self redComponent] withName:@"red"]; + [archiver encodeFloat:[self greenComponent] withName:@"green"]; + [archiver encodeFloat:[self blueComponent] withName:@"blue"]; + [archiver encodeFloat:[self alphaComponent] withName:@"alpha"]; + [archiver encodeFloat:[self hueComponent] withName:@"hue"]; + [archiver encodeFloat:[self saturationComponent] withName:@"saturation"]; + [archiver encodeFloat:[self brightnessComponent] withName:@"brightness"]; + } + else if ([colorSpaceName isEqual:@"NSNamedColorSpace"]) { + // TODO: change it when NSColor in GNUstep will have named color lists +#if 1 + NSColor* new + = [self colorUsingColorSpaceName:@"NSCalibratedRGBColorSpace"]; + [new encodeWithModelArchiver:archiver]; +#else + [unarchiver encodeString:[self catalogNameComponent] + withName:@"catalogName"]; + [unarchiver encodeString:[self colorNameComponent] withName:@"colorName"]; +#endif + } +} + ++ (id)createObjectForModelUnarchiver:(GMUnarchiver*)unarchiver +{ + NSString* colorSpaceName + = [unarchiver decodeStringWithName:@"colorSpaceName"]; + + if ([colorSpaceName isEqual:@"NSDeviceCMYKColorSpace"]) { + float cyan = [unarchiver decodeFloatWithName:@"cyan"]; + float magenta = [unarchiver decodeFloatWithName:@"magenta"]; + float yellow = [unarchiver decodeFloatWithName:@"yellow"]; + float black = [unarchiver decodeFloatWithName:@"black"]; + float alpha = [unarchiver decodeFloatWithName:@"alpha"]; + + return [NSColor colorWithDeviceCyan:cyan + magenta:magenta + yellow:yellow + black:black + alpha:alpha]; + } + else if ([colorSpaceName isEqual:@"NSDeviceWhiteColorSpace"]) { + float white = [unarchiver decodeFloatWithName:@"white"]; + float alpha = [unarchiver decodeFloatWithName:@"alpha"]; + + return [NSColor colorWithDeviceWhite:white alpha:alpha]; + } + else if ([colorSpaceName isEqual:@"NSCalibratedWhiteColorSpace"]) { + float white = [unarchiver decodeFloatWithName:@"white"]; + float alpha = [unarchiver decodeFloatWithName:@"alpha"]; + + return [NSColor colorWithCalibratedWhite:white alpha:alpha]; + } + else if ([colorSpaceName isEqual:@"NSDeviceRGBColorSpace"]) { + float red = [unarchiver decodeFloatWithName:@"red"]; + float green = [unarchiver decodeFloatWithName:@"green"]; + float blue = [unarchiver decodeFloatWithName:@"blue"]; + float alpha = [unarchiver decodeFloatWithName:@"alpha"]; + + return [self colorWithDeviceRed:red green:green blue:blue alpha:alpha]; + } + else if ([colorSpaceName isEqual:@"NSCalibratedRGBColorSpace"]) { + float red = [unarchiver decodeFloatWithName:@"red"]; + float green = [unarchiver decodeFloatWithName:@"green"]; + float blue = [unarchiver decodeFloatWithName:@"blue"]; + float alpha = [unarchiver decodeFloatWithName:@"alpha"]; + + return [self colorWithCalibratedRed:red green:green blue:blue alpha:alpha]; + } + else if ([colorSpaceName isEqual:@"NSNamedColorSpace"]) { + NSAssert (0, @"Named color spaces not supported yet!"); + } +} + +- (id)initWithModelUnarchiver:(GMUnarchiver*)unarchiver +{ + return self; +} + +- (Class)classForModelArchiver +{ + return [NSColor class]; +} + +@end /* NSColor (GMArchiverMethods) */ + + +@implementation NSControl (GMArchiverMethods) + +- (void)encodeWithModelArchiver:(GMArchiver*)archiver +{ + id target; + SEL action; + + if ((target = [self target])) + [archiver encodeObject:target withName:@"target"]; + if ((action = [self action])) + [archiver encodeSelector:action withName:@"action"]; + + [archiver encodeBOOL:[self isEnabled] withName:@"isEnabled"]; + [archiver encodeInt:[self alignment] withName:@"alignment"]; + [archiver encodeObject:[self font] withName:@"font"]; + [archiver encodeBOOL:[self isContinuous] withName:@"isContinuous"]; + [archiver encodeInt:[self tag] withName:@"tag"]; + [archiver encodeBOOL:[self ignoresMultiClick] withName:@"ignoresMultiClick"]; + + [super encodeWithModelArchiver:archiver]; +} + +- (id)initWithModelUnarchiver:(GMUnarchiver*)unarchiver +{ + self = [super initWithModelUnarchiver:unarchiver]; + + [self setTarget:[unarchiver decodeObjectWithName:@"target"]]; + [self setAction:[unarchiver decodeSelectorWithName:@"action"]]; + [self setEnabled:[unarchiver decodeBOOLWithName:@"isEnabled"]]; + [self setAlignment:[unarchiver decodeIntWithName:@"alignment"]]; + [self setFont:[unarchiver decodeObjectWithName:@"font"]]; + [self setContinuous:[unarchiver decodeBOOLWithName:@"isContinuous"]]; + [self setTag:[unarchiver decodeIntWithName:@"tag"]]; + [self setIgnoresMultiClick: + [unarchiver decodeBOOLWithName:@"ignoresMultiClick"]]; + + return self; +} + +- (Class)classForModelArchiver +{ + return [NSControl class]; +} + +@end /* NSControl (GMArchiverMethods) */ + + +@implementation NSFont (GMArchiverMethods) + +- (void)encodeWithModelArchiver:(GMArchiver*)archiver +{ + [archiver encodeString:[self fontName] withName:@"name"]; + [archiver encodeFloat:[self pointSize] withName:@"size"]; +} + ++ (id)createObjectForModelUnarchiver:(GMUnarchiver*)unarchiver +{ + return [NSFont fontWithName:[unarchiver decodeStringWithName:@"name"] + size:[unarchiver decodeFloatWithName:@"size"]]; +} + +- (id)initWithModelUnarchiver:(GMUnarchiver*)unarchiver +{ + return self; +} + +- (Class)classForModelArchiver +{ + return [NSFont class]; +} + +@end /* NSFont (GMArchiverMethods) */ + + +@implementation NSImage (GMArchiverMethods) + +- (void)encodeWithModelArchiver:(GMArchiver*)archiver +{ + [archiver encodeString:[self name] withName:@"name"]; + [archiver encodeSize:[self size] withName:@"size"]; +} + ++ (id)createObjectForModelUnarchiver:(GMUnarchiver*)unarchiver +{ + return [NSImage imageNamed:[unarchiver decodeStringWithName:@"name"]]; +} + +- (id)initWithModelUnarchiver:(GMUnarchiver*)unarchiver +{ + [self setSize:[unarchiver decodeSizeWithName:@"size"]]; + return self; +} + +- (Class)classForModelArchiver +{ + return [NSImage class]; +} + +@end /* NSImage (GMArchiverMethods) */ + + +@implementation NSMenuItem (GMArchiverMethods) + +- (void)encodeWithModelArchiver:(GMArchiver*)archiver +{ +#if XDPS_BACKEND_LIBRARY + [super encodeWithModelArchiver:archiver]; +#endif + + [archiver encodeObject:[self target] withName:@"target"]; + [archiver encodeSelector:[self action] withName:@"action"]; + [archiver encodeString:[self title] withName:@"title"]; + [archiver encodeInt:[self tag] withName:@"tag"]; + [archiver encodeBOOL:[self isEnabled] withName:@"isEnabled"]; + [archiver encodeString:[self keyEquivalent] withName:@"keyEquivalent"]; +} + +- (id)initWithModelUnarchiver:(GMUnarchiver*)unarchiver +{ +#if XDPS_BACKEND_LIBRARY + self = [super initWithModelUnarchiver:unarchiver]; +#endif + + [self setTarget:[unarchiver decodeObjectWithName:@"target"]]; + [self setAction:[unarchiver decodeSelectorWithName:@"action"]]; + [self setTitle:[unarchiver decodeStringWithName:@"title"]]; + [self setTag:[unarchiver decodeIntWithName:@"tag"]]; + [self setEnabled:[unarchiver decodeBOOLWithName:@"isEnabled"]]; + [self setKeyEquivalent:[unarchiver decodeStringWithName:@"keyEquivalent"]]; + +#if 0 + NSLog (@"menu item %@: target = %@, isEnabled = %d", + [self title], [self target], [self isEnabled]); +#endif + + return self; +} + +- (Class)classForModelArchiver +{ + return [NSMenuItem class]; +} + +@end /* NSMenuItem (GMArchiverMethods) */ + + +@implementation NSMenu (GMArchiverMethods) + +- (void)encodeWithModelArchiver:(GMArchiver*)archiver +{ + [archiver encodeObject:[self itemArray] withName:@"itemArray"]; + [archiver encodeBOOL:[self autoenablesItems] withName:@"autoenablesItems"]; + [archiver encodeString:[self title] withName:@"title"]; +} + +/* Define this method here because on OPENSTEP 4.x the NSMenu is inherited from + NSWindow and we don't want the NSWindow's method to be called. */ ++ (id)createObjectForModelUnarchiver:(GMUnarchiver*)unarchiver +{ + NSString* theTitle = [unarchiver decodeStringWithName:@"title"]; + return [[[self allocWithZone:[unarchiver objectZone]] initWithTitle:theTitle] + autorelease]; +} + +- (id)initWithModelUnarchiver:(GMUnarchiver*)unarchiver +{ + int i, count; + NSMutableArray* itemArray = [self itemArray]; + NSMutableArray* decodedItems + = [unarchiver decodeObjectWithName:@"itemArray"]; + + for (i = 0, count = [decodedItems count]; i < count; i++) + [self addItemWithTitle:@"dummy" action:NULL keyEquivalent:@""]; + + [itemArray replaceObjectsInRange:NSMakeRange(0, count) + withObjectsFromArray:decodedItems]; + + for (i = 0; i < count; i++) { + id item = [itemArray objectAtIndex:i]; + id target = [item target]; + + if ([target isKindOfClass:[NSMenu class]]) + [self setSubmenu:target forItem:item]; + } + + [self setAutoenablesItems: + [unarchiver decodeBOOLWithName:@"autoenablesItems"]]; + + [self sizeToFit]; + + return self; +} + +- (Class)classForModelArchiver +{ + return [NSMenu class]; +} + +@end /* NSMenu (GMArchiverMethods) */ + + +@implementation NSResponder (GMArchiverMethods) + +- (void)encodeWithModelArchiver:(GMArchiver*)archiver +{ + id nextResponder; + + if ((nextResponder = [self nextResponder])) + [archiver encodeObject:nextResponder withName:@"nextResponder"]; +} + +- (id)initWithModelUnarchiver:(GMUnarchiver*)unarchiver +{ + [self setNextResponder:[unarchiver decodeObjectWithName:@"nextResponder"]]; + return self; +} + +- (Class)classForModelArchiver +{ + return [NSResponder class]; +} + +@end /* NSResponder (GMArchiverMethods) */ + + +@implementation NSTextField (GMArchiverMethods) + +- (void)encodeWithModelArchiver:(GMArchiver*)archiver +{ + id theCell = [self cell]; + + [super encodeWithModelArchiver:archiver]; + + [archiver encodeBOOL:[self isSelectable] withName:@"isSelectable"]; + [archiver encodeSelector:[self errorAction] withName:@"errorAction"]; + [archiver encodeObject:[self textColor] withName:@"textColor"]; + [archiver encodeObject:[self backgroundColor] withName:@"backgroundColor"]; + [archiver encodeBOOL:[self drawsBackground] withName:@"drawsBackground"]; + [archiver encodeBOOL:[self isBordered] withName:@"isBordered"]; + [archiver encodeBOOL:[self isBezeled] withName:@"isBezeled"]; + [archiver encodeObject:[self nextText] withName:@"nextText"]; + [archiver encodeObject:[self previousText] withName:@"previousText"]; + [archiver encodeObject:[self delegate] withName:@"delegate"]; + [archiver encodeString:[self stringValue] withName:@"stringValue"]; + [archiver encodeBOOL:[self isEditable] withName:@"isEditable"]; + [archiver encodeBOOL:[theCell isScrollable] withName:@"isScrollable"]; +} + +- (id)initWithModelUnarchiver:(GMUnarchiver*)unarchiver +{ + id theCell = [self cell]; + BOOL flag; + + self = [super initWithModelUnarchiver:unarchiver]; + + [self setSelectable:[unarchiver decodeBOOLWithName:@"isSelectable"]]; + [self setErrorAction:[unarchiver decodeSelectorWithName:@"errorAction"]]; + [self setTextColor:[unarchiver decodeObjectWithName:@"textColor"]]; + [self setBackgroundColor: + [unarchiver decodeObjectWithName:@"backgroundColor"]]; + [self setDrawsBackground:[unarchiver decodeBOOLWithName:@"drawsBackground"]]; + + flag = [unarchiver decodeBOOLWithName:@"isBordered"]; + if (flag) + [self setBordered:flag]; + + flag = [unarchiver decodeBOOLWithName:@"isBezeled"]; + if (flag) + [self setBezeled:flag]; + + [self setNextText:[unarchiver decodeObjectWithName:@"nextText"]]; + [self setPreviousText:[unarchiver decodeObjectWithName:@"previousText"]]; + [self setDelegate:[unarchiver decodeObjectWithName:@"delegate"]]; + [theCell setStringValue:[unarchiver decodeStringWithName:@"stringValue"]]; + [self setEditable:[unarchiver decodeBOOLWithName:@"isEditable"]]; + [theCell setScrollable:[unarchiver decodeBOOLWithName:@"isScrollable"]]; + + return self; +} + +- (Class)classForModelArchiver +{ + return [NSTextField class]; +} + +@end /* NSTextField (GMArchiverMethods) */ + + +@implementation NSView (GMArchiverMethods) + +- (void)encodeWithModelArchiver:(GMArchiver*)archiver +{ + [super encodeWithModelArchiver:archiver]; + + [archiver encodeConditionalObject:[self superview] withName:@"superview"]; + [archiver encodeObject:[self subviews] withName:@"subviews"]; + [archiver encodeRect:[self frame] withName:@"frame"]; + [archiver encodeRect:[self bounds] withName:@"bounds"]; + [archiver encodeBOOL:[self postsFrameChangedNotifications] + withName:@"postsFrameChangedNotifications"]; + [archiver encodeBOOL:[self postsBoundsChangedNotifications] + withName:@"postsBoundsChangedNotifications"]; + [archiver encodeBOOL:[self autoresizesSubviews] + withName:@"autoresizesSubviews"]; + [archiver encodeUnsignedInt:[self autoresizingMask] + withName:@"autoresizingMask"]; +} + ++ (id)createObjectForModelUnarchiver:(GMUnarchiver*)unarchiver +{ + NSRect rect = [unarchiver decodeRectWithName:@"frame"]; + NSView* view = [[[self allocWithZone:[unarchiver objectZone]] + initWithFrame:rect] + autorelease]; + return view; +} + +- (id)initWithModelUnarchiver:(GMUnarchiver*)unarchiver +{ + NSArray* subviews; + int i, count; + id superview; + + self = [super initWithModelUnarchiver:unarchiver]; + + superview = [unarchiver decodeObjectWithName:@"superview"]; + [superview addSubview:self]; + + subviews = [unarchiver decodeObjectWithName:@"subviews"]; + for (i = 0, count = [subviews count]; i < count; i++) + [self addSubview:[subviews objectAtIndex:i]]; + + [self setBounds:[unarchiver decodeRectWithName:@"bounds"]]; + [self setPostsFrameChangedNotifications: + [unarchiver decodeBOOLWithName:@"postsFrameChangedNotifications"]]; + [self setPostsBoundsChangedNotifications: + [unarchiver decodeBOOLWithName:@"postsBoundsChangedNotifications"]]; + [self setAutoresizesSubviews: + [unarchiver decodeBOOLWithName:@"autoresizesSubviews"]]; + [self setAutoresizingMask: + [unarchiver decodeUnsignedIntWithName:@"autoresizingMask"]]; + + return self; +} + +- (Class)classForModelArchiver +{ + return [NSView class]; +} + +@end /* NSView (GMArchiverMethods) */ + + +@implementation NSWindow (GMArchiverMethods) + +- (void)encodeWithModelArchiver:(GMArchiver*)archiver +{ + [archiver encodeRect:[self frame] withName:@"frame"]; + [archiver encodeSize:[self maxSize] withName:@"maxSize"]; + [archiver encodeSize:[self minSize] withName:@"minSize"]; + [archiver encodeString:[self frameAutosaveName] + withName:@"frameAutosaveName"]; + [archiver encodeInt:[self level] withName:@"level"]; + [archiver encodeBOOL:[self isVisible] withName:@"isVisible"]; + [archiver encodeBOOL:[self isAutodisplay] withName:@"isAutodisplay"]; + [archiver encodeString:[self title] withName:@"title"]; + [archiver encodeString:[self representedFilename] + withName:@"representedFilename"]; + [archiver encodeBOOL:[self isReleasedWhenClosed] + withName:@"isReleasedWhenClosed"]; + [archiver encodeObject:[self contentView] withName:@"contentView"]; + [archiver encodeBOOL:[self hidesOnDeactivate] + withName:@"hidesOnDeactivate"]; + [archiver encodeObject:[self backgroundColor] withName:@"backgroundColor"]; + [archiver encodeUnsignedInt:[self styleMask] withName:@"styleMask"]; + [archiver encodeUnsignedInt:[self backingType] withName:@"backingType"]; +} + ++ (id)createObjectForModelUnarchiver:(GMUnarchiver*)unarchiver +{ + unsigned backingType = [unarchiver decodeUnsignedIntWithName:@"backingType"]; + unsigned styleMask = [unarchiver decodeUnsignedIntWithName:@"styleMask"]; + NSRect aRect = [unarchiver decodeRectWithName:@"frame"]; + NSWindow* win = [[[NSWindow allocWithZone:[unarchiver objectZone]] + initWithContentRect:aRect + styleMask:styleMask backing:backingType defer:YES] + autorelease]; + + return win; +} + +- (id)initWithModelUnarchiver:(GMUnarchiver*)unarchiver +{ + NSString* frameAutosaveName; + + [self setContentView:[unarchiver decodeObjectWithName:@"contentView"]]; + [self setMaxSize:[unarchiver decodeSizeWithName:@"maxSize"]]; + [self setMinSize:[unarchiver decodeSizeWithName:@"minSize"]]; + + frameAutosaveName = [unarchiver decodeStringWithName:@"frameAutosaveName"]; + if (frameAutosaveName) + [self setFrameAutosaveName:frameAutosaveName]; + + [self setLevel:[unarchiver decodeIntWithName:@"level"]]; + + [self setAutodisplay:[unarchiver decodeBOOLWithName:@"isAutodisplay"]]; + [self setTitle:[unarchiver decodeStringWithName:@"title"]]; + [self setRepresentedFilename: + [unarchiver decodeStringWithName:@"representedFilename"]]; + [self setReleasedWhenClosed: + [unarchiver decodeBOOLWithName:@"isReleasedWhenClosed"]]; + [self setHidesOnDeactivate: + [unarchiver decodeBOOLWithName:@"hidesOnDeactivate"]]; + [self setBackgroundColor: + [unarchiver decodeObjectWithName:@"backgroundColor"]]; + if ([unarchiver decodeBOOLWithName:@"isVisible"]) + [self orderFront:nil]; + +#if GNU_GUI_LIBRARY + [[[self contentView] superview] _unconditionallyResetNeedsDisplayInAllViews]; + [[self contentView] setNeedsDisplay:YES]; +#endif + + return self; +} + +- (Class)classForModelArchiver +{ + return [NSWindow class]; +} + +@end /* NSWindow (GMArchiverMethods) */ + diff --git a/Model/GNUmakefile b/Model/GNUmakefile new file mode 100644 index 000000000..cd87031fd --- /dev/null +++ b/Model/GNUmakefile @@ -0,0 +1,68 @@ +# GNUmakefile +# +# Copyright (C) 1996 Free Software Foundation, Inc. +# +# Author: Ovidiu Predescu +# Date: November 1997 +# +# This file is part of the GNUstep GUI Library. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# + +include $(GNUSTEP_SYSTEM_ROOT)/Makefiles/common.make + +LIBRARY_NAME = libgmodel + +ifeq ($(GUI_LIB), nx) +TOOL_NAME = nib2gmodel +endif + +APP_NAME = test + +libgmodel_OBJC_FILES = IMCustomObject.m IMConnectors.m IMLoading.m GMAppKit.m + +test_OBJC_FILES = test.m Controller.m + +nib2gmodel_OBJC_FILES = IBClasses.m Translator.m nib2gmodel.m + +# Additional library directories the linker should search +ifeq ($(FOUNDATION_LIB), nx) +ADDITIONAL_LIB_DIRS += -framework AppKit +endif + +# Additional flags to pass to the Objective-C compiler +ADDITIONAL_OBJCFLAGS = -Wall +ADDITIONAL_CPPFLAGS += $(RUNTIME_DEFINE) $(GUI_DEFINE) $(BACKEND_DEFINE) + +ADDITIONAL_LIB_DIRS += -L$(GNUSTEP_OBJ_DIR) + +ADDITIONAL_TOOL_LIBS += -lgmodel -lFoundationExt +ADDITIONAL_OBJC_FLAGS += $(BACKEND_DEFINE) + +# What are the libraries this library depends upon. This is needed for some +# systems where building a shared library requires to pass to the linker +# all the libraries the target library depends upon. + +LIBRARIES_DEPEND_UPON = -lFoundationExt $(FND_LIBS) $(GUI_LIBS) \ + $(BACKEND_LIBS) $(SYSTEM_LIBS) + +-include GNUmakefile.local + +include $(GNUSTEP_SYSTEM_ROOT)/Makefiles/library.make +include $(GNUSTEP_SYSTEM_ROOT)/Makefiles/tool.make +include $(GNUSTEP_SYSTEM_ROOT)/Makefiles/application.make + +-include GNUmakefile.postamble diff --git a/Model/IBClasses.h b/Model/IBClasses.h new file mode 100644 index 000000000..4b88e7383 --- /dev/null +++ b/Model/IBClasses.h @@ -0,0 +1,59 @@ +/* + IBClasses.h + + Copyright (C) 1996 Free Software Foundation, Inc. + + Author: Ovidiu Predescu + Date: November 1997 + + This file is part of the GNUstep GUI Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* This is a list of classes used internally by the NeXT's NIB stuff. These + classes were generated using the class-dump utility. */ + +#ifndef _GNUstep_H_IBClasses +#define _GNUstep_H_IBClasses + +#import + +@class NSString; + +@interface NSCustomObject : NSObject +{ + NSString *className; + id realObject; + id extension; +} +@end + + +@interface NSIBConnector : NSObject +{ + id source; + id destination; + NSString *label; +} +@end + +@interface NSIBOutletConnector : NSIBConnector +@end + +@interface NSIBControlConnector : NSIBConnector +@end + +#endif /* _GNUstep_H_IBClasses */ diff --git a/Model/IBClasses.m b/Model/IBClasses.m new file mode 100644 index 000000000..0effa327d --- /dev/null +++ b/Model/IBClasses.m @@ -0,0 +1,129 @@ +/* + IBClasses.m + + Copyright (C) 1996 Free Software Foundation, Inc. + + Author: Ovidiu Predescu + Date: November 1997 + + This file is part of the GNUstep GUI Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include + +#import +#import +#import +#import +#import "IBClasses.h" +#import "Translator.h" +#import "IMConnectors.h" +#import "IMCustomObject.h" + +//#define DEBUG + +@implementation NSCustomObject (NibToGModel) +- (id)awakeAfterUsingCoder:(NSCoder*)aDecoder +{ +#ifdef DEBUG + NSLog (@"%x awakeAfterUsingCoder NSCustomObject: className = %@, realObject = %@, " + @"extension = %@", self, className, realObject, extension); +#endif + [objects addObject:self]; + return self; +} + +- description +{ + return [NSString stringWithFormat:@"className = %@, realObject = %@, extension = %@", className, realObject, extension]; +} + +- nibInstantiate +{ + return self; +} + +- (void)encodeWithModelArchiver:(GMArchiver*)archiver +{ + [archiver encodeString:className withName:@"className"]; + if (realObject) + [archiver encodeObject:realObject withName:@"realObject"]; + if (extension) + [archiver encodeObject:extension withName:@"extension"]; +} + +- (Class)classForModelArchiver +{ + return [IMCustomObject class]; +} + +@end /* NSCustomObject */ + + +@implementation NSIBConnector (NibToGModel) +- (id)awakeAfterUsingCoder:(NSCoder*)aDecoder +{ +#ifdef DEBUG + NSLog (@"%x awakeAfterUsingCoder %@: source = %@, destination = %@, label = %@", + self, NSStringFromClass(isa), source, destination, label); +#endif + + [source retain]; + [destination retain]; + [label retain]; + [connections addObject:self]; + return self; +} + +- (void)encodeWithModelArchiver:(GMArchiver*)archiver +{ + [archiver encodeObject:source withName:@"source"]; + [archiver encodeObject:destination withName:@"destination"]; + [archiver encodeObject:label withName:@"label"]; +} + +- (Class)classForModelArchiver +{ + return [IMConnector class]; +} + +@end /* NSIBConnector */ + + +@implementation NSIBOutletConnector (NibToGModel) +- (void)establishConnection +{ +} + +- (Class)classForModelArchiver +{ + return [IMOutletConnector class]; +} + +@end /* NSIBOutletConnector */ + + +@implementation NSIBControlConnector (NibToGModel) +- (void)establishConnection +{ +} + +- (Class)classForModelArchiver +{ + return [IMControlConnector class]; +} +@end /* NSIBControlConnector */ diff --git a/Model/IMConnectors.h b/Model/IMConnectors.h new file mode 100644 index 000000000..110218bb6 --- /dev/null +++ b/Model/IMConnectors.h @@ -0,0 +1,55 @@ +/* + IMConnectors.h + + Copyright (C) 1996 Free Software Foundation, Inc. + + Author: Ovidiu Predescu + Date: November 1997 + + This file is part of the GNUstep GUI Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* These classes were inspired by IBConnectors classes from objcX, "an + Objective-C class library for a window system". The code was originally + written by Scott Francis, Paul Kunz, Imran Qureshi and Libing Wang. */ + +#ifndef _GNUstep_H_IMConnectors +#define _GNUstep_H_IMConnectors + +#import + +@interface IMConnector : NSObject +{ + id source; + id destination; + NSString* label; +} + +- source; +- destination; +- label; +@end + +@interface IMControlConnector:IMConnector +- (void)establishConnection; +@end + +@interface IMOutletConnector : IMConnector +- (void)establishConnection; +@end + +#endif /* _GNUstep_H_IMConnectors */ diff --git a/Model/IMConnectors.m b/Model/IMConnectors.m new file mode 100644 index 000000000..e40aba580 --- /dev/null +++ b/Model/IMConnectors.m @@ -0,0 +1,130 @@ +/* + IMConnectors.m + + Copyright (C) 1996 Free Software Foundation, Inc. + + Author: Ovidiu Predescu + Date: November 1997 + + This file is part of the GNUstep GUI Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include + +#import +#include +#include +#include "IMCustomObject.h" +#include "IMConnectors.h" + +static void +object_set_instance_variable (id anObject, + const char* variableName, + const void* value) +{ + struct objc_class* class; + struct objc_ivar_list* ivars; + int i; + + if (!anObject) + return; + +// NSLog (@"%@: setting ivar '%s' to %x", anObject, variableName, value); + class = [anObject class]; + ivars = class->ivars; + if (!ivars) + return; + + for (i = 0; i < ivars->ivar_count; i++) { + struct objc_ivar ivar = ivars->ivar_list[i]; + + if (ivar.ivar_name && !strcmp (ivar.ivar_name, variableName)) { + /* We found it! */ + *((id*)(((char*)anObject) + ivar.ivar_offset)) = value; + break; + } + } +} + +@implementation IMConnector + +- (void)encodeWithModelArchiver:(GMArchiver*)archiver +{ + [archiver encodeObject:source withName:@"source"]; + [archiver encodeObject:destination withName:@"destination"]; + [archiver encodeObject:label withName:@"label"]; +} + +- (id)initWithModelUnarchiver:(GMUnarchiver*)unarchiver +{ + source = [unarchiver decodeObjectWithName:@"source"]; + destination = [unarchiver decodeObjectWithName:@"destination"]; + label = [unarchiver decodeObjectWithName:@"label"]; + return self; +} + +- (id)source { return source; } +- (id)destination { return destination; } +- (id)label { return label; } + +@end /* IMConnector */ + + +@implementation IMControlConnector:IMConnector + +- (void)establishConnection +{ + id _source = [source nibInstantiate]; + id _destination = [destination nibInstantiate]; + SEL action = NSSelectorFromString (label); + + if ([_source respondsToSelector:@selector(setTarget:)]) { +// NSLog (@"%@: setting target to %@", _source, _destination); + [_source setTarget:_destination]; + } + else + object_set_instance_variable (_source, "target", _destination); + + if ([_source respondsToSelector:@selector(setAction:)]) { +// NSLog (@"%@: setting action to %@", +// _source, NSStringFromSelector(action)); + [_source setAction:action]; + } + else + object_set_instance_variable (_source, "action", action); +} + +@end /* IMControlConnector:IMConnector */ + + +@implementation IMOutletConnector + +- (void)establishConnection +{ + id _source = [source nibInstantiate]; + id _destination = [destination nibInstantiate]; + NSString* setMethodName = [@"set" stringByAppendingString: + [label capitalizedString]]; + SEL setSelector = NSSelectorFromString (setMethodName); + + if (setSelector && [_source respondsToSelector:setSelector]) + [_source performSelector:setSelector withObject:_destination]; + else + object_set_instance_variable(_source, [label cString], _destination); +} + +@end /* IMOutletConnector */ diff --git a/Model/IMCustomObject.h b/Model/IMCustomObject.h new file mode 100644 index 000000000..90f27c3ac --- /dev/null +++ b/Model/IMCustomObject.h @@ -0,0 +1,54 @@ +/* + IMCustomObject.h + + Copyright (C) 1996 Free Software Foundation, Inc. + + Author: Ovidiu Predescu + Date: November 1997 + + This file is part of the GNUstep GUI Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* This class was inspired by CustomObject class from objcX, "an Objective-C + class library for a window system". The code was originally written by + Paul Kunz and Imran Qureshi. */ + +#ifndef _GNUstep_H_IMCustomObject +#define _GNUstep_H_IMCustomObject + +#import + +/* Add an archiving category to object so every object can respond to + -nibInstantiate +*/ +@interface NSObject (ModelUnarchiving) +- (id)nibInstantiate; +@end + + +@interface IMCustomObject : NSObject +{ + NSString* className; + id realObject; + id extension; +} + +- (id)nibInstantiate; + +@end + +#endif /* _GNUstep_H_IMCustomObject */ diff --git a/Model/IMCustomObject.m b/Model/IMCustomObject.m new file mode 100644 index 000000000..88160ef03 --- /dev/null +++ b/Model/IMCustomObject.m @@ -0,0 +1,89 @@ +/* + IMCustomObject.m + + Copyright (C) 1996 Free Software Foundation, Inc. + + Author: Ovidiu Predescu + Date: November 1997 + + This file is part of the GNUstep GUI Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#import +#include +#include "IMCustomObject.h" + +@implementation NSObject(ModelUnarchiving) + +- (id)nibInstantiate +{ + return self; +} + +@end + + +@implementation IMCustomObject + +extern id _nibOwner; +extern BOOL _fileOwnerDecoded; + ++ (id)createObjectForModelUnarchiver:(GMUnarchiver*)unarchiver +{ + IMCustomObject* customObject = [[self new] autorelease]; + Class class; + + customObject->className = [unarchiver decodeStringWithName:@"className"]; + customObject->extension = [unarchiver decodeObjectWithName:@"extension"]; + customObject->realObject = [unarchiver decodeObjectWithName:@"realObject"]; + + if (!_fileOwnerDecoded) { + _fileOwnerDecoded = YES; + customObject->realObject = _nibOwner; + return customObject; + } + + class = NSClassFromString (customObject->className); + if (class) + customObject->realObject = [[class alloc] init]; + else { + NSLog (@"Class %@ not linked into application!", customObject->className); + } + + return customObject; +} + +- (id)nibInstantiate +{ + return realObject; +} + +- (void)encodeWithModelArchiver:(GMArchiver*)archiver +{ + [archiver encodeString:className withName:@"className"]; + if (realObject) + [archiver encodeObject:realObject withName:@"realObject"]; + if (extension) + [archiver encodeObject:extension withName:@"extension"]; +} + +- (id)initWithModelUnarchiver:(GMUnarchiver*)unarchiver +{ + return self; +} + +@end diff --git a/Model/IMLoading.h b/Model/IMLoading.h new file mode 100644 index 000000000..17047dafb --- /dev/null +++ b/Model/IMLoading.h @@ -0,0 +1,51 @@ +/* + IMLoading.h + + Copyright (C) 1996 Free Software Foundation, Inc. + + Author: Ovidiu Predescu + Date: November 1997 + + This file is part of the GNUstep GUI Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _GNUstep_H_IMLoading +#define _GNUstep_H_IMLoading + +#import + +@interface NSObject (NibAwaking) +- (void)awakeFromModel; +@end + + +@interface NSBundle (IMLoading) ++ (BOOL)loadIMFile:(NSString*)filename owner:(id)owner; +@end + + +@interface GMModel : NSObject +{ + NSArray* objects; + NSArray* connections; +} ++ (BOOL)loadIMFile:(NSString*)path owner:(id)owner; +- (void)_makeConnections; +- (void)_setObjects:objects connections:connections; +@end + +#endif /* _GNUstep_H_IMLoading */ diff --git a/Model/IMLoading.m b/Model/IMLoading.m new file mode 100644 index 000000000..d25b2d0e8 --- /dev/null +++ b/Model/IMLoading.m @@ -0,0 +1,139 @@ +/* + IMLoading.m + + Copyright (C) 1996 Free Software Foundation, Inc. + + Author: Ovidiu Predescu + Date: November 1997 + + This file is part of the GNUstep GUI Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#import +#import +#include +#include "IMLoading.h" +#include "IMCustomObject.h" + +void __dummy_IMLoading_functionForLinking() +{ + __dummy_IMLoading_functionForLinking(); +} + +@implementation NSBundle (IMLoading) + ++ (BOOL)loadIMFile:(NSString*)path owner:(id)owner +{ + return [GMModel loadIMFile:path owner:owner]; +} + +@end /* NSBundle(IMLoading) */ + + +@implementation GMModel + +id _nibOwner = nil; +BOOL _fileOwnerDecoded = NO; + ++ (void)initialize +{ + /* Force linking of AppKit GModel categories */ + extern void __dummy_GMAppKit_functionForLinking(); + __dummy_GMAppKit_functionForLinking (); +} + ++ (BOOL)loadIMFile:(NSString*)path owner:(id)owner +{ + GMUnarchiver* unarchiver = [GMUnarchiver unarchiverWithContentsOfFile:path]; + id previousNibOwner = _nibOwner; + GMModel* decoded; + + if (!unarchiver) + return NO; + + /* Set the _nibOwner to `owner' so that the first decoded custom object + replaces itself with `owner'. Also set _fileOwnerDecoded so that the + first custom object knows it's the first. */ + _nibOwner = owner; + _fileOwnerDecoded = NO; + + decoded = [unarchiver decodeObjectWithName:@"RootObject"]; + [decoded _makeConnections]; + + /* Restore the previous nib owner. We do this because loadIMFile:owner: can + be invoked recursively. */ + _nibOwner = previousNibOwner; + + return YES; +} + +- (void)_makeConnections +{ + int i, count; + + [connections makeObjectsPerform:@selector(establishConnection)]; + + /* Send the -awakeFromModel method */ + for (i = 0, count = [objects count]; i < count; i++) { + id object = [[objects objectAtIndex:i] nibInstantiate]; + + if ([object respondsToSelector:@selector(awakeFromModel)]) + [object awakeFromModel]; + } +} + +- (void)dealloc +{ + [objects release]; + [connections release]; + [super dealloc]; +} + +- (void)_setObjects:_objects connections:_connections +{ + objects = [_objects retain]; + connections = [_connections retain]; +} + +- (void)encodeWithModelArchiver:(GMArchiver*)archiver +{ + [archiver encodeObject:objects withName:@"Objects"]; + [archiver encodeObject:connections withName:@"Connections"]; +} + +- (id)initWithModelUnarchiver:(GMUnarchiver*)unarchiver +{ + objects = [[unarchiver decodeObjectWithName:@"Objects"] retain]; + connections = [[unarchiver decodeObjectWithName:@"Connections"] retain]; + return self; +} + +@end /* GMModel */ + + +#if GNU_RUNTIME +#import "IMConnectors.h" + +static void __dummyFunctionForLinking (void) +{ + [IMCustomObject new]; + [IMConnector new]; + + __dummyFunctionForLinking(); +} + +#endif diff --git a/Model/Translator.h b/Model/Translator.h new file mode 100644 index 000000000..5e8f4a24c --- /dev/null +++ b/Model/Translator.h @@ -0,0 +1,40 @@ +/* + Translator.h + + Copyright (C) 1996 Free Software Foundation, Inc. + + Author: Ovidiu Predescu + Date: November 1997 + + This file is part of the GNUstep GUI Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _GNUstep_H_Translator +#define _GNUstep_H_Translator + +#import + +@class NSMutableArray; + +extern NSMutableArray* objects; +extern NSMutableArray* connections; + +@interface Translator : NSObject +- (void)translateNibFile:(NSString*)nibFile toModelFile:(NSString*)gmodelFile; +@end + +#endif /* _GNUstep_H_Translator */ diff --git a/Model/Translator.m b/Model/Translator.m new file mode 100644 index 000000000..0f91e4737 --- /dev/null +++ b/Model/Translator.m @@ -0,0 +1,69 @@ +/* + Translator.m + + Translate a NIB file to a GNU model file. + + Copyright (C) 1996 Free Software Foundation, Inc. + + Author: Ovidiu Predescu + Date: November 1997 + + This file is part of the GNUstep GUI Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* The original idea comes from the nib translator in objcX, an Objective-C + class library for Motif, translator whose authors are Paul Kunz and + Imran Qureshi. + */ + +#import +#import +#import "IMLoading.h" +#import "IBClasses.h" +#import "Translator.h" + +NSMutableArray* objects; +NSMutableArray* connections; + +@implementation Translator + +- (void)translateNibFile:(NSString*)nibFile toModelFile:(NSString*)gmodelFile +{ + GMArchiver* archiver; + GMModel* model; + + objects = [[NSMutableArray new] autorelease]; + connections = [[NSMutableArray new] autorelease]; + model = [[GMModel new] autorelease]; + + [NSApplication sharedApplication]; + if (![NSBundle loadNibFile:nibFile + externalNameTable:[NSDictionary dictionaryWithObjectsAndKeys: + NSApp, @"NSOwner", nil] + withZone:[NSApp zone]]) { + NSLog (@"Cannot load nib file %@!", nibFile); + exit (1); + } + + archiver = [[GMArchiver new] autorelease]; + [model _setObjects:objects connections:connections]; + [archiver encodeRootObject:model withName:@"RootObject"]; + if (![archiver writeToFile:gmodelFile]) + NSLog (@"cannot write the model output file %@", gmodelFile); +} + +@end diff --git a/Model/nib2gmodel.m b/Model/nib2gmodel.m new file mode 100644 index 000000000..c4ca491a2 --- /dev/null +++ b/Model/nib2gmodel.m @@ -0,0 +1,55 @@ +/* + nib2gmodel.m + + Copyright (C) 1996 Free Software Foundation, Inc. + + Author: Ovidiu Predescu + Date: November 1997 + + This file is part of the GNUstep GUI Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include + +#import +#import +#import +#import +#import "Translator.h" + +int main () +{ + id pool = [NSAutoreleasePool new]; + NSProcessInfo* processInfo = [NSProcessInfo processInfo]; + NSArray* arguments = [processInfo arguments]; + id translator; + + if ([arguments count] != 3) { + printf ("Convert nib files to GNU model files.\n"); + printf ("usage: %s nib-file gmodel-file\n", + [[processInfo processName] cString]); + exit (1); + } + + translator = [[Translator new] autorelease]; + [translator translateNibFile:[arguments objectAtIndex:1] + toModelFile:[arguments objectAtIndex:2]]; + +// [pool release]; + + return 0; +} diff --git a/Model/test.gmodel b/Model/test.gmodel new file mode 100644 index 000000000..b5a05d3b7 --- /dev/null +++ b/Model/test.gmodel @@ -0,0 +1,712 @@ +{ + "Object 1" = { + elements = ("Object 2", "Object 51", "Object 52"); + isa = NSMutableArray; + }; + "Object 2" = {className = NSApplication; isa = IMCustomObject; realObject = "Object 3"; }; + "Object 3" = { + isa = NSApplication; + keyWindow = nil; + mainMenu = "Object 30"; + mainWindow = nil; + windows = "Object 4"; + }; + "Object 4" = { + elements = ("Object 5", "Object 9", "Object 11"); + isa = NSMutableArray; + }; + "Object 5" = { + backgroundColor = "Object 8"; + backingType = 0; + contentView = "Object 6"; + frame = "{x = 0; y = 0; width = 256; height = 128}"; + frameAutosaveName = nil; + hidesOnDeactivate = NO; + isAutodisplay = NO; + isReleasedWhenClosed = NO; + isVisible = NO; + isa = NSWindow; + level = 0; + maxSize = "{width = 3.40282e+38; height = 3.40282e+38}"; + minSize = "{width = 0; height = 0}"; + representedFilename = ""; + styleMask = 0; + title = ""; + }; + "Object 6" = { + autoresizesSubviews = YES; + autoresizingMask = 0; + bounds = "{x = 0; y = 0; width = 256; height = 128}"; + frame = "{x = 0; y = 0; width = 256; height = 128}"; + isa = NSView; + nextResponder = "Object 5"; + postsBoundsChangedNotifications = YES; + postsFrameChangedNotifications = YES; + subviews = "Object 7"; + superview = nil; + }; + "Object 7" = {elements = (); isa = NSMutableArray; }; + "Object 8" = { + alpha = 1.000000; + blue = 0.666667; + brightness = 0.666667; + colorSpaceName = NSCalibratedRGBColorSpace; + green = 0.666667; + hue = 0.000000; + isa = NSColor; + red = 0.666667; + saturation = 0.000000; + }; + "Object 9" = { + backgroundColor = "Object 8"; + backingType = 0; + contentView = "Object 10"; + frame = "{x = 0; y = 0; width = 193; height = 208}"; + frameAutosaveName = nil; + hidesOnDeactivate = NO; + isAutodisplay = NO; + isReleasedWhenClosed = NO; + isVisible = NO; + isa = NSWindow; + level = 0; + maxSize = "{width = 3.40282e+38; height = 3.40282e+38}"; + minSize = "{width = 0; height = 0}"; + representedFilename = ""; + styleMask = 0; + title = ""; + }; + "Object 10" = { + autoresizesSubviews = YES; + autoresizingMask = 0; + bounds = "{x = 0; y = 0; width = 193; height = 208}"; + frame = "{x = 0; y = 0; width = 193; height = 208}"; + isa = NSView; + nextResponder = "Object 9"; + postsBoundsChangedNotifications = YES; + postsFrameChangedNotifications = YES; + subviews = "Object 7"; + superview = nil; + }; + "Object 11" = { + backgroundColor = "Object 8"; + backingType = 2; + contentView = "Object 12"; + frame = "{x = 258; y = 519; width = 422; height = 296}"; + frameAutosaveName = nil; + hidesOnDeactivate = NO; + isAutodisplay = YES; + isReleasedWhenClosed = NO; + isVisible = YES; + isa = NSWindow; + level = 0; + maxSize = "{width = 3.40282e+38; height = 3.40282e+38}"; + minSize = "{width = 0; height = 0}"; + representedFilename = ""; + styleMask = 14; + title = "My Window"; + }; + "Object 12" = { + autoresizesSubviews = NO; + autoresizingMask = 0; + bounds = "{x = 0; y = 0; width = 420; height = 264}"; + frame = "{x = 1; y = 9; width = 420; height = 264}"; + isa = NSView; + nextResponder = "Object 11"; + postsBoundsChangedNotifications = YES; + postsFrameChangedNotifications = YES; + subviews = "Object 13"; + superview = nil; + }; + "Object 13" = { + elements = ( + "Object 14", + "Object 16", + "Object 17", + "Object 18", + "Object 19", + "Object 20", + "Object 21", + "Object 24", + "Object 27" + ); + isa = NSMutableArray; + }; + "Object 14" = { + alignment = 2; + alternateImage = nil; + alternateTitle = Alternate; + autoresizesSubviews = NO; + autoresizingMask = 0; + bounds = "{x = 0; y = 0; width = 114; height = 24}"; + delay = 0.200000; + font = "Object 15"; + frame = "{x = 16; y = 140; width = 114; height = 24}"; + highlightsBy = 12; + ignoresMultiClick = NO; + image = nil; + imagePosition = 0; + interval = 0.025000; + isBordered = YES; + isContinuous = NO; + isEnabled = YES; + isTransparent = NO; + isa = NSButton; + keyEquivalent = ""; + nextResponder = "Object 12"; + postsBoundsChangedNotifications = YES; + postsFrameChangedNotifications = YES; + showsStateBy = 0; + state = 0; + subviews = "Object 7"; + superview = "Object 12"; + tag = 0; + title = "Momentary Light"; + }; + "Object 15" = {isa = NSFont; name = Helvetica; size = 12.000000; }; + "Object 16" = { + alignment = 2; + alternateImage = nil; + alternateTitle = Alternate; + autoresizesSubviews = NO; + autoresizingMask = 0; + bounds = "{x = 0; y = 0; width = 114; height = 24}"; + delay = 0.200000; + font = "Object 15"; + frame = "{x = 16; y = 224; width = 114; height = 24}"; + highlightsBy = 14; + ignoresMultiClick = NO; + image = nil; + imagePosition = 0; + interval = 0.025000; + isBordered = YES; + isContinuous = NO; + isEnabled = YES; + isTransparent = NO; + isa = NSButton; + keyEquivalent = ""; + nextResponder = "Object 12"; + postsBoundsChangedNotifications = YES; + postsFrameChangedNotifications = YES; + showsStateBy = 0; + state = 0; + subviews = "Object 7"; + superview = "Object 12"; + tag = 0; + title = "Momentary Push"; + }; + "Object 17" = { + alignment = 2; + alternateImage = nil; + alternateTitle = Alternate; + autoresizesSubviews = NO; + autoresizingMask = 0; + bounds = "{x = 0; y = 0; width = 114; height = 24}"; + delay = 0.200000; + font = "Object 15"; + frame = "{x = 16; y = 182; width = 114; height = 24}"; + highlightsBy = 1; + ignoresMultiClick = NO; + image = nil; + imagePosition = 0; + interval = 0.025000; + isBordered = YES; + isContinuous = NO; + isEnabled = YES; + isTransparent = NO; + isa = NSButton; + keyEquivalent = ""; + nextResponder = "Object 12"; + postsBoundsChangedNotifications = YES; + postsFrameChangedNotifications = YES; + showsStateBy = 0; + state = 0; + subviews = "Object 7"; + superview = "Object 12"; + tag = 0; + title = "Momentary change"; + }; + "Object 18" = { + alignment = 2; + alternateImage = nil; + alternateTitle = Alternate; + autoresizesSubviews = NO; + autoresizingMask = 0; + bounds = "{x = 0; y = 0; width = 114; height = 24}"; + delay = 0.200000; + font = "Object 15"; + frame = "{x = 17; y = 98; width = 114; height = 24}"; + highlightsBy = 14; + ignoresMultiClick = NO; + image = nil; + imagePosition = 0; + interval = 0.025000; + isBordered = YES; + isContinuous = NO; + isEnabled = YES; + isTransparent = NO; + isa = NSButton; + keyEquivalent = ""; + nextResponder = "Object 12"; + postsBoundsChangedNotifications = YES; + postsFrameChangedNotifications = YES; + showsStateBy = 12; + state = 0; + subviews = "Object 7"; + superview = "Object 12"; + tag = 0; + title = PushOn/PushOff; + }; + "Object 19" = { + alignment = 2; + alternateImage = nil; + alternateTitle = Alternate; + autoresizesSubviews = NO; + autoresizingMask = 0; + bounds = "{x = 0; y = 0; width = 114; height = 24}"; + delay = 0.200000; + font = "Object 15"; + frame = "{x = 16; y = 56; width = 114; height = 24}"; + highlightsBy = 12; + ignoresMultiClick = NO; + image = nil; + imagePosition = 0; + interval = 0.025000; + isBordered = YES; + isContinuous = NO; + isEnabled = YES; + isTransparent = NO; + isa = NSButton; + keyEquivalent = ""; + nextResponder = "Object 12"; + postsBoundsChangedNotifications = YES; + postsFrameChangedNotifications = YES; + showsStateBy = 12; + state = 0; + subviews = "Object 7"; + superview = "Object 12"; + tag = 0; + title = On/Off; + }; + "Object 20" = { + alignment = 2; + alternateImage = nil; + alternateTitle = Alternate; + autoresizesSubviews = NO; + autoresizingMask = 0; + bounds = "{x = 0; y = 0; width = 114; height = 24}"; + delay = 0.200000; + font = "Object 15"; + frame = "{x = 16; y = 14; width = 114; height = 24}"; + highlightsBy = 3; + ignoresMultiClick = NO; + image = nil; + imagePosition = 0; + interval = 0.025000; + isBordered = YES; + isContinuous = NO; + isEnabled = YES; + isTransparent = NO; + isa = NSButton; + keyEquivalent = ""; + nextResponder = "Object 12"; + postsBoundsChangedNotifications = YES; + postsFrameChangedNotifications = YES; + showsStateBy = 1; + state = 0; + subviews = "Object 7"; + superview = "Object 12"; + tag = 0; + title = Toggle; + }; + "Object 21" = { + alignment = 0; + alternateImage = "Object 23"; + alternateTitle = Alternate; + autoresizesSubviews = NO; + autoresizingMask = 0; + bounds = "{x = 0; y = 0; width = 109; height = 15}"; + delay = 0.200000; + font = "Object 15"; + frame = "{x = 204; y = 208; width = 109; height = 15}"; + highlightsBy = 3; + ignoresMultiClick = NO; + image = "Object 22"; + imagePosition = 2; + interval = 0.025000; + isBordered = NO; + isContinuous = NO; + isEnabled = YES; + isTransparent = NO; + isa = NSButton; + keyEquivalent = ""; + nextResponder = "Object 12"; + postsBoundsChangedNotifications = YES; + postsFrameChangedNotifications = YES; + showsStateBy = 1; + state = 0; + subviews = "Object 7"; + superview = "Object 12"; + tag = 0; + title = Switch; + }; + "Object 22" = {isa = NSImage; name = NSSwitch; size = "{width = 15; height = 15}"; }; + "Object 23" = { + isa = NSImage; + name = NSHighlightedSwitch; + size = "{width = 15; height = 15}"; + }; + "Object 24" = { + alignment = 2; + autoresizesSubviews = NO; + autoresizingMask = 0; + backgroundColor = "Object 8"; + bounds = "{x = 0; y = 0; width = 132; height = 26}"; + delegate = nil; + drawsBackground = NO; + errorAction = nil; + font = "Object 25"; + frame = "{x = 194; y = 159; width = 132; height = 26}"; + ignoresMultiClick = NO; + isBezeled = NO; + isBordered = YES; + isContinuous = NO; + isEditable = YES; + isEnabled = YES; + isScrollable = YES; + isSelectable = YES; + isa = NSTextField; + nextResponder = "Object 12"; + nextText = "Object 18"; + postsBoundsChangedNotifications = YES; + postsFrameChangedNotifications = YES; + previousText = "Object 14"; + stringValue = Title; + subviews = "Object 7"; + superview = "Object 12"; + tag = 0; + textColor = "Object 26"; + }; + "Object 25" = {isa = NSFont; name = Helvetica; size = 18.000000; }; + "Object 26" = { + alpha = 1.000000; + blue = 0.000000; + brightness = 0.000000; + colorSpaceName = NSCalibratedRGBColorSpace; + green = 0.000000; + hue = 0.000000; + isa = NSColor; + red = 0.000000; + saturation = 0.000000; + }; + "Object 27" = { + alignment = 2; + autoresizesSubviews = NO; + autoresizingMask = 0; + backgroundColor = "Object 29"; + bounds = "{x = 0; y = 0; width = 214; height = 21}"; + delegate = nil; + drawsBackground = YES; + errorAction = nil; + font = "Object 15"; + frame = "{x = 172; y = 100; width = 214; height = 21}"; + ignoresMultiClick = NO; + isBezeled = YES; + isBordered = NO; + isContinuous = NO; + isEditable = YES; + isEnabled = YES; + isScrollable = YES; + isSelectable = YES; + isa = NSTextField; + nextResponder = "Object 12"; + nextText = "Object 19"; + postsBoundsChangedNotifications = YES; + postsFrameChangedNotifications = YES; + previousText = "Object 18"; + stringValue = Text; + subviews = "Object 7"; + superview = "Object 12"; + tag = 0; + textColor = "Object 28"; + }; + "Object 28" = { + alpha = 1.000000; + blue = 0.000000; + brightness = 0.000000; + colorSpaceName = NSCalibratedRGBColorSpace; + green = 0.000000; + hue = 0.000000; + isa = NSColor; + red = 0.000000; + saturation = 0.000000; + }; + "Object 29" = { + alpha = 1.000000; + blue = 1.000000; + brightness = 1.000000; + colorSpaceName = NSCalibratedRGBColorSpace; + green = 1.000000; + hue = 0.000000; + isa = NSColor; + red = 1.000000; + saturation = 0.000000; + }; + "Object 30" = { + autoenablesItems = YES; + isa = NSMenu; + itemArray = "Object 31"; + title = test; + }; + "Object 31" = { + elements = ("Object 32", "Object 38", "Object 49", "Object 50"); + isa = NSMutableArray; + }; + "Object 32" = { + action = "submenuAction:"; + isEnabled = YES; + isa = NSMenuItem; + keyEquivalent = ""; + tag = 0; + target = "Object 33"; + title = Info; + }; + "Object 33" = { + autoenablesItems = YES; + isa = NSMenu; + itemArray = "Object 34"; + title = Info; + }; + "Object 34" = { + elements = ("Object 35", "Object 36", "Object 37"); + isa = NSMutableArray; + }; + "Object 35" = { + action = nil; + isEnabled = NO; + isa = NSMenuItem; + keyEquivalent = ""; + tag = 0; + target = nil; + title = "Info Panel..."; + }; + "Object 36" = { + action = nil; + isEnabled = NO; + isa = NSMenuItem; + keyEquivalent = ""; + tag = 0; + target = nil; + title = Preferences...; + }; + "Object 37" = { + action = nil; + isEnabled = YES; + isa = NSMenuItem; + keyEquivalent = "?"; + tag = 0; + target = nil; + title = Help...; + }; + "Object 38" = { + action = "submenuAction:"; + isEnabled = YES; + isa = NSMenuItem; + keyEquivalent = ""; + tag = 0; + target = "Object 39"; + title = Document; + }; + "Object 39" = { + autoenablesItems = YES; + isa = NSMenu; + itemArray = "Object 40"; + title = Document; + }; + "Object 40" = { + elements = ( + "Object 41", + "Object 42", + "Object 43", + "Object 44", + "Object 45", + "Object 46", + "Object 47", + "Object 48" + ); + isa = NSMutableArray; + }; + "Object 41" = { + action = nil; + isEnabled = NO; + isa = NSMenuItem; + keyEquivalent = o; + tag = 0; + target = nil; + title = Open...; + }; + "Object 42" = { + action = nil; + isEnabled = NO; + isa = NSMenuItem; + keyEquivalent = n; + tag = 0; + target = nil; + title = New; + }; + "Object 43" = { + action = nil; + isEnabled = NO; + isa = NSMenuItem; + keyEquivalent = s; + tag = 0; + target = nil; + title = Save; + }; + "Object 44" = { + action = nil; + isEnabled = NO; + isa = NSMenuItem; + keyEquivalent = S; + tag = 0; + target = nil; + title = "Save As..."; + }; + "Object 45" = { + action = nil; + isEnabled = NO; + isa = NSMenuItem; + keyEquivalent = ""; + tag = 0; + target = nil; + title = "Save To..."; + }; + "Object 46" = { + action = nil; + isEnabled = NO; + isa = NSMenuItem; + keyEquivalent = ""; + tag = 0; + target = nil; + title = "Save All"; + }; + "Object 47" = { + action = nil; + isEnabled = NO; + isa = NSMenuItem; + keyEquivalent = ""; + tag = 0; + target = nil; + title = "Revert to Saved"; + }; + "Object 48" = { + action = nil; + isEnabled = NO; + isa = NSMenuItem; + keyEquivalent = ""; + tag = 0; + target = nil; + title = Close; + }; + "Object 49" = { + action = nil; + isEnabled = YES; + isa = NSMenuItem; + keyEquivalent = h; + tag = 0; + target = nil; + title = Hide; + }; + "Object 50" = { + action = nil; + isEnabled = YES; + isa = NSMenuItem; + keyEquivalent = q; + tag = 0; + target = nil; + title = Quit; + }; + "Object 51" = {className = NSFontManager; isa = IMCustomObject; }; + "Object 52" = {className = Controller; isa = IMCustomObject; }; + "Object 53" = { + elements = ( + "Object 54", + "Object 56", + "Object 58", + "Object 60", + "Object 62", + "Object 63", + "Object 64", + "Object 65", + "Object 66", + "Object 67" + ); + isa = NSMutableArray; + }; + "Object 54" = { + destination = "Object 2"; + isa = IMControlConnector; + label = "Object 55"; + source = "Object 50"; + }; + "Object 55" = {isa = NSString; string = "terminate:"; }; + "Object 56" = { + destination = "Object 2"; + isa = IMControlConnector; + label = "Object 57"; + source = "Object 49"; + }; + "Object 57" = {isa = NSString; string = "hide:"; }; + "Object 58" = { + destination = "Object 27"; + isa = IMOutletConnector; + label = "Object 59"; + source = "Object 52"; + }; + "Object 59" = {isa = NSString; string = textField; }; + "Object 60" = { + destination = "Object 52"; + isa = IMControlConnector; + label = "Object 61"; + source = "Object 16"; + }; + "Object 61" = {isa = NSString; string = "buttonPressed:"; }; + "Object 62" = { + destination = "Object 52"; + isa = IMControlConnector; + label = "Object 61"; + source = "Object 17"; + }; + "Object 63" = { + destination = "Object 52"; + isa = IMControlConnector; + label = "Object 61"; + source = "Object 14"; + }; + "Object 64" = { + destination = "Object 52"; + isa = IMControlConnector; + label = "Object 61"; + source = "Object 18"; + }; + "Object 65" = { + destination = "Object 52"; + isa = IMControlConnector; + label = "Object 61"; + source = "Object 19"; + }; + "Object 66" = { + destination = "Object 52"; + isa = IMControlConnector; + label = "Object 61"; + source = "Object 20"; + }; + "Object 67" = { + destination = "Object 52"; + isa = IMControlConnector; + label = "Object 61"; + source = "Object 21"; + }; + RootObject = {Connections = "Object 53"; Objects = "Object 1"; isa = GMModel; }; + TopLevelObjects = (RootObject); + Version = 1; +} diff --git a/Model/test.m b/Model/test.m new file mode 100644 index 000000000..1c819a6e6 --- /dev/null +++ b/Model/test.m @@ -0,0 +1,40 @@ +#import +#import +#import "IMLoading.h" + +int main (int argc, char** argv, char** env) +{ + id pool; + NSArray* arguments; + NSProcessInfo* processInfo; + + pool = [NSAutoreleasePool new]; +#if LIB_FOUNDATION_LIBRARY + [NSProcessInfo initializeWithArguments:argv count:argc environment:env]; +#endif + + processInfo = [NSProcessInfo processInfo]; + arguments = [processInfo arguments]; + if ([arguments count] != 2) { + printf ("usage: %s gmodel-file\n", [[processInfo processName] cString]); + exit (1); + } + +#ifndef NX_CURRENT_COMPILER_RELEASE + initialize_gnustep_backend(); +#endif + + if (![GMModel loadIMFile:[arguments objectAtIndex:1] + owner:[NSApplication sharedApplication]]) { + printf ("Cannot load Interface Modeller file!\n"); + exit (1); + } + + [[NSApplication sharedApplication] run]; + printf ("exiting...\n"); + + [pool release]; + exit (0); + return 0; +} + diff --git a/Model/test.nib/data.classes b/Model/test.nib/data.classes new file mode 100644 index 000000000..1a4a70430 --- /dev/null +++ b/Model/test.nib/data.classes @@ -0,0 +1,6 @@ +"Controller" = { + ACTIONS = {"buttonPressed:" = id; }; + OUTLETS = {textField = id; }; + SUPERCLASS = NSObject; +}; +"FirstResponder" = {ACTIONS = {}; OUTLETS = {}; SUPERCLASS = NSObject; }; diff --git a/Model/test.nib/objects.nib b/Model/test.nib/objects.nib new file mode 100644 index 000000000..8c748c701 Binary files /dev/null and b/Model/test.nib/objects.nib differ diff --git a/Source/NSApplication.m b/Source/NSApplication.m index 1fcef2796..d94874ea6 100644 --- a/Source/NSApplication.m +++ b/Source/NSApplication.m @@ -391,7 +391,7 @@ static id NSApp; - (NSEvent*)_eventMatchingMask:(unsigned int)mask { NSEvent* event; - int i, count; + int i, count = [event_queue count]; [self getNextEvent]; @@ -460,6 +460,10 @@ static id NSApp; break; } + // flush any windows that need it + [NSWindow _flushWindows]; + [self _flushCommunicationChannels]; + type = [event type]; // Unhide the cursor if necessary diff --git a/Source/NSImage.m b/Source/NSImage.m index 8a57c0beb..203f182c3 100644 --- a/Source/NSImage.m +++ b/Source/NSImage.m @@ -71,9 +71,6 @@ typedef struct _rep_data_t BOOL validCache; } rep_data_t; -/* Class variables and functions for class methods */ -static NSMutableDictionary* nameDict; - NSArray *iterate_reps_for_types(NSArray *imageReps, SEL method); /* Find the rep_data_t holding a representation */ @@ -132,20 +129,37 @@ set_repd_for_rep(NSMutableArray *_reps, NSImageRep *rep, rep_data_t *new_repd) @implementation NSImage +/* Class variables and functions for class methods */ +static NSMutableDictionary* nameDict = nil; +static NSDictionary* nsmapping = nil; + + (void)initialize { if (self == [NSImage class]) { + NSBundle *system = [NSBundle bundleWithPath:gnustep_libdir]; + NSString* path = [system pathForResource:@"nsmapping" + ofType:@"strings" + inDirectory:NSImage_PATH]; // Initial version [self setVersion:1]; // initialize the class variables nameDict = [[NSMutableDictionary alloc] initWithCapacity: 10]; + if (path) + nsmapping = [[[NSString stringWithContentsOfFile:path] + propertyListFromStringsFileFormat] + retain]; } } + imageNamed: (NSString *)aName { + NSString* realName = [nsmapping objectForKey:aName]; + + if (realName) + aName = realName; + /* If there is no image with that name, search in the main bundle */ if (!nameDict || ![nameDict objectForKey:aName]) { diff --git a/Source/NSMenu.m b/Source/NSMenu.m index c1c95858e..6ec5e2525 100644 --- a/Source/NSMenu.m +++ b/Source/NSMenu.m @@ -47,9 +47,8 @@ #ifdef MAX # undef MAX #endif -# define MAX(a, b) \ - ({typedef _ta = (a), _tb = (b); \ - _ta _a = (a); _tb _b = (b); \ +#define MAX(a, b) \ + ({typeof(a) _a = (a); typeof(b) _b = (b); \ _a > _b ? _a : _b; }) @@ -57,6 +56,10 @@ - (void)_menuChanged; @end +@interface NSMenuMatrix (PrivateMethods2) +- (void)_resizeMenuForCellSize; +@end + @implementation NSMenuMatrix @@ -112,6 +115,21 @@ static NSFont* menuFont = nil; - (void)_resizeMenuForCellSize { + int i, count; + float titleWidth; + + /* Compute the new width of the menu cells matrix */ + cellSize.width = 0; + count = [cells count]; + for (i = 0; i < count; i++) { + titleWidth = [menuFont widthOfString: + [[cells objectAtIndex:i] stringValue]]; + cellSize.width = MAX(titleWidth + ADDITIONAL_WIDTH, cellSize.width); + } + cellSize.width = MAX([menuFont widthOfString:[menu title]] + + ADDITIONAL_WIDTH, + cellSize.width); + /* Resize the frame to hold all the menu cells */ [super setFrameSize:NSMakeSize (cellSize.width, (cellSize.height + INTERCELL_SPACE) * [cells count] - INTERCELL_SPACE)]; @@ -123,18 +141,13 @@ static NSFont* menuFont = nil; atIndex:(unsigned int)index { id menuCell = [[[NSMenu cellClass] new] autorelease]; - float titleWidth; [menuCell setTitle:aString]; [menuCell setAction:aSelector]; [menuCell setKeyEquivalent:charCode]; [menuCell setFont:menuFont]; - titleWidth = [menuFont widthOfString:aString]; - cellSize = NSMakeSize (MAX(titleWidth + ADDITIONAL_WIDTH, cellSize.width), - cellSize.height); [cells insertObject:menuCell atIndex:index]; - [self _resizeMenuForCellSize]; return menuCell; @@ -143,22 +156,11 @@ static NSFont* menuFont = nil; - (void)removeItem:(id )anItem { int row = [cells indexOfObject:anItem]; - float titleWidth; - int i, count; if (row == -1) return; [cells removeObjectAtIndex:row]; - - /* Compute the new width of the menu cells matrix */ - cellSize.width = 0; - count = [cells count]; - for (i = 0; i < count; i++) { - titleWidth = [menuFont widthOfString:[cells objectAtIndex:i]]; - cellSize.width = MAX(titleWidth + ADDITIONAL_WIDTH, cellSize.width); - } - [self _resizeMenuForCellSize]; } @@ -710,9 +712,17 @@ static Class menuCellClass = nil; - (void)sizeToFit { // SUBCLASS + [menuCells _resizeMenuForCellSize]; + [menuCells setNeedsDisplay:YES]; menuHasChanged = NO; } +- (void)setTitle:(NSString*)aTitle +{ + ASSIGN(title, aTitle); + [self sizeToFit]; +} + - (NSString*)title { return title; diff --git a/Source/NSTextField.m b/Source/NSTextField.m index 42e731025..aff9455d7 100644 --- a/Source/NSTextField.m +++ b/Source/NSTextField.m @@ -266,6 +266,8 @@ id gnustep_gui_nstextfield_cell_class = nil; return [cell textColor]; } +- (id)selectedCell { return cell; } + // // Target and Action // diff --git a/Source/NSView.m b/Source/NSView.m index 5bf8e3524..1e1829b3d 100644 --- a/Source/NSView.m +++ b/Source/NSView.m @@ -947,6 +947,20 @@ static NSRecursiveLock *gnustep_gui_nsview_lock = nil; _nextSiblingSubviewThatNeedsDisplay = NULL; } +- (void)_unconditionallyResetNeedsDisplayInAllViews +{ + int i, count; + + _subviewsThatNeedDisplay = NULL; + _nextSiblingSubviewThatNeedsDisplay = NULL; + + if (!sub_views || !(count = [sub_views count])) + return; + + for (i = 0; i < count; i++) + [[sub_views objectAtIndex:i] _unconditionallyResetNeedsDisplayInAllViews]; +} + - (void)_displayNeededViews { NSView* subview; diff --git a/Source/NSWindow.m b/Source/NSWindow.m index 5a5383090..ca22f7d85 100644 --- a/Source/NSWindow.m +++ b/Source/NSWindow.m @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -129,11 +130,12 @@ static BOOL _needsFlushWindows = YES; - (void)dealloc { - // Release the window view - if (content_view) [[content_view superview] release]; - // Release the content view - if (content_view) [content_view release]; + if (content_view) { + // Release the window view + [[content_view superview] release]; + [content_view release]; + } [background_color release]; [represented_filename release]; @@ -224,27 +226,23 @@ static BOOL _needsFlushWindows = YES; // If the window view hasn't been created yet // then create it - if ((!content_view) || ([content_view superview] == nil)) - { - wv = [[NSWindowView alloc] initWithFrame: frame]; - [wv viewWillMoveToWindow: self]; - } + if ((!content_view) || ([content_view superview] == nil)) { + wv = [[NSWindowView alloc] initWithFrame: frame]; + [wv viewWillMoveToWindow: self]; + } else wv = [content_view superview]; if (content_view) - { - [content_view removeFromSuperview]; - [content_view viewWillMoveToWindow:nil]; - } + [content_view removeFromSuperview]; ASSIGN(content_view, aView); // Add to our window view [wv addSubview: content_view]; - - // Tell the view its changing windows - [content_view viewWillMoveToWindow:self]; + NSAssert1 ([[wv subviews] count] == 1, + @"window's view has %d subviews!", + [[wv subviews] count]); // Make us the view's next responder [content_view setNextResponder:self]; @@ -716,7 +714,7 @@ static BOOL _needsFlushWindows = YES; return disable_flush_window; } -- (void)setAutoDisplay:(BOOL)flag +- (void)setAutodisplay:(BOOL)flag { is_autodisplay = flag; }