Mercurial > hg > xemacs-beta
diff lisp/hm--html-menus/internal-drag-and-drop.el @ 98:0d2f883870bc r20-1b1
Import from CVS: tag r20-1b1
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:13:56 +0200 |
parents | 131b0175ea99 |
children | 9f59509498e1 |
line wrap: on
line diff
--- a/lisp/hm--html-menus/internal-drag-and-drop.el Mon Aug 13 09:12:43 2007 +0200 +++ b/lisp/hm--html-menus/internal-drag-and-drop.el Mon Aug 13 09:13:56 2007 +0200 @@ -1,6 +1,6 @@ -;;; $Id: internal-drag-and-drop.el,v 1.1.1.1 1996/12/18 22:43:20 steve Exp $ +;;; $Id: internal-drag-and-drop.el,v 1.2 1997/02/15 22:21:05 steve Exp $ ;;; -;;; Copyright (C) 1996 Heiko Muenkel +;;; Copyright (C) 1996, 1997 Heiko Muenkel ;;; email: muenkel@tnt.uni-hannover.de ;;; ;;; This program is free software; you can redistribute it and/or modify @@ -24,27 +24,28 @@ ;;; drag and drop actions in the emacs. One could start such an ;;; action by clicking with the mouse in the source buffer and ;;; then in the destination buffer. The action could depend on -;;; the points where youve clicked with the mouse, on the state +;;; the points where you've clicked with the mouse, on the state ;;; of the region, the point, the mark and any other properties ;;; of the source and the destination buffers. The actions are ;;; defined by the variable `idd-actions', which is a buffer local -;;; variable. The following is an example for the html-mode: -;;; (defvar html-idd-actions -;;; '((nil (((idd-major-mode-p . dired-mode) -;;; (idd-dired-file-on-line-p . ".*\\.\\(gif\\)\\|\\(jpq\\)")) +;;; variable. The following is an example for the hm--html-mode: +;;; (defvar hm--html-idd-actions +;;; '((nil (((idd-if-major-mode-p . dired-mode) +;;; (idd-if-dired-file-on-line-p +;;; . ".*\\.\\(gif\\)\\|\\(jpq\\)")) ;;; hm--html-idd-add-include-image-from-dired-line) -;;; (((idd-major-mode-p . dired-mode) -;;; (idd-dired-no-file-on-line-p . nil)) +;;; (((idd-if-major-mode-p . dired-mode) +;;; (idd-if-dired-no-file-on-line-p . nil)) ;;; hm--html-idd-add-file-link-to-file-on-dired-line) -;;; (((idd-major-mode-p . dired-mode) -;;; (idd-dired-no-file-on-line-p . t)) +;;; (((idd-if-major-mode-p . dired-mode) +;;; (idd-if-dired-no-file-on-line-p . t)) ;;; hm--html-idd-add-file-link-to-directory-of-buffer) -;;; (((idd-major-mode-p . w3-mode) -;;; (idd-url-at-point-p . t)) +;;; (((idd-if-major-mode-p . w3-mode) +;;; (idd-if-url-at-point-p . t)) ;;; hm--html-idd-add-html-link-from-w3-buffer-point) -;;; (((idd-major-mode-p . w3-mode)) +;;; (((idd-if-major-mode-p . w3-mode)) ;;; hm--html-idd-add-html-link-to-w3-buffer) -;;; (((idd-local-file-p . t)) +;;; (((idd-if-local-file-p . t)) ;;; hm--html-idd-add-file-link-to-buffer))) ;;; Look at the variable `idd-actions' for further descriptions. ;;; @@ -60,45 +61,146 @@ ;;; At first you must click on the source and ;;; after that on the destination." ;;; t) -;;; (define-key global-map [(meta button1)] 'idd-mouse-drag-and-drop) ;;; ;;; Define actions in the variable `idd-actions'. ;;; +;;; The variable `idd-global-mouse-keys' defines the mouse keys, +;;; which are bound to the drag and drop command. +;;; +;;; The variable `idd-drag-and-drop-mouse-binding-type' determines +;;; if you've to hold a mouse button down during moving the mouse +;;; from the source to the destination or not. +;;; -(defvar idd-actions nil +(require 'adapt) +(require 'cl) + +(defvar idd-global-mouse-keys (if (adapt-emacs19p) + [(meta control mouse-1)] + [(meta control button1)]) + "The mouse keys for the command `idd-mouse-drag-and-drop'. +The command `idd-mouse-drag-and-drop' is bound during the loading +of the package internal-drag-and-drop to this keys in the global +key map. + +Set it to nil, if you don't want to bind this function during loading. + +If the command is already bound in the global keymap during loading, +then this key sequence will not be bind.") + +(defvar idd-global-help-mouse-keys (if (adapt-emacs19p) + [(meta control mouse-3)] + [(meta control button3)]) + "The mouse keys for the command `idd-help-mouse-drag-and-drop'. +The command `idd-mouse-drag-and-drop' is bound during the loading +of the package internal-drag-and-drop to this keys in the global +key map. + +Set it to nil, if you don't want to bind this function during loading. + +If the command is already bound in the global keymap during loading, +then this key sequence will not be bind.") + +(defvar idd-drag-and-drop-mouse-binding-type 'click + "*The type of the drag and drop mouse binding. +The value maybe `click or 'press-button-during-move. +A value of `click means, that you've to click over the source, leave +the button and click it again over the destination. +A value of 'press-button-during-move means, that you've to press +the button down over the source and hold it until the mouse pointer +is over the destination. + +The disadvantage of the `press-button-during-move' type compared with +the `click' type is, that you can't select a destination region and +therefore a drag and drop action depending on a selected region can't +be started with that type of mouse binding.") + +(defvar idd-actions '((((idd-if-region-active-p . nil)) + (((idd-if-region-active-p . t)) + idd-action-copy-region)) + + (((idd-if-region-active-p . t)) + (((idd-if-region-active-p . t)) + idd-action-copy-replace-region)) + + (((idd-if-region-active-p . nil) + (idd-if-modifiers-p . nil)) + (((idd-if-region-active-p . t)) + idd-action-move-region)) + + (((idd-if-region-active-p . t) + (idd-if-modifiers-p . nil)) + (((idd-if-region-active-p . t)) + idd-action-move-replace-region)) + ) "The list with actions, depending on the source and the destination. The list looks like: - '((<source-specification-1> (<destination-specification-1> <action-1-1>) - (<destination-specification-2> <action-1-2>) - : + '((<destination-specification-1> (<source-specification-1> <action-1-1>) + (<source-specification-2> <action-1-2>) + : ) - (<source-specification-2> (<destination-specification-1> <action-2-1>) - (<destination-specification-2> <action-2-2>) - : + (<destination-specification-2> (<source-specification-1> <action-2-1>) + (<source-specification-2> <action-2-2>) + : ) : ) The <source-specification> looks like the following: '([(<specification-type> <value>)]) -with <specification-type> :== idd-minor-mode-p | idd-buffer-name-p - | idd-region-active-p ... - -The <destination-specification> looks like <source-specification>, except -that a valid <specification-type> is also idd-major-mode-p. +with <specification-type> :== idd-if-minor-mode-p | idd-if-buffer-name-p + | idd-if-region-active-p | idd-if-url-at-point-p + | idd-if-major-mode-p | idd-if-variable-non-nil-p + | idd-if-dired-file-on-line-p + | idd-if-dired-no-file-on-line-p + | idd-if-local-file-p | idd-if-buffer-name-p + | idd-if-modifiers-p | ... -If <source-specification-1> or <destination-specification-1> is set to -nil, then every source or destination matches. `idd-actions' is a +The <specification-type> - functions must have two arguments, the first one +is the source or destination and the second is the <value>. It must return +nil, if the test wasn't successfull and a number (in general 1), which +specifies the weight of the test function. The weights of all single tests +are added to a summary weight and assigned to the action. The action +with the highest weight is called from the action handler. Look at +the definition of `idd-if-major-mode-p', `idd-if-minor-mode-p' and so on for +examples. Look at the function `idd-get-source-or-destination-alist', if +you wan't to know the structure of the 'source-or-destination' argument +of these functions. + +The <destination-specification> looks like <source-specification>, +but in general it could be set to nil in mode specific idd-action +lists. + +If <destination-specification-1> or <source-specification-1> is set to +nil, then every source or source matches. `idd-actions' is a buffer local variable, which should be at least mode depended. So if -the <source-specification-1> is set to nil it says, that the source +the <destination-specification-1> is set to nil it says, that the destination buffer must only have a specific mode. But however, it's also possible -to define a general `idd-actions' list, where the source mode is -specified by idd-major-mode-p. +to define a general `idd-actions' list, where the destination mode is +specified by `idd-if-major-mode-p'. -<action> ist a function, which has two arguments, the specifies the -source and the second the destination.") +<action> ist a function, which has two arguments, the first specifies the +source and the second the destination. Look at the function definition +of `idd-action-copy-region' and `idd-action-copy-replace-region'. They are +examples for such actions.") (make-variable-buffer-local 'idd-actions) +(defvar idd-help-instead-of-action nil + "*If this variable is t, then a help buffer is displayed. +No action will be performed if this variable is t.") + +(defvar idd-help-start-action-keymap nil + "Keymap used in an extent in the help buffer to start the action.") + +(defvar idd-help-source nil + "Contains the source of an action. Used only in the help buffer.") + +(defvar idd-help-destination nil + "Contains the destination of an action. Used only in the help buffer.") + +(defvar idd-help-start-extent nil + "The start extent in the help buffer.") + (defun idd-compare-a-specification (source-or-destination specification) "Tests if SOURCE-OR-DESTINATION matches the SPECIFICATION. @@ -108,8 +210,8 @@ '(cdr specification)))) (defun idd-compare-specifications-1 (source-or-destination - specifications - value) + specifications + value) "Internal function of `idd-compare-specifications'. VALUE is the value of the last matches." (cond ((not specifications) value) @@ -121,37 +223,37 @@ (+ value match)))))))) (defun idd-compare-specifications (source-or-destination - specifications) + specifications) "Determines how good SOURCE-OR-DESTINATION and SPECIFICATIONS are matching. A return value of zero means, that they don't match. The higher the return value the better is the matching." (cond ((not specifications) 1) (t (idd-compare-specifications-1 source-or-destination - specifications - 0)))) + specifications + 0)))) -(defun idd-get-action-depending-on-destination (destination - actions-depending-on-dest - source-value - value-action-pair) +(defun idd-get-action-depending-on-source (source + actions-depending-on-source + destination-value + value-action-pair) "Internal function of `idd-get-action-depending-on-source-and-destination'." - (let ((destination-value (idd-compare-specifications - destination - (car (car actions-depending-on-dest))))) - (cond ((not actions-depending-on-dest) value-action-pair) - ((or (= destination-value 0) - (<= (+ source-value destination-value) (car value-action-pair))) - (idd-get-action-depending-on-destination - destination - (cdr actions-depending-on-dest) - source-value + (let ((source-value (idd-compare-specifications + source + (car (car actions-depending-on-source))))) + (cond ((not actions-depending-on-source) value-action-pair) + ((or (= source-value 0) + (<= (+ destination-value source-value) (car value-action-pair))) + (idd-get-action-depending-on-source + source + (cdr actions-depending-on-source) + destination-value value-action-pair)) - (t (idd-get-action-depending-on-destination - destination - (cdr actions-depending-on-dest) - source-value - (cons (+ source-value destination-value) - (second (car actions-depending-on-dest)))))))) + (t (idd-get-action-depending-on-source + source + (cdr actions-depending-on-source) + destination-value + (cons (+ destination-value source-value) + (second (car actions-depending-on-source)))))))) (defun idd-get-action-depending-on-source-and-destination (source destination @@ -161,9 +263,10 @@ VALUE-ACTION-PAIR is a list like (<value> <action>). It returns VALUE-ACTION-PAIR, if no other action is found, which has a value higher than (car VALUE-ACTION-PAIR)." - (let ((source-value (idd-compare-specifications source (car (car actions))))) + (let ((destination-value + (idd-compare-specifications destination (car (car actions))))) (cond ((not actions) value-action-pair) - ((= source-value 0) + ((= destination-value 0) (idd-get-action-depending-on-source-and-destination source destination @@ -173,10 +276,10 @@ source destination (cdr actions) - (idd-get-action-depending-on-destination - destination + (idd-get-action-depending-on-source + source (cdr (car actions)) - source-value + destination-value value-action-pair)))))) (defun idd-get-action (source destination actions) @@ -188,6 +291,35 @@ actions '(0 . nil))) +(autoload 'ange-ftp-ftp-path "ange-ftp" + "Parse PATH according to ange-ftp-path-format (which see). +Returns a list (HOST USER PATH), or nil if PATH does not match the format.") + +(defun idd-set-point (source-or-destination) + "Sets the point and buffer to SOURCE-OR-DESTINATION." + (set-buffer (cdr (assoc ':buffer source-or-destination))) + (goto-char (cdr (assoc ':drag-or-drop-point source-or-destination)))) + +(defun idd-set-region (source-or-destination) + "Sets the point, mark and buffer to SOURCE-OR-DESTINATION. +The region is active after this function is called." + (set-buffer (cdr (assoc ':buffer source-or-destination))) + (goto-char (car (cdr (assoc ':region-active source-or-destination)))) + (set-mark (cdr (cdr (assoc ':region-active source-or-destination)))) + (activate-region)) + + +;;; Specification type functions for the list `idd-actions' + +(defun idd-if-region-active-p (source-or-destination value) + "Checks if the region in the SOURCE-OR-DESTINATION was active. +It returns 1, if the region was active and VALUE is t, or if +the region was not active and VALUE is nil. Otherwise it returns +nil." + (if (cdr (assoc ':region-active source-or-destination)) + (if value 1 nil) + (if value nil 1))) + (defun idd-get-buffer-url (source-or-destination) "Returns the URL of the buffer specified by SOURCE-OR-DESTINATION." (save-excursion @@ -201,7 +333,7 @@ (idd-set-point source-or-destination) (w3-view-this-url t))) -(defun idd-url-at-point-p (source-or-destination value) +(defun idd-if-url-at-point-p (source-or-destination value) "Checks if there is an URL at the point of SOURCE-OR-DESTINATION. If that is t and VALUE is t, or that is nil and VALUE is nil, then 1 is returned. Otherwise nil is returned." @@ -213,7 +345,7 @@ nil 1))) -(defun idd-major-mode-p (source-or-destination mode) +(defun idd-if-major-mode-p (source-or-destination mode) "Checks, if the major mode of SOURCE-OR-DESTINATION is MODE. It returns 1, if that is t and nil otherwise." (save-excursion @@ -222,18 +354,19 @@ 1 nil))) -(defun idd-set-point (source-or-destination) - "Sets the point and buffer to SOURCE-OR-DESTINATION." - (set-buffer (cdr (assoc ':buffer source-or-destination))) - (goto-char (cdr (assoc ':drag-or-drop-point source-or-destination)))) +(defun idd-if-variable-non-nil-p (source-or-destination variable) + "Checks, if the variable named VARIABLE isn't t in SOURCE-OR-DESTINATION. +It returns 1, if this is t." + (save-excursion + (set-buffer (cdr (assoc ':buffer source-or-destination))) + (if (eval variable) + 1 + nil))) -(defun idd-set-region (source-or-destination) - "Sets the point, mark and buffer to SOURCE-OR-DESTINATION. -The region is active after this function is called." - (set-buffer (cdr (assoc ':buffer source-or-destination))) - (goto-char (car (cdr (assoc ':region-active source-or-destination)))) - (set-mark (cdr (cdr (assoc ':region-active source-or-destination)))) - (activate-region)) +(defun idd-if-minor-mode-p (source-or-destination minor-mode-variable) + "Checks, if the variable MINOR-MODE-VARIABLE is t in SOURCE-OR-DESTINATION. +MINOR-MODE-VARIABLE is the name of the variable!." + (idd-variable-non-nil-p source-or-destination minor-mode-variable)) (defun idd-get-dired-filename-from-line (source-or-destination) "Returns the filename form the line in a dired buffer. @@ -242,7 +375,7 @@ (idd-set-point source-or-destination) (dired-get-filename nil t))) -(defun idd-dired-file-on-line-p (source-or-destination filename-regexp) +(defun idd-if-dired-file-on-line-p (source-or-destination filename-regexp) "Checks, if the filename on the line match FILENAME-REGEXP. The function `dired-get-filename' is used, to get the filename from the SOURCE-OR-DESTINATION. It returns 1, if it matchs or nil." @@ -254,7 +387,7 @@ 1 nil))) -(defun idd-dired-no-file-on-line-p (source-or-destination value) +(defun idd-if-dired-no-file-on-line-p (source-or-destination value) "Checks, if a filename is in the dired buffer of SOURCE-OR-DESTINATION. It returns 1, if a filename is on the line and if VALUE is t, or if no filename is on the line and VALUE is nil, otherwise it returns @@ -263,10 +396,6 @@ (if value nil 1) (if value 1 nil))) -(autoload 'ange-ftp-ftp-path "ange-ftp" - "Parse PATH according to ange-ftp-path-format (which see). -Returns a list (HOST USER PATH), or nil if PATH does not match the format.") - (defun idd-get-local-filename (source-or-destination) "Returns the filename of a local file specified by SOURCE-OR-DESTINATION." (buffer-file-name (cdr (assoc ':buffer source-or-destination)))) @@ -277,7 +406,7 @@ (idd-set-point source-or-destination) default-directory)) -(defun idd-local-file-p (source-or-destination value) +(defun idd-if-local-file-p (source-or-destination value) "Checks, if SOURCE-OR-DESTINATION has a file on the local filesystem. If that is t and VALUE is t, or that is nil and VALUE is nil, then 1 is returned. Otherwise nil is returned." @@ -287,6 +416,137 @@ (if value 1 nil) (if value nil 1)))) +(defun idd-if-buffer-name-p (source-or-destination buffer-name) + "Checks, if SOURCE-OR-DESTINATION has a buffer called BUFFER-NAME. +It returns 1 if this is the case or nil otherwise." + (if (string= buffer-name + (buffer-name (cdr (assoc ':buffer source-or-destination)))) + 1 + nil)) + +(defun idd-list-1-subset-of-list-2 (list-1 list-2) + "Returns t, if LIST-1 is a subset of LIST-2." + (cond ((not list-1)) + ((member (car list-1 list-2)) + (idd-list-1-subset-of-list-2 (cdr list-1) list-2)) + (t nil))) + +(defun idd-same-modifiers (list-1 list-2) + "Returns t, if both list have the same modifiers." + (and (length list-1 list-2) + (idd-list-1-subset-of-list-2 list-1-list-2))) + +(defun idd-if-modifiers-p (source-or-destination modifiers) + "Checks, if the MODIFIERS hold during selecting the SOURCE-OR-DESTINATION. +Returns 1, if the list MODIFIERS contains the same modifiers, +or if any modyfiers are hold and MODIFIERS is t, +or if no modyfiers are hold and MODIFIERS is nil. +Otherwise nil is returned." + (let ((event-modifiers (event-modifiers + (cdr (assoc ':event source-or-destination))))) + (cond ((not modifiers) + (if event-modifiers nil 1)) + ((listp modifiers) + (if (idd-same-elements modifiers event-modifiers) + 1 + nil)) + (t (if event-modifiers 1 nil))))) + +;;; action functions + +(defun idd-action-copy-region (source destination) + "Copy the region from DESTINATION to SOURCE." + (idd-set-region source) + (let ((region-contents (buffer-substring (point) (mark)))) + (idd-set-point destination) + (insert region-contents))) + +(defun idd-action-copy-replace-region (source destination) + "Copy the region from SOURCE and replace the DESTINATION region with it." + (idd-set-region source) + (let ((region-contents (buffer-substring (point) (mark)))) + (idd-set-region destination) + (delete-region (point) (mark)) + (insert region-contents))) + +(defmacro* idd-with-source-and-destination (source + destination + &key + do-in-source + do-in-destination) + "Macro, usefull for the definition of action functions. +Look at the example `idd-action-move-region'." + `(progn + (if (idd-if-region-active-p ,source t) + (idd-set-region ,source) + (idd-set-point ,source)) + ,(when do-in-source + (cons 'progn do-in-source)) + (if (idd-if-region-active-p ,destination t) + (idd-set-region ,destination) + (idd-set-point ,destination)) + ,(when do-in-destination + (cons 'progn do-in-destination)))) + +(defun idd-action-move-region (source destination) + "Move the region from SOURCE to DESTINATION." + (let ((region)) + (idd-with-source-and-destination + source destination + :do-in-source ((setq region (buffer-substring (point) (mark))) + (delete-region (point) (mark))) + :do-in-destination ((insert region))))) + + +(defun idd-action-move-replace-region (source destination) + "Delete the region at SOURCE and overwrite the DESTINATION region with it." + (let ((region)) + (idd-with-source-and-destination + source destination + :do-in-source ((setq region (buffer-substring (point) (mark))) + (delete-region (point) (mark))) + :do-in-destination ((delete-region (point) (mark)) + (insert region))))) + + +;;; Performing the drag and drop + +(defun idd-display-help-about-action (action source destination) + "Display a help buffer with information about the action." + (if (> (car action) 0) + (if (symbol-function (cdr action)) + (progn + (with-displaying-help-buffer + '(lambda () + (set-buffer "*Help*") + (setq idd-help-source source) + (setq idd-help-destination destination) + (insert "Drag and drop action: `") + (let ((start (point))) + (insert (format "%s" (cdr action))) + (setq idd-help-start-extent (make-extent start (point))) + (set-extent-mouse-face idd-help-start-extent 'highlight) + (set-extent-face idd-help-start-extent 'bold) + (set-extent-keymap idd-help-start-extent + idd-help-start-action-keymap) + ) + (insert "'\n") + (insert (format "Source buffer : `%s'\n" + (buffer-name (cdr (assoc ':buffer source))))) + (insert (format "Destination buffer : `%s'\n" + (buffer-name (cdr (assoc ':buffer destination)) + ))) + (insert "==================================================" + "====================\n") + (insert "Look at `idd-actions' in the " + "destination buffer for other actions!\n") + (insert (format "The documentation of `%s':\n\n" + (cdr action))) + (insert (documentation (cdr action))))) + ) + (error "Error: Action %s isn't a valid function!" (cdr action))) + (message "No valid action defined for this source and this destination!"))) + (defun idd-call-action (action source destination) "Calls the drag and drop ACTION with its arguments SOURCE and DESTINATION." (if (> (car action) 0) @@ -295,35 +555,170 @@ (error "Error: Action %s isn't a valid function!" (cdr action))) (message "No valid action defined for this source and this destination!"))) +(defun idd-start-help-mouse-drag-and-drop () + "Starts help on `idd-start-mouse-drag-and-drop'." + (interactive) + (let ((idd-help-instead-of-action t)) + (idd-start-mouse-drag-and-drop))) + +(defun idd-start-mouse-drag-and-drop () + "Starts a drag and drop command. +This command could be used to start a drag and drop command without a +button event. Therefore this should not be bind direct to a mouse button." + (interactive) + (let ((destination-event) + (drag-and-drop-message "Drag&Drop: Click on the source!")) + (message drag-and-drop-message) + (setq source-event + (next-command-event nil drag-and-drop-message)) + (if (button-press-event-p source-event) + (idd-mouse-drag-and-drop source-event) + (message "Wrong event! Exit drag and drop.")))) + +(defun idd-help-mouse-drag-and-drop (source-event) + "Displays help about the drag and drop action." + (interactive "@e") + (let ((idd-help-instead-of-action t)) + (idd-mouse-drag-and-drop source-event))) + (defun idd-mouse-drag-and-drop (source-event) "Performs a drag and drop action. -At first you must click on the source and after that on the destination." +It calls the command `idd-mouse-drag-and-drop-click' or +`idd-mouse-drag-and-drop-press-button-during-move' depending on +the value of `idd-drag-and-drop-mouse-binding-type'." (interactive "@e") - (let ((source (list (cons ':buffer (current-buffer)) - (cons ':drag-or-drop-point - (event-closest-point source-event)) - (cons ':region-active (if (region-active-p) - (cons (point) - (mark)))))) + (if (eq idd-drag-and-drop-mouse-binding-type 'click) + (idd-mouse-drag-and-drop-click source-event) + (idd-mouse-drag-and-drop-press-button-during-move source-event))) + +(defun idd-get-source-or-destination-alist (event) + "Returns an alist with the description of a source or destination point. +The EVENT must be the button event, which has selected the source or +destination of the drag and drop command. + +The alist has the following structure: + '((:buffer . <buffer-of-the-event>) + (:drag-or-drop-point . <closest-point-to-the-event>) + (:region-active . <t-or-nil>) + (:event . EVENT)) + +Note: <closest-point-to-the-event> is (event-closest-point EVENT), +if the EVENT is a mouse event and if it isn't nil. Otherwise the +point is used." +; (set-buffer (event-buffer event)) + (list (cons ':buffer (event-buffer event)) + (cons ':drag-or-drop-point (set-marker + (make-marker) + (if (mouse-event-p event) + (or (event-closest-point event) + (point)) + (point)))) + (cons ':region-active (if (region-active-p) + (cons (set-marker (make-marker) (point)) + (set-marker (make-marker) (mark))))) + (cons ':event event)) + ) + +(defun idd-mouse-drag-and-drop-press-button-during-move (source-event) + "Performs a drag and drop action. +At first you must press the button down over the source and then +move with the pressed button to the destination, where you must leave +the button up. +This must be bind to a mouse button. The SOURCE-EVENT must be a +button-press-event. + +The disadvantage of this command compared with the command +`idd-mouse-drag-and-drop-click' is, that you can't select a +destination region." + (interactive "@e") + (let ((drag-and-drop-message + "Drag&Drop: Leave the button over the destination!") + (source (idd-get-source-or-destination-alist source-event)) (destination nil) (destination-event)) - (if (adapt-xemacsp) + (message drag-and-drop-message) + (setq destination-event + (next-command-event nil drag-and-drop-message)) + (message "") + (cond ((button-release-event-p destination-event) + (setq destination (idd-get-source-or-destination-alist + destination-event)) + (idd-set-point destination) + (if idd-help-instead-of-action + (idd-display-help-about-action (idd-get-action source + destination + idd-actions) + source + destination) + (idd-call-action (idd-get-action source destination idd-actions) + source + destination))) + (t (message "Wrong event! Exit drag and drop.") nil)))) + +(defun idd-mouse-drag-and-drop-click (source-event) + "Performs a drag and drop action. +At first you must click on the source and after that on the destination. +This must be bind to a mouse button. The SOURCE-EVENT must be a +button-press-event." + (interactive "@e") + (let ((drag-and-drop-message "Drag&Drop: Click on the destination!") + (source (idd-get-source-or-destination-alist source-event)) + (destination nil) + (destination-event)) + (message drag-and-drop-message) + (if (and (adapt-xemacsp) (mouse-event-p source-event)) (dispatch-event (next-command-event))) (setq destination-event - (next-command-event nil "Drag&Drop: Click on the destination!")) + (next-command-event nil drag-and-drop-message)) +(setq heiko source-event) + (message "") (cond ((button-press-event-p destination-event) - (setq destination (list (cons ':buffer - (event-buffer destination-event)) - (cons ':drag-or-drop-point - (event-closest-point - destination-event)) - (cons ':region-active nil))) + (mouse-track destination-event) + (setq destination (idd-get-source-or-destination-alist + destination-event)) + (idd-set-point destination) (if (adapt-emacs19p) (while (not (button-release-event-p (next-command-event))))) - (idd-call-action (idd-get-action source destination idd-actions) - source - destination)) - (t (setq action "Wrong event") nil)))) + (if idd-help-instead-of-action + (idd-display-help-about-action (idd-get-action source + destination + idd-actions) + source + destination) + (idd-call-action (idd-get-action source destination idd-actions) + source + destination))) + (t (message "Wrong event! Exit drag and drop.") nil)))) + +(defun idd-help-start-action (event) + "Used to start the action from the help buffer." + (interactive "@e") + (idd-set-point idd-help-destination) + (idd-call-action (idd-get-action idd-help-source + idd-help-destination + idd-actions) + idd-help-source + idd-help-destination) + (delete-extent idd-help-start-extent)) + +;; keymap for help buffer extents +(if (not idd-help-start-action-keymap) + (progn + (setq idd-help-start-action-keymap + (make-sparse-keymap 'idd-help-start-action-keymap)) + (if (adapt-emacs19p) + (define-key idd-help-start-action-keymap [(mouse-2)] + 'idd-help-start-action) + (define-key idd-help-start-action-keymap "[(button2)]" + 'idd-help-start-action)))) + +;; global key bindings +(when idd-global-mouse-keys + (unless (where-is-internal 'idd-mouse-drag-and-drop global-map t) + (define-key global-map idd-global-mouse-keys 'idd-mouse-drag-and-drop)) + (unless (where-is-internal 'idd-help-mouse-drag-and-drop global-map t) + (define-key global-map + idd-global-help-mouse-keys 'idd-help-mouse-drag-and-drop))) (provide 'internal-drag-and-drop)