theme module
[conkeror.git] / modules / new-tabs.js
blobc55a29b6707763d30d441490607fa3d882bf89ae
1 /**
2  * (C) Copyright 2008 Jeremy Maitin-Shepard
3  * (C) Copyright 2008 Nicholas A. Zigarovich
4  * (C) Copyright 2008 John J. Foerch
5  *
6  * Use, modification, and distribution are subject to the terms specified in the
7  * COPYING file.
8  *
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.
12  **/
14 require("mode.js");
16 define_variable("tab_bar_button_select", 0,
17                 "The mouse button that selects tabs. " +
18                 "0 = left, 1 = middle, 2 = right, null = disabled. " +
19                 "Default is 0.");
21 define_variable("tab_bar_button_close", 2,
22                 "The mouse button that closes tabs.. " +
23                 "0 = left, 1 = middle, 2 = right, null = disabled. " +
24                 "Default is 2.");
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;
33     this.window = window;
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_hook", tab_bar_add_buffer);
39     add_hook.call(window, "kill_buffer_hook", tab_bar_kill_buffer);
40     add_hook.call(window, "buffer_title_change_hook", tab_bar_update_buffer_title);
41     add_hook.call(window, "buffer_description_change_hook", tab_bar_update_buffer_title);
42     //    add_hook.call(window, "buffer_favicon_change_hook", tab_bar_update_buffer_icon);
43     window.buffers.for_each(tab_bar_add_buffer);
44     this.update_multiple_attribute();
45     if (window.buffers.current != null)
46         tab_bar_select_buffer(window.buffers.current);
49 tab_bar.prototype.destroy = function () {
50     remove_hook.call(this.window, "select_buffer_hook", tab_bar_select_buffer);
51     remove_hook.call(this.window, "create_buffer_hook", tab_bar_add_buffer);
52     remove_hook.call(this.window, "kill_buffer_hook", tab_bar_kill_buffer);
53     remove_hook.call(this.window, "buffer_title_change_hook", tab_bar_update_buffer_title);
54     remove_hook.call(this.window, "buffer_description_change_hook", tab_bar_update_buffer_title);
55     //    remove_hook.call(this.window, "buffer_favicon_change_hook", tab_bar_update_buffer_icon);
56     this.window.buffers.for_each(function (b) {
57             delete b.tab;
58         });
59     this.selected_buffer = null;
60     this.element.parentNode.removeChild(this.element);
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 function tab_bar_add_buffer(buffer) {
72     // Get the tab bar
73     var tabbar = buffer.window.tab_bar;
74     tabbar.update_multiple_attribute();
76     // Create a tab and add it to the tab bar
77     var tab = create_XUL(buffer.window, "hbox");
78     tab.setAttribute("class", "tab2");
79     tab.addEventListener("click", function (event) {
80             if (event.button == tab_bar_button_select) {
81                 if (!buffer.dead)
82                     buffer.window.buffers.current = buffer;
83             }
84         }, false /* not capturing */);
85     tab.setAttribute("selected", "false");
87     // Create the label to hold the tab number
88     // TODO: Make the numbers optional and use the favicon if that's what the
89     // user wants.
90     var iconlabel = create_XUL(buffer.window, "label");
91     iconlabel.setAttribute("class", "tab2-icon");
93     // Create the label to hold the tab title
94     var label = create_XUL(buffer.window, "label");
95     label.setAttribute("class", "tab2-label");
96     label.setAttribute("crop", "end");
98     // No close button, just use the designated mouse button.
99     tab.addEventListener("click", function (event) {
100             if (event.button == tab_bar_button_close) {
101                 kill_buffer(buffer);
102                 event.stopPropagation();
103             }
104         }, false /* not capturing */);
106     // Add all the stuff to the new tab
107     tab.appendChild(iconlabel);
108     tab.appendChild(label);
109     tab.tab_label = label;
110     tab.tab_icon = iconlabel;
111     tabbar.element.appendChild(tab);
112     buffer.tab = tab;
113     tab_bar_update_buffer_title(buffer);
115     // Set the tab number. Remember that at this point, the tab has already been
116     // added to the hbox.
117     var total = tabbar.element.getElementsByClassName("tab2").length;
118     iconlabel.value = total;
121 function tab_bar_kill_buffer(b) {
122     var t = b.window.tab_bar;
123     t.update_multiple_attribute();
124     if (t.selected_buffer == b)
125         t.selected_buffer = null;
126     b.tab.parentNode.removeChild(b.tab);
127     t = b.window.tab_bar;
128     delete b.tab;
130     // Renumber the tabs.
131     for (var i = 0; i < t.element.childNodes.length; i++) {
132         t.element.childNodes[i].childNodes[0].value = i + 1;
133     }
136 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_install(window) {
154     if (window.tab_bar)
155         throw new Error("tab bar already initialized for window");
156     new tab_bar(window);
159 function tab_bar_uninstall(window) {
160     if (!window.tab_bar)
161         throw new Error("tab bar not initialized for window");
162     window.tab_bar.destroy();
163     delete window.tab_bar;
166 define_global_mode("tab_bar_mode",
167                    function () { // enable
168                        add_hook("window_initialize_hook", tab_bar_install);
169                        for_each_window(tab_bar_install);
170                    },
171                    function () { // disable
172                        remove_hook("window_initialize_hook", tab_bar_install);
173                        for_each_window(tab_bar_uninstall);
174                    });
176 tab_bar_mode(true);