Further adapt debian webjumps as suggested by John J. Foerch
[conkeror.git] / modules / mode-line.js
blob0300c3724e3dc6ae698f956febe704f492216280
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 in_module(null);
11 require("mode.js");
13 define_window_local_hook("mode_line_hook");
15 define_keywords("$flex", "$align", "$class", "$crop");
16 function generic_element_widget_container (window, container) {
17     this.window = window;
18     this.container = container;
20 generic_element_widget_container.prototype = {
21     add_text_widget: function (widget) {
22         keywords(arguments, $flex = widget.flex,
23                  $class = widget.class_name, $crop = widget.crop);
24         var flex = arguments.$flex;
25         var class_name = arguments.$class;
26         var align = arguments.$align;
27         var crop = arguments.$crop;
28         var element = create_XUL(this.window, "label");
29         if (flex)
30             element.setAttribute("flex", flex);
31         if (align)
32             element.setAttribute("align", align);
33         if (class_name)
34             element.setAttribute("class", class_name);
35         if (crop)
36             element.setAttribute("crop", crop);
37         return this.add_widget(widget, element);
38     },
39     add_widget: function (widget, element) {
40         element.conkeror_widget = new generic_widget_element(element, widget);
41         this.container.appendChild(element);
42         return element.conkeror_widget;
43     },
44     destroy: function () {
45         var children = this.container.childNodes;
46         for (var i = 0, nchildren = children.length; i < nchildren; ++i)
47             children.item(i).conkeror_widget.destroy();
48     }
51 function mode_line (window) {
52     var element = create_XUL(window, "hbox");
53     element.setAttribute("class", "mode-line");
54     /* FIXME: this will need to changed to be buffer-local */
55     var insert_before = window.document.getElementById("minibuffer");
56     insert_before.parentNode.insertBefore(element, insert_before);
57     window.mode_line = this;
58     generic_element_widget_container.call(this, window, element);
59     mode_line_hook.run(window, this);
61 mode_line.prototype = {
62     __proto__: generic_element_widget_container.prototype,
64     uninstall: function () {
65         this.container.parentNode.removeChild(this.window.mode_line.container);
66         generic_element_widget_container.prototype.destroy.call(this);
67     }
71 function generic_widget_element (element, widget) {
72     this.element = element;
73     this.widget = widget;
74     widget.attach(this);
76 generic_widget_element.prototype = {
77     get text () {
78         return this.element.getAttribute("value");
79     },
81     set text (v) {
82         this.element.setAttribute("value", v);
83     },
85     destroy: function () {
86         this.widget.destroy();
87     },
89     remove: function () {
90         this.element.parentNode.removeChild(this.element);
91         this.destroy();
92     }
96 function text_widget (window) {
97     this.window_hooks = [];
98     this.window = window;
100 text_widget.prototype = {
101     add_hook: function (hook_name, handler) {
102         var obj = this;
103         if (handler == null)
104             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 () {},
118     destroy: function () {
119         for each (let i in this.window_hooks) {
120             remove_hook.call(this.window, i[0], i[1]);
121         }
122     },
124     remove: function () {
125         this.view.remove();
126     }
130 define_global_window_mode("mode_line", "window_initialize_early_hook");
132 function current_buffer_name_widget (window) {
133     this.class_name = "current-buffer-name-widget";
134     text_widget.call(this, window);
135     this.flex = "1";
136     this.crop = "end";
137     this.add_hook("current_content_buffer_location_change_hook");
138     this.add_hook("select_buffer_hook");
140 current_buffer_name_widget.prototype.__proto__ = text_widget.prototype;
141 current_buffer_name_widget.prototype.update = function () {
142     this.view.text = this.window.buffers.current.description;
145 function current_buffer_scroll_position_widget (window) {
146     this.class_name = "current-buffer-scroll-position-widget";
147     text_widget.call(this, window);
148     this.add_hook("current_buffer_scroll_hook");
149     this.add_hook("select_buffer_hook");
150     this.add_hook("current_content_buffer_location_change_hook");
151     this.add_hook("current_content_buffer_focus_change_hook");
153 current_buffer_scroll_position_widget.prototype.__proto__ = text_widget.prototype;
154 current_buffer_scroll_position_widget.prototype.update = function () {
155     var b = this.window.buffers.current;
156     var scrollX, scrollY, scrollMaxX, scrollMaxY;
157     if (b instanceof content_buffer) {
158         var w = b.focused_frame;
159         scrollX = w.scrollX;
160         scrollY = w.scrollY;
161         scrollMaxX = w.scrollMaxX;
162         scrollMaxY = w.scrollMaxY;
163     } else {
164         scrollX = b.scrollX;
165         scrollY = b.scrollY;
166         scrollMaxX = b.scrollMaxX;
167         scrollMaxY = b.scrollMaxY;
168     }
169     var x = scrollMaxX == 0 ? 100 : Math.round(scrollX / scrollMaxX * 100);
170     var y = scrollMaxY == 0 ? 100 : Math.round(scrollY / scrollMaxY * 100);
171     this.view.text = "(" + x + ", " + y + ")";
174 function clock_widget (window) {
175     this.class_name = "clock-widget";
176     text_widget.call(this, window);
177     var obj = this;
178     this.do_update = function () { obj.update(); };
179     // todo: use one timer for multiple clock widgets
180     this.timer_ID = window.setTimeout(this.do_update, 0);
181     this.timer_timeout = true;
183 clock_widget.prototype.__proto__ = text_widget.prototype;
184 clock_widget.prototype.update = function () {
185     var time = new Date();
186     var hours = time.getHours();
187     var mins = time.getMinutes();
188     this.view.text = (hours<10 ? "0" + hours:hours) + ":" + (mins<10 ?"0" +mins:mins);
189     if (time.getSeconds() > 0 || time.getMilliseconds() > 100) {
190         this.window.clearTimeout(this.timer_ID);
191         var time = time.getSeconds() * 1000 + time.getMilliseconds();
192         time = 60000 - time;
193         this.timer_ID = this.window.setTimeout(this.do_update, time);
194         this.timer_timeout = true;
195     } else if (this.timer_timeout) {
196         this.window.clearTimeout(this.timer_ID);
197         this.timer_ID = this.window.setInterval(this.do_update, 60000);
198         this.timer_timeout = false;
199     }
201 clock_widget.prototype.destroy = function () {
202     this.window.clearTimeout(this.timer_ID);
205 function buffer_count_widget (window) {
206     this.class_name = "buffer-count-widget";
207     text_widget.call(this, window);
208     this.add_hook("select_buffer_hook");
209     this.add_hook("create_buffer_hook");
210     this.add_hook("kill_buffer_hook");
212 buffer_count_widget.prototype.__proto__ = text_widget.prototype;
213 buffer_count_widget.prototype.update = function () {
214     this.view.text = ("[" + (this.window.buffers.selected_index+1) + "/" +
215                       this.window.buffers.count + "]");
218 function loading_count_widget (window) {
219     this.class_name = "loading-count-widget";
220     text_widget.call(this, window);
221     var obj = this;
222     this.add_hook("content_buffer_started_loading_hook");
223     this.add_hook("content_buffer_finished_loading_hook");
224     this.add_hook("kill_buffer_hook");
226 loading_count_widget.prototype.__proto__ = text_widget.prototype;
227 loading_count_widget.prototype.update = function () {
228     var count = 0;
229     for_each_buffer(function (b) { if (b.loading) count++; });
230     if (count)
231         this.view.text = "(" + count + " loading)";
232     else
233         this.view.text = "";
236 function mode_line_adder (widget_constructor) {
237     if (!('mode_line_adder' in widget_constructor))
238         widget_constructor.mode_line_adder = function (window) {
239             window.mode_line.add_text_widget(new widget_constructor(window));
240         };
241     return widget_constructor.mode_line_adder;
244 add_hook("mode_line_hook", mode_line_adder(current_buffer_name_widget));
245 add_hook("mode_line_hook", mode_line_adder(clock_widget));
246 add_hook("mode_line_hook", mode_line_adder(current_buffer_scroll_position_widget));
248 mode_line_mode(true);
250 provide("mode-line");