2 * (C) Copyright 2008 Jeremy Maitin-Shepard
3 * (C) Copyright 2008 Nicholas A. Zigarovich
4 * (C) Copyright 2008 John J. Foerch
6 * Use, modification, and distribution are subject to the terms specified in the
9 * This is a tab bar which is based on tab-bar.js but makes customization of the
10 * tabs much easier. It provides sensible default styles but lets the user
11 * simply override these defaults by normal CSS.
16 define_variable("tab_bar_button_select", 0,
17 "The mouse button that selects tabs." +
18 "0 = left, 1 = middle, 2 = right, null = disabled.");
20 define_variable("tab_bar_button_close", 2,
21 "The mouse button that closes tabs." +
22 "0 = left, 1 = middle, 2 = right, null = disabled.");
25 * Constructs a tab bar for the given window.
27 function tab_bar (window) {
28 window.tab_bar = this;
29 var scrollbox = create_XUL(window, "arrowscrollbox");
30 scrollbox.setAttribute("id", "tab2-bar");
31 scrollbox.setAttribute("orient", "horizontal");
32 var after = window.buffers.container;
34 this.element = scrollbox;
35 after.parentNode.insertBefore(scrollbox, after);
37 add_hook.call(window, "select_buffer_hook", tab_bar_select_buffer);
38 add_hook.call(window, "create_buffer_early_hook", tab_bar_add_buffer);
39 add_hook.call(window, "kill_buffer_hook", tab_bar_kill_buffer);
40 add_hook.call(window, "create_buffer_hook", tab_bar_update_buffer_title);
41 add_hook.call(window, "buffer_title_change_hook", tab_bar_update_buffer_title);
42 add_hook.call(window, "buffer_description_change_hook", tab_bar_update_buffer_title);
43 // add_hook.call(window, "buffer_favicon_change_hook", tab_bar_update_buffer_icon);
44 window.buffers.for_each(tab_bar_add_buffer);
45 this.update_multiple_attribute();
46 if (window.buffers.current != null)
47 tab_bar_select_buffer(window.buffers.current);
52 * Destroys the tab bar.
54 tab_bar.prototype.destroy = function () {
55 remove_hook.call(this.window, "select_buffer_hook", tab_bar_select_buffer);
56 remove_hook.call(this.window, "create_buffer_early_hook", tab_bar_add_buffer);
57 remove_hook.call(this.window, "kill_buffer_hook", tab_bar_kill_buffer);
58 remove_hook.call(this.window, "create_buffer_hook", tab_bar_update_buffer_title);
59 remove_hook.call(this.window, "buffer_title_change_hook", tab_bar_update_buffer_title);
60 remove_hook.call(this.window, "buffer_description_change_hook", tab_bar_update_buffer_title);
61 // remove_hook.call(this.window, "buffer_favicon_change_hook", tab_bar_update_buffer_icon);
62 this.window.buffers.for_each(function (b) {
65 this.selected_buffer = null;
66 this.element.parentNode.removeChild(this.element);
71 * Updates the "multiple" attribute of the tab bar.
73 tab_bar.prototype.update_multiple_attribute = function () {
74 if (this.window.buffers.count > 1)
75 this.element.setAttribute("multiple", "true");
77 this.element.setAttribute("multiple", "false");
82 * Adds a tab for the given buffer.
84 function tab_bar_add_buffer (buffer) {
87 var tabbar = buffer.window.tab_bar;
88 tabbar.update_multiple_attribute();
90 // Create a tab and add it to the tab bar
91 var tab = create_XUL(buffer.window, "hbox");
92 tab.setAttribute("class", "tab2");
93 tab.addEventListener("click", function (event) {
94 if (event.button == tab_bar_button_select) {
96 buffer.window.buffers.current = buffer;
98 }, false /* not capturing */);
99 tab.setAttribute("selected", "false");
101 // Create the label to hold the tab number
102 // TODO: Make the numbers optional and use the favicon if that's what the
104 var iconlabel = create_XUL(buffer.window, "label");
105 iconlabel.setAttribute("class", "tab2-icon");
107 // Create the label to hold the tab title
108 var label = create_XUL(buffer.window, "label");
109 label.setAttribute("class", "tab2-label");
110 label.setAttribute("crop", "end");
112 // No close button, just use the designated mouse button.
113 tab.addEventListener("click", function (event) {
114 if (event.button == tab_bar_button_close) {
116 event.stopPropagation();
118 }, false /* not capturing */);
120 // Add all the stuff to the new tab
121 tab.appendChild(iconlabel);
122 tab.appendChild(label);
123 tab.tab_label = label;
124 tab.tab_icon = iconlabel;
125 tabbar.element.appendChild(tab);
127 tab_bar_update_buffer_title(buffer);
129 // Set the tab number. Remember that at this point, the tab has already been
130 // added to the hbox.
131 var total = tabbar.element.getElementsByClassName("tab2").length;
132 iconlabel.value = total;
137 * Removes the tab for the given buffer.
139 function tab_bar_kill_buffer (b) {
140 var t = b.window.tab_bar;
141 t.update_multiple_attribute();
142 if (t.selected_buffer == b)
143 t.selected_buffer = null;
144 b.tab.parentNode.removeChild(b.tab);
145 t = b.window.tab_bar;
148 // Renumber the tabs.
149 for (var i = 0; i < t.element.childNodes.length; i++) {
150 t.element.childNodes[i].childNodes[0].value = i + 1;
156 * Updates the tab of the given buffer to indicate it is the currently open one.
158 function tab_bar_select_buffer (b) {
159 var t = b.window.tab_bar;
160 if (t.selected_buffer != null)
161 t.selected_buffer.tab.setAttribute("selected", "false");
162 t.selected_buffer = b;
163 b.tab.setAttribute("selected", "true");
164 t.element.ensureElementIsVisible(b.tab);
169 * Updates the tab title for the given buffer.
171 function tab_bar_update_buffer_title (b) {
173 if (title == null || title.length == 0)
174 title = b.description;
175 b.tab.tab_label.setAttribute("value", title);
180 * Inserts the tab bar in the given window.
182 function tab_bar_install (window) {
184 throw new Error("tab bar already initialized for window");
190 * Removes the tab bar from the given window.
191 * If the tab bar is not installed, throws an error.
193 function tab_bar_uninstall (window) {
195 throw new Error("tab bar not initialized for window");
196 window.tab_bar.destroy();
197 delete window.tab_bar;
201 define_global_mode("tab_bar_mode",
202 function () { // enable
203 add_hook("window_initialize_hook", tab_bar_install);
204 for_each_window(tab_bar_install);
206 function () { // disable
207 remove_hook("window_initialize_hook", tab_bar_install);
208 for_each_window(tab_bar_uninstall);