<@doc hierarchy="GMLDOM"> Base aspect for all objects editable by Layout Editor. This includes: Container, ScenarioUsage, Interactor, Control (c) SAP AG 2003-2006. All rights reserved. Aspect Widget for Layout; // implement ILayoutable; // Uncomment when parser starts to support this virtual property opacity = 1; // Layoutable type: none | diagram | box | control | viewbar | toolbar virtual property type = 'none'; virtual property arrowImageTopShift = 12; //[[imageHeigth(42px) - controlHeight(16px)] / 2] - 1 virtual property isRendered = false; constructor(board, parent) // if (!board) throw new Error('Failed to create Widget. No "board" supplied'); if (!board) throw new Error('#TEXT[XMSG_FAIL_DISPLAY_LAYOUT_BOARD]'); this.id = base.id; this.board = board; // board object (LayoutEditor object) this.parentID = parent.id; // Parent Aspect object this.doc = board.document; this.diagramID = parent.diagramID || this.parentID; board.setWidget(this); this.elem = null; // This HTML element this.parentElement = null; // Parent HTML element // // Find closest parent 'box' object // var lobj = parent; while (lobj && lobj.type != 'box') lobj = lobj.getParent(); this.boxID = lobj && lobj.id; end destructor() end virtual method getBox() return this.board.getWidget(this.boxID); end virtual method getParent() return this.board.getWidget(this.parentID)||this.getDiagram(); end virtual method getDiagram() if (this.diagramID == this.board.diagram.id) return this.board.diagram; return this.board.getWidget(this.diagramID); end /////////////////////////////////////////////////////////////////////////// // ILayoutable implementation // parentElement is null by default - means that it's this.getParent().elem override virtual method paint(parentElement) var parent = parentElement ? null : this.getParent(); this.parentElement = parentElement || (parent && parent.elem) || this.board.canvas; end override virtual method repaint(attr) end /* <@method name="setZOrder"> Sets the box layer The new z order index // VC04: METHOD('setLayer', function(z) { override virtual method setZOrder(z) var elem = this.elem; if (!elem) return; elem.z = INT(z); elem.style.zIndex = elem.z; end */ <@method name="setPos"> Sets the widget position The new position Indicates whether to snap to the nearest valid position // VC04: METHOD('setPos', function(x, y, snap) { virtual method setPos(pos, snap) var elem = this.elem; if (!elem) return; elem.x = snap ? ROUND(INT(pos.x), elem.gs||0) : INT(pos.x); elem.y = snap ? ROUND(INT(pos.y), elem.gs||0) : INT(pos.y); var st = elem.style; st.left = elem.x; st.top = elem.y; end <@method name="capturePos"> Called once before starting a move operation. This method can be used to capture the box position before it is moved. // VC04: METHOD('capturePos', function() { virtual method capturePos() // override end <@method name="applyPos"> Called once after finishing a move operation. This method can be used to apply custom behavior when the box is moved // VC04: METHOD('applyPos', function() { virtual method applyPos() // override end <@method name="setSize"> Sets the box size The new width The new height Indicates whether to snap to the nearest valid size // VC04: METHOD('setSize', function(w, h, snap) { virtual method setSize(size, snap) var elem = this.elem; if (!elem) return; elem.w = snap ? ROUND(INT(size.w), elem.gs||0) : INT(size.w); elem.h = snap ? ROUND(INT(size.h), elem.gs||0) : INT(size.h); if (elem.w < 0) elem.w = 0; if (elem.h < 0) elem.h = 0; var st = elem.style; st.width = elem.w; // st.width = elem.w+1; st.height = elem.h; // st.height = elem.h+1; // NOTE: Why VC04 has +1 here? end <@method name="setRect"> Sets the box position and size The new rectangle containing position and size Indicates whether to snap to the nearest valid size // VC04: METHOD('setBBox', function(x, y, w, h, snap) { virtual method setRect(rect, snap) this.setPos({x: rect.x, y: rect.y}, snap); this.setSize({w: rect.w, h: rect.h}, snap); end <@method name="captureBBox"> Called once before starting a resize operation. This method can be used to capture the box sized before it is resized. // VC04: METHOD('captureBBox', function() { virtual method captureRect() // override end <@method name="applyRect"> Called once after finishing a resize operation. This method can be used to apply custom behavior when the box is resized virtual method applyRect() // VC04: METHOD('applyBBox', function() { // override end <@method name="resetRect"> Resets the box position and size to cancel any pending move/resize operation virtual method resetRect() // NOTE: consider moving this to SelectionMgr if there's no reason for overrides var elem = this.elem; if (!elem) return; if (!elem.oldx || !elem.oldy || !elem.oldw || !elem.oldh) return; this.setPos({x: elem.oldx, y: elem.oldy}, true); this.setSize({w: elem.oldw, h: elem.oldh}, true); end <@method name="setVisibility"> Sets the box visibility The box opacity level, between 0 (invisible) and 1 (visible) virtual method setVisibility(opacity) // VC04: METHOD('setVisibility', function(opacity) { var elem = this.elem; if (!elem) return; if (POS(this.opacity) == opacity) return; var st = elem.style; //var st=this.style; if (opacity <= 0 ) { st.visibility = 'hidden'; st.filter = 'none'; } else if (opacity >= 1 ) { st.visibility = 'inherit'; st.filter = 'none'; } else { st.visibility = 'inherit'; st.filter = 'alpha(opacity='+(opacity*100)+')'; } this.opacity = opacity; end virtual method applyLayout(focusWidget, operation, repaint) return false; end virtual method buildRearrangeParams(focusWidget, operation, contentsSize, syncElems) return null; end override virtual method updateElements(operation, syncElems) var rootInfo = this.buildRearrangeParams(null, operation, undefined, syncElems); if (!rootInfo) return; var changes = this.board.getChangesFromCache(rootInfo&&rootInfo.focus); RULE('rearrangeWidgets', base, this.board, rootInfo, changes); if (!ISEMPTY(changes)) RULE('doApplyLayout', base, changes); end virtual method getPos() if (!this.elem) return {x: 0, y: 0}; return {x: this.elem.offsetLeft, y: this.elem.offsetTop}; end virtual method getSize() if (!this.elem) return {w: 320, h: 200}; return {w: this.elem.offsetWidth, h: this.elem.offsetHeight}; end virtual method getRect() var pos = this.getPos(); var size = this.getSize(); return {x: pos.x, y: pos.y, w: size.w, h: size.h}; end <@method name="setResizePolicy"> Updates box resize policy, used by Selection Manager virtual method setResizePolicy(policy) var sel = this.board.selection; if (!this.elem || !sel) return; if (typeof policy == 'number') { var p = null; switch (policy) { case #[LYT_MOVE_VERT]: p = {moveH: false, moveV: true, resizeH: true, resizeV: true }; break; case #[LYT_MOVE_HORZ]: p = {moveH: true, moveV: false, resizeH: true, resizeV: true }; break; case #[LYT_RESIZE_FIXED]: p = {moveH: false, moveV: false, resizeH: false, resizeV: false}; break; case #[LYT_RESIZE_FREE]: p = {moveH: true, moveV: true, resizeH: true, resizeV: true }; break; case #[LYT_RESIZE_HORZ]: p = {moveH: true, moveV: true, resizeH: true, resizeV: false}; break; case #[LYT_RESIZE_VERT]: p = {moveH: true, moveV: true, resizeH: false, resizeV: true }; break; case #[LYT_MOVERESIZE_HORZ]: p = {moveH: true, moveV: false, resizeH: true, resizeV: false}; break; case #[LYT_MOVERESIZE_HORZ_LEFT]: p = {moveH: true, moveV: true, resizeH: true, resizeV: false, alignH: 1, cursor: #[LYT_COL_RESIZE]}; break; case #[LYT_MOVE_HORZ_RESIZE_HORZ_LEFT]: p = {moveH: true, moveV: false, resizeH: true, resizeV: false, alignH: 1, cursor: #[LYT_COL_RESIZE]}; break; case #[LYT_MOVERESIZE_HORZ_RIGHT]: p = {moveH: true, moveV: true, resizeH: true, resizeV: false, alignH: -1, cursor: #[LYT_COL_RESIZE]}; break; case #[LYT_MOVE_NO_RESIZE_HORZ]: p = {moveH: true, moveV: true, resizeH: false, resizeV: false}; break; case #[LYT_MOVE_HORZ_NO_RESIZE]: p = {moveH: true, moveV: false, resizeH: false, resizeV: false}; break; case #[LYT_MOVEVERT_RESIZE_SE]: p = {moveH: false, moveV: true, resizeH: true, resizeV: true, alignH: 1, alignV: 1}; break; case #[LYT_MOVEHORZ_RESIZE_SE]: p = {moveH: true, moveV: false, resizeH: true, resizeV: true, alignH: 1, alignV: 1}; break; case #[LYT_RESIZE_SE]: p = {moveH: true, moveV: true, resizeH: true, resizeV: true, alignH: 1, alignV: 1}; break; case #[LYT_MOVERESIZE_VERT_BOTTOM]: p = {moveH: true, moveV: true, resizeH: false, resizeV: true, alignV: 1, cursor: #[LYT_ROW_RESIZE]}; break; } policy = p; } this.elem.style.resizePolicy = sel.encodeResizePolicy(policy); end <@doc scope="private"> Handles an update of base object property virtual method onModelUpdate(evt) end <@doc scope="private"> Handles an insertion of a child object into base object virtual method onModelInsert(evt) end <@doc scope="private"> Handles a removal of a child object from the base object virtual method onModelRemove(evt) end // DOC: derived implementations should also take care of setBaseRect virtual method setBasePos(pos) // Convert HTML event coordinates (elem.offsetParent-relative) - convert it to parent.content-relative var parent = this.getParent(); if (parent && this.elem) pos = parent.offsetToContent(this.elem.offsetParent, pos); RULE('setWidgetDimensions', base, pos, null, null, this.board.sessionCache); end virtual method setBaseSize(size) RULE('setWidgetDimensions', base, null, size, null, this.board.sessionCache); end // DOC: derived implementations should also take care of setBasePos virtual method setBaseRect(rect) // Convert HTML event coordinates (elem.offsetParent-relative) - convert it to parent.content-relative var parent = this.getParent(); if (parent && this.elem) { var cpos = parent.offsetToContent(this.elem.offsetParent, {x: rect.x, y: rect.y}); rect.x = cpos.x; rect.y = cpos.y; } RULE('setWidgetDimensions', base, null, null, rect, this.board.sessionCache); end // VC04: METHOD('getBoxPos', function() { virtual method getBasePos() var v=SPLIT(base.pos), gs=this.board.gridSize; return {x:MAX(ROUND(v[0]||0, gs), 0), y:MAX(ROUND(v[1]||0, gs), 0)} end // VC04: METHOD('getBoxSize', function() { virtual method getBaseSize() var v=SPLIT(base.size), gs=this.board.gridSize; return {w:MAX(ROUND(v[0]||320, gs), 8), h:MAX(ROUND(v[1]||240, gs), 8)} end virtual method getBaseRect() var pos = this.getBasePos(); var size = this.getBaseSize(); var rect = {x: pos.x, y: pos.y, w: size.w, h: size.h}; return rect; end virtual method getBaseZOrder() // NOTE: Implement and get rid of the 'undefined' option return (base.z === undefined) ? 0 : base.z; end ///////////////////////////////////////////////////////////////////////////// // Widget methods <@method name="createHtmlElement"> Creates a new element in the owner document of this box The tag name of the new element The CSS class name to assign to the new element The parent element under which to append the new element The new element // VC04: METHOD('createElement', function(tagName, className, parentElement) { virtual method createHtmlElement(tagName, className, id, parentElement) var elem = this.doc.createElement(tagName); if (className) elem.className = className; if (parentElement) parentElement.appendChild(elem); if (id) elem.id = id; return elem; end // returns rectangle to use when repainting the object // (usually either calculated from 'base' or taken asked from parent Widget) virtual method getRepaintRect() return {x: 0, y: 0, w: 0, h: 0}; end <@method name="fitContents"> Resizes the box to fit its contents // VC04: METHOD('fitContents', function() { virtual method fitContents() // override end /* <@method name="fitWindow"> Resizes the box to fit the window // NOTE: Implement // VC04: METHOD('fitWindow', function() { virtual method fitWindow() var rule=this.rule, pos=rule.@getBoxPos(), size=rule.@getBoxSize(), gs=this.elem.gs; var W = (this.board.gridObj.offsetWidth || 200) - 2*gs; rule.setProperty('@box_pos', gs+' '+pos.y); // rule.setAttr('box_pos', gs+' '+pos.y); rule.setProperty('@box_size', W+' '+size.h); // rule.setAttr('box_size', W+' '+size.h); end */ <@method name="getItem"> Gets a specified box item (field) The requested item name // VC04: METHOD('getItem', function(name) { virtual method getItem(name) // override //NOTE: see if this should be part of Interactor end <@method name="clearContents"> Clears the contents of this box // VC04: METHOD('clearContents', function() { virtual method clearContents() // override end <@method name="repaintContents"> Repaints the contents of this box // VC04: METHOD('repaintContents', function() { virtual method repaintContents(attr) // override end <@method name="reselectContents"> Reselects the box contents after the contents are scrolled virtual method reselectContents() var sel = this.board.selection; if (!sel || sel.size==0) return; var item = sel.getItem(0); if (!this.elem.contains(item)) return; if (this.scrollTimer) clearTimeout(this.scrollTimer); this.scrollTimer = setTimeout(function () { sel.adjustSelection(); }, 10); end <@method name="layoutContents"> Rearranges the contents of this widget virtual method layoutContents(focusWidget, operation) return false; end <@method name="resizeRepeater"> Resizes the contents repeater block // VC04: METHOD('resizeRepeater', function() { virtual method resizeRepeater() // override end virtual method applyFrameStyle() // override end // Returns content rect in client (this.elem-relative) coordinates virtual method getContentRect() var elem = this.elem; if (!elem) return {x:0, y:0, w:0, h:0}; return {x: 0, y: 0, w: elem.clientWidth, h: elem.clientHeight }; end // Returns size object with current content scroll ratios virtual method getContentScroll() var elem = this.elem; if (!elem) return {w: 0, h: 0}; return {w: elem.scrollLeft, h: elem.scrollTop}; end // Returns Widget content area rect in absolute (EDITBOX-relative) coordinates virtual method getAbsoluteContentRect() var rect = this.getContentRect(); var elem = this.elem; if (!elem) return rect; var opos = {x: rect.x, y: rect.y}; var apos = this.board.offsetToAbsolute(elem, opos); rect.x = apos.x; rect.y = apos.y; return rect; end // Converts offset coordinates (coords relative to elem.offsetParent, like event.offsetX/Y) to content-relative (relative to widget.contents) virtual method offsetToContent(elem, pos) if (!elem || !this.elem || (elem == this.elem)) return pos; return this.board.offsetToClient(this.elem, elem, pos); end virtual method adjustDndArrows(clientX, clientY, currentElement, checkParent) var data = { oneArrowVisible: false, twoArrowVisible: false, dropObjVisible: false, newIndex: undefined, newOffX: 0, newParent: undefined }; return data; end virtual method adjustParentArrows(currentElement) var data = { oneArrowVisible: false, twoArrowVisible: false, dropObjVisible: false, formObjVisible: false, newIndex: undefined, newOffX: 0, newOffY: 0, newParent: undefined, cellObject: undefined, dropObjLeft: 0, dropObjTop: 0, dropObjWidth: 0, dropObjHeight: 0, left: 0, top: 0, formObjLeft: 0, formObjTop: 0, formObjWidth: 0, formObjHeight: 0, formObjRow: -1, formObjCol: -1 }; try { var r = this.getAbsoluteContentRect(); if (base.arrows) { var left = base.arrows[this.board.getWidget(currentElement).base.index].left; data.top = r.y - this.arrowImageTopShift; data.left = r.x + left; data.newOffX = left; } data.dropObjLeft = r.x + this.getDropLeftShift(); data.dropObjTop = r.y; data.dropObjWidth = r.w; data.dropObjHeight = r.h; } catch(ex) {} return data; end virtual method getArrowedWidgetFromPoint(point) var elems = []; var styles = []; var widget = this; var board = this.board; while(widget) { var st = widget.elem.style; elems.push(st); styles.push(st.visibility); st.visibility = 'hidden'; var prev = widget; widget = board.getWidgetFromPoint(point); if (widget && widget.id == prev.id) break; } for (var len = elems.length, i = len - 1; i>= 0; i--) elems[i].visibility = styles[i]; return widget; end virtual method getDropLeftShift() return 0; end /* * Returns contents top gap. */ virtual method getContentsTopGap() return 0; end /* * Returns contents left gap. */ virtual method getContentsLeftGap() return 0; end /* * Returns ~true if Point (x,y) is inside the wiget's Rectangle borders. * else - returns ~false */ virtual method isAtPos(x, y) var r = this.getAbsoluteContentRect(); if (r) { if (x > r.x && x < (r.x + r.w) && y > r.y && y < (r.y + r.h)) return true; } return false; end virtual method checkOrganizer() //override end