<@class name="WinFrame"> A class that represents a floating window (c) SAP AG 2003-2006. All rights reserved. ////////////////////////////////////////////////////////////////////////////////////// // CLASS DECLARATION // Window constructor function WinFrame(settings, params, onCloseCallback) { // add window to the windows collection this.handle = WinFrame.lastHandle = POS(WinFrame.lastHandle)+1; this.visible = true; this._hasOwnSize = true; this.setCloseCallback(onCloseCallback); _allWindows[this.handle] = this; _visWindows[this.handle] = this; _currWindow = this; _visCount++; if(_visCount == 1) $ENV.fireRefreshToolbar(); this.gripIndexis = { NNW:4, N:0, NNE:5, NWW:11, NEE:6, W:3, E:1, SWW:10, SEE:7, SSW:9, S:2, SSE:8 }; // build frame based on initial settings this.params = params || null; this.loaded = false; this.initSettings(settings); this.margin = 4; //outer border width this.padding = 3; //inner border width this.buildFrame(); this.adjustFrame(); this.raise(); } // Window destructor WinFrame.prototype.dispose = function() { if (this.contentsObj) this.contentsObj.src = 'about:blank'; if (this.glassObj) this.glassObj.removeNode(true); for (var i=0, G1=this.sizeOutGrips,G2=this.sizeInGrips, len=G1 && G1.length; i Gets the window contents url This the url of an external file to be displayed in a secondary browser inside the window. <@prop name="key:s" default="" access="RO" also="@reusable"> Gets the window key The window key is used for identifying the window. In case the window is @reusable, at most one window instance with the same key may exist. If the window is not reusable, then any number of windows with the same key exist. If omitted, the window key will be set to the window url. <@prop name="behavior:s:amodal" access="RO"> Gets the window behavioral mode Value | Description ~modal | modal window ~amodal | amodal window ~lens | lens window <@prop name="position:s:inside" access="RO"> Gets the window positioning mode Value | Description ~inside | floating, inside canvas bounds ~unbound | floating, without bounds ~fill | fill entire canvas ~center | position on canvas center ~side | dock to canvas side (top, bottom, left, right) <@prop name="movable:b:true" access="RO">Indicates whether the window can be moved <@prop name="sizable:b:true" access="RO">Indicates whether the window can be resized <@prop name="dockable:b:false" access="RO">Indicates whether the window can be docked <@prop name="reusable:b:true" access="RO" also="@key">Indicates whether the window can be reused <@prop name="board:s" access="RO">Gets the window board id, if the window is a board window <@method name="open" scope="private"> Opens (reopens) the window WinFrame.prototype.open = function(settings, params, onCloseCallback) { this.setCloseCallback(onCloseCallback); this.initSettings(settings); if (this.btnMaxObj) setToggleButton(this.btnMaxObj, false) this.glassObj.style.display = this.behavior == 'modal' ? 'block' : 'none'; for (var i=0, G1=this.sizeOutGrips, G2=this.sizeInGrips, sizable = this.sizable, len=G1 && G1.length; i Notifies that the window has completed loading WinFrame.prototype.notifyLoad = function() { this.loaded = true; } <@method name="close"> Closes the window WinFrame.prototype.close = function(force, skipWIN_HIDE) { if (_currWindow == this) _currWindow = null; if (this.visible) { _visCount--; delete _visWindows[this.handle]; } this.visible = false; this.z = -1; if (!force && this.reusable) { if (this.contentsObj && !skipWIN_HIDE) this.contentsObj.contentWindow.__WIN_HIDE(); this.frameObj.style.display = 'none'; this.glassObj.style.display = 'none'; for (var i=0, G1=this.sizeOutGrips, G2=this.sizeInGrips, len=G1 && G1.length; i= zmax) { _currWindow=win; zmax=win.z; } } var st = _currWindow.titleTextObj.parentElement.style; st.background = _currWindow._titlePrimaryBGColor; st.color = _currWindow._titlePrimaryColor; setTimeout(_currWindow.getFocus); } if (this.board && this.oldboard) $WIN.switchBoard(this.oldboard); //Keep context when closing floating window // $ENV.context = this.params.root; SIGNAL('BOARD->layoutSelection'); } <@method name="reload"> Reloads the window WinFrame.prototype.reload = function() { if (!this.visible || !this.contentsObj) return; this.contentsObj.src = this.url; } ////////////////////////////////////////////////////////////////////////////////////// // WINDOW STYLE <@prop name="background:s:white" access="RO" group="Window Style" sortGroup="no"> Gets the window background color Value | Description ~color | color name / rgb code ~none | no color (transparent) <@prop name="border:s:thin" access="RO"> Gets the window border style Value | Description ~thick | thick frame ~thin | thin frame ~dash | dashed frame ~double | double frame ~none | no frame <@prop name="shadow:s:none" access="RO"> Gets the window shadow style Value | Description ~none | no shadow ~drop | drop shadow ~gradient | gradient shadow <@prop name="opacity:n:100" access="RO">Gets the window opacity, between 0 (transparent) and 100 (opaque) ////////////////////////////////////////////////////////////////////////////////////// // WINDOW TITLEBAR <@prop name="titlebar:s:raised" access="RO" group="Window Titlebar" sortGroup="no"> Gets the window titlebar style Value | Description ~raised | raised titlebar (3D) ~flat | flat titlebar ~thin | thin flat titlebar ~text | text-only titlebar ~none | no titlebar <@prop name="titleColor:s:auto" access="RO"> Gets the window titlebar color Value | Description ~auto | color depends on titlebar style ~color | explicit color name / rgb code ~none | no color (transparent) <@prop name="titleText:s" access="RO">Gets the window title text <@prop name="btnClose:b:true" access="RO">Indicates whether to show the Close button <@prop name="btnLock:b:false" access="RO">Indicates whether to show the Lock/Unlock button <@prop name="btnMax:b:false" access="RO">Indicates whether to show the Maximize/Restore button <@method name="setTitle"> Sets the window title The title text WinFrame.prototype.setTitle = function(text) { if (!text) text = ''; this.titleText = text; if (this.titleTextObj) this.titleTextObj.innerHTML = text; } ////////////////////////////////////////////////////////////////////////////////////// // WINDOW POSITIONING <@prop name="x:n:auto" access="RO" group="Window Positioning" sortGroup="no">Gets the window y position (relative to the canvas origin) <@prop name="y:n:auto" access="RO">Gets the window x position (relative to the canvas origin) <@prop name="w:n:auto" access="RO">Gets the window width <@prop name="h:n:auto" access="RO">Gets the window height <@prop name="minw:n:100" access="RO">Gets the minimum window width <@prop name="minh:n:50" access="RO">Gets the minimum window height <@prop name="maxw:n:9999" access="RO">Gets the maximum window width <@prop name="maxh:n:9999" access="RO">Gets the maximum window height <@prop name="margin:n:0" access="RO">Gets the margin to leave around the window <@method name="center"> Centers the window on a given point The new window x center The new window y center If the center point is omitted, the window will be centered in the middle of the canvas. WinFrame.prototype.centerOn = function(x,y) { if (arguments.length == 0) { this.moveTo((clientWidth-this.w)/2, (clientHeight-this.h)/2); } else { this.moveTo(x-this.w/2, y-this.h/2); } } <@method name="moveTo"> Moves the window The new window x position The new window y position WinFrame.prototype.moveTo = function(x,y) { if ('|inside|unbound|'.indexOf(this.position) < 0) return; if (x == this.x && y == this.y) return; var st=this.frameObj.style; st.left = this.x = x; st.top = this.y = y; this.adjustGrips(); } <@method name="resizeTo"> Resizes the window The new window width The new window height WinFrame.prototype.resizeTo = function(w,h) { if (!this._hasOwnSize) { this._hasOwnSize = true; this.glassObj.style.visibility = 'visible'; this.frameObj.style.visibility = 'visible'; } var w = LIMIT(this.minw, POS(w), this.maxw); var h = LIMIT(this.minh, POS(h), this.maxh); if (w == this.w && h == this.h) return; this.w = w; this.h = h; if (this.position == 'fill') return; this.position = 'inside'; this.adjustFrame(); } <@method name="raise"> Raises the window to the front WinFrame.prototype.raise = function() { if (!this.visible) return; // increase z-index, if needed if (this.z < _maxZIndex) { this.setZIndex(_maxZIndex+3); $MAINMENU.showFocusEffect(false); } _currWindow = this; // change title's background // and compact all z-indexes, once in a while var updateZIndex = _maxZIndex > _visCount*10; var V=[]; for (var k in _visWindows) V.push(_visWindows[k]); SORTN(V, 'z'); for (var i=0; i<_visCount; i++) { if (updateZIndex) V[i].setZIndex((i+1)*3); if (V[i] != _currWindow) { var st = V[i].titleTextObj.parentElement.style; st.background = V[i]._titleSecondaryBGColor; st.color = V[i]._titleSecondaryColor; } } var st = _currWindow.titleTextObj.parentElement.style; st.background = _currWindow._titlePrimaryBGColor; st.color = _currWindow._titlePrimaryColor; } <@method name="maximize"> Maximizes the window to fill the entire canvas WinFrame.prototype.maximize = function() { this.position = 'fill'; if (this.btnMaxObj) setToggleButton(this.btnMaxObj, true) this.adjustFrame(); } <@method name="restore"> Restores the window to its last position WinFrame.prototype.restore = function() { this.position = 'inside'; if (this.btnMaxObj) setToggleButton(this.btnMaxObj, false) this.adjustFrame(); } ////////////////////////////////////////////////////////////////////////////////////// // WINDOW BUILDING METHODS // PRIVATE: initializes the window settings WinFrame.prototype.initSettings = function(settings) { var win=this; // window control properties pstr ('url', ''); pstr ('key', this.url); pstr ('behavior', 'amodal', 'modal amodal lens'); pstr ('position', 'inside', 'inside unbound fill center top bottom left right'); pbool('movable', true); pbool('sizable', true); pbool('dockable', false); pbool('reusable', true); pstr ('board', ''); // window style properties pstr ('border', 'thin', 'vc_editor thick thin dash double none'); pstr ('background', 'white'); pnum ('opacity', 100); pstr ('shadow', 'none', 'none drop gradient'); // window titlebar properties pstr ('titlebar', 'raised', 'vc_editor raised flat thin text none'); pstr ('titleColor', 'auto'); pstr ('titleText', ''); pbool('btnClose', true); pbool('btnLock', false); pbool('btnMax', false); // window positioning properties pnum ('x', 'auto'); pnum ('y', 'auto'); pnum ('w', 'auto'); pnum ('h', 'auto'); pnum ('minw', 100); pnum ('minh', 50); pnum ('maxw', 9999); pnum ('maxh', 9999); pbool('islayoutBoard', false); // set window position and size var W=clientWidth, H=clientHeight; if (this.w <= 0 || this.w == 'auto') { this.w = 200; this._hasOwnSize = false; } if (this.h <= 0 || this.h == 'auto') { this.h = 150; this._hasOwnSize = false; } if (this.x == 'auto') this.x = (W-this.w)/2; if (this.y == 'auto') this.y = (H-this.h)/2; this.z = -1; function pnum(name, dflt) { win[name] = (settings && (name in settings)) ? FLOAT(settings[name]) : dflt; } function pbool(name, dflt) { win[name] = (settings && (name in settings)) ? BOOL(settings[name]) : dflt; } function pstr(name, dflt, domain) { win[name] = (settings && (name in settings)) ? settings[name] : dflt; if (!domain) return; win[name] = LOWER(win[name]); for (var i=0, V=SPLIT(domain), len=V.length; i W) { this.w = w = W - 2*mr; this.x = x = mr; } else { this.x = x = MAX(W - w, mr); this.w = w = W - x; } } if (H < y + h + mr) { if (h +2*mr > H) { this.h = h = H - 2*mr; this.y = y = mr; } else { this.y = y = MAX(H - h, mr); this.h = h = H - y; } } setBBox(frm,x,y,w,h); if (this.sizable) this.adjustGrips(); if (this.titleBarObj) { var ch = this.titleBarObj.children; var dx = (this.titlebar == 'raised' ? -2 : -1) - INT(this.titleBarObj.paddingRight, 0); var fw = frm.clientWidth; for (var i=ch.length-1; i>=1; i--) { dx -= 13; ch(i).style.left = fw+dx; } ch(i).style.width = fw+dx; } if (this.contentsObj) { var cy = this.titleBarObj ? this.titleBarObj.offsetHeight : 0; var cw = frm.clientWidth; var ch = POS(frm.clientHeight - cy); setBBox(this.contentsObj, 0, cy, cw-1, ch-1); } } // PRIVATE: adjusts the window grips after move or resize WinFrame.prototype.adjustGrips = function(resizing, x,y,w,h) { if (!this.sizeOutGrips) return; var G1=this.sizeOutGrips, G2=this.sizeInGrips, frm=this.frameObj, br=POS(this.borderWidth); var d1=this.margin, d2=this.padding, c=MAX(d1+d2, 10), dc=MAX(d1+d2, 10); var gi = this.gripIndexis; if (arguments.length == 0) { x = frm.offsetLeft; y = frm.offsetTop; w = frm.clientWidth; h = frm.clientHeight; } switch (this.position) { case 'fill': break; case 'top': break; case 'left': break; case 'bottom': y+=br; break; case 'right': x+=br; break; default: x+=br; y+=br; break; } /* -----NNW------N------NNE----- -NWW NEE- -W E- -SWW SEE- -----SSW------S------SSE----- */ setBBox(G1[gi['N']], x+c, y-d1, w-2*c, d1); setBBox(G2[gi['N']], x+c, y, w-2*c, d2); setBBox(G1[gi['E']], x+w, y+c, d1, h-c-dc); setBBox(G2[gi['E']], x+w-d2, y+c, d2, h-c-dc); setBBox(G1[gi['S']], x+c, y+h, w-c-dc, d1); setBBox(G2[gi['S']], x+c, y+h-d2, w-c-dc, d2); setBBox(G1[gi['W']], x-d1, y+c, d1, h-2*c); setBBox(G2[gi['W']], x, y+c, d2, h-2*c); setBBox(G1[gi['NNW']], x-d1, y-d1, d1+c, d1); setBBox(G2[gi['NNW']], x, y, c, d2); setBBox(G1[gi['NNE']], x+w-c, y-d1, d1+c, d1); setBBox(G2[gi['NNE']], x+w-c, y, c, d2); setBBox(G1[gi['NEE']], x+w, y, d1, c); setBBox(G2[gi['NEE']], x+w-d2, y, d2, c); setBBox(G1[gi['SEE']], x+w, y+h-dc, d1, dc); setBBox(G2[gi['SEE']], x+w-d2, y+h-dc, d2, dc); setBBox(G1[gi['SSE']], x+w-dc, y+h, d1+dc, d1); setBBox(G2[gi['SSE']], x+w-dc, y+h-d2, dc, d2); setBBox(G1[gi['SSW']], x-d1, y+h, d1+c, d1); setBBox(G2[gi['SSW']], x, y+h-d2, c, d2); setBBox(G1[gi['SWW']], x-d1, y+h-c, d1, c); setBBox(G2[gi['SWW']], x, y+h-c, d2, c); setBBox(G1[gi['NWW']], x-d1, y, d1, c); setBBox(G2[gi['NWW']], x, y, d2, c); if (!resizing) //do nothing while resizing setBBox(this.cornerObj, x+w-dc, y+h-dc, dc, dc); var hide = !this._hasOwnSize || this.position == 'fill'; for (var i=0, len=G1.length; i 0 && !win.dockable) return; var frm=win.frameObj; if (!win.islayoutBoard) { _moveFrame = frm.cloneNode(true); _moveFrame.children[frm.children.length - 1].removeNode(true); //remove IFrame _canvas.appendChild(_moveFrame); frm = _moveFrame; win.frameObj.style.visibility = 'hidden'; win.cornerObj.style.visibility = 'hidden'; frm.style.filter = 'alpha(opacity=50)'; } frm.onmousemove = win.doMove; frm.onmouseup = win.endMove; frm.onlosecapture = win.endMove; _moveWin = win; _moveX = event.x - frm.offsetLeft; _moveY = event.y - frm.offsetTop; frm.setCapture(true); } WinFrame.prototype.doMove = function() { if (!_moveWin) return; var win=_moveWin, frm=_moveFrame||_moveWin.frameObj; var W=clientWidth, H=clientHeight, mr=win.margin; var x = event.x - _moveX; var y = event.y - _moveY; if (win.position != 'unbound') { var x0=mr, x1=W-mr-win.w; var y0=mr, y1=H-mr-win.h; if (win.dockable) { var pos = (yy1) ? 'bottom' : (xx1) ? 'right' : 'inside'; if (pos != win.position) { if (_moveX > win.w) { _moveX = win.w/2; x = LIMIT(x0, event.x-_moveX, x1); } if (_moveY > win.h) { _moveY = win.h/2; y = LIMIT(y0, event.y-_moveY, y1); } win.position = pos; win.adjustFrame(); } if (pos != 'inside') { x = frm.offsetLeft; y = frm.offsetTop; } } x = LIMIT(x0, x, x1); y = LIMIT(y0, y, y1); } frm.style.left = win.x = x; frm.style.top = win.y = y; } WinFrame.prototype.endMove = function() { if (!_moveWin) return; var win=_moveWin, frm=_moveFrame||_moveWin.frameObj; win.doMove(); _moveWin = null; frm.releaseCapture(); frm.onmousemove = frm.onmouseup = frm.onlosecapture = null; if (win.sizable) win.adjustGrips(false, frm.offsetLeft, frm.offsetTop, frm.clientWidth, frm.clientHeight); if (!win.islayoutBoard) { st = win.frameObj.style; st.visibility = 'visible'; st.left = frm.offsetLeft; st.top = frm.offsetTop; win.cornerObj.style.visibility = 'visible'; if (_moveFrame) _moveFrame.removeNode(true); _moveFrame = null; } win.getFocus(); } WinFrame.prototype.doDblClick = function() { var win = getEventWindow(); if (!win || !win.sizable) return; if (win.position == 'fill') win.restore(); else win.maximize(); } ////////////////////////////////////////////////////////////////////////////////////// // WINDOW RESIZE HANDLER var _resizeWin, _resizeOx, _resizeOy, _resizeDx, _resizeDy; WinFrame.prototype.attachResizeHandler = function(obj) { obj.win = this; obj.onmousedown = this.startResize; } WinFrame.prototype.startResize = function() { if (event.button == 2) return; var win=getEventWindow(), G=win.sizeOutGrips; if (!win) return; win.raise(); if (!G || !win.sizable || win.position == 'fill') return; var frm=win.frameObj; frm.onmousemove = win.doResize; frm.onmouseup = win.endResize; frm.onlosecapture = win.endResize; _resizeWin = win; _resizeOx = event.x; _resizeOy = event.y; _resizeDx = event.srcElement.dx; _resizeDy = event.srcElement.dy; for (var i=0, len=G.length; i win.maxw) dw=win.maxw-w; if (h+dh < win.minh) dh=win.minh-h; else if (h+dh > win.maxh) dh=win.maxh-h; var dx = (_resizeDx < 0 ? -dw : 0); var dy = (_resizeDy < 0 ? -dh : 0); var W=clientWidth-mr, H=clientHeight-mr, X=frameElement.offsetTop+mr, Y=frameElement.offsetLeft+mr; var nx = x+dx; if (nx < X) { dw -= X-nx; nx = X; } var ny = y+dy; if (ny < Y) { dh -= Y-ny; ny = Y; } var nw = w+dw > W-nx ? W-nx : w+dw; var nh = h+dh > H-ny ? H-ny : h+dh; win.adjustGrips(true, nx, ny, nw, nh); } WinFrame.prototype.endResize = function() { if (!_resizeWin) return; var win=_resizeWin, frm=_resizeWin.frameObj; var G=win.sizeOutGrips, mr=win.margin, br=win.borderWidth; if (event.type == 'mouseup') { win.doResize(); if (_resizeDx != 0) { win.x = G[3].offsetLeft+mr-br; win.w = G[1].offsetLeft-win.x+br; } if (_resizeDy != 0) { win.y = G[0].offsetTop+mr-br; win.h = G[2].offsetTop-win.y+br; } } for (var i=0, len=G.length; i