merge in themes branch to keep in sync

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@23705 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2006-10-02 05:09:48 +00:00
parent c8e6566831
commit c033d17a2d
13 changed files with 1446 additions and 372 deletions

View file

@ -1,3 +1,42 @@
2006-10-01 Richard Frith-Macdonald <rfm@gnu.org>
* Source/GSTheme.m: Add rudimentary inspector.
Make themes in panel be in alphabetical order except for the
default theme (always first in the list).
Allow setting of default theme for application.
* Source/NSHelpManager.m:
* Source/NSHelpPanel.m: Implement simple fallback help panel display
for systems where no rtf/rtfd viewing application is installed.
2006-09-30 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSColor.m: Remove debug log message.
* Source/GSInfoPanel.m: Open theme handling panel.
* Source/GSTheme.m: Rudimentary theme handling panel.
* Headers/Additions/GNUstepGUI/GSTheme.h: A few more methods.
Start adding a panel to allow selection of themes in a running app.
2006-09-29 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSWindow.m: If ordering out a deferred window which was
never ordered in, there is nothing to do.
* Source/NSMenu.m: (_organize) when switching from horizontal to
vertical menu, attempt to restore contents fo the app menu to the
main menu in a reasonable manner.
* Source/NSHelpManager.m: Use the help file specified in Info.plist
* Headers/Additions/GNUstepGUI/GSTheme.h:
* Source/GSTheme.m: Add -authors and -icon methods. Support loading
from an absolute path.
2006-09-28 Richard Frith-Macdonald <rfm@gnu.org>
* Source/GSTheme.m: Update main menu on theme activation.
* Source/NSMenu.m: ([setMain:]) handle change of interface style.
* Source/NSInterfaceStyle.m: Observe/handle theme activation.
* Headers/AppKit/NSMenu.h: remove internal method from public header
* Headers/Additions/GNUstepGUI/GSTheme.h: add -infoDictionary method
and documentation.
2006-09-26 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSWorkspace.m: Use png in preference to tiff.
@ -25,7 +64,7 @@
2006-09-23 Richard Frith-Macdonald <rfm@gnu.org>
* Source/GSWindowDecorationView.m: coimment out dubious change.
* Source/GSWindowDecorationView.m: comment out dubious change.
* Source/GSDisplayServer.m: Add method for expose events
* Source/NSWindow.m: Handle expose events.
* Headers/AppKit/NSEvent.h: Add expose event type.

View file

@ -139,8 +139,11 @@
#include "AppKit/NSButtonCell.h"
#if OS_API_VERSION(GS_API_NONE,GS_API_NONE)
@class NSArray;
@class NSBundle;
@class NSColor;
@class NSDictionary;
@class NSImage;
@class GSDrawTiles;
/**
@ -207,8 +210,15 @@ APPKIT_EXPORT NSString *GSThemeDidDeactivateNotification;
NSBundle *_bundle;
NSMutableArray *_images;
NSMutableDictionary *_tiles;
NSImage *_icon;
}
/**
* Creates and displays a panel allowing selection of different themes
* and display of the current theme inspector.
*/
+ (void) orderFrontSharedThemePanel: (id)sender;
/**
* Set the currently active theme to be the instance specified.<br />
* You do not normally need to call this method as it is called
@ -228,17 +238,27 @@ APPKIT_EXPORT NSString *GSThemeDidDeactivateNotification;
* <p>This method is called automatically when the receiver is made into
* the currently active theme by the +setTheme: method. Subclasses may
* override it to perform startup operations, but should call the super
* class implementation before doing their own thing.
* class implementation after doing their own thing.
* </p>
* <p>The base implementation handles setup and caching of certain image
* information and then sends a GSThemeDidActivateNotification to allow
* other parts of the GUI library to update themselves from the new theme.<br />
* <p>The base implementation handles setup and caching of the system
* color list, standard image information, tiling information,
* and user defaults.<br />
* It then sends a GSThemeDidActivateNotification to allow other
* parts of the GUI library to update themselves from the new theme.<br />
* If the theme sets an alternative system color list, the notification
* userInfo dictionary will contain that list keyed on <em>Colors</em>.
* </p>
* <p>Finally, this method marks all windows in the application as needing
* update ... so they will draw themselves with the new theme information.
* </p>
*/
- (void) activate;
/**
* Returns the names of the theme's authors.
*/
- (NSArray*) authors;
/**
* Return the bundle containing the resources used by the current theme.
*/
@ -258,6 +278,11 @@ APPKIT_EXPORT NSString *GSThemeDidDeactivateNotification;
*/
- (void) deactivate;
/**
* Returns the theme's icon.
*/
- (NSImage*) icon;
/** <init />
* Initialise an instance of a theme with the specified resource bundle.<br />
* You don't need to call this method directly, but if you are subclassing
@ -265,6 +290,59 @@ APPKIT_EXPORT NSString *GSThemeDidDeactivateNotification;
*/
- (id) initWithBundle: (NSBundle*)bundle;
/**
* <p>Returns the info dictionary for this theme. In the base class
* implementation this is simply the info dictionary of the theme
* bundle, but subclasses may override this method to return extra
* or different information.
* </p>
* <p>Keys found in this dictionary include:
* </p>
* <deflist>
* <term>GSThemeDomain</term>
* <desc>A dictionary whose key/value pairs are used to set up new values
* in the GSThemeDomain domain of the user defaults system, and hence
* define values for these unless overridden by values set explicitly by
* the user.
* </desc>
* <term>GSThemeTiles</term>
* <desc>A dictionary keyed on tile names and containing the following:
* <deflist>
* <term>FileName</term>
* <desc>Name of the file (within the GSThemeTiles directory in the
* bundle) in which the image for this tile is tored.
* </desc>
* <term>HorizontalDivision</term>
* <desc>The offet along the X-axis used to divide the image into
* columns of tiles.
* </desc>
* <term>VerticalDivision</term>
* <desc>The offet along the Y-axis used to divide the image into
* rows of tiles.
* </desc>
* </deflist>
* </desc>
* </deflist>
*/
- (NSDictionary*) infoDictionary;
/**
* Return the theme's name.
*/
- (NSString*) name;
/**
* <p>Provides a standard inspector window used to display information about
* the receiver. The default implementation displays the icon, the name,
* and the authors of the theme.
* </p>
* <p>The code managing this object (if any) must be prepared to have the
* content view of the window reparented into another window for display
* on screen.
* </p>
*/
- (NSWindow*) themeInspector;
/**
* Returns the tile image information for a particular image name,
* or nil if there is no such information.<br />

View file

@ -48,43 +48,43 @@
//
// Accessing the Help Panel
//
+ (NSHelpPanel *)sharedHelpPanel;
+ (NSHelpPanel *)sharedHelpPanelWithDirectory:(NSString *)helpDirectory;
+ (NSHelpPanel *) sharedHelpPanel;
+ (NSHelpPanel *) sharedHelpPanelWithDirectory: (NSString *)helpDirectory;
//
// Managing the Contents
//
+ (void)setHelpDirectory:(NSString *)helpDirectory;
- (void)addSupplement:(NSString *)helpDirectory
inPath:(NSString *)supplementPath;
- (NSString *)helpDirectory;
- (NSString *)helpFile;
+ (void) setHelpDirectory: (NSString *)helpDirectory;
- (void) addSupplement: (NSString *)helpDirectory
inPath: (NSString *)supplementPath;
- (NSString *) helpDirectory;
- (NSString *) helpFile;
//
// Attaching Help to Objects
//
+ (void)attachHelpFile:(NSString *)filename
markerName:(NSString *)markerName
to:(id)anObject;
+ (void)detachHelpFrom:(id)anObject;
+ (void) attachHelpFile: (NSString *)filename
markerName: (NSString *)markerName
to: (id)anObject;
+ (void) detachHelpFrom: (id)anObject;
//
// Showing Help
//
- (void)showFile:(NSString *)filename
atMarker:(NSString *)markerName;
- (BOOL)showHelpAttachedTo:(id)anObject;
- (void) showFile: (NSString *)filename
atMarker: (NSString *)markerName;
- (BOOL) showHelpAttachedTo: (id)anObject;
//
// Printing
//
- (void)print:(id)sender;
- (void) print: (id)sender;
//
// NSCoding protocol
//
- (void)encodeWithCoder: (NSCoder *)aCoder;
- initWithCoder: (NSCoder *)aDecoder;
- (void) encodeWithCoder: (NSCoder *)aCoder;
- (id) initWithCoder: (NSCoder *)aDecoder;
@end

View file

@ -592,9 +592,14 @@ The displayed menus on the screen have the following structure:
- (NSWindow*) window;
/**
Flag this menu to be the main menu of the application,
<p>Flag this menu to be the main menu of the application,
when isMain is YES. Flag it as no longer being the main
menu when NO is handed in.
</p>
<p>This method also checks the user defaults to determine how
the menu is to be displayed (eg vertical or horizontal) and can
therefore be used to change window geometry.
</p>
*/
- (void) setMain: (BOOL)isMain;
@ -609,13 +614,6 @@ The displayed menus on the screen have the following structure:
*/
- (void) displayTransient;
/**
Positions the menu according to the standard user defaults.
If the position is not found in the defaults revert to positioning
the window in the upper left corner.
*/
- (void) setGeometry;
/**
When the flag is YES
this method will detach the receiver from its parent and

View file

@ -30,11 +30,13 @@
#include "AppKit/NSFont.h"
#include "AppKit/NSImage.h"
#include "AppKit/NSTextField.h"
#include "GNUstepGUI/GSInfoPanel.h"
#include <Foundation/NSBundle.h>
#include <Foundation/NSDictionary.h>
#include <Foundation/NSString.h>
#include <Foundation/NSProcessInfo.h>
#include "GNUstepGUI/GSInfoPanel.h"
#include "GNUstepGUI/GSTheme.h"
static id
value_from_info_plist_for_key (NSString *key)
@ -156,7 +158,7 @@ new_label (NSString *value)
}
}
-(id) initWithDictionary: (NSDictionary *)dictionary;
- (id) initWithDictionary: (NSDictionary *)dictionary;
{
/* Info to show */
NSString *name = nil;
@ -593,4 +595,15 @@ new_label (NSString *value)
[self center];
return self;
}
- (void) mouseDown: (NSEvent*)theEvent
{
/*
* Mouse down on window background ... we could do different things in
* different regions of the window, but for now we just use this to
* activate the theme panel.
*/
[GSTheme orderFrontSharedThemePanel: self];
}
@end

File diff suppressed because it is too large Load diff

View file

@ -1680,7 +1680,6 @@ systemColorWithName(NSString *name)
list = [NSColorList colorListNamed: @"System"];
ASSIGN(systemColors, list);
[systemDict removeAllObjects];
NSLog(@"Theme activation with control background %@", [self controlBackgroundColor]);
[[NSNotificationCenter defaultCenter]
postNotificationName: NSSystemColorsDidChangeNotification object: nil];
}

View file

@ -27,6 +27,7 @@
*/
#include <Foundation/NSUserDefaults.h>
#include <Foundation/NSData.h>
#include <Foundation/NSNotification.h>
#include <Foundation/NSFileManager.h>
#include <Foundation/NSString.h>
@ -36,13 +37,14 @@
#include "AppKit/NSApplication.h"
#include "AppKit/NSWorkspace.h"
#include "AppKit/NSHelpManager.h"
#include "AppKit/NSHelpPanel.h"
#include "AppKit/NSGraphics.h"
#include "GNUstepGUI/GSHelpManagerPanel.h"
@implementation NSBundle (NSHelpManager)
- (NSString *)pathForHelpResource:(NSString *)fileName
- (NSString *) pathForHelpResource: (NSString *)fileName
{
NSFileManager *fm = [NSFileManager defaultManager];
NSMutableArray *array = [NSMutableArray array];
@ -59,6 +61,7 @@
while ((language = [enumerator nextObject]))
{
NSString *langDir = [NSString stringWithFormat: @"%@.lproj", language];
[array addObject: [primary stringByAppendingPathComponent: langDir]];
}
@ -71,6 +74,7 @@
while ((language = [enumerator nextObject]))
{
NSString *langDir = [NSString stringWithFormat: @"%@.lproj", language];
[array addObject: [primary stringByAppendingPathComponent: langDir]];
}
@ -107,7 +111,7 @@
return nil;
}
- (NSAttributedString *)contextHelpForKey:(NSString *)key
- (NSAttributedString *) contextHelpForKey: (NSString *)key
{
NSFileManager *fm = [NSFileManager defaultManager];
NSString *dictPath = [self pathForResource: @"Help" ofType: @"plist"];
@ -127,8 +131,8 @@
if (helpFile)
{
NSData *data = [helpFile objectForKey: @"NSHelpRTFContents"];
return ((data != nil) ? [NSUnarchiver unarchiveObjectWithData: data] :
nil) ;
return ((data != nil) ? [NSUnarchiver unarchiveObjectWithData: data]
: nil);
}
else
@ -137,8 +141,10 @@
if (helpFile)
{
NSString *helpstr = [[NSAttributedString alloc] initWithPath: helpFile
documentAttributes: NULL];
NSString *helpstr;
helpstr = [[NSAttributedString alloc] initWithPath: helpFile
documentAttributes: NULL];
return TEST_AUTORELEASE (helpstr);
}
}
@ -165,7 +171,7 @@
// "appname.rtfd" or "appname.rtf"
}
if (help)
if (help != nil)
{
NSString *file = nil;
@ -180,13 +186,64 @@
[help stringByAppendingPathExtension: @"rtf"]];
}
}
else
{
file = [mb pathForHelpResource: help];
}
if (file)
{
[[NSWorkspace sharedWorkspace] openFile: file];
return;
}
}
if (file != nil)
{
if ([[NSWorkspace sharedWorkspace] openFile: file] == YES)
{
return;
}
else
{
NSHelpPanel *panel = [NSHelpPanel sharedHelpPanel];
NSString *ext = [file pathExtension];
NSTextView *tv;
id object;
tv = [(NSScrollView*)[panel contentView] documentView];
if (ext == nil
|| [ext isEqualToString: @""]
|| [ext isEqualToString: @"txt"]
|| [ext isEqualToString: @"text"])
{
object = [NSString stringWithContentsOfFile: file];
}
else if ([ext isEqualToString: @"rtf"])
{
NSData *data = [NSData dataWithContentsOfFile: file];
object = [[NSAttributedString alloc] initWithRTF: data
documentAttributes: 0];
AUTORELEASE (object);
}
else if ([ext isEqualToString: @"rtfd"])
{
NSFileWrapper *wrapper;
wrapper = [[NSFileWrapper alloc] initWithPath: file];
AUTORELEASE (wrapper);
object = [[NSAttributedString alloc]
initWithRTFDFileWrapper: wrapper
documentAttributes: 0];
AUTORELEASE (object);
}
if (object != nil)
{
[[tv textStorage] setAttributedString: object];
[tv sizeToFit];
}
[tv setNeedsDisplay: YES];
[panel makeKeyAndOrderFront: self];
return;
}
}
}
NSBeep();
}
@ -207,7 +264,7 @@ static BOOL _gnu_contextHelpActive = NO;
//
// Class methods
//
+ (NSHelpManager*)sharedHelpManager
+ (NSHelpManager*) sharedHelpManager
{
if (!_gnu_sharedHelpManager)
{
@ -217,12 +274,12 @@ static BOOL _gnu_contextHelpActive = NO;
return _gnu_sharedHelpManager;
}
+ (BOOL)isContextHelpModeActive
+ (BOOL) isContextHelpModeActive
{
return _gnu_contextHelpActive;
}
+ (void)setContextHelpModeActive: (BOOL) flag
+ (void) setContextHelpModeActive: (BOOL) flag
{
_gnu_contextHelpActive = flag;
if (flag)
@ -287,7 +344,7 @@ static BOOL _gnu_contextHelpActive = NO;
NSMapRemove(contextHelpTopics, object);
}
- (void)setContextHelp:(NSAttributedString *)help forObject:(id)object
- (void) setContextHelp: (NSAttributedString *)help forObject: (id)object
{
NSMapInsert(contextHelpTopics, object, help);
}

View file

@ -26,6 +26,9 @@
#include "config.h"
#include "AppKit/NSHelpPanel.h"
#include "AppKit/NSHelpManager.h"
#include "AppKit/NSScrollView.h"
#include "AppKit/NSTextView.h"
#include "AppKit/NSTextContainer.h"
@implementation NSApplication (NSHelpPanel)
@ -40,49 +43,68 @@
@implementation NSHelpPanel
static NSString *_helpDirectory = nil;
static NSString *_helpFile = nil;
static NSHelpPanel *_sharedPanel = nil;
//
// Class methods
//
+ (void)initialize
+ (void) initialize
{
if (self == [NSHelpPanel class])
{
// Initial version
[self setVersion:1];
[self setVersion: 1];
}
}
//
// Accessing the Help Panel
//
+ (NSHelpPanel *)sharedHelpPanel
+ (NSHelpPanel*) sharedHelpPanel
{
NSRunAlertPanel (NULL, @"Help Panel not implemented yet",
@"OK", NULL, NULL);
return nil;
if (_sharedPanel == nil)
{
return [self new];
}
return _sharedPanel;
}
+ (NSHelpPanel *)sharedHelpPanelWithDirectory:(NSString *)helpDirectory
+ (NSHelpPanel *) sharedHelpPanelWithDirectory: (NSString *)helpDirectory
{
return nil;
[self setHelpDirectory: helpDirectory];
return [self sharedHelpPanel];
}
//
// Managing the Contents
//
+ (void)setHelpDirectory:(NSString *)helpDirectory
{}
+ (void) setHelpDirectory: (NSString *)helpDirectory
{
ASSIGN(_helpDirectory, helpDirectory);
}
//
// Attaching Help to Objects
//
+ (void)attachHelpFile:(NSString *)filename
markerName:(NSString *)markerName
to:(id)anObject
{}
+ (void) attachHelpFile: (NSString *)filename
markerName: (NSString *)markerName
to: (id)anObject
{
if ([filename isAbsolutePath] == NO)
{
filename = [[[NSHelpPanel sharedHelpPanel] helpDirectory]
stringByAppendingPathComponent: filename];
}
[[NSHelpManager sharedHelpManager] setContextHelp: (id)filename
forObject: anObject];
}
+ (void)detachHelpFrom:(id)anObject
{}
+ (void) detachHelpFrom: (id)anObject
{
[[NSHelpManager sharedHelpManager] removeContextHelpForObject: anObject];
}
//
// Instance methods
@ -90,37 +112,100 @@ to:(id)anObject
//
// Managing the Contents
//
- (void)addSupplement:(NSString *)helpDirectory
inPath:(NSString *)supplementPath
{}
- (NSString *)helpDirectory
- (void) addSupplement: (NSString *)helpDirectory
inPath: (NSString *)supplementPath
{
return nil;
}
- (NSString *)helpFile
- (NSString *) helpDirectory
{
return nil;
return _helpDirectory;
}
- (NSString *) helpFile
{
return _helpFile;
}
- (id) initWithContentRect: (NSRect)contentRect
styleMask: (unsigned int)aStyle
backing: (NSBackingStoreType)bufferingType
defer: (BOOL)flag
screen: (NSScreen*)aScreen
{
if (_sharedPanel == nil)
{
NSScrollView *s;
NSTextView *v;
NSRect r;
self = [super initWithContentRect: NSMakeRect(100,100,400,500)
styleMask: NSTitledWindowMask|NSClosableWindowMask|NSResizableWindowMask
backing: NSBackingStoreBuffered
defer: NO
screen: nil];
[self setReleasedWhenClosed: NO];
[self setTitle: @"Help"];
s = [[NSScrollView alloc] initWithFrame: contentRect];
[s setHasHorizontalScroller: YES];
[s setHasVerticalScroller: YES];
[s setAutoresizingMask: (NSViewWidthSizable | NSViewHeightSizable)];
[self setContentView: s];
RELEASE(s);
r = [[s documentView] frame];
v = [[NSTextView alloc] initWithFrame: r];
[v setHorizontallyResizable: YES];
[v setVerticallyResizable: YES];
[v setEditable: NO];
[v setRichText: YES];
[v setMinSize: NSMakeSize (0, 0)];
[v setMaxSize: NSMakeSize (1E7, 1E7)];
[v setAutoresizingMask: NSViewHeightSizable | NSViewWidthSizable];
[[v textContainer] setContainerSize:
NSMakeSize (r.size.width, 1e7)];
[[v textContainer] setWidthTracksTextView: YES];
[s setDocumentView: v];
RELEASE(v);
_sharedPanel = self;
}
else
{
RELEASE(self);
}
return _sharedPanel;
}
//
// Showing Help
//
- (void)showFile:(NSString *)filename
atMarker:(NSString *)markerName
{}
- (BOOL)showHelpAttachedTo:(id)anObject
- (void) showFile: (NSString *)filename
atMarker: (NSString *)markerName
{
return NO;
if ([filename isAbsolutePath] == NO)
{
filename = [[[NSHelpPanel sharedHelpPanel] helpDirectory]
stringByAppendingPathComponent: filename];
}
[[NSHelpManager sharedHelpManager] setContextHelp: (id)filename
forObject: self];
[self showHelpAttachedTo: self];
}
- (BOOL) showHelpAttachedTo: (id)anObject
{
return [[NSHelpManager sharedHelpManager]
showContextHelpForObject: anObject locationHint: NSZeroPoint];
}
//
// Printing
//
- (void)print:(id)sender
{}
- (void) print: (id)sender
{
}
//
// NSCoding protocol

View file

@ -33,6 +33,7 @@
#include "AppKit/NSResponder.h"
#include "AppKit/NSInterfaceStyle.h"
#include "GNUstepGUI/GSTheme.h"
NSString *NSInterfaceStyleDefault = @"NSInterfaceStyleDefault";
@ -173,6 +174,11 @@ NSInterfaceStyleForKey(NSString *key, NSResponder *responder)
selector: @selector(defaultsDidChange:)
name: NSUserDefaultsDidChangeNotification
object: nil];
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: @selector(defaultsDidChange:)
name: GSThemeDidActivateNotification
object: nil];
}
}
@ -183,6 +189,12 @@ NSInterfaceStyleForKey(NSString *key, NSResponder *responder)
NSString *key;
void *val;
/*
* We ignore the actual notification, which may be nil (when called at
* initialization), or may contain a user defaults object (if a persistent
* domain changed), or may contain a theme object (if a theme activated).
* What we need to do is examine the current state of the standard defaults.
*/
defs = [NSUserDefaults standardUserDefaults];
/*

View file

@ -120,10 +120,11 @@ static NSNotificationCenter *nc;
@interface NSMenu (GNUstepPrivate)
- (NSString *) _locationKey;
- (NSMenuPanel *) _createWindow;
- (void) _updateUserDefaults: (id) notification;
- (NSString *) _locationKey;
- (void) _rightMouseDisplay: (NSEvent*)theEvent;
- (void) _setGeometry;
- (void) _updateUserDefaults: (id) notification;
@end
@ -204,38 +205,78 @@ static NSNotificationCenter *nc;
- (void) _organizeMenu
{
if (_horizontal == YES)
int i;
if ([self isEqual: [NSApp mainMenu]] == YES)
{
NSString *title = [[NSProcessInfo processInfo] processName];
NSMenu *appMenu = [[self itemWithTitle: title] submenu];
NSString *appTitle;
NSMenu *appMenu;
NSMenuItem *appItem;
if (![self isEqual: [NSApp mainMenu]])
return;
appTitle = [[NSProcessInfo processInfo] processName];
appItem = (NSMenuItem *)[self itemWithTitle: appTitle];
appMenu = [appItem submenu];
if (appMenu == nil)
if (_horizontal == YES)
{
int i;
NSMutableArray *itemsToMove = [NSMutableArray new];
NSMenuItem *appItem;
NSImage *ti = [[NSApp applicationIconImage] copy];
float bar = [NSMenuView menuBarHeight] - 4;
NSMutableArray *itemsToMove;
NSImage *ti;
float bar;
appMenu = [NSMenu new];
for (i = 0; i < [_items count]; i++)
ti = [[NSApp applicationIconImage] copy];
if (ti == nil)
{
NSMenuItem *anItem = [_items objectAtIndex: i];
NSString *title = [anItem title];
ti = [[NSImage imageNamed: @"GNUstep"] copy];
}
[ti setScalesWhenResized: YES];
bar = [NSMenuView menuBarHeight] - 4;
[ti setSize: NSMakeSize(bar, bar)];
if (![anItem submenu])
itemsToMove = [NSMutableArray new];
if (appMenu == nil)
{
[self insertItemWithTitle: appTitle
action: NULL
keyEquivalent: @""
atIndex: 0];
appItem = [self itemAtIndex: 0];
appMenu = [NSMenu new];
[self setSubmenu: appMenu forItem: appItem];
RELEASE(appMenu);
}
else
{
int index = [self indexOfItem: appItem];
if (index != 0)
{
RETAIN (appItem);
[self removeItemAtIndex: index];
[self insertItem: appItem atIndex: 0];
RELEASE (appItem);
}
}
[appItem setImage: ti];
RELEASE(ti);
for (i = 1; i < [_items count]; i++)
{
NSMenuItem *anItem = [_items objectAtIndex: i];
NSString *title = [anItem title];
NSMenu *submenu = [anItem submenu];
if (submenu == nil)
{
[itemsToMove addObject: anItem];
}
if ([title isEqual: NSLocalizedString (@"Info",
@"Info")])
else
{
[itemsToMove addObject: anItem];
if ([title isEqual: NSLocalizedString (@"Info", @"Info")])
{
[itemsToMove addObject: anItem];
}
[[submenu menuRepresentation] update];
}
}
@ -244,76 +285,99 @@ static NSNotificationCenter *nc;
[self removeItem: [itemsToMove objectAtIndex: i]];
[appMenu addItem: [itemsToMove objectAtIndex: i]];
}
[[appMenu menuRepresentation] update];
[self insertItemWithTitle: [[NSProcessInfo processInfo] processName]
action: NULL
keyEquivalent: @""
atIndex: 0];
appItem = (NSMenuItem *)[self itemWithTitle: title];
if (!ti)
ti = [[NSImage imageNamed: @"GNUstep"] copy];
[ti setScalesWhenResized: YES];
[ti setSize: NSMakeSize(bar, bar)];
[appItem setImage: ti];
RELEASE (ti);
[self setSubmenu: appMenu forItem: appItem];
[itemsToMove release];
RELEASE(itemsToMove);
}
else
{
int i;
NSMutableArray *itemsToMove = [NSMutableArray new];
NSMenuItem *appItem = [self itemWithTitle: [[NSProcessInfo processInfo] processName]];
int index = [self indexOfItem: appItem];
NSImage *ti = [[NSApp applicationIconImage] copy];
float bar = [NSMenuView menuBarHeight] - 4;
if (!ti)
ti = [[NSImage imageNamed: @"GNUstep"] copy];
[ti setScalesWhenResized: YES];
[ti setSize: NSMakeSize(bar, bar)];
[appItem setImage: ti];
RELEASE (ti);
if (index != 0)
[appItem setImage: nil];
if (appMenu != nil)
{
RETAIN (appItem);
[self removeItemAtIndex: index];
[self insertItem: appItem atIndex: 0];
RELEASE (appItem);
}
NSArray *array = [NSArray arrayWithArray: [appMenu itemArray]];
for (i = 0; i < [_items count]; i++)
{
NSMenuItem *anItem = [_items objectAtIndex: i];
NSString *title = [anItem title];
for (i = 0; i < [array count]; i++)
{
NSMenuItem *anItem = [array objectAtIndex: i];
NSMenu *submenu = [anItem submenu];
if (![anItem submenu])
{
[itemsToMove addObject: anItem];
}
if ([title isEqual: NSLocalizedString (@"Info",
@"Info")])
{
[itemsToMove addObject: anItem];
[appMenu removeItem: anItem];
if (submenu == nil)
{
[self addItem: anItem];
}
else
{
[self insertItem: anItem atIndex: 0]; // Info menu
}
}
[self removeItem: appItem];
}
for (i = 0; i < [itemsToMove count]; i++)
{
[self removeItem: [itemsToMove objectAtIndex: i]];
[appMenu addItem: [itemsToMove objectAtIndex: i]];
}
[itemsToMove release];
}
}
for (i = 0; i < [_items count]; i++)
{
NSMenuItem *anItem = [_items objectAtIndex: i];
NSMenu *submenu = [anItem submenu];
if (submenu != nil)
{
if ([submenu isTransient])
{
[submenu closeTransient];
}
[submenu close];
[submenu _organizeMenu];
}
}
[[self menuRepresentation] update];
[self sizeToFit];
}
- (void) _setGeometry
{
NSPoint origin;
if (_horizontal == YES)
{
origin = NSMakePoint (0, [[NSScreen mainScreen] frame].size.height
- [_aWindow frame].size.height);
[_aWindow setFrameOrigin: origin];
[_bWindow setFrameOrigin: origin];
}
else
{
NSString *key;
if (nil != (key = [self _locationKey]))
{
NSUserDefaults *defaults;
NSDictionary *menuLocations;
NSString *location;
defaults = [NSUserDefaults standardUserDefaults];
menuLocations = [defaults objectForKey: NSMenuLocationsKey];
if ([menuLocations isKindOfClass: [NSDictionary class]])
location = [menuLocations objectForKey: key];
else
location = nil;
if (location && [location isKindOfClass: [NSString class]])
{
[_aWindow setFrameFromString: location];
[_bWindow setFrameFromString: location];
return;
}
}
origin = NSMakePoint(0, [[_aWindow screen] visibleFrame].size.height
- [_aWindow frame].size.height);
[_aWindow setFrameOrigin: origin];
[_bWindow setFrameOrigin: origin];
}
}
/**
@ -543,7 +607,7 @@ static NSNotificationCenter *nc;
else
[_notifications addObject: inserted];
// Set this after the insert notification has been send.
// Set this after the insert notification has been sent.
[newItem setMenu: self];
}
@ -1407,9 +1471,9 @@ static NSNotificationCenter *nc;
_superMenu->_attachedMenu = self;
}
else if ([_aWindow frame].origin.y <= 0
&& _popUpButtonCell == nil) // get geometry only if not set
&& _popUpButtonCell == nil) // get geometry only if not set
{
[self setGeometry];
[self _setGeometry];
}
NSDebugLLog (@"NSMenu",
@ -1472,51 +1536,6 @@ static NSNotificationCenter *nc;
[_bWindow orderFront: self];
}
- (void) setGeometry
{
NSPoint origin;
if (_horizontal == YES)
{
origin = NSMakePoint (0, [[NSScreen mainScreen] frame].size.height
- [_aWindow frame].size.height);
[_aWindow setFrameOrigin: origin];
[_bWindow setFrameOrigin: origin];
}
else
{
NSString *key;
if (nil != (key = [self _locationKey]))
{
NSUserDefaults *defaults;
NSDictionary *menuLocations;
NSString *location;
defaults = [NSUserDefaults standardUserDefaults];
menuLocations = [defaults objectForKey: NSMenuLocationsKey];
if ([menuLocations isKindOfClass: [NSDictionary class]])
location = [menuLocations objectForKey: key];
else
location = nil;
if (location && [location isKindOfClass: [NSString class]])
{
[_aWindow setFrameFromString: location];
[_bWindow setFrameFromString: location];
return;
}
}
origin = NSMakePoint(0, [[_aWindow screen] visibleFrame].size.height
- [_aWindow frame].size.height);
[_aWindow setFrameOrigin: origin];
[_bWindow setFrameOrigin: origin];
}
}
- (void) close
{
NSMenu *sub = [self attachedMenu];
@ -1591,22 +1610,40 @@ static NSNotificationCenter *nc;
{
if (isMain)
{
/*
* If necessary,. rebuild menu for macintosh (horizontal) style
*/
if (NSInterfaceStyleForKey(@"NSMenuInterfaceStyle", nil)
== NSMacintoshInterfaceStyle)
{
NSMenuView *rep = [[NSMenuView alloc] initWithFrame: NSZeroRect];
NSMenuView *oldRep;
NSInterfaceStyle oldStyle;
NSInterfaceStyle newStyle;
[rep setHorizontal: YES];
[self setMenuRepresentation: rep];
oldRep = [self menuRepresentation];
oldStyle = [oldRep interfaceStyle];
newStyle = NSInterfaceStyleForKey(@"NSMenuInterfaceStyle", nil);
/*
* If necessary, rebuild menu for (different) style
*/
if (oldStyle != newStyle)
{
NSMenuView *newRep;
newRep = [[NSMenuView alloc] initWithFrame: NSZeroRect];
if (newStyle == NSMacintoshInterfaceStyle)
{
[newRep setHorizontal: YES];
}
else
{
[newRep setHorizontal: NO];
}
[newRep setInterfaceStyle: newStyle];
[self setMenuRepresentation: newRep];
[self _organizeMenu];
RELEASE(rep);
RELEASE(newRep);
}
[[self window] setTitle: [[NSProcessInfo processInfo] processName]];
[[self window] setLevel: NSMainMenuWindowLevel];
[self setGeometry];
[self _setGeometry];
[self sizeToFit];
if ([NSApp isActive])
{

View file

@ -74,11 +74,11 @@ static NSMapTable *viewInfo = 0;
@class NSButton;
@interface NSMenuView (Private)
- (BOOL) _rootIsHorizontal;
- (BOOL) _rootIsHorizontal: (BOOL*)isAppMenu;
@end
@implementation NSMenuView (Private)
- (BOOL) _rootIsHorizontal
- (BOOL) _rootIsHorizontal: (BOOL*)isAppMenu
{
NSMenu *m = _attachedMenu;
@ -87,6 +87,17 @@ static NSMapTable *viewInfo = 0;
{
m = [m supermenu];
}
if (isAppMenu != 0)
{
if (m == [NSApp mainMenu])
{
*isAppMenu = YES;
}
else
{
*isAppMenu = NO;
}
}
return [[m menuRepresentation] isHorizontal];
}
@end
@ -220,6 +231,8 @@ _addLeftBorderOffsetToRect(NSRect aRect)
- (void) setMenu: (NSMenu*)menu
{
NSNotificationCenter *theCenter = [NSNotificationCenter defaultCenter];
unsigned count;
unsigned i;
if (_attachedMenu != nil)
{
@ -248,30 +261,25 @@ _addLeftBorderOffsetToRect(NSRect aRect)
selector: @selector(itemRemoved:)
name: NSMenuDidRemoveItemNotification
object: _attachedMenu];
// Force menu view's layout to be recalculated.
[self setNeedsSizing: YES];
[self update];
}
if (_horizontal)
count = [[[self menu] itemArray] count];
for (i = 0; i < count; i++)
{
unsigned count = [[[self menu] itemArray] count];
unsigned i;
NSNumber *n = [NSNumber numberWithInt: i];
NSDictionary *d;
for (i = 0; i < count; i++)
{
NSNumber *n = [NSNumber numberWithInt: i];
NSDictionary *d;
d = [NSDictionary dictionaryWithObject: n forKey: @"NSMenuItemIndex"];
d = [NSDictionary dictionaryWithObject: n forKey: @"NSMenuItemIndex"];
[self itemAdded: [NSNotification
notificationWithName: NSMenuDidAddItemNotification
object: self
userInfo: d]];
}
[self itemAdded: [NSNotification
notificationWithName: NSMenuDidAddItemNotification
object: self
userInfo: d]];
}
// Force menu view's layout to be recalculated.
[self setNeedsSizing: YES];
[self update];
}
- (NSMenu*) menu
@ -559,43 +567,55 @@ _addLeftBorderOffsetToRect(NSRect aRect)
*/
- (void) update
{
if (NSInterfaceStyleForKey(@"NSMenuInterfaceStyle", self)
== NSMacintoshInterfaceStyle)
BOOL needTitleView;
BOOL rootIsAppMenu;
NSDebugLLog (@"NSMenu", @"update called on menu view");
/*
* Ensure that a title view exists only if needed.
*/
if (_attachedMenu == nil)
{
[self sizeToFit];
needTitleView = NO;
}
else if ([self _rootIsHorizontal: &rootIsAppMenu] == YES)
{
needTitleView = NO;
}
else if (rootIsAppMenu == YES)
{
needTitleView = YES;
}
else
{
NSDebugLLog (@"NSMenu", @"update called on menu view");
needTitleView = ([_attachedMenu _ownedByPopUp] == YES) ? NO : YES;
}
/*
* Ensure that a title view exists only if needed.
*/
if (![_attachedMenu _ownedByPopUp] && !_titleView)
if (needTitleView == YES && _titleView == nil)
{
_titleView = [[GSTitleView alloc] initWithOwner: _attachedMenu];
[self addSubview: _titleView];
RELEASE(_titleView);
}
if (needTitleView == NO && _titleView != nil)
{
[_titleView removeFromSuperview];
_titleView = nil;
}
[self sizeToFit];
if ([_attachedMenu _ownedByPopUp] == NO)
{
if ([_attachedMenu isTornOff] && ![_attachedMenu isTransient])
{
_titleView = [[GSTitleView alloc] initWithOwner:_attachedMenu];
[self addSubview: _titleView];
RELEASE(_titleView);
[_titleView
addCloseButtonWithAction: @selector(_performMenuClose:)];
}
else if ([_attachedMenu _ownedByPopUp] && _titleView)
else
{
[_titleView removeFromSuperview];
_titleView = nil;
}
[self sizeToFit];
if ([_attachedMenu _ownedByPopUp] == NO)
{
if ([_attachedMenu isTornOff] && ![_attachedMenu isTransient])
{
[_titleView
addCloseButtonWithAction: @selector(_performMenuClose:)];
}
else
{
[_titleView removeCloseButton];
}
[_titleView removeCloseButton];
}
}
}
@ -809,9 +829,8 @@ _addLeftBorderOffsetToRect(NSRect aRect)
+ menuBarHeight)];
[_titleView setFrame: NSMakeRect (0, howMany * _cellSize.height,
NSWidth (_bounds), menuBarHeight)];
_needsSizing = NO;
}
_needsSizing = NO;
}
- (float) stateImageOffset
@ -969,15 +988,15 @@ _addLeftBorderOffsetToRect(NSRect aRect)
subOrigin.y - NSHeight(submenuFrame) - 3 +
2*[NSMenuView menuBarHeight]);
}
else if ([self _rootIsHorizontal] == YES)
else if ([self _rootIsHorizontal: 0] == YES)
{
NSRect aRect = [self rectOfItemAtIndex:
[_attachedMenu indexOfItemWithSubmenu: aSubmenu]];
NSPoint subOrigin = [_window convertBaseToScreen:
NSMakePoint(aRect.origin.x, aRect.origin.y)];
// FIXME ... why is the offset +1 needed below?
return NSMakePoint (NSMaxX(frame),
subOrigin.y - NSHeight(submenuFrame) + aRect.size.height);
subOrigin.y - NSHeight(submenuFrame) + aRect.size.height + 1);
}
else
{
@ -1042,7 +1061,8 @@ _addLeftBorderOffsetToRect(NSRect aRect)
// Compute position for popups, if needed
if (selectedItemIndex != -1)
{
screenFrame.origin.y += screenRect.size.height * selectedItemIndex;
screenFrame.origin.y
+= screenRect.size.height * selectedItemIndex;
}
}
else

View file

@ -1534,6 +1534,10 @@ many times.
if (place == NSWindowOut)
{
if (_windowNum == 0)
{
return; /* This deferred window was never ordered in. */
}
_f.visible = NO;
/*
* Don't keep trying to update the window while it is ordered out