* startup.el (command-line): Enable tool-bar-mode as long as it is
[bpt/emacs.git] / lisp / tool-bar.el
CommitLineData
e8af40ee 1;;; tool-bar.el --- setting up the tool bar
ec7f4585 2;;
5fd6d89f 3;; Copyright (C) 2000, 2001, 2002, 2003, 2004,
409cc4a3 4;; 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
ec7f4585
DL
5;;
6;; Author: Dave Love <fx@gnu.org>
7;; Keywords: mouse frames
8
9;; This file is part of GNU Emacs.
10
eb3fa2cf 11;; GNU Emacs is free software: you can redistribute it and/or modify
ec7f4585 12;; it under the terms of the GNU General Public License as published by
eb3fa2cf
GM
13;; the Free Software Foundation, either version 3 of the License, or
14;; (at your option) any later version.
ec7f4585
DL
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
eb3fa2cf 22;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
ec7f4585
DL
23
24;;; Commentary:
25
02d709c0 26;; Provides `tool-bar-mode' to control display of the tool-bar and
ec7f4585
DL
27;; bindings for the global tool bar with convenience functions
28;; `tool-bar-add-item' and `tool-bar-add-item-from-menu'.
29
9a4b8870 30;; The normal global binding for [tool-bar] (below) uses the value of
c129b5ef
DL
31;; `tool-bar-map' as the actual keymap to define the tool bar. Modes
32;; may either bind items under the [tool-bar] prefix key of the local
33;; map to add to the global bar or may set `tool-bar-map'
b28e72df 34;; buffer-locally to override it. (Some items are removed from the
9a4b8870 35;; global bar in modes which have `special' as their `mode-class'
b011dcb0 36;; property.)
9a4b8870 37
adf7d3a8
DL
38;; Todo: Somehow make tool bars easily customizable by the naive?
39
ec7f4585
DL
40;;; Code:
41
646cb69e
RS
42;; The autoload cookie doesn't work when preloading.
43;; Deleting it means invoking this command won't work
44;; when you are on a tty. I hope that won't cause too much trouble -- rms.
ec7f4585
DL
45(define-minor-mode tool-bar-mode
46 "Toggle use of the tool bar.
a81fc510 47With numeric ARG, display the tool bar if and only if ARG is positive.
ec7f4585
DL
48
49See `tool-bar-add-item' and `tool-bar-add-item-from-menu' for
50conveniently adding tool bar items."
929e8487 51 :init-value nil
ec7f4585
DL
52 :global t
53 :group 'mouse
54 :group 'frames
ef32aa02 55 (and (display-images-p)
095fe281
KL
56 (modify-all-frames-parameters (list (cons 'tool-bar-lines
57 (if tool-bar-mode 1 0))))
ef32aa02 58 (if (and tool-bar-mode
095fe281 59 (display-graphic-p))
ef32aa02 60 (tool-bar-setup))))
ec7f4585 61
929e8487 62;;;###autoload
6a5af08f
KL
63;; Used in the Show/Hide menu, to have the toggle reflect the current frame.
64(defun toggle-tool-bar-mode-from-frame (&optional arg)
65 "Toggle tool bar on or off, based on the status of the current frame.
66See `tool-bar-mode' for more information."
67 (interactive (list (or current-prefix-arg 'toggle)))
68 (if (eq arg 'toggle)
69 (tool-bar-mode (if (> (frame-parameter nil 'tool-bar-lines) 0) 0 1))
70 (tool-bar-mode arg)))
71
72;;;###autoload
929e8487
PA
73;; We want to pretend the toolbar by standard is on, as this will make
74;; customize consider disabling the toolbar a customization, and save
75;; that. We could do this for real by setting :init-value above, but
76;; that would turn on the toolbar in MS Windows where it is currently
77;; useless, and it would overwrite disabling the tool bar from X
78;; resources. If anyone want to implement this in a cleaner way,
79;; please do so.
80;; -- Per Abrahamsen <abraham@dina.kvl.dk> 2002-02-21.
81(put 'tool-bar-mode 'standard-value '(t))
82
9a4b8870
DL
83(defvar tool-bar-map (make-sparse-keymap)
84 "Keymap for the tool bar.
85Define this locally to override the global tool bar.")
86
87(global-set-key [tool-bar]
88 '(menu-item "tool bar" ignore
c8fcd943
SM
89 :filter tool-bar-make-keymap))
90
aa360da1
GM
91(declare-function image-mask-p "image.c" (spec &optional frame))
92
c8fcd943
SM
93(defun tool-bar-make-keymap (&optional ignore)
94 "Generate an actual keymap from `tool-bar-map'.
95Its main job is to figure out which images to use based on the display's
96color capability and based on the available image libraries."
97 (mapcar (lambda (bind)
71928058 98 (let (image-exp plist)
c8fcd943 99 (when (and (eq (car-safe (cdr-safe bind)) 'menu-item)
71928058
CY
100 ;; For the format of menu-items, see node
101 ;; `Extended Menu Items' in the Elisp manual.
102 (setq plist (nthcdr (if (consp (nth 4 bind)) 5 4)
103 bind))
104 (setq image-exp (plist-get plist :image))
105 (consp image-exp)
106 (not (eq (car image-exp) 'image))
107 (fboundp (car image-exp)))
108 (if (not (display-images-p))
109 (setq bind nil)
110 (let ((image (eval image-exp)))
6a9cbb85 111 (unless (and image (image-mask-p image))
71928058
CY
112 (setq image (append image '(:mask heuristic))))
113 (setq bind (copy-sequence bind)
114 plist (nthcdr (if (consp (nth 4 bind)) 5 4)
115 bind))
116 (plist-put plist :image image))))
117 bind))
c8fcd943
SM
118 tool-bar-map))
119
120(defconst tool-bar-find-image-cache (make-hash-table :weakness t :test 'equal))
121
122(defun tool-bar-find-image (specs)
123 "Like `find-image' but with caching."
124 (or (gethash specs tool-bar-find-image-cache)
125 (puthash specs (find-image specs) tool-bar-find-image-cache)))
ec7f4585
DL
126
127;;;###autoload
9a4b8870 128(defun tool-bar-add-item (icon def key &rest props)
ec7f4585
DL
129 "Add an item to the tool bar.
130ICON names the image, DEF is the key definition and KEY is a symbol
9a4b8870
DL
131for the fake function key in the menu keymap. Remaining arguments
132PROPS are additional items to add to the menu item specification. See
133Info node `(elisp)Tool Bar'. Items are added from left to right.
ec7f4585 134
cb4aae04 135ICON is the base name of a file containing the image to use. The
d36b11e2 136function will first try to use low-color/ICON.xpm if `display-color-cells'
968d6127 137is less or equal to 256, then ICON.xpm, then ICON.pbm, and finally
cb4aae04 138ICON.xbm, using `find-image'.
9a4b8870 139
ca1b34c8
RS
140Use this function only to make bindings in the global value of `tool-bar-map'.
141To define items in any other map, use `tool-bar-local-item'."
142 (apply 'tool-bar-local-item icon def key tool-bar-map props))
143
144;;;###autoload
145(defun tool-bar-local-item (icon def key map &rest props)
146 "Add an item to the tool bar in map MAP.
147ICON names the image, DEF is the key definition and KEY is a symbol
148for the fake function key in the menu keymap. Remaining arguments
149PROPS are additional items to add to the menu item specification. See
150Info node `(elisp)Tool Bar'. Items are added from left to right.
151
152ICON is the base name of a file containing the image to use. The
c8fcd943 153function will first try to use low-color/ICON.xpm if `display-color-cells'
968d6127 154is less or equal to 256, then ICON.xpm, then ICON.pbm, and finally
ca1b34c8 155ICON.xbm, using `find-image'."
3fae165c
GM
156 (let* ((fg (face-attribute 'tool-bar :foreground))
157 (bg (face-attribute 'tool-bar :background))
158 (colors (nconc (if (eq fg 'unspecified) nil (list :foreground fg))
159 (if (eq bg 'unspecified) nil (list :background bg))))
cf545823
JD
160 (xpm-spec (list :type 'xpm :file (concat icon ".xpm")))
161 (xpm-lo-spec (if (> (display-color-cells) 256)
162 nil
ffda926c
BW
163 (list :type 'xpm :file
164 (concat "low-color/" icon ".xpm"))))
165 (pbm-spec (append (list :type 'pbm :file
166 (concat icon ".pbm")) colors))
167 (xbm-spec (append (list :type 'xbm :file
168 (concat icon ".xbm")) colors))
c8fcd943
SM
169 (image-exp `(tool-bar-find-image
170 (if (display-color-p)
171 ',(list xpm-lo-spec xpm-spec pbm-spec xbm-spec)
172 ',(list pbm-spec xbm-spec xpm-lo-spec xpm-spec)))))
cf545823 173
c8fcd943
SM
174 (define-key-after map (vector key)
175 `(menu-item ,(symbol-name key) ,def :image ,image-exp ,@props))))
ec7f4585 176
c2156508 177;;;###autoload
ec7f4585 178(defun tool-bar-add-item-from-menu (command icon &optional map &rest props)
7c064859 179 "Define tool bar binding for COMMAND in keymap MAP using the given ICON.
ca1b34c8
RS
180This makes a binding for COMMAND in `tool-bar-map', copying its
181binding from the menu bar in MAP (which defaults to `global-map'), but
182modifies the binding by adding an image specification for ICON. It
183finds ICON just like `tool-bar-add-item'. PROPS are additional
184properties to add to the binding.
185
186MAP must contain appropriate binding for `[menu-bar]' which holds a keymap.
187
188Use this function only to make bindings in the global value of `tool-bar-map'.
7c064859 189To define items in any other map, use `tool-bar-local-item-from-menu'."
03a8bf7d
SM
190 (apply 'tool-bar-local-item-from-menu command icon
191 (default-value 'tool-bar-map) map props))
ca1b34c8
RS
192
193;;;###autoload
194(defun tool-bar-local-item-from-menu (command icon in-map &optional from-map &rest props)
7c064859 195 "Define local tool bar binding for COMMAND using the given ICON.
ca1b34c8
RS
196This makes a binding for COMMAND in IN-MAP, copying its binding from
197the menu bar in FROM-MAP (which defaults to `global-map'), but
198modifies the binding by adding an image specification for ICON. It
199finds ICON just like `tool-bar-add-item'. PROPS are additional
200properties to add to the binding.
201
7c064859
NR
202FROM-MAP must contain appropriate binding for `[menu-bar]' which
203holds a keymap."
ca1b34c8
RS
204 (unless from-map
205 (setq from-map global-map))
206 (let* ((menu-bar-map (lookup-key from-map [menu-bar]))
ec7f4585 207 (keys (where-is-internal command menu-bar-map))
3fae165c
GM
208 (fg (face-attribute 'tool-bar :foreground))
209 (bg (face-attribute 'tool-bar :background))
210 (colors (nconc (if (eq fg 'unspecified) nil (list :foreground fg))
211 (if (eq bg 'unspecified) nil (list :background bg))))
cf545823
JD
212 (xpm-spec (list :type 'xpm :file (concat icon ".xpm")))
213 (xpm-lo-spec (if (> (display-color-cells) 256)
214 nil
ffda926c
BW
215 (list :type 'xpm :file
216 (concat "low-color/" icon ".xpm"))))
217 (pbm-spec (append (list :type 'pbm :file
218 (concat icon ".pbm")) colors))
219 (xbm-spec (append (list :type 'xbm :file
220 (concat icon ".xbm")) colors))
c8fcd943
SM
221 (image-exp `(tool-bar-find-image
222 (if (display-color-p)
223 ',(list xpm-lo-spec xpm-spec pbm-spec xbm-spec)
224 ',(list pbm-spec xbm-spec xpm-lo-spec xpm-spec))))
ec7f4585 225 submap key)
c8fcd943
SM
226 ;; We'll pick up the last valid entry in the list of keys if
227 ;; there's more than one.
228 (dolist (k keys)
229 ;; We're looking for a binding of the command in a submap of
230 ;; the menu bar map, so the key sequence must be two or more
231 ;; long.
232 (if (and (vectorp k)
233 (> (length k) 1))
234 (let ((m (lookup-key menu-bar-map (substring k 0 -1)))
235 ;; Last element in the bound key sequence:
236 (kk (aref k (1- (length k)))))
237 (if (and (keymapp m)
238 (symbolp kk))
239 (setq submap m
240 key kk)))))
241 (when (and (symbolp submap) (boundp submap))
242 (setq submap (eval submap)))
243 (let ((defn (assq key (cdr submap))))
244 (if (eq (cadr defn) 'menu-item)
245 (define-key-after in-map (vector key)
246 (append (cdr defn) (list :image image-exp) props))
247 (setq defn (cdr defn))
248 (define-key-after in-map (vector key)
249 (let ((rest (cdr defn)))
250 ;; If the rest of the definition starts
251 ;; with a list of menu cache info, get rid of that.
252 (if (and (consp rest) (consp (car rest)))
253 (setq rest (cdr rest)))
254 (append `(menu-item ,(car defn) ,rest)
255 (list :image image-exp) props)))))))
ec7f4585
DL
256
257;;; Set up some global items. Additions/deletions up for grabs.
258
095fe281 259(defvar tool-bar-setup nil
3ab3140b 260 "Set to t if the tool-bar has been set up by `tool-bar-setup'.")
095fe281
KL
261
262(defun tool-bar-setup (&optional frame)
263 (unless tool-bar-setup
264 (with-selected-frame (or frame (selected-frame))
265 ;; People say it's bad to have EXIT on the tool bar, since users
266 ;; might inadvertently click that button.
267 ;;(tool-bar-add-item-from-menu 'save-buffers-kill-emacs "exit")
268 (tool-bar-add-item-from-menu 'find-file "new")
269 (tool-bar-add-item-from-menu 'menu-find-file-existing "open")
270 (tool-bar-add-item-from-menu 'dired "diropen")
271 (tool-bar-add-item-from-menu 'kill-this-buffer "close")
272 (tool-bar-add-item-from-menu 'save-buffer "save" nil
273 :visible '(or buffer-file-name
274 (not (eq 'special
275 (get major-mode
276 'mode-class)))))
277 (tool-bar-add-item-from-menu 'write-file "saveas" nil
278 :visible '(or buffer-file-name
279 (not (eq 'special
280 (get major-mode
281 'mode-class)))))
282 (tool-bar-add-item-from-menu 'undo "undo" nil
283 :visible '(not (eq 'special (get major-mode
284 'mode-class))))
285 (tool-bar-add-item-from-menu (lookup-key menu-bar-edit-menu [cut])
286 "cut" nil
287 :visible '(not (eq 'special (get major-mode
288 'mode-class))))
289 (tool-bar-add-item-from-menu (lookup-key menu-bar-edit-menu [copy])
290 "copy")
291 (tool-bar-add-item-from-menu (lookup-key menu-bar-edit-menu [paste])
292 "paste" nil
293 :visible '(not (eq 'special (get major-mode
294 'mode-class))))
295 (tool-bar-add-item-from-menu 'nonincremental-search-forward "search")
296 ;;(tool-bar-add-item-from-menu 'ispell-buffer "spell")
297
298 ;; There's no icon appropriate for News and we need a command rather
299 ;; than a lambda for Read Mail.
c8fcd943 300 ;;(tool-bar-add-item-from-menu 'compose-mail "mail/compose")
095fe281 301
c8fcd943 302 (tool-bar-add-item-from-menu 'print-buffer "print")
095fe281 303
c8fcd943
SM
304 ;; tool-bar-add-item-from-menu itself operates on
305 ;; (default-value 'tool-bar-map), but when we don't use that function,
306 ;; we must explicitly operate on the default value.
095fe281 307
c8fcd943
SM
308 (let ((tool-bar-map (default-value 'tool-bar-map)))
309 (tool-bar-add-item "preferences" 'customize 'customize
310 :help "Edit preferences (customize)")
bc2fa80d 311
c8fcd943
SM
312 (tool-bar-add-item "help" (lambda ()
313 (interactive)
314 (popup-menu menu-bar-help-menu))
315 'help
316 :help "Pop up the Help menu"))
317 (setq tool-bar-setup t))))
ec7f4585 318
ec7f4585 319
c044516d 320(provide 'tool-bar)
cbee283d 321;; arch-tag: 15f30f0a-d0d7-4d50-bbb7-f48fd0c8582f
ec7f4585 322;;; tool-bar.el ends here