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
7 * Use, modification, and distribution are subject to the terms specified in the
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.
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.");
34 * Constructs a tab bar for the given window.
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;
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);
54 window.buffers.for_each(tab_bar_add_buffer);
55 this.update_multiple_attribute();
56 if (window.buffers.current != null)
57 tab_bar_select_buffer(window.buffers.current);
62 * Destroys the tab bar.
64 tab_bar.prototype.destroy = function () {
65 remove_hook.call(this.window, "select_buffer_hook", tab_bar_select_buffer);
66 remove_hook.call(this.window, "create_buffer_early_hook", tab_bar_add_buffer);
67 remove_hook.call(this.window, "kill_buffer_hook", tab_bar_kill_buffer);
68 remove_hook.call(this.window, "create_buffer_hook", tab_bar_update_buffer_title);
69 remove_hook.call(this.window, "buffer_title_change_hook", tab_bar_update_buffer_title);
70 remove_hook.call(this.window, "buffer_description_change_hook", tab_bar_update_buffer_title);
71 remove_hook.call(this.window, "buffer_icon_change_hook", tab_bar_update_buffer_icon);
72 this.window.buffers.for_each(function (b) { delete b.tab; });
73 this.selected_buffer = null;
74 this.element.parentNode.removeChild(this.element);
75 delete this.window.tab_bar;
80 * Updates the "multiple" attribute of the tab bar.
82 tab_bar.prototype.update_multiple_attribute = function () {
83 if (this.window.buffers.count > 1)
84 this.element.setAttribute("multiple", "true");
86 this.element.setAttribute("multiple", "false");
91 * Adds a tab for the given buffer.
93 function tab_bar_add_buffer (buffer) {
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) {
105 buffer.window.buffers.current = buffer;
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) {
129 event.stopPropagation();
131 }, false /* not capturing */);
133 // Add all the stuff to the new tab
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);
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;
154 * Removes the tab for the given buffer.
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;
165 // Renumber the tabs.
166 for (var i = 0; i < t.element.childNodes.length; i++) {
167 t.element.childNodes[i].index.value = i + 1;
173 * Updates the tab of the given buffer to indicate it is the currently open one.
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.
188 function tab_bar_update_buffer_title (b) {
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.
199 function tab_bar_update_buffer_icon (b) {
201 b.tab.image.setAttribute("src", b.icon);
203 b.tab.image.removeAttribute("src");
208 * Inserts the tab bar in the given window.
210 function tab_bar_install (window) {
212 throw new Error("tab bar already initialized for window");
218 * Removes the tab bar from the given window.
219 * If the tab bar is not installed, throws an error.
221 function tab_bar_uninstall (window) {
223 throw new Error("tab bar not initialized for window");
224 window.tab_bar.destroy();
228 define_global_mode("tab_bar_mode",
229 function () { // enable
230 add_hook("window_initialize_hook", tab_bar_install);
231 for_each_window(tab_bar_install);
233 function () { // disable
234 remove_hook("window_initialize_hook", tab_bar_install);
235 for_each_window(tab_bar_uninstall);