summaryrefslogtreecommitdiff
path: root/examples/howto-drag-and-drop.cxx
blob: 72e32996d6391ccfc0401706421a7c10a0775c35 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//
// A simple demo of 'drag and drop' with FLTK.
// Originally from erco's cheat sheet, permission by author.
// Inspired by Michael Sephton's original example posted on fltk.general.
//
// When you run the program, just drag the red square over
// to the green square to show a 'drag and drop' sequence.
//
// You can also drag and drop text from another application over
// to the green square to show a 'drag and drop' sequence.
//
// Copyright 1998-2017 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file.  If this
// file is missing or damaged, see the license at:
//
//     https://www.fltk.org/COPYING.php
//
// Please see the following page on how to report bugs and issues:
//
//     https://www.fltk.org/bugs.php
//

#include <stdio.h>
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Box.H>
#include <FL/fl_ask.H> // fl_message()

// SIMPLE SENDER CLASS
class Sender : public Fl_Box {
public:
  // Ctor
  Sender(int x,int y,int w,int h) : Fl_Box(x,y,w,h) {
    box(FL_FLAT_BOX);
    color(9);
    label("Drag\nfrom\nhere..");
  }
  // Sender event handler
  int handle(int event) FL_OVERRIDE {
    int ret = Fl_Box::handle(event);
    switch ( event ) {
      case FL_PUSH: {             // do 'copy/dnd' when someone clicks on box
        const char *msg = "It works!";
        Fl::copy(msg, (int)strlen(msg), 0);
        Fl::dnd();
        ret = 1;
        break;
      }
    }
    return(ret);
  }
};
// SIMPLE RECEIVER CLASS
class Receiver : public Fl_Box {
  int dnd_inside;
  char *dnd_text;
public:
  // Ctor
  Receiver(int x,int y,int w,int h) : Fl_Box(x,y,w,h) {
    box(FL_FLAT_BOX); color(10); label("..to\nhere");
    dnd_inside = 0;
    dnd_text = 0;
  }
  // Receiver event handler
  int handle(int event) FL_OVERRIDE {
    int ret = Fl_Box::handle(event);
    int len;
    switch ( event ) {
      case FL_DND_ENTER:        // return(1) for this event to 'accept' dnd
        label("ENTER");         // visible only if you stop the mouse at the widget's border
        fprintf(stderr, "FL_DND_ENTER\n");
        dnd_inside = 1;         // status: inside the widget, accept drop
        ret = 1;
        break;
      case FL_DND_DRAG:         // return(1) for this event to 'accept' dnd
        label("drop\nhere");
        fprintf(stderr, "FL_DND_DRAG\n");
        ret = 1;
        break;
      case FL_DND_RELEASE:      // return(1) for this event to 'accept' the payload (drop)
        fprintf(stderr, "FL_DND_RELEASE\n");
        if (dnd_inside) {
          ret = 1;              // return(1) and expect FL_PASTE event to follow
          label("RELEASE");
        } else {
          ret = 0;              // return(0) to reject the DND payload (drop)
          label("DND\nREJECTED!");
        }
        break;
      case FL_PASTE:              // handle actual drop (paste) operation
        fprintf(stderr, "FL_PASTE\n");
        copy_label(Fl::event_text());
        fprintf(stderr, "Pasted '%s'\n", Fl::event_text());

        // Don't pop up dialog windows in FL_DND_* or FL_PASTE event handling
        // resulting from DND operations. This may hang or even crash the
        // application on *some* platforms. Use a short timer to delay the
        // message display after the event processing is completed.

        delete[] dnd_text;      // don't leak (just in case)
        dnd_text = 0;

        len = Fl::event_length();
        if (len && Fl::event_text()) {
          dnd_text = new char[len + 1];
          memcpy(dnd_text, Fl::event_text(), len);
          dnd_text[len] = '\0';
          Fl::add_timeout(0.001, timer_cb, this); // delay message popup
        }
        ret = 1;
        break;
      case FL_DND_LEAVE:        // not strictly necessary to return(1) for this event
        label("..to\nhere");    // reset label
        fprintf(stderr, "FL_DND_LEAVE\n");
        dnd_inside = 0;         // status: mouse is outside, don't accept drop
        ret = 1;                // return(1) anyway..
        break;
    }
    return(ret);
  }

  // static timer callback
  static void timer_cb(void *data) {
    Receiver *r = (Receiver *)data;
    r->dnd_cb();
  }

  // dnd (FL_PASTE) popup method
  void dnd_cb() {
    if (dnd_text) {
      fl_message("%s", dnd_text);
      delete[] dnd_text;
      dnd_text = 0;
    }
  }
};

int main(int argc, char **argv) {
  // Create sender window and widget
  Fl_Window win_a(0,0,200,100,"Sender");
  Sender a(0,0,100,100);
  win_a.end();
  win_a.show();
  // Create receiver window and widget
  Fl_Window win_b(400,0,200,100,"Receiver");
  Receiver b(100,0,100,100);
  win_b.end();
  win_b.show();
  return(Fl::run());
}