Toolbar improvements, include validation, border, memory leaks, selected item

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@19390 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Quentin Mathe 2004-05-23 18:22:45 +00:00
parent 3963927f9c
commit 031f8b56bc
9 changed files with 778 additions and 111 deletions

View file

@ -1,10 +1,25 @@
2004-05-23 Quentin Mathe <qmathe@lub-internet.fr>
* Source/GSToolbarView.m:
* Headers/GNUstepGUI/GSToolbarView.h:
* Source/GSToolbar.m:
* Headers/GNUstepGUI/GSToolbar.h:
* Source/NSToolbar.m:
* Headers/AppKit/NSToolbar.h:
* Source/NSToolbarItem.m:
* Headers/AppKit/NSToolbarItem.h:
* Source/NSWindow+Toolbar.m:
Last part in the validation implementation, border taken in account by the
layout process, lot of memory leaks fixed, selected item possibility
implemented and other minor improvements.
2004-05-18 Quentin Mathe <qmathe@club-internet.fr>
* Source/GSToolbarView: Added color customization (default background
* Source/GSToolbarView.m: Added color customization (default background
color is now no color), part of the toolbar validation mechanism
and other minor changes.
* Headers/GNUstepGUI/GSToolbarView.h: Same.
* Source/NSToolbarItem: Added part of the toolbar validation mechanism,
* Source/NSToolbarItem.m: Added part of the toolbar validation mechanism,
new menuFormRepresentation implementation to have the menu item titles
used as label with the text display mode and other minor changes.

View file

@ -76,6 +76,7 @@ APPKIT_EXPORT NSString *NSToolbarWillAddItemNotification;
NSToolbarDisplayMode _displayMode;
NSToolbarSizeMode _sizeMode;
NSString *_identifier;
NSString *_selectedItemIdentifier;
NSMutableArray *_items;
GSToolbarView *_toolbarView;
NSWindow *_window;
@ -109,6 +110,7 @@ APPKIT_EXPORT NSString *NSToolbarWillAddItemNotification;
- (void) setConfigurationFromDictionary: (NSDictionary*)configDict;
- (void) setDelegate: (id)delegate;
- (void) setSelectedItemIdentifier: (NSString *) identifier;
- (void) setUsesStandardBackgroundColor: (BOOL)standard;
- (NSToolbarSizeMode) sizeMode;
@end /* interface of NSToolbar */
@ -138,7 +140,7 @@ willBeInsertedIntoToolbar: (BOOL)flag;
// Extensions
@interface NSArray (ObjectsWithValueForKey)
- (NSArray *) objectsWithValue: (NSString *)value forKey: (NSString *)key;
- (NSArray *) objectsWithValue: (id)value forKey: (NSString *)key;
@end
#endif /* _GNUstep_H_NSToolbar */

View file

@ -52,9 +52,9 @@ enum {
};
typedef enum {
_ToolbarViewDefaultHeight = 61,
_ToolbarViewRegularHeight = 61,
_ToolbarViewSmallHeight = 51
_ToolbarViewDefaultHeight = 62,
_ToolbarViewRegularHeight = 62,
_ToolbarViewSmallHeight = 52
} _ToolbarViewHeight;
typedef enum {
@ -88,6 +88,7 @@ static const int _ClippedItemsViewWidth = 28;
unsigned int _borderMask;
NSToolbarDisplayMode _displayMode;
NSToolbarSizeMode _sizeMode;
NSRect _rectAvailable;
unsigned int _heightFromLayout;
}
@ -105,12 +106,9 @@ static const int _ClippedItemsViewWidth = 28;
@end
// Toolbar related NSColor methods
@interface NSColor (Extensions)
+ (NSColor *) toolbarBackgroundColor;
+ (NSColor *) toolbarBorderColor;
@end
#endif

View file

@ -72,6 +72,7 @@ APPKIT_EXPORT NSString *NSToolbarPrintItemIdentifier;
id _view;
NSView *_backView;
BOOL _modified;
BOOL _selectable;
// size
NSSize _maxSize;
@ -134,8 +135,9 @@ APPKIT_EXPORT NSString *NSToolbarPrintItemIdentifier;
@end /* interface of NSToolbarItem */
@protocol NSToolbarItemValidation
- (BOOL) validateToolbarItem: (NSToolbarItem *)theItem;
// Informal protocol for the toolbar validation
@interface NSObject (NSToolbarItemValidation)
- (BOOL) validateToolbarItem: (NSToolbarItem *)toolbarItem;
@end
#endif /* _GNUstep_H_NSToolbarItem */

View file

@ -34,6 +34,7 @@
#include <Foundation/NSException.h>
#include <Foundation/NSNotification.h>
#include <Foundation/NSUserDefaults.h>
#include "AppKit/NSApplication.h"
#include "AppKit/NSToolbarItem.h"
#include "AppKit/NSView.h"
#include "AppKit/NSClipView.h"
@ -44,6 +45,7 @@
#include "AppKit/NSMenu.h"
#include "AppKit/NSEvent.h"
#include "AppKit/NSWindow.h"
#include "AppKit/NSWindow+Toolbar.h"
#include "GNUstepGUI/GSToolbarView.h"
#include "GNUstepGUI/GSToolbar.h"
@ -53,12 +55,14 @@ static const int current_version = 1;
static NSMutableArray *toolbars;
// Validation stuff
static const unsigned int ValidationInterval = 10;
static id validationCenter;
// Extensions
@implementation NSArray (ObjectsWithValueForKey)
- (NSArray *) objectsWithValue: (NSString *)value forKey: (NSString *)key
- (NSArray *) objectsWithValue: (id)value forKey: (NSString *)key
{
NSMutableArray *result = [[NSMutableArray alloc] init];
NSArray *keys = [self valueForKey: key];
@ -71,7 +75,7 @@ static NSMutableArray *toolbars;
for (i = 0; i < n; i++)
{
if ([[keys objectAtIndex: i] isEqualToString: value])
if ([[keys objectAtIndex: i] isEqual: value])
{
[result addObject: [self objectAtIndex: i]];
}
@ -80,10 +84,361 @@ static NSMutableArray *toolbars;
if ([result count] == 0)
return nil;
AUTORELEASE(result);
return result;
}
@end
// Validation support
@interface NSView (ToolbarValidation)
- (void) mouseDown: (NSEvent *)event;
@end
@interface GSValidationObject : NSObject
{
NSMutableArray *_observers;
NSView *_view;
}
- (id) initWithView: (NSView *)view;
- (NSArray *) observers;
- (void) addObserver: (id)observer;
- (void) removeObserver: (id)observer;
- (void) validate;
- (NSView *) view;
@end
@interface GSValidationManager : NSObject
{
NSWindow *_window;
NSView *_trackingRectView;
NSTrackingRectTag _trackingRect;
NSTimer *_validationTimer;
BOOL _inside;
}
- (id) initWithWindow: (NSWindow *)window;
- (void) validate;
- (void) invalidate;
// Tracking rect methods
- (void) mouseEntered: (NSEvent *)event;
- (void) mouseExited: (NSEvent *)event;
@end
@interface GSValidationCenter : NSObject
{
NSMutableArray *_validationManagers;
NSMutableArray *_validationObjects;
NSWindow *_prevWindow;
}
+ (GSValidationCenter *) sharedValidationCenter;
- (id) init;
- (void) viewWillMove: (NSNotification *)notification;
- (void) viewDidMove: (NSNotification *)notification;
- (void) unregisterValidationObject: (GSValidationObject *)validationObject;
- (GSValidationObject *) validationObjectWithView: (NSView *)view;
// Private methods
- (GSValidationManager *) _validationManagerWithWindow: (NSWindow *)window;
- (NSArray *) _validationObjectsWithWindow: (NSWindow *)window;
@end
// Validation mechanism
@implementation NSView (ToolbarValidation)
- (void) mouseDown: (NSEvent *)event
{
GSValidationManager *validationManager =
[[GSValidationCenter sharedValidationCenter] _validationManagerWithWindow: [self window]];
[validationManager performSelector: @selector(validate) withObject: nil afterDelay: 0.1];
}
@end
@implementation GSValidationObject
- (id) initWithView: (NSView *)view
{
if ((self = [super init]) != nil)
{
ASSIGN(_view, view);
_observers = [[NSMutableArray alloc] init];
}
return self;
}
- (void) dealloc
{
RELEASE(_view);
RELEASE(_observers);
[super dealloc];
}
- (NSArray *) observers
{
return _observers;
}
- (void) addObserver: (id)observer
{
[_observers addObject: observer];
}
- (void) removeObserver: (id)observer
{
if ([_observers containsObject: observer])
[_observers removeObject: observer];
}
- (void) validate
{
if ([_view superview] != nil)
{
[_observers makeObjectsPerformSelector: @selector(_validate)];
}
}
- (NSView *) view
{
return _view;
}
@end
@interface NSWindow (GNUstepPrivate)
- (NSView *) _windowView;
@end
@implementation GSValidationManager
- (id) initWithWindow: (NSWindow *)window {
if ((self = [super init]) != nil)
{;
NSView *vw = [window _windowView];
ASSIGN(_window, window);
[nc addObserver: self selector: @selector(windowWillClose:)
name: NSWindowWillCloseNotification object: _window];
ASSIGN(_trackingRectView, vw);
_trackingRect = [_trackingRectView addTrackingRect: [_trackingRectView bounds]
owner: self
userData: nil
assumeInside: NO];
}
return self;
}
- (void) invalidate
{
[_trackingRectView removeTrackingRect: _trackingRect]; // tracking rect retains us, that is normal ?
[_validationTimer invalidate]; // timer idem
}
- (void) dealloc
{
RELEASE(_trackingRectView);
RELEASE(_window);
[super dealloc];
}
- (void) windowWillClose: (NSNotification *)notification
{
GSValidationCenter *vc = [GSValidationCenter sharedValidationCenter];
NSEnumerator *e;
id vo;
[nc removeObserver: self];
e = [[vc _validationObjectsWithWindow: _window] objectEnumerator];
while ((vo = [e nextObject]) != nil)
{
[vc unregisterValidationObject: vo];
}
}
- (void) mouseEntered: (NSEvent *)event
{
_inside = YES;
if (_validationTimer == nil || ![_validationTimer isValid])
{
_validationTimer = [NSTimer timerWithTimeInterval: ValidationInterval
target: self
selector: @selector(validate)
userInfo: nil
repeats: YES];
[[NSRunLoop currentRunLoop] addTimer: _validationTimer forMode: NSDefaultRunLoopMode];
[self validate];
}
}
- (void) mouseExited: (NSEvent *)event
{
_inside = NO;
[_validationTimer invalidate];
_validationTimer = nil;
}
- (void) validate
{
[[[GSValidationCenter sharedValidationCenter]
_validationObjectsWithWindow: _window] makeObjectsPerformSelector: @selector(validate)];
}
@end
@implementation GSValidationCenter
+ (GSValidationCenter *) sharedValidationCenter
{
if (validationCenter == nil)
validationCenter = [[GSValidationCenter alloc] init];
return validationCenter;
}
- (id) init
{
if ((self = [super init]) != nil)
{
_validationManagers = [[NSMutableArray alloc] init];
_validationObjects = [[NSMutableArray alloc] init];
[nc addObserver: self selector: @selector(viewWillMove:) name: @"GSViewWillMoveToWindow" object: nil];
[nc addObserver: self selector: @selector(viewDidMove:) name: @"GSViewDidMoveToWindow" object: nil];
}
return self;
}
- (void) viewWillMove: (NSNotification *)notification
{
_prevWindow = [[notification object] window];
RETAIN(_prevWindow);
}
- (void) viewDidMove: (NSNotification *)notification
{
NSWindow *window = [[notification object] window];
GSValidationManager *validationManager = [self _validationManagerWithWindow : _prevWindow];
if (validationManager != nil && [[self _validationObjectsWithWindow: _prevWindow] count] == 0)
{
[validationManager invalidate];
[_validationManagers removeObject: validationManager];
}
if (window == nil)
return;
validationManager = [self _validationManagerWithWindow: window];
if (validationManager == nil)
{
validationManager = [[GSValidationManager alloc] initWithWindow: window];
[_validationManagers addObject: validationManager];
RELEASE(validationManager);
}
RELEASE(_prevWindow);
}
/* validationObjectWithView: opposite method
* Remove the object in the validation objects list.
* Release the validation manager associated to the window (related to the validation object and its
* view) in the case there are no other validation objects related to this window.
*/
- (void) unregisterValidationObject: (GSValidationObject *)validationObject
{
int index;
if ((index = [_validationObjects indexOfObject: validationObject]) != NSNotFound)
{
NSWindow *window = [[validationObject view] window];
[_validationObjects removeObjectAtIndex: index];
if ([[self _validationObjectsWithWindow: window] count] == 0)
{
GSValidationManager *validationManager = [self _validationManagerWithWindow: window];
[validationManager invalidate];
[_validationManagers removeObject: validationManager];
}
}
}
/* Return the validation object associated with the parameter view.
* If there is no such validation object, create it by using view and then check that an associated
* validation manager (bound to the window which the view depends on) exists.
* If there is no such validation manager, create it.
*/
- (GSValidationObject *) validationObjectWithView: (NSView *)view
{
GSValidationObject *validationObject;
GSValidationManager *validationManager;
NSWindow *window = [view window];
if (view == nil)
{
NSLog(@"Validation object cannot be created because the view is nil");
return nil;
}
validationObject = [[_validationObjects objectsWithValue: view forKey: @"_view"] objectAtIndex: 0];
if (validationObject == nil)
{
validationObject = [[GSValidationObject alloc] initWithView: view];
[_validationObjects addObject: validationObject];
if (window == nil)
return nil;
validationManager = [self _validationManagerWithWindow: window];
if (validationManager == nil)
{
validationManager = [[GSValidationManager alloc] initWithWindow: window];
[_validationManagers addObject: validationManager];
RELEASE(validationManager);
}
}
return validationObject;
}
// Private methods
- (GSValidationManager *) _validationManagerWithWindow: (NSWindow *)window
{
GSValidationManager *validationManager =
[[_validationManagers objectsWithValue: window forKey: @"_window"] objectAtIndex: 0];
return validationManager;
}
- (NSArray *) _validationObjectsWithWindow: (NSWindow *)window
{
NSEnumerator *e = [_validationObjects objectEnumerator];
id validationObject;
NSMutableArray *array = [NSMutableArray array];
while ((validationObject = [e nextObject]) != nil)
{
if ([[validationObject view] window] == window)
[array addObject: validationObject];
}
return array;
}
@end
// ---
@interface GSToolbar (GNUstepPrivate)
@ -112,6 +467,7 @@ static NSMutableArray *toolbars;
- (void) _loadConfig;
- (NSToolbarItem *) _toolbarItemForIdentifier: (NSString *)itemIdent;
- (GSToolbar *) _toolbarModel;
- (void) _validate;
// Accessors
- (void) _setToolbarView: (GSToolbarView *)toolbarView;
@ -121,14 +477,21 @@ static NSMutableArray *toolbars;
@end
@interface NSToolbarItem (GNUstepPrivate)
- (BOOL) _selectable;
- (void) _setSelectable: (BOOL)selectable;
- (BOOL) _selected;
- (void) _setSelected: (BOOL)selected;
- (void) _setToolbar: (GSToolbar *)toolbar;
@end
@interface GSToolbarView (GNUstepPrivate)
- (void) _reload;
// Accessors
- (NSArray *) _visibleBackViews;
- (BOOL) _willBeVisible;
- (void) _setWillBeVisible: (BOOL)willBeVisible;
- (void) _setUsesStandardBackgroundColor: (BOOL)standard;
@end
// ---
@ -195,8 +558,6 @@ static NSMutableArray *toolbars;
}
//[self _loadConfig];
[self _setDelegate: [toolbarModel delegate] broadcast: NO];
}
else
{
@ -220,8 +581,11 @@ static NSMutableArray *toolbars;
- (void) dealloc
{
DESTROY (_identifier);
DESTROY (_configurationDictionary);
// use DESTROY ?
RELEASE(_identifier);
RELEASE(_selectedItemIdentifier);
RELEASE(_configurationDictionary);
RELEASE(_items);
if (_delegate != nil)
{
@ -311,7 +675,7 @@ static NSMutableArray *toolbars;
- (NSString *) selectedItemIdentifier
{
return nil;
return _selectedItemIdentifier;
}
- (NSArray *) visibleItems
@ -355,7 +719,33 @@ static NSMutableArray *toolbars;
- (void) setSelectedItemIdentifier: (NSString *)itemIdentifier
{
// do something here
NSArray *selectedItems;
NSArray *itemsToSelect;
NSEnumerator *e;
NSToolbarItem *item;
NSArray *selectableIdentifiers;
// First, we have to deselect the previous selected toolbar items
selectedItems = [[self items] objectsWithValue: [self selectedItemIdentifier]
forKey: @"_itemIdentifier"];
e = [selectedItems objectEnumerator];
while ((item = [e nextObject]) != nil)
{
[item _setSelected: NO];
}
ASSIGN(_selectedItemIdentifier, itemIdentifier);
if ([_delegate respondsToSelector: @selector(toolbarSelectableItemIdentifiers:)])
selectableIdentifiers = [_delegate toolbarSelectableItemIdentifiers: self];
itemsToSelect = [_items objectsWithValue: _selectedItemIdentifier forKey: @"_itemIdentifier"];
e = [itemsToSelect objectEnumerator];
while ((item = [e nextObject]) != nil)
{
if ([selectableIdentifiers containsObject: [item itemIdentifier]] && ![item _selected])
[item _setSelected: YES];
}
}
- (NSToolbarSizeMode) sizeMode
@ -363,6 +753,11 @@ static NSMutableArray *toolbars;
return _sizeMode;
}
- (void) setUsesStandardBackgroundColor: (BOOL)standard
{
[_toolbarView _setUsesStandardBackgroundColor: standard];
}
// Private methods
- (void) _build
@ -385,9 +780,7 @@ static NSMutableArray *toolbars;
toolbarModel = [self _toolbarModel];
if (toolbarModel != nil
&& toolbarModel != self
&& [toolbarModel delegate] == _delegate)
if (toolbarModel != nil && [toolbarModel delegate] == _delegate)
{
wantedItemIdentifiers =
[[toolbarModel items] valueForKey: @"_itemIdentifier"];
@ -411,7 +804,7 @@ static NSMutableArray *toolbars;
- (void) _loadConfig
{
if(_identifier != nil)
if (_identifier != nil)
{
NSUserDefaults *defaults;
NSString *tableKey;
@ -441,6 +834,9 @@ static NSMutableArray *toolbars;
if (linked != nil && [linked count] > 0)
{
toolbar = [linked objectAtIndex: 0];
// toolbar model class must be identical to self class :
// an NSToolbar instance cannot use a GSToolbar instance as a model
if ([toolbar isMemberOfClass: [self class]] && toolbar != self)
return toolbar;
}
@ -471,7 +867,7 @@ static NSMutableArray *toolbars;
*
* The methods below handles the toolbar edition and broacasts each associated
* event to the other toolbars with identical identifiers.
*
* Warning : broadcast process only happens between instances based on the same class.
*/
#define TRANSMIT(signature) \
@ -503,9 +899,17 @@ static NSMutableArray *toolbars;
if (item != nil)
{
[nc postNotificationName: NSToolbarWillAddItemNotification
NSArray *selectableItems;
if ([_delegate respondsToSelector: @selector(toolbarSelectableItemIdentifiers:)])
{
selectableItems = [_delegate toolbarSelectableItemIdentifiers: self];
if ([selectableItems containsObject: itemIdentifier])
[item _setSelectable: YES];
}
[nc postNotificationName: NSToolbarWillAddItemNotification
object: self];
[item _setToolbar: self];
[_items insertObject: item atIndex: index];
@ -574,8 +978,16 @@ static NSMutableArray *toolbars;
- (void) _setDelegate: (id)delegate broadcast: (BOOL)broadcast
{
if (_delegate == delegate)
if (_delegate == delegate
|| (broadcast == NO && [_delegate isMemberOfClass: [delegate class]]))
return;
// We don't reload instances which received this message and already have a
// delegate based on a class identical to the parameter delegate, it permits
// to use only one nib owner class as a toolbar delegate even if a new instance
// of the nib owner are created with each new window (see MiniController.m in
// the toolbar example application).
#define CHECK_REQUIRED_METHOD(selector_name) \
if (![delegate respondsToSelector: @selector(selector_name)]) \
@ -616,7 +1028,26 @@ static NSMutableArray *toolbars;
- (void) _setToolbarView: (GSToolbarView *)toolbarView
{
GSValidationObject *validationObject = nil;
GSValidationCenter *vc = [GSValidationCenter sharedValidationCenter];
GSToolbar *toolbarModel = [self _toolbarModel];
validationObject = [vc validationObjectWithView: _toolbarView];
if (validationObject != nil)
{
[validationObject removeObserver: self];
if ([[validationObject observers] count] == 0)
[vc unregisterValidationObject: validationObject];
}
ASSIGN(_toolbarView, toolbarView);
validationObject = [vc validationObjectWithView: _toolbarView];
if (validationObject != nil)
[validationObject addObserver: self];
if (_delegate == nil)
[self _setDelegate: [toolbarModel delegate] broadcast: NO];
}
- (GSToolbarView *) _toolbarView
@ -624,4 +1055,9 @@ static NSMutableArray *toolbars;
return _toolbarView;
}
- (void) _validate
{
[self validateVisibleItems];
}
@end

View file

@ -47,7 +47,7 @@
// internal
static const int current_version = 1;
static NSColorList *SystemExtensionsColors;
static NSColor *ClassicBackgroundColor;
static NSColor *StandardBackgroundColor;
static NSColor *BackgroundColor;
static NSColor *BorderColor;
@ -103,7 +103,6 @@ static void initSystemExtensionsColors(void)
continue;
color = [colors objectForKey: colorKey];
[SystemExtensionsColors setColor: color forKey: colorKey];
changed = YES;
@ -131,16 +130,20 @@ static void initSystemExtensionsColors(void)
*/
@interface GSToolbar (GNUstepPrivate)
- (void) _build;
// Accessors
- (void) _setToolbarView: (GSToolbarView *)toolbarView;
- (GSToolbarView *) _toolbarView;
@end
@interface NSToolbarItem (GNUstepPrivate)
- (void) _layout;
// Accessors
- (NSView *) _backView;
- (NSMenuItem *) _defaultMenuFormRepresentation;
- (BOOL) _isModified;
- (BOOL) _isFlexibleSpace;
- (void) _layout;
@end
@interface GSToolbarView (GNUstepPrivate)
@ -153,6 +156,8 @@ static void initSystemExtensionsColors(void)
// Accessors
- (float) _heightFromLayout;
- (NSArray *) _visibleBackViews;
- (void) _setSizeMode: (NSToolbarSizeMode)sizeMode;
- (NSToolbarSizeMode) _sizeMode;
- (void) _setWillBeVisible: (BOOL)willBeVisible;
- (BOOL) _willBeVisible;
@end
@ -180,7 +185,7 @@ static void initSystemExtensionsColors(void)
NSImage *image = [NSImage imageNamed: @"common_ToolbarClippedItemsMark"];
if ((self = [super initWithFrame: NSMakeRect(0, 0, _ClippedItemsViewWidth,
_ItemBackViewDefaultHeight)]) != nil)
100)]) != nil) // the correct height will be set by the layout method
{
[self setBordered: NO];
[[self cell] setHighlightsBy: NSChangeGrayCellMask
@ -195,13 +200,19 @@ static void initSystemExtensionsColors(void)
return nil;
}
- (void) dealloc
{
RELEASE(_toolbar);
[super dealloc];
}
- (void) layout {
[self setFrameSize: NSMakeSize([self frame].size.width,
[[_toolbar _toolbarView] _heightFromLayout])];
[[_toolbar _toolbarView] _heightFromLayout])];
}
- (void) mouseDown: (NSEvent *)event {
NSMenu *clippedItemsMenu = [self menuForEvent:event];
NSMenu *clippedItemsMenu = [self menuForEvent: event];
[super highlight: YES];
@ -224,9 +235,9 @@ static void initSystemExtensionsColors(void)
- (NSMenu *) returnMenu
{
// this method cannot be called menu otherwise it would
// this method cannot be called "menu" otherwise it would
// override NSResponder method with the same name
NSMenu *menu = [[NSMenu alloc] initWithTitle:@""];
NSMenu *menu = [[NSMenu alloc] initWithTitle: @""];
NSEnumerator *e;
id item;
NSArray *visibleItems;
@ -271,8 +282,10 @@ static void initSystemExtensionsColors(void)
return;
initSystemExtensionsColors();
ClassicBackgroundColor =
StandardBackgroundColor =
RETAIN([NSColor colorWithCalibratedRed: 0.8 green: 0.8 blue: 0.8 alpha: 1.0]);
// Never released, but that's not a problem because the variable is static and then will be
// deallocated with the class when the application quits.
}
- (id) initWithFrame: (NSRect)frame
@ -286,7 +299,7 @@ static void initSystemExtensionsColors(void)
displayMode: (NSToolbarDisplayMode)displayMode
sizeMode: (NSToolbarSizeMode)sizeMode
{
if((self = [super initWithFrame: frame]) != nil)
if ((self = [super initWithFrame: frame]) != nil)
{
float toolbarViewHeight;
@ -309,31 +322,31 @@ static void initSystemExtensionsColors(void)
toolbarViewHeight = 0;
}
[self setFrame: NSMakeRect(
frame.origin.x,
frame.origin.y,
frame.size.width,
toolbarViewHeight)];
[self setFrame: NSMakeRect(frame.origin.x,
frame.origin.y,
frame.size.width,
toolbarViewHeight)];
// ---
_clipView = [[NSClipView alloc] initWithFrame:
NSMakeRect(0, 1, frame.size.width, toolbarViewHeight - 1)];
_clipView = [[NSClipView alloc] initWithFrame: NSMakeRect(0, 0, 100, 100)];
[_clipView setAutoresizingMask: (NSViewWidthSizable |
NSViewHeightSizable)];
[self setBorderMask: GSToolbarViewTopBorder | GSToolbarViewBottomBorder
| GSToolbarViewRightBorder | GSToolbarViewLeftBorder]; // Adjust the clip view frame
[self addSubview: _clipView];
_clippedItemsMark = [[GSToolbarClippedItemsButton alloc] init];
_borderMask = GSToolbarViewTopBorder | GSToolbarViewBottomBorder
| GSToolbarViewRightBorder | GSToolbarViewLeftBorder;
BackgroundColor = [SystemExtensionsColors colorWithKey: @"toolbarBackgroundColor"];
BorderColor = [SystemExtensionsColors colorWithKey: @"toolbarBorderColor"];
RETAIN(BackgroundColor);
RETAIN(BorderColor);
// Never released, but that's not a problem because the variables are static and then will be
// deallocated with the class when the application quits.
// ---
@ -377,7 +390,7 @@ static void initSystemExtensionsColors(void)
{
[NSBezierPath strokeLineFromPoint: NSMakePoint(0, viewFrame.size.height - 0.5)
toPoint: NSMakePoint(viewFrame.size.width,
viewFrame.size.height - 0.5)];
viewFrame.size.height - 0.5)];
}
if (_borderMask & GSToolbarViewLeftBorder)
{
@ -388,11 +401,10 @@ static void initSystemExtensionsColors(void)
{
[NSBezierPath strokeLineFromPoint: NSMakePoint(viewFrame.size.width - 0.5,0)
toPoint: NSMakePoint(viewFrame.size.width - 0.5,
viewFrame.size.height)];
viewFrame.size.height)];
}
[super drawRect: aRect];
}
- (BOOL) isOpaque
@ -415,16 +427,6 @@ static void initSystemExtensionsColors(void)
[self _reload];
}
- (void) viewDidMoveToSuperview
{
// NSView method called when a view is moved not to a superview
if (_toolbar != nil)
{
//[self _reload];
}
}
- (void) viewDidMoveToWindow
{
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
@ -433,11 +435,9 @@ static void initSystemExtensionsColors(void)
// variable _window)
[super viewDidMoveToWindow];
[nc removeObserver: self name: NSWindowDidResizeNotification object: _window];
[nc removeObserver: self name: NSWindowDidResizeNotification object: nil];
[nc addObserver: self selector: @selector(windowDidResize:)
name: NSWindowDidResizeNotification object: nil];
//[self viewDidMoveToSuperview];
name: NSWindowDidResizeNotification object: _window];
[nc postNotificationName: @"GSViewDidMoveToWindow" object: self];
}
@ -465,7 +465,51 @@ static void initSystemExtensionsColors(void)
- (void) setBorderMask: (unsigned int)borderMask
{
NSRect toolbarViewFrame = [self frame];
NSRect rect = NSMakeRect(0, 0, toolbarViewFrame.size.width, 100);
_borderMask = borderMask;
// Take in account the size mode
switch (_sizeMode)
{
case NSToolbarSizeModeDefault:
rect.size.height = _ToolbarViewDefaultHeight;
break;
case NSToolbarSizeModeRegular:
rect.size.height = _ToolbarViewRegularHeight;
break;
case NSToolbarSizeModeSmall:
rect.size.height = _ToolbarViewSmallHeight;
break;
default:
; // invalid
}
// Take in account the border
if (_borderMask & GSToolbarViewBottomBorder)
{
rect = NSMakeRect(rect.origin.x, ++rect.origin.y, rect.size.width, --rect.size.height);
}
if (_borderMask & GSToolbarViewTopBorder)
{
rect = NSMakeRect(rect.origin.x, rect.origin.y, rect.size.width, --rect.size.height);
}
if (_borderMask & GSToolbarViewLeftBorder)
{
rect = NSMakeRect(++rect.origin.x, rect.origin.y, --rect.size.width, rect.size.height);
}
if (_borderMask & GSToolbarViewRightBorder)
{
rect = NSMakeRect(rect.origin.x, rect.origin.y, --rect.size.width, rect.size.height);
}
[_clipView setFrame: rect];
}
- (void) setToolbar: (GSToolbar *)toolbar
@ -479,9 +523,9 @@ static void initSystemExtensionsColors(void)
[self _setToolbar: toolbar];
}
- (NSColor *) classicBackgroundColor
- (NSColor *) standardBackgroundColor
{
return ClassicBackgroundColor;
return StandardBackgroundColor;
}
// Private methods
@ -496,8 +540,8 @@ static void initSystemExtensionsColors(void)
// ---
NSArray *subviews = [self subviews];
_heightFromLayout = 100;
_heightFromLayout = 0;
while ((item = [e nextObject]) != nil)
{
itemBackView = [item _backView];
@ -513,12 +557,12 @@ static void initSystemExtensionsColors(void)
itemBackViewFrame = [itemBackView frame];
[itemBackView setFrame: NSMakeRect(x,
itemBackViewFrame.origin.y,
itemBackViewFrame.size.width,
itemBackViewFrame.size.height)];
itemBackViewFrame.origin.y,
itemBackViewFrame.size.width,
itemBackViewFrame.size.height)];
x += [itemBackView frame].size.width;
if (itemBackViewFrame.size.height < _heightFromLayout)
if (itemBackViewFrame.size.height > _heightFromLayout)
_heightFromLayout = itemBackViewFrame.size.height;
}
@ -592,7 +636,7 @@ static void initSystemExtensionsColors(void)
// Resize the clip view
if (lastVisibleBackView != nil)
width = NSMaxX([lastVisibleBackView frame]);
width = NSMaxX([lastVisibleBackView frame]);
[_clipView setFrame: NSMakeRect(clipViewFrame.origin.x,
clipViewFrame.origin.y,
width,
@ -614,14 +658,14 @@ static void initSystemExtensionsColors(void)
}
else if (([_clippedItemsMark superview] != nil)
&& ([visibleBackViews count] >= [backViews count]))
&& ([visibleBackViews count] == [backViews count]))
{
[_clippedItemsMark removeFromSuperview];
[_clipView setFrame: NSMakeRect(clipViewFrame.origin.x,
clipViewFrame.origin.y,
[self frame].size.width,
clipViewFrame.size.height)];
[self frame].size.width,
clipViewFrame.size.height)];
}
}
@ -672,7 +716,7 @@ static void initSystemExtensionsColors(void)
}
if (lengthAvailable < flexibleSpaceItemsNumber)
return;
return;
e = [items objectEnumerator];
while ((item = [e nextObject]) != nil)
@ -703,21 +747,31 @@ static void initSystemExtensionsColors(void)
- (float) _heightFromLayout
{
return _heightFromLayout;
float height = _heightFromLayout;
if (_borderMask & GSToolbarViewBottomBorder)
{
height++;
}
if (_borderMask & GSToolbarViewTopBorder)
{
height++;
}
return height;
}
- (NSArray *) _visibleBackViews
// Will return the visible (not clipped) back views in the toolbar view even when the toolbar is not visible
// May be should be renamed _notClippedBackViews method
- (NSArray *) _visibleBackViews
{
NSArray *items = [_toolbar items];
NSView *backView;
int i, n = [items count];
float backViewsWidth = 0, toolbarWidth = [self frame].size.width;
/*
// _willBeVisible indicates that the toolbar view previously hidden is in
// process to become visible again before the end of current the event loop.
if ([self superview] == nil && ![self _willBeVisible])
return nil;
*/
[_visibleBackViews release];
_visibleBackViews = [[NSMutableArray alloc] init];
@ -738,6 +792,18 @@ static void initSystemExtensionsColors(void)
}
- (void) _setSizeMode: (NSToolbarSizeMode)sizeMode
{
_sizeMode = sizeMode;
}
- (NSToolbarSizeMode) _sizeMode
{
return _sizeMode;
}
// _willBeVisible indicates that the toolbar view previously hidden is in
// process to become visible again before the end of current the event loop.
- (BOOL) _willBeVisible
{
return _willBeVisible;
@ -748,4 +814,18 @@ static void initSystemExtensionsColors(void)
_willBeVisible = willBeVisible;
}
- (void) _setUsesStandardBackgroundColor: (BOOL)standard
{
if (standard)
{
RELEASE(BackgroundColor);
BackgroundColor = [self standardBackgroundColor];
}
else
{
BackgroundColor = [NSColor clearColor];
RETAIN(BackgroundColor);
}
}
@end

View file

@ -73,9 +73,13 @@ static const int current_version = 1;
@interface GSToolbarView (GNUstepPrivate)
- (void) _reload;
// Accessors
- (NSArray *) _visibleBackViews;
- (BOOL) _willBeVisible;
- (void) _setSizeMode: (NSToolbarSizeMode)sizeMode;
- (NSToolbarSizeMode) _sizeMode;
- (void) _setWillBeVisible: (BOOL)willBeVisible;
- (BOOL) _willBeVisible;
@end
@interface NSWindow (ToolbarPrivate)
@ -204,6 +208,7 @@ static const int current_version = 1;
broadcast: (BOOL)broadcast
{
_sizeMode = sizeMode;
[_toolbarView _setSizeMode: _sizeMode];
[_toolbarView _reload];
[_window _adjustToolbarView];
@ -246,7 +251,8 @@ static const int current_version = 1;
- (void)_setWindow: (NSWindow *)window
{
ASSIGN(_window, window);
_window = window;
// We don't do an ASSIGN because the toolbar view retains us.
// call [NSWindow(Toolbar) setToolbar:] to set the toolbar window
}

View file

@ -62,11 +62,16 @@
@end
@interface NSToolbarItem (GNUstepPrivate)
- (void) _layout;
// ---
- (NSView *) _backView;
- (NSMenuItem *) _defaultMenuFormRepresentation;
- (BOOL) _isFlexibleSpace;
- (BOOL) _isModified;
- (void) _layout;
- (BOOL) _selectable;
- (void) _setSelectable: (BOOL)selectable;
- (BOOL) _selected;
- (void) _setSelected: (BOOL)selected;
- (void) _setToolbar: (GSToolbar *)toolbar;
@end
@ -85,15 +90,19 @@
- (id) initWithToolbarItem: (NSToolbarItem *)toolbarItem;
- (void) layout;
- (void) setToolbarItemAction: (SEL)action;
// Accessors
- (NSToolbarItem *) toolbarItem;
- (SEL) toolbarItemAction;
- (void) setToolbarItemAction: (SEL)action;
@end
@implementation GSToolbarButton
- (id) initWithToolbarItem: (NSToolbarItem *)toolbarItem
{
self = [super initWithFrame: NSMakeRect(_ItemBackViewX, _ItemBackViewY, _ItemBackViewDefaultWidth, _ItemBackViewDefaultHeight)];
// Frame will be reset by the layout method
if (self != nil)
{
ASSIGN(_toolbarItem, toolbarItem);
@ -101,15 +110,24 @@
return self;
}
- (void) dealloc
{
RELEASE(_toolbarItem);
[super dealloc];
}
- (void) layout
{
float textWidth, layoutedWidth = -1, layoutedHeight = -1;
NSAttributedString *attrStr;
NSDictionary *attr;
NSFont *font = [NSFont systemFontOfSize: 11]; // [NSFont smallSystemFontSize] or better should NSControlContentFontSize
unsigned int borderMask = [[[_toolbarItem toolbar] _toolbarView] borderMask];
NSString *label = [_toolbarItem label];
// Adjust the layout in accordance with NSToolbarSizeMode
switch ([[_toolbarItem toolbar] sizeMode])
{
case NSToolbarSizeModeDefault:
@ -137,11 +155,27 @@
}
[[self cell] setFont: font];
// Adjust the layout in accordance with the border
if (!(borderMask & GSToolbarViewBottomBorder))
{
layoutedHeight++;
layoutedWidth++;
}
if (!(borderMask & GSToolbarViewTopBorder))
{
layoutedHeight++;
layoutedWidth++;
}
// Adjust the layout in accordance with the label
attr = [NSDictionary dictionaryWithObject: font forKey: @"NSFontAttributeName"];
attrStr = [[NSAttributedString alloc] initWithString: [_toolbarItem label] attributes: attr];
if (label == nil || [label isEqualToString: @""])
label = @"Dummy";
attrStr = [[NSAttributedString alloc] initWithString: label attributes: attr];
textWidth = [attrStr size].width + 2 * _InsetItemTextX;
if (layoutedWidth != -1 && textWidth > layoutedWidth)
@ -176,8 +210,20 @@
}
- (void) mouseDown: (NSEvent *)event
{
if ([_toolbarItem _selectable] && [self state])
return; // Abort in case the button is selectable and selected
// HACK: must be improved to handle drag event
[super mouseDown: event];
}
- (BOOL) sendAction: (SEL)action to: (id)target
{
if ([_toolbarItem _selectable])
[[_toolbarItem toolbar] setSelectedItemIdentifier: [_toolbarItem itemIdentifier]];
if (_toolbarItemAction)
{
return [NSApp sendAction: _toolbarItemAction to: target from: _toolbarItem];
@ -227,6 +273,7 @@
{
self = [super initWithFrame: NSMakeRect(_ItemBackViewX, _ItemBackViewY, _ItemBackViewDefaultWidth,
_ItemBackViewDefaultHeight)];
// Frame will be reset by the layout method
if (self != nil)
{
@ -236,12 +283,20 @@
return self;
}
- (void) dealloc
{
RELEASE(_toolbarItem);
//RELEASE(_font);
[super dealloc];
}
- (void)drawRect: (NSRect)rect
{
NSAttributedString *attrString;
NSDictionary *attr;
NSColor *color;
int textX;
float textX;
[super drawRect: rect]; // We draw _view which is a subview
@ -258,10 +313,10 @@
{
// we draw the label
attr = [NSDictionary dictionaryWithObjectsAndKeys: _font,
@"NSFontAttributeName",
@"NSFontAttributeName",
color,
@"NSForegroundColorAttributeName",
nil];
@"NSForegroundColorAttributeName",
nil];
attrString = [[NSAttributedString alloc] initWithString: [_toolbarItem label] attributes: attr];
textX = (([self frame].size.width - _InsetItemTextX) - [attrString size].width) / 2;
[attrString drawAtPoint: NSMakePoint(textX, _InsetItemTextY)];
@ -275,6 +330,8 @@
float textWidth, layoutedWidth = -1, layoutedHeight = -1;
NSAttributedString *attrStr;
NSDictionary *attr;
unsigned int borderMask = [[[_toolbarItem toolbar] _toolbarView] borderMask];
NSString *label = [_toolbarItem label];
_font = [NSFont systemFontOfSize: 11]; // [NSFont smallSystemFontSize] or better should be NSControlContentFontSize
@ -307,11 +364,27 @@
default:
NSLog(@"Invalid NSToolbarSizeMode"); // invalid
}
// Adjust the layout in accordance with the border
if (!(borderMask & GSToolbarViewBottomBorder))
{
layoutedHeight++;
layoutedWidth++;
}
if (!(borderMask & GSToolbarViewTopBorder))
{
layoutedHeight++;
layoutedWidth++;
}
// Adjust the layout in accordance with the label
attr = [NSDictionary dictionaryWithObject: _font forKey: @"NSFontAttributeName"];
attrStr = [[NSAttributedString alloc] initWithString: [_toolbarItem label] attributes: attr];
if (label == nil || [label isEqualToString: @""])
label = @"Dummy";
attrStr = [[NSAttributedString alloc] initWithString: label attributes: attr];
textWidth = [attrStr size].width + 2 * _InsetItemTextX;
if (textWidth > layoutedWidth)
@ -430,7 +503,12 @@
- (void) _layout
{
// override the default implementation in order to do nothing
NSView *backView = [self _backView];
// override the default implementation
[(id)backView layout];
[backView setFrameSize: NSMakeSize(30, [backView frame].size.height)];
}
@end
@ -453,11 +531,6 @@
{
return nil;// override the default implementation in order to do nothing
}
- (void) _layout
{
// override the default implementation in order to do nothing
}
@end
// ---- NSToolbarFlexibleSpaceItemIdentifier
@ -485,6 +558,8 @@
{
NSView *backView = [self _backView];
[(id)backView layout];
[backView setFrameSize: NSMakeSize(0, [backView frame].size.height)];
// override the default implementation in order to reset the _backView to a zero width
@ -504,7 +579,7 @@
self = [super initWithItemIdentifier: itemIdentifier];
[self setImage: image];
[self setLabel: @"Colors"];
[self setLabel: @"Colors"]; // FIX ME: localize
// set action...
[self setTarget: nil]; // goes to first responder..
@ -527,7 +602,7 @@
self = [super initWithItemIdentifier: itemIdentifier];
[self setImage: image];
[self setLabel: @"Fonts"];
[self setLabel: @"Fonts"]; // FIX ME: localize
// set action...
[self setTarget: nil]; // goes to first responder..
@ -550,7 +625,7 @@
self = [super initWithItemIdentifier: itemIdentifier];
[self setImage: image];
[self setLabel: @"Customize"];
[self setLabel: @"Customize"]; // FIX ME: localize
// set action...
[self setTarget: nil]; // goes to first responder..
@ -573,7 +648,7 @@
self = [super initWithItemIdentifier: itemIdentifier];
[self setImage: image];
[self setLabel: @"Print..."];
[self setLabel: @"Print..."]; // FIX ME: localize
// set action...
[self setTarget: nil]; // goes to first responder..
@ -696,6 +771,20 @@
return self;
}
- (void) dealloc
{
RELEASE(_itemIdentifier);
RELEASE(_label);
RELEASE(_image);
RELEASE(_menuFormRepresentation);
RELEASE(_paletteLabel);
RELEASE(_toolTip);
RELEASE(_view);
RELEASE(_backView);
[super dealloc];
}
- (BOOL) isEnabled
{
if(_flags._isEnabled)
@ -945,6 +1034,45 @@
return [self isKindOfClass: [GSToolbarFlexibleSpaceItem class]];
}
- (BOOL) _selectable
{
return _selectable;
}
- (BOOL) _selected
{
return [(GSToolbarButton *)_backView state];
}
- (void) _setSelected: (BOOL)selected
{
if (_selectable && ![self _selected] && selected)
{
[(GSToolbarButton *)_backView performClick:self];
}
else if (!selected)
{
[(GSToolbarButton *)_backView setState: NO];
}
else if (!_selectable)
{
NSLog(@"The toolbar item %@ is not selectable", self);
}
}
- (void) _setSelectable: (BOOL)selectable
{
if ([_backView isKindOfClass: [GSToolbarButton class]])
{
_selectable = selectable;
[(GSToolbarButton *)_backView setButtonType: NSOnOffButton];
}
else
{
NSLog(@"The toolbar item %@ is not selectable", self);
}
}
- (void) _setToolbar: (GSToolbar *)toolbar
{
ASSIGN(_toolbar, toolbar);

View file

@ -13,7 +13,7 @@
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