buffer ordering
[conkeror.git] / modules / tab-bar.js
blobb0c50612e0e26dd0284a8dd1e599cd2ce8ef6631
1 /**
2  * (C) Copyright 2008 Jeremy Maitin-Shepard
3  *
4  * Use, modification, and distribution are subject to the terms specified in the
5  * COPYING file.
6 **/
8 in_module(null);
10 require("favicon.js");
11 require("mode.js");
13 function tab_bar (window) {
14     window.tab_bar = this;
15     var element = create_XUL(window, "arrowscrollbox");
16     element.setAttribute("id", "tab-bar");
17     element.setAttribute("orient", "horizontal");
18     var after = window.buffers.container;
19     this.window = window;
20     this.element = element;
21     after.parentNode.insertBefore(element, after);
23     add_hook.call(window, "select_buffer_hook", tab_bar_select_buffer);
24     add_hook.call(window, "create_buffer_early_hook", tab_bar_add_buffer);
25     add_hook.call(window, "kill_buffer_hook", tab_bar_kill_buffer);
26     add_hook.call(window, "move_buffer_hook", tab_bar_move_buffer);
27     add_hook.call(window, "create_buffer_hook", tab_bar_update_buffer_title);
28     add_hook.call(window, "buffer_title_change_hook", tab_bar_update_buffer_title);
29     add_hook.call(window, "buffer_description_change_hook", tab_bar_update_buffer_title);
30     add_hook.call(window, "buffer_icon_change_hook", tab_bar_update_buffer_icon);
32     window.buffers.for_each(function (b) tab_bar_add_buffer(b, true));
33     this.update_multiple_attribute();
34     this.update_ordinals();
35     if (window.buffers.current != null)
36         tab_bar_select_buffer(window.buffers.current);
38 tab_bar.prototype.destroy = function () {
39     remove_hook.call(this.window, "select_buffer_hook", tab_bar_select_buffer);
40     remove_hook.call(this.window, "create_buffer_early_hook", tab_bar_add_buffer);
41     remove_hook.call(this.window, "kill_buffer_hook", tab_bar_kill_buffer);
42     remove_hook.call(this.window, "move_buffer_hook", tab_bar_move_buffer);
43     remove_hook.call(this.window, "create_buffer_hook", tab_bar_update_buffer_title);
44     remove_hook.call(this.window, "buffer_title_change_hook", tab_bar_update_buffer_title);
45     remove_hook.call(this.window, "buffer_description_change_hook", tab_bar_update_buffer_title);
46     remove_hook.call(this.window, "buffer_icon_change_hook", tab_bar_update_buffer_icon);
47     this.window.buffers.for_each(function (b) { delete b.tab; });
48     this.selected_buffer = null;
49     this.element.parentNode.removeChild(this.element);
50     delete this.window.tab_bar;
54 /**
55  * Updates the "ordinal" attribute of all tabs.
56  */
57 tab_bar.prototype.update_ordinals = function () {
58     var buffers = this.window.buffers;
59     for (var i = 0, n = this.element.childNodes.length; i < n; i++) {
60         var ordinal = buffers.index_of(this.element.childNodes[i].buffer) + 1;
61         this.element.childNodes[i].setAttribute("ordinal", ordinal);
62     }
65 tab_bar.prototype.update_multiple_attribute = function () {
66     if (this.window.buffers.count > 1)
67         this.element.setAttribute("multiple", "true");
68     else
69         this.element.setAttribute("multiple", "false");
72 /**
73  * Adds a tab for the given buffer.  When second argument 'noupdate' is
74  * true, a new tab in the middle of the buffer list will not cause the
75  * ordinals of other tabs to be updated.  This is used during
76  * initialization of the tab bar.
77  */
78 function tab_bar_add_buffer (b, noupdate) {
79     var t = b.window.tab_bar;
80     t.update_multiple_attribute();
81     var ordinal = b.window.buffers.index_of(b) + 1;
82     if (ordinal < b.window.buffers.buffer_list.length && ! noupdate)
83         t.update_ordinals();
84     var tab = create_XUL(b.window, "hbox");
85     tab.buffer = b;
86     tab.setAttribute("class", "tab");
87     tab.addEventListener("click", function () {
88             if (!tab.buffer.dead)
89                 tab.buffer.window.buffers.current = tab.buffer;
90         }, false /* not capturing */);
91     tab.setAttribute("selected", "false");
92     tab.setAttribute("ordinal", ordinal);
93     var image = create_XUL(b.window, "image");
94     image.setAttribute("class", "tab-icon");
95     if (b.icon != null)
96         image.setAttribute("src", b.icon);
97     var label = create_XUL(b.window, "label");
98     label.setAttribute("class", "tab-label");
99     label.setAttribute("crop", "end");
100     var button = create_XUL(b.window, "toolbarbutton");
101     button.setAttribute("class", "tab-close-button");
102     button.addEventListener("click", function (event) {
103             kill_buffer(tab.buffer);
104             event.stopPropagation();
105         }, false /* not capturing */);
106     tab.appendChild(image);
107     tab.appendChild(label);
108     tab.appendChild(button);
109     tab.tab_label = label;
110     tab.tab_image = image;
111     t.element.appendChild(tab);
112     b.tab = tab;
113     tab_bar_update_buffer_title(b);
116 function tab_bar_kill_buffer (b) {
117     var t = b.window.tab_bar;
118     t.update_multiple_attribute();
119     if (t.selected_buffer == b)
120         t.selected_buffer = null;
121     b.tab.parentNode.removeChild(b.tab);
122     delete b.tab;
123     t.update_ordinals();
128  * Updates all tab indices and ensure that the current tab is still visible.
129  */
130 function tab_bar_move_buffer (b) {
131     var t = b.window.tab_bar;
132     t.update_ordinals();
133     t.element.ensureElementIsVisible(b.window.buffers.current.tab);
137 function tab_bar_select_buffer (b) {
138     var t = b.window.tab_bar;
139     if (t.selected_buffer != null)
140         t.selected_buffer.tab.setAttribute("selected", "false");
141     t.selected_buffer = b;
142     b.tab.setAttribute("selected", "true");
143     t.element.ensureElementIsVisible(b.tab);
146 function tab_bar_update_buffer_title (b) {
147     var title = b.title;
148     if (title == null || title.length == 0)
149         title = b.description;
150     b.tab.tab_label.setAttribute("value", title);
153 function tab_bar_update_buffer_icon (b) {
154     if (b.icon != null)
155         b.tab.tab_image.setAttribute("src", b.icon);
156     else
157         b.tab.tab_image.removeAttribute("src");
160 function tab_bar_install (window) {
161     if (window.tab_bar)
162         throw new Error("tab bar already initialized for window");
163     new tab_bar(window);
166 function tab_bar_uninstall (window) {
167     if (!window.tab_bar)
168         throw new Error("tab bar not initialized for window");
169     window.tab_bar.destroy();
172 define_global_mode("tab_bar_mode",
173                    function () { // enable
174                        add_hook("window_initialize_hook", tab_bar_install);
175                        for_each_window(tab_bar_install);
176                    },
177                    function () { // disable
178                        remove_hook("window_initialize_hook", tab_bar_install);
179                        for_each_window(tab_bar_uninstall);
180                    });
182 tab_bar_mode(true);
184 provide("new-tabs");
185 provide("tab-bar");