1/* 2 NSToolbarItem.m 3 4 The Toolbar item class. 5 6 Copyright (C) 2002 Free Software Foundation, Inc. 7 8 Author: Gregory John Casamento <greg_casamento@yahoo.com>, 9 Fabien Vallon <fabien.vallon@fr.alcove.com>, 10 Quentin Mathe <qmathe@club-internet.fr> 11 Date: May 2002 12 13 This file is part of the GNUstep GUI Library. 14 15 This library is free software; you can redistribute it and/or 16 modify it under the terms of the GNU Lesser General Public 17 License as published by the Free Software Foundation; either 18 version 2 of the License, or (at your option) any later version. 19 20 This library is distributed in the hope that it will be useful, 21 but WITHOUT ANY WARRANTY; without even the implied warranty of 22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 Lesser General Public License for more details. 24 25 You should have received a copy of the GNU Lesser General Public 26 License along with this library; see the file COPYING.LIB. 27 If not, see <http://www.gnu.org/licenses/> or write to the 28 Free Software Foundation, 51 Franklin Street, Fifth Floor, 29 Boston, MA 02110-1301, USA. 30*/ 31 32#import <Foundation/NSObject.h> 33#import <Foundation/NSArray.h> 34#import <Foundation/NSArchiver.h> 35#import <Foundation/NSDictionary.h> 36#import <Foundation/NSString.h> 37#import "AppKit/NSApplication.h" 38#import "AppKit/NSAttributedString.h" 39#import "AppKit/NSButton.h" 40#import "AppKit/NSButtonCell.h" 41#import "AppKit/NSDragging.h" 42#import "AppKit/NSEvent.h" 43#import "AppKit/NSFont.h" 44#import "AppKit/NSImage.h" 45#import "AppKit/NSMenu.h" 46#import "AppKit/NSMenuItem.h" 47#import "AppKit/NSParagraphStyle.h" 48#import "AppKit/NSPasteboard.h" 49#import "AppKit/NSStringDrawing.h" 50#import "AppKit/NSToolbar.h" 51#import "AppKit/NSView.h" 52#import "GNUstepGUI/GSToolbarView.h" 53#import "AppKit/NSToolbarItem.h" 54 55#import "NSToolbarFrameworkPrivate.h" 56#import "GSGuiPrivate.h" 57 58/* 59 * Each NSToolbarItem object are coupled with a backView which is their 60 * representation on the screen. 61 * backView for the standard toolbar item (without custom view) are NSButton 62 * subclass called GSToolbarButton. 63 * backView for the toolbar item with a custom view are NSView subclass called 64 * GSToolbarBackView. 65 * GSToolbarButton and GSToolbarBackView are adjusted according to their content 66 * and their title when the method layout is called. 67 * The predefined GNUstep toolbar items are implemented with a class cluster 68 * pattern: initWithToolbarItemIdentifier: returns differents concrete subclass 69 * in accordance with the item identifier. 70 */ 71 72typedef enum { 73 ItemBackViewDefaultHeight = 60, 74 ItemBackViewRegularHeight = 60, 75 ItemBackViewSmallHeight = 50 76} ItemBackViewHeight; 77 78typedef enum { 79 ItemBackViewDefaultWidth = 60, 80 ItemBackViewRegularWidth = 60, 81 ItemBackViewSmallWidth = 50 82} ItemBackViewWidth; 83 84static const int ItemBackViewX = 0; 85static const int ItemBackViewY = 0; 86static const int InsetItemViewX = 10; 87static const int InsetItemViewY = 26; 88static const int InsetItemTextX = 3; 89static const int InsetItemTextY = 4; 90 91// See NSToolbarItem -initialize method 92static NSFont *NormalFont = nil; 93static NSFont *SmallFont = nil; 94 95NSString *GSMovableToolbarItemPboardType = @"GSMovableToolbarItemPboardType"; 96 97/* 98 * NSButton subclass is the toolbar buttons _backView 99 */ 100@interface GSToolbarButton : NSButton 101{ 102 NSToolbarItem *_toolbarItem; 103} 104 105- (id) initWithToolbarItem: (NSToolbarItem *)toolbarItem; 106- (void) layout; 107 108// Accessors 109- (NSToolbarItem *) toolbarItem; 110@end 111 112@interface GSToolbarButtonCell : NSButtonCell 113{ 114 NSRect titleRect; 115 NSRect imageRect; 116} 117 118@end 119 120// --- 121 122@implementation GSToolbarButton 123 124+ (Class) cellClass 125{ 126 return [GSToolbarButtonCell class]; 127} 128 129- (id) initWithToolbarItem: (NSToolbarItem *)toolbarItem 130{ 131 // Frame will be reset by the layout method 132 self = [super initWithFrame: NSMakeRect(ItemBackViewX, ItemBackViewY, 133 ItemBackViewDefaultWidth, ItemBackViewDefaultHeight)]; 134 135 if (self != nil) 136 { 137 // Don't do an ASSIGN here, the toolbar item itself retains us. 138 _toolbarItem = toolbarItem; 139 140 [self setTitle: @""]; 141 [self setEnabled: NO]; 142 [_cell setBezeled: YES]; 143 [self setImagePosition: NSImageAbove]; 144 [self setHighlightsBy: 145 NSChangeGrayCellMask | NSChangeBackgroundCellMask]; 146 [self setFont: NormalFont]; 147 } 148 149 return self; 150} 151 152/* 153 * The code below should be kept in sync with GSToolbarBackView methods which 154 * have identical names. 155 */ 156 157- (void) layout 158{ 159 float textWidth, layoutedWidth = -1, layoutedHeight = -1; 160 NSFont *font; 161 unsigned int borderMask = [[[_toolbarItem toolbar] _toolbarView] borderMask]; 162 NSSize labelSize = NSZeroSize; 163 164 font = NormalFont; 165 166 // Adjust the layout in accordance with NSToolbarSizeMode 167 switch ([[_toolbarItem toolbar] sizeMode]) 168 { 169 case NSToolbarSizeModeDefault: 170 layoutedWidth = ItemBackViewDefaultWidth; 171 layoutedHeight = ItemBackViewDefaultHeight; 172 [[_toolbarItem image] setSize: NSMakeSize(32, 32)]; 173 break; 174 case NSToolbarSizeModeRegular: 175 layoutedWidth = ItemBackViewRegularWidth; 176 layoutedHeight = ItemBackViewRegularHeight; 177 [[_toolbarItem image] setSize: NSMakeSize(32, 32)]; 178 break; 179 case NSToolbarSizeModeSmall: 180 layoutedWidth = ItemBackViewSmallWidth; 181 layoutedHeight = ItemBackViewSmallHeight; 182 /* Not use [self image] here because it can return nil, when image 183 position is set to NSNoImage. Even if NSToolbarDisplayModeTextOnly 184 is not true anymore -setImagePosition: is only called below, then 185 [self image] can still returns nil. */ 186 [[_toolbarItem image] setSize: NSMakeSize(24, 24)]; 187 font = SmallFont; 188 break; 189 default: 190 NSLog(@"Invalid NSToolbarSizeMode"); // Invalid 191 } 192 193 [self setFont: font]; 194 195 // Adjust the layout in accordance with the border 196 if (!(borderMask & GSToolbarViewBottomBorder)) 197 { 198 layoutedHeight++; 199 layoutedWidth++; 200 } 201 202 if (!(borderMask & GSToolbarViewTopBorder)) 203 { 204 layoutedHeight++; 205 layoutedWidth++; 206 } 207 208 // Adjust the layout in accordance with the label 209 { 210 NSAttributedString *attrStr; 211 NSDictionary *attr; 212 NSString *label = [_toolbarItem label]; 213 214 attr = [NSDictionary dictionaryWithObject: font forKey: NSFontAttributeName]; 215 if (label == nil || [label isEqualToString: @""]) 216 label = @"Dummy"; 217 attrStr = [[NSAttributedString alloc] initWithString: label attributes: attr]; 218 labelSize = [attrStr size]; 219 DESTROY(attrStr); 220 } 221 222 textWidth = labelSize.width + 2 * InsetItemTextX; 223 if ([[_toolbarItem toolbar] displayMode] != NSToolbarDisplayModeIconOnly 224 && layoutedWidth != -1 && textWidth > layoutedWidth) 225 layoutedWidth = textWidth; 226 227 // Adjust the layout in accordance with NSToolbarDisplayMode 228 switch ([[_toolbarItem toolbar] displayMode]) 229 { 230 case NSToolbarDisplayModeDefault: 231 [self setImagePosition: NSImageAbove]; 232 break; 233 case NSToolbarDisplayModeIconAndLabel: 234 [self setImagePosition: NSImageAbove]; 235 break; 236 case NSToolbarDisplayModeIconOnly: 237 [self setImagePosition: NSImageOnly]; 238 layoutedHeight -= labelSize.height + InsetItemTextY; 239 break; 240 case NSToolbarDisplayModeLabelOnly: 241 [self setImagePosition: NSNoImage]; 242 layoutedHeight = labelSize.height + InsetItemTextY * 2; 243 break; 244 default: 245 ; // Invalid 246 } 247 248 // Set the frame size to use the new layout 249 [self setFrameSize: NSMakeSize(layoutedWidth, layoutedHeight)]; 250} 251 252- (void) mouseDown: (NSEvent *)event 253{ 254 NSToolbar *toolbar = [_toolbarItem toolbar]; 255 256 if (([event modifierFlags] == NSCommandKeyMask 257 && [toolbar allowsUserCustomization]) 258 || [toolbar customizationPaletteIsRunning] || toolbar == nil) 259 { 260 NSSize viewSize = [self frame].size; 261 NSImage *image = [[NSImage alloc] initWithSize: viewSize]; 262 NSCell *cell = [self cell]; 263 NSPasteboard *pboard; 264 NSInteger index = NSNotFound; 265 266 // Prepare the drag 267 268 /* We need to keep this view (aka self) to be able to draw the drag 269 image. */ 270 RETAIN(self); 271 272 // Draw the drag content in an image 273 /* The code below is only partially supported by GNUstep, then NSImage 274 needs to be improved. */ 275 [image lockFocus]; 276 [cell setShowsFirstResponder: NO]; // To remove the dotted rect 277 [cell drawWithFrame: 278 NSMakeRect(0, 0, viewSize.width, viewSize.height) inView: nil]; 279 [cell setShowsFirstResponder: YES]; 280 [image unlockFocus]; 281 282 pboard = [NSPasteboard pasteboardWithName: NSDragPboard]; 283 [pboard declareTypes: [NSArray arrayWithObject: GSMovableToolbarItemPboardType] 284 owner: nil]; 285 if (toolbar != nil) 286 { 287 index = [toolbar _indexOfItem: _toolbarItem]; 288 } 289 [GSToolbarView setDraggedItemIndex:index]; 290 [pboard setString: [NSString stringWithFormat:@"%ld", (long) index] 291 forType: GSMovableToolbarItemPboardType]; 292 293 [self dragImage: image 294 at: NSMakePoint(0.0, viewSize.height) 295 offset: NSMakeSize(0.0, 0.0) 296 event: event 297 pasteboard: pboard 298 source: self 299 slideBack: NO]; 300 RELEASE(image); 301 } 302 else if ([event modifierFlags] != NSCommandKeyMask) 303 { 304 [super mouseDown: event]; 305 } 306} 307 308- (void) draggedImage: (NSImage *)dragImage beganAt: (NSPoint)location 309{ 310 //nothing to do 311} 312 313- (void) draggedImage: (NSImage *)dragImage 314 endedAt: (NSPoint)location 315 operation: (NSDragOperation)operation 316{ 317 //nothing to do 318} 319 320- (NSDragOperation) draggingSourceOperationMaskForLocal: (BOOL)isLocal 321{ 322 return isLocal ? NSDragOperationGeneric : NSDragOperationNone; 323} 324 325- (NSToolbarItem *) toolbarItem 326{ 327 return _toolbarItem; 328} 329 330/* 331 * End of the code to keep in sync 332 */ 333 334- (BOOL) sendAction: (SEL)action to: (id)target 335{ 336 if ([_toolbarItem _selectable]) 337 { 338 [[_toolbarItem toolbar] 339 setSelectedItemIdentifier: [_toolbarItem itemIdentifier]]; 340 } 341 342 if (action) 343 { 344 // Send from toolbar item not self 345 return [NSApp sendAction: action 346 to: target 347 from: _toolbarItem]; 348 } 349 else 350 { 351 return NO; 352 } 353} 354 355@end 356 357@implementation GSToolbarButtonCell 358 359/* Overriden NSButtonCell method to handle cell type in a basic way which avoids 360 to lose image or empty title on new image position (when this involves a cell 361 type switch) and the need to reset it. That would happen in GSToolbarButton 362 -layout method (on toolbar display mode switch). 363 Note that empty title are used with space or separator toolbar items. */ 364- (void) setImagePosition: (NSCellImagePosition)aPosition 365{ 366 _cell.image_position = aPosition; 367 368 if (_cell.image_position == NSNoImage) 369 { 370 _cell.type = NSTextCellType; 371 } 372 else 373 { 374 _cell.type = NSImageCellType; 375 } 376} 377 378/* Allways return the image, even when no image gets displayed. */ 379- (NSImage*) image 380{ 381 return _cell_image; 382} 383 384// Overriden NSButtonCell method to make sure all text is at the same height. 385- (void) drawInteriorWithFrame: (NSRect)cellFrame inView: (NSView*)controlView 386{ 387 BOOL flippedView = [controlView isFlipped]; 388 NSCellImagePosition ipos = _cell.image_position; 389 // We ignore alternateAttributedTitle, it is not needed 390 NSSize titleSize = [[self attributedTitle] size]; 391 392 if (flippedView == YES) 393 { 394 if (ipos == NSImageAbove) 395 { 396 ipos = NSImageBelow; 397 } 398 else if (ipos == NSImageBelow) 399 { 400 ipos = NSImageAbove; 401 } 402 } 403 404 /* We store the values we need to customize the drawing into titleRect and 405 imageRect. */ 406 switch (ipos) 407 { 408 case NSNoImage: 409 titleRect = cellFrame; 410 break; 411 412 case NSImageOnly: 413 imageRect = cellFrame; 414 break; 415 416 default: 417 case NSImageBelow: 418 titleRect.origin.x = cellFrame.origin.x; 419 titleRect.origin.y = NSMaxY(cellFrame) - titleSize.height - InsetItemTextY; 420 titleRect.size.width = cellFrame.size.width; 421 titleRect.size.height = titleSize.height; 422 423 imageRect.origin.x = cellFrame.origin.x; 424 imageRect.origin.y = cellFrame.origin.y; 425 imageRect.size.width = cellFrame.size.width; 426 imageRect.size.height = cellFrame.size.height - titleRect.size.height; 427 break; 428 429 case NSImageAbove: 430 titleRect.origin.x = cellFrame.origin.x; 431 titleRect.origin.y = cellFrame.origin.y + InsetItemTextY; 432 titleRect.size.width = cellFrame.size.width; 433 titleRect.size.height = titleSize.height; 434 435 imageRect.origin.x = cellFrame.origin.x; 436 imageRect.origin.y = cellFrame.origin.y + titleRect.size.height; 437 imageRect.size.width = cellFrame.size.width; 438 imageRect.size.height = cellFrame.size.height - titleRect.size.height; 439 break; 440 } 441 442 [super drawInteriorWithFrame: cellFrame inView: controlView]; 443} 444 445// Overriden NSCell method 446- (void) _drawAttributedText: (NSAttributedString*)aString 447 inFrame: (NSRect)aRect 448{ 449 if (aString == nil) 450 return; 451 452 /* Important: text should always be vertically centered without considering 453 descender (as if descender did not exist). This is particularly important 454 for single line texts.Please make sure the output remains always 455 correct. */ 456 457 [aString drawInRect: titleRect]; // We ignore aRect value 458} 459 460// Overriden NSButtonCell method 461- (void) drawImage: (NSImage *)anImage withFrame: (NSRect)aRect inView: (NSView*)controlView 462{ 463 // We ignore aRect value 464 [super drawImage: anImage withFrame: imageRect inView: controlView]; 465} 466 467@end 468 469/* 470 * Back view used to enclose toolbar item's custom view 471 */ 472@interface GSToolbarBackView : NSView 473{ 474 NSToolbarItem *_toolbarItem; 475 NSFont *_font; 476 BOOL _enabled; 477 BOOL _showLabel; 478 // record the fact that the view responds to these 479 // to save time. 480 struct __flags 481 { 482 // gets 483 unsigned int _isEnabled:1; 484 unsigned int _action:1; 485 unsigned int _target:1; 486 unsigned int _image:1; 487 // sets 488 unsigned int _setEnabled:1; 489 unsigned int _setAction:1; 490 unsigned int _setTarget:1; 491 unsigned int _setImage:1; 492 493 // to even out the int. 494 unsigned int RESERVED:24; 495 } _flags; 496} 497 498- (id) initWithToolbarItem: (NSToolbarItem *)toolbarItem; 499- (void) layout; 500 501- (NSToolbarItem *) toolbarItem; 502- (BOOL) isEnabled; 503- (void) setEnabled: (BOOL)enabled; 504@end 505 506@implementation GSToolbarBackView 507 508- (id) initWithToolbarItem: (NSToolbarItem *)toolbarItem 509{ 510 self = [super initWithFrame: NSMakeRect(ItemBackViewX, ItemBackViewY, 511 ItemBackViewDefaultWidth, ItemBackViewDefaultHeight)]; 512 // Frame will be reset by the layout method 513 514 if (self != nil) 515 { 516 NSView *view; 517 518 // Don't do an ASSIGN here, the toolbar item itself retains us. 519 _toolbarItem = toolbarItem; 520 view = [toolbarItem view]; 521 522 // gets 523 _flags._isEnabled = [view respondsToSelector: @selector(isEnabled)]; 524 _flags._action = [view respondsToSelector: @selector(action)]; 525 _flags._target = [view respondsToSelector: @selector(target)]; 526 _flags._image = [view respondsToSelector: @selector(image)]; 527 // sets 528 _flags._setEnabled = [view respondsToSelector: @selector(setEnabled:)]; 529 _flags._setAction = [view respondsToSelector: @selector(setAction:)]; 530 _flags._setTarget = [view respondsToSelector: @selector(setTarget:)]; 531 _flags._setImage = [view respondsToSelector: @selector(setImage:)]; 532 } 533 534 return self; 535} 536 537- (void) drawRect: (NSRect)rect 538{ 539 if (_showLabel && NSIntersectsRect(rect, [self bounds])) 540 { 541 NSAttributedString *attrString; 542 NSDictionary *attr; 543 NSColor *color; 544 NSMutableParagraphStyle *pStyle; 545 NSRect titleRect; 546 NSRect viewBounds = [self bounds]; 547 548 if (_enabled) 549 { 550 color = [NSColor blackColor]; 551 } 552 else 553 { 554 color = [NSColor disabledControlTextColor]; 555 } 556 557 pStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; 558 [pStyle setAlignment: NSCenterTextAlignment]; 559 560 // We draw the label 561 attr = [NSDictionary dictionaryWithObjectsAndKeys: _font, 562 NSFontAttributeName, color, NSForegroundColorAttributeName, pStyle, 563 NSParagraphStyleAttributeName, nil]; 564 RELEASE(pStyle); 565 566 attrString = [[NSAttributedString alloc] 567 initWithString: [_toolbarItem label] attributes: attr]; 568 569 titleRect.origin.x = viewBounds.origin.x; 570 titleRect.origin.y = viewBounds.origin.y + InsetItemTextY; 571 titleRect.size.width = viewBounds.size.width; 572 titleRect.size.height = [attrString size].height; 573 [attrString drawInRect: titleRect]; 574 575 DESTROY(attrString); 576 } 577} 578 579- (NSView *) hitTest: (NSPoint)point 580{ 581 if (_super_view && [_super_view mouse: point inRect: _frame]) 582 { 583 NSEvent *event = [NSApp currentEvent]; 584 NSToolbar *toolbar = [_toolbarItem toolbar]; 585 586 if (([event type] == NSLeftMouseDown) 587 && (([event modifierFlags] == NSCommandKeyMask 588 && [toolbar allowsUserCustomization]) 589 || [toolbar customizationPaletteIsRunning] || toolbar == nil)) 590 { 591 return self; 592 } 593 } 594 595 return [super hitTest: point]; 596} 597 598/* 599 * The code below should be kept in sync with GSToolbarButton methods which 600 * have identical names. 601 */ 602 603- (void) layout 604{ 605 NSView *view = [_toolbarItem view]; 606 float textWidth, layoutedWidth = -1, layoutedHeight = -1; 607 NSFont *font; 608 unsigned int borderMask = [[[_toolbarItem toolbar] _toolbarView] borderMask]; 609 NSSize labelSize = NSZeroSize; 610 611 font = NormalFont; 612 613 if ([view superview] == nil) // Show the view to eventually hide it later 614 [self addSubview: view]; 615 616 if ([view respondsToSelector: @selector(sizeToFit)]) 617 { 618 NSSize newSize, minSize = [_toolbarItem minSize]; 619 620 [(id)view sizeToFit]; 621 newSize = [view frame].size; 622 if (minSize.width > 0 || newSize.height < minSize.height) 623 { 624 if (minSize.width > 0) 625 newSize.width = minSize.width; 626 newSize.height = MAX(newSize.height, minSize.height); 627 [view setFrameSize: newSize]; 628 } 629 } 630 631 // Adjust the layout in accordance with NSToolbarSizeMode 632 switch ([[_toolbarItem toolbar] sizeMode]) 633 { 634 case NSToolbarSizeModeDefault: 635 layoutedWidth = ItemBackViewDefaultWidth; 636 layoutedHeight = ItemBackViewDefaultHeight; 637 if ([view frame].size.height > 32) 638 [view removeFromSuperview]; 639 break; 640 case NSToolbarSizeModeRegular: 641 layoutedWidth = ItemBackViewRegularWidth; 642 layoutedHeight = ItemBackViewRegularHeight; 643 if ([view frame].size.height > 32) 644 [view removeFromSuperview]; 645 break; 646 case NSToolbarSizeModeSmall: 647 layoutedWidth = ItemBackViewSmallWidth; 648 layoutedHeight = ItemBackViewSmallHeight; 649 font = SmallFont; 650 if ([view frame].size.height > 24) 651 [view removeFromSuperview]; 652 break; 653 default: 654 NSLog(@"Invalid NSToolbarSizeMode"); // Invalid 655 } 656 657 _font = font; 658 659 // Adjust the layout in accordance with the border 660 if (!(borderMask & GSToolbarViewBottomBorder)) 661 { 662 layoutedHeight++; 663 layoutedWidth++; 664 } 665 666 if (!(borderMask & GSToolbarViewTopBorder)) 667 { 668 layoutedHeight++; 669 layoutedWidth++; 670 } 671 672 // Adjust the layout in accordance with the label 673 { 674 NSAttributedString *attrStr; 675 NSDictionary *attr; 676 NSString *label = [_toolbarItem label]; 677 678 attr = [NSDictionary dictionaryWithObject: font forKey: NSFontAttributeName]; 679 if (label == nil || [label isEqualToString: @""]) 680 label = @"Dummy"; 681 attrStr = [[NSAttributedString alloc] initWithString: label attributes: attr]; 682 labelSize = [attrStr size]; 683 DESTROY(attrStr); 684 } 685 686 textWidth = labelSize.width + 2 * InsetItemTextX; 687 if (textWidth > layoutedWidth) 688 layoutedWidth = textWidth; 689 690 _enabled = YES; 691 /* This boolean variable is used to known when it's needed to draw the label 692 in the -drawRect: method. */ 693 _showLabel = YES; 694 695 // Adjust the layout in accordance with NSToolbarDisplayMode 696 switch ([[_toolbarItem toolbar] displayMode]) 697 { 698 case NSToolbarDisplayModeDefault: 699 break; // Nothing to do 700 case NSToolbarDisplayModeIconAndLabel: 701 break; // Nothing to do 702 case NSToolbarDisplayModeIconOnly: 703 _showLabel = NO; 704 layoutedHeight -= labelSize.height + InsetItemTextY; 705 break; 706 case NSToolbarDisplayModeLabelOnly: 707 _enabled = NO; 708 layoutedHeight = labelSize.height + InsetItemTextY * 2; 709 if ([view superview] != nil) 710 [view removeFromSuperview]; 711 break; 712 default: 713 ; // Invalid 714 } 715 716 /* If the view is visible... 717 Adjust the layout in accordance with the view width in the case it is 718 needed. */ 719 if ([view superview] != nil) 720 { 721 if (layoutedWidth < [view frame].size.width + 2 * InsetItemViewX) 722 layoutedWidth = [view frame].size.width + 2 * InsetItemViewX; 723 } 724 725 // Set the frame size to use the new layout 726 [self setFrameSize: NSMakeSize(layoutedWidth, layoutedHeight)]; 727 728 /* If the view is visible... 729 Adjust the view position in accordance with the new layout. */ 730 if ([view superview] != nil) 731 { 732 float insetItemViewY = ([self frame].size.height 733 - [view frame].size.height) / 2; 734 735 if (_showLabel) 736 { 737 insetItemViewY += (labelSize.height + InsetItemTextY) / 2; 738 } 739 740 [view setFrameOrigin: NSMakePoint((layoutedWidth 741 - [view frame].size.width) / 2, insetItemViewY)]; 742 } 743} 744 745- (void) mouseDown: (NSEvent *)event 746{ 747 NSToolbar *toolbar = [_toolbarItem toolbar]; 748 749 if (([event modifierFlags] == NSCommandKeyMask 750 && [toolbar allowsUserCustomization]) 751 || [toolbar customizationPaletteIsRunning] || toolbar == nil) 752 { 753 NSSize viewSize = [self frame].size; 754 NSImage *image = [[NSImage alloc] initWithSize: viewSize]; 755 NSPasteboard *pboard; 756 NSInteger index = NSNotFound; 757 758 // Prepare the drag 759 760 /* We need to keep this view (aka self) to be able to draw the drag 761 image. */ 762 RETAIN(self); 763 764 // Draw the drag content in an image 765 /* The code below is only partially supported by GNUstep, then NSImage 766 needs to be improved. */ 767 [image lockFocus]; 768 [self drawRect: 769 NSMakeRect(0, 0, viewSize.width, viewSize.height)]; 770 [image unlockFocus]; 771 772 pboard = [NSPasteboard pasteboardWithName: NSDragPboard]; 773 [pboard declareTypes: [NSArray arrayWithObject: GSMovableToolbarItemPboardType] 774 owner: nil]; 775 if (toolbar != nil) 776 { 777 index = [toolbar _indexOfItem: _toolbarItem]; 778 } 779 [GSToolbarView setDraggedItemIndex:index]; 780 [pboard setString: [NSString stringWithFormat:@"%ld", (long) index] 781 forType: GSMovableToolbarItemPboardType]; 782 783 [self dragImage: image 784 //at: NSMakePoint(0.0, viewSize.height) 785 at: NSMakePoint(0.0, 0.0) 786 offset: NSMakeSize(0.0, 0.0) 787 event: event 788 pasteboard: pboard 789 source: self 790 slideBack: NO]; 791 RELEASE(image); 792 } 793 else if ([event modifierFlags] != NSCommandKeyMask) 794 { 795 [super mouseDown: event]; 796 } 797} 798 799- (void) draggedImage: (NSImage *)dragImage beganAt: (NSPoint)location 800{ 801 //nothing to do 802} 803 804- (void) draggedImage: (NSImage *)dragImage 805 endedAt: (NSPoint)location 806 operation: (NSDragOperation)operation 807{ 808 //nothing to do 809} 810 811- (NSDragOperation) draggingSourceOperationMaskForLocal: (BOOL)isLocal 812{ 813 return isLocal ? NSDragOperationGeneric : NSDragOperationNone; 814} 815 816- (NSToolbarItem *) toolbarItem 817{ 818 return _toolbarItem; 819} 820 821/* 822 * End of the code to keep in sync 823 */ 824 825- (BOOL) isEnabled 826{ 827 if (_flags._isEnabled) 828 { 829 id view = [_toolbarItem view]; 830 831 return [view isEnabled]; 832 } 833 else 834 { 835 return _enabled; 836 } 837} 838 839- (void) setEnabled: (BOOL)enabled 840{ 841 if (_flags._setEnabled) 842 { 843 id view = [_toolbarItem view]; 844 845 [view setEnabled: enabled]; 846 } 847 else 848 { 849 _enabled = enabled; 850 } 851} 852 853- (NSImage *) image 854{ 855 if (_flags._image) 856 { 857 id view = [_toolbarItem view]; 858 859 return [view image]; 860 } 861 else 862 { 863 return nil; 864 } 865} 866 867- (void) setImage: (NSImage *)image 868{ 869 if (_flags._setImage) 870 { 871 id view = [_toolbarItem view]; 872 873 [view setImage: image]; 874 } 875} 876 877- (void) setAction: (SEL)action 878{ 879 if (_flags._setAction) 880 { 881 id view = [_toolbarItem view]; 882 883 [view setAction: action]; 884 } 885} 886 887- (SEL) action 888{ 889 if (_flags._action) 890 { 891 id view = [_toolbarItem view]; 892 893 return [view action]; 894 } 895 else 896 { 897 return 0; 898 } 899} 900 901- (void) setTarget: (id)target 902{ 903 if (_flags._setTarget) 904 { 905 id view = [_toolbarItem view]; 906 907 [view setTarget: target]; 908 } 909} 910 911- (id) target 912{ 913 if (_flags._target) 914 { 915 id view = [_toolbarItem view]; 916 917 return [view target]; 918 } 919 else 920 { 921 return nil; 922 } 923} 924 925@end 926 927/* 928 * Standard toolbar items. 929 */ 930 931// ---- NSToolbarSeparatorItemIdentifier 932@interface NSToolbarSeparatorItem : NSToolbarItem 933{ 934} 935@end 936 937@implementation NSToolbarSeparatorItem 938- (id) initWithItemIdentifier: (NSString *)itemIdentifier 939{ 940 self = [super initWithItemIdentifier: itemIdentifier]; 941 if (!self) 942 return nil; 943 944 [(NSButton *)[self _backView] setImagePosition: NSImageOnly]; 945 [(NSButton *)[self _backView] setImage: 946 [NSImage imageNamed: @"common_ToolbarSeparatorItem"]]; 947 /* We bypass the toolbar item accessor to set the image in order to have it 948 (48 * 48) not resized. */ 949 [self setPaletteLabel: _(@"Separator")]; 950 951 [[self _backView] setFrameSize: NSMakeSize(30, ItemBackViewDefaultHeight)]; 952 953 return self; 954} 955 956- (NSMenuItem *) _defaultMenuFormRepresentation 957{ 958 return nil; // Override the default implementation in order to do nothing 959} 960 961- (void) _layout 962{ 963 NSView *backView = [self _backView]; 964 965 // Override the default implementation 966 967 [(id)backView layout]; 968 if ([self toolbar] != nil) 969 [backView setFrameSize: NSMakeSize(30, [backView frame].size.height)]; 970} 971 972- (BOOL) allowsDuplicatesInToolbar 973{ 974 return YES; 975} 976 977@end 978 979// ---- NSToolbarSpaceItemIdentifier 980@interface NSToolbarSpaceItem : NSToolbarItem 981{ 982} 983@end 984 985@implementation NSToolbarSpaceItem 986- (id) initWithItemIdentifier: (NSString *)itemIdentifier 987{ 988 self = [super initWithItemIdentifier: itemIdentifier]; 989 if (!self) 990 return nil; 991 [self setPaletteLabel: _(@"Space")]; 992 993 return self; 994} 995 996// Override the default implementation in order to do nothing 997- (NSMenuItem *) _defaultMenuFormRepresentation 998{ 999 return nil; 1000} 1001 1002- (BOOL) allowsDuplicatesInToolbar 1003{ 1004 return YES; 1005} 1006 1007@end 1008 1009// ---- NSToolbarFlexibleSpaceItemIdentifier 1010@interface NSToolbarFlexibleSpaceItem : NSToolbarItem 1011{ 1012} 1013@end 1014 1015@implementation NSToolbarFlexibleSpaceItem 1016- (id) initWithItemIdentifier: (NSString *)itemIdentifier 1017{ 1018 self = [super initWithItemIdentifier: itemIdentifier]; 1019 if (!self) 1020 return nil; 1021 [self setPaletteLabel: _(@"Flexible Space")]; 1022 [self _layout]; 1023 1024 return self; 1025} 1026 1027// Override the default implementation in order to do nothing 1028- (NSMenuItem *) _defaultMenuFormRepresentation 1029{ 1030 return nil; 1031} 1032 1033// Override the default implementation in order to reset the _backView to a zero width 1034- (void) _layout 1035{ 1036 NSView *backView = [self _backView]; 1037 NSSize size; 1038 1039 [(id)backView layout]; 1040 size = [backView frame].size; 1041 1042 /* If the item is not part of a toolbar, this usually means it is used by 1043 customization palette, we shouldn't resize it in this case. */ 1044 if ([self toolbar] != nil) 1045 [backView setFrameSize: NSMakeSize(0, size.height)]; 1046 1047 [self setMinSize: NSMakeSize(0, size.height)]; 1048 [self setMaxSize: NSMakeSize(10000, size.height)]; 1049} 1050 1051- (BOOL) _isFlexibleSpace 1052{ 1053 return YES; 1054} 1055 1056- (BOOL) allowsDuplicatesInToolbar 1057{ 1058 return YES; 1059} 1060 1061@end 1062 1063// ---- NSToolbarShowColorsItemIdentifier 1064@interface GSToolbarShowColorsItem : NSToolbarItem 1065{ 1066} 1067@end 1068 1069@implementation GSToolbarShowColorsItem 1070- (id) initWithItemIdentifier: (NSString *)itemIdentifier 1071{ 1072 self = [super initWithItemIdentifier: itemIdentifier]; 1073 if (!self) 1074 return nil; 1075 [self setImage: [NSImage imageNamed: @"common_ToolbarShowColorsItem"]]; 1076 [self setLabel: _(@"Colors")]; 1077 1078 // Set action... 1079 [self setTarget: nil]; // Goes to first responder.. 1080 [self setAction: @selector(orderFrontColorPanel:)]; 1081 1082 return self; 1083} 1084@end 1085 1086// ---- NSToolbarShowFontsItemIdentifier 1087@interface GSToolbarShowFontsItem : NSToolbarItem 1088{ 1089} 1090@end 1091 1092@implementation GSToolbarShowFontsItem 1093- (id) initWithItemIdentifier: (NSString *)itemIdentifier 1094{ 1095 self = [super initWithItemIdentifier: itemIdentifier]; 1096 if (!self) 1097 return nil; 1098 [self setImage: [NSImage imageNamed: @"common_ToolbarShowFontsItem"]]; 1099 [self setLabel: _(@"Fonts")]; 1100 1101 // Set action... 1102 [self setTarget: nil]; // Goes to first responder.. 1103 [self setAction: @selector(orderFrontFontPanel:)]; 1104 1105 return self; 1106} 1107@end 1108 1109// ---- NSToolbarCustomizeToolbarItemIdentifier 1110@interface GSToolbarCustomizeToolbarItem : NSToolbarItem 1111{ 1112} 1113@end 1114 1115@implementation GSToolbarCustomizeToolbarItem 1116- (id) initWithItemIdentifier: (NSString *)itemIdentifier 1117{ 1118 self = [super initWithItemIdentifier: itemIdentifier]; 1119 if (!self) 1120 return nil; 1121 [self setImage: [NSImage imageNamed: @"common_ToolbarCustomizeToolbarItem"]]; 1122 [self setLabel: _(@"Customize")]; 1123 1124 // Set action... 1125 [self setTarget: nil]; // Goes to first responder.. 1126 [self setAction: @selector(runToolbarCustomizationPalette:)]; 1127 1128 return self; 1129} 1130@end 1131 1132// ---- NSToolbarPrintItemIdentifier 1133@interface GSToolbarPrintItem : NSToolbarItem 1134{ 1135} 1136@end 1137 1138@implementation GSToolbarPrintItem 1139- (id) initWithItemIdentifier: (NSString *)itemIdentifier 1140{ 1141 self = [super initWithItemIdentifier: itemIdentifier]; 1142 if (!self) 1143 return nil; 1144 [self setImage: [NSImage imageNamed: @"common_Printer"]]; 1145 [self setLabel: _(@"Print...")]; 1146 1147 // Set action... 1148 [self setTarget: nil]; // goes to first responder.. 1149 [self setAction: @selector(printDocument:)]; 1150 1151 return self; 1152} 1153@end 1154 1155 1156@implementation NSToolbarItem 1157 1158+ (void) initialize 1159{ 1160 // This used to be size 11. 1161 NormalFont = RETAIN([NSFont systemFontOfSize: [NSFont systemFontSize]]); 1162 // [NSFont smallSystemFontSize] or better should be NSControlContentFontSize 1163 SmallFont = RETAIN([NSFont systemFontOfSize: [NSFont smallSystemFontSize]]); 1164} 1165 1166- (id) initWithItemIdentifier: (NSString *)itemIdentifier 1167{ 1168 // GNUstep predefined toolbar items 1169 if ([itemIdentifier isEqualToString: NSToolbarSeparatorItemIdentifier] 1170 && [self isKindOfClass: [NSToolbarSeparatorItem class]] == NO) 1171 { 1172 RELEASE(self); 1173 return [[NSToolbarSeparatorItem alloc] 1174 initWithItemIdentifier: itemIdentifier]; 1175 } 1176 else if ([itemIdentifier isEqualToString: NSToolbarSpaceItemIdentifier] 1177 && [self isKindOfClass: [NSToolbarSpaceItem class]] == NO) 1178 { 1179 RELEASE(self); 1180 return [[NSToolbarSpaceItem alloc] 1181 initWithItemIdentifier: itemIdentifier]; 1182 } 1183 else if ([itemIdentifier 1184 isEqualToString: NSToolbarFlexibleSpaceItemIdentifier] 1185 && [self isKindOfClass: [NSToolbarFlexibleSpaceItem class]] == NO) 1186 { 1187 RELEASE(self); 1188 return [[NSToolbarFlexibleSpaceItem alloc] 1189 initWithItemIdentifier: itemIdentifier]; 1190 } 1191 else if ([itemIdentifier 1192 isEqualToString: NSToolbarShowColorsItemIdentifier] 1193 && [self isKindOfClass: [GSToolbarShowColorsItem class]] == NO) 1194 { 1195 RELEASE(self); 1196 return [[GSToolbarShowColorsItem alloc] 1197 initWithItemIdentifier: itemIdentifier]; 1198 } 1199 else if ([itemIdentifier 1200 isEqualToString: NSToolbarShowFontsItemIdentifier] 1201 && [self isKindOfClass: [GSToolbarShowFontsItem class]] == NO) 1202 { 1203 RELEASE(self); 1204 return [[GSToolbarShowFontsItem alloc] 1205 initWithItemIdentifier: itemIdentifier]; 1206 } 1207 else if ([itemIdentifier 1208 isEqualToString: NSToolbarCustomizeToolbarItemIdentifier] 1209 && [self isKindOfClass: [GSToolbarCustomizeToolbarItem class]] == NO) 1210 { 1211 RELEASE(self); 1212 return [[GSToolbarCustomizeToolbarItem alloc] 1213 initWithItemIdentifier: itemIdentifier]; 1214 } 1215 else if ([itemIdentifier isEqualToString: NSToolbarPrintItemIdentifier] 1216 && [self isKindOfClass: [GSToolbarPrintItem class]] == NO) 1217 { 1218 RELEASE(self); 1219 return [[GSToolbarPrintItem alloc] 1220 initWithItemIdentifier: itemIdentifier]; 1221 } 1222 else 1223 { 1224 if ((self = [super init]) != nil) 1225 { 1226 // Normal toolbar items 1227 ASSIGN(_itemIdentifier, itemIdentifier); 1228 [self setAutovalidates: YES]; 1229 1230 // Set the backview to an GSToolbarButton, will get reset to a 1231 // GSToolbarBackView when setView: gets called. 1232 [self setView: nil]; 1233 } 1234 } 1235 1236 return self; 1237} 1238 1239- (void) dealloc 1240{ 1241 RELEASE(_itemIdentifier); 1242 RELEASE(_label); 1243 RELEASE(_image); 1244 RELEASE(_menuFormRepresentation); 1245 RELEASE(_paletteLabel); 1246 RELEASE(_toolTip); 1247 TEST_RELEASE(_view); 1248 RELEASE(_backView); 1249 1250 [super dealloc]; 1251} 1252 1253- (BOOL) allowsDuplicatesInToolbar 1254{ 1255 return NO; 1256} 1257 1258- (BOOL) isEnabled 1259{ 1260 return [(GSToolbarButton*)_backView isEnabled]; 1261} 1262 1263- (NSImage *) image 1264{ 1265 // return [(GSToolbarButton*)_backView image]; 1266 return _image; 1267} 1268 1269- (NSString *) itemIdentifier 1270{ 1271 return _itemIdentifier; 1272} 1273 1274- (NSString *) label 1275{ 1276 // FIXME: I think this is not needed 1277 if ([[self toolbar] displayMode] == NSToolbarDisplayModeLabelOnly) 1278 { 1279 NSMenuItem *menuItem = [self menuFormRepresentation]; 1280 1281 if (menuItem != nil) 1282 return [menuItem title]; 1283 } 1284 1285 if (nil != _label) 1286 { 1287 return _label; 1288 } 1289 else 1290 { 1291 return @""; 1292 } 1293} 1294 1295- (NSSize) maxSize 1296{ 1297 return _maxSize; 1298} 1299 1300- (NSMenuItem *) menuFormRepresentation 1301{ 1302 return _menuFormRepresentation; 1303} 1304 1305- (NSSize) minSize 1306{ 1307 return _minSize; 1308} 1309 1310- (NSString *) paletteLabel 1311{ 1312 return _paletteLabel; 1313} 1314 1315- (void) setAction: (SEL)action 1316{ 1317 [(GSToolbarButton *)_backView setAction: action]; 1318 1319 [self setEnabled: (action != NULL)]; 1320} 1321 1322- (void) setEnabled: (BOOL)enabled 1323{ 1324 [(GSToolbarButton*)_backView setEnabled: enabled]; 1325} 1326 1327- (void) setImage: (NSImage *)image 1328{ 1329 ASSIGN(_image, image); 1330 1331 [_image setScalesWhenResized: YES]; 1332 //[_image setSize: NSMakeSize(32, 32)]; 1333 1334 // Do not set the image on the button if we are in "LabelOnly" 1335 // mode. If the toolbar's displayMode changes later, we'll 1336 // put the image on the button in the layout method. 1337 if ([[self toolbar] displayMode] != NSToolbarDisplayModeLabelOnly) 1338 { 1339 [(GSToolbarButton*)_backView setImage: image]; 1340 } 1341} 1342 1343- (void) setLabel: (NSString *)label 1344{ 1345 ASSIGN(_label, label); 1346 1347 if (!_view) 1348 [(GSToolbarButton *)_backView setTitle: _label]; 1349 1350 _modified = YES; 1351 if (_toolbar != nil) 1352 [[_toolbar _toolbarView] _reload]; 1353} 1354 1355- (void) setMaxSize: (NSSize)maxSize 1356{ 1357 _maxSize = maxSize; 1358} 1359 1360- (void) setMenuFormRepresentation: (NSMenuItem *)menuItem 1361{ 1362 ASSIGN(_menuFormRepresentation, menuItem); 1363} 1364 1365- (void) setMinSize: (NSSize)minSize 1366{ 1367 _minSize = minSize; 1368} 1369 1370- (void) setPaletteLabel: (NSString *)paletteLabel 1371{ 1372 ASSIGN(_paletteLabel, paletteLabel); 1373} 1374 1375- (void) setTag: (NSInteger)tag 1376{ 1377 _tag = tag; 1378} 1379 1380- (void) setTarget: (id)target 1381{ 1382 [(NSButton *)_backView setTarget: target]; 1383} 1384 1385- (void) setToolTip: (NSString *)toolTip 1386{ 1387 ASSIGN(_toolTip, toolTip); 1388 if (_view) 1389 { 1390 [_view setToolTip: _toolTip]; 1391 } 1392 else 1393 { 1394 [_backView setToolTip: _toolTip]; 1395 } 1396} 1397 1398- (void) setView: (NSView *)view 1399{ 1400 if ((_view == view) && (_backView != nil)) 1401 return; 1402 1403 ASSIGN(_view, view); 1404 1405 if (view) 1406 { 1407 NSSize size; 1408 1409 size = [view frame].size; 1410 if (NSEqualSizes(NSZeroSize, _minSize)) 1411 [self setMinSize: size]; 1412 if (NSEqualSizes(NSZeroSize, _maxSize)) 1413 [self setMaxSize: size]; 1414 1415 [_view setToolTip: _toolTip]; 1416 1417 RELEASE(_backView); 1418 _backView = [[GSToolbarBackView alloc] initWithToolbarItem: self]; 1419 } 1420 else 1421 { 1422 RELEASE(_backView); 1423 _backView = [[GSToolbarButton alloc] initWithToolbarItem: self]; 1424 [_backView setToolTip: _toolTip]; 1425 } 1426} 1427 1428- (NSInteger) tag 1429{ 1430 return _tag; 1431} 1432 1433- (NSString *) toolTip 1434{ 1435 return _toolTip; 1436} 1437 1438- (NSToolbar *) toolbar 1439{ 1440 return _toolbar; 1441} 1442 1443- (void) validate 1444{ 1445 BOOL enabled = YES; 1446 id target; 1447 1448 /* No validation for custom views */ 1449 if (_view) 1450 return; 1451 1452 target = [NSApp targetForAction: [self action] to: [self target] from: self]; 1453 if (target == nil || ![target respondsToSelector: [self action]]) 1454 { 1455 enabled = NO; 1456 } 1457 else if ([target respondsToSelector: @selector(validateToolbarItem:)]) 1458 { 1459 enabled = [target validateToolbarItem: self]; 1460 } 1461 else if ([target respondsToSelector: @selector(validateUserInterfaceItem:)]) 1462 { 1463 enabled = [target validateUserInterfaceItem: self]; 1464 } 1465 [self setEnabled: enabled]; 1466} 1467 1468- (NSView *) view 1469{ 1470 return _view; 1471} 1472 1473// Private or package like visibility methods 1474 1475- (NSView *) _backView 1476{ 1477 return _backView; 1478} 1479 1480// 1481// This method invokes using the toolbar item as the sender. 1482// When invoking from the menu, it shouldn't send the menuitem as the 1483// sender since some applications check this and try to get additional 1484// information about the toolbar item which this is coming from. Since 1485// we implement the menu's action, we must also validate it. 1486// 1487- (void) _sendAction: (id)sender 1488{ 1489 [NSApp sendAction: [self action] 1490 to: [self target] 1491 from: self]; 1492} 1493 1494- (BOOL) validateMenuItem: (NSMenuItem *)menuItem 1495{ 1496 return [self isEnabled]; 1497} 1498 1499- (NSMenuItem *) _defaultMenuFormRepresentation 1500{ 1501 NSMenuItem *menuItem; 1502 1503 menuItem = [[NSMenuItem alloc] initWithTitle: [self label] 1504 action: @selector(_sendAction:) 1505 keyEquivalent: @""]; 1506 [menuItem setTarget: self]; 1507 AUTORELEASE(menuItem); 1508 1509 return menuItem; 1510} 1511 1512- (void) _layout 1513{ 1514 // Reset to image on the backview: We may have toggled 1515 // from one NSToolbarDisplayMode to another, and it is 1516 // possible setImage: would have been called on the 1517 // NSToolbarItem while we were in NSToolbarDisplayModeLabelOnly 1518 if ([[self toolbar] displayMode] != NSToolbarDisplayModeLabelOnly) 1519 { 1520 [(GSToolbarButton*)_backView setImage: _image]; 1521 } 1522 1523 [(id)_backView layout]; 1524} 1525 1526- (BOOL) _isModified 1527{ 1528 return _modified; 1529} 1530 1531- (BOOL) _isFlexibleSpace 1532{ 1533 return NO; 1534} 1535 1536- (BOOL) _selectable 1537{ 1538 return _selectable; 1539} 1540 1541- (BOOL) _selected 1542{ 1543 return [(GSToolbarButton *)_backView state]; 1544} 1545 1546- (void) _setSelected: (BOOL)selected 1547{ 1548 if (_selectable) 1549 { 1550 if ([self _selected] != selected) 1551 [(GSToolbarButton *)_backView setState: selected]; 1552 } 1553 else 1554 { 1555 NSLog(@"The toolbar item %@ is not selectable", self); 1556 } 1557} 1558 1559- (void) _setSelectable: (BOOL)selectable 1560{ 1561 if ([_backView isKindOfClass: [GSToolbarButton class]]) 1562 { 1563 _selectable = selectable; 1564 [(GSToolbarButton *)_backView setButtonType: NSOnOffButton]; 1565 } 1566 else 1567 { 1568 NSLog(@"The toolbar item %@ is not selectable", self); 1569 } 1570} 1571 1572- (void) _setToolbar: (NSToolbar *)toolbar 1573{ 1574 // Don't do an ASSIGN here, the toolbar itself retains us. 1575 _toolbar = toolbar; 1576} 1577 1578- (BOOL) autovalidates 1579{ 1580 return _autovalidates; 1581} 1582 1583- (void) setAutovalidates: (BOOL)autovalidates 1584{ 1585 _autovalidates = autovalidates; 1586} 1587 1588- (NSInteger) visibilityPriority 1589{ 1590 return _visibilityPriority; 1591} 1592 1593- (void) setVisibilityPriority: (NSInteger)visibilityPriority 1594{ 1595 _visibilityPriority = visibilityPriority; 1596} 1597 1598// NSValidatedUserInterfaceItem protocol 1599- (SEL) action 1600{ 1601 return [(GSToolbarButton *)_backView action]; 1602} 1603 1604- (id) target 1605{ 1606 return [(GSToolbarButton *)_backView target]; 1607} 1608 1609// NSCopying protocol 1610- (id) copyWithZone: (NSZone *)zone 1611{ 1612 NSToolbarItem *new = [[NSToolbarItem allocWithZone: zone] 1613 initWithItemIdentifier: _itemIdentifier]; 1614 NSString *toolTip; 1615 NSImage *image; 1616 NSString *label; 1617 NSMenuItem *item; 1618 1619 // Copy all items individually... 1620 [new setTarget: [self target]]; 1621 [new setAction: [self action]]; 1622 1623 toolTip = [[self toolTip] copyWithZone: zone]; 1624 [new setToolTip: toolTip]; 1625 RELEASE(toolTip); 1626 [new setTag: [self tag]]; 1627 image = [[self image] copyWithZone: zone]; 1628 [new setImage: image]; 1629 RELEASE(image); 1630 [new setEnabled: [self isEnabled]]; 1631 label = [[self paletteLabel] copyWithZone: zone]; 1632 [new setPaletteLabel: label]; 1633 RELEASE(label); 1634 label = [[self label] copyWithZone: zone]; 1635 [new setLabel: label]; 1636 RELEASE(label); 1637 [new setMinSize: [self minSize]]; 1638 [new setMaxSize: [self maxSize]]; 1639 [new setAutovalidates: [self autovalidates]]; 1640 [new setVisibilityPriority: [self visibilityPriority]]; 1641 item = [[self menuFormRepresentation] copyWithZone: zone]; 1642 [new setMenuFormRepresentation: item]; 1643 RELEASE(item); 1644 1645 if ([self view] != nil) 1646 { 1647 NSData *encodedView = nil; 1648 NSView *superview = nil; 1649 1650 /* NSView doesn't implement -copyWithZone:, that's why we encode 1651 then decode the view to create a copy of it. */ 1652 superview = [[self view] superview]; 1653 /* We must avoid to encode view hierarchy */ 1654 [[self view] removeFromSuperviewWithoutNeedingDisplay]; 1655 NSLog(@"Encode toolbar item with label %@, view %@ and superview %@", 1656 [self label], [self view], superview); 1657 // NOTE: Keyed archiver would fail on NSSlider here. 1658 encodedView = [NSArchiver archivedDataWithRootObject: [self view]]; 1659 [new setView: [NSUnarchiver unarchiveObjectWithData: encodedView]]; 1660 // Re-add the view to its hierarchy 1661 [superview addSubview: [self view]]; 1662 } 1663 1664 return new; 1665} 1666 1667- (NSString *) description 1668{ 1669 return [NSString stringWithFormat: @"<%@ - <%@>>",[super description],[self itemIdentifier]]; 1670} 1671 1672- (id) initWithCoder: (NSCoder *)aCoder 1673{ 1674 self = [self initWithItemIdentifier: [aCoder decodeObjectForKey:@"NSToolbarItemIdentifier"]]; 1675 1676 if ([aCoder containsValueForKey: @"NSToolbarItemTarget"]) 1677 [self setTarget: [aCoder decodeObjectForKey:@"NSToolbarItemTarget"]]; 1678 if ([aCoder containsValueForKey: @"NSToolbarItemAction"]) 1679 [self setAction: NSSelectorFromString([aCoder decodeObjectForKey:@"NSToolbarItemAction"])]; 1680 if ([aCoder containsValueForKey: @"NSToolbarItemToolTip"]) 1681 [self setToolTip: [aCoder decodeObjectForKey:@"NSToolbarItemToolTip"]]; 1682 if ([aCoder containsValueForKey: @"NSToolbarItemTag"]) 1683 [self setTag: [aCoder decodeIntForKey:@"NSToolbarItemTag"]]; 1684 if ([aCoder containsValueForKey: @"NSToolbarItemImage"]) 1685 [self setImage: [aCoder decodeObjectForKey:@"NSToolbarItemImage"]]; 1686 if ([aCoder containsValueForKey: @"NSToolbarItemEnabled"]) 1687 [self setEnabled: [aCoder decodeBoolForKey:@"NSToolbarItemEnabled"]]; 1688 if ([aCoder containsValueForKey: @"NSToolbarItemPaletteLabel"]) 1689 [self setPaletteLabel: [aCoder decodeObjectForKey:@"NSToolbarItemPaletteLabel"]]; 1690 if ([aCoder containsValueForKey: @"NSToolbarItemLabel"]) 1691 [self setLabel: [aCoder decodeObjectForKey:@"NSToolbarItemLabel"]]; 1692 if ([aCoder containsValueForKey: @"NSToolbarItemMinSize"]) 1693 [self setMinSize: [aCoder decodeSizeForKey:@"NSToolbarItemMinSize"]]; 1694 if ([aCoder containsValueForKey: @"NSToolbarItemMaxSize"]) 1695 [self setMaxSize: [aCoder decodeSizeForKey:@"NSToolbarItemMaxSize"]]; 1696 if ([aCoder containsValueForKey: @"NSToolbarItemAutovalidates"]) 1697 [self setAutovalidates: [aCoder decodeBoolForKey:@"NSToolbarItemAutovalidates"]]; 1698 if ([aCoder containsValueForKey: @"NSToolbarItemVisibilityPriority"]) 1699 [self setVisibilityPriority: [aCoder decodeIntForKey:@"NSToolbarItemVisibilityPriority"]]; 1700 if ([aCoder containsValueForKey: @"NSToolbarItemView"]) 1701 [self setView: [aCoder decodeObjectForKey: @"NSToolbarItemView"]]; 1702 1703 return self; 1704} 1705 1706@end 1707