Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add uiDragDestination for text and file drop. #245

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
3 changes: 3 additions & 0 deletions common/control.c
Expand Up @@ -4,6 +4,8 @@

void uiControlDestroy(uiControl *c)
{
if (c->dragDest != NULL)
uiprivControlDestroyDragDestination(c);
(*(c->Destroy))(c);
}

Expand Down Expand Up @@ -67,6 +69,7 @@ uiControl *uiAllocControl(size_t size, uint32_t OSsig, uint32_t typesig, const c
c->Signature = uiprivControlSignature;
c->OSSignature = OSsig;
c->TypeSignature = typesig;
c->dragDest = NULL;
return c;
}

Expand Down
77 changes: 77 additions & 0 deletions common/dragdestination.c
@@ -0,0 +1,77 @@
#include "../ui.h"
#include "uipriv.h"

uiDragOperation defaultOnEnter(uiDragDestination *dd, uiDragContext *dc, void *data)
{
return uiDragOperationNone;
}

uiDragOperation defaultOnMove(uiDragDestination *dd, uiDragContext *dc, void *data)
{
return uiDragDestinationLastDragOperation(dd);
}

void defaultOnExit(uiDragDestination *dd, void *data)
{
// do nothing
}

int defaultOnDrop(uiDragDestination *dd, uiDragContext *dc, void *senderData)
{
return 0;
}

void uiDragDestinationOnEnter(uiDragDestination *dd, uiDragOperation (*f)(uiDragDestination *, uiDragContext *, void *), void *data)
{
dd->onEnter = f;
dd->onEnterData = data;
}

void uiDragDestinationOnMove(uiDragDestination *dd, uiDragOperation (*f)(uiDragDestination *, uiDragContext *, void *), void *data)
{
dd->onMove = f;
dd->onMoveData = data;
}

void uiDragDestinationOnExit(uiDragDestination *dd, void (*f)(uiDragDestination *, void *), void *data)
{
dd->onExit = f;
dd->onExitData = data;
}

void uiDragDestinationOnDrop(uiDragDestination *dd, int (*f)(uiDragDestination *, uiDragContext *, void *), void *data)
{
dd->onDrop = f;
dd->onDropData = data;
}

void uiDragDestinationSetAcceptTypes(uiDragDestination* dd, int typeMask)
{
dd->typeMask = typeMask;
}

int uiDragDestinationAcceptTypes(uiDragDestination* dd)
{
return dd->typeMask;
}

uiDragOperation uiDragDestinationLastDragOperation(uiDragDestination* dd)
{
return dd->op;
}

uiDragDestination* uiNewDragDestination(void)
{
uiDragDestination *dd;

dd = uiprivNew(uiDragDestination);
dd->typeMask = 0;

uiDragDestinationOnEnter(dd, defaultOnEnter, NULL);
uiDragDestinationOnMove(dd, defaultOnMove, NULL);
uiDragDestinationOnExit(dd, defaultOnExit, NULL);
uiDragDestinationOnDrop(dd, defaultOnDrop, NULL);

return dd;
}

1 change: 1 addition & 0 deletions common/meson.build
Expand Up @@ -7,6 +7,7 @@ libui_sources += [
'common/areaevents.c',
'common/control.c',
'common/debug.c',
'common/dragdestination.c',
'common/matrix.c',
'common/opentype.c',
'common/shouldquit.c',
Expand Down
20 changes: 20 additions & 0 deletions common/uipriv.h
Expand Up @@ -62,6 +62,26 @@ extern void uiprivFallbackTransformSize(uiDrawMatrix *, double *, double *);
// OS-specific text.* files
extern int uiprivStricmp(const char *a, const char *b);

// dragdestination.c
struct uiDragDestination {
uiControl *control;
uiDragOperation (*onEnter)(uiDragDestination *, uiDragContext *, void *);
uiDragOperation (*onMove)(uiDragDestination *, uiDragContext *, void *);
void (*onExit)(uiDragDestination *, void *);
int (*onDrop)(uiDragDestination *, uiDragContext *, void *);
void *onEnterData;
void *onMoveData;
void *onExitData;
void *onDropData;

uiDragOperation op;
int typeMask;
void *priv;
};

// control.c
extern void uiprivControlDestroyDragDestination(uiControl *c);

#ifdef __cplusplus
}
#endif
4 changes: 3 additions & 1 deletion darwin/box.m
Expand Up @@ -11,7 +11,7 @@ @interface boxChild : NSObject
- (NSView *)view;
@end

@interface boxView : NSView {
@interface boxView : NSView<NSDraggingDestination> {
uiBox *b;
NSMutableArray *children;
BOOL vertical;
Expand Down Expand Up @@ -62,6 +62,8 @@ - (NSView *)view

@implementation boxView

uiDarwinDragDestinationMethods(b)

- (id)initWithVertical:(BOOL)vert b:(uiBox *)bb
{
self = [super initWithFrame:NSZeroRect];
Expand Down
4 changes: 3 additions & 1 deletion darwin/button.m
Expand Up @@ -8,7 +8,7 @@
void *onClickedData;
};

@interface uiprivButton : NSButton {
@interface uiprivButton : NSButton<NSDraggingDestination> {
uiButton *button;
}
- (id)initWithFrame:(NSRect)frame uiButton:(uiButton *)b;
Expand All @@ -17,6 +17,8 @@ - (IBAction)onClicked:(id)sender;

@implementation uiprivButton

uiDarwinDragDestinationMethods(button)

- (id)initWithFrame:(NSRect)frame uiButton:(uiButton *)b
{
self = [super initWithFrame:frame];
Expand Down
4 changes: 3 additions & 1 deletion darwin/checkbox.m
Expand Up @@ -8,7 +8,7 @@
void *onToggledData;
};

@interface uiprivCheckbox : NSButton {
@interface uiprivCheckbox : NSButton<NSDraggingDestination> {
uiCheckbox *checkbox;
}
- (id)initWithFrame:(NSRect)frame uiCheckbox:(uiCheckbox *)c;
Expand All @@ -17,6 +17,8 @@ - (IBAction)onToggled:(id)sender;

@implementation uiprivCheckbox

uiDarwinDragDestinationMethods(checkbox)

- (id)initWithFrame:(NSRect)frame uiCheckbox:(uiCheckbox *)c
{
self = [super initWithFrame:frame];
Expand Down
4 changes: 3 additions & 1 deletion darwin/colorbutton.m
Expand Up @@ -3,7 +3,7 @@

// TODO no intrinsic height?

@interface colorButton : NSColorWell {
@interface colorButton : NSColorWell<NSDraggingDestination> {
uiColorButton *libui_b;
BOOL libui_changing;
BOOL libui_setting;
Expand All @@ -26,6 +26,8 @@ - (void)libuiSetColor:(double)r g:(double)g b:(double)b a:(double)a;

@implementation colorButton

uiDarwinDragDestinationMethods(libui_b)

- (id)initWithFrame:(NSRect)frame libuiColorButton:(uiColorButton *)b
{
self = [super initWithFrame:frame];
Expand Down
4 changes: 3 additions & 1 deletion darwin/combobox.m
Expand Up @@ -12,7 +12,7 @@
void *onSelectedData;
};

@interface uiprivCombobox : NSPopUpButton {
@interface uiprivCombobox : NSPopUpButton<NSDraggingDestination> {
uiCombobox *combobox;
}
- (id)initWithFrame:(NSRect)frame uiCombobox:(uiCombobox *)c;
Expand All @@ -21,6 +21,8 @@ - (IBAction)onSelected:(id)sender;

@implementation uiprivCombobox

uiDarwinDragDestinationMethods(combobox)

- (id)initWithFrame:(NSRect)frame uiCombobox:(uiCombobox *)c
{
self = [super initWithFrame:frame pullsDown:NO];
Expand Down
31 changes: 31 additions & 0 deletions darwin/control.m
Expand Up @@ -82,3 +82,34 @@ void uiDarwinNotifyVisibilityChanged(uiDarwinControl *c)
if (parent != NULL)
uiDarwinControlChildVisibilityChanged(uiDarwinControl(parent));
}

void uiprivControlDestroyDragDestination(uiControl *c)
{
[(id)uiControlHandle(c) unregisterDraggedTypes];
uiprivFree(c->dragDest);
c->dragDest = NULL;
}

void uiControlRegisterDragDestination(uiControl *c, uiDragDestination *dd)
{
NSMutableArray *types;
if (c->dragDest != NULL)
uiprivControlDestroyDragDestination(c);

if (dd == NULL)
return;

c->dragDest = dd;

types = [NSMutableArray new];
if (dd->typeMask & uiDragTypeURIs) {
[types addObject:NSFilenamesPboardType];
}
if (dd->typeMask & uiDragTypeText) {
[types addObject:NSStringPboardType];
}

[(id)uiControlHandle(c) registerForDraggedTypes:types];
[types release];
}

4 changes: 3 additions & 1 deletion darwin/datetimepicker.m
Expand Up @@ -11,7 +11,7 @@

// TODO see if target-action works here or not; I forgot what cody271@ originally said
// the primary advantage of the delegate is the ability to reject changes, but libui doesn't support that yet — we should consider that API option as well
@interface uiprivDatePicker : NSDatePicker<NSDatePickerCellDelegate> {
@interface uiprivDatePicker : NSDatePicker<NSDatePickerCellDelegate, NSDraggingDestination> {
uiDateTimePicker *picker;
}
- (id)initWithElements:(NSDatePickerElementFlags)elements uiDateTimePicker:(uiDateTimePicker *)d;
Expand All @@ -21,6 +21,8 @@ - (void)doTimer:(NSTimer *)timer;

@implementation uiprivDatePicker

uiDarwinDragDestinationMethods(picker)

- (id)initWithElements:(NSDatePickerElementFlags)elements uiDateTimePicker:(uiDateTimePicker *)d
{
self = [super initWithFrame:NSZeroRect];
Expand Down
81 changes: 81 additions & 0 deletions darwin/dragcontext.m
@@ -0,0 +1,81 @@
#import "uipriv_darwin.h"

void uiDragContextPosition(uiDragContext *dc, int *x, int *y)
{
NSPoint pt = [dc->info draggingLocation];
*x = pt.x;
*y = dc->view.frame.size.height - pt.y;
}

int uiDragContextDragTypes(uiDragContext *dc)
{
int types = 0;
NSPasteboard *pboard = [dc->info draggingPasteboard];

if ([[pboard types] containsObject:NSStringPboardType])
types |= uiDragTypeText;
if ([[pboard types] containsObject:NSFilenamesPboardType])
types |= uiDragTypeURIs;

return types;
}

int uiDragContextDragOperations(uiDragContext *dc)
{
int ops = uiDragOperationNone;
NSDragOperation mask = [dc->info draggingSourceOperationMask];

if (mask & NSDragOperationCopy)
ops |= uiDragOperationCopy;
if (mask & NSDragOperationLink)
ops |= uiDragOperationLink;
if (mask & NSDragOperationMove)
ops |= uiDragOperationMove;

return ops;
}

uiDragData* uiDragContextDragData(uiDragContext *dc, uiDragType type)
{
uiDragData *d = NULL;
NSPasteboard *pboard = [dc->info draggingPasteboard];

switch (type) {
case uiDragTypeURIs:
{
if ([[pboard types] containsObject:NSFilenamesPboardType]) {
int i;
NSArray *urls = [pboard propertyListForType:NSFilenamesPboardType];

// TODO inform about failure?
if (urls == nil)
return NULL;

d = uiprivNew(uiDragData);
d->type = uiDragTypeURIs;
d->data.URIs.numURIs = [urls count];
d->data.URIs.URIs = uiprivAlloc(d->data.URIs.numURIs * sizeof(*d->data.URIs.URIs), "uiDrag DropData->data.URIs.URIs");
for (i = 0; i < d->data.URIs.numURIs; ++i)
d->data.URIs.URIs[i] = uiDarwinNSStringToText(urls[i]);
}
}
break;
case uiDragTypeText:
{
if ([[pboard types] containsObject:NSStringPboardType]) {
NSString *text = [pboard stringForType:NSStringPboardType];

// TODO inform about failure?
if (text == nil)
return NULL;

d = uiprivNew(uiDragData);
d->type = uiDragTypeText;
d->data.text = uiDarwinNSStringToText(text);
}
}
break;
}
return d;
}

20 changes: 20 additions & 0 deletions darwin/dragdata.m
@@ -0,0 +1,20 @@
#import "uipriv_darwin.h"

void uiFreeDragData(uiDragData *d)
{
int i;

switch (d->type) {
case uiDragTypeText:
uiFreeText(d->data.text);
break;
case uiDragTypeURIs:
for (i = 0; i < d->data.URIs.numURIs; ++i)
uiFreeText(d->data.URIs.URIs[i]);
if (d->data.URIs.URIs != NULL)
uiprivFree(d->data.URIs.URIs);
break;
}
uiprivFree(d);
}

17 changes: 17 additions & 0 deletions darwin/dragdestination.m
@@ -0,0 +1,17 @@
#import "uipriv_darwin.h"

NSDragOperation uiprivDragOperationToNSDragOperation(uiDragOperation op)
{
switch (op) {
case uiDragOperationNone:
return NSDragOperationNone;
case uiDragOperationCopy:
return NSDragOperationCopy;
case uiDragOperationLink:
return NSDragOperationLink;
case uiDragOperationMove:
return NSDragOperationMove;
}
return NSDragOperationNone;
}