Made new windows position themselves randomly.
[philo.git] / contrib / gilbert / media / gilbert / lib / app.js
1 Ext.ns('Gilbert.lib.app')
2
3
4 Gilbert.lib.app.Desktop = Ext.extend(Ext.Panel, {
5         
6         constructor: function(application, config) {
7                 var application = this.application = application;
8                 Gilbert.lib.app.Desktop.superclass.constructor.call(this, Ext.applyIf(config||{}, {
9                         region: 'center',
10                         border: false,
11                         padding: '5px',
12                         bodyStyle: 'background: none;',
13                 }));
14         },
15         
16 });
17
18
19 Gilbert.lib.app.MainMenu = Ext.extend(Ext.Toolbar, {
20         
21         constructor: function(application, config) {
22                 var application = this.application = application;
23                 Gilbert.lib.app.MainMenu.superclass.constructor.call(this, Ext.applyIf(config||{}, {
24                         region: 'north',
25                         autoHeight: true,
26                         items: [
27                                 {
28                                         xtype: 'tbtext',
29                                         text: '<span style="font-weight: bolder; text-transform: uppercase;">Gilbert</span>',
30                                 },
31                                 {
32                                         xtype: 'tbseparator',
33                                 },
34                         ],
35                 }));
36         },
37         
38 });
39
40
41 Gilbert.lib.app.TaskBar = Ext.extend(Ext.Toolbar, {
42         
43         constructor: function(application, config) {
44                 var application = this.application = application;
45                 Gilbert.lib.app.TaskBar.superclass.constructor.call(this, Ext.applyIf(config||{}, {
46                         region: 'south',
47                         enableOverflow: true,
48                         autoHeight: true,
49                         items: [],
50                         plugins: [
51                                 new Ext.ux.ToolbarReorderer({
52                                         defaultReorderable: true,
53                                 }),
54                         ],
55                 }));
56         },
57         
58         get_button_for_window: function(win) {
59                 return this.find('represented_window', win)[0];
60         },
61         
62         default_button_handler: function(button) {
63                 var win = button.represented_window;
64                 if (this.active_window === win) {
65                         win.minimize();
66                 } else {
67                         win.show();
68                 }
69         },
70         
71         register_window: function(win) {
72                 win.on('show', this.window_shown, this);
73                 win.on('hide', this.window_hidden, this);
74                 win.on('minimize', this.window_minimize, this);
75                 win.on('deactivate', this.window_deactivated, this);
76                 win.on('activate', this.window_activated, this);
77                 win.on('titlechange', this.window_titlechanged, this);
78                 win.on('iconchange', this.window_iconchanged, this);
79                 
80                 var button = new Ext.Button({
81                         text: win.title,
82                         iconCls: win.iconCls,
83                         enableToggle: true,
84                         allowDepress: false,
85                         width: 200,
86                         hidden: true,
87                 });
88                 button.represented_window = win;
89                 button.setHandler(this.default_button_handler, this);
90                 
91                 this.add(button);
92                 
93                 win.on('destroy', this.window_destroyed, this);
94         },
95         
96         window_destroyed: function(win) {
97                 this.remove(this.get_button_for_window(win));
98                 this.application.do_layout();
99         },
100         
101         window_shown: function(win) {
102                 if (this.minimizing_window !== win) {
103                         this.get_button_for_window(win).show();
104                         this.application.do_layout();
105                 }
106         },
107         
108         window_hidden: function(win) {
109                 if (this.minimizing_window !== win) {
110                         this.get_button_for_window(win).hide();
111                         this.application.do_layout();
112                 }
113         },
114         
115         window_minimize: function(win) {
116                 var button = this.get_button_for_window(win);
117                 
118                 this.minimizing_window = win;
119                 win.hide(button.el, function () {
120                         this.minimizing_window = undefined;
121                         
122                         win.minimized = true;
123                         button.setText('<i>'+win.title+'</i>');
124                         button.setHandler(function (button) {
125                                 var win = button.represented_window;
126                                 
127                                 win.minimized = false;
128                                 button.setText(win.title);
129                                 button.setHandler(this.default_button_handler, this);
130                                 
131                                 this.minimizing_window = win;
132                                 win.show(button.el, function () {
133                                         this.minimizing_window = undefined;
134                                 }, this);
135                         }, this);
136                 }, this);
137         },
138         
139         window_deactivated: function(win) {
140                 var button = this.get_button_for_window(win);
141                 button.toggle(false);
142                 button.setText(win.title);
143                 
144                 if (this.active_window === win) {
145                         this.active_window = undefined;
146                 }
147         },
148         
149         window_activated: function(win) {
150                 var button = this.get_button_for_window(win);
151                 button.toggle(true);
152                 button.setText('<b>'+win.title+'</b>');
153                 
154                 this.active_window = win;
155         },
156         
157         window_titlechanged: function(win) {
158                 var button = this.get_button_for_window(win);
159                 if (win.minimized) {
160                         button.setText('<i>'+win.title+'</i>');
161                 } else {
162                         button.setText(win.title);
163                 }
164         },
165         
166         window_iconchanged: function(win) {
167                 var button = this.get_button_for_window(win);
168                 button.setIconClass(win.iconCls);
169         },
170         
171 });
172
173
174 Gilbert.lib.app.Application = Ext.extend(Ext.util.Observable, {
175         
176         constructor: function (config) {
177                 
178                 this.models = {};
179                 this.plugins = {};
180                 
181                 Ext.apply(this, config, {
182                         renderTo: Ext.getBody(),
183                 });
184                 
185                 Gilbert.lib.app.Application.superclass.constructor.call(this);
186                 
187                 this.addEvents({
188                         'ready': true,
189                         'model_registered': true,
190                         'plugin_registered': true,
191                         'window_created': true,
192                 });
193                 
194                 Ext.onReady(this.pre_init.createDelegate(this));
195         },
196         
197         pre_init: function () {
198                 var outer = this;
199                 
200                 Gilbert.api.plugins.auth.get_preference('gilbert.background', function (background) {
201                         if (background) {
202                                 outer.renderTo.setStyle('background', background);
203                         }
204                 });
205                 Gilbert.api.plugins.auth.get_preference('gilbert.theme', function (theme) {
206                         if (theme) {
207                                 outer._set_theme(theme);
208                         }
209                         outer.init();
210                 });
211         },
212         
213         _set_theme: function(theme) {
214                 var link_element = document.getElementById('gilbert.theme.' + theme);
215                 if (link_element) {
216                         Ext.each(document.getElementsByClassName('gilbert.theme'), function (theme_element) {
217                                 if (theme_element != link_element) {
218                                         theme_element.disabled = true;
219                                 } else {
220                                         theme_element.disabled = false;
221                                 }
222                         });
223                 }
224         },
225         
226         init: function () {
227                 Ext.QuickTips.init();
228                 
229                 var desktop = this.desktop = new Gilbert.lib.app.Desktop();
230                 var mainmenu = this.mainmenu = new Gilbert.lib.app.MainMenu(this);
231                 var taskbar = this.taskbar = new Gilbert.lib.app.TaskBar(this);
232                 var viewport = this.viewport = new Ext.Viewport({
233                         renderTo: this.renderTo,
234                         layout: 'border',
235                         items: [
236                                 this.mainmenu,
237                                 this.desktop,
238                                 this.taskbar,
239                         ],
240                 });
241                 
242                 var windows = this.windows = new Ext.WindowGroup();
243                 
244                 Ext.Direct.on('exception', function (exception) {
245                         if (exception.code == Ext.Direct.exceptions.TRANSPORT) {
246                                 if (exception.xhr.status == 403) {
247                                         window.alert('You have been unexpectedly logged out.');
248                                         window.location.reload(true);
249                                 }
250                         }
251                         if (exception.html) {
252                                 var win = this.create_window({
253                                         width: 400,
254                                         height: 300,
255                                         maximizable: true,
256                                         minimizable: false,
257                                         modal: true,
258                                         html_source: exception.html,
259                                 }, Gilbert.lib.ui.HTMLWindow);
260                                 win.show();
261                         }
262                 }, this);
263                 
264                 var initial_plugins = this.plugins;
265                 this.plugins = {};
266                 
267                 Ext.iterate(initial_plugins, function (name, plugin, plugins) {
268                         this.register_plugin(name, plugin);
269                 }, this);
270                 
271                 this.do_layout();
272                 
273                 this.renderTo.on('contextmenu', Ext.emptyFn, null, {preventDefault: true});
274                 
275                 window.onbeforeunload = function (event) {
276                         var notice = 'You will lose all unsaved changes and windows.';
277                         var event = event || window.event;
278                         if (event) {
279                                 event.returnValue = notice;
280                         }
281                 
282                         return notice;
283                 };
284                 
285                 this.fireEvent('ready', this);
286         },
287         
288         create_window: function(config, cls) {
289                 var win = new(cls||Ext.Window)(Ext.applyIf(config||{},{
290                         renderTo: this.desktop.el,
291                         manager: this.windows,
292                         minimizable: true,
293                         constrainHeader: true,
294                 }));
295                 
296                 win.setPosition(Math.floor(Math.random() * ((this.desktop.getInnerWidth() - win.width) - 1)), Math.floor(Math.random() * ((this.desktop.getInnerHeight() - win.height) - 1)));
297                 
298                 win.render(this.desktop.el);
299                 if (win.modal) {
300                         win.on('show', function () {
301                                 this.mainmenu.hide();
302                                 this.taskbar.hide();
303                                 this.do_layout();
304                         }, this);
305                         win.on('hide', function () {
306                                 this.taskbar.show();
307                                 this.mainmenu.show();
308                                 this.do_layout();
309                         }, this);
310                         win.on('close', function () {
311                                 this.taskbar.show();
312                                 this.mainmenu.show();
313                                 this.do_layout();
314                         }, this);
315                 }
316                 this.taskbar.register_window(win);
317                 this.fireEvent('window_created', win);
318                 return win;
319         },
320         
321         do_layout: function() {
322                 this.mainmenu.doLayout();
323                 this.taskbar.doLayout();
324                 this.viewport.doLayout();
325         },
326         
327         register_plugin: function (name, plugin) {
328                 if (plugin.init(this) != false) {
329                         this.plugins[name] = plugin;
330                         this.fireEvent('plugin_registered', name, plugin, this);
331                 }
332         },
333         
334         get_plugin: function (name) {
335                 return this.plugins[name];
336         },
337         
338         register_model: function (app_label, name, model) {
339                 if (!this.models[app_label]) {
340                         this.models[app_label] = {};
341                 }
342                 this.models[app_label][name] = model;
343                 this.fireEvent('model_registered', name, model, this);
344         },
345         
346         get_model: function (app_label, name) {
347                 if (!this.models[app_label]) {
348                         return undefined;
349                 }
350                 return this.models[app_label][name];
351         },
352         
353 });