From 7b6550f72d758f8dcb6876964709eff3c4fe9578 Mon Sep 17 00:00:00 2001 From: "Pascal J. Bourguignon" Date: Fri, 10 Mar 2000 18:19:25 +0000 Subject: [PATCH] Added the following features to GSAlertPanel private subclass of NSPanel: - fit the height of the panel according to the height of the message, in addition to the width. - when the final size for the panel is much too big respective to the screen, it is reduced, and the message is put in a scroll view. - made the attention panel stay visible when the application is deactivated as manded by the OpenStep specifications. - more than one attention panel can be run simultaneously, without the later invocation stealing the panel of the former one. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@6262 72102866-910b-0410-8b05-ffd578937521 --- Source/NSPanel.m | 1735 ++++++++++++++++++++++++++++------------------ 1 file changed, 1071 insertions(+), 664 deletions(-) diff --git a/Source/NSPanel.m b/Source/NSPanel.m index 254b66fae..b3cae55d7 100644 --- a/Source/NSPanel.m +++ b/Source/NSPanel.m @@ -13,6 +13,10 @@ Author: Richard Frith-Macdonald Date: 1998 + GSAlertPanel and alert panel functions cleanup and improvements (scroll view) + Author: Pascal J. Bourguignon + Date: 2000-03-08 + This file is part of the GNUstep GUI Library. This library is free software; you can redistribute it and/or @@ -44,12 +48,111 @@ #include #include #include +#include #include #include #include +/* + PJB: + SMALL TUTORIAL FOR C PROGRAMMERS WHO NEVER LEARNED + A HIGH LEVEL LANGUAGE SUCH AS PASCAL OR MODULA-2 + + + A boolean variable can be true or false. + A condition can be true of false. + A pointer can be null or not. + A integer can be 0 or not. + + Therefore, it should be obvious to everybody that : + - a pointer IS NOT a condition; + - an integer IS NOT a condition; + - there is no need to compare a boolean to YES to know if it is true. + + And, given the following declarations: + + BOOL active; + NSString* title; + + we should not write: but we should write: + + if(active==YES){ if(active){ + wrong(); right(); + } } + + if(active==NO){ if(!active){ + wrong(); right(); + } } + + if(title){ if(title!=nil){ + wrong(); right(); + } } + + if(!title){ if(title==nil){ + wrong(); right(); + } } + + + Writting if(active==YES){ + is as ludicrulus as writting: if(((((active==YES)==YES)==YES)==YES)==YES){ + + Moreover, you must know that defining YES and NO like this: + + #ifndef YES + #define YES 1 + #endif YES + #ifndef NO + #define NO 0 + #endif NO + + Is not portable. For example, the native value for the mc680x0 of + true is not 1, but 255 (0xff). Hence, with a naive C -> mc680x0 + compiler we could have (active==YES)==YES being wrong, and this + would be OK as for C. No C standard define that (0==0) must be 1, + only that (0==0)!=0. + + + The right way of defining YES and NO is: + + #undef YES + #define YES ((BOOL)(0==0)) + #undef NO + #define NO ((BOOL)(0!=0)) + + + + void PleaseWrite(bool isBetter,void* pointer,int value) + { + if((!isBetter)&&(pointer!=NULL)||(value==0)){ + print("Right!\n"); + } + }//PleaseWrite; + + + void DontBeSilly(bool isSilly,void* pointer,int value) + { + if((isSilly!=true)&&(pointer)||(!value)){ + print("Wrong!!\n"); + } + }//DontBeSilly; + + + + + PS: Note the comment at the end of each method duplicating the + name of the same. Very handy, isn't it? With them, you always + know to what method belongs a statement. And what if you're in + the middle of a method and neither the header nor this ending + comment is visible, you'll ask? Well, obviously, if THIS is + the case, then your method is definitely TOO long, and should + be structured somewhat more. + +*/ + + + @implementation NSPanel /* @@ -61,7 +164,8 @@ { [self setVersion:1]; } -} +}//initialize; + /* * Instance methods @@ -74,7 +178,8 @@ styleMask: style backing: NSBackingStoreBuffered defer: NO]; -} +}//init; + - (void) _initDefaults { @@ -82,19 +187,21 @@ [self setReleasedWhenClosed: NO]; [self setHidesOnDeactivate: YES]; [self setExcludedFromWindowsMenu: YES]; -} +}//initDefaults; + - (BOOL) canBecomeKeyWindow { if (_becomesKeyOnlyIfNeeded) return NO; return YES; -} +}//canBecomeKeyWindow; - (BOOL) canBecomeMainWindow { return NO; -} +}//canBecomeMainWindow; + /* * If we receive an escape, close. @@ -106,7 +213,8 @@ [self close]; else [super keyDown: theEvent]; -} +}//keyDown:; + /* * Determining the Panel's Behavior @@ -114,7 +222,8 @@ - (BOOL) isFloatingPanel { return _isFloatingPanel; -} +}//isFloatingPanel; + - (void) setFloatingPanel: (BOOL)flag { @@ -130,27 +239,32 @@ [self setLevel: NSNormalWindowLevel]; } } -} +}//setFloatingPanel:; + - (BOOL) worksWhenModal { return _worksWhenModal; -} +}//worksWhenModal; + - (void) setWorksWhenModal: (BOOL)flag { _worksWhenModal = flag; -} +}//setWorksWhenModal:; + - (BOOL) becomesKeyOnlyIfNeeded { return _becomesKeyOnlyIfNeeded; -} +}//becomesKeyOnlyIfNeeded; + - (void) setBecomesKeyOnlyIfNeeded: (BOOL)flag { _becomesKeyOnlyIfNeeded = flag; -} +}//setBecomesKeyOnlyIfNeeded:; + /* * NSCoding protocol @@ -158,742 +272,1035 @@ - (void) encodeWithCoder: (NSCoder*)aCoder { [super encodeWithCoder: aCoder]; -} +}//encodeWithCoder:; + - (id) initWithCoder: (NSCoder*)aDecoder { [super initWithCoder: aDecoder]; return self; -} +}//initWithCoder:; + @end /* NSPanel */ -#define PANX 362.0 -#define PANY 161.0 + +//////////////////////////////////////////////////////////////////////// +// GSAlertPanel + +/* + + +--------------------------------------------------------------------------+ + |############################Title bar#####################################| + +--------------------------------------------------------------------------+ + | | | | | | + | ........... | | | | + | : | : | | | | + |--: Icon | :----Title | | | + | :-------|-: | | | + | :.........: | | | + | | | + |-===========================|=============~~~~~~=========================-| + | s | | + | s | | + | ...................s....|......................................... | + | :Message s s ; | + | : s s : | + | : s s : | + |----: s s :----| + | :~~~~~~~~~~~~~~~~~~s~~~~~~~~~~~~~~~~~~~~s~~~~~~~~~~~~~~~~~~~~~~~~: | + | : s s : | + | :..................s.............................................: | + | | s | + | | s +-----------+ +-----------+ +-----------+ | + | | s | Altern |---| Cancel |---| OK |----| + | | s +-----------+ +-----------+ +-----------+ | + | | s | | | | + +--------------------------------------------------------------------------+ + + Apart from the buttons and window borders, '|' and '-' mean not + flexible, while '~' and 's' mean flexible. + + The global window size is determined by the message text field + size. which is computed with sizeToFit. However, if the window + would become larger than the screen, then the message text field + is replaced with a scroll view containing the text. + + + The strategy taken in this new version of GSAlertPanel is to let + the icon, the title field and the line (box view) being placed + automatically by resizing the window, but to always place + explicitely the message field (or scroll view when it's needed) + and the buttons (that may change of width), the whole in the + sizeToFitIfNeeded method. We're doing it separately from the + setting of the elements (setTitle:...) because we also need to + recompute the size of the window and position of the elements when + dearchiving a panel, because it could be dearchived and displayed + on a much smaller screen than originaly created, in which case we + needed to embed the message field into a scroll view, and reduce + the size of the window. + + + Some rules (which are implemented in sizePanelToFit): + ===================================================== + + + IF the messageField is too big either vertically or horizontally and + would make the window greater than the screen in any direction, + THEN use a scroll view. + + + The width of the window is the minimum of: + = the screen width, + = the maximum of: + = a minimum width of 362, + = the messageField width + 2=MessageHorzMargin, + = the sum of sizes of the buttons and their interspaces + and margins, + = the sum of sizes of the icon, title and their interspaces + and margin. + + + The height of the window is the minimum of: + = the screen height (minus the title bar height of the window), + = the maximum of: + = a minimum height of 161. + = the sum of: + = The height of the icon, the line and their interspaces. + = The height of the messageField and its interspaces, + if present. + = The height of the buttons and their interspaces, + if present. + + + The size of the scroll view must be at minimum ScrollMinSize + in each direction. + + The size of the messageField is a given (sizeToFit). + + The height of the scroll is the rest of the height of the window minus + the height of the other elements. + + The width of the scroll is the rest of the width of the window minus the + margins. + + ((wsize.width<=ssize.width) + and ([messageField frame].size.width+2*MessageHorzMargin<=wsize.width)) + or ((wsize.width==ssize.width) + and ([scroll frame].size.width=wsize.width-2*MessageHorzMargin)); + + ... +*/ + + @class GSAlertPanel; -static GSAlertPanel *standardAlertPanel = nil; -static GSAlertPanel *informationalAlertPanel = nil; -static GSAlertPanel *criticalAlertPanel = nil; -static GSAlertPanel *gmodelAlertPanel = nil; +static GSAlertPanel* standardAlertPanel=nil; +static GSAlertPanel* informationalAlertPanel=nil; +static GSAlertPanel* criticalAlertPanel=nil; +static GSAlertPanel* gmodelAlertPanel=nil; -@interface GSAlertPanel : NSPanel + +@interface GSAlertPanel:NSPanel { - NSSize originalSize; - NSButton *defButton; - NSButton *altButton; - NSButton *othButton; - NSButton *icoButton; - NSTextField *messageField; - NSTextField *titleField; - int result; - BOOL active; + NSButton* defButton; + NSButton* altButton; + NSButton* othButton; + NSButton* icoButton; + NSTextField* titleField; + NSTextField* messageField; + NSScrollView* scroll; + int result; + BOOL isGreen; // we were unarchived and not resized. + //PJB: I removed the active flag. Please see the isActivePanel method below. } -- (void) buttonAction: (id) sender; -- (int) result; -- (int) runModal; -- (void) setTitle: (NSString*)title - message: (NSString*)message - def: (NSString*)defaultButton - alt: (NSString*)alternateButton - other: (NSString*)otherButton; -@end + +// NSPanel methods: + + -(id)initWithContentRect:(NSRect)r + styleMask:(unsigned)m + backing:(NSBackingStoreType)b + defer:(BOOL)d + screen:(NSScreen*)s; + /* + POST: result!=nil => result->isGreen. + */ + + -(id)initWithModelUnarchiver:(GMUnarchiver*)unarchiver; + /* + POST: result!=nil => result->isGreen. + */ + + + -(int)runModal; + /* + POST: !(sef->isGreen). + */ + + +// GSAlertPanel methods: + + -(void)setTitle:(NSString*)title + message:(NSString*)message + def:(NSString*)defaultButton + alt:(NSString*)alternateButton + other:(NSString*)otherButton; + /* + POST: self->isGreen. + */ + + + -(void)sizePanelToFit; + /* + POST: !(sef->isGreen). + */ + + -(void)buttonAction:(id)sender; + -(int)result; + -(BOOL)isActivePanel; + + +/* + Note: You definitely don't want to pass to clients + an instance i such as i->isGreen. +*/ + + +@end //GSAlertPanel. + + +//////////////////////////////////////////////////////////////////////// + @implementation GSAlertPanel -/* - * Class methods - */ -+ (void)initialize -{ - if (self == [GSAlertPanel class]) + static const float WTitleHeight=24.0; // TODO: Check this value. + static const float WinMinWidth=362.0; + static const float WinMinHeight=161.0; + static const float IconSide=48.0; + static const float IconBottom=-56.0; // from the top of the window. + static const float IconLeft=8.0; + static const float TitleBottom=-40.0; // from the top of the window. + static const float TitleLeft=64.0; + static const float TitleMinRight=8.0; + static const float LineHeight=2.0; + static const float LineBottom=-66.0; // from the top of the window. + static const float LineLeft=0.0; + static const float ScrollMinSize=48.0; // in either direction. + static const float MessageHorzMargin=8.0; // 5 is too little margin. + static const float MessageMinHeight=20.0; + static const float MessageVertMargin=6.0; // from the top of the buttons. + static const float MessageTop=-72; // from the top of the window; + static const float ButtonBottom=8.0; // from the bottom of the window. + static const float ButtonMargin=8.0; + static const float ButtonInterspace=10.0; + static const float ButtonMinHeight=24.0; + static const float ButtonMinWidth=72.0; + +#define MessageFont [NSFont systemFontOfSize: 14.0] +// TODO: Check on NeXTSTEP, I think that the message font size is only 12.0. + + + +// Class methods: + + +(void)initialize { - [self setVersion:1]; - } -} + if(self==[GSAlertPanel class]){ + [self setVersion:1]; + } + }//initialize; -+ (id) createObjectForModelUnarchiver: (GMUnarchiver*)unarchiver -{ - unsigned backingType = [unarchiver decodeUnsignedIntWithName: - @"backingType"]; - unsigned styleMask = [unarchiver decodeUnsignedIntWithName:@"styleMask"]; - NSRect aRect = [unarchiver decodeRectWithName:@"frame"]; - NSPanel* panel = [[[GSAlertPanel allocWithZone:[unarchiver objectZone]] - initWithContentRect:aRect - styleMask:styleMask backing:backingType defer:YES] - autorelease]; - return panel; -} - -- (void) buttonAction: (id)sender -{ - if (active == NO) + +(id)createObjectForModelUnarchiver:(GMUnarchiver*)unarchiver { - NSLog(@"alert panel buttonAction: when not in modal loop\n"); - return; - } - else if (sender == defButton) + unsigned backingType=[unarchiver decodeUnsignedIntWithName: + @"backingType"]; + unsigned styleMask=[unarchiver decodeUnsignedIntWithName:@"styleMask"]; + NSRect aRect=[unarchiver decodeRectWithName:@"frame"]; + NSPanel* panel=[[[GSAlertPanel allocWithZone:[unarchiver objectZone]] + initWithContentRect:aRect + styleMask:styleMask backing:backingType defer:YES] + autorelease]; + return panel; + }//createObjectForModelUnarchiver:(; + + + -(void)dealloc { - result = NSAlertDefaultReturn; - } - else if (sender == altButton) + if (self==standardAlertPanel){ + standardAlertPanel=nil; + } + if (self==informationalAlertPanel){ + informationalAlertPanel=nil; + } + if (self==criticalAlertPanel){ + criticalAlertPanel=nil; + } + [defButton release]; + [altButton release]; + [othButton release]; + [icoButton release]; + [titleField release]; + [messageField release]; + [scroll release]; + [super dealloc]; + }//dealloc; + + + -(void)encodeWithModelArchiver:(GMArchiver*)archiver { - result = NSAlertAlternateReturn; - } - else if (sender == othButton) + [super encodeWithModelArchiver: archiver]; + [archiver encodeSize:[self frame].size withName: @"OriginalSize"]; + [archiver encodeObject: defButton withName: @"DefaultButton"]; + [archiver encodeObject: altButton withName: @"AlternateButton"]; + [archiver encodeObject: othButton withName: @"OtherButton"]; + [archiver encodeObject: icoButton withName: @"IconButton"]; + [archiver encodeObject: messageField withName: @"MessageField"]; + [archiver encodeObject: titleField withName: @"TitleField"]; + // PJB: I don't know but probably we must not change the order in + // which the elements are archived, without changing the version. + }//encodeWithModelArchiver:; + + + + static NSScrollView* makeScrollViewWithRect(NSRect rect) { - result = NSAlertOtherReturn; - } - else + float lineHeight=[MessageFont boundingRectForFont].size.height; + NSScrollView* scroll=[[NSScrollView alloc]initWithFrame:rect]; + [scroll setBorderType:NSLineBorder]; + [scroll setBackgroundColor:[NSColor lightGrayColor]]; + [scroll setHasHorizontalScroller:YES]; + [scroll setHasVerticalScroller:YES]; + [scroll setScrollsDynamically:YES]; + [scroll setLineScroll:lineHeight]; + [scroll setPageScroll:lineHeight*10.0]; + return(scroll); + }//makeScrollViewWithRect; + + + -(NSButton*)_makeButtonWithRect:(NSRect)rect { - NSLog(@"alert panel buttonAction: from unknown sender - x%x\n", - (unsigned)sender); - } - active = NO; - [[NSApplication sharedApplication] stopModal]; -} + NSButton* button=[[NSButton alloc] initWithFrame:rect]; + [button setAutoresizingMask: NSViewMinXMargin | NSViewMaxYMargin]; + [button setButtonType: NSMomentaryPushButton]; + [button setTitle: @""]; + [button setTarget: self]; + [button setAction: @selector(buttonAction:)]; + [button setFont: [NSFont systemFontOfSize: 12.0]]; + return(button); + }//_makeButtonWithRect; -- (void) dealloc -{ - if (self == standardAlertPanel) - standardAlertPanel = nil; - if (self == informationalAlertPanel) - informationalAlertPanel = nil; - if (self == criticalAlertPanel) - criticalAlertPanel = nil; - [defButton release]; - [altButton release]; - [othButton release]; - [icoButton release]; - [messageField release]; - [titleField release]; - [super dealloc]; -} -- (void) encodeWithModelArchiver: (GMArchiver *)archiver -{ - [super encodeWithModelArchiver: archiver]; - [archiver encodeSize: originalSize withName: @"OriginalSize"]; - [archiver encodeObject: defButton withName: @"DefaultButton"]; - [archiver encodeObject: altButton withName: @"AlternateButton"]; - [archiver encodeObject: othButton withName: @"OtherButton"]; - [archiver encodeObject: icoButton withName: @"IconButton"]; - [archiver encodeObject: messageField withName: @"MessageField"]; - [archiver encodeObject: titleField withName: @"TitleField"]; -} +#define useControl(control) ([control superview]!=nil) -- (id) initWithContentRect: (NSRect)r - styleMask: (unsigned)m - backing: (NSBackingStoreType)b - defer: (BOOL)d - screen: (NSScreen*)s -{ - self = [super initWithContentRect: r - styleMask: m - backing: b - defer: d - screen: s]; - if (self) + static void setControl(NSView* content,id control,NSString* title) { - NSView *content; - NSImage *image; - unsigned bs = 10.0; /* Inter-button space */ - unsigned bh = 24.0; /* Button height. */ - unsigned bw = 72.0; /* Button width. */ - NSRect rect; - NSBox *box; + if(title!=nil){ + if([control respondsToSelector:@selector(setTitle:)]){ + [control setTitle:title]; + } + if([control respondsToSelector:@selector(setStringValue:)]){ + [control setStringValue:title]; + } + [control sizeToFit]; + if(!useControl(control)){ + [content addSubview:control]; + } + }else if(useControl(control)){ + [control removeFromSuperview]; + } + }//setControl; - originalSize = r.size; - [self setMaxSize: r.size]; - [self setMinSize: r.size]; - [self setTitle: @" "]; - content = [self contentView]; - rect.size.height = 2.0; - rect.size.width = 362.0; - rect.origin.y = 95.0; - rect.origin.x = 0.0; - box = [[NSBox alloc] initWithFrame: rect]; - [box setAutoresizingMask: NSViewWidthSizable | NSViewMinYMargin]; - [box setTitlePosition: NSNoTitle]; - [box setBorderType: NSGrooveBorder]; - [content addSubview: box]; - RELEASE(box); - - rect.size.height = bh; - rect.size.width = bw; - rect.origin.y = bs; - rect.origin.x = 280.0; - defButton = [[NSButton alloc] initWithFrame: rect]; - [defButton setAutoresizingMask: NSViewMinXMargin | NSViewMaxYMargin]; - [defButton setButtonType: NSMomentaryPushButton]; - [defButton setTitle: @"Default"]; - [defButton setTarget: self]; - [defButton setAction: @selector(buttonAction:)]; - [defButton setFont: [NSFont systemFontOfSize: 12.0]]; - [defButton setKeyEquivalent: @"\r"]; - [defButton setImagePosition: NSImageRight]; - [defButton setImage: [NSImage imageNamed: @"common_ret"]]; - - rect.origin.x = 199.0; - altButton = [[NSButton alloc] initWithFrame: rect]; - [altButton setAutoresizingMask: NSViewMinXMargin | NSViewMaxYMargin]; - [altButton setButtonType: NSMomentaryPushButton]; - [altButton setTitle: @"Alternative"]; - [altButton setTarget: self]; - [altButton setAction: @selector(buttonAction:)]; - [altButton setFont: [NSFont systemFontOfSize: 12.0]]; - - rect.origin.x = 120.0; - othButton = [[NSButton alloc] initWithFrame: rect]; - [othButton setAutoresizingMask: NSViewMinXMargin | NSViewMaxYMargin]; - [othButton setButtonType: NSMomentaryPushButton]; - [othButton setTitle: @"Other"]; - [othButton setTarget: self]; - [othButton setAction: @selector(buttonAction:)]; - [othButton setFont: [NSFont systemFontOfSize: 12.0]]; - - rect.size.height = 48.0; - rect.size.width = 48.0; - rect.origin.y = 105.0; - rect.origin.x = 8.0; - icoButton = [[NSButton alloc] initWithFrame: rect]; - [icoButton setAutoresizingMask: NSViewMaxXMargin | NSViewMinYMargin]; - [icoButton setBordered: NO]; - [icoButton setEnabled: NO]; - [icoButton setImagePosition: NSImageOnly]; - image = [[NSApplication sharedApplication] applicationIconImage]; - [icoButton setImage: image]; - - rect.size.height = 36.0; - rect.size.width = 344.0; - rect.origin.y = 55.0; - rect.origin.x = 8.0; - messageField = [[NSTextField alloc] initWithFrame: rect]; - [messageField setAutoresizingMask: - NSViewMinYMargin | NSViewMaxYMargin]; - [messageField setEditable: NO]; - [messageField setSelectable: NO]; - [messageField setBezeled: NO]; - [messageField setDrawsBackground: NO]; - [messageField setAlignment: NSCenterTextAlignment]; - [messageField setStringValue: @""]; - [messageField setFont: [NSFont systemFontOfSize: 14.0]]; - - rect.size.height = 21.0; - rect.size.width = 289.0; - rect.origin.y = 121.0; - rect.origin.x = 64.0; - titleField = [[NSTextField alloc] initWithFrame: rect]; - [titleField setAutoresizingMask: NSViewMinYMargin]; - [titleField setEditable: NO]; - [titleField setSelectable: NO]; - [titleField setBezeled: NO]; - [titleField setDrawsBackground: NO]; - [titleField setStringValue: @""]; - [titleField setFont: [NSFont systemFontOfSize: 18.0]]; - - } - return self; -} - -- (id) initWithModelUnarchiver: (GMUnarchiver*)unarchiver -{ - self = [super initWithModelUnarchiver: unarchiver]; - originalSize = [unarchiver decodeSizeWithName: @"OriginalSize"]; - defButton = [[unarchiver decodeObjectWithName: @"DefaultButton"] retain]; - altButton = [[unarchiver decodeObjectWithName: @"AlternateButton"] retain]; - othButton = [[unarchiver decodeObjectWithName: @"OtherButton"] retain]; - icoButton = [[unarchiver decodeObjectWithName: @"IconButton"] retain]; - messageField = [[unarchiver decodeObjectWithName: @"MessageField"] retain]; - titleField = [[unarchiver decodeObjectWithName: @"TitleField"] retain]; - gmodelAlertPanel = self; - return gmodelAlertPanel; -} - -- (int) result -{ - return result; -} - -- (int) runModal -{ - active = YES; - [NSApp runModalForWindow: self]; - [self orderOut: self]; - return result; -} - -- (void) setTitle: (NSString*)title - message: (NSString*)message - def: (NSString*)defaultButton - alt: (NSString*)alternateButton - other: (NSString*)otherButton -{ - NSView *content = [self contentView]; - float button_origin; - float excessWidth = 0; - float width; - NSRect bRect; - NSSize buttonSize = NSMakeSize (72, 24); - int numberOfButtons = 0; - - /* First step, get minimum size needed for objects */ - /* Put all the objects in the panel now, otherwise resizing the panel - won't do the vertical position computations for us */ - if ([icoButton superview] == nil) - [content addSubview: icoButton]; - - /* NB: Need to make all the buttons of the same size */ - if (defaultButton != nil) + -(id)initWithContentRect:(NSRect)r + styleMask:(unsigned)m + backing:(NSBackingStoreType)b + defer:(BOOL)d + screen:(NSScreen*)s { - numberOfButtons++; - [defButton setTitle: defaultButton]; - [defButton sizeToFit]; - bRect = [defButton frame]; - if (bRect.size.height > buttonSize.height) - buttonSize.height = bRect.size.height; - if (bRect.size.width > buttonSize.width) - buttonSize.width = bRect.size.width; - - if ([defButton superview] == nil) - [content addSubview: defButton]; - } - else - { - if ([defButton superview] != nil) - [defButton removeFromSuperview]; - } + self=[super initWithContentRect:r + styleMask:m + backing:b + defer:d + screen:s]; + if(self!=nil){ + NSRect rect; + NSImage* image; + NSBox* box; + NSView* content=[self contentView]; - if (alternateButton != nil) - { - numberOfButtons++; - [altButton setTitle: alternateButton]; - [altButton sizeToFit]; - bRect = [altButton frame]; - if (bRect.size.height > buttonSize.height) - buttonSize.height = bRect.size.height; - if (bRect.size.width > buttonSize.width) - buttonSize.width = bRect.size.width; + [self setTitle: @" "]; - if ([altButton superview] == nil) - [content addSubview: altButton]; - } - else - { - if ([altButton superview] != nil) - [altButton removeFromSuperview]; - } + // we're an ATTENTION panel, therefore: + [self setHidesOnDeactivate:NO]; + [self setBecomesKeyOnlyIfNeeded:NO]; - if (otherButton != nil) - { - numberOfButtons++; - [othButton setTitle: otherButton]; - [othButton sizeToFit]; - bRect = [othButton frame]; - if (bRect.size.height > buttonSize.height) - buttonSize.height = bRect.size.height; - if (bRect.size.width > buttonSize.width) - buttonSize.width = bRect.size.width; - - if ([othButton superview] == nil) - [content addSubview: othButton]; - } - else - { - if ([othButton superview] != nil) - [othButton removeFromSuperview]; - } + // First, the subviews that will be positioned automatically. - if (numberOfButtons > 0) - { - // Compute total width taken up by buttons - // buttonSize: size of a button - // 10: spacing between buttons - // 5: spacing between last button and window border - width = (10 + buttonSize.width) * numberOfButtons; + rect.size.height=IconSide; + rect.size.width=IconSide; + rect.origin.y=r.origin.y+r.size.height+IconBottom; + rect.origin.x=IconLeft; + icoButton=[[NSButton alloc] initWithFrame: rect]; + [icoButton setAutoresizingMask:NSViewMaxXMargin|NSViewMinYMargin]; + [icoButton setBordered: NO]; + [icoButton setEnabled: NO]; + [icoButton setImagePosition: NSImageOnly]; + image=[[NSApplication sharedApplication] applicationIconImage]; + [icoButton setImage: image]; + [content addSubview:icoButton]; - // If needed, take note that we have to resize the panel - if (width - originalSize.width > excessWidth) - excessWidth = width - originalSize.width; - // Secondary TODO: Check also height. - } + rect.size.height=20.0; // will be sized to fit anyway. + rect.size.width=80.0; // will be sized to fit anyway. + rect.origin.y=r.origin.y+r.size.height+TitleBottom; + rect.origin.x=TitleLeft; + titleField=[[NSTextField alloc] initWithFrame: rect]; + [titleField setAutoresizingMask: NSViewMinYMargin]; + [titleField setEditable: NO]; + [titleField setSelectable: YES]; + [titleField setBezeled: NO]; + [titleField setDrawsBackground: NO]; + [titleField setStringValue: @""]; + [titleField setFont: [NSFont systemFontOfSize: 18.0]]; - if (message != nil) - { - [messageField setStringValue: message]; - [messageField sizeToFit]; - // 5: spacing between text and window borders - width = [messageField frame].size.width + 10; + rect.size.height=LineHeight; + rect.size.width=r.size.width; + rect.origin.y=r.origin.y+r.size.height+LineBottom; + rect.origin.x=LineLeft; + box=[[NSBox alloc] initWithFrame: rect]; + [box setAutoresizingMask: NSViewWidthSizable | NSViewMinYMargin]; + [box setTitlePosition: NSNoTitle]; + [box setBorderType: NSGrooveBorder]; + [content addSubview: box]; + RELEASE(box); - if (width - originalSize.width > excessWidth) - excessWidth = width - originalSize.width; - if ([messageField superview] == nil) - [content addSubview: messageField]; - } - else - { - if ([messageField superview] != nil) - [messageField removeFromSuperview]; - } + // Then, make the subviews that'll be sized by sizePanelToFit; - if (title != nil) - { - [titleField setStringValue: title]; - [titleField sizeToFit]; - // TODO: Check title dimension + rect.size.height=20.0; + rect.size.width=80.0; + rect.origin.y=0.0; + rect.origin.x=0.0; - if ([titleField superview] == nil) - [content addSubview: titleField]; - } - else - { - if ([titleField superview] != nil) - [titleField removeFromSuperview]; - } + messageField=[[NSTextField alloc] initWithFrame:rect]; + [messageField setEditable: NO]; + [messageField setSelectable: YES]; + /* + PJB: + How do you want the user to report an error message if it is + not selectable? Any text visible on the screen should always + be selectable for a copy-and-paste. Hence, setSelectable:YES. + */ + [messageField setBezeled: NO]; + [messageField setDrawsBackground: YES]; + [messageField setBackgroundColor: [NSColor lightGrayColor]]; + [messageField setAlignment: NSCenterTextAlignment]; + [messageField setStringValue: @""]; + [messageField setFont: MessageFont]; - /* Second step, resize the panel to comfortable size */ - if (excessWidth > 0) - { - NSSize s = NSMakeSize (originalSize.width + excessWidth, - originalSize.height + (excessWidth/2)); - [self setMaxSize: s]; - [self setMinSize: s]; - [self setContentSize: s]; - } - else - { - // Resize the panel to standard dimension - [self setMaxSize: originalSize]; - [self setMinSize: originalSize]; - [self setContentSize: originalSize]; - } + defButton=[self _makeButtonWithRect:rect]; + [defButton setKeyEquivalent: @"\r"]; + [defButton setImagePosition: NSImageRight]; + [defButton setImage: [NSImage imageNamed: @"common_ret"]]; - /* Third step, now that the panel size is OK, move objects - in the right position */ - button_origin = [content bounds].size.width - 5 - buttonSize.width; + altButton=[self _makeButtonWithRect:rect]; + othButton=[self _makeButtonWithRect:rect]; - if (defaultButton != nil) - { - bRect.size = buttonSize; - bRect.origin.x = button_origin; - bRect.origin.y = [defButton frame].origin.y; - [defButton setFrame: bRect]; - button_origin -= 10 + buttonSize.width; - - [self makeFirstResponder: defButton]; - } - - if (alternateButton != nil) - { - bRect.size = buttonSize; - bRect.origin.x = button_origin; - bRect.origin.y = [altButton frame].origin.y; - [altButton setFrame: bRect]; - button_origin -= 10 + buttonSize.width; - } - - if (otherButton != nil) - { - bRect.size = buttonSize; - bRect.origin.x = button_origin; - bRect.origin.y = [othButton frame].origin.y; - [othButton setFrame: bRect]; - } - - if (message != nil) - { - // Center the message - bRect = [messageField frame]; - bRect.origin.x = ([content frame].size.width - bRect.size.width) / 2; - [messageField setFrameOrigin: NSMakePoint (bRect.origin.x, bRect.origin.y)]; - } + rect.size.height=80.0; + scroll=makeScrollViewWithRect(rect); + + result=NSAlertErrorReturn; + isGreen=YES; + } + return self; + }//initWithContentRect:styleMask:backing:defer:screen:; + + + -(id)initWithModelUnarchiver:(GMUnarchiver*)unarchiver + { + self=[super initWithModelUnarchiver: unarchiver]; + if(self!=nil){ + // TODO: Remove the following line when NSPanel archiver method will be implemented. + [self setBecomesKeyOnlyIfNeeded:NO]; + + (void)[unarchiver decodeSizeWithName:@"OriginalSize"]; + defButton=[[unarchiver decodeObjectWithName:@"DefaultButton"] + retain]; + altButton=[[unarchiver decodeObjectWithName:@"AlternateButton"] + retain]; + othButton=[[unarchiver decodeObjectWithName:@"OtherButton"] + retain]; + icoButton=[[unarchiver decodeObjectWithName:@"IconButton"] + retain]; + messageField=[[unarchiver decodeObjectWithName:@"MessageField"] + retain]; + titleField=[[unarchiver decodeObjectWithName:@"TitleField"] + retain]; + scroll=makeScrollViewWithRect(NSMakeRect(0.0,0.0,80.0,80.0)); + result=NSAlertErrorReturn; + isGreen=YES; + } + gmodelAlertPanel=self; + return gmodelAlertPanel; + }//initWithModelUnarchiver:; + + + -(void)sizePanelToFit + { + NSRect bounds; + NSSize ssize; // screen size (corrected). + NSSize bsize; // button size (max of the three). + NSSize wsize={0.0,0.0}; // window size (computed). + NSScreen* screen; + NSView* content; + NSButton* buttons[3]; + float position=0.0; + int numberOfButtons; + int i; + BOOL needsScroll; + BOOL couldNeedScroll; + + screen=[self screen]; + if(screen==nil){ + screen=[NSScreen mainScreen]; + } + ssize=[screen frame].size; + ssize.height-=WTitleHeight; + + + // Let's size the title. + if(useControl(titleField)){ + NSRect rect=[titleField frame]; + float width=TitleLeft+rect.size.width+TitleMinRight; + if(wsize.width the title will be silently clipped. + } + } + + wsize.height=-LineBottom; + + + // Let's count the buttons. + bsize.width=ButtonMinWidth; + bsize.height=ButtonMinHeight; + buttons[0]=defButton; + buttons[1]=altButton; + buttons[2]=othButton; + numberOfButtons=0; + for(i=0;i<3;i++){ + if(useControl(buttons[i])){ + NSRect rect=[buttons[i] frame]; + if(bsize.width0){ + // (with NSGetAlertPanel, there could be zero buttons). + float width=(bsize.width+ButtonInterspace)*numberOfButtons + -ButtonInterspace+ButtonMargin*2; + // If the buttons are too wide or too high to fit in the screen, + // then too bad! Thought it would be simple enough to put them + // in the scroll view with the messageField. + // TODO: See if we raise an exception here or if we let the + // QA people detect this kind of problem. + if(wsize.width0){ + position=bounds.origin.x+bounds.size.width-ButtonMargin; + for(i=0;i<3;i++){ + if(useControl(buttons[i])){ + NSRect rect; + position-=bsize.width; + rect.origin.x=position; + rect.origin.y=bounds.origin.y+ButtonBottom; + rect.size.width=bsize.width; + rect.size.height=bsize.height; + [buttons[i] setFrame:rect]; + position-=ButtonInterspace; + } + } + } + + + // Finaly, place the message. + if(useControl(messageField)){ + NSRect mrect=[messageField frame]; + if(needsScroll){ + NSRect srect; + // The scroll view takes all the space that is available. + srect.origin.x=bounds.origin.x+MessageHorzMargin; + if(numberOfButtons>0){ + srect.origin.y=bounds.origin.y+ButtonBottom + +bsize.height+MessageVertMargin; + }else{ + srect.origin.y=bounds.origin.y+MessageVertMargin; + } + srect.size.width=bounds.size.width-2*MessageHorzMargin; + srect.size.height=bounds.origin.y+bounds.size.height + +MessageTop-srect.origin.y; + [scroll setFrame:srect]; + if(!useControl(scroll)){ + [content addSubview:scroll]; + } + [messageField removeFromSuperview]; + mrect.origin.x=srect.origin.x+srect.size.width-mrect.size.width; + mrect.origin.y=srect.origin.y+srect.size.height + -mrect.size.height; + [messageField setFrame:mrect]; + [scroll setDocumentView:messageField]; + [[scroll contentView]scrollToPoint:NSMakePoint(mrect.origin.x, + mrect.origin.y+mrect.size.height + -[[scroll contentView] bounds].size.height)]; + [scroll reflectScrolledClipView:[scroll contentView]]; + }else{ + float vmargin; + // We must center vertically the messageField because + // the window has a minimum size, thus may be greated + // than expected. + mrect.origin.x=bounds.origin.x+MessageHorzMargin; + vmargin=bounds.size.height+LineBottom-mrect.size.height; + if(numberOfButtons>0){ + vmargin-=ButtonBottom+bsize.height; + } + vmargin/=2.0; // if negative, it'll bite up and down. + mrect.origin.y=bounds.origin.y+vmargin; + if(numberOfButtons>0){ + mrect.origin.y+=ButtonBottom+bsize.height; + } + [messageField setFrame:mrect]; + } + }else if(useControl(scroll)){ + [scroll removeFromSuperview]; + } + + isGreen=NO; + [content display]; + }//sizePanelToFit; + + + + -(void)buttonAction:(id)sender + { + if(![self isActivePanel]){ + NSLog(@"alert panel buttonAction: when not in modal loop\n"); + return; + }else if(sender==defButton){ + result=NSAlertDefaultReturn; + }else if(sender==altButton){ + result=NSAlertAlternateReturn; + }else if(sender==othButton){ + result=NSAlertOtherReturn; + }else{ + NSLog(@"alert panel buttonAction: from unknown sender - x%x\n", + (unsigned)sender); + } + [[NSApplication sharedApplication] stopModal]; + }//buttonAction:; + + + -(int)result + { + return result; + }//result; + + + -(BOOL)isActivePanel + { + return([[NSApplication sharedApplication]modalWindow]==self); + }//isActivePanel; + + + -(int)runModal + { + if(isGreen){ + [self sizePanelToFit]; + } + [NSApp runModalForWindow: self]; + [self orderOut: self]; + return result; + }//runModal; + + + + -(void)setTitle:(NSString*)title + message:(NSString*)message + def:(NSString*)defaultButton + alt:(NSString*)alternateButton + other:(NSString*)otherButton + { + NSView* content=[self contentView]; + setControl(content,titleField,title); + // TODO: Remove the following line once NSView is corrected. + [scroll setDocumentView:nil]; + [scroll removeFromSuperview]; + [messageField removeFromSuperview]; + setControl(content,messageField,message); + setControl(content,defButton,defaultButton); + setControl(content,altButton,alternateButton); + setControl(content,othButton,otherButton); + if(useControl(defButton)){ + [self makeFirstResponder: defButton]; + }else{ + [self makeFirstResponder: self]; + } + isGreen=YES; + result=NSAlertErrorReturn; /* If no button was pressed */ + }//setTitle:message:def:alt:other:; - result = NSAlertErrorReturn; /* If no button was pressed */ - [content display]; -} @end /* GSAlertPanel */ -id -NSGetAlertPanel(NSString *title, - NSString *msg, - NSString *defaultButton, - NSString *alternateButton, - NSString *otherButton, ...) -{ - va_list ap; - NSString *message; - GSAlertPanel *panel; +// END GSAlertPanel +//////////////////////////////////////////////////////////////////////// - va_start (ap, otherButton); - message = [NSString stringWithFormat: msg arguments: ap]; - va_end (ap); - if (title == nil) - title = @"Alert"; - if (standardAlertPanel == nil) + /* + These functions may be called "recursively". For example, from a + timed event. Therefore, there may be several alert panel active + at the same time, but only the first one will be THE + standardAlertPanel, which will not be released once finished + with, but which will be kept for future use. + + +---------+---------+---------+---------+---------+ + | std!=0 | std act | pan=std | pan=new | std=new | + +---------+---------+---------+---------+---------+ + a: | F | N/A | | X | X | + +---------+---------+---------+---------+---------+ + b: | V | F | X | | | + +---------+---------+---------+---------+---------+ + c: | V | V | | X | | + +---------+---------+---------+---------+---------+ + */ + + +#define NEW_PANEL [[GSAlertPanel alloc] \ + initWithContentRect: NSMakeRect(0.0,0.0,WinMinWidth,WinMinHeight) \ + styleMask: NSTitledWindowMask \ + backing: NSBackingStoreRetained \ + defer: YES \ + screen: nil] + + /* + if(![GMModel loadIMFile:@"AlertPanel" owner:[GSAlertPanel alloc]]){ + NSLog(@"cannot open alert panel model file\n"); + return nil; + } + */ + +/* + TODO: Check if this discrepancy is wanted and needed. + If not, we could merge these parameters, even + for the alert panel, setting its window title to "Alert". + + + +*/ + + static GSAlertPanel* getSomePanel(GSAlertPanel** instance, + NSString* defaultTitle, + NSString* title, + NSString* message, + NSString* defaultButton, + NSString* alternateButton, + NSString* otherButton) { -#if 0 - if (![GMModel loadIMFile: @"AlertPanel" owner: [GSAlertPanel alloc]]) - { - NSLog(@"cannot open alert panel model file\n"); - return nil; + GSAlertPanel* panel; + + if((*instance)!=0){ + if([(*instance) isActivePanel]){ // c: + panel=NEW_PANEL; + + }else{ // b: + panel=(*instance); + } + }else{ // a: + panel=NEW_PANEL; + (*instance)=panel; } + + if(title==nil){ + title=defaultTitle; + } + + if(defaultTitle!=nil){ + [panel setTitle:defaultTitle]; + } + [panel setTitle: title + message: message + def: defaultButton + alt: alternateButton + other: otherButton]; + [panel sizePanelToFit]; + return panel; + }//getSomePanel; + + + id NSGetAlertPanel(NSString* title, + NSString* msg, + NSString* defaultButton, + NSString* alternateButton, + NSString* otherButton, ...) + { + va_list ap; + NSString* message; + + va_start(ap,otherButton); + message=[NSString stringWithFormat:msg arguments:ap]; + va_end(ap); + + return(getSomePanel(&standardAlertPanel, +#ifndef STRICT_OPENSTEP + @"Alert", #else - - panel = [GSAlertPanel alloc]; - panel = [panel initWithContentRect: NSMakeRect(0, 0, PANX, PANY) - styleMask: NSTitledWindowMask - backing: NSBackingStoreRetained - defer: YES - screen: nil]; - + @" ", #endif - } - else + title,message, + defaultButton,alternateButton,otherButton)); + }//NSGetAlertPanel; + + + + int NSRunAlertPanel(NSString *title, + NSString *msg, + NSString *defaultButton, + NSString *alternateButton, + NSString *otherButton, ...) { - panel = standardAlertPanel; - standardAlertPanel = nil; - } - [panel setTitle: title - message: message - def: defaultButton - alt: alternateButton - other: otherButton]; + va_list ap; + NSString* message; + GSAlertPanel* panel; + int result; - return panel; -} + va_start(ap,otherButton); + message=[NSString stringWithFormat:msg arguments:ap]; + va_end(ap); -id -NSGetCriticalAlertPanel(NSString *title, - NSString *msg, - NSString *defaultButton, - NSString *alternateButton, - NSString *otherButton, ...) -{ - va_list ap; - NSString *message; - GSAlertPanel *panel; + if(defaultButton==nil){ + defaultButton=@"OK"; + } - if (title == nil) - title = @"Warning"; - va_start (ap, otherButton); - message = [NSString stringWithFormat: msg arguments: ap]; - va_end (ap); + panel=getSomePanel(&standardAlertPanel, +#ifndef STRICT_OPENSTEP + @"Alert", +#else + @" ", +#endif + title,message, + defaultButton,alternateButton,otherButton); + result=[panel runModal]; + NSReleaseAlertPanel(panel); + return(result); + }//NSRunAlertPanel; - if (criticalAlertPanel == nil) + + int NSRunLocalizedAlertPanel(NSString *table, + NSString *title, + NSString *msg, + NSString *defaultButton, + NSString *alternateButton, + NSString *otherButton, ...) { - panel = NSGetAlertPanel(title, msg, defaultButton, - alternateButton, otherButton, ap); - criticalAlertPanel = panel; - } - else - panel = criticalAlertPanel; + va_list ap; + NSString* message; + GSAlertPanel* panel; + int result; + NSBundle* bundle=[NSBundle mainBundle]; - [panel setTitle: @"Critical"]; - [panel setTitle: title - message: message - def: defaultButton - alt: alternateButton - other: otherButton]; - return panel; -} + if(title==nil){ +#ifndef STRICT_OPENSTEP + title=@"Alert"; +#else + title=@" "; +#endif + } -id -NSGetInformationalAlertPanel(NSString *title, - NSString *msg, - NSString *defaultButton, - NSString *alternateButton, - NSString *otherButton, ...) -{ - va_list ap; - NSString *message; - GSAlertPanel *panel; +#define localize(string) if(string!=nil) \ + string=[bundle localizedStringForKey:string value:string table:table] - if (title == nil) - title = @"Information"; - va_start (ap, otherButton); - message = [NSString stringWithFormat: msg arguments: ap]; - va_end (ap); + localize(title); + localize(defaultButton); + localize(alternateButton); + localize(otherButton); + localize(msg); - if (informationalAlertPanel == nil) +#undef localize + + va_start(ap,otherButton); + message=[NSString stringWithFormat:msg arguments:ap]; + va_end(ap); + + if(defaultButton==nil){ + defaultButton=@"OK"; + } + + panel=getSomePanel(&standardAlertPanel,@"Alert",//anyway,title!=nil. + title,message, + defaultButton,alternateButton,otherButton); + result=[panel runModal]; + NSReleaseAlertPanel(panel); + return(result); + }//NSRunLocalizedAlertPanel; + + + + id NSGetCriticalAlertPanel(NSString* title, + NSString* msg, + NSString* defaultButton, + NSString* alternateButton, + NSString* otherButton, ...) { - panel = NSGetAlertPanel(title, msg, defaultButton, - alternateButton, otherButton, ap); - informationalAlertPanel = panel; - } - else - panel = informationalAlertPanel; + va_list ap; + NSString* message; - [panel setTitle: @"Information"]; - [panel setTitle: title - message: message - def: defaultButton - alt: alternateButton - other: otherButton]; - return panel; -} + va_start(ap,otherButton); + message=[NSString stringWithFormat:msg arguments:ap]; + va_end(ap); -void -NSReleaseAlertPanel(id alertPanel) -{ - if (alertPanel != standardAlertPanel - && alertPanel != informationalAlertPanel - && alertPanel != criticalAlertPanel) - [alertPanel release]; -} + return(getSomePanel(&criticalAlertPanel,@"Critical", + title,message, + defaultButton,alternateButton,otherButton)); + }//NSGetCriticalAlertPanel; -int -NSRunAlertPanel(NSString *title, - NSString *msg, - NSString *defaultButton, - NSString *alternateButton, - NSString *otherButton, ...) -{ - va_list ap; - GSAlertPanel *panel; - NSString *message; - int result; - if (title == nil) - title = @"Alert"; - if (defaultButton == nil) - defaultButton = @"OK"; - - va_start (ap, otherButton); - message = [NSString stringWithFormat: msg arguments: ap]; - va_end (ap); - - if (standardAlertPanel) + int NSRunCriticalAlertPanel(NSString *title, + NSString *msg, + NSString *defaultButton, + NSString *alternateButton, + NSString *otherButton, ...) { - panel = standardAlertPanel; - [panel setTitle: title - message: message - def: defaultButton - alt: alternateButton - other: otherButton]; - } - else + va_list ap; + NSString* message; + GSAlertPanel* panel; + int result; + + va_start(ap,otherButton); + message=[NSString stringWithFormat:msg arguments:ap]; + va_end(ap); + + panel=getSomePanel(&criticalAlertPanel,@"Critical", + title,message, + defaultButton,alternateButton,otherButton); + result=[panel runModal]; + NSReleaseAlertPanel(panel); + return(result); + }//NSRunCriticalAlertPanel; + + + id NSGetInformationalAlertPanel(NSString* title, + NSString* msg, + NSString* defaultButton, + NSString* alternateButton, + NSString* otherButton, ...) { - panel = NSGetAlertPanel(title, message, defaultButton, - alternateButton, otherButton, ap); - standardAlertPanel = panel; - } + va_list ap; + NSString* message; - result = [panel runModal]; - NSReleaseAlertPanel(panel); - return result; -} + va_start(ap,otherButton); + message=[NSString stringWithFormat:msg arguments:ap]; + va_end(ap); -int -NSRunCriticalAlertPanel(NSString *title, - NSString *msg, - NSString *defaultButton, - NSString *alternateButton, - NSString *otherButton, ...) -{ - va_list ap; - GSAlertPanel *panel; - int result; + return(getSomePanel(&informationalAlertPanel, + @"Information", + title,message, + defaultButton,alternateButton,otherButton)); + }//NSGetInformationalAlertPanel; - va_start (ap, otherButton); - panel = NSGetCriticalAlertPanel(title, msg, - defaultButton, alternateButton, otherButton, ap); - va_end (ap); - result = [panel runModal]; - NSReleaseAlertPanel(panel); - return result; -} + int NSRunInformationalAlertPanel(NSString *title, + NSString *msg, + NSString *defaultButton, + NSString *alternateButton, + NSString *otherButton, ...) + { + va_list ap; + NSString* message; + GSAlertPanel* panel; + int result; -int -NSRunInformationalAlertPanel(NSString *title, - NSString *msg, - NSString *defaultButton, - NSString *alternateButton, - NSString *otherButton, ...) -{ - va_list ap; - GSAlertPanel *panel; - int result; + va_start(ap,otherButton); + message=[NSString stringWithFormat:msg arguments:ap]; + va_end(ap); - va_start (ap, otherButton); - panel = NSGetInformationalAlertPanel(title, msg, - defaultButton, alternateButton, otherButton, ap); - va_end (ap); + panel=getSomePanel(&informationalAlertPanel, + @"Information", + title,message, + defaultButton,alternateButton,otherButton); + result=[panel runModal]; + NSReleaseAlertPanel(panel); + return(result); + }//NSRunInformationalAlertPanel; - result = [panel runModal]; - NSReleaseAlertPanel(panel); - return result; -} -int -NSRunLocalizedAlertPanel(NSString *table, - NSString *title, - NSString *msg, - NSString *defaultButton, - NSString *alternateButton, - NSString *otherButton, ...) -{ - va_list ap; - GSAlertPanel *panel; - NSString *message; - int result; - NSBundle *bundle = [NSBundle mainBundle]; - - if (title == nil) - title = @"Alert"; - - title = [bundle localizedStringForKey: title - value: title - table: table]; - if (defaultButton) - defaultButton = [bundle localizedStringForKey: defaultButton - value: defaultButton - table: table]; - if (alternateButton) - alternateButton = [bundle localizedStringForKey: alternateButton - value: alternateButton - table: table]; - if (otherButton) - otherButton = [bundle localizedStringForKey: otherButton - value: otherButton - table: table]; - if (msg) - msg = [bundle localizedStringForKey: msg - value: msg - table: table]; - - va_start (ap, otherButton); - message = [NSString stringWithFormat: msg arguments: ap]; - va_end (ap); - - if (standardAlertPanel) + void NSReleaseAlertPanel(id alertPanel) { - panel = standardAlertPanel; - [panel setTitle: title - message: message - def: defaultButton - alt: alternateButton - other: otherButton]; - } - else - { - panel = NSGetAlertPanel(title, message, defaultButton, - alternateButton, otherButton, ap); - standardAlertPanel = panel; - } + if((alertPanel!=standardAlertPanel) + &&(alertPanel!=informationalAlertPanel) + &&(alertPanel!=criticalAlertPanel)){ + [alertPanel release]; + } + }//NSReleaseAlertPanel; - result = [panel runModal]; - NSReleaseAlertPanel(panel); - return result; -} + +/*** NSPanel.m -- 2000-03-08 05:15:47 -- PJB ***/