Mercurial > hg > xemacs-beta
comparison lisp/dragdrop.el @ 284:558f606b08ae r21-0b40
Import from CVS: tag r21-0b40
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:34:13 +0200 |
parents | c42ec1d1cded |
children | e11d67e05968 |
comparison
equal
deleted
inserted
replaced
283:fa3d41851a08 | 284:558f606b08ae |
---|---|
24 | 24 |
25 ;;; Synched up with: Not in FSF. | 25 ;;; Synched up with: Not in FSF. |
26 | 26 |
27 ;;; Commentary: | 27 ;;; Commentary: |
28 | 28 |
29 ;; This file is dumped with XEmacs (when window system support is compiled in). | 29 ;; This file is dumped with XEmacs (when drag'n'drop support is compiled in). |
30 | 30 |
31 ;;; Code: | 31 ;;; Code: |
32 | |
33 (provide 'dragdrop) | |
34 | 32 |
35 ;; we need mouse-set-point | 33 ;; we need mouse-set-point |
36 (require 'mouse) | 34 (require 'mouse) |
35 (provide 'dragdrop) | |
37 | 36 |
38 ;; I think this is a better name for the custom group | 37 ;; I think this is a better name for the custom group |
39 ;; looks better in the menu and the group display as dragdrop | 38 ;; looks better in the menu and the group display as dragdrop |
39 ;; Anyway: is dragdrop- a good prefix for all this? | |
40 ;; What if someone type drop<TAB> into the minibuffer? | |
40 (defgroup drag-n-drop nil | 41 (defgroup drag-n-drop nil |
41 "Window system-independent drag'n'drop support." | 42 "Window system-independent drag'n'drop support." |
42 :group 'editing) | 43 :group 'editing) |
43 | 44 |
44 (defcustom dragdrop-drop-at-point nil | 45 (defcustom dragdrop-drop-at-point nil |
52 "*If non-nil, autoload tm-view if a MIME buffer needs to be decoded. | 53 "*If non-nil, autoload tm-view if a MIME buffer needs to be decoded. |
53 Otherwise, the buffer is only decoded if tm-view is already avaiable." | 54 Otherwise, the buffer is only decoded if tm-view is already avaiable." |
54 :type 'boolean | 55 :type 'boolean |
55 :group 'drag-n-drop) | 56 :group 'drag-n-drop) |
56 | 57 |
57 (defcustom dragdrop-drop-functions '(dragdrop-drop-url-default | 58 ;; the widget for editing the drop-functions |
58 dragdrop-drop-mime-default) | 59 (define-widget 'dragdrop-function-widget 'list |
60 "Widget for editing drop dispatch functions." | |
61 :args `((choice :tag "Function" | |
62 (function-item dragdrop-drop-url-default) | |
63 (function-item dragdrop-drop-mime-default) | |
64 (function-item dragdrop-drop-log-function) | |
65 (function :tag "Other" nil)) | |
66 (choice :tag "Button" :value t | |
67 (choice-item :tag "Ignore" t) | |
68 (choice-item 0) (choice-item 1) (choice-item 2) | |
69 (choice-item 3) (choice-item 4) (choice-item 5) | |
70 (choice-item 6) (choice-item 7)) | |
71 (radio-button-choice :tag "Modifiers" | |
72 (const :tag "Ignore Modifier Keys" t) | |
73 (checklist :greedy t | |
74 :format "Modifier Keys:\n%v" | |
75 :extra-offset 6 | |
76 (const shift) | |
77 (const control) | |
78 (const meta) | |
79 (const alt) | |
80 (const hyper) | |
81 (const super))) | |
82 (repeat :inline t :value nil :tag "Extra Function Arguments" | |
83 (sexp :tag "Arg" :value nil))) | |
84 :value '(nil t t)) | |
85 | |
86 ;; button and widget selectors are still "shaky": | |
87 ;; button may be a number or t (or nil?), t means "Ignore" | |
88 ;; mods may be t or nil or a list of mod-syms, t means "Ignore" | |
89 ;; but this seems to be a porblem for the widget, well perhaps I find | |
90 ;; a solution... | |
91 (defcustom dragdrop-drop-functions '((dragdrop-drop-url-default t t) | |
92 (dragdrop-drop-mime-default t t)) | |
59 "This is the standart drop function search list. | 93 "This is the standart drop function search list. |
60 Each variable in this list is called with the drop data until | 94 Each element is a list of a function, a button selector, a modifier |
61 one of the functions return t, or the end of the list is reached." | 95 selector and optional argumets to the function call. |
96 The function must accept at least two arguments: first is the event | |
97 of the drop, second the object data, followed by any of the optional | |
98 arguments provided in this list. | |
99 The functions are called in order, until one returns t." | |
62 :group 'drag-n-drop | 100 :group 'drag-n-drop |
63 :type '(repeat (choice (function-item dragdrop-drop-url-default) | 101 :type '(repeat dragdrop-function-widget)) |
64 (function-item dragdrop-drop-mime-default) | 102 |
65 (function :tag "other")))) | 103 (defgroup dnd-debug nil |
104 "Drag'n'Drop debugging options." | |
105 :group 'drag-n-drop) | |
106 | |
107 (defcustom dragdrop-drop-log nil | |
108 "If non-nil, every drop is logged. | |
109 The name of the buffer is set in the custom 'dragdrop-drop-log-name" | |
110 :group 'dnd-debug | |
111 :type 'boolean) | |
112 | |
113 (defcustom dragdrop-drop-log-name "*drop log buffer*" | |
114 "The name of the buffer used to log drops. | |
115 Set dragdrop-drop-log to non-nil to enable this feature." | |
116 :group 'dnd-debug | |
117 :type 'string) | |
118 | |
119 (defvar dragdrop-drop-log-buffer nil | |
120 "Buffer to log drops in debug mode.") | |
66 | 121 |
67 (defun dragdrop-drop-dispatch (object) | 122 (defun dragdrop-drop-dispatch (object) |
68 "This function identifies DROP type misc-user-events. | 123 "This function identifies DROP type misc-user-events. |
69 It tries to find out how to handle the dropped data by looking | 124 It calls functions which will handle the drag." |
70 for dragdrop-drop-functions in extents and variables." | 125 (let ((event current-mouse-event)) |
126 (and dragdrop-drop-log | |
127 (dragdrop-drop-log-function event object)) | |
128 (dragdrop-drop-find-functions event object))) | |
129 | |
130 (defun dragdrop-drop-find-functions (event object) | |
131 "Finds valid drop-handle functions and executes them to dispose the drop. | |
132 It does this by looking for extent-properties called 'dragdrop-drop-functions | |
133 and for variables named like this." | |
71 (catch 'dragdrop-drop-is-done | 134 (catch 'dragdrop-drop-is-done |
72 (and (event-over-text-area-p current-mouse-event) | 135 (and (event-over-text-area-p event) |
73 ;; let's search the extents | 136 ;; let's search the extents |
74 (catch 'dragdrop-extents-done | 137 (catch 'dragdrop-extents-done |
75 (let ((window (event-window current-mouse-event)) | 138 (let ((window (event-window event)) |
76 (pos (event-point current-mouse-event)) | 139 (pos (event-point event)) |
77 (cpos (event-closest-point current-mouse-event)) | 140 (cpos (event-closest-point event)) |
78 (buffer nil)) | 141 (buffer nil)) |
79 (or window (throw 'dragdrop-extents-done nil)) | 142 (or window (throw 'dragdrop-extents-done nil)) |
80 (or pos (setq pos cpos)) | 143 (or pos (setq pos cpos)) |
81 (select-window window) | 144 (select-window window) |
82 (setq buffer (window-buffer)) | 145 (setq buffer (window-buffer)) |
83 (let ((ext (extent-at pos buffer 'dragdrop-drop-functions))) | 146 (let ((ext (extent-at pos buffer 'dragdrop-drop-functions))) |
84 (while (not (eq ext nil)) | 147 (while (not (eq ext nil)) |
85 (dragdrop-drop-do-functions | 148 (dragdrop-drop-do-functions |
86 (extent-property ext 'dragdrop-drop-functions) | 149 (extent-property ext 'dragdrop-drop-functions) |
150 event | |
87 object) | 151 object) |
88 (setq ext (extent-at pos buffer 'dragdrop-drop-functions ext))))))) | 152 (setq ext (extent-at pos buffer 'dragdrop-drop-functions ext))))))) |
89 ;; now look into the variable dragdrop-drop-functions | 153 ;; now look into the variable dragdrop-drop-functions |
90 (dragdrop-drop-do-functions dragdrop-drop-functions object))) | 154 (dragdrop-drop-do-functions dragdrop-drop-functions event object))) |
91 | 155 |
92 (defun dragdrop-drop-do-functions (drop-funs object) | 156 (defun dragdrop-compare-mods (first-mods second-mods) |
157 "Returns t if both first-mods and second-mods contain the same elements. | |
158 Order is not important." | |
159 (let ((moda (copy-sequence first-mods)) | |
160 (modb (copy-sequence second-mods))) | |
161 (while (and (not (eq moda ())) | |
162 (not (eq modb ()))) | |
163 (setq modb (delete (car moda) modb)) | |
164 (setq moda (delete (car moda) moda))) | |
165 (and (eq moda ()) | |
166 (eq modb ())))) | |
167 | |
168 (defun dragdrop-drop-do-functions (drop-funs event object) | |
93 "Calls all functions in drop-funs with object until one returns t. | 169 "Calls all functions in drop-funs with object until one returns t. |
94 Returns t if one of drop-funs returns t. Otherwise returns nil." | 170 Returns t if one of drop-funs returns t. Otherwise returns nil." |
95 (while (not (eq drop-funs ())) | 171 (let ((flist nil) |
96 (and (funcall (car drop-funs) object) | 172 (button (event-button event)) |
97 (throw 'dragdrop-drop-is-done t)) | 173 (mods (event-modifiers event))) |
98 (setq drop-funs (cdr drop-funs))) | 174 (while (not (eq drop-funs ())) |
175 (setq flist (car drop-funs)) | |
176 (and (or (eq (cadr flist) t) | |
177 (= (cadr flist) button)) | |
178 (or (eq (caddr flist) t) | |
179 (dragdrop-compare-mods (caddr flist) modifiers)) | |
180 (apply (car flist) `(,event ,object ,@(cdddr flist))) | |
181 ;; (funcall (car flist) event object) | |
182 (throw 'dragdrop-drop-is-done t)) | |
183 (setq drop-funs (cdr drop-funs)))) | |
99 nil) | 184 nil) |
100 | 185 |
101 (defun dragdrop-drop-url-default (object) | 186 (defun dragdrop-drop-log-function (event object &optional message buffer) |
187 "Logs any drops into a buffer. | |
188 If buffer is nil, it inserts the data into a buffer called after | |
189 dragdrop-drop-log-name. | |
190 If dragdrop-drop-log is non-nil, this is done automatically for each drop. | |
191 The function always returns nil." | |
192 (save-excursion | |
193 (cond ((buffer-live-p buffer) | |
194 (set-buffer buffer)) | |
195 ((stringp buffer) | |
196 (set-buffer (get-buffer-create buffer))) | |
197 ((buffer-live-p dragdrop-drop-log-buffer) | |
198 (set-buffer dragdrop-drop-log-buffer)) | |
199 (t | |
200 (setq dragdrop-drop-log-buffer (get-buffer-create dragdrop-drop-log-name)) | |
201 (set-buffer dragdrop-drop-log-buffer))) | |
202 (insert (format "* %s: %s\n" | |
203 (current-time-string) | |
204 (if message message "received a drop"))) | |
205 (insert (format " at %d,%d (%d,%d) with button %d and mods %s\n" | |
206 (event-x event) | |
207 (event-y event) | |
208 (event-x-pixel event) | |
209 (event-y-pixel event) | |
210 (event-button event) | |
211 (event-modifiers event))) | |
212 (insert (format " data is of type %s (%d %s)\n" | |
213 (cond ((eq (car object) 'dragdrop-URL) "URL") | |
214 ((eq (car object) 'dragdrop-MIME) "MIME") | |
215 (t "UNKNOWN")) | |
216 (length (cdr object)) | |
217 (if (= (length (cdr object)) 1) "element" "elements"))) | |
218 (let ((i 1) | |
219 (data (cdr object))) | |
220 (while (not (eq data ())) | |
221 (insert (format " Element %d: %S\n" | |
222 i (car data))) | |
223 (setq i (1+ i)) | |
224 (setq data (cdr data)))) | |
225 (insert "----------\n")) | |
226 nil) | |
227 | |
228 (defun dragdrop-drop-url-default (event object) | |
102 "Default handler for dropped URL data. | 229 "Default handler for dropped URL data. |
103 Finds files and URLs. Returns nil if object does not contain URL data." | 230 Finds files and URLs. Returns nil if object does not contain URL data." |
104 (cond ((eq (car object) 'dragdrop-URL) | 231 (cond ((eq (car object) 'dragdrop-URL) |
105 (let ((data (cdr object)) | 232 (let ((data (cdr object)) |
106 (frame (event-channel current-mouse-event)) | 233 (frame (event-channel event)) |
107 (x pop-up-windows)) | 234 (x pop-up-windows)) |
108 (setq pop-up-windows nil) | 235 (setq pop-up-windows nil) |
109 (while (not (eq data ())) | 236 (while (not (eq data ())) |
110 (cond ((dragdrop-is-some-url "file" (car data)) | 237 (cond ((dragdrop-is-some-url "file" (car data)) |
111 ;; if it is some file, pop it to a buffer | 238 ;; if it is some file, pop it to a buffer |
124 (make-frame-visible frame) | 251 (make-frame-visible frame) |
125 (setq pop-up-windows x) | 252 (setq pop-up-windows x) |
126 t)) | 253 t)) |
127 (t nil))) | 254 (t nil))) |
128 | 255 |
129 (defun dragdrop-drop-mime-default (object) | 256 (defun dragdrop-drop-mime-default (event object) |
130 "Default handler for dropped MIME data. | 257 "Default handler for dropped MIME data. |
131 Inserts text into buffer, creates MIME buffers for other types. | 258 Inserts text into buffer, creates MIME buffers for other types. |
132 Returns nil if object does not contain MIME data." | 259 Returns nil if object does not contain MIME data." |
133 (cond ((eq (car object) 'dragdrop-MIME) | 260 (cond ((eq (car object) 'dragdrop-MIME) |
134 (let ((ldata (cdr object)) | 261 (let ((ldata (cdr object)) |
135 (frame (event-channel current-mouse-event)) | 262 (frame (event-channel event)) |
136 (x pop-up-windows) | 263 (x pop-up-windows) |
137 (data nil)) | 264 (data nil)) |
138 ;; how should this be handled??? | 265 ;; how should this be handled??? |
139 ;; insert drops of text/* into buffer | 266 ;; insert drops of text/* into buffer |
140 ;; create new buffer if pointer is outside buffer... | 267 ;; create new buffer if pointer is outside buffer... |
148 ;; drops are inserted at mouse-point, if inside a buffer | 275 ;; drops are inserted at mouse-point, if inside a buffer |
149 (while (not (eq ldata ())) | 276 (while (not (eq ldata ())) |
150 (setq data (car ldata)) | 277 (setq data (car ldata)) |
151 (if (and (listp data) | 278 (if (and (listp data) |
152 (= (length data) 3) | 279 (= (length data) 3) |
153 (string= (car data) "text/plain") | 280 (listp (car data)) |
154 (event-over-text-area-p current-mouse-event)) | 281 (stringp (caar data)) |
155 (let ((window (event-window current-mouse-event))) | 282 (string= (caar data) "text/plain") |
283 (event-over-text-area-p event)) | |
284 (let ((window (event-window event))) | |
156 (and window | 285 (and window |
157 (select-window window)) | 286 (select-window window)) |
158 (and (not dragdrop-drop-at-point) | 287 (and (not dragdrop-drop-at-point) |
159 (mouse-set-point current-mouse-event)) | 288 (mouse-set-point event)) |
160 (insert (caddr data))) | 289 (insert (caddr data))) |
161 (let ((buf (get-buffer-create "*MIME-Drop data*"))) | 290 (let ((buf (get-buffer-create "*MIME-Drop data*"))) |
162 (set-buffer buf) | 291 (set-buffer buf) |
163 (pop-to-buffer buf nil frame) | 292 (pop-to-buffer buf nil frame) |
164 (or (featurep 'tm-view) | 293 (or (featurep 'tm-view) |
185 (erase-buffer) | 314 (erase-buffer) |
186 (insert (caddr data)) | 315 (insert (caddr data)) |
187 (and (featurep 'tm-view) | 316 (and (featurep 'tm-view) |
188 ;; this list of (car data) should be done before | 317 ;; this list of (car data) should be done before |
189 ;; enqueing the event | 318 ;; enqueing the event |
190 (mime/viewer-mode buf (list (car data)) (cadr data)))) | 319 (mime/viewer-mode buf (car data) (cadr data)))) |
191 (t | 320 (t |
192 (display-message 'error "Wrong drop data"))))) | 321 (display-message 'error "Wrong drop data"))))) |
193 (undo-boundary) | 322 (undo-boundary) |
194 (setq ldata (cdr ldata))) | 323 (setq ldata (cdr ldata))) |
195 (make-frame-visible frame) | 324 (make-frame-visible frame) |