Update front-end support for registering dnd types.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@4407 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
richard 1999-06-15 09:23:39 +00:00
parent d0b2bf42c6
commit a967db2efb
8 changed files with 240 additions and 126 deletions

View file

@ -1,37 +0,0 @@
/*
GSDragManager.h
Copyright (C) 1999 Free Software Foundation, Inc.
Author: Richard Frith-Macdonald <richard@brainstorm.co.uk>
Date: June 1999
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_GSDragManager
#define _GNUstep_H_GSDragManager
#include <Foundation/Foundation.h>
NSArray *GSGetDragTypes(id obj);
void GSRegisterDragTypes(id obj, NSArray *types);
void GSUnregisterDragTypes(id obj);
#endif

View file

@ -31,6 +31,8 @@
#include <Foundation/NSObject.h>
#include <Foundation/NSGeometry.h>
#include <Foundation/NSMapTable.h>
#include <Foundation/NSSet.h>
#include <AppKit/GSMethodTable.h>
@ -100,6 +102,7 @@ typedef enum _NSWindowOrderingMode
NSMutableData *context_data;
NSMutableArray *focus_stack;
NSMutableArray *event_queue;
NSMapTable *drag_types;
}
+ (NSGraphicsContext*) currentContext;
@ -129,6 +132,13 @@ NSGraphicsContext *GSCurrentContext();
- (void) lockFocusView: (NSView*)aView inRect: (NSRect)rect;
- (void) unlockFocusView: (NSView*)aView needsFlush: (BOOL)flush;
/*
* Drag and drop support
*/
- (BOOL) _addDragTypes: (NSArray*)types toWindow: (int)winNum;
- (BOOL) _removeDragTypes: (NSArray*)types fromWindow: (int)winNum;
- (NSCountedSet*) _dragTypesForWindow: (int)winNum;
@end
#endif

View file

@ -378,6 +378,10 @@ enum {
@end
#endif
/*
* GNUstep specific function to determine the drag types registered for a view.
*/
extern NSArray *GSGetDragTypes(NSView* aView);
/* Notifications */
extern NSString *NSViewFrameDidChangeNotification;

View file

@ -109,7 +109,6 @@ NSView.m \
NSWindow.m \
NSWorkspace.m \
GSTrackingRect.m \
GSDragManager.m \
GSServicesManager.m \
tiff.m \
externs.m
@ -213,7 +212,6 @@ AppKit/GSMethodTable.h \
AppKit/DPSOperators.h \
AppKit/PSOperators.h \
AppKit/GSPasteboardServer.h \
AppKit/GSDragManager.h \
AppKit/GSServicesManager.h
-include GNUmakefile.preamble

View file

@ -1,75 +0,0 @@
/*
GSDragManager.m
Copyright (C) 1999 Free Software Foundation, Inc.
Author: Richard Frith-Macdonald <richard@brainstorm.co.uk>
Date: June 1999
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 <gnustep/gui/config.h>
#include <Foundation/Foundation.h>
#include <AppKit/AppKit.h>
/*
* Stuff to maintain a map table so we know what windows and views are
* registered for drag and drop.
* FIXME - may need locks for thread safety?
*/
static NSMapTable *typesMap = 0;
static inline void
GSSetupDragTypes()
{
if (typesMap == 0)
{
typesMap = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks,
NSObjectMapValueCallBacks, 0);
}
}
NSArray*
GSGetDragTypes(id obj)
{
GSSetupDragTypes();
return NSMapGet(typesMap, (void*)(gsaddr)obj);
}
void
GSRegisterDragTypes(id obj, NSArray *types)
{
NSArray *m = [types mutableCopy];
NSArray *t = [m copy];
RELEASE(m);
GSSetupDragTypes();
NSMapInsert(typesMap, (void*)(gsaddr)obj, (void*)(gsaddr)t);
RELEASE(t);
}
void
GSUnregisterDragTypes(id obj)
{
GSSetupDragTypes();
NSMapRemove(typesMap, (void*)(gsaddr)obj);
}

View file

@ -155,6 +155,7 @@ struct NSWindow_struct
DESTROY(context_data);
DESTROY(context_info);
DESTROY(event_queue);
NSFreeMapTable(drag_types);
[super dealloc];
}
@ -182,6 +183,8 @@ struct NSWindow_struct
initWithCapacity: 1];
event_queue = [[NSMutableArray allocWithZone: [self zone]]
initWithCapacity: 32];
drag_types = NSCreateMapTable(NSIntMapKeyCallBacks,
NSObjectMapValueCallBacks, 0);
/*
* The classMethodTable dictionary and the list of all contexts must both
@ -263,6 +266,90 @@ struct NSWindow_struct
[focus_stack removeLastObject];
}
/*
* Drag and drop support
*/
/*
* Add (increment count by 1) each drag type to those registered
* for the window. If this results in a change to the types registered
* in the counted set, return YES, otherwise return NO.
* Subclasses should override this method, call 'super' and take
* appropriate action if the method returns 'YES'.
*/
- (BOOL) _addDragTypes: (NSArray*)types toWindow: (int)winNum
{
NSCountedSet *old = (NSCountedSet*)NSMapGet(drag_types, winNum);
unsigned originalCount;
unsigned i = [types count];
/*
* Make sure the set exists.
*/
if (old == nil)
{
old = [NSCountedSet new];
NSMapInsert(drag_types, (void*)winNum, (void*)(gsaddr)old);
RELEASE(old);
}
originalCount = [old count];
while (i-- > 0)
{
id o = [types objectAtIndex: i];
[old removeObject: o];
}
if ([old count] == originalCount)
return NO;
return YES;
}
/*
* Remove (decrement count by 1) each drag type from those registered
* for the window. If this results in a change to the types registered
* in the counted set, return YES, otherwise return NO.
* If given 'nil' as the array of types, remove ALL.
* Subclasses should override this method, call 'super' and take
* appropriate action if the method returns 'YES'.
*/
- (BOOL) _removeDragTypes: (NSArray*)types fromWindow: (int)winNum
{
NSCountedSet *old = (NSCountedSet*)NSMapGet(drag_types, winNum);
if (types == nil)
{
if (old == nil)
return NO;
NSMapRemove(drag_types, (void*)winNum);
return YES;
}
else if (old == nil)
{
return NO;
}
else
{
unsigned originalCount = [old count];
unsigned i = [types count];
while (i-- > 0)
{
id o = [types objectAtIndex: i];
[old removeObject: o];
}
if ([old count] == originalCount)
return NO;
return YES;
}
}
- (NSCountedSet*) _dragTypesForWindow: (int)winNum
{
return (NSCountedSet*)NSMapGet(drag_types, winNum);
}
@end
@implementation NSGraphicsContext (Private)

View file

@ -47,7 +47,6 @@
#include <AppKit/NSView.h>
#include <AppKit/NSWindow.h>
#include <AppKit/GSDragManager.h>
#include <AppKit/GSTrackingRect.h>
#include <AppKit/NSAffineTransform.h>
@ -67,6 +66,72 @@ static SEL appSel = @selector(appendTransform:);
static void (*invalidateImp)(NSView*, SEL) = 0;
static SEL invalidateSel = @selector(_invalidateCoordinates);
/*
* Stuff to maintain a map table so we know what views are
* registered for drag and drop - we don't store the info in
* the view directly 'cot it would take up a pointer in each
* view and the vast majority of views wouldn't use it.
* Types are not registered/unregistered often enough for the
* performance of this mechanism to be an issue.
*/
static NSMapTable *typesMap = 0;
static NSLock *typesLock = nil;
/*
* This is the only external interface to the drag types info.
*/
NSArray*
GSGetDragTypes(NSView *obj)
{
NSArray *t;
[typesLock lock];
t = (NSArray*)NSMapGet(typesMap, (void*)(gsaddr)obj);
[typesLock unlock];
return t;
}
static void
GSRemoveDragTypes(NSView* obj)
{
[typesLock lock];
NSMapRemove(typesMap, (void*)(gsaddr)obj);
[typesLock unlock];
}
static NSArray*
GSSetDragTypes(NSView* obj, NSArray *types)
{
unsigned count = [types count];
NSString *strings[count];
NSArray *t;
unsigned i;
/*
* Make a new array with copies of the type strings so we don't get
* them mutated by someone else.
*/
[types getObjects: strings];
for (i = 0; i < count; i++)
{
strings[i] = [strings[i] copy];
}
t = [NSArray arrayWithObjects: strings count: count];
for (i = 0; i < count; i++)
{
RELEASE(strings[i]);
}
/*
* Store it.
*/
[typesLock lock];
NSMapInsert(typesMap, (void*)(gsaddr)obj, (void*)(gsaddr)t);
[typesLock unlock];
return t;
}
/*
* Class methods
*/
@ -77,6 +142,10 @@ static SEL invalidateSel = @selector(_invalidateCoordinates);
Class matrixClass = [NSAffineTransform class];
NSAffineTransformStruct ats = { 1, 0, 0, -1, 0, 1 };
typesMap = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks,
NSObjectMapValueCallBacks, 0);
typesLock = [NSLock new];
appImp = (void (*)(NSAffineTransform*, SEL, NSAffineTransform*))
[matrixClass instanceMethodForSelector: appSel];
@ -405,7 +474,21 @@ static SEL invalidateSel = @selector(_invalidateCoordinates);
- (void) viewWillMoveToWindow: (NSWindow*)newWindow
{
if (newWindow == window)
return;
if (_rFlags.has_draginfo)
{
NSGraphicsContext *ctxt = GSCurrentContext();
NSArray *t = GSGetDragTypes(self);
if (window != nil)
[ctxt _removeDragTypes: t fromWindow: [window windowNumber]];
[ctxt _addDragTypes: t toWindow: [newWindow windowNumber]];
}
window = newWindow;
if (_rFlags.has_subviews)
{
unsigned count = [sub_views count];
@ -1772,17 +1855,56 @@ static NSView* findByTag(NSView *view, int aTag, unsigned *level)
slideBack: (BOOL)slideFlag
{}
- (void) registerForDraggedTypes: (NSArray*)newTypes
- (void) registerForDraggedTypes: (NSArray*)types
{
GSRegisterDragTypes(self, newTypes);
NSArray *o;
NSArray *t;
if (types == nil || [types count] == 0)
[NSException raise: NSInvalidArgumentException
format: @"Types information missing"];
/*
* Get the old drag types for this view if we need to tell the context
* to change the registered types for the window.
*/
if (_rFlags.has_draginfo == 1 && window != nil)
{
o = GSGetDragTypes(self);
TEST_RETAIN(o);
}
else
{
o = nil;
}
t = GSSetDragTypes(self, types);
_rFlags.has_draginfo = 1;
if (window != nil)
{
NSGraphicsContext *ctxt = GSCurrentContext();
[ctxt _addDragTypes: t toWindow: [window windowNumber]];
if (o != nil)
{
[ctxt _removeDragTypes: t fromWindow: [window windowNumber]];
}
}
TEST_RELEASE(o);
}
- (void) unregisterDraggedTypes
{
if (_rFlags.has_draginfo)
{
GSUnregisterDragTypes(self);
if (window != nil)
{
NSGraphicsContext *ctxt = GSCurrentContext();
NSArray *t = GSGetDragTypes(self);
[ctxt _removeDragTypes: t fromWindow: [window windowNumber]];
}
GSRemoveDragTypes(self);
_rFlags.has_draginfo = 0;
}
}

View file

@ -181,7 +181,12 @@ static Class responderClass;
TEST_RELEASE(miniaturized_image);
TEST_RELEASE(window_title);
TEST_RELEASE(rectsBeingDrawn);
[self unregisterDraggedTypes];
/*
* FIXME This should not be necessary - the views should have removed
* their drag types, so we should already have been removed.
*/
[GSCurrentContext() _removeDragTypes: nil fromWindow: [self windowNumber]];
[super dealloc];
}
@ -1464,17 +1469,17 @@ static Class responderClass;
- (void) registerForDraggedTypes: (NSArray*)newTypes
{
GSRegisterDragTypes(self, newTypes);
_rFlags.has_draginfo = 1;
/*
* Ensure we have a content view and it's associated window view.
*/
if (content_view == nil)
[self setContentView: nil];
[[content_view superView] registerForDraggedTypes: newTypes];
}
- (void) unregisterDraggedTypes
{
if (_rFlags.has_draginfo)
{
GSUnregisterDragTypes(self);
_rFlags.has_draginfo = 0;
}
[[content_view superView] unregisterDraggedTypes];
}
/*