gmane page-mode: binding for browser-object-links
[conkeror.git] / modules / mode-line.js
blob72315f74bef2849bd61f0215ee1bfad9840a1627
1 /**
2  * (C) Copyright 2005 Shawn Betts
3  * (C) Copyright 2007-2008 Jeremy Maitin-Shepard
4  *
5  * Use, modification, and distribution are subject to the terms specified in the
6  * COPYING file.
7 **/
9 require("mode.js");
11 define_window_local_hook("mode_line_hook");
13 function generic_element_widget_container(window, container)
15     this.window = window;
16     this.container = container;
18 define_keywords("$flex", "$align", "$class", "$crop");
19 generic_element_widget_container.prototype = {
20     add_text_widget : function (widget) {
21         keywords(arguments, $flex = widget.flex,
22                  $class = widget.class_name, $crop = widget.crop);
23         var flex = arguments.$flex;
24         var class_name = arguments.$class;
25         var align = arguments.$align;
26         var crop = arguments.$crop;
27         var element = create_XUL(this.window, "label");
28         if (flex)
29             element.setAttribute("flex", flex);
30         if (align)
31             element.setAttribute("align", align);
32         if (class_name)
33             element.setAttribute("class", class_name);
34         if (crop)
35             element.setAttribute("crop", crop);
36         element.conkeror_widget = new generic_widget_element(element, widget);
37         this.container.appendChild(element);
38         return element.conkeror_widget;
39     },
40     destroy : function() {
41         var children = this.container.childNodes;
42         for (var i = 0; i < children.length; ++i)
43             children.item(i).conkeror_widget.destroy();
44     }
47 function mode_line(window)
49     var element = create_XUL(window, "hbox");
50     element.setAttribute("class", "mode-line");
51     /* FIXME: this will need to changed to be buffer-local */
52     var insert_before = window.document.getElementById("minibuffer");
53     insert_before.parentNode.insertBefore(element, insert_before);
54     window.mode_line = this;
55     generic_element_widget_container.call(this, window, element);
56     mode_line_hook.run(window, this);
58 mode_line.prototype = {
59     __proto__: generic_element_widget_container.prototype,
61     uninstall: function () {
62         this.container.parentNode.removeChild(this.window.mode_line.container);
63         this.__proto__.__proto__.destroy.call(this);
64     }
68 function generic_widget_element(element, widget)
70     this.element = element;
71     this.widget = widget;
72     widget.attach(this);
75 generic_widget_element.prototype = {
76     get text () {
77         return this.element.getAttribute("value");
78     },
80     set text (v) {
81         this.element.setAttribute("value", v);
82     },
84     destroy : function () {
85         this.widget.destroy();
86     },
88     remove : function () {
89         this.element.parentNode.removeChild(this.element);
90         this.destroy();
91     }
95 function text_widget(window)
97     this.window_hooks = [];
98     this.window = window;
100 text_widget.prototype = {
101     add_hook : function (hook_name, handler)
102     {
103         var obj = this;
104         if (handler == null) handler = function () { obj.update(); }
105         add_hook.call(this.window, hook_name, handler);
106         this.window_hooks.push([hook_name, handler]);
107     },
109     view : null,
111     attach : function (view) {
112         this.view = view;
113         this.update();
114     },
116     update : function () {
117     },
119     destroy : function ()
120     {
121         for each (let i in this.window_hooks) {
122             remove_hook.call(this.window, i[0], i[1]);
123         }
124     },
126     remove : function ()
127     {
128         this.view.remove();
129     }
132 define_global_window_mode("mode_line", "window_initialize_early_hook");
134 function current_buffer_name_widget(window) {
135     this.class_name = "current-buffer-name-widget";
136     text_widget.call(this, window);
137     this.flex = "1";
138     this.crop = "end";
139     this.add_hook("current_content_buffer_location_change_hook");
140     this.add_hook("select_buffer_hook");
142 current_buffer_name_widget.prototype.__proto__ = text_widget.prototype;
143 current_buffer_name_widget.prototype.update = function () {
144     this.view.text = this.window.buffers.current.description;
147 function current_buffer_scroll_position_widget(window) {
148     this.class_name = "current-buffer-scroll-position-widget";
149     text_widget.call(this, window);
150     this.add_hook("current_buffer_scroll_hook");
151     this.add_hook("select_buffer_hook");
152     this.add_hook("current_content_buffer_location_change_hook");
153     this.add_hook("current_content_buffer_focus_change_hook");
155 current_buffer_scroll_position_widget.prototype.__proto__ = text_widget.prototype;
156 current_buffer_scroll_position_widget.prototype.update = function () {
157     var b = this.window.buffers.current;
158     var scrollX, scrollY, scrollMaxX, scrollMaxY;
159     if (b instanceof content_buffer)
160     {
161         var w = b.focused_frame;
162         scrollX = w.scrollX;
163         scrollY = w.scrollY;
164         scrollMaxX = w.scrollMaxX;
165         scrollMaxY = w.scrollMaxY;
166     } else
167     {
168         scrollX = b.scrollX;
169         scrollY = b.scrollY;
170         scrollMaxX = b.scrollMaxX;
171         scrollMaxY = b.scrollMaxY;
172     }
173     var x = scrollMaxX == 0 ? 100 : Math.round(scrollX / scrollMaxX * 100);
174     var y = scrollMaxY == 0 ? 100 : Math.round(scrollY / scrollMaxY * 100);
175     this.view.text = "(" + x + ", " + y + ")";
178 function clock_widget(window)
180     this.class_name = "clock-widget";
181     text_widget.call(this, window);
182     var obj = this;
183     this.timer_ID = window.setInterval(function () { obj.update(); }, 60000);
185 clock_widget.prototype.__proto__ = text_widget.prototype;
186 clock_widget.prototype.update = function () {
187     var time = new Date();
188     var hours = time.getHours();
189     var mins = time.getMinutes();
190     this.view.text = (hours<10 ? "0" + hours:hours) + ":" + (mins<10 ?"0" +mins:mins);
192 clock_widget.prototype.destroy = function () {
193     this.window.clearTimeout(this.timer_ID);
196 function buffer_count_widget(window) {
197     this.class_name = "buffer-count-widget";
198     text_widget.call(this, window);
199     this.add_hook("select_buffer_hook");
200     this.add_hook("create_buffer_hook");
201     this.add_hook("kill_buffer_hook");
203 buffer_count_widget.prototype.__proto__ = text_widget.prototype;
204 buffer_count_widget.prototype.update = function () {
205     this.view.text = ("[" + (this.window.buffers.selected_index+1) + "/" +
206                       this.window.buffers.count + "]");
209 function loading_count_widget(window) {
210     this.class_name = "loading-count-widget";
211     text_widget.call(this, window);
212     var obj = this;
213     this.add_hook("content_buffer_started_loading_hook");
214     this.add_hook("content_buffer_finished_loading_hook");
215     this.add_hook("kill_buffer_hook");
217 loading_count_widget.prototype.__proto__ = text_widget.prototype;
218 loading_count_widget.prototype.update = function () {
219     var count = 0;
220     for_each_buffer(function(b) {if (b.loading) count++;});
221     if (count)
222         this.view.text = "(" + count + " loading)";
223     else
224         this.view.text = "";
227 function mode_line_adder(widget_constructor) {
228     if (!('mode_line_adder' in widget_constructor))
229         widget_constructor.mode_line_adder = function (window) {
230             window.mode_line.add_text_widget(new widget_constructor(window));
231         };
232     return widget_constructor.mode_line_adder;
235 add_hook("mode_line_hook", mode_line_adder(current_buffer_name_widget));
236 add_hook("mode_line_hook", mode_line_adder(clock_widget));
237 add_hook("mode_line_hook", mode_line_adder(current_buffer_scroll_position_widget));
239 mode_line_mode(true);