diff options
author | Derrell Lipman <derrell@samba.org> | 2006-12-30 05:09:59 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 14:30:29 -0500 |
commit | 1170417ceeb8c49a46cda522a38eaa71c9cae30c (patch) | |
tree | dbf4c3fdcdb1af928dbd55f642ea40f00d09283a /webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev | |
parent | 23ccdca41670085da4486841b0d4900b4c8b02f3 (diff) | |
download | samba-1170417ceeb8c49a46cda522a38eaa71c9cae30c.tar.gz samba-1170417ceeb8c49a46cda522a38eaa71c9cae30c.tar.bz2 samba-1170417ceeb8c49a46cda522a38eaa71c9cae30c.zip |
r20414: Start to make SWAT usable by others. This is just a start...
(This used to be commit 26a34037a7ca6fbd05c5a6f7c2d5973e34bc6918)
Diffstat (limited to 'webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev')
13 files changed, 2062 insertions, 0 deletions
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/Pollution.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/Pollution.js new file mode 100644 index 0000000000..9377a76fdd --- /dev/null +++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/Pollution.js @@ -0,0 +1,249 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org + + License: + LGPL 2.1: http://www.gnu.org/licenses/lgpl.html + + Authors: + * Sebastian Werner (wpbasti) + * Andreas Ecker (ecker) + +************************************************************************ */ + +/* ************************************************************************ + +#module(dev) + +************************************************************************ */ + +qx.OO.defineClass("qx.dev.Pollution"); + +qx.Class.names = +{ + "window" : window, + "document" : document, + "body" : document.body +} + +qx.Class.ignore = +{ + "window" : + [ + // Firefox + "__firebug__", + "Components", + "controllers", + + // Firefox extension: Firebug + "console", + + // IE + "event", + "offscreenBuffering", + "clipboardData", + "clientInformation", + "Option", + "Image", + "external", + "screenTop", + "screenLeft", + + // Standard + "length", + "window", + "document", + "location", + "navigator", + "netscape", + "parent", + "frames", + "top", + "scrollbars", + "name", + "scrollX", + "scrollY", + "self", + "screen", + "history", + "content", + "menubar", + "toolbar", + "locationbar", + "personalbar", + "statusbar", + "directories", + "closed", + "crypto", + "pkcs11", + "opener", + "status", + "defaultStatus", + "innerWidth", + "innerHeight", + "outerWidth", + "outerHeight", + "screenX", + "screenY", + "pageXOffset", + "pageYOffset", + "scrollMaxX", + "scrollMaxY", + "fullScreen", + "frameElement" + ], + + "document" : + [ + "domConfig", + "location", + "compatMode", + "implementation", + "defaultView", + "title", + "body", + "styleSheets", + "documentElement", + "nodeName", + "nodeType", + "firstChild", + "lastChild", + "doctype", + "images", + "applets", + "links", + "forms", + "anchors", + "cookie", + "embeds", + "plugins", + "designMode", + "childNodes" + ], + + "body" : + [ + "textContent", + "innerHTML", + "outerHTML", + "innerText", + "outerText", + "scopeName", + "parentElement", + "tagName", + "filters", + "contentEditable", + "document", + "currentStyle", + "isMultiLine", + "clientHeight", + "clientWidth", + + "lastChild", + "firstChild", + "offsetTop", + "offsetLeft", + "offsetWidth", + "offsetHeight", + "tabIndex", + "className", + "attributes", + "previousSibling", + "nextSibling", + "ownerDocument", + "localName", + "childNodes", + "parentNode", + "nodeType", + "nodeName", + "style", + + "scrollTop", + "scrollLeft", + "scrollWidth", + "scrollHeight" + ] +} + +qx.Class.consoleInfo = function(object) +{ + alert("Global namespace is polluted by:\n\n" + qx.dev.Pollution.getTextList(object)); +} + +qx.Class.extract = function(object) +{ + var ext = []; + var ign = qx.dev.Pollution.ignore[object]; + var obj = qx.dev.Pollution.names[object]; + + for (var key in obj) + { + try + { + // Ignore null or undefined values + if (typeof obj[key] == "undefined" || obj[key] === null) { + continue; + } + + // Ignore native code + if (typeof obj[key] == "function" && obj[key].toString().indexOf("[native code]") != -1) { + continue; + } + + // Ignore if configured + if (qx.lang.Array.contains(ign, key)) { + continue; + } + } + catch(ex) + { + continue; + } + + ext.push({ "key" : key, "value" : obj[key] }); + } + + return ext; +} + +qx.Class.getHtmlTable = function(object) +{ + var all = []; + + var rowStart = "<tr style='vertical-align:top'><td>"; + var cellSplit = "</td><td>"; + var rowEnd = "</td></tr>"; + + all.push("<table>"); + + var ext = this.extract(object); + + for (var i=0; i<ext.length; i++) { + all.push(rowStart + ext[i].key + cellSplit + ext[i].value + rowEnd); + } + + all.push("</table>"); + + return all.join(""); +} + +qx.Class.getTextList = function(object) +{ + var all = []; + + var cellSplit = ": "; + var rowEnd = "\n"; + + var ext = this.extract(object); + + for (var i=0; i<ext.length; i++) { + all.push(ext[i].key + cellSplit + ext[i].value + rowEnd); + } + + return all.join(""); +} diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/TimeTracker.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/TimeTracker.js new file mode 100755 index 0000000000..a18502656f --- /dev/null +++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/TimeTracker.js @@ -0,0 +1,320 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org + + License: + LGPL 2.1: http://www.gnu.org/licenses/lgpl.html + + Authors: + * Sebastian Werner (wpbasti) + * Andreas Ecker (ecker) + +************************************************************************ */ + +/* ************************************************************************ + +#module(dev) + +************************************************************************ */ + +qx.OO.defineClass("qx.dev.TimeTracker", qx.core.Object, +function() +{ + qx.core.Object.call(this); + + this._functions = qx.lang.Array.fromArguments(arguments); + + this.buttonSets(); +}); + +qx.dev.TimeTracker.compare = function(a, b) { + return a-b; +} + + + + + + +/* +--------------------------------------------------------------------------- + METHODS +--------------------------------------------------------------------------- +*/ + +qx.Proto.buttonSets = function() +{ + var btnLayout = new qx.ui.layout.HorizontalBoxLayout; + + btnLayout.setLocation(20, 48); + btnLayout.setSpacing(5); + + var loopLabel = new qx.ui.basic.Atom("Method Loops: "); + loopLabel.setAllowStretchY(false); + loopLabel.setVerticalAlign("middle"); + + var loopInput = new qx.ui.form.TextField("100"); + loopInput.setAllowStretchY(false); + loopInput.setWidth(50); + loopInput.setVerticalAlign("middle"); + + var repeatLabel = new qx.ui.basic.Atom("Repeat Number: "); + repeatLabel.setAllowStretchY(false); + repeatLabel.setVerticalAlign("middle"); + repeatLabel.setMarginLeft(30); + + var btnStart1 = new qx.ui.form.Button("Start 3x", "icon/16/button-ok.png"); + var btnStart2 = new qx.ui.form.Button("Start 7x", "icon/16/button-ok.png"); + var btnStart3 = new qx.ui.form.Button("Start 15x", "icon/16/button-ok.png"); + var btnStart4 = new qx.ui.form.Button("Start 25x", "icon/16/button-ok.png"); + + btnStart1.addEventListener("execute", function() { this.start(3, parseInt(loopInput.getValue())); }, this); + btnStart2.addEventListener("execute", function() { this.start(7, parseInt(loopInput.getValue())); }, this); + btnStart3.addEventListener("execute", function() { this.start(15, parseInt(loopInput.getValue())); }, this); + btnStart4.addEventListener("execute", function() { this.start(25, parseInt(loopInput.getValue())); }, this); + + var htmlOutput = this._output = new qx.ui.embed.HtmlEmbed(); + + htmlOutput.setHtml(""); + htmlOutput.setLocation(20, 78); + htmlOutput.setRight(335); + htmlOutput.setBottom(48); + htmlOutput.setBorder("1px solid black"); + htmlOutput.setBackgroundColor("white"); + htmlOutput.setPadding(10); + htmlOutput.setOverflow("auto"); + htmlOutput.addToDocument(); + + btnLayout.add(loopLabel, loopInput, repeatLabel, btnStart1, btnStart2, btnStart3, btnStart4); + btnLayout.addToDocument(); +} + +qx.Proto.start = function(vRounds, vLoops) +{ + var vFuncs = this._functions; + var vLength = vFuncs.length; + var vStart; + var vLocalTimes; + var vAllTimes = []; + var vHtmlMeasured = []; + var vHtmlResults = []; + var vCellWidth = Math.round(100 / (vLength+1)) + "%"; + + vHtmlMeasured.push("<h3>Measured Values</h3>"); + + vHtmlMeasured.push("<style type='text/css'>.output{border: 1px solid black; width:100%; margin-bottom: 20px } .output thead{ font-weight: bold; } .output td, .output th{ text-align:left; width: " + vCellWidth + "; } .output td{padding:4px}</style>"); + + vHtmlMeasured.push("<table class='output'>"); + + vHtmlMeasured.push("<thead>"); + + vHtmlMeasured.push("<tr><td> </td>"); + + for (var j=0; j<vLength; j++) { + vHtmlMeasured.push("<td>Method " + (j+1) + "</td>"); + } + + vHtmlMeasured.push("</thead><tbody>"); + + for (var i=0; i<vRounds; i++) + { + vLocalTimes = []; + + for (var j=0; j<vLength; j++) + { + vStart = (new Date).valueOf(); + + vFuncs[j](vLoops); + + vLocalTimes.push((new Date).valueOf()-vStart); + } + + vHtmlMeasured.push("<tr><th>Round " + i + "</th>"); + + for (var j=0; j<vLocalTimes.length; j++) { + vHtmlMeasured.push("<td>" + vLocalTimes[j] + "</td>"); + } + + vHtmlMeasured.push("</tr>"); + vAllTimes.push(vLocalTimes); + } + + vHtmlMeasured.push("</tbody></table>"); + + + + + + var vSum, vMeanValue, vMeanAll=[], vMeanMin=1e7, vMeanMax=0; + + for (var j=0; j<vLength; j++) + { + vSum = 0; + + for (var i=0; i<vRounds; i++) + { + vSum += vAllTimes[i][j]; + } + + vMeanValue = Math.round(vSum / vRounds); + + vMeanAll.push(vMeanValue); + + vMeanMin = Math.min(vMeanMin, vMeanValue); + vMeanMax = Math.max(vMeanMax, vMeanValue); + } + + + + var vMedian, vMedianValue, vMedianAll=[], vMedianMin=1e7, vMedianMax=0; + + for (var j=0; j<vLength; j++) + { + vMedian = []; + + for (var i=0; i<vRounds; i++) + { + vMedian.push(vAllTimes[i][j]); + } + + vMedian.sort(qx.dev.TimeTracker.compare); + vMedianValue = vMedian[Math.floor(vRounds / 2)].toString(); + + vMedianAll.push(vMedianValue); + + vMedianMin = Math.min(vMedianValue, vMedianMin); + vMedianMax = Math.max(vMedianValue, vMedianMax); + } + + + + + + vHtmlResults.push("<h3>Results Summary</h3>"); + + vHtmlResults.push("<table class='output'>"); + + vHtmlResults.push("<thead>"); + + vHtmlResults.push("<tr><td> </td>"); + + for (var j=0; j<vLength; j++) { + vHtmlResults.push("<td>Method " + (j+1) + "</td>"); + } + + vHtmlResults.push("</thead><tbody>"); + + + vHtmlResults.push("<tr>"); + + vHtmlResults.push("<th>Median</th>"); + + for (var j=0; j<vLength; j++) { + vHtmlResults.push("<td>" + vMedianAll[j] + "</td>"); + } + + vHtmlResults.push("</tr>"); + + + + vHtmlResults.push("<tr>"); + + vHtmlResults.push("<th>Median Factor</th>"); + + for (var j=0; j<vLength; j++) + { + vHtmlResults.push("<td>"); + vHtmlResults.push(vMedianMin > 0 ? Math.round(vMedianAll[j] / vMedianMin) : "1"); + vHtmlResults.push("x</td>"); + } + + vHtmlResults.push("</tr>"); + + + + vHtmlResults.push("<tr>"); + + vHtmlResults.push("<th>Mean</th>"); + + for (var j=0; j<vLength; j++) { + vHtmlResults.push("<td>" + vMeanAll[j] + "</td>"); + } + + vHtmlResults.push("</tr>"); + + + + vHtmlResults.push("<tr>"); + + vHtmlResults.push("<th>Mean Factor</th>"); + + for (var j=0; j<vLength; j++) + { + vHtmlResults.push("<td>"); + vHtmlResults.push(vMeanMin > 0 ? Math.round(vMeanAll[j] / vMeanMin) : 1); + vHtmlResults.push("x</td>"); + } + + vHtmlResults.push("</tr>"); + + + + vHtmlResults.push("<tr>"); + + vHtmlResults.push("<th>Winner</th>"); + + for (var j=0; j<vLength; j++) + { + vHtmlResults.push("<td>"); + + if (vMedianMin == vMedianAll[j] && vMeanMin == vMeanAll[j]) + { + vHtmlResults.push("BOTH"); + } + + else if (vMedianMin == vMedianAll[j]) + { + vHtmlResults.push("MEDIAN"); + } + + else if (vMeanMin == vMeanAll[j]) + { + vHtmlResults.push("MEAN"); + } + + vHtmlResults.push("</td>"); + } + + vHtmlResults.push("</tr>"); + + vHtmlResults.push("</tbody></table>"); + + this._output.setHtml(vHtmlResults.join("") + vHtmlMeasured.join("")); +} + + + + + + +/* +--------------------------------------------------------------------------- + DISPOSER +--------------------------------------------------------------------------- +*/ + +qx.Proto.dispose = function() +{ + if (this.getDisposed()) { + return; + } + + this._functions = null; + + return qx.core.Object.prototype.dispose.call(this); +} diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/AlertAppender.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/AlertAppender.js new file mode 100644 index 0000000000..d800ac13ae --- /dev/null +++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/AlertAppender.js @@ -0,0 +1,65 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org + 2006 by STZ-IDA, Germany, http://www.stz-ida.de + + License: + LGPL 2.1: http://www.gnu.org/licenses/lgpl.html + + Authors: + * Andreas Ecker (ecker) + * Til Schneider (til132) + +************************************************************************ */ + +/* ************************************************************************ + +#module(log) + +************************************************************************ */ + +/** + * An appender that writes each message to a native alert(). + * <p> + * This class does not depend on qooxdoo widgets, so it also works when there + * are problems with widgets or when the widgets are not yet initialized. + * <p> + * It allows to go through the log messages step-by-step, since the alert + * window temporarily halts the regular program execution. That way even + * the dispose process can easily be debugged. + */ +qx.OO.defineClass("qx.dev.log.AlertAppender", qx.dev.log.Appender, +function() { + qx.dev.log.Appender.call(this); +}); + + +// overridden +qx.OO.changeProperty({ name:"useLongFormat", type:"boolean", defaultValue:false, allowNull:false }); + +// overridden +qx.Proto.appendLogEvent = function(evt) { + + // Append the message + var text = evt.logger.getName(); + if (evt.instanceId != null) { + text += " (" + evt.instanceId + ")"; + } + + alert("\n" + text + "\n" + this.formatLogEvent(evt)); +} + + +// overridden +qx.Proto.dispose = function() { + if (this.getDisposed()) { + return true; + } + + return qx.dev.log.Appender.prototype.dispose.call(this); +} diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/Appender.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/Appender.js new file mode 100644 index 0000000000..b1645a87fd --- /dev/null +++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/Appender.js @@ -0,0 +1,181 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2006 by STZ-IDA, Germany, http://www.stz-ida.de + + License: + LGPL 2.1: http://www.gnu.org/licenses/lgpl.html + + Authors: + * Til Schneider (til132) + +************************************************************************ */ + +/* ************************************************************************ + +#module(core) +#module(log) + +************************************************************************ */ + +/** + * An appender. Does the actual logging. + */ +qx.OO.defineClass("qx.dev.log.Appender", qx.dev.log.LogEventProcessor, +function() { + qx.dev.log.LogEventProcessor.call(this); +}); + + +/** Whether the logger name and log level should be included in the formatted log message. */ +qx.OO.addProperty({ name:"useLongFormat", type:"boolean", defaultValue:true, allowNull:false }); + + +// overridden +qx.Proto.handleLogEvent = function(evt) { + if (this.decideLogEvent(evt) != qx.dev.log.Filter.DENY) { + this.appendLogEvent(evt); + } +} + + +/** + * Appends a log event to the log. + * + * @param evt {Map} The event to append. + */ +qx.Proto.appendLogEvent = function(evt) { + throw new Error("appendLogEvent is abstract"); +} + + +/** + * Formats a log event. + * + * @param evt {Map} The log event to format. + * @return {string} The formatted event. + */ +qx.Proto.formatLogEvent = function(evt) { + var Logger = qx.dev.log.Logger; + + var text = ""; + + // Append the time stamp + var time = new String(new Date().getTime() - qx._LOADSTART); + while (time.length < 6) { + time = "0" + time; + } + text += time; + + // Append the level + if (this.getUseLongFormat()) { + switch (evt.level) { + case Logger.LEVEL_DEBUG: text += " DEBUG: "; break; + case Logger.LEVEL_INFO: text += " INFO: "; break; + case Logger.LEVEL_WARN: text += " WARN: "; break; + case Logger.LEVEL_ERROR: text += " ERROR: "; break; + case Logger.LEVEL_FATAL: text += " FATAL: "; break; + } + } else { + text += ": "; + } + + // Append the indent + var indent = ""; + for (var i = 0; i < evt.indent; i++) { + indent += " "; + } + text += indent; + + // Append the logger name and instance + if (this.getUseLongFormat()) { + text += evt.logger.getName(); + if (evt.instanceId != null) { + text += "[" + evt.instanceId + "]"; + } + text += ": "; + } + + // Append the message + if (typeof evt.message == "string") { + text += evt.message; + } else { + // The message is an object -> Log a dump of the object + var obj = evt.message; + if (obj == null) { + text += "Object is null"; + } else { + text += "--- Object: " + obj + " ---\n"; + var attrArr = new Array(); + try { + for (var attr in obj) { + attrArr.push(attr); + } + } catch (exc) { + text += indent + " [not readable: " + exc + "]\n"; + } + attrArr.sort(); + for (var i = 0; i < attrArr.length; i++) { + try { + text += indent + " " + attrArr[i] + "=" + obj[attrArr[i]] + "\n"; + } + catch (exc) { + text += indent + " " + attrArr[i] + "=[not readable: " + exc + "]\n"; + } + } + text += indent + "--- End of object ---"; + } + } + + // Append the throwable + if (evt.throwable != null) { + var thr = evt.throwable; + + if (thr.name == null) { + text += ": " + thr; + } else { + text += ": " + thr.name; + } + if (thr.message != null) { + text += " - " + thr.message; + } + if (thr.number != null) { + text += " (#" + thr.number + ")"; + } + + if (thr.stack != null) { + text += "\n" + this._beautyStackTrace(thr.stack); + } + } + + return text; +} + + +/** + * Beautifies a stack trace. + * + * @param stack {string} the stack trace to beautify. + * @return {string} the beautified stack trace. + */ +qx.Proto._beautyStackTrace = function(stack) { + // e.g. "()@http://localhost:8080/webcomponent-test-SNAPSHOT/webcomponent/js/com/ptvag/webcomponent/common/log/Logger:253" + var lineRe = /@(.+):(\d+)$/gm; + var hit; + var out = ""; + var scriptDir = "/script/"; + while ((hit = lineRe.exec(stack)) != null) { + var url = hit[1]; + + var jsPos = url.indexOf(scriptDir); + var className = (jsPos == -1) ? url : url.substring(jsPos + scriptDir.length).replace(/\//g, "."); + + var lineNumber = hit[2]; + out += " at " + className + ":" + lineNumber + "\n"; + } + return out; +} diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/DefaultFilter.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/DefaultFilter.js new file mode 100644 index 0000000000..411a631ecd --- /dev/null +++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/DefaultFilter.js @@ -0,0 +1,57 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2006 by STZ-IDA, Germany, http://www.stz-ida.de + + License: + LGPL 2.1: http://www.gnu.org/licenses/lgpl.html + + Authors: + * Til Schneider (til132) + +************************************************************************ */ + +/* ************************************************************************ + +#module(core) +#module(log) + +************************************************************************ */ + +/** + * The default filter. Has a minimum level and can be enabled or disabled. + */ +qx.OO.defineClass("qx.dev.log.DefaultFilter", qx.dev.log.Filter, +function() { + qx.dev.log.Filter.call(this); +}); + + +/** + * Whether the filter should be enabled. If set to false all log events + * will be denied. + */ +qx.OO.addProperty({ name:"enabled", type:"boolean", defaultValue:true, allowNull:false, getAlias:"isEnabled" }); + +/** + * The minimum log level. If set only log messages with a level greater or equal + * to the set level will be accepted. + */ +qx.OO.addProperty({ name:"minLevel", type:"number", defaultValue:null }); + + +// overridden +qx.Proto.decide = function(evt) { + var Filter = qx.dev.log.Filter; + if (! this.isEnabled()) { + return Filter.DENY; + } else if (this.getMinLevel() == null) { + return Filter.NEUTRAL; + } else { + return (evt.level >= this.getMinLevel()) ? Filter.ACCEPT : Filter.DENY; + } +} diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/DivAppender.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/DivAppender.js new file mode 100644 index 0000000000..1f7376fa64 --- /dev/null +++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/DivAppender.js @@ -0,0 +1,164 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2006 by STZ-IDA, Germany, http://www.stz-ida.de + + License: + LGPL 2.1: http://www.gnu.org/licenses/lgpl.html + + Authors: + * Til Schneider (til132) + +************************************************************************ */ + +/* ************************************************************************ + +#module(log) + +************************************************************************ */ + +/** + * An appender that writes all messages to a div element. + * + * This class does not depend on qooxdoo widgets, so it also works when there + * are problems with widgets or when the widgets are not yet initialized. + * + * @param divId {string ? "qx_log"} the ID of the div element to write the + * messages to. + */ +qx.OO.defineClass("qx.dev.log.DivAppender", qx.dev.log.Appender, +function(divId) { + qx.dev.log.Appender.call(this); + + this._divId = divId ? divId : "qx_log"; +}); + + +/** + * The maximum number of messages to show. If null the number of messages is not + * limited. + */ +qx.OO.addProperty({ name:"maxMessages", type:"number", defaultValue:500 }); + +// overridden +qx.OO.changeProperty({ name:"useLongFormat", type:"boolean", defaultValue:false, allowNull:false }); + +/** The CSS class name for the head div {containing the clear button}. */ +qx.OO.addProperty({ name:"headClassName", type:"string", defaultValue:"log-head" }); + +/** The CSS class name for the body div {containing the log messages}. */ +qx.OO.addProperty({ name:"bodyClassName", type:"string", defaultValue:"log-body" }); + +/** The CSS class name for a div showing the name of the current group. */ +qx.OO.addProperty({ name:"groupClassName", type:"string", defaultValue:"log-group" }); + +/** The CSS class name for a div showing a debug message. */ +qx.OO.addProperty({ name:"debugClassName", type:"string", defaultValue:"log-debug" }); + +/** The CSS class name for a div showing a info message. */ +qx.OO.addProperty({ name:"infoClassName", type:"string", defaultValue:"log-info" }); + +/** The CSS class name for a div showing a warn message. */ +qx.OO.addProperty({ name:"warnClassName", type:"string", defaultValue:"log-warn" }); + +/** The CSS class name for a div showing a error message. */ +qx.OO.addProperty({ name:"errorClassName", type:"string", defaultValue:"log-error" }); + + +/** + * Creates an onclick handler that clears a div element. This method is used to + * create a minimum closure. + * + * @param logElem {Element} the element to clear when the handler is called. + * @return {Function} the handler. + */ +qx.Proto._createClearButtonHandler = function(logElem) { + return function(evt) { + logElem.innerHTML = ""; + } +} + + +// overridden +qx.Proto.appendLogEvent = function(evt) { + var Logger = qx.dev.log.Logger; + + // Initialize the log element if nessesary + if (this._logElem == null) { + var divElem = document.getElementById(this._divId); + if (divElem == null) { + throw new Error("Logging div with ID " + this._divId + " not found"); + } + divElem.innerHTML = '<div class="' + this.getHeadClassName() + '"><button>Clear</button></div>' + + '<div class="' + this.getBodyClassName() + '"></div>'; + + this._clearBt = divElem.firstChild.firstChild; + this._logElem = divElem.lastChild; + + this._clearBt.onclick = this._createClearButtonHandler(this._logElem); + } + + // Append the group when needed + var group = evt.logger.getName(); + if (evt.instanceId != null) { + group += "[" + evt.instanceId + "]"; + } + + if (group != this._lastGroup) { + var elem = document.createElement("div"); + elem.className = this.getGroupClassName(); + elem.innerHTML = group; + + this._logElem.appendChild(elem); + this._lastGroup = group; + } + + // Append the message + var elem = document.createElement("div"); + switch (evt.level) { + case Logger.LEVEL_DEBUG: elem.className = this.getDebugClassName(); break; + case Logger.LEVEL_INFO: elem.className = this.getInfoClassName(); break; + case Logger.LEVEL_WARN: elem.className = this.getWarnClassName(); break; + case Logger.LEVEL_ERROR: elem.className = this.getErrorClassName(); break; + } + elem.innerHTML = this.formatLogEvent(evt).replace(/&/g, "&") + .replace(/</g, "<").replace(/ /g, "  ").replace(/[\n]/g, "<br>"); + this._logElem.appendChild(elem); + + // Remove superflous messages + while (this._logElem.childNodes.length > this.getMaxMessages()) { + this._logElem.removeChild(this._logElem.firstChild); + + if (this._removedMessageCount == null) { + this._removedMessageCount = 1; + } else { + this._removedMessageCount++; + } + } + + if (this._removedMessageCount != null) { + this._logElem.firstChild.className = ""; + this._logElem.firstChild.innerHTML = "(" + this._removedMessageCount + + " messages removed)"; + } +} + + +// overridden +qx.Proto.dispose = function() { + if (this.getDisposed()) { + return true; + } + + if (this._clearBt) { + this._clearBt.onclick = null; + this._clearBt = null; + } + this._logElem = null; + + return qx.dev.log.Appender.prototype.dispose.call(this); +} diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/Filter.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/Filter.js new file mode 100644 index 0000000000..60cee7ad6e --- /dev/null +++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/Filter.js @@ -0,0 +1,51 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2006 by STZ-IDA, Germany, http://www.stz-ida.de + + License: + LGPL 2.1: http://www.gnu.org/licenses/lgpl.html + + Authors: + * Til Schneider (til132) + +************************************************************************ */ + +/* ************************************************************************ + +#module(core) +#module(log) + +************************************************************************ */ + +/** + * A filter for log events. + */ +qx.OO.defineClass("qx.dev.log.Filter", qx.core.Object, +function() { + qx.core.Object.call(this); +}); + +/** + * Decidies whether a log event is accepted. + * + * @param evt {Map} The event to check. + * @return {int} {@link #ACCEPT}, {@link #DENY} or {@link #NEUTRAL}. + */ +qx.Proto.decide = function(evt) { + throw new Error("decide is abstract"); +} + + +/** {int} Specifies that the log event is accepted. */ +qx.Class.ACCEPT = 1; + +/** {int} Specifies that the log event is denied. */ +qx.Class.DENY = 2; + +/** {int} Specifies that the filter is neutral to the log event. */ +qx.Class.NEUTRAL = 3; diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/FireBugAppender.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/FireBugAppender.js new file mode 100644 index 0000000000..34d66234c2 --- /dev/null +++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/FireBugAppender.js @@ -0,0 +1,72 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2006 by David Perez + + License: + LGPL 2.1: http://www.gnu.org/licenses/lgpl.html + + Authors: + * David Perez (david-perez) + +************************************************************************ */ + +/* ************************************************************************ + +#module(core) +#module(log) + +************************************************************************ */ + +/** + * An appender that writes all messages to FireBug, a nice extension for debugging and developing under Firefox. + * <p> + * This class does not depend on qooxdoo widgets, so it also works when there + * are problems with widgets or when the widgets are not yet initialized. + * </p> + */ +qx.OO.defineClass('qx.dev.log.FireBugAppender', qx.dev.log.Appender, function() { + qx.dev.log.Appender.call(this); +}); + +qx.Proto.appendLogEvent = function(evt) +{ + if (typeof console != 'undefined') + { + var log = qx.dev.log.Logger; + var msg = this.formatLogEvent(evt); + + switch (evt.level) + { + case log.LEVEL_DEBUG: + if (console.debug) { + console.debug(msg); + } + break; + case log.LEVEL_INFO: + if (console.info) { + console.info(msg); + } + break; + case log.LEVEL_WARN: + if (console.warn) { + console.warn(msg); + } + break; + default: + if (console.error) { + console.error(msg); + } + break; + } + // Force a stack dump, for helping locating the error + if (evt.level > log.LEVEL_WARN && (!evt.throwable || !evt.throwable.stack) && console.trace) + { + console.trace(); + } + } +} diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/ForwardAppender.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/ForwardAppender.js new file mode 100644 index 0000000000..5268f87989 --- /dev/null +++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/ForwardAppender.js @@ -0,0 +1,41 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2006 by STZ-IDA, Germany, http://www.stz-ida.de + + License: + LGPL 2.1: http://www.gnu.org/licenses/lgpl.html + + Authors: + * Til Schneider (til132) + +************************************************************************ */ + +/* ************************************************************************ + +#module(log) + +************************************************************************ */ + +/** + * An appender that forwards all log events to a log event processor. + * + * @param targetProcessor {LogEventProcessor} The log event processor Where to + * pass the log events. + */ +qx.OO.defineClass("qx.dev.log.ForwardAppender", qx.dev.log.Appender, +function(targetProcessor) { + qx.dev.log.Appender.call(this); + + this._targetProcessor = targetProcessor; +}); + + +// overridden +qx.Proto.appendLogEvent = function(evt) { + this._targetProcessor.handleLogEvent(evt); +} diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/LogEventProcessor.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/LogEventProcessor.js new file mode 100644 index 0000000000..c6c4a8ed33 --- /dev/null +++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/LogEventProcessor.js @@ -0,0 +1,141 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2006 by STZ-IDA, Germany, http://www.stz-ida.de + + License: + LGPL 2.1: http://www.gnu.org/licenses/lgpl.html + + Authors: + * Til Schneider (til132) + +************************************************************************ */ + +/* ************************************************************************ + +#module(core) + +************************************************************************ */ + +/** + * Processes log events. May be configured with filters in order to specify + * which log events should be processed. + */ +qx.OO.defineClass("qx.dev.log.LogEventProcessor", qx.core.Object, +function() { + qx.core.Object.call(this); +}); + + +/** + * Appends a filter to the filter chain. + * + * @param filter {Filter} The filter to append. + */ +qx.Proto.addFilter = function(filter) { + if (this._filterArr == null) { + this._filterArr = [] + } + this._filterArr.push(filter); +} + + +/** + * Clears the filter chain. + */ +qx.Proto.clearFilters = function() { + this._filterArr = null; +} + + +/** + * Returns the head filter from the chain. Returns null if there are no filters. + * + * @return {Filter} the head filter from the chain. + */ +qx.Proto.getHeadFilter = function() { + return (this._filterArr == null || this._filterArr.length == 0) ? null : this._filterArr[0]; +} + + +/** + * Returns the default filter from the chain. If the head filter is no default + * filter, the chain will be cleared and a default filter will be created. + * + * @return {Filter} the default filter. + */ +qx.Proto._getDefaultFilter = function() { + var headFilter = this.getHeadFilter(); + if (! (headFilter instanceof qx.dev.log.DefaultFilter)) { + // The head filter of the appender is no DefaultFilter + // (or the appender has no filters at all) + // -> Create a default handler and append it + this.clearFilters(); + headFilter = new qx.dev.log.DefaultFilter(); + this.addFilter(headFilter); + } + + return headFilter; +} + + +/** + * Sets whether event processing should be enabled. + * <p> + * Note: This will clear all custom filters. + * + * @param enabled {boolean} whether event processing should be enabled. + */ +qx.Proto.setEnabled = function(enabled) { + this._getDefaultFilter().setEnabled(enabled); +} + + +/** + * Sets the min level an event must have in order to be processed. + * <p> + * Note: This will clear all custom filters. + * + * @param minLevel {int} the new min level. + */ +qx.Proto.setMinLevel = function(minLevel) { + this._getDefaultFilter().setMinLevel(minLevel); +} + + +/** + * Decides whether a log event is processed. + * + * @param evt {Map} the event to check. + * @return {int} {@link Filter#ACCEPT}, {@link Filter#DENY} or + * {@link Filter#NEUTRAL}. + */ +qx.Proto.decideLogEvent = function(evt) { + var NEUTRAL = qx.dev.log.Filter.NEUTRAL; + + if (this._filterArr != null) { + for (var i = 0; i < this._filterArr.length; i++) { + var decision = this._filterArr[i].decide(evt); + if (decision != NEUTRAL) { + return decision; + } + } + } + + // All filters are neutral, so are we + return NEUTRAL; +} + + +/** + * Processes a log event. + * + * @param evt {Map} The log event to process. + */ +qx.Proto.handleLogEvent = function(evt) { + throw new Error("handleLogEvent is abstract"); +} diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/Logger.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/Logger.js new file mode 100644 index 0000000000..b5cd3d6705 --- /dev/null +++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/Logger.js @@ -0,0 +1,374 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2006 by STZ-IDA, Germany, http://www.stz-ida.de + + License: + LGPL 2.1: http://www.gnu.org/licenses/lgpl.html + + Authors: + * Til Schneider (til132) + +************************************************************************ */ + +/* ************************************************************************ + +#module(core) +#module(log) +#require(qx.dev.log.WindowAppender) + +************************************************************************ */ + +/** + * A logger. Logs messages of one log category. + * + * @param name {string} The category name of this logger. (Normally a class or + * package name) + * @param parentLogger {Logger} The parent logger. + */ +qx.OO.defineClass("qx.dev.log.Logger", qx.dev.log.LogEventProcessor, +function(name, parentLogger) { + qx.dev.log.LogEventProcessor.call(this); + + this._name = name; + this._parentLogger = parentLogger; +}); + + +/** + * Returns the name of this logger. (Normally a class or package name) + * + * @return {string} the name. + */ +qx.Proto.getName = function() { + return this._name; +} + + +/** + * Returns the parent logger. + * + * @return {Logger} the parent logger. + */ +qx.Proto.getParentLogger = function() { + return this._parentLogger; +} + + +/** + * Indents all following log messages by one. + * <p> + * This affects all log messages. Even those of other loggers. + */ +qx.Proto.indent = function() { + qx.dev.log.Logger._indent++; +} + + +/** + * Unindents all following log messages by one. + * <p> + * This affects all log messages. Even those of other loggers. + */ +qx.Proto.unindent = function() { + qx.dev.log.Logger._indent--; +} + + +/** + * Adds an appender. + * <p> + * If a logger has an appender, log events will not be passed to the + * appenders of parent loggers. If you want this behaviour, also append a + * {@link ForwardAppender}. + * + * @param appender {Appender} the appender to add. + */ +qx.Proto.addAppender = function(appender) { + if (this._appenderArr == null) { + this._appenderArr = []; + } + + this._appenderArr.push(appender); +} + + +/** + * Removes an appender. + * + * @param appender {Appender} the appender to remove. + */ +qx.Proto.removeAppender = function(appender) { + if (this._appenderArr != null) { + this._appenderArr.remove(appender); + } +} + + +/** + * Removes all appenders. + */ +qx.Proto.removeAllAppenders = function() { + this._appenderArr = null; +} + + +// overridden +qx.Proto.handleLogEvent = function(evt) { + var Filter = qx.dev.log.Filter; + + var decision = Filter.NEUTRAL; + var logger = this; + while (decision == Filter.NEUTRAL && logger != null) { + decision = logger.decideLogEvent(evt); + logger = logger.getParentLogger(); + } + + if (decision != Filter.DENY) { + this.appendLogEvent(evt); + } +} + + +/** + * Passes a log event to the appenders. If the logger has no appenders the + * event will be passed to the appenders of the parent logger, and so on. + * + * @param evt {Map} The event to append. + */ +qx.Proto.appendLogEvent = function(evt) { + if (this._appenderArr != null && this._appenderArr.length != 0) { + for (var i = 0; i < this._appenderArr.length; i++) { + this._appenderArr[i].handleLogEvent(evt); + } + } else if (this._parentLogger != null) { + this._parentLogger.appendLogEvent(evt); + } +} + + +/** + * Logs a message. + * + * @param level {int} the log level. + * @param msg {var} the message to log. If this is not a string, the + * object dump will be logged. + * @param instanceId {var ? null} the ID of the instance the log message comes from. + * @param exc {var ? null} the exception to log. + */ +qx.Proto.log = function(level, msg, instanceId, exc) { + var evt = { logger:this, level:level, message:msg, throwable:exc, + indent:qx.dev.log.Logger._indent, instanceId:instanceId } + this.handleLogEvent(evt); +} + + +/** + * Logs a debug message. + * + * @param msg {var} the message to log. If this is not a string, the + * object dump will be logged. + * @param instanceId {var ? null} the ID of the instance the log message comes from. + * @param exc {var ? null} the exception to log. + */ +qx.Proto.debug = function(msg, instanceId, exc) { + this.log(qx.dev.log.Logger.LEVEL_DEBUG, msg, instanceId, exc); +} + + +/** + * Logs an info message. + * + * @param msg {var} the message to log. If this is not a string, the + * object dump will be logged. + * @param instanceId {var ? null} the ID of the instance the log message comes from. + * @param exc {var ? null} the exception to log. + */ +qx.Proto.info = function(msg, instanceId, exc) { + this.log(qx.dev.log.Logger.LEVEL_INFO, msg, instanceId, exc); +} + + +/** + * Logs a warning message. + * + * @param msg {var} the message to log. If this is not a string, the + * object dump will be logged. + * @param instanceId {var ? null} the ID of the instance the log message comes from. + * @param exc {var ? null} the exception to log. + */ +qx.Proto.warn = function(msg, instanceId, exc) { + this.log(qx.dev.log.Logger.LEVEL_WARN, msg, instanceId, exc); +} + + +/** + * Logs an error message. + * + * @param msg {var} the message to log. If this is not a string, the + * object dump will be logged. + * @param instanceId {var ? null} the ID of the instance the log message comes from. + * @param exc {var ? null} the exception to log. + */ +qx.Proto.error = function(msg, instanceId, exc) { + this.log(qx.dev.log.Logger.LEVEL_ERROR, msg, instanceId, exc); +} + + +/** + * Logs a fatal message. + * + * @param msg {var} the message to log. If this is not a string, its + * object dump will be logged. + * @param instanceId {var ? null} the ID of the instance the log message comes from. + * @param exc {var ? null} the exception to log. + */ +qx.Proto.fatal = function(msg, instanceId, exc) { + this.log(qx.dev.log.Logger.LEVEL_FATAL, msg, instanceId, exc); +} + + +/** + * Resets the measure timer. + * + * @see #measure{} + */ +qx.Proto.measureReset = function() { + if (this._totalMeasureTime != null) { + this.debug("Measure reset. Total measure time: " + this._totalMeasureTime + " ms"); + } + + this._lastMeasureTime = null; + this._totalMeasureTime = null; +} + + +/** + * Logs a debug message and measures the time since the last call of measure. + * + * @param msg {string} the message to log. + * @param instanceId {var ? null} the ID of the instance the log message comes from. + * @param exc {var ? null} the exception to log. + */ +qx.Proto.measure = function(msg, instanceId, exc) { + if (this._lastMeasureTime == null) { + msg = "(measure start) " + msg; + } else { + var delta = new Date().getTime() - this._lastMeasureTime; + + if (this._totalMeasureTime == null) { + this._totalMeasureTime = 0; + } + + this._totalMeasureTime += delta; + msg = "(passed time: " + delta + " ms) " + msg; + } + + this.debug(msg, instanceId, exc); + + this._lastMeasureTime = new Date().getTime(); +} + + +/** + * Logs the current stack trace as a debug message. + */ +qx.Proto.printStackTrace = function() { + try { + forced_exception.go; + } catch (exc) { + this.debug("Current stack trace", "", exc); + } +} + + +/** + * Returns the logger of a class. + * + * @param clazz {Function} The class of which to return the logger. + */ +qx.Class.getClassLogger = function(clazz) { + var logger = clazz._logger; + if (logger == null) { + // Get the parent logger + var classname = clazz.classname; + var splits = classname.split("."); + var currPackage = window; + var currPackageName = ""; + var parentLogger = qx.dev.log.Logger.ROOT_LOGGER; + for (var i = 0; i < splits.length - 1; i++) { + currPackage = currPackage[splits[i]]; + currPackageName += ((i != 0) ? "." : "") + splits[i]; + + if (currPackage._logger == null) { + // This package has no logger -> Create one + currPackage._logger = new qx.dev.log.Logger(currPackageName, parentLogger); + } + parentLogger = currPackage._logger; + } + + // Create the class logger + logger = new qx.dev.log.Logger(classname, parentLogger); + clazz._logger = logger; + } + return logger; +} + + +/** {int} The current indent. */ +qx.Class._indent = 0; + +/** + * (int) The ALL level has the lowest possible rank and is intended to turn on + * all logging. + */ +qx.Class.LEVEL_ALL = 0; + +/** + * (int) The DEBUG Level designates fine-grained informational events that are + * most useful to debug an application. + */ +qx.Class.LEVEL_DEBUG = 200; + +/** + * (int) The INFO level designates informational messages that highlight the + * progress of the application at coarse-grained level. + */ +qx.Class.LEVEL_INFO = 500; + +/** {int} The WARN level designates potentially harmful situations. */ +qx.Class.LEVEL_WARN = 600; + +/** + * (int) The ERROR level designates error events that might still allow the + * application to continue running. + */ +qx.Class.LEVEL_ERROR = 700; + +/** + * (int) The FATAL level designates very severe error events that will + * presumably lead the application to abort. + */ +qx.Class.LEVEL_FATAL = 800; + +/** + * (int) The OFF has the highest possible rank and is intended to turn off + * logging. + */ +qx.Class.LEVEL_OFF = 1000; + + +/** + * {Logger} The root logger. This is the root of the logger tree. All loggers + * should be a child or grand child of this root logger. + * <p> + * This logger logs by default everything greater than level INFO to a log + * window. + */ +qx.Class.ROOT_LOGGER = new qx.dev.log.Logger("root", null); +qx.Class.ROOT_LOGGER.setMinLevel(qx.dev.log.Logger.LEVEL_DEBUG); +qx.Class.ROOT_LOGGER.addAppender(new qx.dev.log.WindowAppender); diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/RingBufferAppender.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/RingBufferAppender.js new file mode 100644 index 0000000000..32d24c6636 --- /dev/null +++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/RingBufferAppender.js @@ -0,0 +1,122 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2006 by STZ-IDA, Germany, http://www.stz-ida.de + + License: + LGPL 2.1: http://www.gnu.org/licenses/lgpl.html + + Authors: + * Carsten Lergenmueller (carstenl) + +************************************************************************ */ + +/* ************************************************************************ + +#module(log) + +************************************************************************ */ + +/** + * An appender that writes all messages to a memory container. The messages + * can be retrieved later, f. i. when an error dialog pops up and the question + * arises what actions have caused the error. + * + */ +qx.OO.defineClass("qx.dev.log.RingBufferAppender", qx.dev.log.Appender, +function() { + qx.dev.log.Appender.call(this); + + this._history = []; + this._nextIndexToStoreTo = 0; + this._appenderToFormatStrings = null; +}); + + +/** + * The maximum number of messages to hold. If null the number of messages is not + * limited. Warning: Changing this property will clear the events logged so far. + */ +qx.OO.addProperty({ name:"maxMessages", type:"number", defaultValue:50 }); + +qx.Proto._modifyMaxMessages = function(propValue, propOldValue, propData){ + this._history = []; + this._nextIndexToStoreTo = 0; +}; + +// overridden +qx.Proto.appendLogEvent = function(evt) { + var maxMessages = this.getMaxMessages(); + if (this._history.length < maxMessages){ + this._history.push(evt); + } else { + this._history[this._nextIndexToStoreTo++] = evt; + if (this._nextIndexToStoreTo >= maxMessages){ + this._nextIndexToStoreTo = 0; + } + } +}; + +/** + * Returns log events which have been logged previously. + * + * @param count {int} The number of events to retreive. If there are more events than the + * given count, the oldest ones will not be returned. + * @return {array} array of stored log events + */ +qx.Proto.retrieveLogEvents = function(count) { + if (count > this._history.length){ + count = this._history.length; + } + + var indexOfYoungestElementInHistory + = this._history.length == this.getMaxMessages() ? this._nextIndexToStoreTo - 1 + : this._history.length - 1; + var startIndex = indexOfYoungestElementInHistory - count + 1; + if (startIndex < 0){ + startIndex += this._history.length; + } + + var result; + if (startIndex <= indexOfYoungestElementInHistory){ + result = this._history.slice(startIndex, indexOfYoungestElementInHistory + 1); + } else { + result = this._history.slice(startIndex, this._history.length).concat( + this._history.slice(0, indexOfYoungestElementInHistory + 1) + ); + } + return result; +}; + +/** + * Returns a string holding the information of log events which have been logged previously. + * + * @param count {int} The number of events to retreive. If there are more events than the + * given count, the oldest ones will not be returned. + * @return {string} string + */ +qx.Proto.formatLogEvents = function(count) { + if (this._appenderToFormatStrings == null){ + this._appenderToFormatStrings = new qx.dev.log.Appender(); + } + + var events = this.retrieveLogEvents(count); + var string = ""; + for(var idx=0; idx < events.length; idx++) { + string += this._appenderToFormatStrings.formatLogEvent(events[idx]) + "\n"; + } + return string; +}; + +// overridden +qx.Proto.dispose = function() { + if (this.getDisposed()) { + return true; + } + + return qx.dev.log.Appender.prototype.dispose.call(this); +}; diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/WindowAppender.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/WindowAppender.js new file mode 100644 index 0000000000..e62efe4c37 --- /dev/null +++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/dev/log/WindowAppender.js @@ -0,0 +1,225 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2006 by STZ-IDA, Germany, http://www.stz-ida.de + + License: + LGPL 2.1: http://www.gnu.org/licenses/lgpl.html + + Authors: + * Til Schneider (til132) + +************************************************************************ */ + +/* ************************************************************************ + +#module(core) +#module(log) + +************************************************************************ */ + +/** + * An appender that writes all messages to a log window. + * <p> + * This class does not depend on qooxdoo widgets, so it also works when there + * are problems with widgets or when the widgets are not yet initialized. + * + * @param name {string ? "qx_log"} the name of the log window. + */ +qx.OO.defineClass("qx.dev.log.WindowAppender", qx.dev.log.Appender, +function(name) { + qx.dev.log.Appender.call(this); + + this._id = qx.dev.log.WindowAppender.register(this); + this._name = (name == null) ? "qx_log" : name; + + this._logWindowOpened = false; +}); + + +/** + * The maximum number of messages to show. If null the number of messages is not + * limited. + */ +qx.OO.addProperty({ name:"maxMessages", type:"number", defaultValue:500 }); + +/** Whether the window should appear under the main window. */ +qx.OO.addProperty({ name:"popUnder", type:"boolean", defaultValue:false, allowNull:false }); + + +/** + * Creates and opens the log window if it doesn't alread exist. + */ +qx.Proto.openWindow = function() { + if (this._logWindowOpened) { + // The window is already open -> Nothing to do + return; + } + + // Open the logger window + var winWidth = 600; + var winHeight = 350; + var winLeft = window.screen.width - winWidth; + var winTop = window.screen.height - winHeight; + var params = "toolbar=no,scrollbars=yes,resizable=yes," + + "width=" + winWidth + ",height=" + winHeight + + ",left=" + winLeft + ",top=" + winTop; + + // NOTE: In window.open the browser will process the event queue. + // Which means that other log events may arrive during this time. + // The log window is then in an inconsistent state, because the + // this._logElem is not created yet. These events will be added to the + // this._logEventQueue and logged after this._logElem is created. + this._logWindow = window.open("", this._name, params); + + if (!this._logWindow || this._logWindow.closed) + { + if (!this._popupBlockerWarning) { + alert("Couldn't open debug window. Please disable your popup blocker!"); + } + + this._popupBlockerWarning = true; + return; + } + + // Seems to be OK now. + this._popupBlockerWarning = false; + + // Store that window is open + this._logWindowOpened = true; + + if (this.getPopUnder()) { + this._logWindow.blur(); + window.focus(); + } + + var logDocument = this._logWindow.document; + // NOTE: We have to use a static onunload handler, because an onunload + // that is set later using DOM is ignored completely. + // (at least in Firefox, but maybe in IE, too) + logDocument.open(); + logDocument.write("<html><head><title>" + this._name + "</title></head>" + + '<body onload="qx = opener.qx;" onunload="try{qx.dev.log.WindowAppender._registeredAppenders[' + this._id + '].closeWindow()}catch(e){}">' + + '<pre id="log" wrap="wrap" style="font-size:11"></pre></body></html>'); + logDocument.close(); + + this._logElem = logDocument.getElementById("log"); + + // Log the events from the queue + if (this._logEventQueue != null) { + for (var i = 0; i < this._logEventQueue.length; i++) { + this.appendLogEvent(this._logEventQueue[i]); + } + this._logEventQueue = null; + } +} + + +/** + * Closes the log window. + */ +qx.Proto.closeWindow = function() { + if (this._logWindow != null) { + this._logWindow.close(); + this._logWindow = null; + this._logElem = null; + this._logWindowOpened = false; + } +} + + +// overridden +qx.Proto.appendLogEvent = function(evt) { + if (!this._logWindowOpened) { + this._logEventQueue = []; + this._logEventQueue.push(evt); + + this.openWindow(); + + // Popup-Blocker was active! + if (!this._logWindowOpened) { + return; + } + } else if (this._logElem == null) { + // The window is currenlty opening, but not yet finished + // -> Put the event in the queue + this._logEventQueue.push(evt); + } else { + var divElem = this._logWindow.document.createElement("div"); + if (evt.level == qx.dev.log.Logger.LEVEL_ERROR) { + divElem.style.backgroundColor = "#FFEEEE"; + } else if (evt.level == qx.dev.log.Logger.LEVEL_DEBUG) { + divElem.style.color = "gray"; + } + divElem.innerHTML = this.formatLogEvent(evt).replace(/&/g, "&") + .replace(/</g, "<").replace(/ /g, "  ").replace(/[\n]/g, "<br>"); + this._logElem.appendChild(divElem); + + while (this._logElem.childNodes.length > this.getMaxMessages()) { + this._logElem.removeChild(this._logElem.firstChild); + + if (this._removedMessageCount == null) { + this._removedMessageCount = 1; + } else { + this._removedMessageCount++; + } + } + + if (this._removedMessageCount != null) { + this._logElem.firstChild.innerHTML = "(" + this._removedMessageCount + + " messages removed)"; + } + + // Scroll to bottom + this._logWindow.scrollTo(0, this._logElem.offsetHeight); + } +} + + +// overridden +qx.Proto.dispose = function() { + if (this.getDisposed()) { + return true; + } + + this.closeWindow(); + + return qx.dev.log.Appender.prototype.dispose.call(this); +} + + +qx.Class._nextId = 1; +qx.Class._registeredAppenders = {}; + + +/** + * Registers a WindowAppender. This is used by the WindowAppender internally. + * You don't have to call this. + * + * @param appender {WindowAppender} the WindowAppender to register. + * @return {int} the ID. + */ +qx.Class.register = function(appender) { + var WindowAppender = qx.dev.log.WindowAppender; + + var id = WindowAppender._nextId++; + WindowAppender._registeredAppenders[id] = appender; + + return id; +} + + +/** + * Returns a prviously registered WindowAppender. + * + * @param id {int} the ID of the wanted WindowAppender. + * @return {WindowAppender} the WindowAppender or null if no + * WindowAppender with this ID is registered. + */ +qx.Class.getAppender = function(id) { + return qx.dev.log.WindowAppender._registeredAppenders[id]; +} |