SVG widget in GNU Emacs

 

(Left) SVG widget in Emacs buffer
(Right) SVG image

(Top) SVG sprite sheet (Bottom) widgets from sprite sheet
Sample interaction dialog using SVG widget


Now you can use SVG widget in GNU Emacs. That is, use an SVG image or fragment as background for push-button widget in Emacs buffer. You can also specify the width and height of the widget for finer control. Generally speaking, you can use any type of image for this purpose. But SVG suits best because you can draw widget of any size without any distortion.
 
The ability to use SVG fragment means you can define multiple symbols in an SVG and use the same as a sprite sheet or a symbol library for your UI requirements. Thus the number of files to be managed is reduced. An SVG symbol library is a simple SVG file with each symbol as a direct descendant of the root node. Video above shows an example of such usage.

Another use case would be better looking customize form. Or at the very least, rounded "Save" and "Cancel" buttons. In other words, a more visually appealing UI in graphical environments while maintaining the promise of Emacs in terminal.

Code: https://gitlab.com/atamariya/emacs/-/blob/dev/lisp/svg.el

Patch
modified   lisp/wid-edit.el
@@ -353,6 +353,7 @@ widget-specify-button
   "Specify button for WIDGET between FROM and TO."
   (let ((overlay (make-overlay from to nil t nil))
     (follow-link (widget-get widget :follow-link))
+    (display (widget-get widget :display))
     (help-echo (widget-get widget :help-echo)))
     (widget-put widget :button-overlay overlay)
     (if (functionp help-echo)
@@ -360,6 +361,7 @@ widget-specify-button
     (overlay-put overlay 'button widget)
     (overlay-put overlay 'keymap (widget-get widget :keymap))
     (overlay-put overlay 'evaporate t)
+    (overlay-put overlay 'display display)
     ;; We want to avoid the face with image buttons.
     (unless (widget-get widget :suppress-face)
       (overlay-put overlay 'face (widget-apply widget :button-face-get))


Usage
(load "~/svg.el"

(defun test()
  (let ((file "~/c.svg")
        image)
    (with-current-buffer (find-file-noselect file)
      (setq image (libxml-parse-xml-region (point-min) (point-max))))
    ;; Handle XML PI
    (when (and image (eq (dom-tag image) 'top))
      (setq image (car (dom-by-tag image 'svg))))
    (canvas--scrub-image image)
    (dolist (el (dom-children image))
      (svg-widget image el 100 100 :help-echo "This is an SVG widget"))))

 
c.svg
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg"
     width="400" height="400" viewBox="-2 -1 8 8">
  <defs>
    <circle id="c1" cx="0" cy="0" r="1"/>
    <circle id="c2" cx="0" cy="0" r="1"/>
    <rect   id="c2" x="0" y="0" width="1" height="1"/>
    <path   id="c" d="M 0,0 0.5,0.5 .75,0 1,0.5 z"/>
  </defs>
  <use href="#c1" x="0" y="0" fill="red"/>
  <use href="#c" x="1" y="1"/>
  <use href="#c" x="1" y="1" transform="rotate(90)"/>
  <use href="#c" x="0" y="0" transform="rotate(45,1,1)"/>
</svg>

 

 



 




Comments

Popular posts from this blog

Draw and Scribble Notes in GNU Emacs

Basic WYSIWYG printing in GNU Emacs