diff --git a/ChangeLog b/ChangeLog index 18571bb62..c6612d104 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2004-02-24 Gregory John Casamento + On behalf of Quentin Mathé + + * Headers/Additions/GNUstepGUI/GSToolbarView.h: Changes for + new toolbar implementation. + * Headers/AppKit/NSToolbar.h: same as above. + * Headers/AppKit/NSToolbarItem.h: same... + * GNUmakefile: Added new files + * Source/NSButtonCell.m: Changes to improve the look of + unbordered buttons. + * Source/NSToolbar.m: Changes for new toolbar implementation. + * Source/NSToolbarItem.m: same... + 2004-02-24 Fred Kiefer * Headers/Additions/GNUstepGUI/GSDrawFunctions.h: diff --git a/Headers/Additions/GNUstepGUI/GSToolbarView.h b/Headers/Additions/GNUstepGUI/GSToolbarView.h index 80e87f4a4..4303cf0b4 100644 --- a/Headers/Additions/GNUstepGUI/GSToolbarView.h +++ b/Headers/Additions/GNUstepGUI/GSToolbarView.h @@ -31,21 +31,63 @@ #define _GSToolbarView_h_INCLUDE #include -#include "AppKit/NSToolbarItem.h" -#include "AppKit/NSToolbar.h" -#include "AppKit/NSView.h" +#include + +@class NSMutableArray; +@class NSToolbar; +@class NSToolbarItem; +@class NSView; +@class NSClipView; +@class GSToolbarClippedItemsButton; + +enum { + GSToolbarViewNoBorder = 0, + GSToolbarViewRightBorder = 2, + GSToolbarViewLeftBorder = 4, + GSToolbarViewTopBorder = 8, + GSToolbarViewBottomBorder = 16 +}; + +typedef enum _ItemBackViewHeight { + _ItemBackViewDefaultHeight = 60, + _ItemBackViewRegularHeight = 60, + _ItemBackViewSmallHeight = 50 +} _ItemBackViewHeight; + +typedef enum _ItemViewWidth { + _ItemBackViewDefaultWidth = 60, + _ItemBackViewRegularWidth = 60, + _ItemBackViewSmallWidth = 50 +} _ItemBackViewWidth; + +static const int _ItemBackViewX = 0; +static const int _ItemBackViewY = 0; +static const int _InsetItemViewX = 10; +static const int _InsetItemViewY = 26; +static const int _InsetItemTextX = 3; +static const int _InsetItemTextY = 4; + +static const int _ClippedItemsViewWidth = 28; @interface GSToolbarView : NSView { NSToolbar *_toolbar; + NSClipView *_clipView, *_clipViewForEditMode; + NSView *_loadedViewEdited; + GSToolbarClippedItemsButton *_clippedItemsMark; + NSMutableArray *_visibleBackViews; + BOOL _willBeVisible; + unsigned int _borderMask; } -- (id) initWithToolbar: (NSToolbar *)toolbar; -- (void) setToolbar: (NSToolbar *)toolbar; -- (NSToolbar *) toolbar; -@end -@interface NSToolbar (GNUstepPrivate) -- (id) _toolbarView; +- (id) initWithFrame: (NSRect)frame; + +// Accessors +- (NSToolbar *) toolbar; +- (void) setToolbar: (NSToolbar *)toolbar; +- (unsigned int) borderMask; +- (void) setBorderMask: (unsigned int)borderMask; + @end #endif diff --git a/Headers/AppKit/NSToolbar.h b/Headers/AppKit/NSToolbar.h index 16b431fef..3504689b8 100644 --- a/Headers/AppKit/NSToolbar.h +++ b/Headers/AppKit/NSToolbar.h @@ -31,17 +31,17 @@ #define _GNUstep_H_NSToolbar #include -#include - -#include +@class NSString; @class NSArray; @class NSMutableArray; -@class NSString; @class NSDictionary; @class NSMutableDictionary; -@class NSToolbarItem; @class NSNotification; +@class NSLock; +@class NSToolbarItem; +@class GSToolbarView; +@class NSWindow; /* * Constants @@ -54,6 +54,13 @@ typedef enum NSToolbarDisplayModeLabelOnly } NSToolbarDisplayMode; +typedef enum +{ + NSToolbarSizeModeDefault, + NSToolbarSizeModeRegular, + NSToolbarSizeModeSmall, +} NSToolbarSizeMode; + APPKIT_EXPORT NSString *NSToolbarDidRemoveItemNotification; APPKIT_EXPORT NSString *NSToolbarWillAddItemNotification; @@ -68,11 +75,19 @@ APPKIT_EXPORT NSString *NSToolbarWillAddItemNotification; NSString *_identifier; BOOL _visible; NSMutableArray *_items; - NSMutableArray *_visibleItems; - id _toolbarView; + GSToolbarView *_toolbarView; + NSWindow *_window; + BOOL _build;; } // Instance methods +- (id) initWithIdentifier: (NSString*)identifier; + +- (void) insertItemWithItemIdentifier: (NSString*)itemIdentifier atIndex: (int)index; +- (void) removeItemAtIndex: (int)index; +- (void) runCustomizationPalette: (id)sender; + +// Accessors - (BOOL) allowsUserCustomization; - (BOOL) autosavesConfiguration; - (NSDictionary*) configurationDictionary; @@ -80,22 +95,22 @@ APPKIT_EXPORT NSString *NSToolbarWillAddItemNotification; - (id) delegate; - (NSToolbarDisplayMode) displayMode; - (NSString*) identifier; -- (id) initWithIdentifier: (NSString*)identifier; -- (void) insertItemWithItemIdentifier: (NSString*)itemIdentifier - atIndex: (int)index; - (BOOL) isVisible; - (NSArray*) items; -- (void) removeItemAtIndex: (int)index; -- (void) runCustomizationPalette: (id)sender; - +- (NSString *) selectedItemIdentifier; +- (NSArray*) visibleItems; - (void) setAllowsUserCustomization: (BOOL)flag; - (void) setAutosavesConfiguration: (BOOL)flag; - (void) setConfigurationFromDictionary: (NSDictionary*)configDict; - (void) setDelegate: (id)delegate; - (void) setDisplayMode: (NSToolbarDisplayMode)displayMode; +- (void) setSelectedItemIdentifier: (NSString *) identifier; +- (void) setSizeMode: (NSToolbarSizeMode)sizeMode; - (void) setVisible: (BOOL)shown; +- (NSToolbarSizeMode) sizeMode; + - (void) validateVisibleItems; -- (NSArray*) visibleItems; + @end /* interface of NSToolbar */ /* @@ -110,11 +125,13 @@ APPKIT_EXPORT NSString *NSToolbarWillAddItemNotification; // required method - (NSToolbarItem*)toolbar: (NSToolbar*)toolbar itemForItemIdentifier: (NSString*)itemIdentifier - willBeInsertedIntoToolbar: (BOOL)flag; +willBeInsertedIntoToolbar: (BOOL)flag; // required method - (NSArray*) toolbarAllowedItemIdentifiers: (NSToolbar*)toolbar; // required method - (NSArray*) toolbarDefaultItemIdentifiers: (NSToolbar*)toolbar; +// optional method +- (NSArray *) toolbarSelectableItemIdentifiers: (NSToolbar *)toolbar; @end #endif /* _GNUstep_H_NSToolbar */ diff --git a/Headers/AppKit/NSToolbarItem.h b/Headers/AppKit/NSToolbarItem.h index c3ca0f204..9e260cb5f 100644 --- a/Headers/AppKit/NSToolbarItem.h +++ b/Headers/AppKit/NSToolbarItem.h @@ -31,9 +31,9 @@ #define _GNUstep_H_NSToolbarItem #include -#include -#include #include +#include +#include @class NSArray; @class NSString; @@ -63,11 +63,14 @@ APPKIT_EXPORT NSString *NSToolbarPrintItemIdentifier; NSString *_label; NSMenuItem *_menuFormRepresentation; NSString *_paletteLabel; + NSImage *_image; // toolbar NSToolbar *_toolbar; NSString *_toolTip; id _view; + NSView *_backView; + BOOL _updated; // size NSSize _maxSize; @@ -95,39 +98,43 @@ APPKIT_EXPORT NSString *NSToolbarPrintItemIdentifier; } // Instance methods -- (SEL)action; -- (BOOL)allowsDuplicatesInToolbar; -- (NSImage *)image; - (id)initWithItemIdentifier: (NSString *)itemIdentifier; -- (BOOL)isEnabled; -- (NSString *)itemIdentifier; -- (NSString *)label; -- (NSSize)maxSize; -- (NSMenuItem *)menuFormRepresentation; -- (NSSize)minSize; -- (NSString *)paletteLabel; -- (void)setAction: (SEL)action; -- (void)setEnabled: (BOOL)enabled; -- (void)setImage: (NSImage *)image; -- (void)setLabel: (NSString *)label; -- (void)setMaxSize: (NSSize)maxSize; -- (void)setMenuFormRepresentation: (NSMenuItem *)menuItem; -- (void)setMinSize: (NSSize)minSize; -- (void)setPaletteLabel: (NSString *)paletteLabel; -- (void)setTag: (int)tag; -- (void)setTarget: (id)target; -- (void)setToolTip: (NSString *)toolTip; -- (void)setView: (NSView *)view; -- (int)tag; -- (id)target; -- (NSString *)toolTip; -- (NSToolbar *)toolbar; + - (void)validate; -- (NSView *)view; + +// Accessors +- (SEL) action; +- (BOOL) allowsDuplicatesInToolbar; +- (NSImage *) image; +- (BOOL) isEnabled; +- (NSString *) itemIdentifier; +- (NSString *) label; +- (NSSize) maxSize; +- (NSMenuItem *) menuFormRepresentation; +- (NSSize) minSize; +- (NSString *) paletteLabel; +- (int) tag; +- (id) target; +- (NSString *) toolTip; +- (NSToolbar *) toolbar; +- (NSView *) view; +- (void) setAction: (SEL)action; +- (void) setEnabled: (BOOL)enabled; +- (void) setImage: (NSImage *)image; +- (void) setLabel: (NSString *)label; +- (void) setMaxSize: (NSSize)maxSize; +- (void) setMenuFormRepresentation: (NSMenuItem *)menuItem; +- (void) setMinSize: (NSSize)minSize; +- (void) setPaletteLabel: (NSString *)paletteLabel; +- (void) setTag: (int)tag; +- (void) setTarget: (id)target; +- (void) setToolTip: (NSString *)toolTip; +- (void) setView: (NSView *)view; + @end /* interface of NSToolbarItem */ @protocol NSToolbarItemValidation -- (BOOL)validateToolbarItem: (NSToolbarItem *)theItem; +- (BOOL) validateToolbarItem: (NSToolbarItem *)theItem; @end #endif /* _GNUstep_H_NSToolbarItem */ diff --git a/Images/GNUmakefile b/Images/GNUmakefile index decdeac50..fd1807a0a 100644 --- a/Images/GNUmakefile +++ b/Images/GNUmakefile @@ -107,6 +107,7 @@ common_LeftTabStop.tiff \ common_DecimalTabStop.tiff \ common_Diamond.tiff \ common_Printer.tiff \ +common_ToolbarClippedItemsMark.tiff \ common_ToolbarSeperatorItem.tiff \ common_ToolbarShowColorsItem.tiff \ common_ToolbarShowFontsItem.tiff \ diff --git a/Source/GNUmakefile b/Source/GNUmakefile index c916f635e..ff60fcb9f 100644 --- a/Source/GNUmakefile +++ b/Source/GNUmakefile @@ -103,7 +103,6 @@ NSMenu.m \ NSMenuView.m \ NSMenuItem.m \ NSMenuItemCell.m \ -NSNib.m \ NSOpenGLContext.m \ NSOpenGLPixelFormat.m \ NSOpenGLView.m \ @@ -152,6 +151,7 @@ NSTextStorage.m \ NSToolbar.m \ NSToolbarItem.m \ NSView.m \ +NSWindow+Toolbar.m \ NSWindow.m \ NSWindowController.m \ NSWorkspace.m \ @@ -182,7 +182,8 @@ GSTypesetter.m \ GSHorizontalTypesetter.m \ GSNibTemplates.m \ GSNibCompatibility.m \ -GSTitleView.m +GSTitleView.m \ +GSToolbarView.m # Turn off NSMenuItem warning that NSMenuItem conforms to , # but does not implement 's methods itself (it inherits @@ -253,7 +254,6 @@ NSMenu.h \ NSMenuItem.h \ NSMenuItemCell.h \ NSMenuView.h \ -NSNib.h \ NSOpenPanel.h \ NSOpenGL.h \ NSOpenGLView.h \ diff --git a/Source/GSToolbarView.m b/Source/GSToolbarView.m new file mode 100644 index 000000000..fc915cce2 --- /dev/null +++ b/Source/GSToolbarView.m @@ -0,0 +1,512 @@ +/* + GSToolbarView.m + + The toolbar view class. + + Copyright (C) 2004 Free Software Foundation, Inc. + + Author: Quentin Mathé + Date: January 2004 + + This file is part of the GNUstep GUI Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include +#include +#include +#include +#include "AppKit/NSToolbarItem.h" +#include "AppKit/NSToolbar.h" +#include "AppKit/NSView.h" +#include "AppKit/NSClipView.h" +#include "AppKit/NSButton.h" +#include "AppKit/NSBezierPath.h" +#include "AppKit/NSImage.h" +#include "AppKit/NSMenu.h" +#include "AppKit/NSEvent.h" +#include "AppKit/NSWindow.h" +#include "GNUstepGUI/GSToolbarView.h" + +// internal +static const int current_version = 1; + + +@interface NSToolbar (GNUstepPrivate) +- (void) _build; +- (void) _setToolbarView: (GSToolbarView *)toolbarView; +@end + +@interface NSToolbarItem (GNUstepPrivate) +- (NSView *) _backView; +- (BOOL) _isModified; +- (BOOL) _isFlexibleSpace; +- (void) _layout; +@end + +@interface GSToolbarClippedItemsButton : NSButton +{ + NSToolbar *_toolbar; +} + +- (id) init; + +// Accessors +- (NSMenu *) returnMenu; // this method cannot be called menu otherwise +// it would override NSResponder method with the same name +- (void)setToolbar: (NSToolbar *)toolbar; +@end + +@interface GSToolbarView (GNUstepPrivate) +- (void) _handleViewsSize; +- (void) _handleViewsOrigin; +- (void) _handleViewsVisibility; +- (void) _reload; +- (void) _takeInAccountFlexibleSpaces; + +// Accessors +- (NSArray *) _visibleBackViews; +- (void) _setWillBeVisible: (BOOL)willBeVisible; +- (BOOL) _willBeVisible; +@end + +@implementation GSToolbarClippedItemsButton +- (id)init +{ + NSImage *image = [NSImage imageNamed: @"common_ToolbarClippedItemsMark"]; + + if ((self = [super initWithFrame: NSMakeRect(0, 0, _ClippedItemsViewWidth, _ItemBackViewDefaultHeight)]) != nil) + { + [self setBordered: NO]; + [[self cell] setHighlightsBy: NSChangeGrayCellMask | NSChangeBackgroundCellMask]; + [self setAutoresizingMask: (NSViewNotSizable | NSViewMinXMargin)]; + [self setImagePosition: NSImageOnly]; + [image setScalesWhenResized: YES]; + [image setSize: NSMakeSize(20., 20.)]; + [self setImage: image]; + return self; + } + return nil; +} + +- (void)mouseDown: (NSEvent *)event { + NSMenu *clippedItemsMenu = [self menuForEvent:event]; + + if (clippedItemsMenu != nil) + { + [NSMenu popUpContextMenu: clippedItemsMenu withEvent: event forView: self]; + } +} + +- (NSMenu *)menuForEvent: (NSEvent *)event { + if ([event type] == NSLeftMouseDown) + { + return [self returnMenu]; + } + return nil; +} + +- (NSMenu *)returnMenu +// this method cannot be called menu otherwise it would override NSResponder method with the same name +{ + NSMenu *menu = [[NSMenu alloc] initWithTitle:@""]; + NSEnumerator *e; + id item; + NSArray *visibleItems; + + AUTORELEASE(menu); + + visibleItems = [_toolbar visibleItems]; + + e = [[_toolbar items] objectEnumerator]; + while ((item = [e nextObject]) != nil) + { + if (![visibleItems containsObject: item]) + { + id menuItem; + + menuItem = [item menuFormRepresentation]; + if (menuItem != nil) + [menu addItem: menuItem]; + } + } + + return menu; +} + +// Accessors + +- (void)setToolbar: (NSToolbar *)toolbar +{ + ASSIGN(_toolbar, toolbar); +} +@end + +// Implementation GSToolbarView + +@implementation GSToolbarView +- (id) initWithFrame: (NSRect)frame +{ + if((self = [super initWithFrame: frame]) != nil) + { + _clipView = [[NSClipView alloc] initWithFrame: NSMakeRect(0, 1, frame.size.width, frame.size.height)]; + [_clipView setAutoresizingMask: (NSViewWidthSizable | NSViewHeightSizable)]; + [self addSubview: _clipView]; + + _clippedItemsMark = [[GSToolbarClippedItemsButton alloc] init]; + + _borderMask = GSToolbarViewTopBorder | GSToolbarViewBottomBorder | GSToolbarViewRightBorder | GSToolbarViewLeftBorder; + } + return self; +} + +- (void) dealloc +{ + RELEASE(_toolbar); + RELEASE(_clippedItemsMark); + RELEASE(_clipView); + + [super dealloc]; +} + +// More overrided methods + +- (void) drawRect: (NSRect)aRect +{ + NSBezierPath *rect = [NSBezierPath bezierPathWithRect: aRect]; + NSRect viewFrame = [self frame]; + + // We draw the background + [[NSColor colorWithDeviceRed: 0.8 green: 0.8 blue: 0.8 alpha:1] set]; + [rect fill]; + + // We draw the border + [[NSColor colorWithDeviceRed: 0.5 green: 0.5 blue: 0.5 alpha:1] set]; + if (_borderMask & GSToolbarViewBottomBorder) + { + [NSBezierPath strokeLineFromPoint: NSMakePoint(0, 0.5) + toPoint: NSMakePoint(viewFrame.size.width, 0.5)]; + } + if (_borderMask & GSToolbarViewTopBorder) + { + [NSBezierPath strokeLineFromPoint: NSMakePoint(0, viewFrame.size.height - 0.5) + toPoint: NSMakePoint(viewFrame.size.width, viewFrame.size.height - 0.5)]; + } + if (_borderMask & GSToolbarViewLeftBorder) + { + [NSBezierPath strokeLineFromPoint: NSMakePoint(0.5, 0) + toPoint: NSMakePoint(0.5, viewFrame.size.height)]; + } + if (_borderMask & GSToolbarViewRightBorder) + { + [NSBezierPath strokeLineFromPoint: NSMakePoint(viewFrame.size.width - 0.5, 0) + toPoint: NSMakePoint(viewFrame.size.width - 0.5, viewFrame.size.height)]; + } + + [super drawRect: aRect]; + +} + +- (BOOL) isOpaque +{ + return YES; +} + +- (void) windowDidResize: (NSNotification *)notification +{ + if (![_toolbar isVisible]) return; + + [self _handleViewsVisibility]; +} + +- (void) viewDidMoveToSuperview +{ + // NSView method called when a view is moved not to a superview + + if (_toolbar != nil) + { + [self _handleViewsVisibility]; + } +} + +- (void) viewDidMoveToWindow +{ + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + + // NSView method called when a view is moved to a window (NSView has a variable _window) + [super viewDidMoveToWindow]; + + [nc removeObserver: self name: NSWindowDidResizeNotification object: _window]; + [nc addObserver: self selector: @selector(windowDidResize:) name: NSWindowDidResizeNotification object: nil]; + + [self viewDidMoveToSuperview]; +} + +// More methods... Accessors + +- (unsigned int) borderMask +{ + return _borderMask; +} + +- (NSToolbar *) toolbar +{ + return _toolbar; +} + +- (void) setBorderMask: (unsigned int)borderMask +{ + _borderMask = borderMask; +} + +- (void) setToolbar: (NSToolbar *)toolbar +{ + ASSIGN(_toolbar, toolbar); + [_clippedItemsMark setToolbar: _toolbar]; + + [_toolbar _build]; // Use the delegate to build the toolbar + + [_toolbar _setToolbarView: self]; + [self _reload]; // Load the toolbar in the toolbar view +} + +// Private methods + +- (void) _handleViewsOrigin +{ + NSEnumerator *e = [[_toolbar items] objectEnumerator]; + NSToolbarItem *item; + NSView *itemView; + NSRect itemViewFrame; + float x = 0.; + + while ((item = [e nextObject]) != nil) + { + itemView = [item _backView]; + + if ([item _isFlexibleSpace]) + { + [item _layout]; + } + + itemViewFrame = [itemView frame]; + [itemView setFrame: NSMakeRect(x, itemViewFrame.origin.y, itemViewFrame.size.width, itemViewFrame.size.height)]; + x += [itemView frame].size.width; + } +} + +- (void) _handleViewsSize +{ + NSEnumerator *e = [[_toolbar items] objectEnumerator]; + NSToolbarItem *item; + NSView *itemView, *itemViewEdited; + NSArray *subviews = [self subviews]; + + while ((item = [e nextObject]) != nil) + { + itemView = [item _backView]; + if (![subviews containsObject: itemView] || [item _isModified]) + { + itemViewEdited = itemView; + } + + // Example : when a label is changed, _isModified returns YES + // to let us known we must recalculate the text lenght and + // then the item view size with the subsequent arrangement + + if (itemViewEdited != nil) + [item _layout]; + } + +} + +- (void) _handleViewsVisibility +{ + NSArray *items = [_toolbar items]; + + // the backViews which are associated with the toolbar items now (the toolbar items doesn't + // reflect the toolbar view content) + NSArray *itemBackViews = [items valueForKey: @"_backView"]; + + // the backViews which will be visible in the toolbar view (when _handleViewsVisibility will be terminated) + NSArray *visibleItemBackViews = [self _visibleBackViews]; + + // the backViews which are visible in the toolbar view now + NSArray *currentItemBackViews = [_clipView subviews]; + + NSEnumerator *e; + NSView *itemBackView; + NSRect clipViewFrame; + + [self _handleViewsOrigin]; + + [self _takeInAccountFlexibleSpaces]; + + // We remove the _backView (itemBackView variable) associated with the removed or not visible + // toolbar items + + e = [currentItemBackViews objectEnumerator]; + + while ((itemBackView = [e nextObject]) != nil) + { + if (![itemBackViews containsObject: itemBackView] || ![visibleItemBackViews containsObject: itemBackView]) + { + if ([itemBackView superview] != nil) + [itemBackView removeFromSuperview]; + } + } + + // We add the _backView (itemBackView variable) associated with the added toolbar item when it + // is visible + + e = [visibleItemBackViews objectEnumerator]; + + while ((itemBackView = [e nextObject]) != nil) + { + if (![currentItemBackViews containsObject: itemBackView]) + { + [_clipView addSubview: itemBackView]; + } + } + + clipViewFrame = [_clipView frame]; + + if (([_clippedItemsMark superview] == nil) && ([visibleItemBackViews count] < [itemBackViews count])) + { + [_clipView setFrame: NSMakeRect(clipViewFrame.origin.x, clipViewFrame.origin.y, + clipViewFrame.size.width - _ClippedItemsViewWidth, + clipViewFrame.size.height)]; + clipViewFrame = [_clipView frame]; // we get the new _clipView frame + [_clippedItemsMark setFrameOrigin: NSMakePoint(clipViewFrame.size.width, + clipViewFrame.origin.y)]; + [self addSubview: _clippedItemsMark]; + } + else if (([_clippedItemsMark superview] != nil) && ([visibleItemBackViews count] >= + [itemBackViews count])) + { + [_clippedItemsMark removeFromSuperview]; + [_clipView setFrame: NSMakeRect(clipViewFrame.origin.x, clipViewFrame.origin.y, + clipViewFrame.size.width + _ClippedItemsViewWidth, clipViewFrame.size.height)]; + } + + [self setNeedsDisplay: YES]; +} + +- (void) _reload { + + [self _handleViewsSize]; + [self _handleViewsVisibility]; + +} + +- (void) _takeInAccountFlexibleSpaces +{ + NSArray *items = [_toolbar items]; + NSEnumerator *e = [items objectEnumerator]; + NSToolbarItem *item; + NSView *itemView; + NSRect lastItemViewFrame = [[[items lastObject] _backView] frame]; + float lengthAvailable = [self frame].size.width - (lastItemViewFrame.origin.x + + lastItemViewFrame.size.width); + int flexibleSpaceItemsNumber = 0; + BOOL mustAdjustNext = NO; + float x = 0.; + + if (lengthAvailable < 1) + return; + + while ((item = [e nextObject]) != nil) + { + if ([item _isFlexibleSpace]) + { + flexibleSpaceItemsNumber++; + } + } + + if (lengthAvailable < flexibleSpaceItemsNumber) + return; + + e = [items objectEnumerator]; + while ((item = [e nextObject]) != nil) + { + itemView = [item _backView]; + if ([item _isFlexibleSpace]) + { + NSRect itemViewFrame = [itemView frame]; + + [itemView setFrame: + NSMakeRect(x, itemViewFrame.origin.y, lengthAvailable / flexibleSpaceItemsNumber, + itemViewFrame.size.height)]; + mustAdjustNext = YES; + } + else if (mustAdjustNext) + { + NSRect itemViewFrame = [itemView frame]; + + [itemView setFrame: NSMakeRect(x, itemViewFrame.origin.y, itemViewFrame.size.width, + itemViewFrame.size.height)]; + } + x += [itemView frame].size.width; + } + +} + +// Accessors private methods + +- (NSArray *) _visibleBackViews +{ + NSArray *items = [_toolbar items]; + NSView *itemView; + int i, n = [items count]; + float totalWidth = 0, toolbarWidth; + + if (![_toolbar isVisible] && ![self _willBeVisible]) + return nil; + + [_visibleBackViews release]; + _visibleBackViews = [[NSMutableArray alloc] init]; + + toolbarWidth = [self frame].size.width;; + + for (i = 0; i < n; i++) + { + itemView = [[items objectAtIndex:i] _backView]; + + totalWidth += [itemView frame].size.width; + + if ((totalWidth + _ClippedItemsViewWidth <= toolbarWidth) || (i == n - 1 && totalWidth <= + toolbarWidth)) + { + [_visibleBackViews addObject: itemView]; + } + } + + return _visibleBackViews; + +} + +- (BOOL) _willBeVisible +{ + return _willBeVisible; +} + +- (void) _setWillBeVisible: (BOOL)willBeVisible +{ + _willBeVisible = willBeVisible; +} + +@end diff --git a/Source/NSButtonCell.m b/Source/NSButtonCell.m index a58ace12d..aedc44b33 100644 --- a/Source/NSButtonCell.m +++ b/Source/NSButtonCell.m @@ -413,21 +413,7 @@ - (BOOL) isOpaque { - /* - * MacOS-X says we should return !transparent && [self isBordered], - * but that's wrong in our case, since if there is no border, - * we draw the interior of the cell to fill completely the bounds. - * They are likely to draw differently. - */ - - // This seems the best to achieve a correct behaviour - // (consistent with Nextstep) - if (!(_cell.is_bordered - || (_highlightsByMask & NSChangeBackgroundCellMask) - || (_highlightsByMask & NSChangeGrayCellMask))) - return NO; - - return !_buttoncell_is_transparent; + return !_buttoncell_is_transparent && _cell.is_bordered; } - (NSBezelStyle)bezelStyle @@ -706,15 +692,6 @@ cellFrame = NSOffsetRect(cellFrame, 1., flippedView ? 1. : -1.); } - /* Determine the background color. */ - if (mask & (NSChangeGrayCellMask | NSChangeBackgroundCellMask)) - { - backgroundColor = [NSColor selectedControlColor]; - } - - if (backgroundColor == nil) - backgroundColor = [NSColor controlBackgroundColor]; - /* Draw the cell's background color. We draw when there is a border or when highlightsByMask is NSChangeBackgroundCellMask or NSChangeGrayCellMask, @@ -723,8 +700,22 @@ || (_highlightsByMask & NSChangeBackgroundCellMask) || (_highlightsByMask & NSChangeGrayCellMask)) { - [backgroundColor set]; - NSRectFill (cellFrame); + /* Determine the background color. */ + if (mask & (NSChangeGrayCellMask | NSChangeBackgroundCellMask)) + { + backgroundColor = [NSColor selectedControlColor]; + } + else if (_cell.is_bordered) + { + backgroundColor = [NSColor controlBackgroundColor]; + } + + if (backgroundColor != nil) + { + [backgroundColor set]; + NSRectFill (cellFrame); + } + } /* @@ -800,10 +791,7 @@ titleRect = imageRect; titleRect.origin.x += imageSize.width + xDist; titleRect.size.width = cellFrame.size.width - imageSize.width - xDist; - if (_cell.is_bordered || _cell.is_bezeled) - { - titleRect.size.width -= 3; - } + titleRect.size.width -= 3; break; case NSImageRight: @@ -820,11 +808,8 @@ titleRect.origin = cellFrame.origin; titleRect.size.width = cellFrame.size.width - imageSize.width - xDist; titleRect.size.height = cellFrame.size.height; - if (_cell.is_bordered || _cell.is_bezeled) - { - titleRect.origin.x += 3; - titleRect.size.width -= 3; - } + titleRect.origin.x += 3; + titleRect.size.width -= 3; break; case NSImageAbove: @@ -847,14 +832,13 @@ if (_cell.is_bordered || _cell.is_bezeled) { + imageRect.origin.x += 3; imageRect.size.width -= 6; - imageRect.origin.x += 3; - titleRect.size.width -= 6; - titleRect.origin.x += 3; imageRect.size.height -= 1; - titleRect.size.height -= 1; - titleRect.origin.y += 1; } + titleRect.origin.x += 3; + titleRect.origin.y += 4; + titleRect.size.width -= 6; break; case NSImageBelow: @@ -879,12 +863,12 @@ { imageRect.size.width -= 6; imageRect.origin.x += 3; - titleRect.size.width -= 6; - titleRect.origin.x += 3; imageRect.size.height -= 1; imageRect.origin.y += 1; - titleRect.size.height -= 1; } + titleRect.size.width -= 6; + titleRect.origin.x += 3; + titleRect.size.height -= 4; break; case NSImageOverlaps: @@ -919,12 +903,7 @@ if (_cell.shows_first_responder && [[controlView window] firstResponder] == controlView) { - if (_cell.is_bordered || _cell.is_bezeled) NSDottedFrameRect(cellFrame); - else if (ipos == NSImageOnly) - NSDottedFrameRect(cellFrame); - else - NSDottedFrameRect(titleRect); } } diff --git a/Source/NSToolbar.m b/Source/NSToolbar.m index ee3506721..042a0b9a1 100644 --- a/Source/NSToolbar.m +++ b/Source/NSToolbar.m @@ -32,74 +32,75 @@ #include #include #include +#include #include #include "AppKit/NSToolbarItem.h" #include "AppKit/NSToolbar.h" #include "AppKit/NSView.h" +#include "AppKit/NSClipView.h" #include "AppKit/NSButton.h" #include "AppKit/NSNibLoading.h" +#include "AppKit/NSBezierPath.h" +#include "AppKit/NSImage.h" +#include "AppKit/NSMenu.h" +#include "AppKit/NSEvent.h" +#include "AppKit/NSWindow.h" #include "GNUstepGUI/GSToolbarView.h" // internal static NSNotificationCenter *nc = nil; static const int current_version = 1; -@implementation GSToolbarView -- (id) initWithToolbar: (NSToolbar *)toolbar -{ - if((self = [super init]) != nil) - { - ASSIGN(_toolbar,toolbar); - } - return self; -} +static NSMutableArray *toolbars; -- (void) dealloc -{ - RELEASE(_toolbar); - [super dealloc]; -} -- (void) setToolbar: (NSToolbar *)toolbar -{ - ASSIGN(_toolbar, toolbar); - -} -- (NSToolbar *) toolbar -{ - return _toolbar; -} +@interface NSToolbar (GNUstepPrivate) +// Private class methods ++ (NSArray *) _toolbars; ++ (NSArray *) _toolbarsForIdentifier: (NSString *)identifier; -- (void) drawRect: (NSRect)aRect -{ - NSArray *items = [_toolbar items]; - NSEnumerator *en = [items objectEnumerator]; - id item = nil; - float x = 0; +// --- - [super drawRect: aRect]; - while((item = [en nextObject]) != nil) - { - NSView *itemView = [item view]; - NSRect itemFrame = [itemView frame]; +- (void) _insertItemWithItemIdentifier: (NSString *)itemIdentifier atIndex: (int)index broadcast: (BOOL)broadcast; - // now we need to draw the items... - itemFrame.origin.x = x; // start at x - itemFrame.origin.y = 0; // reset to top of view. - [itemView drawRect: itemFrame]; - x += NSWidth(itemFrame) + 2; // move over by the frame width plus 2 pixels. - } -} +// Private methods with broacast support +- (void) _insertItemWithItemIdentifier: (NSString *)itemIdentifier atIndex: (int)index broadcast: (BOOL)broadcast; +- (void) _removeItemAtIndex: (int)index broadcast: (BOOL)broadcast; +- (void) _setAllowsUserCustomization: (BOOL)flag broadcast: (BOOL)broadcast; +- (void) _setAutosavesConfiguration: (BOOL)flag broadcast: (BOOL)broadcast; +- (void) _setConfigurationFromDictionary: (NSDictionary *)configDict broadcast: (BOOL)broadcast; +- (void) _setDisplayMode: (NSToolbarDisplayMode)displayMode broadcast: (BOOL)broadcast; +- (void) _setVisible: (BOOL)shown broadcast: (BOOL)broadcast; +- (void) _setDelegate: (id)delegate broadcast: (BOOL)broadcast; + +// Few other private methods +- (void) _build; +- (void) _loadConfig; + +// Accessors +- (void) _setToolbarView: (GSToolbarView *)toolbarView; +- (GSToolbarView *) _toolbarView; +- (void) _setWindow: (NSWindow *)window; +- (NSWindow *) _window; @end -@implementation NSToolbar (GNUstepPrivate) -- (id) _toolbarView -{ - return _toolbarView; -} +@interface NSToolbarItem (GNUstepPrivate) +- (void) _setToolbar: (NSToolbar *)toolbar; @end +@interface GSToolbarView (GNUstepPrivate) +- (void) _reload; +- (NSArray *) _visibleBackViews; +- (BOOL) _willBeVisible; +- (void) _setWillBeVisible: (BOOL)willBeVisible; +@end + +// --- + @implementation NSToolbar + +// Class methods + // Initialize the class when it is loaded + (void) initialize { @@ -107,10 +108,142 @@ static const int current_version = 1; { [self setVersion: current_version]; nc = [NSNotificationCenter defaultCenter]; + toolbars = [[NSMutableArray alloc] init]; } } +// Private class methods + ++ (NSArray *) _toolbars +{ + return toolbars; +} + ++ (NSArray *) _toolbarsForIdentifier: (NSString *)identifier +{ + NSMutableArray *wanted = [[NSMutableArray alloc] init]; + NSArray *identifiers = [toolbars valueForKey: @"identifier"]; + int i, n; + + if (identifiers == nil) + return nil; + + n = [identifiers count]; + + for (i = 0; i < n; i++) + { + if ([[identifiers objectAtIndex: i] isEqualToString: identifier]) + { + [wanted addObject: [toolbars objectAtIndex: i]]; + } + } + + return wanted; +} + +// --- + // Instance methods + +- (id) initWithIdentifier: (NSString*)identifier +{ + NSArray *linked; + NSToolbar *toolbarModel = nil; + + [super init]; + + ASSIGN(_identifier, identifier); + + _items = [[NSMutableArray alloc] init]; + + linked = [NSToolbar _toolbarsForIdentifier: _identifier]; + + if (linked != nil && [linked count] > 0) + { + toolbarModel = [linked objectAtIndex: 0]; + } + + if (toolbarModel != nil) + { + _customizationPaletteIsRunning = NO; + _allowsUserCustomization = [toolbarModel allowsUserCustomization]; + _autosavesConfiguration = [toolbarModel autosavesConfiguration]; + ASSIGN(_configurationDictionary, [toolbarModel configurationDictionary]); + _displayMode = [toolbarModel displayMode]; + _visible = [toolbarModel isVisible]; + + //[self _loadConfig]; + + [self _setDelegate: [toolbarModel delegate] broadcast: NO]; + } + else + { + _customizationPaletteIsRunning = NO; + _allowsUserCustomization = NO; + _autosavesConfiguration = NO; + _configurationDictionary = nil; + _displayMode = NSToolbarDisplayModeDefault; + _visible = YES; + _items = [[NSMutableArray alloc] init]; + + [self _loadConfig]; + + _delegate = nil; + } + + [toolbars addObject: self]; + + return self; +} + +- (void) dealloc +{ + DESTROY (_identifier); + DESTROY (_configurationDictionary); + + if (_delegate != nil) + { + [nc removeObserver: _delegate name: nil object: self]; + _delegate = nil; + } + + [super dealloc]; +} + +- (void) insertItemWithItemIdentifier: (NSString *)itemIdentifier + atIndex: (int)index +{ + [self _insertItemWithItemIdentifier: itemIdentifier atIndex: index broadcast: YES]; +} + +- (void) removeItemAtIndex: (int)index +{ + [self _removeItemAtIndex: index broadcast: YES]; +} + +- (void) runCustomizationPalette: (id)sender +{ + _customizationPaletteIsRunning = [NSBundle loadNibNamed: @"GSToolbarCustomizationPalette" + owner: self]; + if(!_customizationPaletteIsRunning) + { + NSLog(@"Failed to load gorm for GSToolbarCustomizationPalette"); + } +} + +- (void) validateVisibleItems +{ + NSEnumerator *en = [[self visibleItems] objectEnumerator]; + NSToolbarItem *item = nil; + + while((item = [en nextObject]) != nil) + { + [item validate]; + } +} + +// Accessors + - (BOOL) allowsUserCustomization { return _allowsUserCustomization; @@ -146,6 +279,118 @@ static const int current_version = 1; return _identifier; } +- (BOOL) isVisible +{ + return _visible; +} + +- (NSArray *) items +{ + return _items; +} + +- (NSString *) selectedItemIdentifier +{ + return nil; +} + +- (NSArray *) visibleItems +{ + return [[_toolbarView _visibleBackViews] valueForKey: @"toolbarItem"]; +} + +- (void) setAllowsUserCustomization: (BOOL)flag +{ + [self _setAllowsUserCustomization: flag broadcast: YES]; +} + +- (void) setAutosavesConfiguration: (BOOL)flag +{ + [self _setAutosavesConfiguration: flag broadcast: YES]; +} + +- (void) setConfigurationFromDictionary: (NSDictionary *)configDict +{ + ASSIGN(_configurationDictionary, configDict); +} + +/** + * Sets the receivers delegate ... this is the object which will receive + * -toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar: + * -toolbarAllowedItemIdentifiers: and -toolbarDefaultItemIdentifiers: + * messages. + */ + +- (void) setDelegate: (id)delegate +{ + [self _setDelegate: delegate broadcast: YES]; +} + +- (void) setDisplayMode: (NSToolbarDisplayMode)displayMode +{ + [self _setDisplayMode: displayMode broadcast: YES]; +} + +- (void) setSelectedItemIdentifier: (NSString *)itemIdentifier +{ + +} + +- (void) setSizeMode: (NSToolbarSizeMode)sizeMode +{ + +} + +- (void) setVisible: (BOOL)shown +{ + [self _setVisible: shown broadcast: NO]; +} + +- (NSToolbarSizeMode) sizeMode +{ + return 0; +} + +// Private methods + +- (void) _build +{ + /* + * toolbar build : + * will use the delegate when there is no toolbar model + */ + + NSToolbar *toolbarModel; + NSArray *wantedItemIdentifiers; + NSEnumerator *e; + id itemIdentifier; + int i = 0; + + _build = YES; + + RELEASE(_items); + _items = [[NSMutableArray alloc] init]; + + toolbarModel = [[NSToolbar _toolbarsForIdentifier: _identifier] objectAtIndex: 0]; + if (toolbarModel != nil && toolbarModel != self) + { + wantedItemIdentifiers = [[toolbarModel items] valueForKey: @"itemIdentifier"]; + } + else + { + wantedItemIdentifiers = [_delegate toolbarDefaultItemIdentifiers:self]; + } + + e = [wantedItemIdentifiers objectEnumerator]; + while ((itemIdentifier = [e nextObject]) != nil) + { + [self _insertItemWithItemIdentifier: itemIdentifier atIndex: i broadcast: NO]; + i++; + } + + _build = NO; +} + - (void) _loadConfig { if(_identifier != nil) @@ -165,156 +410,192 @@ static const int current_version = 1; } } -- (id) initWithIdentifier: (NSString*)identifier -{ - [super init]; +/* + * + * The methods below handles the toolbar edition and broacasts each associated event + * to the other toolbars with identical identifiers. + * + */ - _customizationPaletteIsRunning = NO; - _allowsUserCustomization = NO; - _autosavesConfiguration = NO; - _configurationDictionary = nil; - _delegate = nil; - _displayMode = NSToolbarDisplayModeDefault; - _visible = YES; - _items = nil; - _visibleItems = nil; - ASSIGN(_identifier, identifier); - [self _loadConfig]; - - return self; -} - -- (void) dealloc -{ - DESTROY (_identifier); - DESTROY (_configurationDictionary); - - if (_delegate != nil) - { - [nc removeObserver: _delegate name: nil object: self]; - _delegate = nil; +#define TRANSMIT(signature) \ + NSEnumerator *e = [[NSToolbar _toolbarsForIdentifier: _identifier] objectEnumerator]; \ + NSToolbar *toolbar; \ + \ + while ((toolbar = [e nextObject]) != nil) \ + { \ + if (toolbar != self) \ + [toolbar signature]; \ } - [super dealloc]; -} - - -- (void) insertItemWithItemIdentifier: (NSString *)itemIdentifier - atIndex: (int)index +- (void) _insertItemWithItemIdentifier: (NSString *)itemIdentifier atIndex: (int)index broadcast: (BOOL)broadcast { NSToolbarItem *item = nil; NSArray *allowedItems = [_delegate toolbarAllowedItemIdentifiers: self]; + if([allowedItems containsObject: itemIdentifier]) { item = [_delegate toolbar: self - itemForItemIdentifier: itemIdentifier - willBeInsertedIntoToolbar: YES]; - [nc postNotificationName: NSToolbarWillAddItemNotification - object: self]; - [_items insertObject: item atIndex: index]; - } + itemForItemIdentifier: itemIdentifier + willBeInsertedIntoToolbar: YES]; + + if (item != nil) + { + [nc postNotificationName: NSToolbarWillAddItemNotification object: self]; + [item _setToolbar: self]; + [_items insertObject: item atIndex: index]; + if (!_build) // we reload the toolbarView each time a new item is added except when we build/create the toolbar + [_toolbarView _reload]; + + if (broadcast) + { + TRANSMIT(_insertItemWithItemIdentifier: itemIdentifier atIndex: index broadcast: NO); + } + } + } + } -- (BOOL) isVisible -{ - return _visible; -} - -- (NSArray *) items -{ - return _items; -} - -- (void) removeItemAtIndex: (int)index +- (void) _removeItemAtIndex: (int)index broadcast: (BOOL)broadcast { - id obj = [_items objectAtIndex: index]; [_items removeObjectAtIndex: index]; - [_visibleItems removeObject: obj]; + [_toolbarView _reload]; [nc postNotificationName: NSToolbarDidRemoveItemNotification object: self]; -} -- (void) runCustomizationPalette: (id)sender -{ - _customizationPaletteIsRunning = [NSBundle loadNibNamed: @"GSToolbarCustomizationPalette" - owner: self]; - if(!_customizationPaletteIsRunning) + if (broadcast) { - NSLog(@"Failed to load gorm for GSToolbarCustomizationPalette"); + TRANSMIT(_removeItemAtIndex: index broadcast: NO); } } -- (void) setAllowsUserCustomization: (BOOL)flag +- (void) _setAllowsUserCustomization: (BOOL)flag broadcast: (BOOL)broadcast { _allowsUserCustomization = flag; + + if (broadcast) + { + TRANSMIT(_setAllowsUserCustomization: _allowsUserCustomization broadcast: NO); + } } -- (void) setAutosavesConfiguration: (BOOL)flag +- (void) _setAutosavesConfiguration: (BOOL)flag broadcast: (BOOL)broadcast { _autosavesConfiguration = flag; + + if (broadcast) + { + TRANSMIT(_setAutosavesConfiguration: _autosavesConfiguration broadcast: NO); + } } -- (void) setConfigurationFromDictionary: (NSDictionary *)configDict +- (void) _setConfigurationFromDictionary: (NSDictionary *)configDict broadcast: (BOOL)broadcast { ASSIGN(_configurationDictionary, configDict); + + if (broadcast) + { + TRANSMIT(_setConfigurationFromDictionary: _configurationDictionary broadcast: NO); + } } -/** - * Sets the receivers delgate ... this is the object which will receive - * -toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar: - * -toolbarAllowedItemIdentifiers: and -toolbarDefaultItemIdentifiers: - * messages. - */ -- (void) setDelegate: (id)delegate -{ -#define CHECK_REQUIRED_METHOD(selector_name) \ +- (void) _setDisplayMode: (NSToolbarDisplayMode)displayMode broadcast: (BOOL)broadcast +{ + _displayMode = displayMode; + + if (broadcast) + { + TRANSMIT(_setDisplayMode: _displayMode broadcast: NO); + } +} + +- (void) _setVisible: (BOOL)shown broadcast: (BOOL)broadcast +{ + if (_visible != shown) + { + if (_window) + { + if (shown) + [_toolbarView _setWillBeVisible: YES]; + + [_window toggleToolbarShown: self]; + + [_toolbarView _setWillBeVisible: NO]; + _visible = shown; + // Important to set _visible after the toolbar has been toggled + // because NSWindow method contentViewWithoutToolbar uses [NSToolbar visible] + // when we toggle the toolbar + } + else + { + NSLog(@"setVisible: doesn't work because the toolbar is not a window toolbar."); + } + } + + if (broadcast) + { + TRANSMIT(_setVisible: _visible broadcast: NO); + } +} + +- (void)_setDelegate: (id)delegate broadcast: (BOOL)broadcast +{ + #define CHECK_REQUIRED_METHOD(selector_name) \ if (![delegate respondsToSelector: @selector(selector_name)]) \ [NSException raise: NSInternalInconsistencyException \ - format: @"delegate does not respond to %@",@#selector_name] + format: @"delegate does not respond to %@",@#selector_name] CHECK_REQUIRED_METHOD(toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar:); CHECK_REQUIRED_METHOD(toolbarAllowedItemIdentifiers:); CHECK_REQUIRED_METHOD(toolbarDefaultItemIdentifiers:); - if (_delegate) + if (_delegate) [nc removeObserver: _delegate name: nil object: self]; _delegate = delegate; - -#define SET_DELEGATE_NOTIFICATION(notif_name) \ + #define SET_DELEGATE_NOTIFICATION(notif_name) \ if ([_delegate respondsToSelector: @selector(toolbar##notif_name:)]) \ [nc addObserver: _delegate \ - selector: @selector(toolbar##notif_name:) \ - name: NSToolbar##notif_name##Notification object: self] + selector: @selector(toolbar##notif_name:) \ + name: NSToolbar##notif_name##Notification object: self] SET_DELEGATE_NOTIFICATION(DidRemoveItem); SET_DELEGATE_NOTIFICATION(WillAddItem); -} - -- (void) setDisplayMode: (NSToolbarDisplayMode)displayMode -{ - _displayMode = displayMode; -} - -- (void) setVisible: (BOOL)shown -{ - _visible = shown; -} - -- (void) validateVisibleItems -{ - NSEnumerator *en = [_visibleItems objectEnumerator]; - NSToolbarItem *item = nil; - - while((item = [en nextObject]) != nil) + + if (_window != nil) // The delegate should be called when the toolbar will become visible (= window not nil) { - [item validate]; + [self _build]; // Build the toolbar with the delegate or a toolbar model + [_toolbarView _reload]; } + + // broadcast now... + + if (broadcast) + { + TRANSMIT(_setDelegate: _delegate broadcast: NO); + } } -- (NSArray *) visibleItems +// Private Accessors + +- (void) _setToolbarView: (GSToolbarView *)toolbarView { - return _visibleItems; + ASSIGN(_toolbarView, toolbarView); } -@end /* interface of NSToolbar */ + +- (GSToolbarView *) _toolbarView +{ + return _toolbarView; +} + +- (void)_setWindow: (NSWindow *)window +{ + ASSIGN(_window, window); // call [NSWindow(Toolbar) setToolbar:] to set the toolbar window +} + +- (NSWindow *) _window +{ + return _window; +} + +@end diff --git a/Source/NSToolbarItem.m b/Source/NSToolbarItem.m index 55c07c370..83be96d88 100644 --- a/Source/NSToolbarItem.m +++ b/Source/NSToolbarItem.m @@ -29,11 +29,393 @@ #include #include +#include + #include "AppKit/NSToolbarItem.h" #include "AppKit/NSToolbar.h" +#include "AppKit/NSMenu.h" #include "AppKit/NSMenuItem.h" #include "AppKit/NSImage.h" #include "AppKit/NSButton.h" +#include "AppKit/NSFont.h" +#include "AppKit/NSEvent.h" +#include "GNUstepGUI/GSToolbarView.h" + +/* + * Each NSToolbarItem object are coupled with a backView which is their representation + * on the screen. + * backView for the standard toolbar item (without custom view) are NSButton subclass + * called GSToolbarButton. + * backView for the toolbar item with a custom view are NSView subclass called + * GSToolbarBackView. + * GSToolbarButton and GSToolbarBackView are adjusted according to their content and + * their title when the method layout is called. + * The predefined GNUstep toolbar items are implemented with a class cluster pattern : + * initWithToolbarItemIdentifier: returns differents concrete subclass in accordance + * with the item identifier. + */ + +@interface NSToolbar (GNUstepPrivate) +- (GSToolbarView *) _toolbarView; +@end + +@interface NSToolbarItem (GNUstepPrivate) +- (void) _layout; +- (NSView *) _backView; +- (BOOL) _isUpdated; +- (BOOL) _isFlexibleSpace; +- (void) _setToolbar: (NSToolbar *)toolbar; +@end + +@interface GSToolbarView (GNUstepPrivate) +- (void) _reload; +@end + +/* + * NSButton subclass is the toolbar buttons _backView + */ +@interface GSToolbarButton : NSButton +{ + NSToolbarItem *_toolbarItem; +} + +- (id) initWithToolbarItem: (NSToolbarItem *)toolbarItem; +- (void) layout; +- (NSToolbarItem *) toolbarItem; +@end + +@implementation GSToolbarButton +- (id) initWithToolbarItem: (NSToolbarItem *)toolbarItem +{ + self = [super initWithFrame: NSMakeRect(_ItemBackViewX, _ItemBackViewY, _ItemBackViewDefaultWidth, _ItemBackViewDefaultHeight)]; + if (self != nil) + { + ASSIGN(_toolbarItem, toolbarItem); + } + return self; +} + +- (void) layout +{ + float textWidth, layoutedWidth; + NSAttributedString *attrStr; + NSDictionary *attr; + NSFont *font =[NSFont systemFontOfSize: 11]; // [NSFont smallSystemFontSize] or better should NSControlContentFontSize + + attr = [NSDictionary dictionaryWithObject: font forKey: @"NSFontAttributeName"]; + attrStr = [[NSAttributedString alloc] initWithString: [_toolbarItem label] attributes: attr]; + + textWidth = [attrStr size].width + 2 * _InsetItemTextX; + if (textWidth > _ItemBackViewDefaultWidth) + { + layoutedWidth = textWidth; + } + else + { + layoutedWidth = _ItemBackViewDefaultWidth; + } + + [self setFrameSize: NSMakeSize(layoutedWidth, _ItemBackViewDefaultHeight)]; + +} + +- (NSToolbarItem *) toolbarItem +{ + return _toolbarItem; +} +@end + +/* + * Back view used to enclose toolbar item's custom view + */ +@interface GSToolbarBackView : NSView +{ + NSToolbarItem *_toolbarItem; + BOOL _enabled; +} + +- (id) initWithToolbarItem: (NSToolbarItem *)toolbarItem; +- (NSToolbarItem *) toolbarItem; +- (void) setEnabled: (BOOL)enabled; +@end + +@implementation GSToolbarBackView + +- (id)initWithToolbarItem: (NSToolbarItem *)toolbarItem +{ + self = [super initWithFrame: NSMakeRect(_ItemBackViewX, _ItemBackViewY, _ItemBackViewDefaultWidth, + _ItemBackViewDefaultHeight)]; + + if (self != nil) + { + ASSIGN(_toolbarItem, toolbarItem); + } + + return self; +} + +- (void)drawRect: (NSRect)rect +{ + NSAttributedString *attrString; + NSDictionary *attr; + NSFont *font = [NSFont systemFontOfSize: 11]; // [NSFont smallSystemFontSize] or better should be NSControlContentFontSize + int textX; + + [super drawRect: rect]; // We draw _view which is a subview + + if (_enabled) + { + [[NSColor blackColor] set]; + } + else + { + [[NSColor grayColor] set]; + } + + attr = [NSDictionary dictionaryWithObject: font forKey: @"NSFontAttributeName"]; + attrString = [[NSAttributedString alloc] initWithString: [_toolbarItem label] attributes: attr]; // we draw the label + textX = (([self frame].size.width - _InsetItemTextX) - [attrString size].width) / 2; + [attrString drawAtPoint: NSMakePoint(textX, _InsetItemTextY)]; +} + +- (void) layout +{ + NSView *view; + float textWidth; + NSAttributedString *attrStr; + NSDictionary *attr; + NSFont *font = [NSFont systemFontOfSize: 11]; // [NSFont smallSystemFontSize] or better should be NSControlContentFontSize + + view = [_toolbarItem view]; + + if ([view frame].size.height <= _ItemBackViewDefaultHeight) + { + [view setFrameOrigin: NSMakePoint(_InsetItemViewX, _InsetItemViewY)]; + [self addSubview: view]; + } + else + { + [view removeFromSuperview]; + } + + [self setFrameSize: NSMakeSize([view frame].size.width + 2 * _InsetItemViewX, _ItemBackViewDefaultHeight)]; + + attr = [NSDictionary dictionaryWithObject: font forKey: @"NSFontAttributeName"]; + attrStr = [[NSAttributedString alloc] initWithString: [_toolbarItem label] attributes: attr]; + + textWidth = [attrStr size].width + 2 * _InsetItemTextX; + if (textWidth > [self frame].size.width) + { + [self setFrameSize: NSMakeSize(textWidth, _ItemBackViewDefaultHeight)]; + [view setFrameOrigin: NSMakePoint((textWidth - [view frame].size.width) / 2, _InsetItemViewY)]; + } +} + +- (NSToolbarItem *)toolbarItem +{ + return _toolbarItem; +} + +- (void) setEnabled: (BOOL)enabled +{ + id view = [_toolbarItem view]; + + _enabled = enabled; + if ([view respondsToSelector: @selector(setEnabled:)]) + { + [view setEnabled: enabled]; + } +} + +@end + +/* + * + * Standard toolbar items. + * + */ + +// ---- NSToolbarSeparatorItemIdentifier +@interface GSToolbarSeparatorItem : NSToolbarItem +{ +} +@end + +@implementation GSToolbarSeparatorItem +- (id) initWithItemIdentifier: (NSString *)itemIdentifier +{ + NSImage *image = [NSImage imageNamed: @"common_ToolbarSeperatorItem"]; + + self = [super initWithItemIdentifier: itemIdentifier]; + [(NSButton *)[self _backView] setImagePosition: NSImageOnly]; + [(NSButton *)[self _backView] setImage: image]; + // We bypass the toolbar item accessor to set the image in order to have it (48 * 48) not resized + + [[self _backView] setFrameSize: NSMakeSize(15, _ItemBackViewDefaultHeight)]; + + return self; +} + +- (NSMenuItem *) menuFormRepresentation +{ + return nil; // override the default implementation in order to do nothing +} + +- (void) _layout +{ + // override the default implementation in order to do nothing +} +@end + +// ---- NSToolbarSpaceItemIdentifier +@interface GSToolbarSpaceItem : NSToolbarItem +{ +} +@end + +@implementation GSToolbarSpaceItem +- (id) initWithItemIdentifier: (NSString *)itemIdentifier +{ + self = [super initWithItemIdentifier: itemIdentifier]; + [self setLabel: @""]; + + return self; +} + +- (NSMenuItem *) menuFormRepresentation +{ + return nil;// override the default implementation in order to do nothing +} + +- (void) _layout +{ + // override the default implementation in order to do nothing +} +@end + +// ---- NSToolbarFlexibleSpaceItemIdentifier +@interface GSToolbarFlexibleSpaceItem : NSToolbarItem +{ +} +@end + +@implementation GSToolbarFlexibleSpaceItem +- (id) initWithItemIdentifier: (NSString *)itemIdentifier +{ + self = [super initWithItemIdentifier: itemIdentifier]; + [self setLabel: @""]; + [self _layout]; + + return self; +} + +- (NSMenuItem *) menuFormRepresentation +{ + return nil;// override the default implementation in order to do nothing +} + +- (void) _layout +{ + NSView *backView = [self _backView]; + + [backView setFrameSize: NSMakeSize(0, [backView frame].size.height)]; + + // override the default implementation in order to reset the _backView to a zero width +} +@end + +// ---- NSToolbarShowColorsItemIdentifier +@interface GSToolbarShowColorsItem : NSToolbarItem +{ +} +@end + +@implementation GSToolbarShowColorsItem +- (id) initWithItemIdentifier: (NSString *)itemIdentifier +{ + NSImage *image = [NSImage imageNamed: @"common_ToolbarShowColorsItem"]; + + self = [super initWithItemIdentifier: itemIdentifier]; + [self setImage: image]; + [self setLabel: @"Colors"]; + + // set action... + [self setTarget: nil]; // goes to first responder.. + [self setAction: @selector(orderFrontColorPanel:)]; + + return self; +} +@end + +// ---- NSToolbarShowFontsItemIdentifier +@interface GSToolbarShowFontsItem : NSToolbarItem +{ +} +@end + +@implementation GSToolbarShowFontsItem +- (id) initWithItemIdentifier: (NSString *)itemIdentifier +{ + NSImage *image = [NSImage imageNamed: @"common_ToolbarShowFontsItem"]; + + self = [super initWithItemIdentifier: itemIdentifier]; + [self setImage: image]; + [self setLabel: @"Fonts"]; + + // set action... + [self setTarget: nil]; // goes to first responder.. + [self setAction: @selector(orderFrontFontPanel:)]; + + return self; +} +@end + +// ---- NSToolbarCustomizeToolbarItemIdentifier +@interface GSToolbarCustomizeToolbarItem : NSToolbarItem +{ +} +@end + +@implementation GSToolbarCustomizeToolbarItem +- (id) initWithItemIdentifier: (NSString *)itemIdentifier +{ + NSImage *image = [NSImage imageNamed: @"common_ToolbarCustomizeToolbarItem"]; + + self = [super initWithItemIdentifier: itemIdentifier]; + [self setImage: image]; + [self setLabel: @"Customize"]; + + // set action... + [self setTarget: nil]; // goes to first responder.. + [self setAction: @selector(runCustomizationPalette:)]; + + return self; +} +@end + +// ---- NSToolbarPrintItemIdentifier +@interface GSToolbarPrintItem : NSToolbarItem +{ +} +@end + +@implementation GSToolbarPrintItem +- (id) initWithItemIdentifier: (NSString *)itemIdentifier +{ + NSImage *image = [NSImage imageNamed: @"common_Printer"]; + + self = [super initWithItemIdentifier: itemIdentifier]; + [self setImage: image]; + [self setLabel: @"Print..."]; + + // set action... + [self setTarget: nil]; // goes to first responder.. + [self setAction: @selector(print:)]; + + return self; +} +@end + @implementation NSToolbarItem - (BOOL)allowsDuplicatesInToolbar @@ -45,14 +427,105 @@ { if(_flags._image) { - return [_view image]; + return [(id)_backView image]; } return nil; } - (id)initWithItemIdentifier: (NSString *)itemIdentifier { - ASSIGN(_itemIdentifier,itemIdentifier); + GSToolbarButton *button; + NSButtonCell *cell; + + if ((self = [super init]) != nil) + { + + // GNUstep predefined toolbar items + + if ([itemIdentifier isEqualToString: @"NSToolbarSeparatorItemIdentifier"] + && ![self isKindOfClass:[GSToolbarSeparatorItem class]]) + { + [self release]; + self = [[GSToolbarSeparatorItem alloc] initWithItemIdentifier: itemIdentifier]; + } + + else if ([itemIdentifier isEqualToString: @"NSToolbarSpaceItemIdentifier"] + && ![self isKindOfClass:[GSToolbarSpaceItem class]]) + { + [self release]; + self = [[GSToolbarSpaceItem alloc] initWithItemIdentifier: itemIdentifier]; + } + + else if ([itemIdentifier isEqualToString: @"NSToolbarFlexibleSpaceItemIdentifier"] + && ![self isKindOfClass:[GSToolbarFlexibleSpaceItem class]]) + { + [self release]; + self = [[GSToolbarFlexibleSpaceItem alloc] initWithItemIdentifier: itemIdentifier]; + } + + else if ([itemIdentifier isEqualToString: @"NSToolbarShowColorsItemIdentifier"] + && ![self isKindOfClass:[GSToolbarShowColorsItem class]]) + { + [self release]; + self = [[GSToolbarShowColorsItem alloc] initWithItemIdentifier: itemIdentifier]; + } + + else if ([itemIdentifier isEqualToString: @"NSToolbarShowFontsItemIdentifier"] + && ![self isKindOfClass:[GSToolbarShowFontsItem class]]) + { + [self release]; + self = [[GSToolbarShowFontsItem alloc] initWithItemIdentifier: itemIdentifier]; + } + + else if ([itemIdentifier isEqualToString: @"NSToolbarCustomizeToolbarItemIdentifier"] + && ![self isKindOfClass:[GSToolbarCustomizeToolbarItem class]]) + { + [self release]; + self = [[GSToolbarCustomizeToolbarItem alloc] initWithItemIdentifier: itemIdentifier]; + } + + else if ([itemIdentifier isEqualToString: @"NSToolbarPrintItemIdentifier"] + && ![self isKindOfClass:[GSToolbarPrintItem class]]) + { + [self release]; + self = [[GSToolbarPrintItem alloc] initWithItemIdentifier: itemIdentifier]; + } + + // Normal toolbar items + else + { + + ASSIGN(_itemIdentifier, itemIdentifier); + + button = [[GSToolbarButton alloc] initWithToolbarItem: self]; + cell = [button cell]; + [button setTitle: @""]; + [button setEnabled: NO]; + [button setBordered: NO]; + [button setImagePosition: NSImageAbove]; + [cell setBezeled: YES]; + [cell setHighlightsBy: NSChangeGrayCellMask | NSChangeBackgroundCellMask]; + [cell setFont: [NSFont systemFontOfSize: 11]]; // [NSFont smallSystemFontSize] or better should be controlContentFontSize + + [_backView release]; + _backView = button; + } + + // gets + _flags._isEnabled = [_backView respondsToSelector: @selector(isEnabled)]; + _flags._tag = YES; + _flags._action = [_backView respondsToSelector: @selector(action)]; + _flags._target = [_backView respondsToSelector: @selector(target)]; + _flags._image = [_backView respondsToSelector: @selector(image)]; + // sets + _flags._setEnabled = [_backView respondsToSelector: @selector(setEnabled:)]; + _flags._setTag = YES; + _flags._setAction = [_backView respondsToSelector: @selector(setAction:)]; + _flags._setTarget = [_backView respondsToSelector: @selector(setTarget:)]; + _flags._setImage = [_backView respondsToSelector: @selector(setImage:)]; + + } + return self; } @@ -60,7 +533,7 @@ { if(_flags._isEnabled) { - return [_view isEnabled]; + return [(id)_backView isEnabled]; } return NO; } @@ -82,7 +555,22 @@ - (NSMenuItem *)menuFormRepresentation { - return _menuFormRepresentation; + NSMenuItem *menuItem; + + if (_menuFormRepresentation == nil) + { + menuItem = [[NSMenuItem alloc] initWithTitle: [self label] + action: [self action] + keyEquivalent: @""]; + [menuItem setTarget: [self target]]; + AUTORELEASE(menuItem); + } + else + { + menuItem = [_menuFormRepresentation copy]; + } + + return menuItem; } - (NSSize)minSize @@ -99,29 +587,49 @@ { if(_flags._setAction) { - [_view setAction: action]; + if ([_backView isKindOfClass: [NSButton class]]) + [(NSButton *)_backView setAction: action]; + if (action != NULL) + { + [(NSButton *)_backView setEnabled: YES]; + } + else + { + [(NSButton *)_backView setEnabled: NO]; + } } } - (void)setEnabled: (BOOL)enabled { if(_flags._setEnabled) - { - [_view setEnabled: enabled]; - } + [(id)_backView setEnabled: enabled]; } - (void)setImage: (NSImage *)image { if(_flags._setImage) - { - [_view setImage: image]; + { + ASSIGN(_image, image); + + [_image setScalesWhenResized: YES]; + [_image setSize: NSMakeSize(32, 32)]; + + if ([_backView isKindOfClass: [NSButton class]]) + [(NSButton *)_backView setImage: _image]; } } - (void)setLabel: (NSString *)label { ASSIGN(_label, label); + + if ([_backView isKindOfClass: [NSButton class]]) + [(NSButton *)_backView setTitle:_label]; + + _updated = YES; + if (_toolbar != nil) + [[_toolbar _toolbarView] _reload]; } - (void)setMaxSize: (NSSize)maxSize @@ -147,17 +655,16 @@ - (void)setTag: (int)tag { if(_flags._tag) - { - [_view setTag: tag]; - } + [_backView setTag: tag]; } - (void)setTarget: (id)target - { +{ if(_flags._target) - { - [_view setTarget: target]; - } + { + if ([_backView isKindOfClass: [NSButton class]]) + [(NSButton *)_backView setTarget: target]; + } } - (void)setToolTip: (NSString *)toolTip @@ -168,26 +675,43 @@ - (void)setView: (NSView *)view { ASSIGN(_view, view); - // gets - _flags._isEnabled = [_view respondsToSelector: @selector(isEnabled)]; - _flags._tag = [_view respondsToSelector: @selector(tag)]; - _flags._action = [_view respondsToSelector: @selector(action)]; - _flags._target = [_view respondsToSelector: @selector(target)]; - _flags._image = [_view respondsToSelector: @selector(image)]; - // sets - _flags._setEnabled = [_view respondsToSelector: @selector(setEnabled:)]; - _flags._setTag = [_view respondsToSelector: @selector(setTag:)]; - _flags._setAction = [_view respondsToSelector: @selector(setAction:)]; - _flags._setTarget = [_view respondsToSelector: @selector(setTarget:)]; - _flags._setImage = [_view respondsToSelector: @selector(setImage:)]; + + if (_view == nil) + { + // gets + _flags._isEnabled = [_backView respondsToSelector: @selector(isEnabled)]; + _flags._action = [_backView respondsToSelector: @selector(action)]; + _flags._target = [_backView respondsToSelector: @selector(target)]; + _flags._image = [_backView respondsToSelector: @selector(image)]; + // sets + _flags._setEnabled = [_backView respondsToSelector: @selector(setEnabled:)]; + _flags._setAction = [_backView respondsToSelector: @selector(setAction:)]; + _flags._setTarget = [_backView respondsToSelector: @selector(setTarget:)]; + _flags._setImage = [_backView respondsToSelector: @selector(setImage:)]; + } + else + { + // gets + _flags._isEnabled = [_view respondsToSelector: @selector(isEnabled)]; + _flags._action = [_view respondsToSelector: @selector(action)]; + _flags._target = [_view respondsToSelector: @selector(target)]; + _flags._image = [_backView respondsToSelector: @selector(image)]; + // sets + _flags._setEnabled = [_view respondsToSelector: @selector(setEnabled:)]; + _flags._setAction = [_view respondsToSelector: @selector(setAction:)]; + _flags._setTarget = [_view respondsToSelector: @selector(setTarget:)]; + _flags._setImage = [_backView respondsToSelector: @selector(setImage:)]; + } + + [_backView release]; + _backView = [[GSToolbarBackView alloc] initWithToolbarItem: self]; } - (int)tag { if(_flags._tag) - { - return [_view tag]; - } + return [_backView tag]; + return 0; } @@ -212,12 +736,40 @@ return _view; } +// Private or package like visibility methods + +- (NSView *)_backView +{ + return _backView; +} + +- (void) _layout +{ + [(id)_backView layout]; +} + +- (BOOL)_isUpdated +{ + return _updated; +} + +- (BOOL)_isFlexibleSpace +{ + return [self isKindOfClass: [GSToolbarFlexibleSpaceItem class]]; +} + +- (void) _setToolbar: (NSToolbar *)toolbar +{ + ASSIGN(_toolbar, toolbar); +} + // NSValidatedUserInterfaceItem protocol - (SEL)action { if(_flags._action) { - return [_view action]; + if ([_backView isKindOfClass: [NSButton class]]) + return [(NSButton *)_backView action]; } return 0; } @@ -226,8 +778,10 @@ { if(_flags._target) { - return [_view target]; + if ([_backView isKindOfClass: [NSButton class]]) + return [(NSButton *)_backView target]; } + return nil; } @@ -251,166 +805,3 @@ return self; } @end - -/* - * - * Standard toolbar items. - * - */ - -// ---- NSToolbarSeperatorItemIdentifier -@interface GSToolbarSeperatorItem : NSToolbarItem -{ -} -@end - -@implementation GSToolbarSeperatorItem -- (id) initWithItemIdentifier: (NSString *)itemIdentifier -{ - NSImage *image = [NSImage imageNamed: @"common_ToolbarSeperatorItem"]; - NSButton *button = [[NSButton alloc] initWithFrame: NSMakeRect(0,0,48,48)]; - [button setBordered: NO]; - [super initWithItemIdentifier: itemIdentifier]; - [self setView: button]; - [self setImage: image]; - return self; -} -@end - -// ---- NSToolbarSpaceItemIdentifier -@interface GSToolbarSpaceItem : NSToolbarItem -{ -} -@end - -@implementation GSToolbarSpaceItem -- (id) initWithItemIdentifier: (NSString *)itemIdentifier -{ - NSImage *image = [NSImage imageNamed: @"common_ToolbarSpaceItem"]; - NSButton *button = [[NSButton alloc] initWithFrame: NSMakeRect(0,0,48,48)]; - [button setBordered: NO]; - [super initWithItemIdentifier: itemIdentifier]; - [self setView: button]; - [self setImage: image]; - return self; -} -@end - -// ---- NSToolbarFlexibleSpaceItemIdentifier -@interface GSToolbarFlexibleSpaceItem : NSToolbarItem -{ -} -@end - -@implementation GSToolbarFlexibleSpaceItem -- (id) initWithItemIdentifier: (NSString *)itemIdentifier -{ - NSImage *image = [NSImage imageNamed: @"common_ToolbarFlexibleSpaceItem"]; - NSButton *button = [[NSButton alloc] initWithFrame: NSMakeRect(0,0,48,48)]; - [button setBordered: NO]; - [super initWithItemIdentifier: itemIdentifier]; - [self setView: button]; - [self setImage: image]; - return self; -} -@end - -// ---- NSToolbarShowColorsItemIdentifier -@interface GSToolbarShowColorsItem : NSToolbarItem -{ -} -@end - -@implementation GSToolbarShowColorsItem -- (id) initWithItemIdentifier: (NSString *)itemIdentifier -{ - NSImage *image = [NSImage imageNamed: @"common_ToolbarShowColorsItem"]; - NSButton *button = [[NSButton alloc] initWithFrame: NSMakeRect(0,0,48,48)]; - [button setBordered: YES]; - [super initWithItemIdentifier: itemIdentifier]; - [self setView: button]; - [self setImage: image]; - - // set action... - [self setTarget: nil]; // goes to first responder.. - [self setAction: @selector(orderFrontColorPanel:)]; - - // return - return self; -} -@end - -// ---- NSToolbarShowFontsItemIdentifier -@interface GSToolbarShowFontsItem : NSToolbarItem -{ -} -@end - -@implementation GSToolbarShowFontsItem -- (id) initWithItemIdentifier: (NSString *)itemIdentifier -{ - NSImage *image = [NSImage imageNamed: @"common_ToolbarShowFontsItem"]; - NSButton *button = [[NSButton alloc] initWithFrame: NSMakeRect(0,0,48,48)]; - [button setBordered: YES]; - [super initWithItemIdentifier: itemIdentifier]; - [self setView: button]; - [self setImage: image]; - - // set action... - [self setTarget: nil]; // goes to first responder.. - [self setAction: @selector(orderFrontFontPanel:)]; - - // return - return self; -} -@end - -// ---- NSToolbarCustomizeToolbarItemIdentifier -@interface GSToolbarCustomizeToolbarItem : NSToolbarItem -{ -} -@end - -@implementation GSToolbarCustomizeToolbarItem -- (id) initWithItemIdentifier: (NSString *)itemIdentifier -{ - NSImage *image = [NSImage imageNamed: @"common_ToolbarCustomizeToolbarItem"]; - NSButton *button = [[NSButton alloc] initWithFrame: NSMakeRect(0,0,48,48)]; - [button setBordered: YES]; - [super initWithItemIdentifier: itemIdentifier]; - [self setView: button]; - [self setImage: image]; - - // set action... - [self setTarget: nil]; // goes to first responder.. - [self setAction: @selector(runCustomizationPalette:)]; - - // return - return self; -} -@end - -// ---- NSToolbarPrintItemIdentifier -@interface GSToolbarPrintItem : NSToolbarItem -{ -} -@end - -@implementation GSToolbarPrintItem -- (id) initWithItemIdentifier: (NSString *)itemIdentifier -{ - NSImage *image = [NSImage imageNamed: @"common_Printer"]; - NSButton *button = [[NSButton alloc] initWithFrame: NSMakeRect(0,0,48,48)]; - [super initWithItemIdentifier: itemIdentifier]; - [button setBordered: YES]; - [self setView: button]; - [self setImage: image]; - - // set action... - [self setTarget: nil]; // goes to first responder.. - [self setAction: @selector(print:)]; - - // return - return self; -} -@end diff --git a/Source/NSWindow+Toolbar.h b/Source/NSWindow+Toolbar.h new file mode 100644 index 000000000..ee738b8d5 --- /dev/null +++ b/Source/NSWindow+Toolbar.h @@ -0,0 +1,45 @@ +/* + NSWindow+Toolbar.h + + The window toolbar category + + Copyright (C) 2004 Free Software Foundation, Inc. + + Author: Quentin Mathé + Date: January 2004 + + This file is part of the GNUstep GUI Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _GNUstep_H_NSWindow_Toolbar +#define _GNUstep_H_NSWindow_Toolbar + +#include "AppKit/NSWindow.h" + +@class NSToolbar; + +@interface NSWindow (Toolbar) +- (void) runToolbarCustomizationPalette: (id)sender; +- (void) toggleToolbarShown: (id)sender; +- (NSView *) contentViewWithoutToolbar; +- (NSToolbar *) toolbar; +- (void) setContentViewWithoutToolbar: (NSView *)contentViewWithoutToolbar; +- (void) setToolbar: (NSToolbar*)toolbar; +@end + +#endif diff --git a/Source/NSWindow+Toolbar.m b/Source/NSWindow+Toolbar.m new file mode 100644 index 000000000..68e619553 --- /dev/null +++ b/Source/NSWindow+Toolbar.m @@ -0,0 +1,249 @@ +/** NSWindow+Toolbar + + The window class category to include toolbar support + + Copyright (C) 2004 Free Software Foundation, Inc. + + Author: Quentin Mathé + Date: January 2004 + + This file is part of the GNUstep GUI Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include +#include + +#include "NSWindow+Toolbar.h" +#include "AppKit/NSView.h" +#include "AppKit/NSToolbar.h" +#include "GNUstepGUI/GSToolbarView.h" + +static const int ToolbarHeight = 61; + +@interface NSToolbar (GNUstepPrivate) ++ (NSArray *) _toolbars; +- (GSToolbarView *) _toolbarView; +- (void) _setWindow: (NSWindow *)window; +- (NSWindow *) _window; +@end + +@interface GSToolbarView (GNUstepPrivate) +- (void) _handleViewsVisibility; +@end + +@interface NSWindow (ToolbarPrivate) +- (void) _toggleToolbarView: (GSToolbarView *)toolbarView display: (BOOL)flag; +@end + +@implementation NSWindow (Toolbar) + +- (void) runToolbarCustomizationPalette: (id)sender +{ + [[self toolbar] runCustomizationPalette: sender]; +} + +- (void) toggleToolbarShown: (id)sender +{ + NSToolbar *toolbar = [self toolbar]; + + if ([sender isEqual: toolbar]) // we can enter this branch when the toolbar class has called +toggleToolbarShown: + { + [self _toggleToolbarView: [toolbar _toolbarView] display: YES]; + } + else + { + // we call the toolbar class letting it call back on toggleToolbarShown: + [toolbar setVisible: ![toolbar isVisible]]; + } + +} + +// Accessors + +- (NSView *) contentViewWithoutToolbar +{ + NSToolbar *toolbar = [self toolbar]; + + if (toolbar != nil && [toolbar isVisible]) + { + NSArray *subviews = [_contentView subviews]; + id subview; + int i, n = [subviews count]; + GSToolbarView *toolbarView = [toolbar _toolbarView]; + + if (n > 2 || ![[toolbarView superview] isEqual: _contentView]) { + [NSException raise: @"_contentView error" + format: @"_contenView is not valid. _contentView needs a toolbar view and a contentViewWithoutToolbar, with no others subviews."]; + } + + for (i = 0; i < n; i++) + { + subview = [subviews objectAtIndex: i]; + if (![subview isEqual: toolbarView]) + { + return subview; + } + } + + return nil; + } + + return [self contentView]; +} + +- (NSToolbar *) toolbar +{ + NSArray *toolbars = [NSToolbar _toolbars]; + NSArray *windows; + unsigned index = 0; + + if (toolbars == nil) + return nil; + windows = [toolbars valueForKey: @"_window"]; + index = [windows indexOfObjectIdenticalTo: self]; + + return (index == NSNotFound) ? nil : [toolbars objectAtIndex: index]; +} + +- (void) setContentViewWithoutToolbar: (NSView *)contentViewWithoutToolbar // user oriented method +{ + NSToolbar *toolbar = [self toolbar]; + + if (toolbar != nil && [toolbar isVisible]) { + [_contentView replaceSubview: [self contentViewWithoutToolbar] with: contentViewWithoutToolbar]; + } + else + { + [self setContentView: contentViewWithoutToolbar]; + } +} + + +- (void) setToolbar: (NSToolbar*)toolbar +{ + NSToolbar *lastToolbar = [self toolbar]; + GSToolbarView *toolbarView = nil; + + if (lastToolbar != nil) + { + // we throw the last toolbar out + + [self _toggleToolbarView : [lastToolbar _toolbarView] display: NO]; + [lastToolbar _setWindow: nil]; + } + + // when there is no new toolbar + + if (toolbar == nil) + { + [self display]; // to show we have toggle the previous toolbar view + return; + } + + // ELSE + // the window want to know which toolbar is binded + + [toolbar _setWindow : self]; + + // insert the toolbar view (we create this view when the toolbar hasn't such view)... + + toolbarView = [toolbar _toolbarView]; + if (toolbarView == nil) + { + toolbarView = [[GSToolbarView alloc] initWithFrame: NSMakeRect(0, 0, 0, 0)]; + // _toggleToolbarView:display: method will set the toolbar view to the right frame + [toolbarView setAutoresizingMask: NSViewWidthSizable | NSViewMinYMargin]; + } + [toolbarView setBorderMask: GSToolbarViewBottomBorder]; + [self _toggleToolbarView: toolbarView display: YES]; + + // load the toolbar inside the toolbar view + + [toolbarView setToolbar: toolbar]; + +} + +// Private methods + +- (void) _toggleToolbarView: (GSToolbarView *)toolbarView display: (BOOL)flag { + NSRect windowFrame; + + if ([toolbarView superview] == nil) + { + NSView *contentViewWithoutToolbar; + NSRect contentViewWithoutToolbarFrame; + + contentViewWithoutToolbar = _contentView; + + // Switch the content view + + RETAIN(contentViewWithoutToolbar); + [self setContentView: [[NSView alloc] initWithFrame: [_contentView frame]]]; + + // Resize the window + + windowFrame = [self frame]; + [self setFrame: NSMakeRect(windowFrame.origin.x, windowFrame.origin.y - ToolbarHeight, windowFrame.size.width, + windowFrame.size.height + ToolbarHeight) display: flag]; + + // Plug the toolbar view + + contentViewWithoutToolbarFrame = [contentViewWithoutToolbar frame]; + [toolbarView setFrame: NSMakeRect(0, contentViewWithoutToolbarFrame.size.height, contentViewWithoutToolbarFrame.size.width, ToolbarHeight)]; + [_contentView addSubview: toolbarView]; + [toolbarView _handleViewsVisibility]; + [toolbarView setNextResponder: self]; + + // Insert the previous content view + + [_contentView addSubview: contentViewWithoutToolbar]; + RELEASE(contentViewWithoutToolbar); + } + else + { + NSView *contentViewWithoutToolbar; + + contentViewWithoutToolbar = [self contentViewWithoutToolbar]; + + // Unplug the toolbar view + + [toolbarView removeFromSuperview]; + + // Resize the window + + [contentViewWithoutToolbar setAutoresizingMask: NSViewMaxYMargin]; + + windowFrame = [self frame]; + [self setFrame: NSMakeRect(windowFrame.origin.x, windowFrame.origin.y + ToolbarHeight, + windowFrame.size.width, + windowFrame.size.height - ToolbarHeight) display: flag]; + + [contentViewWithoutToolbar setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable]; + // Autoresizing mask will be set again by the setContentView: method + + // Switch the content view + + RETAIN(contentViewWithoutToolbar); // because setContentView: will release the parent view and their subviews + [self setContentView: contentViewWithoutToolbar]; + RELEASE(contentViewWithoutToolbar); + } + +} + +@end