/* Algo: a dekstop environment look-a-like in your web browser Copyright (C) 2009 Niels Serup This file is part of Algo. Algo is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Algo is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Algo. If not, see . */ /* The screen class creates the screen on which all the windows appear. As a matter of fact, the screen class simply serves as a layer for adding windows. That's all. */ function screen() { this.elem = document.createElement('div') this.elem.className = 'area' this.elem.style.width = '100%' // Height determined by JavaScript later on wrapper.appendChild(this.elem) /* len and olen dynamically increases as new windows are opened. But while len is decreased when windows are closed, olen is never decreases. This proves helpful when the windows in objects/iframes must be able to access their own windows. */ this.len = 0 this.olen = 0 /* wndpos holds information about the windows on the screen. Each wndpos entry is a link to a scr_window class. wndpos keeps the links in their index order. */ this.wndpos = new Array() /* It is neccessary to create an overlay, as the window objects/iframes will catch focus if the mouse is moved over them. The overlay is on whenever a window is being moved or adjusted */ this.overlay = document.createElement('div') this.overlay.className = 'overlay' this.elem.appendChild(this.overlay) } screen.prototype.rethink = function() { // rethink() reorganises the screen top and height based on the navbars. var navil = navi.length var mh, th, borders, bl, border mh = 0 th = 0 /* The following loop uses the height and the border height of the navbars to compute the space on which the screen should be positioned. */ for (var i = 0; i < navil; i++) { border = 0 borders = navi[i].border bl = borders.length for (var ii = 0; ii < bl; ii += 2) { border += borders[ii] } mh += navi[i].height if (navi[i].pos[0] != -1) th += navi[i].height + border if (navi[i].pos[0] != -1 || navi[i].pos[2] != -1) mh += border } // bi = the heights of the navbars plus the border heights of the navbars this.bi = mh this.elem.style.top = th + 'px' } screen.prototype.update = function() { // Updates width and height and adjusts the height this.wh() this.elem.style.height = sh + 'px' } screen.prototype.wh = function() { // Get screen width and height if (self.innerHeight) { h = self.innerHeight w = self.innerWidth } else if (document.documentElement && document.documentElement.clientHeight) { h = document.documentElement.clientHeight w = document.documentElement.clientWidth } else if (document.body) { h = document.body.clientHeight w = document.body.clientWidth } // sh = screen height - navbars heights. The height of the screen area is sh sh = h - this.bi } screen.prototype.change_focus = function(num, det) { /* This function changes focus to the window specified in "num". "det" is a special identifier that tells this function what to do. Or whatever. */ if (det == undefined) var det = 0 var num = num * 1 for (var i = 0; i < this.len; i++) { // Delete link from the wndpos list if (this.wndpos[i] == num) this.wndpos.splice(i, 1) } /* if det == 0: add window to front if det == 1: add window to back if det == 2: remove and close window */ if (det == 0) this.wndpos.splice(0, 0, num) else if (det == 1) this.wndpos.splice(this.len, this.len, num) else if (det == 2) { this.len-- this.elem.removeChild(wnds[num].elem) navi[posis['appboxes']].appboxes.removeChild(wnds[num].appbox) for (i = 0; i < this.len; i++) { if (this.wndpos[i] > num) { wnds[this.wndpos[i]].renum(-1) // Readjust windows with a higher index this.wndpos[i]-- } } // Different actions based on different variables if (moving_window > num) moving_window-- else if (moving_window == num) this.move_end() if (adjusting_window > num) adjusting_window-- else if (adjusting_window == num) this.adjust_end() delete wnds[num] wnds.splice(num, 1) } // This function has no done anything visually. setindex takes care of that. this.setindex() } screen.prototype.setindex = function() { /* This function writes any changes made in the classes in the wndpos to the screen. If focus has changed from one window to another, setindex makes the user see that. */ for (var i = 1; i < this.len; i++) { wnds[this.wndpos[i]].elem.style.zIndex = this.len - i + 1 wnds[this.wndpos[i]].elem.id = '' wnds[this.wndpos[i]].appbox.className = '' } if (this.len > 0) { // The first window in the hierarchy gets the focus wnds[this.wndpos[0]].elem.style.zIndex = this.len + 2 wnds[this.wndpos[0]].elem.id = 'active' wnds[this.wndpos[0]].appbox.className = '' this.overlay.style.zIndex = this.len + 1 } // vis will turn true if any window is visible var vis = false for (i = 0; i < this.len; i++) { if (wnds[i].visible) vis = true } // Only make the current window current if at least one window is visible if (vis) wnds[this.wndpos[0]].appbox.className = 'current' // Check if there's enough space for the appboxes navi[posis['appboxes']].check_abs_height(true) } screen.prototype.set_overlay = function() { this.overlay.style.display = 'block' } screen.prototype.del_overlay = function() { this.overlay.style.display = 'none' } screen.prototype.move_start = function(what) { /* "move_start" sets the global value "moving_window" to the active window and thereby makes it recognisable by the set_coor function. */ moving_window = what * 1 /* The overlays are needed to keep the objects/iframes from getting the mouse focus. In theory this should not happen, but as the mouse is often moved faster than the window, this happens. There are two overlays: one that covers the window and on that covers the other windows. */ wnds[moving_window].cn('data_overlay').style.display = 'block' this.set_overlay() // These are needed later on to determine the position of the window. diff_x = x - wnds[moving_window].elem.offsetLeft diff_y = y - wnds[moving_window].elem.offsetTop } screen.prototype.move_end = function() { if (moving_window > -1) wnds[moving_window].cn('data_overlay').style.display = 'none' moving_window = -1 this.blurfocus() } screen.prototype.adjust_start = function(what, dir) { /* This is the same as "move_start" except that this does not start moving the window, but instead it starts adjusting (resizing) it. */ adjusting_window = what * 1 adjusting_dir = dir * 1 wnds[adjusting_window].cn('data_overlay').style.display = 'block' this.set_overlay() // Different variables are set depending on the direction of the adjusting. /* The directions are: 0: top-left 1: top 2: top-right 3: right 4: bottom-right 5: bottom 6: bottom-left 7: left If the resize direction is diagonal, both of the below options are true. */ if (adjusting_dir != 1 && adjusting_dir != 5) { // If vertical start_x = x start_w = wnds[adjusting_window].width diff_x = start_x - wnds[adjusting_window].elem.offsetLeft } if (adjusting_dir != 3 && adjusting_dir != 7) { // If horizontal start_y = y start_h = wnds[adjusting_window].height diff_y = start_y - wnds[adjusting_window].elem.offsetTop } } screen.prototype.adjust_end = function() { if (adjusting_window > -1) wnds[adjusting_window].cn('data_overlay').style.display = 'none' adjusting_window = -1 adjusting_dir = -1 this.blurfocus() } screen.prototype.blurfocus = function() { // Hides the overlay and applies the fix this.del_overlay() highlightfix.focus() highlightfix.select() } screen.prototype.setwindow = function(a, b, c, d, e, f, g, h, i, j, k, l, m, n) { // This function is the one that must be called when creating a new window. wnds[wnds.length] = new scr_window(a, b, c, d, e, f, g, h, i, j, k, l, m, n) // Positions itself at the front this.wndpos.splice(0, 0, this.len) this.len++ this.olen++ this.setindex() } screen.prototype.move_window = function() { // Moves the window based on current and earlier set variables var cx = x - diff_x if (cx < -diff_x) cx = -diff_x else if (cx > w - diff_x) cx = w - diff_x var cy = y - diff_y if (cy < 0) cy = 0 else if (cy > sh - scr.hheight) cy = sh - scr.hheight if (scr.len > moving_window) { wnds[moving_window].elem.style.left = cx + 'px' wnds[moving_window].elem.style.top = cy + 'px' } } screen.prototype.adjust_window = function() { // Adjusts the window based on current and earlier set variables // This function uses the same direction principle as "adjust_start". if (adjusting_dir != 1 && adjusting_dir != 5) { var cx, cw, cxs cxs = false if (adjusting_dir == 0 || adjusting_dir == 6 || adjusting_dir == 7) { // If to the left cx = x - diff_x cw = start_w + start_x - x if (x - diff_x < 0) { cx = 0 cxs = true } } else { // If to the right cx = start_x - start_w + start_w - diff_x cw = start_w + x - start_x if (x + start_w - diff_x > w) cxs = true } if (cw < width_min) cxs = true if (!cxs && scr.len > adjusting_window) { wnds[adjusting_window].elem.style.left = cx + 'px' wnds[adjusting_window].width = cw } } if (adjusting_dir != 3 && adjusting_dir != 7) { var cy, ch, cys cys = false if (adjusting_dir == 0 || adjusting_dir == 1 || adjusting_dir == 2) { // If upwards cy = y - diff_y ch = start_h + start_y - y if (y - diff_y < 0) { cy = 0 cys = true } } else { // If downwards cy = start_y - start_y + start_y - diff_y ch = start_h + y - start_y if (y + start_h - diff_y > sh) cys = true } if (ch < height_min) cys = true if (!cys && scr.len > adjusting_window) { wnds[adjusting_window].elem.style.top = cy + 'px' wnds[adjusting_window].height = ch } } // Update the window position wnds[adjusting_window].update() } screen.prototype.set_coor = function(e) { /* This function sets the global coordinates of the screen. If a window is eiher being moved or adjusted, this function calls the "move_window" or "adjust_window" functions */ if (!e) var e = window.event if (e.pageX || e.pageY) { x = e.pageX y = e.pageY } else if (e.clientX || e.clientY) { x = e.clientX + document.body.scrollLeft y = e.clientY + document.body.scrollTop } if (moving_window != -1) scr.move_window() else if (adjusting_window != -1) scr.adjust_window() }