Add 2010 to copyright years.
[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,
114f9c96 4;; 2005, 2006, 2007, 2008, 2009, 2010 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
f3af39b8
CY
55 (if tool-bar-mode
56 (progn
fca863b8
MR
57 ;; Make one tool-bar-line for any - including non-graphical -
58 ;; terminal, see Bug#1754. If this causes problems, we should
59 ;; handle the problem in `modify-frame-parameters' or do not
60 ;; call `modify-all-frames-parameters' when toggling the tool
61 ;; bar off either.
62 (modify-all-frames-parameters (list (cons 'tool-bar-lines 1)))
e4779829
CY
63 (if (= 1 (length (default-value 'tool-bar-map))) ; not yet setup
64 (tool-bar-setup)))
f3af39b8 65 (modify-all-frames-parameters (list (cons 'tool-bar-lines 0)))))
ec7f4585 66
929e8487 67;;;###autoload
6a5af08f
KL
68;; Used in the Show/Hide menu, to have the toggle reflect the current frame.
69(defun toggle-tool-bar-mode-from-frame (&optional arg)
70 "Toggle tool bar on or off, based on the status of the current frame.
71See `tool-bar-mode' for more information."
72 (interactive (list (or current-prefix-arg 'toggle)))
73 (if (eq arg 'toggle)
74 (tool-bar-mode (if (> (frame-parameter nil 'tool-bar-lines) 0) 0 1))
75 (tool-bar-mode arg)))
76
77;;;###autoload
929e8487
PA
78;; We want to pretend the toolbar by standard is on, as this will make
79;; customize consider disabling the toolbar a customization, and save
80;; that. We could do this for real by setting :init-value above, but
81;; that would turn on the toolbar in MS Windows where it is currently
82;; useless, and it would overwrite disabling the tool bar from X
83;; resources. If anyone want to implement this in a cleaner way,
84;; please do so.
85;; -- Per Abrahamsen <abraham@dina.kvl.dk> 2002-02-21.
86(put 'tool-bar-mode 'standard-value '(t))
87
9a4b8870
DL
88(defvar tool-bar-map (make-sparse-keymap)
89 "Keymap for the tool bar.
90Define this locally to override the global tool bar.")
91
92(global-set-key [tool-bar]
1e8780b1 93 `(menu-item ,(purecopy "tool bar") ignore
c8fcd943
SM
94 :filter tool-bar-make-keymap))
95
aa360da1
GM
96(declare-function image-mask-p "image.c" (spec &optional frame))
97
b8067901
CY
98(defconst tool-bar-keymap-cache (make-hash-table :weakness t :test 'equal))
99
c8fcd943
SM
100(defun tool-bar-make-keymap (&optional ignore)
101 "Generate an actual keymap from `tool-bar-map'.
102Its main job is to figure out which images to use based on the display's
103color capability and based on the available image libraries."
b8067901
CY
104 (let ((key (cons (frame-terminal) tool-bar-map)))
105 (or (gethash key tool-bar-keymap-cache)
106 (puthash key (tool-bar-make-keymap-1) tool-bar-keymap-cache))))
107
108(defun tool-bar-make-keymap-1 ()
109 "Generate an actual keymap from `tool-bar-map', without caching."
c8fcd943 110 (mapcar (lambda (bind)
71928058 111 (let (image-exp plist)
c8fcd943 112 (when (and (eq (car-safe (cdr-safe bind)) 'menu-item)
71928058
CY
113 ;; For the format of menu-items, see node
114 ;; `Extended Menu Items' in the Elisp manual.
115 (setq plist (nthcdr (if (consp (nth 4 bind)) 5 4)
116 bind))
117 (setq image-exp (plist-get plist :image))
118 (consp image-exp)
119 (not (eq (car image-exp) 'image))
120 (fboundp (car image-exp)))
121 (if (not (display-images-p))
122 (setq bind nil)
123 (let ((image (eval image-exp)))
6a9cbb85 124 (unless (and image (image-mask-p image))
71928058
CY
125 (setq image (append image '(:mask heuristic))))
126 (setq bind (copy-sequence bind)
127 plist (nthcdr (if (consp (nth 4 bind)) 5 4)
128 bind))
129 (plist-put plist :image image))))
130 bind))
c8fcd943
SM
131 tool-bar-map))
132
ec7f4585 133;;;###autoload
9a4b8870 134(defun tool-bar-add-item (icon def key &rest props)
ec7f4585
DL
135 "Add an item to the tool bar.
136ICON names the image, DEF is the key definition and KEY is a symbol
9a4b8870
DL
137for the fake function key in the menu keymap. Remaining arguments
138PROPS are additional items to add to the menu item specification. See
139Info node `(elisp)Tool Bar'. Items are added from left to right.
ec7f4585 140
cb4aae04 141ICON is the base name of a file containing the image to use. The
d36b11e2 142function will first try to use low-color/ICON.xpm if `display-color-cells'
968d6127 143is less or equal to 256, then ICON.xpm, then ICON.pbm, and finally
cb4aae04 144ICON.xbm, using `find-image'.
9a4b8870 145
ca1b34c8
RS
146Use this function only to make bindings in the global value of `tool-bar-map'.
147To define items in any other map, use `tool-bar-local-item'."
148 (apply 'tool-bar-local-item icon def key tool-bar-map props))
149
150;;;###autoload
151(defun tool-bar-local-item (icon def key map &rest props)
152 "Add an item to the tool bar in map MAP.
153ICON names the image, DEF is the key definition and KEY is a symbol
154for the fake function key in the menu keymap. Remaining arguments
155PROPS are additional items to add to the menu item specification. See
156Info node `(elisp)Tool Bar'. Items are added from left to right.
157
158ICON is the base name of a file containing the image to use. The
c8fcd943 159function will first try to use low-color/ICON.xpm if `display-color-cells'
968d6127 160is less or equal to 256, then ICON.xpm, then ICON.pbm, and finally
ca1b34c8 161ICON.xbm, using `find-image'."
3fae165c
GM
162 (let* ((fg (face-attribute 'tool-bar :foreground))
163 (bg (face-attribute 'tool-bar :background))
164 (colors (nconc (if (eq fg 'unspecified) nil (list :foreground fg))
165 (if (eq bg 'unspecified) nil (list :background bg))))
cf545823 166 (xpm-spec (list :type 'xpm :file (concat icon ".xpm")))
afb465eb
CY
167 (xpm-lo-spec (list :type 'xpm :file
168 (concat "low-color/" icon ".xpm")))
ffda926c
BW
169 (pbm-spec (append (list :type 'pbm :file
170 (concat icon ".pbm")) colors))
171 (xbm-spec (append (list :type 'xbm :file
172 (concat icon ".xbm")) colors))
b8067901 173 (image-exp `(find-image
afb465eb
CY
174 (cond ((not (display-color-p))
175 ',(list pbm-spec xbm-spec xpm-lo-spec xpm-spec))
176 ((< (display-color-cells) 256)
177 ',(list xpm-lo-spec xpm-spec pbm-spec xbm-spec))
178 (t
179 ',(list xpm-spec pbm-spec xbm-spec))))))
c8fcd943
SM
180 (define-key-after map (vector key)
181 `(menu-item ,(symbol-name key) ,def :image ,image-exp ,@props))))
ec7f4585 182
c2156508 183;;;###autoload
ec7f4585 184(defun tool-bar-add-item-from-menu (command icon &optional map &rest props)
7c064859 185 "Define tool bar binding for COMMAND in keymap MAP using the given ICON.
ca1b34c8
RS
186This makes a binding for COMMAND in `tool-bar-map', copying its
187binding from the menu bar in MAP (which defaults to `global-map'), but
188modifies the binding by adding an image specification for ICON. It
189finds ICON just like `tool-bar-add-item'. PROPS are additional
190properties to add to the binding.
191
192MAP must contain appropriate binding for `[menu-bar]' which holds a keymap.
193
194Use this function only to make bindings in the global value of `tool-bar-map'.
7c064859 195To define items in any other map, use `tool-bar-local-item-from-menu'."
03a8bf7d
SM
196 (apply 'tool-bar-local-item-from-menu command icon
197 (default-value 'tool-bar-map) map props))
ca1b34c8
RS
198
199;;;###autoload
200(defun tool-bar-local-item-from-menu (command icon in-map &optional from-map &rest props)
7c064859 201 "Define local tool bar binding for COMMAND using the given ICON.
ca1b34c8
RS
202This makes a binding for COMMAND in IN-MAP, copying its binding from
203the menu bar in FROM-MAP (which defaults to `global-map'), but
204modifies the binding by adding an image specification for ICON. It
205finds ICON just like `tool-bar-add-item'. PROPS are additional
206properties to add to the binding.
207
7c064859
NR
208FROM-MAP must contain appropriate binding for `[menu-bar]' which
209holds a keymap."
ca1b34c8
RS
210 (unless from-map
211 (setq from-map global-map))
212 (let* ((menu-bar-map (lookup-key from-map [menu-bar]))
ec7f4585 213 (keys (where-is-internal command menu-bar-map))
3fae165c
GM
214 (fg (face-attribute 'tool-bar :foreground))
215 (bg (face-attribute 'tool-bar :background))
216 (colors (nconc (if (eq fg 'unspecified) nil (list :foreground fg))
217 (if (eq bg 'unspecified) nil (list :background bg))))
cf545823 218 (xpm-spec (list :type 'xpm :file (concat icon ".xpm")))
afb465eb
CY
219 (xpm-lo-spec (list :type 'xpm :file
220 (concat "low-color/" icon ".xpm")))
ffda926c
BW
221 (pbm-spec (append (list :type 'pbm :file
222 (concat icon ".pbm")) colors))
223 (xbm-spec (append (list :type 'xbm :file
224 (concat icon ".xbm")) colors))
b8067901 225 (image-exp `(find-image
afb465eb
CY
226 (cond ((not (display-color-p))
227 ',(list pbm-spec xbm-spec xpm-lo-spec xpm-spec))
228 ((< (display-color-cells) 256)
229 ',(list xpm-lo-spec xpm-spec pbm-spec xbm-spec))
230 (t
231 ',(list xpm-spec pbm-spec xbm-spec)))))
ec7f4585 232 submap key)
c8fcd943
SM
233 ;; We'll pick up the last valid entry in the list of keys if
234 ;; there's more than one.
235 (dolist (k keys)
236 ;; We're looking for a binding of the command in a submap of
237 ;; the menu bar map, so the key sequence must be two or more
238 ;; long.
239 (if (and (vectorp k)
240 (> (length k) 1))
241 (let ((m (lookup-key menu-bar-map (substring k 0 -1)))
242 ;; Last element in the bound key sequence:
243 (kk (aref k (1- (length k)))))
244 (if (and (keymapp m)
245 (symbolp kk))
246 (setq submap m
247 key kk)))))
248 (when (and (symbolp submap) (boundp submap))
249 (setq submap (eval submap)))
250 (let ((defn (assq key (cdr submap))))
251 (if (eq (cadr defn) 'menu-item)
252 (define-key-after in-map (vector key)
253 (append (cdr defn) (list :image image-exp) props))
254 (setq defn (cdr defn))
255 (define-key-after in-map (vector key)
256 (let ((rest (cdr defn)))
257 ;; If the rest of the definition starts
258 ;; with a list of menu cache info, get rid of that.
259 (if (and (consp rest) (consp (car rest)))
260 (setq rest (cdr rest)))
261 (append `(menu-item ,(car defn) ,rest)
262 (list :image image-exp) props)))))))
ec7f4585
DL
263
264;;; Set up some global items. Additions/deletions up for grabs.
265
e4779829
CY
266(defun tool-bar-setup ()
267 ;; People say it's bad to have EXIT on the tool bar, since users
268 ;; might inadvertently click that button.
269 ;;(tool-bar-add-item-from-menu 'save-buffers-kill-emacs "exit")
270 (tool-bar-add-item-from-menu 'find-file "new")
271 (tool-bar-add-item-from-menu 'menu-find-file-existing "open")
272 (tool-bar-add-item-from-menu 'dired "diropen")
273 (tool-bar-add-item-from-menu 'kill-this-buffer "close")
274 (tool-bar-add-item-from-menu 'save-buffer "save" nil
275 :visible '(or buffer-file-name
276 (not (eq 'special
277 (get major-mode
278 'mode-class)))))
279 (tool-bar-add-item-from-menu 'write-file "saveas" nil
280 :visible '(or buffer-file-name
281 (not (eq 'special
282 (get major-mode
283 'mode-class)))))
284 (tool-bar-add-item-from-menu 'undo "undo" nil
285 :visible '(not (eq 'special (get major-mode
286 'mode-class))))
287 (tool-bar-add-item-from-menu (lookup-key menu-bar-edit-menu [cut])
288 "cut" nil
289 :visible '(not (eq 'special (get major-mode
290 'mode-class))))
291 (tool-bar-add-item-from-menu (lookup-key menu-bar-edit-menu [copy])
292 "copy")
293 (tool-bar-add-item-from-menu (lookup-key menu-bar-edit-menu [paste])
294 "paste" nil
295 :visible '(not (eq 'special (get major-mode
296 'mode-class))))
297 (tool-bar-add-item-from-menu 'nonincremental-search-forward "search")
298 ;;(tool-bar-add-item-from-menu 'ispell-buffer "spell")
299
300 ;; There's no icon appropriate for News and we need a command rather
301 ;; than a lambda for Read Mail.
302 ;;(tool-bar-add-item-from-menu 'compose-mail "mail/compose")
303
304 (tool-bar-add-item-from-menu 'print-buffer "print")
305
306 ;; tool-bar-add-item-from-menu itself operates on
307 ;; (default-value 'tool-bar-map), but when we don't use that function,
308 ;; we must explicitly operate on the default value.
309
310 (let ((tool-bar-map (default-value 'tool-bar-map)))
311 (tool-bar-add-item "preferences" 'customize 'customize
312 :help "Edit preferences (customize)")
313
314 (tool-bar-add-item "help" (lambda ()
315 (interactive)
316 (popup-menu menu-bar-help-menu))
317 'help
318 :help "Pop up the Help menu")))
ec7f4585 319
ec7f4585 320
c044516d 321(provide 'tool-bar)
cbee283d 322;; arch-tag: 15f30f0a-d0d7-4d50-bbb7-f48fd0c8582f
ec7f4585 323;;; tool-bar.el ends here