new-tabs: put buffer icon after buffer index
[conkeror.git] / modules / new-tabs.js
blob5af970559a6ad002358b3716959acc7aab4824ea
1 /**
2  * (C) Copyright 2008 Jeremy Maitin-Shepard
3  * (C) Copyright 2008 Nicholas A. Zigarovich
4  * (C) Copyright 2008 John J. Foerch
5  * (C) Copyright 2011 Peter Lunicks
6  *
7  * Use, modification, and distribution are subject to the terms specified in the
8  * COPYING file.
9  *
10  * This is a tab bar which is based on tab-bar.js but makes customization of the
11  * tabs much easier. It provides sensible default styles but lets the user
12  * simply override these defaults by normal CSS.
13  **/
15 in_module(null);
17 require("mode.js");
19 define_variable("tab_bar_button_select", 0,
20                 "The mouse button that selects tabs." +
21                 "0 = left, 1 = middle, 2 = right, null = disabled.");
23 define_variable("tab_bar_button_close", 2,
24                 "The mouse button that closes tabs." +
25                 "0 = left, 1 = middle, 2 = right, null = disabled.");
27 define_variable("tab_bar_show_icon", false,
28                 "Whether or not to show buffer icons in tabs.");
30 define_variable("tab_bar_show_index", true,
31                 "Whether or not to show the tab index in each tab.");
33 /**
34  * Constructs a tab bar for the given window.
35  */
36 function tab_bar (window) {
37     window.tab_bar = this;
38     var scrollbox = create_XUL(window, "arrowscrollbox");
39     scrollbox.setAttribute("id", "tab2-bar");
40     scrollbox.setAttribute("orient", "horizontal");
41     var after = window.buffers.container;
42     this.window = window;
43     this.element = scrollbox;
44     after.parentNode.insertBefore(scrollbox, after);
46     add_hook.call(window, "select_buffer_hook", tab_bar_select_buffer);
47     add_hook.call(window, "create_buffer_early_hook", tab_bar_add_buffer);
48     add_hook.call(window, "kill_buffer_hook", tab_bar_kill_buffer);
49     add_hook.call(window, "create_buffer_hook", tab_bar_update_buffer_title);
50     add_hook.call(window, "buffer_title_change_hook", tab_bar_update_buffer_title);
51     add_hook.call(window, "buffer_description_change_hook", tab_bar_update_buffer_title);
52     add_hook.call(window, "buffer_icon_change_hook", tab_bar_update_buffer_icon);
53     window.buffers.for_each(tab_bar_add_buffer);
54     this.update_multiple_attribute();
55     if (window.buffers.current != null)
56         tab_bar_select_buffer(window.buffers.current);
60 /**
61  * Destroys the tab bar.
62  */
63 tab_bar.prototype.destroy = function () {
64     remove_hook.call(this.window, "select_buffer_hook", tab_bar_select_buffer);
65     remove_hook.call(this.window, "create_buffer_early_hook", tab_bar_add_buffer);
66     remove_hook.call(this.window, "kill_buffer_hook", tab_bar_kill_buffer);
67     remove_hook.call(this.window, "create_buffer_hook", tab_bar_update_buffer_title);
68     remove_hook.call(this.window, "buffer_title_change_hook", tab_bar_update_buffer_title);
69     remove_hook.call(this.window, "buffer_description_change_hook", tab_bar_update_buffer_title);
70     remove_hook.call(this.window, "buffer_icon_change_hook", tab_bar_update_buffer_icon);
71     this.window.buffers.for_each(function (b) {
72             delete b.tab;
73         });
74     this.selected_buffer = null;
75     this.element.parentNode.removeChild(this.element);
79 /**
80  * Updates the "multiple" attribute of the tab bar.
81  */
82 tab_bar.prototype.update_multiple_attribute = function () {
83     if (this.window.buffers.count > 1)
84         this.element.setAttribute("multiple", "true");
85     else
86         this.element.setAttribute("multiple", "false");
90 /**
91  * Adds a tab for the given buffer.
92  */
93 function tab_bar_add_buffer (buffer) {
95     // Get the tab bar
96     var tabbar = buffer.window.tab_bar;
97     tabbar.update_multiple_attribute();
99     // Create a tab and add it to the tab bar
100     var tab = create_XUL(buffer.window, "hbox");
101     tab.setAttribute("class", "tab2");
102     tab.addEventListener("click", function (event) {
103             if (event.button == tab_bar_button_select) {
104                 if (!buffer.dead)
105                     buffer.window.buffers.current = buffer;
106             }
107         }, false /* not capturing */);
108     tab.setAttribute("selected", "false");
110     // Create the label to hold the buffer icon
111     var image = create_XUL(buffer.window, "image");
112     image.setAttribute("class", "tab2-icon");
113     if (buffer.icon != null)
114         image.setAttribute("src", buffer.icon);
116     // Create the label to hold the tab number
117     var index = create_XUL(buffer.window, "label");
118     index.setAttribute("class", "tab2-index");
120     // Create the label to hold the tab title
121     var label = create_XUL(buffer.window, "label");
122     label.setAttribute("class", "tab2-label");
123     label.setAttribute("crop", "end");
125     // No close button, just use the designated mouse button.
126     tab.addEventListener("click", function (event) {
127             if (event.button == tab_bar_button_close) {
128                 kill_buffer(buffer);
129                 event.stopPropagation();
130             }
131         }, false /* not capturing */);
133     // Add all the stuff to the new tab
134     tab.image = image;
135     tab.label = label;
136     tab.index = index;
137     if (tab_bar_show_index)
138         tab.appendChild(index);
139     if (tab_bar_show_icon)
140         tab.appendChild(image);
141     tab.appendChild(label);
142     tabbar.element.appendChild(tab);
143     buffer.tab = tab;
144     tab_bar_update_buffer_title(buffer);
146     // Set the tab number. Remember that at this point, the tab has already been
147     // added to the hbox.
148     var total = tabbar.element.getElementsByClassName("tab2").length;
149     index.value = total;
154  * Removes the tab for the given buffer.
155  */
156 function tab_bar_kill_buffer (b) {
157     var t = b.window.tab_bar;
158     t.update_multiple_attribute();
159     if (t.selected_buffer == b)
160         t.selected_buffer = null;
161     b.tab.parentNode.removeChild(b.tab);
162     t = b.window.tab_bar;
163     delete b.tab;
165     // Renumber the tabs.
166     for (var i = 0; i < t.element.childNodes.length; i++) {
167         t.element.childNodes[i].childNodes[0].value = i + 1;
168     }
173  * Updates the tab of the given buffer to indicate it is the currently open one.
174  */
175 function tab_bar_select_buffer (b) {
176     var t = b.window.tab_bar;
177     if (t.selected_buffer != null)
178         t.selected_buffer.tab.setAttribute("selected", "false");
179     t.selected_buffer = b;
180     b.tab.setAttribute("selected", "true");
181     t.element.ensureElementIsVisible(b.tab);
186  * Updates the tab title for the given buffer.
187  */
188 function tab_bar_update_buffer_title (b) {
189     var title = b.title;
190     if (title == null || title.length == 0)
191         title = b.description;
192     b.tab.label.setAttribute("value", title);
197  * Updates the tab icon for the given buffer.
198  */
199 function tab_bar_update_buffer_icon (b) {
200     if (b.icon != null)
201         b.tab.image.setAttribute("src", b.icon);
202     else
203         b.tab.image.removeAttribute("src");
208  * Inserts the tab bar in the given window.
209  */
210 function tab_bar_install (window) {
211     if (window.tab_bar)
212         throw new Error("tab bar already initialized for window");
213     new tab_bar(window);
218  * Removes the tab bar from the given window.
219  * If the tab bar is not installed, throws an error.
220  */
221 function tab_bar_uninstall (window) {
222     if (!window.tab_bar)
223         throw new Error("tab bar not initialized for window");
224     window.tab_bar.destroy();
225     delete window.tab_bar;
229 define_global_mode("tab_bar_mode",
230                    function () { // enable
231                        add_hook("window_initialize_hook", tab_bar_install);
232                        for_each_window(tab_bar_install);
233                    },
234                    function () { // disable
235                        remove_hook("window_initialize_hook", tab_bar_install);
236                        for_each_window(tab_bar_uninstall);
237                    });
239 tab_bar_mode(true);
241 provide("tab-bar");
242 provide("new-tabs");