5

I'm looking for a way to display both text and a picture in Emacs in a pop-up, as it is done in Wikipedia. Is there already a solution for this?

Drew
  • 75,699
  • 9
  • 109
  • 225
Andreas
  • 53
  • 2
  • This would be hard for terminal Emacs. Are you only interested in ideas for GUI version of Emacs then? – wvxvw Aug 02 '18 at 14:31

1 Answers1

5

It works if tooltip-mode is enabled with:

GNU Emacs 26.1 (build 1, x86<sub>64</sub>-unknown-cygwin, GTK+ Version 3.22.28) of 2018-05-28

(Note especially the GTK+ toolkit since that feature may be toolkit dependent.)

  1. Put the 'help-echo text property on the text to be augmented with the tooltip.
  2. Append a space to the help echo text.
  3. Propertize that space with the 'display property containing the image you want to show.

There follows a very silly example. For that example you also need SVG-support compiled into Emacs.

(with-current-buffer (get-buffer-create "*ToolTipTest*")
  (tooltip-mode)
  (insert
   (propertize
    "Some text"
    'help-echo
    (concat
     "Help text"
     (propertize
      " " 'display
      (let ((svg (svg-create 100 100)))
        (svg-ellipse svg 50 50 40 40 :fill-color "red")
        (svg-text svg "SVG" :x 30 :y 55 :font-size 20 :stroke-color "blue" :fill-color "red")
    (svg-image svg))))))
  (display-buffer (current-buffer)))

If you hoover the mouse pointer over Some text in the newly created buffer <*ToolTipTest*> you get the following image:

Buffer <code><*ToolTipTest*></code> with tooltip

Your original question had that org-mode-tag. So I will also demonstrate a solution special to org-mode. You can use org-link-set-parameters to set :help-echo property of links in org-link-parameters.

(defun my-download-as-string (url)
  "Download file from URL and return it as string."
  (let ((image-buf (url-retrieve-synchronously url)))
    (when image-buf
      (with-current-buffer image-buf
        (goto-char (point-min))
        (when (looking-at "HTTP/")
          (delete-region (point-min)
                         (progn (re-search-forward "\n[\n]+")
                                (point))))
        (buffer-substring-no-properties (point-min) (point-max))))))

(defun my-download-image (url)
  "Download URL as image."
  (create-image (my-download-as-string url) (image-type-from-file-name url) t))

(defun my-org-tooltip-jpeg-images (window object position)
  "Org link :help-echo function for displaying images from the net."
  (when (bufferp object)
    (with-current-buffer object
      (save-excursion
    (goto-char position)
    (let* ((el (org-element-context))
           (el-type (org-element-type el))
           (prot (org-element-property :type el))
           (link (org-element-property :raw-link el))
           (b (org-element-property :begin el))
           (e (org-element-property :end el))
           (img (get-text-property b :help-echo-image)))
      (if (and (eq el-type 'link)
           (string-match "https?" prot)
           (image-type-from-file-name link))
          (progn
        (unless img
          (setq img (my-download-image link))
          (add-text-properties b (1+ b) (list :help-echo-image img)))
        (concat "LINK: " link " " (propertize " " 'display img)))
        link))))))

(org-link-set-parameters "http" :help-echo #'my-org-tooltip-jpeg-images)

(org-link-set-parameters "https" :help-echo #'my-org-tooltip-jpeg-images)

An impression how it looks like when one hoovers over links in org-mode after running the above code:

:help-echo property in <code>org-link-parameters</code>

It also works with display-local-help called by C-h .. In that case the image is shown in the echo area:

Image shown in the echo area.

Tobias
  • 32,569
  • 1
  • 34
  • 75