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.");
24 function tab_bar(window) {
25 window.tab_bar = this;
26 var scrollbox = create_XUL(window, "arrowscrollbox");
27 scrollbox.setAttribute("id", "tab2-bar");
28 scrollbox.setAttribute("orient", "horizontal");
29 var after = window.buffers.container;
31 this.element = scrollbox;
32 after.parentNode.insertBefore(scrollbox, after);
34 add_hook.call(window, "select_buffer_hook", tab_bar_select_buffer);
35 add_hook.call(window, "create_buffer_hook", tab_bar_add_buffer);
36 add_hook.call(window, "kill_buffer_hook", tab_bar_kill_buffer);
37 add_hook.call(window, "buffer_title_change_hook", tab_bar_update_buffer_title);
38 add_hook.call(window, "buffer_description_change_hook", tab_bar_update_buffer_title);
39 // add_hook.call(window, "buffer_favicon_change_hook", tab_bar_update_buffer_icon);
40 window.buffers.for_each(tab_bar_add_buffer);
41 this.update_multiple_attribute();
42 if (window.buffers.current != null)
43 tab_bar_select_buffer(window.buffers.current);
46 tab_bar.prototype.destroy = function () {
47 remove_hook.call(this.window, "select_buffer_hook", tab_bar_select_buffer);
48 remove_hook.call(this.window, "create_buffer_hook", tab_bar_add_buffer);
49 remove_hook.call(this.window, "kill_buffer_hook", tab_bar_kill_buffer);
50 remove_hook.call(this.window, "buffer_title_change_hook", tab_bar_update_buffer_title);
51 remove_hook.call(this.window, "buffer_description_change_hook", tab_bar_update_buffer_title);
52 // remove_hook.call(this.window, "buffer_favicon_change_hook", tab_bar_update_buffer_icon);
53 this.window.buffers.for_each(function (b) {
56 this.selected_buffer = null;
57 this.element.parentNode.removeChild(this.element);
60 tab_bar.prototype.update_multiple_attribute = function () {
61 if (this.window.buffers.count > 1)
62 this.element.setAttribute("multiple", "true");
64 this.element.setAttribute("multiple", "false");
67 function tab_bar_add_buffer(buffer) {
70 var tabbar = buffer.window.tab_bar;
71 tabbar.update_multiple_attribute();
73 // Create a tab and add it to the tab bar
74 var tab = create_XUL(buffer.window, "hbox");
75 tab.setAttribute("class", "tab2");
76 tab.addEventListener("click", function (event) {
77 if (event.button == tab_bar_button_select) {
79 buffer.window.buffers.current = buffer;
81 }, false /* not capturing */);
82 tab.setAttribute("selected", "false");
84 // Create the label to hold the tab number
85 // TODO: Make the numbers optional and use the favicon if that's what the
87 var iconlabel = create_XUL(buffer.window, "label");
88 iconlabel.setAttribute("class", "tab2-icon");
90 // Create the label to hold the tab title
91 var label = create_XUL(buffer.window, "label");
92 label.setAttribute("class", "tab2-label");
93 label.setAttribute("crop", "end");
95 // No close button, just use the designated mouse button.
96 tab.addEventListener("click", function (event) {
97 if (event.button == tab_bar_button_close) {
99 event.stopPropagation();
101 }, false /* not capturing */);
103 // Add all the stuff to the new tab
104 tab.appendChild(iconlabel);
105 tab.appendChild(label);
106 tab.tab_label = label;
107 tab.tab_icon = iconlabel;
108 tabbar.element.appendChild(tab);
110 tab_bar_update_buffer_title(buffer);
112 // Set the tab number. Remember that at this point, the tab has already been
113 // added to the hbox.
114 var total = tabbar.element.getElementsByClassName("tab2").length;
115 iconlabel.value = total;
118 function tab_bar_kill_buffer(b) {
119 var t = b.window.tab_bar;
120 t.update_multiple_attribute();
121 if (t.selected_buffer == b)
122 t.selected_buffer = null;
123 b.tab.parentNode.removeChild(b.tab);
124 t = b.window.tab_bar;
127 // Renumber the tabs.
128 for (var i = 0; i < t.element.childNodes.length; i++) {
129 t.element.childNodes[i].childNodes[0].value = i + 1;
133 function tab_bar_select_buffer(b) {
135 var t = b.window.tab_bar;
136 if (t.selected_buffer != null)
137 t.selected_buffer.tab.setAttribute("selected", "false");
138 t.selected_buffer = b;
139 b.tab.setAttribute("selected", "true");
140 t.element.ensureElementIsVisible(b.tab);
143 function tab_bar_update_buffer_title(b) {
145 if (title == null || title.length == 0)
146 title = b.description;
147 b.tab.tab_label.setAttribute("value", title);
150 function tab_bar_install(window) {
152 throw new Error("tab bar already initialized for window");
156 function tab_bar_uninstall(window) {
158 throw new Error("tab bar not initialized for window");
159 window.tab_bar.destroy();
160 delete window.tab_bar;
163 define_global_mode("tab_bar_mode",
164 function () { // enable
165 add_hook("window_initialize_hook", tab_bar_install);
166 for_each_window(tab_bar_install);
168 function () { // disable
169 remove_hook("window_initialize_hook", tab_bar_install);
170 for_each_window(tab_bar_uninstall);