summaryrefslogtreecommitdiff
path: root/examples/pygtk-demo/demos/dnd.py
blob: bc6f793898ea133e5411571bedade0b12d444013 (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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#!/usr/bin/env python
'''Drag and Drop

This is a test of the drag and drop capabilities of gtk.  It is a
fairly straight forward port of the example distributed with gtk.
'''

import pygtk
pygtk.require('2.0')
import gtk
import gobject

from dndpixmap import drag_icon_xpm, trashcan_open_xpm, trashcan_closed_xpm

TARGET_STRING = 0
TARGET_ROOTWIN = 1

target = [
    ('STRING', 0, TARGET_STRING),
    ('text/plain', 0, TARGET_STRING),
    ('application/x-rootwin-drop', 0, TARGET_ROOTWIN)
]

def create_pixmap(widget, xpm_data):
    return \
        gtk.gdk.pixmap_colormap_create_from_xpm_d(
            None, widget.get_colormap(), None, xpm_data)

class DragAndDropDemo(gtk.Window):
    trashcan_open = None
    trashcan_open_mask = None
    trashcan_closed = None
    trashcan_closed_mask = None
    drag_icon = None
    drag_mask = None
    have_drag = False
    popped_up = False
    in_popup = False
    popup_timer = 0
    popdown_timer = 0
    popup_win = None

    def __init__(self, parent=None):
        gtk.Window.__init__(self)
        try:
            self.set_screen(parent.get_screen())
        except AttributeError:
            self.connect('destroy', lambda *w: gtk.main_quit())
        self.set_title(self.__class__.__name__)

        table = gtk.Table(2,2)
        self.add(table)

        self.drag_icon, self.drag_mask = \
            create_pixmap(self, drag_icon_xpm)
        self.trashcan_open, self.trashcan_open_mask = \
            create_pixmap(self, trashcan_open_xpm)
        self.trashcan_closed, self.trashcan_closed_mask = \
            create_pixmap(self, trashcan_closed_xpm)

        label = gtk.Label('Drop to Trashcan!\n')
        label.drag_dest_set(gtk.DEST_DEFAULT_ALL, target[:-1],
                gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE)
        label.connect('drag_data_received', self.label_drag_data_received)
        table.attach(label, 0, 1, 0, 1)

        label = gtk.Label('Popup\n')
        label.drag_dest_set(gtk.DEST_DEFAULT_ALL, target[:-1],
                gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE)
        table.attach(label, 1, 2, 1, 2)
        label.connect('drag_motion', self.popsite_motion)
        label.connect('drag_leave', self.popsite_leave)

        image = gtk.Image()
        image.set_from_pixmap(self.trashcan_closed, self.trashcan_closed_mask)
        image.drag_dest_set(0, [], 0)
        table.attach(image, 1, 2, 0, 1)
        image.connect('drag_leave', self.target_drag_leave)
        image.connect('drag_motion', self.target_drag_motion)
        image.connect('drag_drop', self.target_drag_drop)
        image.connect('drag_data_received', self.target_drag_data_received)

        b = gtk.Button('Drag from Here\n')
        b.drag_source_set(gtk.gdk.BUTTON1_MASK | gtk.gdk.BUTTON3_MASK,
                  target, gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE)
        b.drag_source_set_icon(self.get_colormap(), self.drag_icon, self.drag_mask)
        table.attach(b, 0, 1, 1, 2)
        b.connect('drag_data_get', self.source_drag_data_get)
        b.connect('drag_data_delete', self.source_drag_data_delete)
        self.show_all()

    def label_drag_data_received(self, w, context, x, y, data, info, time):
        if data and data.format == 8:
            print 'Received "%s" in label' % data.data
            context.finish(True, False, time)
        else:
            context.finish(False, False, time)

    def popsite_motion(self, w, context, x, y, time):
        if not self.popup_timer:
            self.popup_timer = gobject.timeout_add(500, self.popup_cb)
        return True

    def popsite_leave(self, w, context, time):
        if self.popup_timer:
            gobject.source_remove(self.popup_timer)
            self.popup_timer = 0

    def popup_motion(self, w, context, x, y, time):
        print 'popup_motion'
        if not self.in_popup:
            self.in_popup = True
            if self.popdown_timer:
                print 'removed popdown'
                gobject.source_remove(self.popdown_timer)
                self.popdown_timer = 0
        return True

    def popup_leave(self, w, context, time):
        print 'popup_leave'
        if self.in_popup:
            self.in_popup = False
            if not self.popdown_timer:
                print 'added popdown'
                self.popdown_timer = gobject.timeout_add(500, self.popdown_cb)

    def popup_cb(self):
        if not self.popped_up:
            if self.popup_win is None:
                self.popup_win = gtk.Window(gtk.WINDOW_POPUP)
                self.popup_win.set_position(gtk.WIN_POS_MOUSE)
                table = gtk.Table(3, 3)
                for k in range(9):
                    i, j = divmod(k, 3)
                    b = gtk.Button("%d,%d" % (i,j))
                    b.drag_dest_set(gtk.DEST_DEFAULT_ALL, target[:-1],
                        gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE)
                    b.connect('drag_motion', self.popup_motion)
                    b.connect('drag_leave', self.popup_leave)
                    table.attach(b, i, i+1, j, j+1)
                table.show_all()
                self.popup_win.add(table)
            self.popup_win.present()
            self.popped_up = True
        self.popdown_timer = gobject.timeout_add(500, self.popdown_cb)
        print 'added popdown'
        self.popup_timer = 0
        return False

    def popdown_cb(self):
        print 'popdown'
        #if self.in_popup:
        #    return True
        self.popdown_timer = 0
        self.popup_win.hide()
        self.popped_up = False
        return False

    def target_drag_leave(self, img, context, time):
        print 'leave'
        self.have_drag = False
        img.set_from_pixmap(self.trashcan_closed, self.trashcan_closed_mask)

    def target_drag_motion(self, img, context, x, y, time):
        if self.have_drag is False:
            self.have_drag = True
            img.set_from_pixmap(self.trashcan_open, self.trashcan_open_mask)
        source_widget = context.get_source_widget()
        print 'motion, source ',
        if source_widget:
            print source_widget.__class__.__name__
        else:
            print 'unknown'
        context.drag_status(context.suggested_action, time)
        return True

    def target_drag_drop(self, img, context, x, y, time):
        print 'drop'
        self.have_drag = False
        img.set_from_pixmap(self.trashcan_closed, self.trashcan_closed_mask)
        if context.targets:
            img.drag_get_data(context, context.targets[0], time)
            return True
        return False

    def target_drag_data_received(self, img, context, x, y, data, info, time):
        if data.format == 8:
            print 'Received "%s" in trashcan' % data.data
            context.finish(True, False, time)
        else:
            context.finish(False, False, time)

    def source_drag_data_get(self, btn, context, selection_data, info, time):
        if info == TARGET_ROOTWIN:
            print 'I was dropped on the rootwin'
        else:
            selection_data.set(selection_data.target, 8, "I'm Data!")

    def source_drag_data_delete(self, btn, context, data):
        print 'Delete the data!'

def main():
    DragAndDropDemo()
    gtk.main()

if __name__ == '__main__':
    main()