Added the possibility to rearrange toolbar items

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@19976 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
qmathe 2004-09-02 17:40:00 +00:00
parent a0266207a1
commit e589de7383
5 changed files with 387 additions and 39 deletions

View file

@ -1,3 +1,16 @@
2004-09-02 Quentin Mathe <qmathe@club-internet.fr>
* Headers/AppKit/NSToolbarItem.h: Added GSMovableToolbarPboardType
declaration.
* Source/NSToolbarItem.m: Added the toolbar items rearranging possibility by
implementing the dragging source methods.
* Source/GSToolbar.m: Added or reworked some methods to support model updates
without direct view effects to manipulate the toolbar items when a dragging
session happens.
* Source/GSToolbarView.m: Added the toolbar items rearranging possibility by
implementing the dragging destination methods. And added a method to
support the insertion index calculation based on the mouse location.
2004-09-01 Adam Fedor <fedor@gnu.org> 2004-09-01 Adam Fedor <fedor@gnu.org>
* Source/NSPrintInfo.m ([NSPrintInfo -paperSize]): Avoid returning * Source/NSPrintInfo.m ([NSPrintInfo -paperSize]): Avoid returning

View file

@ -141,4 +141,7 @@ APPKIT_EXPORT NSString *NSToolbarPrintItemIdentifier;
- (BOOL) validateToolbarItem: (NSToolbarItem *)toolbarItem; - (BOOL) validateToolbarItem: (NSToolbarItem *)toolbarItem;
@end @end
// Extra private stuff
extern NSString *GSMovableToolbarItemPboardType;
#endif /* _GNUstep_H_NSToolbarItem */ #endif /* _GNUstep_H_NSToolbarItem */

View file

@ -32,18 +32,19 @@
#include <Foundation/NSArray.h> #include <Foundation/NSArray.h>
#include <Foundation/NSDictionary.h> #include <Foundation/NSDictionary.h>
#include <Foundation/NSException.h> #include <Foundation/NSException.h>
#include <Foundation/NSKeyValueCoding.h>
#include <Foundation/NSNotification.h> #include <Foundation/NSNotification.h>
#include <Foundation/NSNull.h>
#include <Foundation/NSRunLoop.h>
#include <Foundation/NSString.h>
#include <Foundation/NSTimer.h>
#include <Foundation/NSUserDefaults.h> #include <Foundation/NSUserDefaults.h>
#include "AppKit/NSApplication.h" #include "AppKit/NSApplication.h"
#include "AppKit/NSEvent.h"
#include "AppKit/NSMenu.h"
#include "AppKit/NSNibLoading.h"
#include "AppKit/NSToolbarItem.h" #include "AppKit/NSToolbarItem.h"
#include "AppKit/NSView.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 "AppKit/NSWindow.h"
#include "AppKit/NSWindow+Toolbar.h" #include "AppKit/NSWindow+Toolbar.h"
#include "GNUstepGUI/GSToolbarView.h" #include "GNUstepGUI/GSToolbarView.h"
@ -482,9 +483,14 @@ static GSValidationCenter *vc;
- (void) _setConfigurationFromDictionary: (NSDictionary *)configDict - (void) _setConfigurationFromDictionary: (NSDictionary *)configDict
broadcast: (BOOL)broadcast; broadcast: (BOOL)broadcast;
- (void) _setDelegate: (id)delegate broadcast: (BOOL)broadcast; - (void) _setDelegate: (id)delegate broadcast: (BOOL)broadcast;
- (void) _moveItemFromIndex: (int)index toIndex: (int)newIndex broadcast: (BOOL)broadcast;
// Few other private methods // Few other private methods
- (void) _build; - (void) _build;
- (int) _indexOfItem: (NSToolbarItem *)item;
- (void) _insertPassivelyItem: (NSToolbarItem *)item atIndex: (int)newIndex;
- (void) _performRemoveItem: (NSToolbarItem *)item;
- (void) _concludeRemoveItem: (NSToolbarItem *)item atIndex: (int)index broadcast: (BOOL)broadcast;
- (void) _loadConfig; - (void) _loadConfig;
- (NSToolbarItem *) _toolbarItemForIdentifier: (NSString *)itemIdent; - (NSToolbarItem *) _toolbarItemForIdentifier: (NSString *)itemIdent;
- (GSToolbar *) _toolbarModel; - (GSToolbar *) _toolbarModel;
@ -898,6 +904,23 @@ static GSValidationCenter *vc;
_build = NO; _build = NO;
} }
- (int) _indexOfItem: (NSToolbarItem *)item
{
return [_items indexOfObjectIdenticalTo: item];
}
- (void) _insertPassivelyItem: (NSToolbarItem *)item atIndex: (int)newIndex
{
if (![_items containsObject: item])
{
[_items insertObject: item atIndex: newIndex];
}
else
{
NSLog(@"Error: the toolbar already contains the item to insert.");
}
}
- (void) _loadConfig - (void) _loadConfig
{ {
if (_identifier != nil) if (_identifier != nil)
@ -1034,15 +1057,25 @@ static GSValidationCenter *vc;
- (void) _removeItemAtIndex: (int)index broadcast: (BOOL)broadcast - (void) _removeItemAtIndex: (int)index broadcast: (BOOL)broadcast
{ {
id item; id item = [_items objectAtIndex: index];
RETAIN(item);
[self _performRemoveItem: item];
[self _concludeRemoveItem: item atIndex: index broadcast: broadcast];
RELEASE(item);
}
item = RETAIN([_items objectAtIndex: index]); - (void) _performRemoveItem: (NSToolbarItem *)item
[_items removeObjectAtIndex: index]; {
[_items removeObject: item];
[_toolbarView _reload]; [_toolbarView _reload];
}
- (void) _concludeRemoveItem: (NSToolbarItem *)item atIndex: (int)index broadcast: (BOOL)broadcast
{
[nc postNotificationName: NSToolbarDidRemoveItemNotification [nc postNotificationName: NSToolbarDidRemoveItemNotification
object: self object: self
userInfo: [NSDictionary dictionaryWithObject: item forKey: @"item"]]; userInfo: [NSDictionary dictionaryWithObject: item forKey: @"item"]];
RELEASE(item);
if (broadcast) if (broadcast)
{ {
@ -1136,6 +1169,30 @@ static GSValidationCenter *vc;
} }
} }
- (void) _moveItemFromIndex: (int)index toIndex: (int)newIndex broadcast: (BOOL)broadcast
{
id item;
item = RETAIN([_items objectAtIndex: index]);
[_items removeObjectAtIndex: index];
if (newIndex > [_items count] - 1)
{
[_items addObject: item];
}
else
{
[_items insertObject: item atIndex: newIndex];
}
[_toolbarView _reload];
RELEASE(item);
if (broadcast)
{
TRANSMIT(_moveItemFromIndex: index toIndex: newIndex broadcast: NO);
}
}
// Private Accessors // Private Accessors
- (void) _setToolbarView: (GSToolbarView *)toolbarView - (void) _setToolbarView: (GSToolbarView *)toolbarView

View file

@ -29,19 +29,24 @@
#include <Foundation/NSObject.h> #include <Foundation/NSObject.h>
#include <Foundation/NSArray.h> #include <Foundation/NSArray.h>
#include <Foundation/NSDictionary.h> #include <Foundation/NSDictionary.h>
#include <Foundation/NSException.h>
#include <Foundation/NSNotification.h>
#include <Foundation/NSUserDefaults.h> #include <Foundation/NSUserDefaults.h>
#include <Foundation/NSString.h> #include <Foundation/NSString.h>
#include "AppKit/NSToolbarItem.h"
#include "AppKit/NSBezierPath.h" #include "AppKit/NSBezierPath.h"
#include "AppKit/NSButton.h" #include "AppKit/NSButton.h"
#include "AppKit/NSClipView.h" #include "AppKit/NSClipView.h"
#include "AppKit/NSColor.h" #include "AppKit/NSColor.h"
#include "AppKit/NSColorList.h" #include "AppKit/NSColorList.h"
#include "AppKit/NSDragging.h"
#include "AppKit/NSEvent.h" #include "AppKit/NSEvent.h"
#include "AppKit/NSImage.h" #include "AppKit/NSImage.h"
#include "AppKit/NSMenu.h" #include "AppKit/NSMenu.h"
#include "AppKit/NSPasteboard.h"
#include "AppKit/NSToolbarItem.h" // It contains GSMovableToolbarItemPboardType declaration
#include "AppKit/NSView.h" #include "AppKit/NSView.h"
#include "AppKit/NSWindow.h" #include "AppKit/NSWindow.h"
#include "GNUstepGUI/GSToolbar.h"
#include "GNUstepGUI/GSToolbarView.h" #include "GNUstepGUI/GSToolbarView.h"
typedef enum { typedef enum {
@ -138,6 +143,12 @@ static void initSystemExtensionsColors(void)
*/ */
@interface GSToolbar (GNUstepPrivate) @interface GSToolbar (GNUstepPrivate)
- (void) _build; - (void) _build;
- (void) _concludeRemoveItem: (NSToolbarItem *)item atIndex: (int)index broadcast: (BOOL)broadcast;
- (int) _indexOfItem: (NSToolbarItem *)item;
- (void) _insertPassivelyItem: (NSToolbarItem *)item atIndex: (int)newIndex;
- (void) _moveItemFromIndex: (int)index toIndex: (int)newIndex broadcast: (BOOL)broacast;
- (void) _toolbarViewWillMoveToSuperview: (NSView *)newSuperview; - (void) _toolbarViewWillMoveToSuperview: (NSView *)newSuperview;
// Accessors // Accessors
@ -155,12 +166,21 @@ static void initSystemExtensionsColors(void)
- (BOOL) _isFlexibleSpace; - (BOOL) _isFlexibleSpace;
@end @end
@interface GSToolbarButton
- (NSToolbarItem *) toolbarItem;
@end
@interface GSToolbarBackView
- (NSToolbarItem *) toolbarItem;
@end
@interface GSToolbarView (GNUstepPrivate) @interface GSToolbarView (GNUstepPrivate)
- (void) _handleBackViewsFrame; - (void) _handleBackViewsFrame;
- (void) _handleViewsVisibility; - (void) _handleViewsVisibility;
- (void) _reload; - (void) _reload;
- (void) _setToolbar: (GSToolbar *)toolbar; - (void) _setToolbar: (GSToolbar *)toolbar;
- (void) _takeInAccountFlexibleSpaces; - (void) _takeInAccountFlexibleSpaces;
- (int) _insertionIndexAtPoint: (NSPoint)location;
// Accessors // Accessors
- (float) _heightFromLayout; - (float) _heightFromLayout;
@ -190,6 +210,13 @@ static void initSystemExtensionsColors(void)
- (void) setToolbar: (GSToolbar *)toolbar; - (void) setToolbar: (GSToolbar *)toolbar;
@end @end
@interface GSToolbarClipView : NSClipView
{
}
@end
@implementation GSToolbarClippedItemsButton @implementation GSToolbarClippedItemsButton
- (id) init - (id) init
{ {
@ -279,6 +306,14 @@ static void initSystemExtensionsColors(void)
} }
@end @end
// ---
@implementation GSToolbarClipView
// Nothing here
@end
// Implementation GSToolbarView // Implementation GSToolbarView
@implementation GSToolbarView @implementation GSToolbarView
@ -314,19 +349,19 @@ static void initSystemExtensionsColors(void)
switch (_sizeMode) switch (_sizeMode)
{ {
case NSToolbarSizeModeDefault: case NSToolbarSizeModeDefault:
toolbarViewHeight = ToolbarViewDefaultHeight; toolbarViewHeight = ToolbarViewDefaultHeight;
break; break;
case NSToolbarSizeModeRegular: case NSToolbarSizeModeRegular:
toolbarViewHeight = ToolbarViewRegularHeight; toolbarViewHeight = ToolbarViewRegularHeight;
break; break;
case NSToolbarSizeModeSmall: case NSToolbarSizeModeSmall:
toolbarViewHeight = ToolbarViewSmallHeight; toolbarViewHeight = ToolbarViewSmallHeight;
break; break;
default: default:
// Raise exception // Raise exception
toolbarViewHeight = 0; toolbarViewHeight = 0;
} }
[self setFrame: NSMakeRect(frame.origin.x, [self setFrame: NSMakeRect(frame.origin.x,
frame.origin.y, frame.origin.y,
@ -335,7 +370,7 @@ static void initSystemExtensionsColors(void)
// --- // ---
_clipView = [[NSClipView alloc] initWithFrame: NSMakeRect(0, 0, 100, 100)]; _clipView = [[GSToolbarClipView alloc] initWithFrame: NSMakeRect(0, 0, 100, 100)];
[_clipView setAutoresizingMask: (NSViewWidthSizable | [_clipView setAutoresizingMask: (NSViewWidthSizable |
NSViewHeightSizable)]; NSViewHeightSizable)];
@ -355,6 +390,8 @@ static void initSystemExtensionsColors(void)
// deallocated with the class when the application quits. // deallocated with the class when the application quits.
// --- // ---
[self registerForDraggedTypes: [NSArray arrayWithObject: GSMovableToolbarItemPboardType]];
return self; return self;
} }
@ -380,6 +417,68 @@ static void initSystemExtensionsColors(void)
[super dealloc]; [super dealloc];
} }
// Dragging related methods
- (NSDragOperation) draggingEntered: (id <NSDraggingInfo>)info
{
if ([self _insertionIndexAtPoint: [info draggingLocation]] != NSNotFound);
{
return NSDragOperationGeneric;
}
return NSDragOperationNone;
}
- (NSDragOperation) draggingUpdated: (id <NSDraggingInfo>)info
{
if ([self _insertionIndexAtPoint: [info draggingLocation]] != NSNotFound);
{
return NSDragOperationGeneric;
}
return NSDragOperationNone;
}
- (void) draggingEnded: (id <NSDraggingInfo>)info
{
NSPasteboard *pboard = [info draggingPasteboard];
NSString *str = [pboard stringForType: [[pboard types] objectAtIndex: 0]];
int index = [str intValue];
GSToolbar *toolbar = [self toolbar];
[toolbar _concludeRemoveItem: [[info draggingSource] toolbarItem] atIndex: index broadcast: YES];
}
- (void) draggingExited: (id <NSDraggingInfo>)info
{
// Nothing to do
}
- (BOOL) prepareForDragOperation: (id <NSDraggingInfo>)info
{
return YES;
}
- (BOOL) performDragOperation: (id <NSDraggingInfo>)info
{
NSPasteboard *pboard = [info draggingPasteboard];
NSString *str = [pboard stringForType: [[pboard types] objectAtIndex: 0]];
int index = [str intValue];
GSToolbar *toolbar = [self toolbar];
NSToolbarItem *item = [[info draggingSource] toolbarItem];
int newIndex = [self _insertionIndexAtPoint: [info draggingLocation]]; // Calculate the index
[toolbar _insertPassivelyItem:item atIndex: index];
RELEASE(item);
[toolbar _moveItemFromIndex: index toIndex: newIndex broadcast: YES];
return YES;
}
- (void) concludeDragOperation: (id <NSDraggingInfo>)info
{
// Nothing to do currently
}
// More overrided methods // More overrided methods
- (void) drawRect: (NSRect)aRect - (void) drawRect: (NSRect)aRect
@ -756,6 +855,25 @@ static void initSystemExtensionsColors(void)
} }
- (int) _insertionIndexAtPoint: (NSPoint)location
{
id hitView = [self hitTest: location];
NSRect hitViewFrame = [hitView frame];;
int index;
if ((hitView != nil)
& ([hitView isKindOfClass: [GSToolbarButton class]]
|| [hitView isKindOfClass: [GSToolbarBackView class]]))
{
index = [_toolbar _indexOfItem: [hitView toolbarItem]];
if (location.x - hitViewFrame.origin.x > hitViewFrame.size.width / 2)
index++;
return index;
}
return NSNotFound;
}
// Accessors private methods // Accessors private methods
- (float) _heightFromLayout - (float) _heightFromLayout

View file

@ -29,21 +29,26 @@
*/ */
#include <Foundation/NSObject.h> #include <Foundation/NSObject.h>
#include <Foundation/NSString.h> #include <Foundation/NSArray.h>
#include <Foundation/NSDebug.h> #include <Foundation/NSDebug.h>
#include <Foundation/NSDictionary.h>
#include <Foundation/NSException.h>
#include <Foundation/NSString.h>
#include "AppKit/NSApplication.h" #include "AppKit/NSApplication.h"
#include "AppKit/NSToolbarItem.h"
#include "AppKit/NSMenu.h"
#include "AppKit/NSMenuItem.h"
#include "AppKit/NSImage.h"
#include "AppKit/NSButton.h" #include "AppKit/NSButton.h"
#include "AppKit/NSButtonCell.h" #include "AppKit/NSButtonCell.h"
#include "AppKit/NSFont.h" #include "AppKit/NSDragging.h"
#include "AppKit/NSEvent.h" #include "AppKit/NSEvent.h"
#include "AppKit/NSFont.h"
#include "AppKit/NSImage.h"
#include "AppKit/NSMenu.h"
#include "AppKit/NSMenuItem.h"
#include "AppKit/NSParagraphStyle.h" #include "AppKit/NSParagraphStyle.h"
#include "AppKit/NSPasteboard.h"
#include "AppKit/NSView.h"
#include "GNUstepGUI/GSToolbar.h" #include "GNUstepGUI/GSToolbar.h"
#include "GNUstepGUI/GSToolbarView.h" #include "GNUstepGUI/GSToolbarView.h"
#include "AppKit/NSToolbarItem.h"
/* /*
* Each NSToolbarItem object are coupled with a backView which is their representation * Each NSToolbarItem object are coupled with a backView which is their representation
@ -83,8 +88,13 @@ static NSFont *NormalFont = nil; // See NSToolbarItem -initialize method
static NSFont *SmallFont = nil; static NSFont *SmallFont = nil;
NSString *GSMovableToolbarItemPboardType = @"GSMovableToolbarItemPboardType";
@interface GSToolbar (GNUstepPrivate) @interface GSToolbar (GNUstepPrivate)
- (GSToolbarView *) _toolbarView; - (GSToolbarView *) _toolbarView;
- (int) _indexOfItem: (NSToolbarItem *)item; // Used by drag setup
- (void) _performRemoveItem: (NSToolbarItem *)item; // Used by drag setup
@end @end
@interface NSToolbarItem (GNUstepPrivate) @interface NSToolbarItem (GNUstepPrivate)
@ -260,15 +270,79 @@ static NSFont *SmallFont = nil;
} }
/*
* The code below should be kept in sync with GSToolbarBackView methods which have identical names
*/
- (void) mouseDown: (NSEvent *)event - (void) mouseDown: (NSEvent *)event
{ {
if ([_toolbarItem _selectable] && [self state]) if ([event modifierFlags] == NSCommandKeyMask)
return; // Abort in case the button is selectable and selected {
// HACK: must be improved to handle drag event NSSize viewSize = [self frame].size;
NSImage *image = [[NSImage alloc] initWithSize: viewSize];
[super mouseDown: event]; NSCell *cell = [self cell];
NSPasteboard *pboard;
GSToolbar *toolbar = [_toolbarItem toolbar];
int index;
AUTORELEASE(image);
// Prepare the drag
RETAIN(self); // We need to keep this view (aka self) to be able to draw the drag image.
// Draw the drag content in an image
// The code below is only partially supported by GNUstep, then NSImage needs to be improved
[image lockFocus];
[cell setShowsFirstResponder: NO]; // To remove the dotted rect
[cell drawWithFrame: NSMakeRect(0, 0, viewSize.width, viewSize.height) inView: nil];
[cell setShowsFirstResponder: YES];
[image unlockFocus];
pboard = [NSPasteboard pasteboardWithName: NSDragPboard];
[pboard declareTypes: [NSArray arrayWithObject: GSMovableToolbarItemPboardType] owner: nil];
index = [toolbar _indexOfItem: _toolbarItem];
[pboard setString: [NSString stringWithFormat:@"%d", index] forType: GSMovableToolbarItemPboardType];
[self dragImage: image
at: NSMakePoint(0.0, 0.0)
offset: NSMakeSize(0.0, 0.0)
event: event
pasteboard: pboard
source: self
slideBack: NO];
}
else
{
[super mouseDown: event];
}
} }
- (void) draggedImage: (NSImage *)dragImage beganAt: (NSPoint)location
{
GSToolbar *toolbar = [_toolbarItem toolbar];
RETAIN(_toolbarItem);
// We retain the toolbar item to be able to have have it reinsered later by the dragging destination.
[toolbar _performRemoveItem: _toolbarItem];
}
- (void) draggedImage: (NSImage *)dragImage endedAt: (NSPoint)location operation: (NSDragOperation)operation
{
RELEASE(self); // The view is no more needed : no more drawing to do with it.
}
- (unsigned int) draggingSourceOperationMaskForLocal: (BOOL)isLocal
{
return isLocal ? NSDragOperationGeneric : NSDragOperationNone;
}
/*
* End of the code to keep in sync
*/
- (BOOL) sendAction: (SEL)action to: (id)target - (BOOL) sendAction: (SEL)action to: (id)target
{ {
if ([_toolbarItem _selectable]) if ([_toolbarItem _selectable])
@ -341,7 +415,6 @@ static NSFont *SmallFont = nil;
* Please make sure the output remains always correct. * Please make sure the output remains always correct.
*/ */
// We ignore aRect value // We ignore aRect value
[aString drawInRect: titleRect]; [aString drawInRect: titleRect];
} }
@ -594,6 +667,90 @@ static NSFont *SmallFont = nil;
DESTROY(attrStr); DESTROY(attrStr);
} }
- (NSView *) hitTest: (NSPoint)point
{
NSEvent *event = [NSApp currentEvent];
if ([self mouse: point inRect: [self frame]]
&& [event modifierFlags] == NSCommandKeyMask
&& [event type] == NSLeftMouseDown)
{
return self;
}
else
{
return [super hitTest: point];
}
}
/*
* The code below should be kept in sync with GSToolbarButton methods which have identical names
*/
- (void) mouseDown: (NSEvent *)event
{
if ([event modifierFlags] == NSCommandKeyMask)
{
NSSize viewSize = [self frame].size;
NSImage *image = [[NSImage alloc] initWithSize: viewSize];
NSPasteboard *pboard;
GSToolbar *toolbar = [_toolbarItem toolbar];
int index;
AUTORELEASE(image);
// Prepare the drag
RETAIN(self); // We need to keep this view (aka self) to be able to draw the drag image.
// The code below is only partially supported by GNUstep, then NSImage needs to be improved
[image lockFocus];
[self drawRect: NSMakeRect(0, 0, viewSize.width, viewSize.height)];
[image unlockFocus];
pboard = [NSPasteboard pasteboardWithName: NSDragPboard];
[pboard declareTypes: [NSArray arrayWithObject: GSMovableToolbarItemPboardType] owner: nil];
index = [toolbar _indexOfItem: _toolbarItem];
[pboard setString: [NSString stringWithFormat:@"%d", index] forType: GSMovableToolbarItemPboardType];
[self dragImage: image
at: NSMakePoint(0.0, 0.0)
offset: NSMakeSize(0.0, 0.0)
event: event
pasteboard: pboard
source: self
slideBack: NO];
}
else
{
[super mouseDown: event];
}
}
- (void) draggedImage: (NSImage *)dragImage beganAt: (NSPoint)location
{
GSToolbar *toolbar = [_toolbarItem toolbar];
RETAIN(_toolbarItem);
// We retain the toolbar item to be able to have have it reinsered later by the dragging destination.
[toolbar _performRemoveItem: _toolbarItem];
}
- (void) draggedImage: (NSImage *)dragImage endedAt: (NSPoint)location operation: (NSDragOperation)operation
{
RELEASE(self); // The view is no more needed : no more drawing to do with it.
}
- (unsigned int) draggingSourceOperationMaskForLocal: (BOOL)isLocal
{
return isLocal ? NSDragOperationGeneric : NSDragOperationNone;
}
/*
* End of the code to keep in sync
*/
- (NSToolbarItem *)toolbarItem - (NSToolbarItem *)toolbarItem
{ {
return _toolbarItem; return _toolbarItem;