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:
Quentin Mathe 2004-09-02 17:40:00 +00:00
parent 19e45d5c7b
commit ef1010acc4
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>
* Source/NSPrintInfo.m ([NSPrintInfo -paperSize]): Avoid returning

View file

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

View file

@ -32,18 +32,19 @@
#include <Foundation/NSArray.h>
#include <Foundation/NSDictionary.h>
#include <Foundation/NSException.h>
#include <Foundation/NSKeyValueCoding.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 "AppKit/NSApplication.h"
#include "AppKit/NSEvent.h"
#include "AppKit/NSMenu.h"
#include "AppKit/NSNibLoading.h"
#include "AppKit/NSToolbarItem.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+Toolbar.h"
#include "GNUstepGUI/GSToolbarView.h"
@ -482,9 +483,14 @@ static GSValidationCenter *vc;
- (void) _setConfigurationFromDictionary: (NSDictionary *)configDict
broadcast: (BOOL)broadcast;
- (void) _setDelegate: (id)delegate broadcast: (BOOL)broadcast;
- (void) _moveItemFromIndex: (int)index toIndex: (int)newIndex broadcast: (BOOL)broadcast;
// Few other private methods
- (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;
- (NSToolbarItem *) _toolbarItemForIdentifier: (NSString *)itemIdent;
- (GSToolbar *) _toolbarModel;
@ -898,6 +904,23 @@ static GSValidationCenter *vc;
_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
{
if (_identifier != nil)
@ -1034,15 +1057,25 @@ static GSValidationCenter *vc;
- (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]);
[_items removeObjectAtIndex: index];
- (void) _performRemoveItem: (NSToolbarItem *)item
{
[_items removeObject: item];
[_toolbarView _reload];
}
- (void) _concludeRemoveItem: (NSToolbarItem *)item atIndex: (int)index broadcast: (BOOL)broadcast
{
[nc postNotificationName: NSToolbarDidRemoveItemNotification
object: self
userInfo: [NSDictionary dictionaryWithObject: item forKey: @"item"]];
RELEASE(item);
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
- (void) _setToolbarView: (GSToolbarView *)toolbarView

View file

@ -29,19 +29,24 @@
#include <Foundation/NSObject.h>
#include <Foundation/NSArray.h>
#include <Foundation/NSDictionary.h>
#include <Foundation/NSException.h>
#include <Foundation/NSNotification.h>
#include <Foundation/NSUserDefaults.h>
#include <Foundation/NSString.h>
#include "AppKit/NSToolbarItem.h"
#include "AppKit/NSBezierPath.h"
#include "AppKit/NSButton.h"
#include "AppKit/NSClipView.h"
#include "AppKit/NSColor.h"
#include "AppKit/NSColorList.h"
#include "AppKit/NSDragging.h"
#include "AppKit/NSEvent.h"
#include "AppKit/NSImage.h"
#include "AppKit/NSMenu.h"
#include "AppKit/NSPasteboard.h"
#include "AppKit/NSToolbarItem.h" // It contains GSMovableToolbarItemPboardType declaration
#include "AppKit/NSView.h"
#include "AppKit/NSWindow.h"
#include "GNUstepGUI/GSToolbar.h"
#include "GNUstepGUI/GSToolbarView.h"
typedef enum {
@ -138,6 +143,12 @@ static void initSystemExtensionsColors(void)
*/
@interface GSToolbar (GNUstepPrivate)
- (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;
// Accessors
@ -155,12 +166,21 @@ static void initSystemExtensionsColors(void)
- (BOOL) _isFlexibleSpace;
@end
@interface GSToolbarButton
- (NSToolbarItem *) toolbarItem;
@end
@interface GSToolbarBackView
- (NSToolbarItem *) toolbarItem;
@end
@interface GSToolbarView (GNUstepPrivate)
- (void) _handleBackViewsFrame;
- (void) _handleViewsVisibility;
- (void) _reload;
- (void) _setToolbar: (GSToolbar *)toolbar;
- (void) _takeInAccountFlexibleSpaces;
- (int) _insertionIndexAtPoint: (NSPoint)location;
// Accessors
- (float) _heightFromLayout;
@ -190,6 +210,13 @@ static void initSystemExtensionsColors(void)
- (void) setToolbar: (GSToolbar *)toolbar;
@end
@interface GSToolbarClipView : NSClipView
{
}
@end
@implementation GSToolbarClippedItemsButton
- (id) init
{
@ -279,6 +306,14 @@ static void initSystemExtensionsColors(void)
}
@end
// ---
@implementation GSToolbarClipView
// Nothing here
@end
// Implementation GSToolbarView
@implementation GSToolbarView
@ -314,19 +349,19 @@ static void initSystemExtensionsColors(void)
switch (_sizeMode)
{
case NSToolbarSizeModeDefault:
toolbarViewHeight = ToolbarViewDefaultHeight;
break;
case NSToolbarSizeModeRegular:
toolbarViewHeight = ToolbarViewRegularHeight;
break;
case NSToolbarSizeModeSmall:
toolbarViewHeight = ToolbarViewSmallHeight;
break;
default:
// Raise exception
toolbarViewHeight = 0;
}
case NSToolbarSizeModeDefault:
toolbarViewHeight = ToolbarViewDefaultHeight;
break;
case NSToolbarSizeModeRegular:
toolbarViewHeight = ToolbarViewRegularHeight;
break;
case NSToolbarSizeModeSmall:
toolbarViewHeight = ToolbarViewSmallHeight;
break;
default:
// Raise exception
toolbarViewHeight = 0;
}
[self setFrame: NSMakeRect(frame.origin.x,
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 |
NSViewHeightSizable)];
@ -355,6 +390,8 @@ static void initSystemExtensionsColors(void)
// deallocated with the class when the application quits.
// ---
[self registerForDraggedTypes: [NSArray arrayWithObject: GSMovableToolbarItemPboardType]];
return self;
}
@ -380,6 +417,68 @@ static void initSystemExtensionsColors(void)
[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
- (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
- (float) _heightFromLayout

View file

@ -29,21 +29,26 @@
*/
#include <Foundation/NSObject.h>
#include <Foundation/NSString.h>
#include <Foundation/NSArray.h>
#include <Foundation/NSDebug.h>
#include <Foundation/NSDictionary.h>
#include <Foundation/NSException.h>
#include <Foundation/NSString.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/NSButtonCell.h"
#include "AppKit/NSFont.h"
#include "AppKit/NSDragging.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/NSPasteboard.h"
#include "AppKit/NSView.h"
#include "GNUstepGUI/GSToolbar.h"
#include "GNUstepGUI/GSToolbarView.h"
#include "AppKit/NSToolbarItem.h"
/*
* 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;
NSString *GSMovableToolbarItemPboardType = @"GSMovableToolbarItemPboardType";
@interface GSToolbar (GNUstepPrivate)
- (GSToolbarView *) _toolbarView;
- (int) _indexOfItem: (NSToolbarItem *)item; // Used by drag setup
- (void) _performRemoveItem: (NSToolbarItem *)item; // Used by drag setup
@end
@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
{
if ([_toolbarItem _selectable] && [self state])
return; // Abort in case the button is selectable and selected
// HACK: must be improved to handle drag event
[super mouseDown: event];
if ([event modifierFlags] == NSCommandKeyMask)
{
NSSize viewSize = [self frame].size;
NSImage *image = [[NSImage alloc] initWithSize: viewSize];
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
{
if ([_toolbarItem _selectable])
@ -341,7 +415,6 @@ static NSFont *SmallFont = nil;
* Please make sure the output remains always correct.
*/
// We ignore aRect value
[aString drawInRect: titleRect];
}
@ -594,6 +667,90 @@ static NSFont *SmallFont = nil;
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
{
return _toolbarItem;