mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-27 16:40:44 +00:00
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:
parent
d0b2bf42c6
commit
a967db2efb
8 changed files with 240 additions and 126 deletions
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -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)
|
||||
|
|
130
Source/NSView.m
130
Source/NSView.m
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue