diff options
Diffstat (limited to 'elpa/auctex-13.1.3/toolbar-x.el')
-rw-r--r-- | elpa/auctex-13.1.3/toolbar-x.el | 1565 |
1 files changed, 0 insertions, 1565 deletions
diff --git a/elpa/auctex-13.1.3/toolbar-x.el b/elpa/auctex-13.1.3/toolbar-x.el deleted file mode 100644 index d97035f..0000000 --- a/elpa/auctex-13.1.3/toolbar-x.el +++ /dev/null @@ -1,1565 +0,0 @@ -;;; toolbar-x.el --- fancy toolbar handling in Emacs -*- lexical-binding: t; -*- - -;; Copyright (C) 2004-2022 Free Software Foundation, Inc. - -;; This program is free software; you can redistribute it and/or -;; modify it under the terms of the GNU General Public License as -;; published by the Free Software Foundation; either version 3 of -;; the License, or (at your option) any later version. - -;; This program is distributed in the hope that it will be -;; useful, but WITHOUT ANY WARRANTY; without even the implied -;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -;; PURPOSE. See the GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public -;; License along with this program; if not, write to the Free -;; Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -;; MA 02110-1301 USA - -;;; Author: Miguel Vinicius Santini Frasson - -;;; Commentary: -;; This program implements a common interface to display toolbar -;; buttons. A toolbar should be basically -;; defined by a image and a command to run when the button is pressed, -;; and additional properties could be added. This is the idea of this -;; program. See the documentation of function -;; `toolbarx-install-toolbar' for a description of how to specify -;; toolbars. - -;;; Features: - -;; * Button properties are given in the toolbar definition (BUTTON -;; paramenter in `toolbarx-install-toolbar') and/or in an alist with -;; associates the symbol with properties (MEANING-ALIST paramenter in -;; `toolbarx-install-toolbar'). - -;; * Supported properties: -;; - `:insert', `:image', `:command', `:help', `:enable', -;; `:append-command', `:prepend-command', -;; `:visible' and `:button'; -;; For the precise value-type for each property, see documentation of -;; the function `toolbarx-install-toolbar'. -;; (ps: properties that are particular to an editor are just ignored -;; the other editor flavour.) - -;; * Properties can have value specified by function (with no -;; argument) or variables that evaluate to an object of the correct -;; type for a particular property. The evaluation is done when the -;; roolbar is refresh (a call of `toolbarx-refresh'.) -;; (ps: this is valid only for properties that *not* have \`form\' as -;; value type.) - -;; * On `refresh time' (a call `toolbarx-refresh', necessary when the -;; toolbar should change), the `:insert' property (if present) is -;; evaluated to decide if button will be displayed. - -;; Properties can be distributed to several buttons, using \`groups\'. -;; Example: (foo (bar baz :enable (mytest)) :help "please") -;; means that `foo', `bar' and `baz' have `:help "please"' and `bar' and -;; `baz' have the property `:enable (mytest)'. - -;; * (Part of) the toolbar definition can be stored in a variable, -;; evaluated in `installation time'. See `:eval-group' on the -;; documentation of the function `toolbarx-install-toolbar'. - -;; * It is possible to define sets of buttons that appear according to -;; an option selected in a dropdown menu. See `:dropdown-group' on -;; the documentation of the function `toolbarx-install-toolbar'. - -;;; Rough description of the implementation -;; There are 2 \`engines\' implemented: - -;; == the 1st one (parsing) parses the toolbar definition -;; independently of editor flavour and store the parsed buttons with -;; their properties, in the same order that they appear in the -;; definitions, in a variable `toolbarx-internal-button-switches'; - -;; == the 2nd one (refresh for Emacs) inserts buttons in the Emacs -;; toolbar in the same order that they appear in the definitions; -;; if a (real) button does not have at least (valid) image -;; and command properties, they are silently ignored; - -;;; History: - -;; This program was motivated by the intention of implementation of a -;; good toolbar for AUCTeX, that would work in both Emacs and XEmacs. -;; Since toolbars were very different in behaviour and implementation -;; (for instance, in Emacs one can display as many toolbar buttons as -;; wanted, because it becomes mult-line, and in XEmacs, there is one -;; line, but toolbars and all sides of a frame.) - - -;;; Code: - -(eval-when-compile - (require 'cl-lib)) - -;; Note that this just gives a useful default. Icons are expected to -;; be in subdirectory "images" or "toolbar" relative to the load-path. -;; Packages loading toolbarx are advised to explicitly add their own -;; searchpath with add-to-list here even when they fulfill that -;; criterion: another package might have loaded toolbar-x previously -;; when load-path was not yet correctly set. The default setting -;; really caters only for toolbar-x' stock icons. - -(defvar toolbarx-image-path - (nconc - (delq nil (mapcar #'(lambda(x) - (and x - (member - (file-name-nondirectory - (directory-file-name x)) - '("toolbar" "images")) - ;;(file-directory-p x) - x)) - load-path)) - (list data-directory)) - "List of directories where toolbarx finds its images.") - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; First engine: Parsing buttons - -;; it obtains button information, process it and stores result in -;; `toolbarx-internal-button-switches', which is a list with 1st -;; element the symbol `:switches', the 2nd element as a list of -;; processed buttons, and the 3rd element is used for Emacs to store -;; the keys used in ``constant'' buttons. - -;; The 2nd element of `toolbarx-internal-button-switches' is a list -;; where each element is either: -;; * a button-list, that is, a list with elements to define a button. -;; * a list where 1st elem is `:insert' and 2nd is a form, and the -;; following elements are in the same format of the 2nd element of -;; `toolbarx-internal-button-switches'. - -(defun toolbarx-make-string-from-symbol (symbol) - "Return a string from the name of a SYMBOL. -Upcase initials and replace dashes by spaces." - (let* ((str (upcase-initials (symbol-name symbol))) - (str2)) - (dolist (i (append str nil)) - (if (eq i 45) ; if dash, push space - (push 32 str2) - (push i str2))) ; else push identical - (concat (nreverse str2)))) - -(defun toolbarx-make-symbol-from-string (string) - "Return a (intern) symbol from STRING. -Downcase string and replace spaces by dashes." - (let* ((str1 (append (downcase string) nil)) - (str2)) - (dolist (i str1) - (if (eq i 32) ; if dash, push space - (push 45 str2) - (push i str2))) - (intern (concat (nreverse str2))))) - -(defun toolbarx-good-option-list-p (option-list valid-options) - "Non-nil means the OPTION-LIST is of form (OPT FORM ... OPT FORM). -Each OPT is member of VALID-OPTIONS and OPT are pairwise -different. OPTION-LIST equal to nil is a good option list." - (let ((elt-in-valid t) - (temp-opt-list option-list) - (list-diff) - (n (/ (length option-list) 2))) - (dotimes (i n) - (when (> i 0) - (setq temp-opt-list (cddr temp-opt-list))) - (cl-pushnew (car temp-opt-list) list-diff :test #'equal) - (setq elt-in-valid (and elt-in-valid - (memq (car temp-opt-list) - valid-options)))) - (and elt-in-valid ; options are on VALID-OPTOPNS - ;; OPTION-LIST has all option different from each other - (eq (length list-diff) n) - ;; OPTION-LIST has even number of elements - (eq (% (length option-list) 2) 0)))) - -(defun toolbarx-separate-options (group-list valid-options &optional check) - "Return a cons cell with non-options and options of GROUP-LIST. -The options-part is the largest tail of the list GROUP-LIST that -has an element of VALID-OPTIONS (the comparation is made with -`memq'.) The non-options-part is the beginning of GROUP-LIST -less its tail. Return a cons cell which `car' is the -non-options-part and the `cdr' is the options-part. - -If CHECK is non-nil, the tail is the largest that yield non-nil -when applied to `toolbarx-good-option-list-p'." - (let ((maximal) - (temp)) - (dolist (i valid-options) - (setq temp (memq i group-list)) - (when (and (> (length temp) (length maximal)) - (if check - (toolbarx-good-option-list-p temp valid-options) - t)) - (setq maximal (memq i group-list)))) - (cons (butlast group-list (length maximal)) maximal))) - - -(defun toolbarx-merge-props (inner-props outer-props override add) - "Merge property lists INNER-PROPS and OUTER-PROPS. -INNER-PROPS and OUTER-PROPS are two lists in the format - (PROP VAL PROP VAL ... PROP VAL). -Returns a list with properties and values merged. - -OVERRIDE and ADD are supposed to be lists of symbols. The value -of a property in OVERRIDE is the one on OUTER-PROPS or -INNER-PROPS, but if the property is in both, the value in -INNER-PROPS is used. The value of a property in ADD will be a -list with first element the symbol `:add-value-list' and the rest -are the properties, inner properties first." - (let* ((merged) - (inner-prop) - (outer-prop)) - (dolist (prop override) - (if (memq prop inner-props) - (setq merged (append merged - (list prop (cadr (memq prop inner-props))))) - (when (memq prop outer-props) - (setq merged (append merged - (list prop (cadr (memq prop outer-props)))))))) - (dolist (prop add merged) - (setq inner-prop (memq prop inner-props)) - (when inner-prop - (if (and (listp (cadr inner-prop)) - (eq (car (cadr inner-prop)) :add-value-list)) - (setq inner-prop (cdr (cadr inner-prop))) - (setq inner-prop (list (cadr inner-prop))))) - (setq outer-prop (memq prop outer-props)) - (when outer-prop - (if (and (listp (cadr outer-prop)) - (eq (car (cadr outer-prop)) :add-value-list)) - (setq outer-prop (cdr (cadr outer-prop))) - (setq outer-prop (list (cadr outer-prop))))) - (when (append inner-prop outer-prop) - (setq merged (append merged - (list prop (cons :add-value-list - (append inner-prop - outer-prop))))))))) - -(defun toolbarx-make-command (comm prep app) - "Return a command made from COMM, PREP and APP. -COMM is a command or a form. PREP and APP are forms. If PREP or -APP are non-nil, they are added to the resulting command at the -beginning and end, respectively. If both are nil and COMM is a -command, COMM is returned." - (let ((comm-is-command (commandp comm))) - (if (and (not prep) - (not app) - comm-is-command) - comm - (lambda () (interactive) - (let (result) - (when prep (setq result (eval prep t))) - (when comm (setq result - (if comm-is-command - (call-interactively comm) - (eval comm t)))) - (when app (setq result (eval app t))) - result))))) - -(defun toolbarx-emacs-mount-popup-menu - (strings var type &optional title save) - "Return an interactive `lambda'-expression that shows a popup menu. -This function is the action of `toolbarx-mount-popup-menu' if -inside Emacs. See documentation of that function for more." - ;; making the menu keymap by adding each menu-item definition - ;; see (info "(elisp)Menu keymaps") - (let* ((keymap (make-sparse-keymap title)) - (count 1) - (used-symbols '(nil)) - (key) - (real-type - (pcase type - ((or `toggle `radio) type) - ;; Warn if type is not `radio' or `toggle'. - (_ (display-warning 'toolbarx - (format "TYPE should be symbols `radio' or `toggle', but %s found; using `radio'" - type)) - ;; Use `radio' if incorrect. - 'radio))) - (real-save - (pcase save - ((or `nil `offer `always) save) - ;; Warn if save is not `nil', `offer' or ;; `always'. - (_ (display-warning 'toolbarx - (format "SAVE should be symbols `nil', `offer' or `always', but %s found; using `nil'" - save)) - ;; Use nil when incorrect. - nil)))) - (dolist (i strings) - ;; finding a new symbol - (let* ((aux-count 0) - (i-symb (toolbarx-make-symbol-from-string i))) - (setq key i-symb) - (while (memq key used-symbols) - (setq aux-count (1+ aux-count)) - (setq key (intern (format "%s-%d" i-symb aux-count)))) - (setq used-symbols (cons key used-symbols))) - (define-key-after keymap (vector key) - `(menu-item ,i - ,(let ((count count)) - (lambda () (interactive) - (set var - (if (eq real-type 'radio) - count - (if (memq count (symbol-value var)) - (delete count (symbol-value var)) - (sort (cons count (symbol-value var)) #'<)))) - (toolbarx-refresh) - (when (eq real-save 'always) - (customize-save-variable var (symbol-value var))) - (symbol-value var))) - :button ,(if (eq real-type 'radio) - `(:radio eq ,var ,count) - `(:toggle memq ,count ,var)))) - (setq count (1+ count))) - (when (eq real-save 'offer) - (define-key-after keymap [sep] '(menu-item "--shadow-etched-in-dash")) - (let* ((aux-count 0) - (i-symb 'custom-save)) - (setq key i-symb) - (while (memq key used-symbols) - (setq aux-count (1+ aux-count)) - (setq key (intern (format "%s-%d" i-symb aux-count)))) - (setq used-symbols (cons key used-symbols))) - (define-key-after keymap (vector key) - `(menu-item "Save state of this menu" - (lambda nil (interactive) - (customize-save-variable (quote ,var) ,var))))) - ;; returns a `lambda'-expression - (lambda () (interactive) (popup-menu keymap)))) - -(defun toolbarx-mount-popup-menu (strings var type &optional title save) - "Return a command that show a popup menu. -The return is a `lambda'-expression with a interactive declaration. - -STRINGS is a list of strings which will be the itens of the menu. - -VAR is a symbol that is set when an item is clicked. TYPE should -be one of the symbols `radio' or `toggle': `radio' means that the -nth item is selected if VAR is `n' and this item sets VAR to `n'; -`toggle' means that VAR should be a list of integers and the nth -item is selected if `n' belongs to VAR. The item inserts or -deletes `n' from VAR. - -TITLE is a string (the title of the popup menu) or nil for no -title. - -SAVE is one of the symbols nil, `offer' or `always'. If value -is nil, do not try to save anything. If it is `offer', a menu -item is added offering the user the possibiity to save state of -that dropdown menu for future sesseions (using `custom'). If it -is `always', state is saved every time that a item is clicked." - (toolbarx-emacs-mount-popup-menu strings var type title save)) - -(defun toolbarx-option-value (opt) - "If OPT is a vector, return first element, otherwise, return OPT. -If OPT is vector and length is smaller than the necessary, then -nil is returned." - ;; FIXME: This is backward compatibility for when we supported XEmacs - ;; and entries could take the shape [FOO BAR] where FOO was the - ;; value to use for Emacs and BAR the value to use for XEmacs. - ;; This is unused since Mar 2021. - (if (vectorp opt) - (when (> (length opt) 0) - (aref opt 0)) - opt)) - -(defun toolbarx-eval-function-or-symbol (object type-test-func) - "Return a cons cell (GOOD-OBJ . VAL). -GOOD-OBJ non-nil means that VAL is a valid value, according to -the car of the result of TYPE-TEST-FUNCTION, that should return a -cons cell in the same format as the return of this function. - -If OBJECT applied to TYPE-TEST-FUNC return (GOOD-OBJ . VAL), and -GOOD-OBJ is non-nil, return that. Else, check if OBJECT is a -function. If so, evaluate and test again with TYPE-TEST-FUNC. If -not a function or if GOOD-OBJ is again nil, test if OBJECT is a -bound symbol, evaluate that and return the result of -TYPE-TEST-FUNC." - (let* ((ret (funcall type-test-func object))) - (unless (car ret) - (if (functionp object) - (progn - (setq ret (funcall type-test-func (funcall object))) - (unless (car ret) - (when (and (symbolp object) (boundp object)) - (setq ret (funcall type-test-func (symbol-value object)))))) - ;; ok, obj is not function; try symbol - (when (and (symbolp object) (boundp object)) - (setq ret (funcall type-test-func (symbol-value object)))))) - ret)) - -(defun toolbarx-test-image-type (obj) - "Return a cons cell (GOOD-OBJ . VAL). -GOOD-OBJ is non-nil if OBJ yields a valid image object VAL (see -documentation of function `toolbarx-process-symbol')." - (let ((toolbarx-test-image-type-simple - (lambda (img) - (let* ((val (toolbarx-option-value img)) - (all-obj-ok t) - (good-obj - (or (stringp val) ; string - (eq (car-safe val) 'image) ; or image descriptor - (and (symbolp val) ; or a symbol bound to a - (boundp val) ; image descriptor - ; (defined with `defimage') - (consp (symbol-value val)) - (eq (car (symbol-value val)) 'image)) - (and (listp val) ; or list with 4 strings or - ; image descriptors - (= (length val) 4) - (dolist (i val all-obj-ok) - (setq all-obj-ok - (and all-obj-ok - (or (stringp i) - (eq (car-safe i) 'image))))))))) - (cons good-obj val))))) - (toolbarx-eval-function-or-symbol obj toolbarx-test-image-type-simple))) - -(defun toolbarx-test-button-type (obj) - "Return a cons cell (GOOD-OBJ . VAL). -GOOD-OBJ is non-nil if OBJ yields a valid button object VAL (see -documentation of function `toolbarx-process-symbol')." - (let ((toolbarx-test-button-type-simple - (lambda (but) - (let* ((val (toolbarx-option-value but)) - (good-obj - (and (consp val) - (memq (car val) '(:toggle :radio))))) - (cons good-obj val))))) - (toolbarx-eval-function-or-symbol obj toolbarx-test-button-type-simple))) - -(defun toolbarx-test-any-type (obj) - "Return a cons cell (t . VAL). -If OBJ is vector, return VAL according to editor. Else, return -OBJ, because it is a form anyway." - (cons t (toolbarx-option-value obj))) - -(defun toolbarx-test-string-or-nil (obj) - "Return a cons cell (GOOD-OBJ . VAL). -GOOD-OBJ is non-nil if OBJ yields a valid help object VAL (see -documentation of function `toolbarx-process-symbol')." - (let ((toolbarx-test-string-or-nil-simple - (lambda (obj) - (let* ((val (toolbarx-option-value obj)) - (good-obj (or (stringp val) - (not val)))) - (cons good-obj val))))) - (toolbarx-eval-function-or-symbol obj toolbarx-test-string-or-nil-simple))) - -(defun toolbarx-test-toolbar-type (obj) - "Return a cons cell (GOOD-OBJ . VAL). -GOOD-OBJ is non-nil if OBJ yields a valid toolbar property object -VAL (see documentation of function `toolbarx-process-symbol')." - (let ((toolbarx-test-toolbar-type-simple - (lambda (obj) - (let* ((val (toolbarx-option-value obj)) - ;; (all-but-def-opts '(top bottom left right)) - ;; (all-opts '(default top bottom left right)) - ;; (good-obj t) - ) - (cons t val))))) - (toolbarx-eval-function-or-symbol obj toolbarx-test-toolbar-type-simple))) - -(defun toolbarx-test-dropdown-type (obj) - "Return a cons cell (GOOD-OBJ . VAL). -GOOD-OBJ is non-nil if OBJ yields a valid `:type' property object -VAL of a dropdown group (see documentation of function -`toolbarx-process-dropdown-group'." - (let ((toolbarx-test-dropdown-type-simple - (lambda (obj) - (let* ((val (toolbarx-option-value obj)) - (good-obj (memq val '(radio toggle)))) - (cons good-obj val))))) - (toolbarx-eval-function-or-symbol obj toolbarx-test-dropdown-type-simple))) - -(defun toolbarx-test-symbol (obj) - "Return a cons cell (GOOD-OBJ . VAL). -GOOD-OBJ is non-nil if OBJ yields a valid `:variable' property -object VAL of a dropdown group (see documentation of function -`toolbarx-process-dropdown-group'." - (let ((toolbarx-test-symbol-simple - (lambda (obj) - (let* ((val (toolbarx-option-value obj)) - (good-obj (symbolp val))) - (cons good-obj val))))) - (toolbarx-eval-function-or-symbol obj toolbarx-test-symbol-simple))) - -(defun toolbarx-test-dropdown-default (obj) - "Return a cons cell (GOOD-OBJ . VAL). -GOOD-OBJ is non-nil if OBJ yields a valid `:default' property -object VAL of a dropdown group (see documentation of function -`toolbarx-process-dropdown-group'." - (let ((toolbarx-test-dropdown-default-simple - (lambda (obj) - (let* ((val (toolbarx-option-value obj)) - (good-obj (or (integerp val) - (and (listp val) - (let ((ok t)) - (dolist (i val ok) - (setq ok (and ok (integerp i))))))))) - (cons good-obj val))))) - (toolbarx-eval-function-or-symbol obj - toolbarx-test-dropdown-default-simple))) - -(defun toolbarx-test-dropdown-save (obj) - "Return a cons cell (GOOD-OBJ . VAL). -GOOD-OBJ is non-nil if OBJ yields a valid `:save' property -object VAL of a dropdown group (see documentation of function -`toolbarx-process-dropdown-group'." - (let ((toolbarx-test-dropdown-save-simple - (lambda (obj) - (let* ((val (toolbarx-option-value obj)) - (good-obj (memq val '(nil offer always)))) - (cons good-obj val))))) - (toolbarx-eval-function-or-symbol obj toolbarx-test-dropdown-save-simple))) - -(defconst toolbarx-button-props - (let* ((props-types-alist - '((:image toolbarx-test-image-type) - (:command toolbarx-test-any-type) - (:enable toolbarx-test-any-type) - (:visible toolbarx-test-any-type) - (:help toolbarx-test-string-or-nil) - (:insert toolbarx-test-any-type . and) - ;; (:toolbar toolbarx-test-toolbar-type) - (:button toolbarx-test-button-type) - (:append-command toolbarx-test-any-type . progn) - (:prepend-command toolbarx-test-any-type . progn))) - (possible-props (nreverse (let* ((props ())) - (dolist (p props-types-alist props) - (setq props (cons (car p) props)))))) - (props-override (nreverse (let* ((props ())) - (dolist (p props-types-alist props) - (unless (cddr p) - (setq props (cons (car p) props))))))) - (props-add (nreverse (let* ((props ())) - (dolist (p props-types-alist props) - (when (cddr p) - (setq props (cons (car p) props)))))))) - (list props-types-alist possible-props props-override props-add)) - "List yielding all encarnations of properties of a button. -First element: alist, where each element is of form - (PROP . (TYPE-TEST-FUNCTION . ADD-OR-NIL)) -Second is a list with all properties. -Third, a list with properties that override when merging. -Fourth, a list of lists, each in the format (PROP ADD).") - -(defconst toolbarx-dropdown-props - ;; for naming dropdown properties see `Convention' in the doc string - (let* ((props-types-alist - '((:type toolbarx-test-dropdown-type) - (:variable toolbarx-test-symbol) - (:default toolbarx-test-dropdown-default) - (:save toolbarx-test-dropdown-save) - (:title toolbarx-test-string-or-nil) - (:dropdown-image toolbarx-test-image-type) - (:dropdown-enable toolbarx-test-any-type) - (:dropdown-visible toolbarx-test-any-type) - (:dropdown-insert toolbarx-test-any-type . and) - (:dropdown-help toolbarx-test-string-or-nil) - ;; (:dropdown-toolbar toolbarx-test-toolbar-type) - (:dropdown-append-command toolbarx-test-any-type . progn) - (:dropdown-prepend-command toolbarx-test-any-type . progn))) - (possible-props (nreverse (let* ((props ())) - (dolist (p props-types-alist props) - (setq props (cons (car p) props)))))) - (props-override (nreverse (let* ((props ())) - (dolist (p props-types-alist props) - (unless (cddr p) - (setq props (cons (car p) props))))))) - (props-add (nreverse (let* ((props ())) - (dolist (p props-types-alist props) - (when (cddr p) - (setq props (cons (car p) props)))))))) - (list props-types-alist possible-props props-override props-add)) - "List yielding all encarnations of properties of a dropdown group. -First element: alist, where each element is of form - (PROP . (TYPE-TEST-FUNCTION . ADD-OR-NIL)) -Second is a list with all properties. -Third, a list with properties that override when merging. -Fourth, a list of lists, each in the format (PROP ADD). - -Convention: properties for the dropdown button should be formed -with the strings \":dropdown-\" with the button property name -without `:'. This is used on the implementation.") - -(defun toolbarx-process-group-without-insert (group-without-props - merged-props-without-insert - meaning-alist switches) - "Return an updated version of SWITCHES. -GROUP-WITHOUT-PROPS and MERGED-PROPS-WITHOUT-INSERT are -preprocessed variables in `toolbarx-process-group'." - (let ((current-switches switches)) - (dolist (i group-without-props current-switches) - (setq i (toolbarx-option-value i)) - (if (symbolp i) - (setq current-switches - (toolbarx-process-symbol i meaning-alist - merged-props-without-insert - current-switches)) - (when (listp i) - (setq current-switches - (toolbarx-process-group i meaning-alist - merged-props-without-insert - current-switches))))))) - -(defun toolbarx-process-group (group meaning-alist props switches) - "Return an updated version of SWITCHES. -Append to already processed buttons (stored in SWITCHES) a -processed version of GROUP. Groups are useful to distribute -properties. External properties are given in PROPS, and merged -with the internal properties that are in the end of GROUP. If -properties (after merge) contain a `:insert' property, return a -list where the first and second elements are `:insert' and its -value, and after that a list in the same format as SWITCHES." - (cond - ;; if DROPDOWN group - ((eq (car group) :dropdown-group) - (toolbarx-process-dropdown-group group meaning-alist props switches)) - ;; if EVAL group - ((eq (car group) :eval-group) - (let ((current-switches switches)) - (dolist (elt (cdr group) current-switches) - (let ((eval-elt (eval elt t))) - (setq current-switches - (toolbarx-process-group (if (listp eval-elt) - eval-elt - (list eval-elt)) - meaning-alist props - current-switches)))))) - ;; if normal group - (t - (let* ((splited-props - (toolbarx-separate-options - group (append (nth 1 toolbarx-button-props) - (nth 1 toolbarx-dropdown-props)))) - (intern-props (cdr splited-props)) - (group-without-props (car splited-props)) - (merged-props - (toolbarx-merge-props intern-props props - (append (nth 2 toolbarx-button-props) - (nth 2 toolbarx-dropdown-props)) - (append (nth 3 toolbarx-button-props) - (nth 3 toolbarx-dropdown-props))))) - ;; check whether merged props have an `:insert' - (if (memq :insert merged-props) - ;; if yes, prepend switches with a (:insert cond elements) - (let* ((memq-ins (memq :insert merged-props)) - (ins-val (if (and (listp (cadr memq-ins)) - (eq :add-value-list - (car (cadr memq-ins)))) - ;; if property is add-value property - (let* ((p (assq - :insert - (nth 0 toolbarx-button-props))) - (add-list (list (cddr p))) - (prop-good-val)) - (dolist (val (cdr (cadr memq-ins))) - (setq prop-good-val (funcall (cadr p) val)) - (when (car prop-good-val) - (setq add-list (cons (cdr prop-good-val) - add-list)))) - ;; return: (nreverse add-list) - (setq add-list (nreverse add-list)) - (if (eq 2 (length add-list)) - (cadr add-list) ; just 1 value, no - add-list)) ; add-function - ;; if property is not add-value - (cadr memq-ins))) - (merged-props-without-insert - (append (butlast merged-props (length memq-ins)) - (cddr memq-ins))) - (group-switches - (toolbarx-process-group-without-insert - group-without-props merged-props-without-insert - meaning-alist nil))) - ;; return - (nreverse (cons (append (list :insert ins-val) - group-switches) - (nreverse switches)))) - ;; if not, just append what is processed to switches - (toolbarx-process-group-without-insert group-without-props - merged-props meaning-alist - switches)))))) - -(defun toolbarx-process-symbol (symbol meaning-alist props switches) - "Process a button given by SYMBOL in MEANING-ALIST. -The processed button is appended in SWITCHES, which is returned. -Look for a association of SYMBOL in MEANING-ALIST for collecting -properties. Such association is a list that represents either a -normal button (a description of the button) or an alias -group (the symbol is an alias for a group of buttons). PROPS is -a externel list of properties that are merged and then applied to -the button. Scope is given by GLOBAL-FLAG." - ;; there are 3 situations: symbol is :new-line, there is an alias group - ;; or a normal button - (let ((button-assq (cdr (assq symbol meaning-alist)))) - (cond - ((eq (car button-assq) :alias) - ;; button association is ALIAS GROUP is passed to - ;; `toolbarx-process-group' as is but without the car. - ;; return: (toolbarx-process-group... returns updates switch - (toolbarx-process-group (cdr button-assq) meaning-alist props switches)) - (t - ;; NORMAL BUTTON (association is a list of properties) - ;; - ;; properties need to be processed, that is, merge internal - ;; and external (given by PROPS) properties - (let* (;; button properties defined in `toolbarx-button-props' - (props-override (nth 2 toolbarx-button-props)) - (props-add (nth 3 toolbarx-button-props)) - ;; split considering also dropdown-group properties - (button-assq-split - (toolbarx-separate-options - button-assq - (append (nth 1 toolbarx-button-props) - (nth 1 toolbarx-dropdown-props)))) - (button-split-no-props (car button-assq-split)) - (button-split-props (cdr button-assq-split)) - ;; if there is no :image or :command in the props, - ;; try to get them from no-props part - (button-image-no-prop - (unless (memq :image button-split-props) - (when (> (length button-split-no-props) 0) - (list :image (nth 0 button-split-no-props))))) - (button-command-no-prop - (unless (memq :command button-split-props) - (when (> (length button-split-no-props) 1) - (list :command (nth 1 button-split-no-props))))) - (button-props (append button-split-props - button-image-no-prop - button-command-no-prop)) - ;; merge props - (merged-props (toolbarx-merge-props button-props props - props-override - props-add))) - ;; return: - (nreverse (cons (cons symbol merged-props) (nreverse switches)))))))) - -(defun toolbarx-process-dropdown-group (dropdown meaning-alist props switches) - "Process buttons that appear according to dropdown menu. -Process a dropdown group DROPDOWN with meaning alist -MEANING-ALIST, external property list PROP and GLOBAL-FLAG -specifying scope. For a complete description, see documentation -of `toolbarx-install-toolbar'. The processed buttons are stored -in the end of SWITCHES, which is returned." - (let* ((dropdown-group (if (eq (car dropdown) :dropdown-group) - (cdr dropdown) - dropdown)) - (dropdown-list-splited - (toolbarx-separate-options dropdown-group - (append - (nth 1 toolbarx-button-props) - (nth 1 toolbarx-dropdown-props)))) - (dropdown-list (car dropdown-list-splited)) - (dropdown-props (cdr dropdown-list-splited)) - (merged-props - (toolbarx-merge-props dropdown-props props - (append (nth 2 toolbarx-button-props) - (nth 2 toolbarx-dropdown-props)) - (append (nth 3 toolbarx-button-props) - (nth 3 toolbarx-dropdown-props)))) - (merged-props-button-only - (let* ((props-button-only) - (prop)) - (dolist (p (nth 1 toolbarx-button-props) props-button-only) - (setq prop (memq p merged-props)) - (when prop - (setq props-button-only - (append (list p (cadr prop)) - props-button-only)))))) - (merged-props-dropdown-only - (let* ((props-dropdown-only) - (prop)) - (dolist (p (nth 1 toolbarx-dropdown-props) props-dropdown-only) - (setq prop (memq p merged-props)) - (when prop - (setq props-dropdown-only - (append (list p (cadr prop)) - props-dropdown-only)))))) - ;; get value for each property and check type ONLY for props that do - ;; not concern the dropdown button, like `:type', `:save', etc. The - ;; props that concern the button are going to be handled in refresh - ;; time. - (filtered-dropdown-group-props-only - (let* ((filtered-props-temp) - (prop-good-val) - (prop)) - (save-match-data - (dolist (p (nth 0 toolbarx-dropdown-props) filtered-props-temp) - (unless (string-match "^:dropdown-.*$" - (symbol-name (car p))) - ;; property -> (car p) - ;; test type function -> (cadr p) - (setq prop (memq (car p) merged-props-dropdown-only)) - ;; if so, check if value is of correct type - (when prop - (setq prop-good-val (funcall (cadr p) (cadr prop))) - (if (car prop-good-val) - (setq filtered-props-temp - (append filtered-props-temp - (list (car p) (cdr prop-good-val)))) - (display-warning - 'toolbarx - (format (concat "Wrong type for value in " - "property `%s' in dropdown group") - (car p)))))))))) - ;; properties for the dropdown button from dropdown merged properties - (dropdown-button-props - (let* ((props)) - (save-match-data - (dolist (pr (nth 1 toolbarx-dropdown-props)) - (when (and (memq pr merged-props-dropdown-only) - (string-match "^:dropdown-\\(.*\\)$" - (symbol-name pr))) - (let* ((new-pr (intern (concat ":" - (substring (symbol-name pr) - (match-beginning 1) - (match-end 1))))) - (val (cadr (memq pr merged-props-dropdown-only)))) - (setq props (append (list new-pr val) props)))))) - (unless (memq :image props) - (setq props (append (list :image "dropdown") props))) - props)) - (dropdown-button-without-command - (cons 'dropdown dropdown-button-props)) - ;; `:type' defaults to `radio' - (type (if (memq :type filtered-dropdown-group-props-only) - (cadr (memq :type filtered-dropdown-group-props-only)) - 'radio)) - ;; `:default' defaults to 1 or nil depending on `type' - ;; if type is toggle and default is not a list, but a - ;; integer, set as the list with integer - (default - (let* ((memq-default (memq :default - filtered-dropdown-group-props-only)) - (def-temp (cadr memq-default)) - (default-temp (if memq-default - def-temp - (if (eq type 'radio) 1 (list 1))))) - default-temp)) - ;; `:save' defaults to nil and require `:variable' - (save (let* ((save-temp - (when (memq :save filtered-dropdown-group-props-only) - (cadr (memq :save - filtered-dropdown-group-props-only))))) - (if (and save-temp - (not (memq :variable - filtered-dropdown-group-props-only))) - (progn - (display-warning - 'toolbarx - (concat "`:save' property with non-nil value should " - "be used only with the `:variable' property; " - "using value nil for `:save'.")) - nil) - save-temp))) - ;; `:title' defaults to nil - (title (when (memq :title filtered-dropdown-group-props-only) - (cadr (memq :title filtered-dropdown-group-props-only)))) - ;; the menu variable is buildt from the `:variable' option or - ;; make a symbol not used - (variable (if (memq :variable filtered-dropdown-group-props-only) - (cadr (memq :variable - filtered-dropdown-group-props-only)) - (let* ((count 0) - (symb (intern (format - "toolbarx-internal-menu-var-%d" - count)))) - (while (boundp symb) - (setq count (1+ count)) - (setq symb - (intern (format "toolbarx-internal-menu-var-%d" - count)))) - symb))) - ;; auxiliary variables - (list-strings) - (list-buttons)) - ;; setting `variable' - (if save - (custom-declare-variable - variable default - "Used as variable of dropdown menu defined with `toolbarx'.") - (when (not (boundp variable)) - (set variable default))) - ;; now check `variable' content - (set variable - (let ((val (symbol-value variable))) - (if (eq type 'toggle) - (if (listp val) - val - (if (integerp val) - (list val) - (list 1))) - ;; then, type is radio - (if (integerp val) - val - (if (and val - (listp val) - (integerp (car val))) - (car val) - 1))))) - ;; === buiding `list-strings' and `list-buttons' === - ;; if only symbols, build `list-strings' and `list-buttons' from symbols - (if (let ((only-symbols-flag t)) - (dolist (i dropdown-list only-symbols-flag) - (setq only-symbols-flag (and only-symbols-flag (symbolp i))))) - (let ((count 0)) - (dolist (i dropdown-list) - ;; list-strings and list-buttons are built reversed - (setq list-strings (cons (toolbarx-make-string-from-symbol i) - list-strings)) - (setq count (1+ count)) - (setq list-buttons (cons (list i - :insert - (if (eq type 'radio) - (list 'eq count variable) - (list 'memq count variable))) - list-buttons)))) - ;; if not, the it must start with string - (unless (stringp (car dropdown-list)) - (error "%s %s %s" - "If not all items on dropdown are symbols, then a string" - "must come before each set of buttons; no string found" - "in first position")) - (let ((count 0) - (elem) - (temp-list-buttons)) - (while dropdown-list - (setq elem (car dropdown-list)) - (setq dropdown-list (cdr dropdown-list)) - (if (stringp elem) - ;; if string, output `temp-list-buttons' and prepair it again - (progn - ;; list-strings and list-buttons are buildt reversed - (setq list-strings (cons elem list-strings)) - (when temp-list-buttons - (setq list-buttons (cons (append (nreverse temp-list-buttons) - (list :insert - (if (eq type 'radio) - (list 'eq count - variable) - (list 'memq count - variable)))) - list-buttons))) - (setq temp-list-buttons nil) - (setq count (1+ count))) - ;; else, if not string, just insert it to `temp-list-buttons' - ;; which is also buildt reversed - (setq temp-list-buttons (cons elem temp-list-buttons)))) - ;; output last temp list, left behind - (when temp-list-buttons - (setq list-buttons (cons (append (nreverse - temp-list-buttons) - (list - :insert (if (eq type 'radio) - (list 'eq count - variable) - (list 'memq count - variable)))) - list-buttons))))) - ;; lists were made reversed (elements inserted at the beginning) - (setq list-strings (nreverse list-strings)) - (setq list-buttons (nreverse list-buttons)) - ;; now, pass `list-buttons' as a group to `toolbarx-process-group' - (let ((current-switches switches)) - (setq current-switches - (toolbarx-process-group list-buttons meaning-alist - merged-props ; pass non-processed props - current-switches)) - (setq current-switches - ;; outputing dropdown button - (toolbarx-process-group (append dropdown-button-without-command - (list :command - (toolbarx-mount-popup-menu - list-strings variable type - title save))) - meaning-alist merged-props-button-only - switches)) - current-switches))) - - - -;; Still functions `toolbarx-install-toolbar' and `toolbarx-refresh'to -;; complete the parsing engine. Since they interface with other engines, -;; they must come in the end. - -;;; How a image is made, giving a string as (part of) file name. - -;; look at function `image-type-available-p' for Emacs !!!! - -(defun toolbarx-find-image (image) - "Return image descriptor or glyph for IMAGE. - -IMAGE is string. Usually IMAGE neither contains a directory nor -an extension. If the extension is omitted, `xpm', `xbm' and -`pbm' are tried. If the directory is omitted, -`toolbarx-image-path' is searched." - (let ((file)) - (dolist (i '("" ".xpm" ".xbm" ".pbm")) - (unless file - (setq file (locate-library (concat image i) t toolbarx-image-path)))) - (if file - (create-image file) - (find-image `((:type xpm :file ,(concat image ".xpm")) - (:type xbm :file ,(concat image ".xbm")) - (:type pbm :file ,(concat image ".pbm"))))))) - -;; next variable interfaces between parsing and display engines -(defvar toolbarx-internal-button-switches nil - "Store the list of processed buttons, used by `toolbarx-refresh'. -This variable can store different values for the different buffers.") - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Second engine: display parsed buttons in Emacs - -(defun toolbarx-emacs-add-button (button used-keys keymap) - "Insert a button where BUTTON is its description. -USED-KEYS should be a list of symbols, where the first element is -`:used-symbols'. This list should store the symbols of the -buttons already inserted. This list is changed by side effect. -KEYMAP is the keymap where the menu-item corresponding to the -tool-bal button is going to be inserted. Insertion is made in -the end of KEYMAP. - -BUTTON should be a list of form (SYMBOL . PROP-LIST). SYMBOL is -a symbol that \"names\" this button. PROP-LIST is a list in the -format (PROP VAL ... PROP VAL). The supported properties are -`:image', `:command', `:append-command', `:prepend-command', -`:help', `:enable', `:visible', `:button', and `:insert'. -For a description of properties, see documentation of -function `toolbar-install-toolbar'." - (let* ((symbol (nth 0 button)) - (used-keys-list (when used-keys - (cdr used-keys))) - (filtered-props - (let* ((filtered-props-temp) - (prop-good-val) - (prop)) - (dolist (p (nth 0 toolbarx-button-props) filtered-props-temp) - ;; property -> (car p) - ;; test type function -> (cadr p) - ;; add-function -> (cddr p) - (setq prop (memq (car p) button)) - ;; if so, check if value is of correct type - (when prop - ;; if property is of add-type, them the value is a list - ;; (:add-value-list VAL VAL). Each VAL should be checked. - (if (and (cddr p) (eq :add-value-list (car (cadr prop)))) - (let* ((add-list (list (cddr p)))) - (dolist (val (cdr (cadr prop))) - (setq prop-good-val (funcall (cadr p) val)) - (when (car prop-good-val) - (setq add-list (cons (cdr prop-good-val) add-list)))) - (setq add-list (nreverse add-list)) - (when (eq 2 (length add-list)) ; just 1 value, no - ; add-function - (setq add-list (cadr add-list))) - (setq filtered-props-temp (append - (list (car p) add-list) - filtered-props-temp))) - ;; if override-property - (setq prop-good-val (funcall (cadr p) (cadr prop))) - (when (car prop-good-val) - (setq filtered-props-temp (append - (list (car p) - (cdr prop-good-val)) - filtered-props-temp)))))))) - (insert (or (not (memq :insert filtered-props)) - ;; (memq :insert filtered-props) - (eval (nth 1 (memq :insert filtered-props)) t)))) - (when insert - (cond - (t - ;; symbol is not :new-line, therefore a normal button - (let* ((image (cadr (memq :image filtered-props))) - (image-descriptor - (when (memq :image filtered-props) - (cond - ((stringp image) ; string - (toolbarx-find-image image)) - ((and (consp image) ; or image descriptor - (eq (car image) 'image)) - image) - ((and (symbolp image) ; or a symbol bound to a - (boundp image) ; image descriptor (defined - ; with `defimage')g - (consp (symbol-value image)) - (eq (car (symbol-value image)) 'image)) - (symbol-value image)) - (t ; otherwise, must be a list - ; with 4 strings or image - ; descriptors - (apply #'vector (mapcar (lambda (img) - (if (stringp img) - (toolbarx-find-image img) - img)) - image)))))) - (command - (let* ((com (nth 1 (memq :command filtered-props))) - (app (nth 1 (memq :append-command filtered-props))) - (prep (nth 1 (memq :prepend-command filtered-props)))) - (when (or com app prep) - (toolbarx-make-command com prep app)))) - (help (cons (memq :help filtered-props) - (cadr (memq :help filtered-props)))) - (enable (cons (memq :enable filtered-props) - (cadr (memq :enable filtered-props)))) - (visible (cons (memq :visible filtered-props) - (cadr (memq :visible filtered-props)))) - (button (cons (memq :button filtered-props) - (cadr (memq :button filtered-props)))) - (menuitem (if (eq symbol 'separator) - '(menu-item "--") - (append - (list 'menu-item - (toolbarx-make-string-from-symbol symbol) - command - :image image-descriptor) - (when (car help) - (list :help (cdr help))) - (when (car enable) - (list :enable (cdr enable))) - (when (car visible) - (list :visible (cdr visible))) - (when (car button) - (list :button (cdr button))) - '(:vert-only t)))) - (key-not-used - (let* ((count 0) - (symb symbol)) - (while (memq symb used-keys-list) - (setq count (1+ count)) - (setq symb (intern (format "%s-%d" symbol count)))) - symb))) - (when (and image-descriptor command) - (setq used-keys-list (cons key-not-used used-keys-list)) - (define-key-after keymap - (vector key-not-used) menuitem)))))) - (when used-keys (setcdr used-keys used-keys-list)))) - - -(defun toolbarx-emacs-refresh-process-button-or-insert-list (switches - used-keys - keymap) - "Process SWITCHES, inserting buttons in `tool-bar-map'. -If a button is actually a `:insert' clause group (if `car' is -`:insert') and evaluation of `cdr' yields non-nil, process `cddr' -recursively as SWITCHES. USED-KEYS is a list which `car' is -`:used-symbols' and which `cdr' is a list of symbols that have already -been used as keys in the keymap `tool-bar-map'." - (dolist (button switches) - (if (eq (car button) :insert) - (when (eval (cadr button) t) - (toolbarx-emacs-refresh-process-button-or-insert-list (cddr button) - used-keys - keymap)) - (toolbarx-emacs-add-button button used-keys keymap)))) - - - -(defun toolbarx-emacs-refresh (&optional global-flag) - "Refresh and redraw the toolbar in Emacs. -If GLOBAL-FLAG is non-nil, the default value of toolbar switches -is used and the default value of `toolbarx-map' is changed." - (let* ((switches (if global-flag - (if (default-boundp 'toolbarx-internal-button-switches) - (default-value 'toolbarx-internal-button-switches) - toolbarx-internal-button-switches) - toolbarx-internal-button-switches)) - (used-keys (list :used-symbols nil)) - (tool-bar-map-temp (make-sparse-keymap))) - (toolbarx-emacs-refresh-process-button-or-insert-list switches used-keys - tool-bar-map-temp) - (if global-flag - (setq-default tool-bar-map tool-bar-map-temp) - (setq tool-bar-map tool-bar-map-temp)))) - - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; finishing parsing engine - -(defun toolbarx-refresh (&optional global-flag) - "Redraw the toolbar, peviously installed with `toolbarx'. -Force global refresh if GLOBAL-FLAG is non-nil." - (interactive "P") - (toolbarx-emacs-refresh global-flag)) - -;;;###autoload (autoload 'toolbarx-install-toolbar "toolbar-x") - -(defun toolbarx-install-toolbar (buttons &optional meaning-alist global-flag) - "Install toolbar buttons given in BUTTONS. -Button properties are optionally given in MEANING-ALIST. If -GLOBAL-FLAG is non-nil, toolbar is installed globally (on every -buffer that does not have a toolbar set locally). BUTTONS is a -list of format - (ELEM ... ELEM . PROPS), -where each ELEM is either - - - a list in the same format od BUTTONS, which is going to be - refered as a *group*; groups are used to distribute properties - recursively to its elements; there are groups with special - format for special purpose: *dropdown groups* and also *eval - groups*. - - - a symbol, which could be associated in MEANING-ALIST with a - list of button properties (symbol + properties = a *button*) - or associated to a special kind of group (an *alias group*). - -Meaning alist -============= - -MEANING-ALIST is a list where each element is in one of the -formats (SYMB . BUTTON-PROPS-LIST) or (SYMB . ALIAS-GROUP). -BUTTON-PROPS-LIST is a list in one of the formats - (IMAGE COMMAND PROP VAL PROP VAL ... PROP VAL) or - (PROP VAL PROP VAL ... PROP VAL). -The IMAGE is going to be used as the `:image' property of the -button (see button properties bellow), and COMMAND shall be used -as the `:command' property of the button. Each PROP is one of -the button properties, and VAL is its respective value. -ALIAS-GROUP is a list which first element is the symbol `:alias' -and the cdr shall be processed as a group. - -However, a symbol is not required to have an association in -MEANING-ALIST, which is only a way to specify properties to a -button. One can use groups to specify properties. Nil is a good -MEANING-ALIST. - -Buttons -======= - -A toolbar button in `toolbarx' is the set with a symbol and -properties used to display the button, like a image and a command -to call when the button is pressed (which are the minimal -elements that a button should have.) The supported properties -for buttons and their `basic types' (see note on how values of -properties are obtained!) are: - - :image -- either a string or image descriptor (see - info for a definition), or a variable bound to a image - descriptor (like those defined with `defimage') or a list of 4 - strings or image descriptors; - defines the image file displayed by the button. If - it is a string, the image file found with that name (always - using the function `toolbarx-find-image' to make the - \`internal\' image descriptor) is used as button image. For - the other formats, the button image is handled in the same way - as it is treated by the editors; see info nodes bellow for a - description of the capabilities: - info file \"elisp\", node \"Tool Bar\" (see `:image' property); - PS: a *vector* of four strings is used in the Emacs - Lisp documentation as the `more ellaborated' image - property format, but here we reserve vectors to - provide editor-dependent values; this motivates our - choice for a list instead of vector (however, - internally the list becomes a vector when displaying - the button). - - :command -- a form; if the form happens to be a command, it will - be called with `call-interactively'. - - :append-command -- a form added to the end of the value of - `:command'. - - :prepend-command -- a form added at the beginning of the value - of `:command'. - - :help -- either a string or nil; defined the help string of the - button; - - :enable -- a form, evaluated constantly by both editors to - determine if a button is active (enabled) or not. - - :visible -- a form that is evaluated constantly to - determine if a button is visible. - - :button -- a cons cell (TYPE . SELECTED) where the - TYPE should be `:toggle' or `:radio' and the cdr should be a - form. SELECTED is evaluated to determine when the button is - selected. - - :insert -- a form that is evaluated every time that the toolbar - is refresh (a call of `toolbarx-refresh') to determine if the - button is inserted or just ignored (until next refresh). - -How to specify a button -======================= - -One can specify a button by its symbol or by a group to specify -properties. For example, - BUTTON = - ( foo - (bar :image \"bar\" - :command bar-function :help \"Bar help string\") - :insert foo-bar ) - MEANING-ALIST = ( (foo :image \"foo\" :command foo-function) ) -specifiy two buttons `foo' and `bar', each one with its necessary -:image and :command properties, and both use the :insert property -specified ate the end of BUTTONS (because groups distribute -properties to all its elements). `foo' and `bar' will be -inserted only if `foo-bar' evaluation yields non-nil. - -Note on how values of properties are obtained -============================================= - -For each property PROP, its value should be either: - i) a vector of 2 elements; then each element should be of the - basic type of PROP. - ii) an element on the basic type of PROP. - iii) a function (that does not need arguments); it is evaluated - and the return should be ot type i) or ii) above - iv) a symbol bound to a element of type i) or ii). - -The type is cheched in the order i), ii) iii) and iv). This -evaluations are done every time that the oolbar is refresh. - -Ps.: in order to specify a vector as value of a property (like -the :image in Emacs), it is necessary to provide the vector as -element of another vector. - -Special groups -============== - -Eval groups ------------ - -If the first element of a group is the symbol `:eval-group', each -element is evaluated (with `eval'), put inside a list and -processed like a group. Eval groups are useful to store -definition of buttons in a variable. - -Dropdown groups ---------------- - -The idea is to specify a set of buttons that appear when a -determined menu item of a dropdown menu is active. The dropdown -menu appears when a button (by default with a triangle pointing -down) is clicked. This button is called `dropdown button'. The -dropdown button appears on the left of the currently visible -buttons of the dropdown group. - -A dropdown group is a list which first element is the symbol -`:dropdown-group' and in one of the following formats - (:dropdown-group SYMBOL-1 ... SYMBOL-n PROP-1 VAL-1 ... PROP-k VAL-k) -or - (:dropdown-group - STRING-1 ITEM-11 ... ITEM-1n - STRING-2 ITEM-21 ... ITEM-2m - . . . - STRING-n ITEM-n1 ... ITEM-np - PROP-1 VAL-1 ... PROP-j VAL-j) -where - SYMBOL-* is a symbol that defines a button in MEANING-ALIST; - STRING-* is a string that will appear in the dropdown menu; - ITEM-* is any format that define buttons or groups. - -\(a dropdown group of first format is internally converted to the -second by making strings from the symbols and each symbol is the -item) - -The same rules for obtaining property values, described above, -apply here. Properties are also distributed by groups. The -supported properties and their basic type are: - - :type -- one of the symbols `radio' (default) or `toggle'; if - type is radio, only one of the itens may be active, and if - type is toggle, any item number of itens can be active. - - :variable -- a symbol; it is the variable that govern the - dropdown button; every time the value should be an integer - starting from 1 (if type is radio) or a list of integers (if - type is toggle). The Nth set of buttons is :insert'ed. - - :default -- determines the default value when the menu is - installed; it is ignored if a value was saved with custom; it - defaults to 1 if type is radio or nil if type is toggle. If - value is a integer and type is `toggle', value used is a list - with that integer. - - :save -- one of the symbols nil (default), `offer' or - `always'; determined if it is possible for the user to save - the which menu itens are active, for a next session. If value - is `offer', a item (offering to save) is added to the - popup menu. If the value is `always', every time that a item - is selected, the variable is saved. If value is nil, variable - shall not be saved. If value is non-nil then `:variable' is - mandatory. - - :title -- a string or nil; if a string, the popup menu will show - is as menu title; if nil, no title is shown. - - :dropdown-help -- a string or nil; the help string of the - dropdown button. - - :dropdown-image -- either a string or a vector of 4 strings; - defines the image file displayed by the dropdown button; - by default, it is the string \"dropdown\". - - :dropdown-append-command, - :dropdownprepend-command -- a form; append or prepend forms to - the command that shows the dropdown menu, allowing extra code - to run before or after the menu appears (remember that every - menu item clicked refresh the toolbar.) - - :dropdown-enable -- a form; evaluated constantly by both editors - to determine if the dropdown button is active (enabled) or - not. - - :dropdown-visible -- a form; it is evaluated - constantly to determine if the dropdown button is visible. - -Also, if the symbol `dropdown' is associted in MEANING-ALIST -with some properties, these properties override (or add) with -higher precedence. - -Special buttons -=============== - -If the symbol of a button is `:new-line', it is inserted -a (faked) return, and the next button will be displayed a next -line of buttons. The only property supported for this button is -`:insert'." - (let ((switches (toolbarx-process-group buttons meaning-alist nil nil))) - (if global-flag - (setq-default toolbarx-internal-button-switches - switches) - (set (make-local-variable 'toolbarx-internal-button-switches) - switches) - (make-local-variable 'tool-bar-map))) - (toolbarx-refresh global-flag)) - - -(defconst toolbarx-default-toolbar-meaning-alist - '((separator :image "sep" :command t :enable nil :help "") - - (new-file - :image "new" - :command find-file - :enable (not (window-minibuffer-p - (frame-selected-window menu-updating-frame))) - :help "Specify a new file's name, to edit the file") - - (open-file :image "open" - :command menu-find-file-existing - :enable (not (window-minibuffer-p - (frame-selected-window menu-updating-frame))) - :help "Read a file into an Emacs buffer") - - (dired :image "diropen" - :command dired - :help "Read a directory, operate on its files") - - (save-buffer :image "save" - :command save-buffer - :enable (and - (buffer-modified-p) - (buffer-file-name) - (not (window-minibuffer-p - (frame-selected-window menu-updating-frame)))) - :help "Save current buffer to its file" - :visible (or buffer-file-name - (not (eq 'special - (get major-mode 'mode-class))))) - - (write-file :image "saveas" - :command write-file - :enable (not - (window-minibuffer-p - (frame-selected-window menu-updating-frame))) - :help "Write current buffer to another file" - :visible (or buffer-file-name - (not (eq 'special (get major-mode 'mode-class))))) - - (undo :image "undo" - :command undo - :enable (and (not buffer-read-only) - (not (eq t buffer-undo-list)) - (if (eq last-command #'undo) - pending-undo-list - (consp buffer-undo-list))) - :help "Undo last operation" - :visible (not (eq 'special (get major-mode 'mode-class)))) - - (cut :image "cut" - :help "Delete text in region and copy it to the clipboard" - :command clipboard-kill-region - :visible (not (eq 'special (get major-mode 'mode-class)))) - - (copy :image "copy" - :help "Copy text in region to the clipboard" - :command clipboard-kill-ring-save) - - (paste :image "paste" - :help "Paste text from clipboard" - :command clipboard-yank - :visible (not (eq 'special (get major-mode 'mode-class)))) - - (search-forward :command nonincremental-search-forward - :help "Search forward for a string" - :image "search") - - (search-replace - :image "search-replace" - :command query-replace - :help "Replace string interactively, ask about each occurrence") - - (print-buffer :image "print" - :command print-buffer - :help "Print current buffer with page headings") - - (customize :image "preferences" - :command customize - :help "Edit preferences (customize)") - - (help :image "help" - :command (lambda () (interactive) (popup-menu menu-bar-help-menu)) - :help "Pop up the Help menu") - - (kill-buffer :command kill-this-buffer - :enable (kill-this-buffer-enabled-p) - :help "Discard current buffer" - :image "close") - - (exit-emacs :image "exit" - :command save-buffers-kill-emacs - :help "Offer to save unsaved buffers, then exit Emacs") - - (spell-buffer :image "spell" - :command ispell-buffer - :help "Check spelling of selected buffer") - - (info :image "info" - :command info - :help "Enter Info, the documentation browser")) - "A meaning alist with definition of the default buttons. -The following buttons are available: - - `open-file', `dired', `save-buffer', - `undo', `cut', `copy', `paste', `search-replace', `print-buffer', - `spell-buffer', `info'. - `new-file', `write-file', `search-forward', - `customize', `help', `kill-buffer', `exit-emacs'. - -To reproduce the default toolbar with use as BUTTON -in `toolbarx-install-toolbar': - -\(toolbarx-install-toolbar - \\='((open-file dired kill-buffer save-buffer write-file undo cut - copy paste search-forward print-buffer customize help)) - toolbarx-default-toolbar-meaning-alist) - -Ps.: there are more buttons available than suggested in the -expression above.") - -(provide 'toolbar-x) - -;;; toolbar-x.el ends here |