Prepare new Debian package
[conkeror.git] / modules / mode-line.js
blob53e607a0b80178dd4631b4ce2c2afe8083183979
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         return this.add_widget(widget, element);
37     },
38     add_widget : function (widget, element) {
39         element.conkeror_widget = new generic_widget_element(element, widget);
40         this.container.appendChild(element);
41         return element.conkeror_widget;
42     },
43     destroy : function() {
44         var children = this.container.childNodes;
45         for (var i = 0, nchildren = children.length; i < nchildren; ++i)
46             children.item(i).conkeror_widget.destroy();
47     }
50 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)
73     this.element = element;
74     this.widget = widget;
75     widget.attach(this);
78 generic_widget_element.prototype = {
79     get text () {
80         return this.element.getAttribute("value");
81     },
83     set text (v) {
84         this.element.setAttribute("value", v);
85     },
87     destroy : function () {
88         this.widget.destroy();
89     },
91     remove : function () {
92         this.element.parentNode.removeChild(this.element);
93         this.destroy();
94     }
98 function text_widget(window)
100     this.window_hooks = [];
101     this.window = window;
103 text_widget.prototype = {
104     add_hook : function (hook_name, handler)
105     {
106         var obj = this;
107         if (handler == null) handler = function () { obj.update(); }
108         add_hook.call(this.window, hook_name, handler);
109         this.window_hooks.push([hook_name, handler]);
110     },
112     view : null,
114     attach : function (view) {
115         this.view = view;
116         this.update();
117     },
119     update : function () {
120     },
122     destroy : function ()
123     {
124         for each (let i in this.window_hooks) {
125             remove_hook.call(this.window, i[0], i[1]);
126         }
127     },
129     remove : function ()
130     {
131         this.view.remove();
132     }
135 define_global_window_mode("mode_line", "window_initialize_early_hook");
137 function current_buffer_name_widget(window) {
138     this.class_name = "current-buffer-name-widget";
139     text_widget.call(this, window);
140     this.flex = "1";
141     this.crop = "end";
142     this.add_hook("current_content_buffer_location_change_hook");
143     this.add_hook("select_buffer_hook");
145 current_buffer_name_widget.prototype.__proto__ = text_widget.prototype;
146 current_buffer_name_widget.prototype.update = function () {
147     this.view.text = this.window.buffers.current.description;
150 function current_buffer_scroll_position_widget(window) {
151     this.class_name = "current-buffer-scroll-position-widget";
152     text_widget.call(this, window);
153     this.add_hook("current_buffer_scroll_hook");
154     this.add_hook("select_buffer_hook");
155     this.add_hook("current_content_buffer_location_change_hook");
156     this.add_hook("current_content_buffer_focus_change_hook");
158 current_buffer_scroll_position_widget.prototype.__proto__ = text_widget.prototype;
159 current_buffer_scroll_position_widget.prototype.update = function () {
160     var b = this.window.buffers.current;
161     var scrollX, scrollY, scrollMaxX, scrollMaxY;
162     if (b instanceof content_buffer)
163     {
164         var w = b.focused_frame;
165         scrollX = w.scrollX;
166         scrollY = w.scrollY;
167         scrollMaxX = w.scrollMaxX;
168         scrollMaxY = w.scrollMaxY;
169     } else
170     {
171         scrollX = b.scrollX;
172         scrollY = b.scrollY;
173         scrollMaxX = b.scrollMaxX;
174         scrollMaxY = b.scrollMaxY;
175     }
176     var x = scrollMaxX == 0 ? 100 : Math.round(scrollX / scrollMaxX * 100);
177     var y = scrollMaxY == 0 ? 100 : Math.round(scrollY / scrollMaxY * 100);
178     this.view.text = "(" + x + ", " + y + ")";
181 function clock_widget(window)
183     this.class_name = "clock-widget";
184     text_widget.call(this, window);
185     var obj = this;
186     this.do_update = function () { obj.update(); };
187     // todo: use one timer for multiple clock widgets
188     this.timer_ID = window.setTimeout(this.do_update, 0);
189     this.timer_timeout = true;
191 clock_widget.prototype.__proto__ = text_widget.prototype;
192 clock_widget.prototype.update = function () {
193     var time = new Date();
194     var hours = time.getHours();
195     var mins = time.getMinutes();
196     this.view.text = (hours<10 ? "0" + hours:hours) + ":" + (mins<10 ?"0" +mins:mins);
197     if (time.getSeconds() > 0 || time.getMilliseconds() > 100) {
198         this.window.clearTimeout(this.timer_ID);
199         var time = time.getSeconds() * 1000 + time.getMilliseconds();
200         time = 60000 - time;
201         this.timer_ID = this.window.setTimeout(this.do_update, time);
202         this.timer_timeout = true;
203     } else if (this.timer_timeout) {
204         this.window.clearTimeout(this.timer_ID);
205         this.timer_ID = this.window.setInterval(this.do_update, 60000);
206         this.timer_timeout = false;
207     }
209 clock_widget.prototype.destroy = function () {
210     this.window.clearTimeout(this.timer_ID);
213 function buffer_count_widget(window) {
214     this.class_name = "buffer-count-widget";
215     text_widget.call(this, window);
216     this.add_hook("select_buffer_hook");
217     this.add_hook("create_buffer_hook");
218     this.add_hook("kill_buffer_hook");
220 buffer_count_widget.prototype.__proto__ = text_widget.prototype;
221 buffer_count_widget.prototype.update = function () {
222     this.view.text = ("[" + (this.window.buffers.selected_index+1) + "/" +
223                       this.window.buffers.count + "]");
226 function loading_count_widget(window) {
227     this.class_name = "loading-count-widget";
228     text_widget.call(this, window);
229     var obj = this;
230     this.add_hook("content_buffer_started_loading_hook");
231     this.add_hook("content_buffer_finished_loading_hook");
232     this.add_hook("kill_buffer_hook");
234 loading_count_widget.prototype.__proto__ = text_widget.prototype;
235 loading_count_widget.prototype.update = function () {
236     var count = 0;
237     for_each_buffer(function(b) {if (b.loading) count++;});
238     if (count)
239         this.view.text = "(" + count + " loading)";
240     else
241         this.view.text = "";
244 function mode_line_adder(widget_constructor) {
245     if (!('mode_line_adder' in widget_constructor))
246         widget_constructor.mode_line_adder = function (window) {
247             window.mode_line.add_text_widget(new widget_constructor(window));
248         };
249     return widget_constructor.mode_line_adder;
252 add_hook("mode_line_hook", mode_line_adder(current_buffer_name_widget));
253 add_hook("mode_line_hook", mode_line_adder(clock_widget));
254 add_hook("mode_line_hook", mode_line_adder(current_buffer_scroll_position_widget));
256 mode_line_mode(true);