isearch-backspace, isearch-done: docstrings
[conkeror.git] / modules / tab-bar.js
blobafadc6e7fa07c70d809899d6063f154923b4faa2
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 require("favicon.js");
9 require("mode.js");
11 function tab_bar (window) {
12     window.tab_bar = this;
13     var element = create_XUL(window, "arrowscrollbox");
14     element.setAttribute("id", "tab-bar");
15     element.setAttribute("orient", "horizontal");
16     var after = window.buffers.container;
17     this.window = window;
18     this.element = element;
19     after.parentNode.insertBefore(element, after);
21     add_hook.call(window, "select_buffer_hook", tab_bar_select_buffer);
22     add_hook.call(window, "create_buffer_early_hook", tab_bar_add_buffer);
23     add_hook.call(window, "kill_buffer_hook", tab_bar_kill_buffer);
24     add_hook.call(window, "move_buffer_hook", tab_bar_move_buffer);
25     add_hook.call(window, "create_buffer_hook", tab_bar_update_buffer_title);
26     add_hook.call(window, "buffer_title_change_hook", tab_bar_update_buffer_title);
27     add_hook.call(window, "buffer_description_change_hook", tab_bar_update_buffer_title);
28     add_hook.call(window, "buffer_icon_change_hook", tab_bar_update_buffer_icon);
30     window.buffers.for_each(function (b) tab_bar_add_buffer(b, true));
31     this.update_multiple_attribute();
32     this.update_ordinals();
33     if (window.buffers.current != null)
34         tab_bar_select_buffer(window.buffers.current);
36 tab_bar.prototype.destroy = function () {
37     remove_hook.call(this.window, "select_buffer_hook", tab_bar_select_buffer);
38     remove_hook.call(this.window, "create_buffer_early_hook", tab_bar_add_buffer);
39     remove_hook.call(this.window, "kill_buffer_hook", tab_bar_kill_buffer);
40     remove_hook.call(this.window, "move_buffer_hook", tab_bar_move_buffer);
41     remove_hook.call(this.window, "create_buffer_hook", tab_bar_update_buffer_title);
42     remove_hook.call(this.window, "buffer_title_change_hook", tab_bar_update_buffer_title);
43     remove_hook.call(this.window, "buffer_description_change_hook", tab_bar_update_buffer_title);
44     remove_hook.call(this.window, "buffer_icon_change_hook", tab_bar_update_buffer_icon);
45     this.window.buffers.for_each(function (b) { delete b.tab; });
46     this.selected_buffer = null;
47     this.element.parentNode.removeChild(this.element);
48     delete this.window.tab_bar;
52 /**
53  * Updates the "ordinal" attribute of all tabs.
54  */
55 tab_bar.prototype.update_ordinals = function () {
56     var buffers = this.window.buffers;
57     for (var i = 0, n = this.element.childNodes.length; i < n; i++) {
58         var ordinal = buffers.index_of(this.element.childNodes[i].buffer) + 1;
59         this.element.childNodes[i].setAttribute("ordinal", ordinal);
60     }
63 tab_bar.prototype.update_multiple_attribute = function () {
64     if (this.window.buffers.count > 1)
65         this.element.setAttribute("multiple", "true");
66     else
67         this.element.setAttribute("multiple", "false");
70 /**
71  * Adds a tab for the given buffer.  When second argument 'noupdate' is
72  * true, a new tab in the middle of the buffer list will not cause the
73  * ordinals of other tabs to be updated.  This is used during
74  * initialization of the tab bar.
75  */
76 function tab_bar_add_buffer (b, noupdate) {
77     var t = b.window.tab_bar;
78     t.update_multiple_attribute();
79     var ordinal = b.window.buffers.index_of(b) + 1;
80     if (ordinal < b.window.buffers.buffer_list.length && ! noupdate)
81         t.update_ordinals();
82     var tab = create_XUL(b.window, "hbox");
83     tab.buffer = b;
84     tab.setAttribute("class", "tab");
85     tab.addEventListener("click", function () {
86             if (!tab.buffer.dead)
87                 tab.buffer.window.buffers.current = tab.buffer;
88         }, false /* not capturing */);
89     tab.setAttribute("selected", "false");
90     var image = create_XUL(b.window, "image");
91     image.setAttribute("class", "tab-icon");
92     if (b.icon != null)
93         image.setAttribute("src", b.icon);
94     var label = create_XUL(b.window, "label");
95     label.setAttribute("class", "tab-label");
96     label.setAttribute("crop", "end");
97     var button = create_XUL(b.window, "toolbarbutton");
98     button.setAttribute("class", "tab-close-button");
99     button.addEventListener("click", function (event) {
100             kill_buffer(tab.buffer);
101             event.stopPropagation();
102         }, false /* not capturing */);
103     tab.appendChild(image);
104     tab.appendChild(label);
105     tab.appendChild(button);
106     tab.tab_label = label;
107     tab.tab_image = image;
108     t.element.appendChild(tab);
109     b.tab = tab;
110     tab_bar_update_buffer_title(b);
112     // Note, XULRunner 1.9.x puts the tab in the wrong location if we set
113     // the ordinal before adding the tab to the tab-bar.
114     tab.setAttribute("ordinal", ordinal);
117 function tab_bar_kill_buffer (b) {
118     var t = b.window.tab_bar;
119     t.update_multiple_attribute();
120     if (t.selected_buffer == b)
121         t.selected_buffer = null;
122     b.tab.parentNode.removeChild(b.tab);
123     delete b.tab;
124     t.update_ordinals();
129  * Updates all tab indices and ensure that the current tab is still visible.
130  */
131 function tab_bar_move_buffer (b) {
132     var t = b.window.tab_bar;
133     t.update_ordinals();
134     t.element.ensureElementIsVisible(b.window.buffers.current.tab);
138 function tab_bar_select_buffer (b) {
139     var t = b.window.tab_bar;
140     if (t.selected_buffer != null)
141         t.selected_buffer.tab.setAttribute("selected", "false");
142     t.selected_buffer = b;
143     b.tab.setAttribute("selected", "true");
144     t.element.ensureElementIsVisible(b.tab);
147 function tab_bar_update_buffer_title (b) {
148     var title = b.title;
149     if (title == null || title.length == 0)
150         title = b.description;
151     b.tab.tab_label.setAttribute("value", title);
154 function tab_bar_update_buffer_icon (b) {
155     if (b.icon != null)
156         b.tab.tab_image.setAttribute("src", b.icon);
157     else
158         b.tab.tab_image.removeAttribute("src");
161 function tab_bar_install (window) {
162     if (window.tab_bar)
163         throw new Error("tab bar already initialized for window");
164     new tab_bar(window);
167 function tab_bar_uninstall (window) {
168     if (!window.tab_bar)
169         throw new Error("tab bar not initialized for window");
170     window.tab_bar.destroy();
173 define_global_mode("tab_bar_mode",
174                    function () { // enable
175                        add_hook("window_initialize_hook", tab_bar_install);
176                        for_each_window(tab_bar_install);
177                    },
178                    function () { // disable
179                        remove_hook("window_initialize_hook", tab_bar_install);
180                        for_each_window(tab_bar_uninstall);
181                    });
183 tab_bar_mode(true);
185 provide("new-tabs");
186 provide("tab-bar");