Merge remote-tracking branch 'origin/master'

This commit is contained in:
Jürg Lehni 2011-05-26 21:00:05 +01:00
commit 397d3676ed
41 changed files with 6667 additions and 933 deletions

View file

@ -27,6 +27,10 @@ function Link() {
return this;
}
this.toSymbol = function(alias) {
if(/\[\]$/.test(alias)) {
alias = alias.replace(/\[\]$/, '');
this.text = 'array of ' + alias + ' objects';
}
if (defined(alias)) this.alias = new String(alias);
return this;
}
@ -141,11 +145,15 @@ Link.prototype._makeSymbolLink = function(alias) {
var linkText= this.text || alias;
var link = {linkPath: linkPath, linkText: linkText, linkInner: (this.innerName? "#"+this.innerName : "")};
var link = {linkPath: linkPath, linkText: linkText.replace(/^#/, ''), linkInner: (this.innerName? "#" + this.innerName : "")};
if (typeof JSDOC.PluginManager != "undefined") {
JSDOC.PluginManager.run("onSymbolLink", link);
}
if (/^[A-Z].+\#/.test(link.linkText)) {
link.linkText = link.linkText.charAt(0).toLowerCase() + link.linkText.slice(1);
link.linkText = link.linkText.replace(/#/g, '.');
}
return "<a href=\""+link.linkPath+link.linkInner+"\""+target+">"+link.linkText+"</a>";
}

View file

@ -37,7 +37,6 @@ JSDOC.DocComment.prototype.parse = function(/**String*/comment) {
if (RegExp.$1) this.meta = RegExp.$1;
if (RegExp.$2) this.src = RegExp.$2;
}
if (typeof JSDOC.PluginManager != "undefined") {
JSDOC.PluginManager.run("onDocCommentSrc", this);
}
@ -50,7 +49,6 @@ JSDOC.DocComment.prototype.parse = function(/**String*/comment) {
this.src
.split(/(^|[\r\n])\s*@/)
.filter(function($){return $.match(/\S/)});
/**
The tags found in the comment.
@type JSDOC.DocTag[]

View file

@ -36,7 +36,6 @@ JSDOC.DocTag.prototype.parse = function(src) {
if (JSDOC.PluginManager) {
JSDOC.PluginManager.run("onDocTagSynonym", this);
}
src = this.nibbleType(src);
// only some tags are allowed to have names.
@ -122,7 +121,7 @@ JSDOC.DocTag.prototype.nibbleTitle = function(src) {
JSDOC.DocTag.prototype.nibbleType = function(src) {
if (typeof src != "string") throw "src must be a string not "+(typeof src);
if (src.match(/^\s*\{/)) {
if (src.match(/^\s*\{[^@]/)) {
var typeRange = src.balance("{", "}");
if (typeRange[1] == -1) {
throw "Malformed comment tag ignored. Tag type requires an opening { and a closing }: "+src;

View file

@ -0,0 +1,11 @@
JSDOC.PluginManager.registerPlugin(
"JSDOC.operator",
{
onSymbol: function(symbol) {
var operators = symbol.comment.getTag('operator');
if (operators.length) {
symbol.operator = operators[0].desc;
}
}
}
);

View file

@ -25,7 +25,7 @@
<for each="item" in="data">
<div>
<h2>{+new Link().toSrc(item.alias).withText(item.name)+}</h2>
<if test="item.desc">{+resolveLinks(item.desc)+}</if>
<if test="item.desc">{+processInlineTags(item.desc)+}</if>
<dl>
<if test="item.author">
<dt class="heading">Author:</dt>

View file

@ -1,521 +1,110 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset={+IO.encoding+}" />
<meta name="generator" content="JsDoc Toolkit" />
{! Link.base = "../"; /* all generated links will be relative to this */ !}
<title>JsDoc Reference - {+data.alias+}</title>
{! data.classId = data.alias.toLowerCase() !}
{!
var ownProperties = data.properties.filter(function($){return $.memberOf == data.alias && !$.isNamespace && !$.isStatic});
var staticProperties = data.properties.filter(function($){return $.memberOf == data.alias && !$.isNamespace && $.isStatic});
var ownMethods = data.methods.filter(function($){return $.memberOf == data.alias && !$.isNamespace && !$.isStatic && !$.isOperator});
var staticMethods = data.methods.filter(function($){return $.memberOf == data.alias && !$.isNamespace && $.isStatic && !$.isOperator});
var operatorMethods = data.methods.filter(function($){return $.memberOf == data.alias && !$.isNamespace && !$.isStatic && $.isOperator});
if (operatorMethods.length) {
var operators = {};
for (var i = 0, l = operatorMethods.length; i < l; i++) {
var operator = operatorMethods[i];
var name = operator.name.replace(/\^[0-9]$/, '');
if (!operators[name])
operators[name] = [];
operators[name].push(operator);
}
}
!}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>{+data.alias+}</title>
<base target="classFrame">
<link rel="stylesheet" href="../resources/css/reference.css" type="text/css">
<link rel="stylesheet" href="../resources/css/style.css" type="text/css">
<link rel="stylesheet" href="../resources/css/lighter.css" type="text/css">
<script src="../resources/js/bootstrap.js" type="text/javascript"></script>
<script src="../resources/js/lighter.js" type="text/javascript"></script>
<script src="../resources/js/reference.js" type="text/javascript"></script>
</head>
<body class="reference">
<div class="reference-class">
<h1>{+data.alias+}</h1>
<p>{+processInlineTags(data.classDesc)+}</p>
</div>
<!-- ============================== constructors ========================= -->
<div class="reference-members"><h2>Constructors</h2>
<div id="{+data.classId+}" class="member">
<div id="{+data.classId+}-link" class="member-link">
<a name="{+data.classId+}" href="#" onClick="return toggleMember('{+data.classId+}', false);"><tt><b>{+ data.alias +}</b>{+ makeSignature(data.params) +}</tt></a>
</div>
<div id="{+data.classId+}-description" class="member-description hidden">
<div class="member-header">
<div class="member-title">
<div class="member-link">
<a href="#" onClick="return toggleMember('{+data.classId+}', false);"><tt><b>{+ data.alias +}</b>{+ makeSignature(data.params) +}</tt></a>
</div>
</div>
<div class="member-close"><input type="button" value="Close" onClick="toggleMember('{+data.classId+}', false);"></div>
<div class="clear"></div>
</div>
<div class="member-text"><p>{+processInlineTags(data.desc)+}</p>
<if test="data.example.length">
<for each="example" in="data.example">
<pre>{+example+}</pre>
</for>
</if>
{+ templates.parameters.process(data) +}
<if test="data.returns.length">
<ul><b>Returns:</b>
<li>
<for each="item" in="data.returns">
<dd>{+((item.type)?"<span class=\"light fixedFont\">{"+(new Link().toSymbol(item.type))+"}</span> " : "")+}{+processInlineTags(item.desc)+}</dd>
</for>
</li>
</ul>
</if>
</div>
</div>
</div>
</div>
<style type="text/css">
{+include("static/default.css")+}
</style>
</head>
<!-- ============================== properties ========================= -->
<if test="defined(operators)">
<div class="reference-members"><h2>Operators</h2>
<for each="member" in="operators">
{+ templates.operators.process(member) +}
</for>
</div>
</if>
<body>
<!-- ============================== header ================================= -->
<!-- begin static/header.html -->
{+include("static/header.html")+}
<!-- end static/header.html -->
<!-- ============================== classes index ============================ -->
<div id="index">
<!-- begin publish.classesIndex -->
{+publish.classesIndex+}
<!-- end publish.classesIndex -->
</div>
<div id="content">
<!-- ============================== class title ============================ -->
<h1 class="classTitle">
{!
var classType = "";
if (data.isBuiltin()) {
classType += "Built-In ";
}
if (data.isNamespace) {
if (data.is('FUNCTION')) {
classType += "Function ";
}
classType += "Namespace ";
}
!}
{+classType+}{+data.alias+}
</h1>
<!-- ============================== class summary ========================== -->
<p class="description">
<if test="data.version"><br />Version
{+ data.version +}.<br />
</if>
<if test="data.augments.length"><br />Extends
{+
data.augments
.map(
function($) { return new Link().toSymbol($); }
)
.join(", ")
+}.<br />
</if>
{+resolveLinks(data.classDesc)+}
</p>
<!-- ============================== inherited properties summary ===================== -->
<if test="data.properties.length">
{! var ownProperties = data.properties.filter(function($){return $.memberOf == data.alias && !$.isNamespace}); !}
<if test="data.inheritsFrom.length">
<dl class="inheritsList">
{!
var borrowedMembers = data.properties.filter(function($) {return $.memberOf != data.alias});
var contributers = [];
borrowedMembers.map(function($) {if (contributers.indexOf($.memberOf) < 0) contributers.push($.memberOf)});
for (var i = 0, l = contributers.length; i < l; i++) {
output +=
"<dt>Functions inherited from "+new Link().toSymbol(contributers[i])+": </dt>"
+
"<dd>" +
borrowedMembers
.filter(
function($) { return $.memberOf == contributers[i] }
)
.map(
function($) { return new Link().toSymbol($.alias).withText($.name) }
)
.join(", ")
+
"</dd>";
}
!}
</dl>
</if>
</if>
<!-- ============================== inherited methods summary ======================== -->
<if test="data.methods.length">
{! var ownMethods = data.methods.filter(function($){return $.memberOf == data.alias && !$.isNamespace}); !}
<if test="data.inheritsFrom.length">
<dl class="inheritsList">
{!
var borrowedMembers = data.methods.filter(function($) {return $.memberOf != data.alias});
var contributers = [];
borrowedMembers.map(function($) {if (contributers.indexOf($.memberOf) < 0) contributers.push($.memberOf)});
for (var i = 0, l = contributers.length; i < l; i++) {
output +=
"<dt>Methods inherited from "+new Link().toSymbol(contributers[i])+": </dt>"
+
"<dd>" +
borrowedMembers
.filter(
function($) { return $.memberOf == contributers[i] }
)
.map(
function($) { return new Link().toSymbol($.alias).withText($.name) }
)
.join(", ")
+
"</dd>";
}
!}
</dl>
</if>
</if>
<!-- ============================== inherited events summary ======================== -->
<if test="data.events.length">
{! var ownEvents = data.events.filter(function($){return $.memberOf == data.alias && !$.isNamespace}); !}
<if test="data.inheritsFrom.length">
<dl class="inheritsList">
{!
var borrowedMembers = data.events.filter(function($) {return $.memberOf != data.alias});
var contributers = [];
borrowedMembers.map(function($) {if (contributers.indexOf($.memberOf) < 0) contributers.push($.memberOf)});
for (var i = 0, l = contributers.length; i < l; i++) {
output +=
"<dt>Events inherited from "+new Link().toSymbol(contributers[i])+": </dt>"
+
"<dd>" +
borrowedMembers
.filter(
function($) { return $.memberOf == contributers[i] }
)
.map(
function($) { return new Link().toSymbol($.alias).withText($.name) }
)
.join(", ")
+
"</dd>";
}
!}
</dl>
</if>
</if>
<!-- ============================== constructor details ==================== -->
<if test="!data.isBuiltin() && (data.isNamespace || data.is('CONSTRUCTOR'))">
<div class="details"><a name="constructor"> </a>
<div class="sectionTitle">
Constructor
</div>
<div class="fixedFont">{!
if (data.isPrivate) output += "&lt;private&gt; ";
if (data.isInner) output += "&lt;inner&gt; ";
!}
<b>{+ data.alias +}</b><if test="classType != 'Namespace '">{+ makeSignature(data.params) +}</if>
</div>
<div class="description">
{+resolveLinks(data.desc)+}
<if test="data.author"><br /><i>Author: </i>{+data.author+}.</if>
</div>
<if test="data.example.length">
<for each="example" in="data.example">
<pre class="code">{+example+}</pre>
</for>
</if>
<if test="data.params.length">
<dl class="detailList">
<dt class="heading">Parameters:</dt>
<for each="item" in="data.params">
<dt>
<b>{+item.name+}</b> {+((item.type)?""+("<span class=\"light fixedFont\">{"+(new Link().toSymbol(item.type)+"}</span> ")) : "")+}
<if test="item.isOptional"><i>Optional<if test="item.defaultValue">, Default: {+item.defaultValue+}</if></i></if>
</dt>
<dd>{+resolveLinks(item.desc)+}</dd>
</for>
</dl>
</if>
<if test="data.deprecated">
<dl class="detailList">
<dt class="heading">Deprecated:</dt>
<dt>
{+resolveLinks(data.deprecated)+}
</dt>
</dl>
</if>
<if test="data.since">
<dl class="detailList">
<dt class="heading">Since:</dt>
<dd>{+ data.since +}</dd>
</dl>
</if>
<if test="data.exceptions.length">
<dl class="detailList">
<dt class="heading">Throws:</dt>
<for each="item" in="data.exceptions">
<dt>
{+((item.type)?"<span class=\"light fixedFont\">{"+(new Link().toSymbol(item.type))+"}</span> " : "")+} <b>{+item.name+}</b>
</dt>
<dd>{+resolveLinks(item.desc)+}</dd>
</for>
</dl>
</if>
<if test="data.returns.length">
<dl class="detailList">
<dt class="heading">Returns:</dt>
<for each="item" in="data.returns">
<dd>{+((item.type)?"<span class=\"light fixedFont\">{"+(new Link().toSymbol(item.type))+"}</span> " : "")+}{+resolveLinks(item.desc)+}</dd>
</for>
</dl>
</if>
<if test="data.requires.length">
<dl class="detailList">
<dt class="heading">Requires:</dt>
<for each="item" in="data.requires">
<dd>{+ new Link().toSymbol(item) +}</dd>
</for>
</dl>
</if>
<if test="data.see.length">
<dl class="detailList">
<dt class="heading">See:</dt>
<for each="item" in="data.see">
<dd>{+ new Link().toSymbol(item) +}</dd>
</for>
</dl>
</if>
</div>
</if>
<!-- ============================== field details ========================== -->
<if test="defined(ownProperties) && ownProperties.length">
<div class="sectionTitle">
Properties
</div>
<for each="member" in="ownProperties">
<a name="{+Link.symbolNameToLinkName(member)+}"> </a>
<div class="fixedFont">{!
if (member.isPrivate) output += "&lt;private&gt; ";
if (member.isInner) output += "&lt;inner&gt; ";
// if (member.isStatic) output += "&lt;static&gt; ";
if (member.isConstant) output += "&lt;constant&gt; ";
!}
<if test="member.isStatic && member.memberOf != '_global_'"><span class="light">{+member.memberOf+}.</span></if><b>{+member.name+}</b>
<if test="member.type"><span class="light">{{+new Link().toSymbol(member.type)+}}</span></if>
</div>
<div class="description">
{+resolveLinks(member.desc)+}
<if test="member.srcFile != data.srcFile">
<br />
<i>Defined in: </i> {+new Link().toSrc(member.srcFile)+}.
</if>
<if test="member.author"><br /><i>Author: </i>{+member.author+}.</if>
</div>
<if test="member.example.length">
<for each="example" in="member.example">
<pre class="code">{+example+}</pre>
</for>
</if>
<if test="member.deprecated">
<dl class="detailList">
<dt class="heading">Deprecated:</dt>
<dt>
{+ resolveLinks(member.deprecated) +}
</dt>
</dl>
</if>
<if test="member.since">
<dl class="detailList">
<dt class="heading">Since:</dt>
<dd>{+ member.since +}</dd>
</dl>
</if>
<if test="member.see.length">
<dl class="detailList">
<dt class="heading">See:</dt>
<for each="item" in="member.see">
<dd>{+ new Link().toSymbol(item) +}</dd>
</for>
</dl>
</if>
<if test="member.defaultValue">
<dl class="detailList">
<dt class="heading">Default Value:</dt>
<dd>
{+resolveLinks(member.defaultValue)+}
</dd>
</dl>
</if>
<if test="!$member_last"><hr /></if>
</for>
</if>
<if test="defined(ownProperties) && ownProperties.length">
<div class="reference-members"><h2>Properties</h2>
<for each="member" in="ownProperties">
{+ templates.property.process(member) +}
</for>
</div>
</if>
<!-- ============================== method details ========================= -->
<if test="defined(ownMethods) && ownMethods.length">
<div class="sectionTitle">
Functions
</div>
<for each="member" in="ownMethods">
<a name="{+Link.symbolNameToLinkName(member)+}"> </a>
<div class="fixedFont">
{!
if (member.isPrivate) output += "&lt;private&gt; ";
if (member.isInner) output += "&lt;inner&gt; ";
// if (member.isStatic) output += "&lt;static&gt; ";
!}
<if test="member.isStatic && member.memberOf != '_global_'"><span class="light">{+member.memberOf+}.</span></if><b>{+member.name.replace(/\^\d+$/, '')+}</b>{+makeSignature(member.params)+}
</div>
<div class="description">
{+resolveLinks(member.desc)+}
<if test="member.author"><br /><i>Author: </i>{+member.author+}.</if>
</div>
<if test="member.example.length">
<for each="example" in="member.example">
<pre class="code">{+example+}</pre>
</for>
</if>
<if test="member.params.length">
<dl class="detailList">
<dt class="heading">Parameters:</dt>
<for each="item" in="member.params">
<dt>
<b>{+item.name+}</b>{+((item.type)?"<span class=\"light fixedFont\">{"+(new Link().toSymbol(item.type))+"}</span> " : "")+}
<if test="item.isOptional"><i>Optional<if test="item.defaultValue">, Default: {+item.defaultValue+}</if></i></if>
</dt>
<dd>{+resolveLinks(item.desc)+}</dd>
</for>
</dl>
</if>
<if test="member.deprecated">
<dl class="detailList">
<dt class="heading">Deprecated:</dt>
<dt>
{+ resolveLinks(member.deprecated) +}
</dt>
</dl>
</if>
<if test="member.since">
<dl class="detailList">
<dt class="heading">Since:</dt>
<dd>{+ member.since +}</dd>
</dl>
</dl>
</if>
<if test="member.exceptions.length">
<dl class="detailList">
<dt class="heading">Throws:</dt>
<for each="item" in="member.exceptions">
<dt>
{+((item.type)?"<span class=\"light fixedFont\">{"+(new Link().toSymbol(item.type))+"}</span> " : "")+} <b>{+item.name+}</b>
</dt>
<dd>{+resolveLinks(item.desc)+}</dd>
</for>
</dl>
</if>
<if test="member.returns.length">
<dl class="detailList">
<dt class="heading">Returns:</dt>
<for each="item" in="member.returns">
<dd>{+((item.type)?"<span class=\"light fixedFont\">{"+(new Link().toSymbol(item.type))+"}</span> " : "")+}{+resolveLinks(item.desc)+}</dd>
</for>
</dl>
</if>
<if test="member.requires.length">
<dl class="detailList">
<dt class="heading">Requires:</dt>
<for each="item" in="member.requires">
<dd>{+ resolveLinks(item) +}</dd>
</for>
</dl>
</if>
<if test="member.see.length">
<dl class="detailList">
<dt class="heading">See:</dt>
<for each="item" in="member.see">
<dd>{+ new Link().toSymbol(item) +}</dd>
</for>
</dl>
</if>
<if test="!$member_last"><hr /></if>
</for>
<if test="defined(ownMethods) && ownMethods.length">
<div class="reference-members"><h2>Functions</h2>
<for each="member" in="ownMethods">
{! member.desc = processGroupTitle(member.desc, member) !}
<if test="defined(member.groupTitle)">
<h3>{+member.groupTitle+}</h3>
</if>
<!-- ============================== event details ========================= -->
<if test="defined(ownEvents) && ownEvents.length">
<div class="sectionTitle">
Event Detail
</div>
<for each="member" in="ownEvents">
<a name="{+Link.symbolNameToLinkName(member)+}"> </a>
<div class="fixedFont">{!
if (member.isPrivate) output += "&lt;private&gt; ";
if (member.isInner) output += "&lt;inner&gt; ";
// if (member.isStatic) output += "&lt;static&gt; ";
!}
<if test="member.type"><span class="light">{{+new Link().toSymbol(member.type)+}}</span></if>
<if test="member.isStatic && member.memberOf != '_global_'"><span class="light">{+member.memberOf+}.</span></if><b>{+member.name+}</b>{+makeSignature(member.params)+}
</div>
<div class="description">
{+resolveLinks(member.desc)+}
<if test="member.srcFile != data.srcFile">
<br />
<i>Defined in: </i> {+new Link().toSrc(member.srcFile)+}.
</if>
<if test="member.author"><br /><i>Author: </i>{+member.author+}.</if>
</div>
<if test="member.example.length">
<for each="example" in="member.example">
<pre class="code">{+example+}</pre>
</for>
</if>
<if test="member.params.length">
<dl class="detailList">
<dt class="heading">Parameters:</dt>
<for each="item" in="member.params">
<dt>
<b>{+item.name+}</b>{+((item.type)?"<span class=\"light fixedFont\">{"+(new Link().toSymbol(item.type))+"}</span> " : "")+}
<if test="item.isOptional"><i>Optional<if test="item.defaultValue">, Default: {+item.defaultValue+}</if></i></if>
</dt>
<dd>{+ resolveLinks(item.desc) +}</dd>
</for>
</dl>
</if>
<if test="member.deprecated">
<dl class="detailList">
<dt class="heading">Deprecated:</dt>
<dt>
{+ resolveLinks(member.deprecated) +}
</dt>
</dl>
</if>
<if test="member.since">
<dl class="detailList">
<dt class="heading">Since:</dt>
<dd>{+ member.since +}</dd>
</dl>
</dl>
</if>
<if test="member.exceptions.length">
<dl class="detailList">
<dt class="heading">Throws:</dt>
<for each="item" in="member.exceptions">
<dt>
{+((item.type)?"<span class=\"light fixedFont\">{"+(new Link().toSymbol(item.type))+"}</span> " : "")+} <b>{+item.name+}</b>
</dt>
<dd>{+ resolveLinks(item.desc) +}</dd>
</for>
</dl>
</if>
<if test="member.returns.length">
<dl class="detailList">
<dt class="heading">Returns:</dt>
<for each="item" in="member.returns">
<dd>{+((item.type)?"<span class=\"light fixedFont\">{"+(new Link().toSymbol(item.type))+"}</span> " : "")+}{+resolveLinks(item.desc)+}</dd>
</for>
</dl>
</if>
<if test="member.requires.length">
<dl class="detailList">
<dt class="heading">Requires:</dt>
<for each="item" in="member.requires">
<dd>{+ resolveLinks(item) +}</dd>
</for>
</dl>
</if>
<if test="member.see.length">
<dl class="detailList">
<dt class="heading">See:</dt>
<for each="item" in="member.see">
<dd>{+ new Link().toSymbol(item) +}</dd>
</for>
</dl>
</if>
{+ templates.method.process(member) +}
</for>
</div>
</if>
<if test="defined(staticMethods) && staticMethods.length">
<div class="reference-members"><h2>Static Functions</h2>
<for each="member" in="staticMethods">
{+ templates.method.process(member) +}
</for>
</div>
</if>
<if test="!$member_last"><hr /></if>
</for>
</if>
<hr />
</div>
<!-- ============================== footer ================================= -->
<div class="fineprint" style="clear:both">
<if test="JSDOC.opt.D.copyright">&copy;{+JSDOC.opt.D.copyright+}<br /></if>
Documentation generated by <a href="http://code.google.com/p/jsdoc-toolkit/" target="_blank">JsDoc Toolkit</a> {+JSDOC.VERSION+} on {+new Date()+}
</div>
</body>
</html>
</body>

View file

@ -0,0 +1,29 @@
Point
Rectangle
Size
Matrix
Color
GrayColor
RGBColor
GradientColor
Item
PathItem
Path
CompoundPath
TextItem
PointText
Raster
Group
Layer
PlacedItem
Symbol
Project
ProjectView
Segment
Curve
PathStyle
CharacterStyle
ParagraphStyle
Gradient
GradientStop
Symbol

View file

@ -0,0 +1,6 @@
<if test="data.example.length">
<for each="example" in="data.example">
<p>Sample code:</p>
<pre>{+example+}</pre>
</for>
</if>

View file

@ -25,7 +25,7 @@
<for each="thisClass" in="data">
<div>
<h2>{+(new Link().toSymbol(thisClass.alias))+}</h2>
{+resolveLinks(summarize(thisClass.classDesc))+}
{+processInlineTags(summarize(thisClass.classDesc))+}
</div>
<hr />
</for>

View file

@ -0,0 +1,43 @@
{!
var memberId = Helpers.getSymbolId(data);
var functionTitle = '<b>' + data.name.replace(/\^\d+$/, '') + '</b>' + makeSignature(data.params);
if (data.isStatic)
functionTitle = '<b>' + data.memberOf + '.</b>' + functionTitle;
!}
<div id="{+ memberId +}" class="member">
<div id="{+ memberId +}-link" class="member-link">
<a name="{+ memberId +}" href="#" onClick="return toggleMember('{+ memberId +}', false);"><tt>{+ functionTitle +}</tt></a>
</div>
<div id="{+ memberId +}-description" class="member-description hidden">
<div class="member-header">
<div class="member-title">
<div class="member-link">
<a href="#" onClick="return toggleMember('{+ memberId +}', false);"><tt>{+ functionTitle +}</tt></a>
</div>
</div>
<div class="member-close"><input type="button" value="Close" onClick="toggleMember('{+ memberId +}', false);"></div>
<div class="clear"></div>
</div>
<div class="member-text"><p>{+processInlineTags(data.desc)+}</p>
{+ new JSDOC.JsPlate(publish.conf.templatesDir+"examples.tmpl").process(data) +}
{+ new JSDOC.JsPlate(publish.conf.templatesDir+"parameters.tmpl").process(data) +}
<if test="data.returns.length">
<ul><b>Returns:</b>
<for each="item" in="data.returns">
<li>
<tt><if test="defined(item.type)">{+ new Link().toSymbol(item.type) +}<if test="item.desc">&nbsp;&mdash;&nbsp;</if></if>{+processInlineTags(item.desc)+}</tt>
</li>
</for>
</ul>
</if>
<if test="data.see.length">
<p><b>See also:</b>
<for each="item" in="data.see">
<tt>{+ new Link().toSymbol(item) +}</tt>
</for>
</p>
</if>
</div>
</div>
</div>

View file

@ -0,0 +1,52 @@
{!
var operatorCount = 0;
var operatorTitle = [];
for (var i = 0, l = data.length; i < l; i++) {
var type = data[i].params[0].type;
type = type.charAt(0).toUpperCase() + type.slice(1);
operatorTitle.push('<tt><b>' + Operator.getOperator(data[i]) + '</b> ' + type + '</tt>');
}
operatorTitle = operatorTitle.join(', ');
!}
<for each="operator" in="data">
{!
var type = operator.params[0].type;
type = type.charAt(0).toUpperCase() + type.slice(1);
var functionTitle = '<b>' + Operator.getOperator(operator) + '</b> ' + type;
!}
<if test="operatorCount == 0">
{!
var memberId = operator.name.toLowerCase().replace(/\^[0-9]$/,'');
!}
<div id="{+ memberId +}" class="member">
<div id="{+ memberId +}-link" class="member-link">
<a name="{+ memberId +}" href="#" onClick="return toggleMember('{+ memberId +}', false);"><tt>{+ operatorTitle +}</tt></a>
</div>
<div id="{+ memberId +}-description" class="member-description hidden">
</if>
<div class="member-header">
<div class="member-title">
<div class="member-link">
<a href="#" onClick="return toggleMember('{+ memberId +}', false);"><tt>{+ functionTitle +}</tt></a>
</div>
</div>
<div class="member-close"><input type="button" value="Close" onClick="toggleMember('{+ memberId +}', false);"></div>
<div class="clear"></div>
</div>
<if test="operator.type">
<div class="member-text"><p>{+processInlineTags(operator.desc)+}</p>
{+ new JSDOC.JsPlate(publish.conf.templatesDir+"examples.tmpl").process(operator) +}
<ul><b>Returns:</b>
<for each="item" in="operator.returns">
<li>
<tt><if test="defined(item.type)">{+ new Link().toSymbol(item.type) +}&nbsp;&mdash;&nbsp;</if>{+processInlineTags(item.desc)+}</tt>
</li>
</for>
</ul></div>
</if>
<if test="operatorCount == data.length - 1">
</div>
</div>
</if>
{! operatorCount++; !}
</for>

View file

@ -0,0 +1,11 @@
<if test="data.params.length">
<ul><b>Parameters:</b>
<for each="parameter" in="data.params">
<li>
<tt>{+ parameter.name +}: </tt>
{+ new Link().toSymbol(parameter.type) +}
<if test="parameter.defaultValue">&mdash;&nbsp;optional, default: <tt>{+parameter.defaultValue+}</tt></if>
</li>
</for>
</ul>
</if>

View file

@ -0,0 +1,45 @@
{!
data.desc = processGroupTitle(data.desc, data);
var memberId = Helpers.getSymbolId(data);
var title = '<b>' + data.name.replace(/\^\d+$/, '') + '</b>';
if (data.isStatic)
title = '<b>' + data.memberOf + '.</b>' + title;
!}
<if test="defined(data.groupTitle)">
<h3>{+data.groupTitle+}</h3>
</if>
<div id="{+ memberId +}" class="member">
<div id="{+ memberId +}-link" class="member-link">
<a name="{+ memberId +}" href="#" onClick="return toggleMember('{+ memberId +}', false);"><tt>{+ title +}</tt></a>
</div>
<div id="{+ memberId +}-description" class="member-description hidden">
<div class="member-header">
<div class="member-title">
<div class="member-link">
<a href="#" onClick="return toggleMember('{+ memberId +}', false);"><tt>{+ title +}</tt></a>
</div>
</div>
<div class="member-close"><input type="button" value="Close" onClick="toggleMember('{+ memberId +}', false);"></div>
<div class="clear"></div>
</div>
<if test="data.type">
<div class="member-text"><p>
{+processInlineTags(data.desc)+}<if test="data.readOnly"> Read only.</if></p>
{+ new JSDOC.JsPlate(publish.conf.templatesDir+"examples.tmpl").process(data) +}
<if test="data.defaultValue">
<ul><b>Default:</b>
<li>
<tt>{+data.defaultValue+}</tt>
</li>
</ul>
</if>
<ul><b>Type:</b>
<li>
<tt>{+new Link().toSymbol(data.type)+}</tt>
</li>
</ul></div>
</if>
</div>
</div>

View file

@ -1,11 +1,73 @@
var templates;
var Operator = new function() {
var operators = {
add: '+', subtract: '-', multiply: '*', divide: '/', equals: '==',
modulo: '%'
};
var operatorNames = {
add: 'Addition', subtract: 'Subtraction', multiply: 'Multiplication',
divide: 'Division', equals: 'Comparison', modulo: 'Modulo'
};
var operatorClasses = {
Point: true,
Size: true
};
return {
isOperator: function(symbol) {
// As a convention, only add non static bean properties to
// the documentation. static properties are all supposed to
// be uppercae and constants.
if (symbol.operator == 'none')
print(!(symbol.operator && symbol.operator != 'none'));
return symbol.params.length == 1 && !symbol.isStatic && (
/^(add|subtract|multiply|divide|modulo)(\^[0-9])*$/.test(symbol.name)
&& (symbol.operator != 'none')
) || ( // equals
symbol.name == 'equals'
&& symbol.returns.length && symbol.returns[0].type == 'boolean'
);
},
getOperator: function(symbol) {
return operators[symbol.name.replace(/\^[0-9]$/,'')];
}
}
}
var Helpers = {
getSymbolId: function(symbol) {
var id = [symbol.name.toLowerCase().replace(/[\^][0-9]/g, '')];
if (symbol.params) {
for (var i = 0, l = symbol.params.length; i < l; i++) {
var param = symbol.params[i];
if (!param.isOptional)
id.push(param.name);
}
}
return id.join('-');
}
};
/** Called automatically by JsDoc Toolkit. */
function publish(symbolSet) {
publish.conf = { // trailing slash expected for dirs
ext: ".html",
outDir: JSDOC.opt.d || SYS.pwd+"../out/jsdoc/",
ext: ".html",
outDir: JSDOC.opt.d || SYS.pwd+"../out/jsdoc/",
templatesDir: JSDOC.opt.t || SYS.pwd+"../templates/jsdoc/",
symbolsDir: "symbols/",
srcDir: "symbols/src/"
srcDir: "symbols/src/"
};
templates = {
_class: new JSDOC.JsPlate(publish.conf.templatesDir + "class.tmpl"),
method: new JSDOC.JsPlate(publish.conf.templatesDir + "method.tmpl"),
property: new JSDOC.JsPlate(publish.conf.templatesDir + "property.tmpl"),
parameters: new JSDOC.JsPlate(publish.conf.templatesDir + "parameters.tmpl"),
operators: new JSDOC.JsPlate(publish.conf.templatesDir + "operators.tmpl"),
examples: new JSDOC.JsPlate(publish.conf.templatesDir + "examples.tmpl")
};
// is source output is suppressed, just display the links to the source file
@ -14,10 +76,13 @@ function publish(symbolSet) {
return "&lt;"+srcFilePath+"&gt;";
}
}
// Copy over the static files
copyDirectory(
new java.io.File(publish.conf.templatesDir + 'resources/'),
new java.io.File(publish.conf.outDir + 'resources/')
);
// create the folders and subfolders to hold the output
IO.mkPath((publish.conf.outDir+"symbols/src").split("/"));
// used to allow Link to check the details of things being linked to
Link.symbolSet = symbolSet;
@ -41,11 +106,11 @@ function publish(symbolSet) {
// create the hilited source code files
var files = JSDOC.opt.srcFiles;
for (var i = 0, l = files.length; i < l; i++) {
var file = files[i];
var srcDir = publish.conf.outDir + "symbols/src/";
for (var i = 0, l = files.length; i < l; i++) {
var file = files[i];
var srcDir = publish.conf.outDir + "symbols/src/";
makeSrcFile(file, srcDir);
}
}
// get a list of all the classes in the symbolset
var classes = symbols.filter(isaClass).sort(makeSortby("alias"));
@ -76,6 +141,10 @@ function publish(symbolSet) {
symbol.events = symbol.getEvents(); // 1 order matters
symbol.methods = symbol.getMethods(); // 2
for (var j = 0; j < symbol.methods.length; j++) {
var method = symbol.methods[j];
method.isOperator = Operator.isOperator(method);
}
Link.currentSymbol= symbol;
var output = "";
@ -173,29 +242,80 @@ function makeSrcFile(path, srcDir, name) {
/** Build output for displaying function parameters. */
function makeSignature(params) {
if (!params) return "()";
var signature = "("
+
params.filter(
var postString = '';
var first = true;
params = params.filter(
function($) {
return $.name.indexOf(".") == -1; // don't show config params in signature
}
).map(
function($) {
return $.name;
);
var signature = '';
var postSignature = '';
for (var i = 0, l = params.length; i < l; i++) {
var param = params[i];
if (param.isOptional) {
signature += '[';
postSignature += ']';
}
).join(", ")
+
")";
return signature;
if (i > 0)
signature += ', ';
signature += param.name;
}
return '(' + signature + postSignature + ')';
}
/** Find symbol {@link ...} strings in text and turn into html links */
function resolveLinks(str, from) {
str = str.replace(/\{@link ([^} ]+) ?\}/gi,
function(match, symbolName) {
return new Link().toSymbol(symbolName);
}
);
function processGroupTitle(str, symbol) {
// if (/grouptitle/.test(str))
// print('yeah');
// print(str);
var groupTitle = str.match(/\{@grouptitle ([^}]+)\}/);
if (groupTitle) {
symbol.groupTitle = groupTitle[1];
str = str.replace(/\{@grouptitle ([^}]+)\}/, '');
}
return str;
}
function processInlineTags(str) {
// {@link ...} -> html links
str = str.replace(/\{@link ([^} ]+) ?\}/gi,
function(match, symbolName) {
return new Link().toSymbol(symbolName.replace(/[\^]/g, '-'));
}
);
// {@code ...} -> code blocks
str = str.replace(/\{@code[\s]([^}]+)\}/gi,
function(match, code) {
return '<tt>' + code + '</tt>';
}
);
return str;
}
function copyStatic(dir) {
var dir = publish.conf.templatesDir + 'resources/';
}
function copyDirectory(sourceLocation, targetLocation) {
if (sourceLocation.isDirectory()) {
if (!targetLocation.exists()) {
targetLocation.mkdir();
}
var children = sourceLocation.list();
for (var i = 0; i < children.length; i++) {
copyDirectory(new File(sourceLocation, children[i]),
new File(targetLocation, children[i]));
}
} else {
// Copy the file with FileChannels:
targetLocation.createNewFile();
var src = new java.io.FileInputStream(sourceLocation).getChannel();
var dst = new java.io.FileOutputStream(targetLocation).getChannel();
var amount = dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 B

View file

@ -0,0 +1,115 @@
ol.ltLighter {
font-family: Menlo, Consolas, "Vera Mono", monospace;
font-size: 10px;
overflow: auto;
white-space: pre-wrap;
word-wrap: break-word;
}
ol.ltLighter {
white-space: -moz-pre-wrap;
}
ol.ltLighter {
white-space: -pre-wrap;
}
ol.ltLighter {
white-space: -o-pre-wrap;
}
ol.ltLighter {
color: #939393;
list-style: decimal-leading-zero;
background-color: #f4f4f4;
margin-left: 0;
padding-left: 0;
}
ol.ltLighter li {
border-left: 1px solid #939393;
padding: 0 3px 0 10px;
background-color: #fff;
padding-left: 15px;
padding-right: 5px;
margin-left: 40px;
}
ol.ltLighter .ltfirst {
padding-top: 5px;
}
ol.ltLighter .ltlast {
padding-bottom: 5px;
}
ol.ltLighter .alt {
background-color: #edf5fc;
}
ol.ltLighter span {
color: black;
font-size: 11px;
}
ol.ltLighter .de1 {
}
ol.ltLighter .de2 {
}
ol.ltLighter .kw1 {
color: #1b609a;
}
ol.ltLighter .kw2 {
color: #9a6f1b;
}
ol.ltLighter .kw3 {
color: #784e0c;
}
ol.ltLighter .co1 {
color: #888888;
}
ol.ltLighter .co2 {
color: #888888;
}
ol.ltLighter .st0 {
color: #489a1b;
}
ol.ltLighter .st1 {
color: #70483d;
}
ol.ltLighter .st2 {
color: #70483d;
}
ol.ltLighter .nu0 {
color: #70483d;
}
ol.ltLighter .me0 {
color: #666666;
}
ol.ltLighter .br0 {
color: #444444;
}
ol.ltLighter .sy0 {
color: #444444;
}
ol.ltLighter .es0 {
color: #444444;
}
ol.ltLighter .re0 {
color: #784e0c;
}

View file

@ -0,0 +1,120 @@
.reference h1, .reference h2, .reference h3 {
font-size: 12px;
font-weight: normal;
display: block;
margin: 0 0 16px 0;
height: 17px; /* -1 for border */
border-bottom: 1px solid black;
}
.reference h3 {
margin-top: 16px;
border-bottom-style: dotted;
}
.reference a tt, .reference a tt b {
padding-bottom: 1px;
}
.reference pre {
margin: 0 0 18px 0;
}
.reference ul {
margin: 0;
padding: 0;
list-style: none;
}
.reference-list ul, .reference-inherited ul {
margin-left: 16px;
}
.reference hr {
border: none;
border-bottom: 1px dotted #000;
}
.reference-packages {
margin-left: 0px;
}
.reference-packages h2, .reference-packages h3, .reference-packages hr {
margin: 10px 0 10px 0;
}
.reference-packages .first h2 {
margin-top: 0;
}
* html .reference-packages img {
margin-top: 5px;
}
.reference-packages li {
list-style: none;
list-style-image: none; /* needed for ie 6 */
}
.reference-end {
height: 600px;
}
.reference-members {
padding-bottom: 16px;
}
.member-group-text {
margin-bottom: 16px;
}
.member-description {
border: 1px solid #999;
/* .member-header defines border-top for operator lists */
border-top: 0;
margin: 16px 0 16px 0;
}
.member-header {
border-top: 1px solid #999;
padding: 10px;
}
.member-title {
float: left;
width: 400px;
}
.member-close {
float: right;
}
.member-text {
border-top: 1px dashed #999;
padding: 10px 10px 0 10px;
}
.member-link {
text-indent: -30px;
padding-left: 30px;
}
.reference-inherited ul li {
text-indent: -30px;
padding-left: 30px;
}
.member-text ul {
padding-bottom: 10px;
}
ul.package-classes {
padding-bottom: 4px;
}
.package-classes li {
margin-left: 10px;
}
.package-classes li h2 {
margin-left: -10px;
}

View file

@ -0,0 +1,85 @@
body {
background: #fff;
margin: 16px;
font-family: "Lucida Grande", Geneva, Verdana, Arial, sans-serif;
font-size: 12px;
line-height: 19px;
color: #000;
max-width: 540px;
}
select, input, textarea {
font-family: "Lucida Grande", Geneva, Verdana, Arial, sans-serif;
font-size: 11px;
margin: 0;
color: #000;
}
p tt, pre {
font-family: Menlo, Consolas, "Vera Mono", monospace;
font-size: 11px;
line-height: 19px;
}
a {
color: #000;
text-decoration: none;
padding-bottom: 1px;
border-bottom: 1px solid #000;
}
img {
border: 0;
}
a:hover {
background: #e5e5e5;
}
p {
margin: 0 0 19px 0;
}
ul {
padding: 0;
margin: 0 0 19px 16px;
list-style: disc outside url(../assets/bullet.gif);
}
ol {
padding: 0;
margin: 0 0 19px 0;
}
.clear {
clear: both;
}
.hidden {
display: none;
}
.reference-packages, .reference-packages a {
color: #009dec;
border-bottom: 0px;
}
/* border-bottom color for headers and ruler */
.reference-packages h2, .reference-packages h3, .reference-packages hr {
border-color: #009dec;
}
.reference-packages a:hover {
background: #e3f4fc;
}
.reference h1 {
font-size: 18px;
font-weight: normal;
line-height: 24px;
border: none;
}
.footer {
margin-top: 20px;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,826 @@
/**
* Script:
* Fuel.js - Language definition engine for Lighter.js
*
* License:
* MIT-style license.
*
* Author:
* José Prado
*
* Copyright:
* Copyright (©) 2009 [Jose Prado](http://pradador.com/).
*
* Changelog:
* 2009/03/21 (1.0.0)
* - Initial Release
*
*/
Fuel = Base.extend(Callback, {
options: {
matchType: 'standard',
strict: false
},
language: '',
defaultFlame: 'standard',
patterns: new Hash(),
keywords: new Hash(),
rules: new Hash(),
delimiters: new Hash({
start: null,
end: null
}),
/************************
* Common Regex Rules
***********************/
common: {
slashComments: /(?:^|[^\\])\/\/.*$/gm, // Matches a C style single-line comment.
poundComments: /#.*$/gm, // Matches a Perl style single-line comment.
multiComments: /\/\*[\s\S]*?\*\//gm, // Matches a C style multi-line comment.
aposStrings: /'[^'\\]*(?:\\.[^'\\]*)*'/gm, // Matches a string enclosed by single quotes.
quotedStrings: /"[^"\\]*(?:\\.[^"\\]*)*"/gm, // Matches a string enclosed by double quotes.
strings: /'[^'\\]*(?:\\.[^'\\]*)*'|"[^"\\]*(?:\\.[^"\\]*)*"/gm, // Matches both.
properties: /\.([\w]+)\s*/gi, // Matches a property: .property style.
methodCalls: /\.([\w]+)\s*\(/gm, // Matches a method call: .methodName() style.
functionCalls: /\b([\w]+)\s*\(/gm, // Matches a function call: functionName() style.
brackets: /\{|\}|\(|\)|\[|\]/g, // Matches any of the common brackets.
numbers: /\b((?:(\d+)?\.)?[0-9]+|0x[0-9A-F]+)\b/gi // Matches integers, decimals, hexadecimals.
},
/************************
* Fuel Constructor
***********************/
initialize: function(lighter, flame, options, wicks) {
this.setOptions(options);
this.wicks = wicks || [];
// Set Lighter/Fuel/Flame relationship.
this.lighter = lighter;
this.flame = flame;
// Set builder object for matchType.
this.builder = new Hash({
'standard': this.findMatches,
'lazy': this.findMatchesLazy
});
// Add delimiter rules if not in strict mode
if (!options.strict) {
if (this.delimiters.start) this.addFuel('delimBeg', this.delimiters.start, 'de1');
if (this.delimiters.end) this.addFuel('delimEnd', this.delimiters.end, 'de2');
}
// Set Keyword Rules from this.keywords object.
this.keywords.each(function(keywordSet, ruleName) {
if (keywordSet.csv != '') {
this.addFuel(ruleName, this.csvToRegExp(keywordSet.csv, "g"), keywordSet.alias);
}
}, this);
// Set Rules from this.patterns object.
this.patterns.each(function(regex, ruleName) {
this.addFuel(ruleName, regex.pattern, regex.alias);
}, this);
/** Process source code based on match type. */
var codeBeg = 0,
codeEnd = lighter.code.length,
codeSeg = '',
delim = this.delimiters,
matches = [],
match = null,
endMatch = null;
if (!options.strict) {
// Find matches through the complete source code.
matches.append(this.builder[options.matchType].bind(this, lighter.code)());
} else if (delim.start && delim.end) {
// Find areas between language delimiters and find matches there.
while ((match = delim.start.exec(lighter.code)) != null ) {
delim.end.lastIndex = delim.start.lastIndex;
if ((endMatch = delim.end.exec(lighter.code)) != null ) {
matches.push(new Wick(match[0], 'de1', match.index));
codeBeg = delim.start.lastIndex;
codeEnd = endMatch.index-1;
codeSeg = lighter.code.substring(codeBeg, codeEnd);
matches.append(this.builder[options.matchType].bind(this, codeSeg, codeBeg)());
matches.push(new Wick(endMatch[0], 'de2', endMatch.index));
}
}
}
this.wicks = matches;
},
/************************
* Regex Helper methods.
***********************/
addFuel: function(fuelName, RegEx, className) {
this.rules[fuelName] = RegEx;
this.flame.addAlias(fuelName, className);
},
csvToRegExp: function(csv, mod) {return new RegExp('\\b(' + csv.replace(/,\s*/g, '|') + ')\\b', mod);},
delimitedRegex: function(beg, esc, end, mod, suffix) {
beg = beg.escapeRegExp();
if (esc) esc = esc.escapeRegExp();
end = (end) ? end.escapeRegExp() : beg;
pat = (esc) ? beg+"[^"+end+esc+'\\n]*(?:'+esc+'.[^'+end+esc+'\\n]*)*'+end : beg+"[^"+end+'\\n]*'+end;
return new RegExp(pat+(suffix || ''), mod || '');
},
strictRegex: function() {
var regex = '(';
for (var i = 0; i < arguments.length; i++) {
regex += arguments[i].escapeRegExp();
regex += (i < arguments.length - 1) ? '|' : '';
}
regex += ')';
return new RegExp(regex, "gim");
},
/************************
* Match finding Methods
***********************/
findMatches: function(code, offset) {
var wicks = [],
startIndex = 0,
matchIndex = code.length
insertIndex = 0,
match = null,
type = null,
newWick = null,
rule = null,
rules = {},
currentMatch = null,
futureMatch = null;
offset = (offset) ? offset : 0;
this.rules.each(function(regex, rule) {
rules[rule] = {pattern: regex, enabled: true, lastIndex: 0};
}, this);
while(startIndex < code.length) {
matchIndex = code.length;
match = null;
for (rule in rules) {
rules[rule].pattern.lastIndex = startIndex;
currentMatch = rules[rule].pattern.exec(code);
if (currentMatch === null) {
delete rules[rule];
} else {
if (currentMatch.index < matchIndex) {
match = currentMatch;
type = rule;
matchIndex = currentMatch.index;
} else if (currentMatch.index == matchIndex && match[0].length < currentMatch[0].length) {
match = currentMatch;
type = rule;
matchIndex = currentMatch.index;
}
rules[rule].nextIndex = rules[rule].pattern.lastIndex - currentMatch[0].length;
}
}
if (match != null) {
index = (match[1] && match[0].contains(match[1])) ? match.index + match[0].indexOf(match[1]) : match.index;
newWick = new Wick(match[1] || match[0], type, index+offset);
wicks.push(newWick);
futureMatch = rules[type].pattern.exec(code);
if (!futureMatch) {
rules[type].nextIndex = code.length;
} else {
rules[type].nextIndex = rules[type].pattern.lastIndex - futureMatch[0].length;
}
var min = code.length;
for (rule in rules) {
if (rules[rule].nextIndex < min) {
min = rules[rule].nextIndex;
}
}
startIndex = Math.max(min, newWick.end - offset);
} else {
break;
}
}
return wicks;
},
findMatchesLazy: function(code, offset) {
var wicks = this.wicks,
match = null
index = 0;
offset = (offset) ? offset : 0;
this.rules.each(function(regex, rule) {
while ((match = regex.exec(code)) != null) {
index = (match[1] && match[0].contains(match[1])) ? match.index + match[0].indexOf(match[1]) : match.index;
wicks.push(new Wick(match[1] || match[0], rule, index + offset));
}
}, this);
return this.purgeWicks(wicks);
},
purgeWicks: function(wicks) {
wicks = wicks.sort(this.compareWicks);
for (var i = 0, j = 0; i < wicks.length; i++) {
if (wicks[i] == null) continue;
for (j = i+1; j < wicks.length && wicks[i] != null; j++) {
if (wicks[j] == null) {continue;}
else if (wicks[j].isBeyond(wicks[i])) {break;}
else if (wicks[j].overlaps(wicks[i])) {wicks[i] = null;}
else if (wicks[i].contains(wicks[j])) {wicks[j] = null;}
}
}
return wicks.compact();
},
compareWicks: function(wick1, wick2) {return wick1.index - wick2.index;}
});
Fuel.standard = Fuel.extend({initialize: function(lighter, flame, options, wicks) {this.base(lighter, flame, options, wicks);}});
var Wick = Base.extend({
initialize: function(match, type, index) {
this.text = match;
this.type = type;
this.index = index;
this.length = this.text.length;
this.end = this.index + this.length;
},
contains: function(wick) {return (wick.index >= this.index && wick.index < this.end);},
isBeyond: function(wick) {return (this.index >= wick.end);},
overlaps: function(wick) {return (this.index == wick.index && this.length > wick.length);},
toString: function() {return this.index+' - '+this.text+' - '+this.end;}
});
/**
* Script:
* Flame.js - Theme Engine for Lighter.js
*
* License:
* MIT-style license.
*
* Author:
* José Prado
*
* Copyright:
* Copyright (©) 2009 [Jose Prado](http://pradador.com/).
*
* Changelog:
* 2009/03/21 (1.0.0)
* - Initial Release
*
*/
Flame = Base.extend(Callback, {
shortName: 'lt',
aliases: new Hash(),
containers: new Hash(),
common: new Hash(),
layout: new Hash(),
styles: new Hash(),
defaultStyles: new Hash({
de1: new Hash({}), // Beginning delimiter
de2: new Hash({}), // End delimiter
kw1: new Hash({'color': '#1b609a'}), // Keywords 1
kw2: new Hash({'color': '#9a6f1b'}), // Keywords 2
kw3: new Hash({'color': '#784e0c'}), // Keywords 3
co1: new Hash({'color': '#888888'}), // Comments 1
co2: new Hash({'color': '#888888'}), // Comments 2
st0: new Hash({'color': '#489a1b'}), // Strings 1
st1: new Hash({'color': '#70483d'}), // Strings 2
st2: new Hash({'color': '#70483d'}), // Strings 3
nu0: new Hash({'color': '#70483d'}), // Numbers
me0: new Hash({'color': '#666666'}), // Methods and Functions
br0: new Hash({'color': '#444444'}), // Brackets
sy0: new Hash({'color': '#444444'}), // Symbols
es0: new Hash({'color': '#444444'}), // Escape characters
re0: new Hash({'color': '#784e0c'}) // Regular Expressions
}),
defaultCommon: new Hash({
'font-family': 'Monaco, Courier, Monospace',
'font-size': '10px',
'overflow': 'auto',
'white-space': 'pre-wrap',
'word-wrap': 'break-word'
}),
layout: new Hash({
'numColor': new Hash({'background-color': '#f2f2f2'}),
'lineColor': new Hash({'background-color': '#fff'}),
'numStyles': new Hash({
'color': '#939393',
'font-size': '10px',
'list-style': 'decimal-leading-zero'
}),
'lineStyles': new Hash({
'border-top': '1px solid #fff',
'border-bottom': '1px solid #fff',
'border-left': '1px solid #939393',
'padding': '0 3px 0 10px'
}),
'alt': new Hash({
'border-top': '1px solid #eee',
'border-bottom': '1px solid #eee',
'background-color': '#F4F8FC'
}),
'top': new Hash({'padding-top': '5px'}),
'right': new Hash({'padding-right': '5px'}),
'bottom': new Hash({'padding-bottom': '5px'}),
'left': new Hash({'padding-left': '15px'}),
'codeStyles': new Hash({
'color': 'black',
'font-size': '10px'
})
}),
fixes: new Hash({
'div': new Hash({
'div': new Hash({
'clear': 'left',
'overflow': 'auto'
}),
'num': new Hash({
'display': 'block',
'float': 'left',
'text-align': 'center',
'width': '30px'
}),
'line': new Hash({
'display': 'block',
'margin-left': '30px'
})
}),
'table': new Hash({
'num': new Hash({
'text-align': 'center',
'width': '30px'
})
}),
'ol': new Hash({
'ol': new Hash({
'margin-left': '0',
'padding-left': '0'
}),
'li': new Hash({
'margin-left': '40px'
})
})
}),
initialize: function(lighter, fuel) {
// Setup Lighter/Fuel/Flame trio.
this.lighter = lighter;
this.fuel = fuel;
this.common.merge(this.defaultCommon);
this.styles.merge(this.defaultStyles);
// Map general styles to their aliases.
this.defaultStyles.each(function(style, key) {
this.addAlias(key);
}, this);
// Insert stylesheet if in jsStyles mode
if (this.lighter.options.jsStyles && !$('style#lighter_' + this.lighter.options.mode)) this.injectTag();
},
addAlias: function(key, alias) {this.aliases[key] = alias || key;},
injectTag: function() {
var type = this.lighter.options.mode,
pfx = type+'.'+this.shortName+this.lighter.name,
pfx2 = pfx+' .'+this.shortName,
numCSS = this.layout['numStyles'].merge(this.layout.numColor),
lineCSS = this.layout['lineStyles'].merge(this.layout.lineColor),
padCSS = this.layout.left.merge(this.layout.right);
this.styleTag = new HtmlElement("style").setProperty('type','text/css').setProperty('id', 'lighter_' + this.lighter.options.mode).insertInside(DomElement.get('head'));
// General white-space/font styles.
this.addCSS(pfx, this.common);
this.addCSS(pfx, new Hash({'white-space': '-moz-pre-wrap'}));
this.addCSS(pfx, new Hash({'white-space': '-pre-wrap'}));
this.addCSS(pfx, new Hash({'white-space': '-o-pre-wrap'}));
// Case specific styles for a common general style.
switch (type) {
case "pre":
padCSS = padCSS.merge(this.layout.top).merge(this.layout.bottom);
this.addCSS(pfx, this.layout.lineColor.merge(padCSS));
this.addCSS(pfx+' span', this.layout['codeStyles']);
break;
case "ol":
this.addCSS(pfx, numCSS.merge(this.fixes['ol']['ol']));
this.addCSS(pfx+' li', lineCSS.merge(padCSS).merge(this.fixes['ol']['li']));
this.addCSS(pfx2+'first', this.layout['top']);
this.addCSS(pfx2+'last', this.layout['bottom']);
this.addCSS(pfx+' .alt', this.layout['alt']);
this.addCSS(pfx+' span', this.layout['codeStyles']);
break;
case "div":
numCSS = numCSS.merge(this.fixes.div.num),
lineCSS = lineCSS.merge(this.fixes.div.line);
this.addCSS(pfx2+'num', numCSS);
this.addCSS(pfx2+'line', lineCSS.merge(padCSS));
this.addCSS(pfx+' div', this.fixes['div']['div'].merge(this.layout.numColor));
this.addCSS(pfx2+'first', this.layout['top']);
this.addCSS(pfx2+'last', this.layout['bottom']);
this.addCSS(pfx+' .alt', this.layout['alt']);
this.addCSS(pfx+' span', this.layout['codeStyles']);
break;
case "table":
numCSS = numCSS.merge(this.fixes['table']['num']);
this.addCSS(pfx2+'num', numCSS);
this.addCSS(pfx2+'line', lineCSS.merge(padCSS));
this.addCSS(pfx2+'first', this.layout['top']);
this.addCSS(pfx2+'last', this.layout['bottom']);
this.addCSS(pfx+' .alt', this.layout['alt']);
this.addCSS(pfx+' span', this.layout['codeStyles']);
break;
default:
}
this.styles.each(function(stylesHash, styleName) {
this.addCSS(pfx+' .'+styleName, stylesHash);
}, this);
},
/** Code from horseweapon @ http://forum.mootools.net/viewtopic.php?id=6635 */
addCSS: function(styleName, stylesHash) {
//Create the CSS rule
var newStyle = "\n" + styleName + " {\n";
if (stylesHash) {
stylesHash.each(function(value, attribute) {
newStyle += "\t" + attribute + ": " + value + ";\n";
});
}
newStyle += "}\n";
// Insert into Flame's styleTag.
if (browserTrident()) {
this.styleTag.$.styleSheet.cssText += newStyle;
} else {
this.styleTag.appendText(newStyle);
}
}
});
Flame.standard = Flame.extend({initialize: function(lighter, fuel) {this.base(lighter, fuel);}});
/**
* Script:
* Flame.js - Syntax Highlighter written in MooTools.
*
* License:
* MIT-style license.
*
* Author:
* José Prado
*
* Copyright:
* Copyright (©) 2009 [Jose Prado](http://pradador.com/).
*
* Changelog:
* 2009/03/21 (1.0.0)
* - Initial Release
*
*/
var $time = Date.now || function(){
return +new Date;
};
function browserTrident(){
return (!window.ActiveXObject) ? false : ((window.XMLHttpRequest) ? 5 : 4);
}
Lighter = Base.extend(Callback, {
name: 'Lighter',
options: {
altLines: '', // Pseudo-selector enabled.
container: null,
editable: false,
flame: 'standard',
fuel: 'standard',
id: null,
indent: -1,
jsStyles: true,
matchType: "standard",
mode: "pre",
path: "./",
strict: false
},
/***************************
* Lighter Initialization
**************************/
initialize: function(codeblock, options) {
this.setOptions(options);
options = this.options;
this.id = options.id || this.name + '_' + $time();
this.codeblock = $(codeblock)
this.code = codeblock.get('html').chop().replace(/&lt;/gim, '<').replace(/&gt;/gim, '>').replace(/&amp;/gim, '&');
if(this.options.container)
this.container = $(this.options.container);
// Indent code if user option is set.
if (options.indent > -1) this.code = this.code.tabToSpaces(options.indent);
// Set builder options.
this.builder = new Hash({
'pre': this.createLighter.bind(this),
'ol': this.createLighterWithLines.bind(this, ['ol'], ['li']),
'div': this.createLighterWithLines.bind(this, ['div'], ['div', 'span'], true, 'span'),
'table': this.createLighterWithLines.bind(this, ['table', 'tbody'], ['tr', 'td'], true, 'td')
});
// Extract fuel/flame names. Precedence: className > options > standard.
var ff = this.codeblock.get('class').split(':');
if (!ff[0]) ff[0] = this.options.fuel;
if (!ff[1]) ff[1] = this.options.flame;
// Load flame to start chain of loads.
this.loadFlameSrc(ff);
},
loadFlameSrc: function(ff) {
if (!$check(Flame[ff[1]])) {
var flameScript = Asset.script(this.options.path+'Flames/Flame.'+ff[1]+'.js', {
onLoad: function() {
this.loadFlame(ff);
}.bind(this),
onError: function() {
ff[1] = 'standard';
this.loadFlame(ff)
}.bind(this)
});
} else {
this.loadFlame(ff);
}
},
loadFlame: function(ff) {
this.flame = new Flame[ff[1]](this);
this.loadFuelSrc(ff);
},
loadFuelSrc: function(ff) {
if (!$check(Fuel[ff[0]])) {
var fuelScript = Asset.script(this.options.path+'Fuels/Fuel.'+ff[0]+'.js', {
onLoad: function() {
this.loadFuel(ff);
}.bind(this),
onError: function() {
ff[0] = 'standard';
this.loadFuel(ff);
}.bind(this)
});
} else {
this.loadFuel(ff);
}
},
loadFuel: function(ff) {
this.fuel = new Fuel[ff[0]](this, this.flame, {
matchType: this.options.matchType,
strict: this.options.strict
});
this.light();
},
light: function() {
// Build highlighted code object.
this.element = this.toElement();
// Insert lighter in the right spot.
if (this.container) {
this.container.removeChildren();
this.element.insertInside(this.container);
} else {
this.codeblock.setStyle('display', 'none');
this.codeblock.injectAfter(this.element);
}
},
/***************************
* Lighter creation methods
**************************/
createLighter: function() {
var lighter = new HtmlElement('pre', {'class': this.flame.shortName + this.name}),
pointer = 0;
// If no matches were found, insert code plain text.
if (this.fuel.wicks[0] == undefined) {
lighter.appendText(this.code);
} else {
this.fuel.wicks.each(function(match) {
lighter.appendText(this.code.substring(pointer, match.index));
this.insertAndKeepEl(lighter, match.text, match.type);
pointer = match.index + match.text.length;
}, this);
// Add last unmatched code segment if it exists.
if (pointer < this.code.length) {
lighter.appendText(this.code.substring(pointer, this.code.length));
}
}
//lighter.set('text', lighter.get('html'));
return lighter;
},
createLighterWithLines: function(parent, child, addLines, lineType) {
var lighter = new HtmlElement(parent[0], {'class': this.flame.shortName + this.name, 'id': this.id}),
newLine = new HtmlElement(child[0]),
lineNum = 1,
pointer = 0,
text = null;
if (parent[0] == "table") lighter.set("cellpadding", 0).set("cellspacing", 0).set("border", 0);
if (parent[1]) lighter = new HtmlElement(parent[1]).insertInside(lighter);
if (child[1]) newLine = new HtmlElement(child[1]).insertInside(newLine);
newLine.addClass(this.flame.shortName + 'line');
if (addLines) lineNum = this.insertLineNum(newLine, lineNum, lineType);
this.fuel.wicks.each(function(match) {
// Create and insert un-matched source code bits.
if (pointer != match.index) {
text = this.code.substring(pointer, match.index).split('\n');
for (var i = 0; i < text.length; i++) {
if (i < text.length - 1) {
if (text[i] == '') text[i] = ' ';
newLine = this.insertAndMakeEl(newLine, lighter, text[i], child);
if (addLines) lineNum = this.insertLineNum(newLine, lineNum, lineType);
} else {
this.insertAndKeepEl(newLine, text[i]);
}
}
}
// Create and insert matched symbol.
text = match.text.split('\n');
for (i = 0; i < text.length; i++) {
if (i < text.length - 1) {
newLine = this.insertAndMakeEl(newLine, lighter, text[i], child, match.type);
if (addLines) lineNum = this.insertLineNum(newLine, lineNum, lineType);
} else {
this.insertAndKeepEl(newLine, text[i], match.type);
}
}
pointer = match.end;
}, this);
// Add last unmatched code segment if it exists.
if (pointer <= this.code.length) {
text = this.code.substring(pointer, this.code.length).split('\n');
for (var i = 0; i < text.length; i++) {
newLine = this.insertAndMakeEl(newLine, lighter, text[i], child);
if (addLines) lineNum = this.insertLineNum(newLine, lineNum, lineType);
}
}
// Add alternate line styles based on pseudo-selector.
if (this.options.altLines !== '') {
if (this.options.altLines == 'hover') {
lighter.getElements('.'+this.flame.shortName+'line').addEvents({
'mouseover': function() {this.toggleClass('alt');},
'mouseout': function() {this.toggleClass('alt');}
});
} else {
if (child[1]) {
lighter.getChildren(':'+this.options.altLines).getElement('.'+this.flame.shortName+'line').addClass('alt');
} else {
lighter.getChildren(':'+this.options.altLines).addClass('alt');
}
}
}
// Add first/last line classes based on mode.
if (child[1]) {
lighter.getFirst().getChildren().addClass(this.flame.shortName+'first');
lighter.getLast().getChildren().addClass(this.flame.shortName+'last');
} else {
lighter.getFirst().addClass(this.flame.shortName+'first');
lighter.getLast().addClass(this.flame.shortName+'last');
}
if (parent[1]) lighter = lighter.getParent();
return lighter;
},
/** Helper function to insert new code segment into existing line. */
insertAndKeepEl: function(el, text, alias) {
if (text.length > 0) {
var span = new HtmlElement('span');
span.set('text', text);
if (alias) {span.addClass(this.flame.aliases[alias]);}
span.insertInside(el);
}
},
/** Helper function to insert new code segment into existing line and create new line. */
insertAndMakeEl: function(el, group, text, child, alias) {
this.insertAndKeepEl(el, text, alias);
if (child[1]) el = el.getParent();
el.insertInside(group);
var newLine = new HtmlElement(child[0]);
if (child[1]) newLine = new HtmlElement(child[1]).insertInside(newLine);
newLine.addClass(this.flame.shortName+'line');
return newLine;
},
/** Helper funciton to insert line number into line. */
insertLineNum: function(el, lineNum, lineType) {
var newNum = new HtmlElement(lineType, {
'text': lineNum++,
'class': this.flame.shortName+ 'num'
});
newNum.insertTop(el.getParent());
return lineNum;
},
/******************
* Element Methods
******************/
toElement: function() {
if (!this.element) {
this.element = this.builder[this.options.mode]();
if (this.options.editable) {this.element.set('contenteditable', 'true');}
}
return this.element;
},
replaces: function(element){
element = $(element, true);
element.parentNode.replaceChild(this.toElement(), element);
return this;
}
});
/** Element Native extensions */
HtmlElement.inject({
light: function(options) {
return new Lighter(this, options);
}
});
/** String Native extensions */
String.inject({
chop: function() {return this.replace(/(^\s*\n|\n\s*$)/gi, '');},
tabToSpaces: function(spaces) {
for (var i = 0, indent = ''; i < spaces; i++) {indent += ' ';}
return this.replace(/\t/g, indent);
}
});
/**
* Script:
* Fuel.js.js - JavaScript language file for Lighter.js
*
* License:
* MIT-style license.
*
* Author:
* José Prado
*
* Copyright:
* Copyright (©) 2009 [Jose Prado](http://pradador.com/).
*
* Changelog:
* 2009/03/21 (1.0.0)
* - Initial Release
*
*/
Fuel.js = Fuel.extend({
language: 'js',
initialize: function(lighter, flame, options) {
// Keywords Rule Set
this.keywords = new Hash({
commonKeywords: {
csv: "as, break, case, catch, continue, delete, do, else, eval, finally, for, if, in, is, instanceof, return, switch, this, throw, try, typeof, void, while, write, with",
alias: 'kw1'
},
langKeywords: {
csv: "class, const, default, debugger, export, extends, false, function, import, namespace, new, null, package, private, protected, public, super, true, use, var",
alias: 'kw2'
},
windowKeywords: {
csv: "alert, back, blur, close, confirm, focus, forward, home, navigate, onblur, onerror, onfocus, onload, onmove, onresize, onunload, open, print, prompt, scroll, status, stop",
alias: 'kw3'
}
});
// RegEx Rule Set
this.patterns = new Hash({
'slashComments': {pattern: this.common.slashComments, alias: 'co1'},
'multiComments': {pattern: this.common.multiComments, alias: 'co2'},
'strings': {pattern: this.common.strings, alias: 'st0'},
'methodCalls': {pattern: this.common.properties, alias: 'me0'},
'brackets': {pattern: this.common.brackets, alias: 'br0'},
'numbers': {pattern: /\b((([0-9]+)?\.)?[0-9_]+([e][-+]?[0-9]+)?|0x[A-F0-9]+)\b/gi, alias: 'nu0'},
'regex': {pattern: this.delimitedRegex("/", "\\", "/", "g", "[gimy]*"), alias: 're0'},
'symbols': {pattern: /\+|-|\*|\/|%|!|@|&|\||\^|\<|\>|=|,|\.|;|\?|:/g, alias: 'sy0'}
});
// Delimiters
this.delimiters = new Hash({
start: this.strictRegex('<script type="text/javascript">', '<script language="javascript">'),
end: this.strictRegex('</script>')
});
this.base(lighter, flame, options);
}
});

View file

@ -0,0 +1,72 @@
// This is identical with server sided code
var lighterSettings = {
altLines: 'hover',
indent: 4,
mode: 'ol',
fuel: 'js',
jsStyles: false
};
$document.addEvent('domready', function() {
var h = unescape(document.location.hash);
if (h) scrollToElement(h.substring(1));
var code = $$('.text pre, .reference-class pre');
if (code.length) {
code.light(lighterSettings).each(function(obj, i) {
var start =code[i].getProperty('start');
if (start)
obj.element.setProperty('start', start);
});
}
});
var lastMemberId = null;
function toggleMember(id, scrollTo) {
if (lastMemberId && lastMemberId != id) {
var prevId = lastMemberId;
lastMemberId = null;
toggleMember(prevId);
}
var link = $('#' + id + '-link');
if (link) {
var desc = $('#' + id + '-description');
var v = !link.hasClass('hidden');
lastMemberId = v && id;
link.modifyClass('hidden', v);
desc.modifyClass('hidden', !v);
if (!desc.code && v)
desc.code = $$('pre', desc).light(lighterSettings);
if (scrollTo)
scrollToMember(id);
return false;
}
return true;
}
function scrollToElement(id) {
var e = $('#' + id);
if (e) {
var offs = e.getOffset();
$window.setScrollOffset(offs);
if (e.hasClass('member'))
toggleMember(id);
} else {
document.location.hash = id;
}
}
function togglePackage(id, def) {
var e = $('#package-' + id);
if (e) {
var v = !e.hasClass('hidden');
e.modifyClass('hidden', v);
var img = document.images['arrow-' + id];
if (img) img.src = img.src.replace(/open|close/, v ? 'close' : 'open');
}
return false;
}
function toggleThumbnail(id, over) {
$('#' + id).modifyClass('hidden', over);
$('#' + id + '_over').modifyClass('hidden', !over);
}

View file

@ -98,6 +98,14 @@ var Point = this.Point = Base.extend({
return Point.create(this.x, this.y);
},
/**
* @return {string} A string representation of the point.
*/
toString: function() {
var format = Base.formatNumber;
return '{ x: ' + format(this.x) + ', y: ' + format(this.y) + ' }';
},
/**
* Returns the addition of the supplied value to both coordinates of
* the point as a new point.
@ -279,12 +287,23 @@ var Point = this.Point = Base.extend({
return Point.create(-this.x, -this.y);
},
/**
* Transforms the point by the matrix as a new point. The object itself
* is not modified!
*
* @param {Matrix} matrix
* @return {Point} the transformed point
*/
transform: function(matrix) {
return matrix._transformPoint(this);
},
/**
* {@grouptitle Distance & Length}
*
* Returns the distance between the point and another point.
*
* @param {Point} point
* @return {number}
*/
getDistance: function(point) {
@ -297,7 +316,7 @@ var Point = this.Point = Base.extend({
/**
* The length of the vector that is represented by this point's coordinates.
* Each point can be interpreted as a vector that points from the origin
* ({@code x = 0},{@code y = 0}) to the point's location.
* ({@code x = 0}, {@code y = 0}) to the point's location.
* Setting the length changes the location but keeps the vector's angle.
*
* @type number
@ -346,15 +365,8 @@ var Point = this.Point = Base.extend({
return point;
},
// DOCS: Point#getQuadrant
/**
* @return {number}
*/
getQuadrant: function() {
return this.x >= 0 ? this.y >= 0 ? 1 : 4 : this.y >= 0 ? 2 : 3;
},
/**
* {@grouptitle Angle & Rotation}
* Returns the smaller angle between two vectors. The angle is unsigned, no
* information about rotational direction is given.
*
@ -430,6 +442,14 @@ var Point = this.Point = Base.extend({
return this.getAngle(arguments[0]);
},
// DOCS: Point#getQuadrant
/**
* @return {number}
*/
getQuadrant: function() {
return this.x >= 0 ? this.y >= 0 ? 1 : 4 : this.y >= 0 ? 2 : 3;
},
/**
* Returns the angle between two vectors. The angle is directional and
* signed, giving information about the rotational direction.
@ -438,6 +458,7 @@ var Point = this.Point = Base.extend({
* {@link #angle} property.
*
* @param {Point} point
* @return {number} the angle between the two vectors
*/
getDirectedAngle: function(point) {
point = Point.read(arguments);
@ -478,7 +499,7 @@ var Point = this.Point = Base.extend({
* console.log(point == new Point(1, 1)); // false
* console.log(point != new Point(1, 1)); // true
*
* @param {Point}
* @param {Point} point
* @return {boolean}
*/
equals: function(point) {
@ -487,6 +508,8 @@ var Point = this.Point = Base.extend({
},
/**
* {@grouptitle Tests}
*
* Checks whether the point is inside the boundaries of the rectangle.
*
* @param {Rectangle} rect the rectangle to check against
@ -552,6 +575,7 @@ var Point = this.Point = Base.extend({
},
/**
* {@grouptitle Vectorial Math Functions}
* Returns the dot product of the point and another point.
*
* @param {Point} point
@ -594,12 +618,14 @@ var Point = this.Point = Base.extend({
},
/**
* @return {string} A string representation of the point.
* This property is only present if the point is an anchor or control point
* of a {@link Segment} or a {@link Curve}. In this case, it returns
* true if it is selected, false otherwise
*
* @name Point#selected
* @property
* @return {boolean} true if the point is selected, false otherwise
*/
toString: function() {
var format = Base.formatNumber;
return '{ x: ' + format(this.x) + ', y: ' + format(this.y) + ' }';
},
statics: {
/** @lends Point */

View file

@ -15,15 +15,29 @@
*/
var Gradient = this.Gradient = Base.extend({
/** @lends Gradient# */
beans: true,
// TODO: Should type here be called 'radial' and have it
// receive a boolean value?
/**
* Creates a gradient object
*
* @param {GradientStop[]} stops
* @param {string} [type='linear'] 'linear' or 'radial'
* @constructs Gradient
*
* @class The Gradient object.
*/
initialize: function(stops, type) {
this.setStops(stops || ['white', 'black']);
this.type = type || 'linear';
},
/**
* @return {Gradient} a copy of the gradient
*/
clone: function() {
var stops = [];
for (var i = 0, l = this._stops.length; i < l; i++)
@ -31,6 +45,12 @@ var Gradient = this.Gradient = Base.extend({
return new Gradient(stops, this.type);
},
/**
* The gradient stops on the gradient ramp.
*
* @type GradientStop[]
* @bean
*/
getStops: function() {
return this._stops;
},
@ -48,6 +68,12 @@ var Gradient = this.Gradient = Base.extend({
}
},
/**
* Checks whether the gradient is equal to the supplied gradient.
*
* @param {Gradient} gradient
* @return {boolean} true if they are equal, false otherwise
*/
equals: function(gradient) {
if (gradient.type != this.type)
return false;

View file

@ -15,8 +15,21 @@
*/
var GradientColor = this.GradientColor = Color.extend({
/** @lends GradientColor# */
beans: true,
/**
* Creates a gradient color object.
*
* @param {Gradient} gradient
* @param {Point} origin
* @param {Point} destination
* @param {Point} [hilite]
* @constructs GradientColor
*
* @class The GradientColor object.
*/
initialize: function(gradient, origin, destination, hilite) {
this.gradient = gradient || new Gradient();
this.setOrigin(origin);
@ -25,11 +38,20 @@ var GradientColor = this.GradientColor = Color.extend({
this.setHilite(hilite);
},
/**
* @return {GradientColor} a copy of the gradient color
*/
clone: function() {
return new GradientColor(this.gradient, this._origin, this._destination,
this._hilite);
},
/**
* The origin point of the gradient.
*
* @type Point
* @bean
*/
getOrigin: function() {
return this._origin;
},
@ -43,6 +65,12 @@ var GradientColor = this.GradientColor = Color.extend({
return this;
},
/**
* The destination point of the gradient.
*
* @type Point
* @bean
*/
getDestination: function() {
return this._destination;
},
@ -55,6 +83,12 @@ var GradientColor = this.GradientColor = Color.extend({
return this;
},
/**
* The hilite point of the gradient.
*
* @type Point
* @bean
*/
getHilite: function() {
return this._hilite;
},
@ -88,13 +122,13 @@ var GradientColor = this.GradientColor = Color.extend({
}
return gradient;
},
/**
* Checks if the component color values of the color are the
* same as those of the supplied one.
* Checks if the gradient color has the same properties as that of the
* supplied one.
*
* @param obj the GrayColor to compare with
* @return true if the GrayColor is the same, false otherwise.
* @param {GradientColor} color
* @return true if the GradientColor is the same, false otherwise
*/
equals: function(color) {
return color == this || color && color._colorType === this._colorType
@ -102,7 +136,12 @@ var GradientColor = this.GradientColor = Color.extend({
&& this._origin.equals(color._origin)
&& this._destination.equals(color._destination);
},
/**
* Transform the gradient color by the specified matrix.
*
* @param {Matrix} matrix the matrix to transform the gradient color by
*/
transform: function(matrix) {
matrix._transformPoint(this._origin, this._origin, true);
matrix._transformPoint(this._destination, this._destination, true);

View file

@ -16,8 +16,20 @@
// TODO: Support midPoint? (initial tests didn't look nice)
var GradientStop = this.GradientStop = Base.extend({
/** @lends GradientStop# */
beans: true,
/**
* Creates a GradientStop object.
*
* @param {Color} [color=new RGBColor(0, 0, 0)] the color of the stop
* @param {number} [rampPoint=0] the position of the stop on the gradient
* ramp {@default 0}
* @constructs GradientStop
*
* @class The GradientStop object.
*/
initialize: function(arg0, arg1) {
if (arg1 === undefined && Array.isArray(arg0)) {
// [color, rampPoint]
@ -34,10 +46,19 @@ var GradientStop = this.GradientStop = Base.extend({
}
},
/**
* @return {GradientColor} a copy of the gradient-stop
*/
clone: function() {
return new GradientStop(this._color.clone(), this._rampPoint);
},
/**
* The ramp-point of the gradient stop as a value between 0 and 1.
*
* @type number
* @bean
*/
getRampPoint: function() {
return this._rampPoint;
},
@ -47,6 +68,12 @@ var GradientStop = this.GradientStop = Base.extend({
this._rampPoint = rampPoint || 0;
},
/**
* The color of the gradient stop.
*
* @type Color
* @bean
*/
getColor: function() {
return this._color;
},

View file

@ -36,42 +36,6 @@ var Item = this.Item = Base.extend({
this.setStyle(this._project.getCurrentStyle());
},
/**
* Clones the item within the same project and places the copy above the
* item.
*
* @return the newly cloned item
*/
clone: function() {
return this._clone(new this.constructor());
},
_clone: function(copy) {
// Copy over style
copy.setStyle(this._style);
// If this item has children, clone and append each of them:
if (this._children) {
for (var i = 0, l = this._children.length; i < l; i++)
copy.appendTop(this._children[i].clone());
}
// Only copy over these fields if they are actually defined in 'this'
// TODO: Consider moving this to Base once it's useful in more than one
// place
var keys = ['locked', 'visible', 'opacity', 'blendMode', '_clipMask'];
for (var i = 0, l = keys.length; i < l; i++) {
var key = keys[i];
if (this.hasOwnProperty(key))
copy[key] = this[key];
}
// Move the clone above the original, at the same position.
copy.moveAbove(this);
// Only set name once the copy is moved, to avoid setting and unsettting
// name related structures.
if (this._name)
copy.setName(this._name);
return copy;
},
/**
* Private notifier that is called whenever a change occurs in this item or
* its sub-elements, such as Segments, Curves, PathStyles, etc.
@ -97,7 +61,13 @@ var Item = this.Item = Base.extend({
},
/**
* The name of the item.
* The name of the item. If the item has a name, it can be accessed by name
* through its parent's children list.
*
* @example
* var path = new Path();
* path.name = 'example';
* project.activeLayer.children['example'].remove();
*
* @type string
* @bean
@ -123,7 +93,332 @@ var Item = this.Item = Base.extend({
delete children[name];
}
},
/**
* The item's position within the project. This is the
* {@link Rectangle#center} of the {@link #bounds} rectangle.
*
* @example
* // Create a circle at position { x: 10, y: 10 }
* var circle = new Path.Circle(new Point(10, 10), 10);
* circle.fillColor = 'red';
*
* // Move the circle to { x: 20, y: 20 }
* circle.position = new Point(20, 20);
*
* // Move the circle 10 points to the right and 10 points down
* circle.position += new Point(10, 10);
* console.log(circle.position); // { x: 30, y: 30 }
*
* @example
* // Create a circle at position { x: 10, y: 10 }
* var circle = new Path.Circle(new Point(10, 10), 10);
* circle.fillColor = 'red';
*
* // Move the circle 10 points to the right
* circle.position.x += 10;
* console.log(circle.position); // { x: 20, y: 10 }
*
* @type Point
* @bean
*/
getPosition: function() {
// Cache position value
if (!this._position) {
// Center is a LinkedPoint as well, so we can use _x and _y
var center = this.getBounds().getCenter();
this._position = LinkedPoint.create(this, 'setPosition',
center._x, center._y);
}
return this._position;
},
setPosition: function(point) {
point = Point.read(arguments);
if (point)
this.translate(point.subtract(this.getPosition()));
},
/**
* The path style of the item.
*
* @example
* var circle = new Path.Circle(new Point(10, 10), 10);
* circle.style = {
* fillColor: new RGBColor(1, 0, 0),
* strokeColor: new RGBColor(0, 1, 0),
* strokeWidth: 5
* };
*
* @type PathStyle
* @bean
*/
getStyle: function() {
return this._style;
},
setStyle: function(style) {
this._style.initialize(style);
},
/**
* Specifies whether an item is selected and will also return {@code true} if
* the item is partially selected (groups with some selected items/partially
* selected paths).
*
* Paper.js draws the visual outlines of selected items on top of your
* project. This can be useful for debugging, as it allows you to see the
* construction of paths, position of path curves, individual segment points
* and bounding boxes of symbol and raster items.
*
* @example
* console.log(project.selectedItems.length); // 0
* var path = new Path.Circle(new Size(50, 50), 25);
* path.selected = true; // Select the path
* console.log(project.selectedItems.length) // 1
*
* @type boolean true if the item is selected, false otherwise
* @bean
*/
isSelected: function() {
if (this._children) {
for (var i = 0, l = this._children.length; i < l; i++) {
if (this._children[i].isSelected()) {
return true;
}
}
} else {
return !!this._selected;
}
return false;
},
setSelected: function(selected) {
if (this._children) {
for (var i = 0, l = this._children.length; i < l; i++) {
this._children[i].setSelected(selected);
}
} else {
if ((selected = !!selected) != this._selected) {
this._selected = selected;
this._project._selectItem(this, selected);
}
}
},
// TODO: isFullySelected / setFullySelected
// TODO: Change to getter / setters for these below that notify of changes
// through _changed()
// TODO: Item#isLocked is currently ignored in the documentation, as
// locking an item currently has no effect
/**
* Specifies whether the item is locked.
*
* @type boolean
* @default false
* @ignore
*/
locked: false,
/**
* Specifies whether the item is visible. When set to {@code false}, the
* item won't be drawn.
*
* @example
* var path = new Path.Circle(new Point(50, 50), 20);
* path.fillColor = 'red';
* console.log(path.visible) // true
* path.visible = false; // Hides the path
*
* @type boolean true if the item is visible, false otherwise
* @default true
*/
visible: true,
/**
* Specifies whether the item defines a clip mask. This can only be set on
* paths, compound paths, and text frame objects, and only if the item is
* already contained within a clipping group.
*
* @type boolean
* @default false
* @bean
*/
isClipMask: function() {
return this._clipMask;
},
setClipMask: function(clipMask) {
this._clipMask = clipMask;
if (this._clipMask) {
this.setFillColor(null);
this.setStrokeColor(null);
}
},
/**
* The blend mode of the item.
*
* @example
* var circle = new Path.Circle(new Point(50, 50), 10);
* circle.fillColor = 'red';
*
* // Change the blend mode of the path item:
* circle.blendMode = 'multiply';
*
* @type String('normal','screen','multiply','difference','src-in','add','overlay','hard-light','dodge','burn','darken','lighten','exclusion')
* @default 'normal'
*/
blendMode: 'normal',
/**
* The opacity of the item as a value between 0 and 1.
*
* @example
* // Create a circle at position { x: 50, y: 50 }
* var circle = new Path.Circle(new Point(50, 50), 20);
* circle.fillColor = 'red';
*
* // Change the opacity of the circle to 50%:
* circle.opacity = 0.5;
*
* @type number
* @default 1
*/
opacity: 1,
// TODO: get/setIsolated (print specific feature)
// TODO: get/setKnockout (print specific feature)
// TODO: get/setAlphaIsShape
// TODO: get/setData
/**
* {@grouptitle Project Hierarchy}
* The project that this item belongs to.
*
* @type Project
* @bean
*/
getProject: function() {
return this._project;
},
_setProject: function(project) {
if (this._project != project) {
this._project = project;
if (this._children) {
for (var i = 0, l = this._children.length; i < l; i++) {
this._children[i]._setProject(project);
}
}
}
},
// TODO: #getLayer()
/**
* The item that this item is contained within.
*
* @example
* var path = new Path();
* // New items are placed in the active layer:
* console.log(path.parent == project.activeLayer); // true
*
* var group = new Group();
* group.appendTop(path);
* // Now the parent of the path has become the group:
* console.log(path.parent == group); // true
*
* @type Item
* @bean
*/
getParent: function() {
return this._parent;
},
/**
* The children items contained within this item. Items that define a
* {@link #name} can also be accessed by name.
*
* @example
* var path = new Path();
* var group = new Group();
* group.appendTop(path);
*
* // The path has been placed in the children list of the group:
* console.log(group.children[0] == path);
*
* path.name = 'example';
* // Now the path can also be accessed by name:
* console.log(group.children['example'] == path); // true
*
* @type Item[]
* @bean
*/
getChildren: function() {
return this._children;
},
setChildren: function(items) {
this.removeChildren();
for (var i = 0, l = items && items.length; i < l; i++)
this.appendTop(items[i]);
},
/**
* The first item contained within this item. This is a shortcut for
* accessing {@code item.children[0]}.
*
* @type Item
* @bean
*/
getFirstChild: function() {
return this._children && this._children[0] || null;
},
/**
* The last item contained within this item.This is a shortcut for
* accessing {@code item.children[item.children.length - 1]}.
*
* @type Item
* @bean
*/
getLastChild: function() {
return this._children && this._children[this._children.length - 1]
|| null;
},
/**
* The next item on the same level as this item.
*
* @type Item
* @bean
*/
getNextSibling: function() {
return this._parent && this._parent._children[this._index + 1] || null;
},
/**
* The previous item on the same level as this item.
*
* @type Item
* @bean
*/
getPreviousSibling: function() {
return this._parent && this._parent._children[this._index - 1] || null;
},
/**
* The index of this item within the list of its parent's children.
*
* @type number
* @bean
*/
getIndex: function() {
return this._index;
},
_removeFromNamed: function() {
var children = this._parent._children,
namedChildren = this._parent._namedChildren,
@ -157,7 +452,10 @@ var Item = this.Item = Base.extend({
},
/**
* Removes the item from the project.
* Removes the item from the project. If the item has children, they are also
* removed.
*
* @return {boolean} true if the item was removed, false otherwise
*/
remove: function() {
if (this.isSelected())
@ -165,6 +463,20 @@ var Item = this.Item = Base.extend({
return this._removeFromParent();
},
/**
* Removes all of the item's children (if any).
*
* @return {boolean} true if removing was successful, false otherwise
*/
removeChildren: function() {
var removed = false;
if (this._children) {
for (var i = this._children.length - 1; i >= 0; i--)
removed = this._children[i].remove() || removed;
}
return removed;
},
/**
* When passed a project, copies the item to the project,
* or duplicates it within the same project. When passed an item,
@ -185,172 +497,39 @@ var Item = this.Item = Base.extend({
},
/**
* Specifies whether an item is selected and will also return true if
* the item is partially selected (groups with
* some selected items/partially selected paths).
* Clones the item within the same project and places the copy above the
* item.
*
* @example
* console.log(project.selectedItems.length); // 0
* var path = new Path.Circle(new Size(50, 50), 25);
* path.selected = true; // Select the path
* console.log(project.selectedItems.length) // 1
*
* @type boolean
* @bean
*/
isSelected: function() {
* @return {Item} the newly cloned item
*/
clone: function() {
return this._clone(new this.constructor());
},
_clone: function(copy) {
// Copy over style
copy.setStyle(this._style);
// If this item has children, clone and append each of them:
if (this._children) {
for (var i = 0, l = this._children.length; i < l; i++) {
if (this._children[i].isSelected()) {
return true;
}
}
} else {
return !!this._selected;
for (var i = 0, l = this._children.length; i < l; i++)
copy.appendTop(this._children[i].clone());
}
return false;
},
setSelected: function(selected) {
if (this._children) {
for (var i = 0, l = this._children.length; i < l; i++) {
this._children[i].setSelected(selected);
}
} else {
if ((selected = !!selected) != this._selected) {
this._selected = selected;
this._project._selectItem(this, selected);
}
// Only copy over these fields if they are actually defined in 'this'
// TODO: Consider moving this to Base once it's useful in more than one
// place
var keys = ['locked', 'visible', 'opacity', 'blendMode', '_clipMask'];
for (var i = 0, l = keys.length; i < l; i++) {
var key = keys[i];
if (this.hasOwnProperty(key))
copy[key] = this[key];
}
},
/**
* The project that this item belongs to.
*
* @type Project
* @bean
*/
getProject: function() {
return this._project;
},
_setProject: function(project) {
if (this._project != project) {
this._project = project;
if (this._children) {
for (var i = 0, l = this._children.length; i < l; i++) {
this._children[i]._setProject(project);
}
}
}
},
// TODO: isFullySelected / setFullySelected
// TODO: Change to getter / setters for these below that notify of changes
// through _changed()
/**
* Specifies whether the item is locked.
*
* @type boolean
* @default false
*/
locked: false,
/**
* Specifies whether the item is visible.
*
* @type boolean
* @default true
*/
visible: true,
/**
* The opacity of the item as a value between 0 and 1.
*
* @type number
* @default 1
*/
opacity: 1,
// DOCS: list the different blend modes that are possible.
/**
* The blend mode of the item.
* @type string
* @default 'normal'
*/
blendMode: 'normal',
/**
* Specifies whether the item defines a clip mask. This can only be set on
* paths, compound paths, and text frame objects, and only if the item is
* already contained within a clipping group.
*
* @type boolean
* @default false
* @bean
*/
isClipMask: function() {
return this._clipMask;
},
setClipMask: function(clipMask) {
this._clipMask = clipMask;
if (this._clipMask) {
this.setFillColor(null);
this.setStrokeColor(null);
}
},
// TODO: get/setIsolated (print specific feature)
// TODO: get/setKnockout (print specific feature)
// TODO: get/setAlphaIsShape
// TODO: get/setData
/**
* The item that this item is contained within.
*
* @type Item
* @bean
*/
getParent: function() {
return this._parent;
},
// TODO: #getLayer()
/**
* The index of this item within the list of its parent's children.
*
* @type number
* @bean
*/
getIndex: function() {
return this._index;
},
/**
* The children items contained within this item.
*
* @type array
* @bean
*/
getChildren: function() {
return this._children;
},
setChildren: function(items) {
this.removeChildren();
for (var i = 0, l = items && items.length; i < l; i++)
this.appendTop(items[i]);
},
/**
* Checks if the item contains any children items.
*
* @return {boolean} true if it has one or more children, false otherwise.
*/
hasChildren: function() {
return this._children && this._children.length > 0;
// Move the clone above the original, at the same position.
copy.moveAbove(this);
// Only set name once the copy is moved, to avoid setting and unsettting
// name related structures.
if (this._name)
copy.setName(this._name);
return copy;
},
/**
@ -368,63 +547,48 @@ var Item = this.Item = Base.extend({
},
/**
* Removes all of the item's children, if it has any
* Rasterizes the item into a newly created Raster object. The item itself
* is not removed after rasterization.
*
* @param {number} [resolution=72] the resolution of the raster in dpi
* @return {Raster} the newly created raster item
*/
removeChildren: function() {
var removed = false;
if (this._children) {
for (var i = this._children.length - 1; i >= 0; i--)
removed = this._children[i].remove() || removed;
}
return removed;
rasterize: function(resolution) {
// TODO: why would we want to pass a size to rasterize? Seems to produce
// weird results on Scriptographer. Also we can't use antialiasing, since
// Canvas doesn't support it yet. Project colorMode is also out of the
// question for now.
var bounds = this.getStrokeBounds(),
scale = (resolution || 72) / 72,
canvas = CanvasProvider.getCanvas(bounds.getSize().multiply(scale)),
ctx = canvas.getContext('2d'),
matrix = new Matrix().scale(scale).translate(-bounds.x, -bounds.y);
matrix.applyToContext(ctx);
this.draw(ctx, {});
var raster = new Raster(canvas);
raster.setPosition(this.getPosition());
raster.scale(1 / scale);
return raster;
},
/**
* The first item contained within this item.
* {@grouptitle Tests}
* Checks if the item contains any children items.
*
* @type Item
* @bean
* @return {boolean} true if it has one or more children, false otherwise.
*/
getFirstChild: function() {
return this._children && this._children[0] || null;
},
/**
* The last item contained within this item.
*
* @type Item
* @bean
*/
getLastChild: function() {
return this._children && this._children[this._children.length - 1]
|| null;
},
/**
* The next item on the same level as this item.
*
* @type Item
* @bean
*/
getNextSibling: function() {
return this._parent && this._parent._children[this._index + 1] || null;
},
/**
* The previous item on the same level as this item.
*
* @type Item
* @bean
*/
getPreviousSibling: function() {
return this._parent && this._parent._children[this._index - 1] || null;
hasChildren: function() {
return this._children && this._children.length > 0;
},
// TODO: Item#isEditable is currently ignored in the documentation, as
// locking an item currently has no effect
/**
* Checks whether the item is editable.
*
* @return {boolean} true when neither the item, nor its parents are
* locked or hidden, false otherwise.
* @ignore
*/
isEditable: function() {
var parent = this;
@ -464,6 +628,7 @@ var Item = this.Item = Base.extend({
// TODO: isBelow
/**
* {@grouptitle Hierarchy Tests}
* Checks whether the specified item is the parent of the item.
*
* @param {Item} item The item to check against
@ -614,100 +779,10 @@ var Item = this.Item = Base.extend({
*/
// TODO: getControlBounds
/**
* Rasterizes the item into a newly created Raster object. The item itself
* is not removed after rasterization.
*
* @param {number} [resolution=72] the resolution of the raster in dpi
* @return {Raster} the newly created raster item
*/
rasterize: function(resolution) {
// TODO: why would we want to pass a size to rasterize? Seems to produce
// weird results on Scriptographer. Also we can't use antialiasing, since
// Canvas doesn't support it yet. Project colorMode is also out of the
// question for now.
var bounds = this.getStrokeBounds(),
scale = (resolution || 72) / 72,
canvas = CanvasProvider.getCanvas(bounds.getSize().multiply(scale)),
ctx = canvas.getContext('2d'),
matrix = new Matrix().scale(scale).translate(-bounds.x, -bounds.y);
matrix.applyToContext(ctx);
this.draw(ctx, {});
var raster = new Raster(canvas);
raster.setPosition(this.getPosition());
raster.scale(1 / scale);
return raster;
},
/**
* The item's position within the project. This is the
* {@link Rectangle#center} of the {@link Item#bounds} rectangle.
*
* @type Point
* @bean
*/
getPosition: function() {
// Cache position value
if (!this._position) {
// Center is a LinkedPoint as well, so we can use _x and _y
var center = this.getBounds().getCenter();
this._position = LinkedPoint.create(this, 'setPosition',
center._x, center._y);
}
return this._position;
},
setPosition: function(point) {
point = Point.read(arguments);
if (point)
this.translate(point.subtract(this.getPosition()));
},
/**
* @param flags: Array of any of the following: 'objects', 'children',
* 'fill-gradients', 'fill-patterns', 'stroke-patterns', 'lines'.
* Default: ['objects', 'children']
*
* @ignore
*/
transform: function(matrix, flags) {
// TODO: Handle flags, add TransformFlag class and convert to bit mask
// for quicker checking
// TODO: Call transform on chidren only if 'children' flag is provided
if (this._transform)
this._transform(matrix, flags);
// Transform position as well. Do not modify _position directly,
// since it's a LinkedPoint and would cause recursion!
if (this._position)
matrix._transformPoint(this._position, this._position, true);
if (this._children) {
for (var i = 0, l = this._children.length; i < l; i++) {
var child = this._children[i];
child.transform(matrix, flags);
}
}
// PORT: Return 'this' in all chainable commands
return this;
},
/*
_transform: function(matrix, flags) {
// The code that performs the actual transformation of content,
// if defined. Item itself does not define this.
},
*/
/**
* Translates (moves) the item by the given offset point.
*
* @param {Point} delta the offset to translate the item by
*/
translate: function(delta) {
var mx = new Matrix();
return this.transform(mx.translate.apply(mx, arguments));
},
// DOCS: document the different arguments that this function can receive.
/**
* {@grouptitle Transform Functions}
*
* Scales the item by the given value from its center point, or optionally
* by a supplied point.
*
@ -728,9 +803,36 @@ var Item = this.Item = Base.extend({
* // Scale the path 200% from its bottom left corner
* circle.scale(2, circle.bounds.bottomLeft);
*
* @name Item#scale^1
* @function
* @param {number} scale the scale factor
* @param {Point} [center=the center point of the item]
*/
/**
* Scales the item by the given values from its center point, or optionally
* by a supplied point.
*
* @example
* // Create a circle at position { x: 10, y: 10 }
* var circle = new Path.Circle(new Point(10, 10), 10);
* console.log(circle.bounds.width); // 20
*
* // Scale the path horizontally by 200%
* circle.scale(1, 2);
*
* console.log(circle.bounds.width); // 40
*
* @example
* // Create a circle at position { x: 10, y: 10 }
* var circle = new Path.Circle(new Point(10, 10), 10);
*
* // Scale the path 200% horizontally from its bottom left corner
* circle.scale(1, 2, circle.bounds.bottomLeft);
*
* @param {number} sx the horizontal scale factor
* @param {number} sy the vertical scale factor
* @param {Point} [center=the center point of the item]
*/
scale: function(sx, sy /* | scale */, center) {
// See Matrix#scale for explanation of this:
if (arguments.length < 2 || typeof sy === 'object') {
@ -741,6 +843,16 @@ var Item = this.Item = Base.extend({
center || this.getPosition()));
},
/**
* Translates (moves) the item by the given offset point.
*
* @param {Point} delta the offset to translate the item by
*/
translate: function(delta) {
var mx = new Matrix();
return this.transform(mx.translate.apply(mx, arguments));
},
/**
* Rotates the item by a given angle around the given point.
*
@ -777,18 +889,39 @@ var Item = this.Item = Base.extend({
},
/**
* The path style of the item.
*
* @type PathStyle
* @bean
* Transform the item.
*
* @param {Matrix} matrix
* @param {array} flags Array of any of the following: 'objects', 'children',
* 'fill-gradients', 'fill-patterns', 'stroke-patterns', 'lines'.
* Default: ['objects', 'children']
*/
getStyle: function() {
return this._style;
transform: function(matrix, flags) {
// TODO: Handle flags, add TransformFlag class and convert to bit mask
// for quicker checking
// TODO: Call transform on chidren only if 'children' flag is provided
if (this._transform)
this._transform(matrix, flags);
// Transform position as well. Do not modify _position directly,
// since it's a LinkedPoint and would cause recursion!
if (this._position)
matrix._transformPoint(this._position, this._position, true);
if (this._children) {
for (var i = 0, l = this._children.length; i < l; i++) {
var child = this._children[i];
child.transform(matrix, flags);
}
}
// PORT: Return 'this' in all chainable commands
return this;
},
setStyle: function(style) {
this._style.initialize(style);
},
/*
_transform: function(matrix, flags) {
// The code that performs the actual transformation of content,
// if defined. Item itself does not define this.
},
*/
// TODO: toString
@ -924,6 +1057,7 @@ var Item = this.Item = Base.extend({
/** @lends Item# */
/**
* {@grouptitle Hierarchy Operations}
* Inserts the specified item as a child of the item by appending it to
* the list of children and moving it above all other children. You can
* use this function for groups, compound paths and layers.
@ -965,6 +1099,7 @@ var Item = this.Item = Base.extend({
//DOCS: document removeOn(param)
/**
* {@grouptitle Remove On Event}
* Removes the item when the next {@link Tool#onMouseMove} event is fired.
*
* @name Item#removeOnMove

View file

@ -15,8 +15,51 @@
*/
var PlacedSymbol = this.PlacedSymbol = Item.extend({
/** @lends PlacedSymbol# */
beans: true,
/**
* Creates a new PlacedSymbol Item.
*
* @example
* var path = new Path.Star(new Point(0, 0), 6, 5, 13);
* path.style = {
* fillColor: 'white',
* strokeColor: 'black'
* };
*
* // Create a symbol from the path:
* // (the original path is removed from the project)
* var symbol = new Symbol(path);
*
* // Place 100 instances of the symbol:
* for (var i = 0; i < 100; i++) {
* // Place an instance of the symbol in the project:
* var instance = new PlacedSymbol(symbol);
*
* // Move the instance to a random position within the view:
* instance.position = Point.random() * view.size;
*
* // Rotate the instance by a random amount between
* // 0 and 360 degrees:
* instance.rotate(Math.random() * 360);
*
* // Scale the instance between 0.25 and 1:
* instance.scale(0.25 + Math.random() * 0.75);
* }
*
* @param {Symbol} symbol the symbol to place
* @param {Point|Matrix} matrixOrOffset the center point of the placed
* symbol or a {@link Matrix} transformation to transform the placed symbol
* with.
*
* @class A PlacedSymbol represents a symbol which has been placed in a
* Paper.js project.
*
* @extends Item
* @constructs PlacedSymbol
*/
initialize: function(symbol, matrixOrOffset) {
this.base();
this.symbol = symbol instanceof Symbol ? symbol : new Symbol(symbol);
@ -27,6 +70,13 @@ var PlacedSymbol = this.PlacedSymbol = Item.extend({
: new Matrix();
},
/**
* The symbol contained within the placed symbol.
*
* @name PlacedSymbol#symbol
* @type Symbol
*/
clone: function() {
return this._clone(new PlacedSymbol(this.symbol, this.matrix.clone()));
},
@ -60,6 +110,5 @@ var PlacedSymbol = this.PlacedSymbol = Item.extend({
}
}
// TODO:
// embed()
// TODO: PlacedSymbol#embed()
});

View file

@ -34,7 +34,7 @@ var Path = this.Path = PathItem.extend({
* path.moveTo(30, 30);
* path.lineTo(100, 100);
*
* @param {array} [segments] An optional array of segments (or points to be
* @param {Segment[]} [segments] An optional array of segments (or points to be
* converted to segments) that will be added to the path.
*
* @class The Path item represents a path in a Paper.js project.
@ -77,7 +77,7 @@ var Path = this.Path = PathItem.extend({
/**
* The segments contained within the path.
*
* @type array
* @type Segment[]
* @bean
*/
getSegments: function() {
@ -120,7 +120,7 @@ var Path = this.Path = PathItem.extend({
/**
* The curves contained within the path.
*
* @type array
* @type Curve[]
* @bean
*/
getCurves: function() {
@ -282,6 +282,7 @@ var Path = this.Path = PathItem.extend({
* @param {Segment|Point} segment the segment or point to be added.
* @return {Segment} the added segment. This is not necessarily the same
* object, e.g. if the segment to be added already belongs to another path.
* @operator none
*/
add: function(segment1 /*, segment2, ... */) {
return arguments.length > 1 && typeof segment1 !== 'number'

View file

@ -98,7 +98,7 @@ var Project = this.Project = Base.extend({
/**
* The selected items contained within the project.
*
* @type array
* @type Item[]
* @bean
*/
getSelectedItems: function() {
@ -142,7 +142,45 @@ var Project = this.Project = Base.extend({
for (var i in this._selectedItems)
this._selectedItems[i].setSelected(false);
},
/**
* {@grouptitle Project Hierarchy}
*
* The layers contained within the project.
*
* @name Project#layers
* @type Layer[]
*/
/**
* The layer which is currently active. New items will be created on this
* layer by default.
*
* @name Project#activeLayer
* @type Layer
*/
/**
* The symbols contained within the project.
*
* @name Project#symbols
* @type Symbol[]
*/
/**
* The views contained within the project.
*
* @name Project#views
* @type View[]
*/
/**
* The view which is currently active.
*
* @name Project#activeView
* @type View
*/
draw: function(ctx) {
ctx.save();
var param = { offset: new Point(0, 0) };

View file

@ -15,20 +15,59 @@
*/
var Symbol = this.Symbol = Base.extend({
/** @lends Symbol# */
beans: true,
/**
* Creates a Symbol item.
*
* Sample code:
* @example
* var circlePath = new Path.Circle(new Point(100, 100), 50);
* circlePath.fillColor = 'red';
*
* var circleSymbol = new Symbol(circlePath);
* circleSymbol.name = 'Circle';
*
* // The original item is still contained in the document:
* circlePath.remove();
*
* // The symbol can now also be accessed
* // through project.symbols:
* console.log(project.symbols['Circle']);
*
* // To place instances of the symbol in the document:
* var placedCircle = new PlacedSymbol(circleSymbol);
* placedCircle.position = new Point(150, 150);
*
* @param {Item} item the source item which is copied as the definition of
* the symbol
*
* @name Symbol
* @constructor
*
* @class Symbols allow you to place multiple instances of an item in your
* project. This can save memory, since all instances of a symbol
* simply refer to the original item and it can speed up moving
* around complex objects, since internal properties such as segment
* lists and gradient positions don't need to be updated with every
* transformation.
*/
initialize: function(item) {
this.project = paper.project;
this.project.symbols.push(this);
this.setDefinition(item);
},
clone: function() {
return new Symbol(this._definition.clone());
},
// TODO: remove()
/**
* The symbol definition.
*
* @type Item
* @bean
*/
getDefinition: function() {
return this._definition;
},
@ -40,5 +79,14 @@ var Symbol = this.Symbol = Base.extend({
item._removeFromParent();
// Move position to 0, 0. TODO: Why?
item.setPosition(new Point());
},
/**
* Returns a copy of the symbol.
*
* @return {Symbol}
*/
clone: function() {
return new Symbol(this._definition.clone());
}
});

View file

@ -15,6 +15,27 @@
*/
var CharacterStyle = this.CharacterStyle = PathStyle.extend({
/** @lends CharacterStyle# */
/**
* CharacterStyle objects don't need to be created directly. Just pass an
* object to {@link TextItem#characterStyle}, it will be converted to a
* CharacterStyle object internally.
*
* @constructs CharacterStyle
* @param {object} style
*
* @constructs CharacterStyle
*
* @class The CharacterStyle object represents the character style of a text
* item ({@link TextItem#characterStyle})
*
* @example
* var text = new PointText(new Point(50, 50));
* text.fillColor = 'black';
* text.content = 'Hello world.';
* text.characterStyle.fontSize = 50;
*/
initialize: function(style) {
Base.initialize(this, style, {
fontSize: 10,
@ -23,6 +44,22 @@ var CharacterStyle = this.CharacterStyle = PathStyle.extend({
this.base(style);
},
/**
* The font of the character style.
*
* @name CharacterStyle#font
* @default 'sans-serif'
* @type string
*/
/**
* The font size of the character style in points.
*
* @name CharacterStyle#fontSize
* @default 10
* @type number
*/
statics: {
create: function(item) {
var style = new CharacterStyle(CharacterStyle.dont);

View file

@ -15,12 +15,45 @@
*/
var ParagraphStyle = this.ParagraphStyle = Base.extend({
/** @lends ParagraphStyle# */
/**
* ParagraphStyle objects don't need to be created directly. Just pass an
* object to {@link TextItem#paragraphStyle}, it will be converted to a
* ParagraphStyle object internally.
*
* Currently, the ParagraphStyle object may seem a bit empty, with just the
* {@link #justification} property. Yet, we have lots in store for Paper.js
* when it comes to typography. Please stay tuned.
*
* @constructs ParagraphStyle
* @param {object} style
*
* @constructs ParagraphStyle
*
* @class The ParagraphStyle object represents the paragraph style of a text
* item ({@link TextItem#paragraphStyle})
*
* @example
* var text = new PointText(new Point(0,0));
* text.fillColor = 'black';
* text.content = 'Hello world.';
* text.paragraphStyle.justification = 'center';
*/
initialize: function(style) {
Base.initialize(this, style, {
justification: 'left'
});
},
/**
* The justification of the paragraph.
*
* @name ParagraphStyle#justification
* @default 'left'
* @type string
*/
statics: {
create: function(item) {
var style = new ParagraphStyle(ParagraphStyle.dont);

View file

@ -15,8 +15,30 @@
*/
var PointText = this.PointText = TextItem.extend({
/** @lends PointText# */
beans: true,
/**
* Creates a point text item
*
* @example
* var text = new PointText(new Point(50, 100));
* text.paragraphStyle.justification = 'center';
* text.content = 'The contents of the point text';
* text.fillColor = 'black';
*
* @param {Point} point the position where the text will start
*
* @constructs PointText
*
* @class A PointText item represents a piece of typography in your Paper.js
* project which starts from a certain point and extends by the amount of
* characters contained in it.
*
* @extends TextItem
* @extends Item
*/
initialize: function(point) {
this.base();
var point = Point.read(arguments);
@ -33,6 +55,12 @@ var PointText = this.PointText = TextItem.extend({
return copy;
},
/**
* The PointText's anchor point
*
* @type Point
* @bean
*/
getPoint: function() {
return this._point;
},

View file

@ -15,8 +15,21 @@
*/
var TextItem = this.TextItem = Item.extend({
/** @lends TextItem# */
beans: true,
/**
* @constructs TextItem
*
* @class The TextItem type allows you to create typography. Its
* functionality is inherited by different text item types such as
* {@link PointText}, and {@link AreaText} (coming soon). They each add a
* layer of functionality that is unique to their type, but share the
* underlying properties and functions that they inherit from TextItem.
*
* @extends Item
*/
initialize: function() {
this.base();
this.content = null;
@ -26,12 +39,27 @@ var TextItem = this.TextItem = Item.extend({
this.setParagraphStyle();
},
/**
* The text contents of the text item.
*
* @name TextItem#content
* @type string
*/
_clone: function(copy) {
copy.setCharacterStyle(this._characterStyle);
copy.setParagraphStyle(this._paragraphStyle);
return this.base(copy);
},
/**
* {@grouptitle Style Properties}
*
* The character style of the text item.
*
* @type CharacterStyle
* @bean
*/
getCharacterStyle: function() {
return this._characterStyle;
},
@ -39,7 +67,13 @@ var TextItem = this.TextItem = Item.extend({
setCharacterStyle: function(style) {
this._characterStyle.initialize(style);
},
/**
* The paragraph style of the text item.
*
* @type ParagraphStyle
* @bean
*/
getParagraphStyle: function() {
return this._paragraphStyle;
},

View file

@ -20,7 +20,6 @@ var ToolEvent = this.ToolEvent = Base.extend({
beans: true,
/**
*
* @name ToolEvent
* @constructor
*

View file

@ -16,13 +16,50 @@
var KeyEvent = this.KeyEvent = Event.extend(new function() {
return {
/** @lends KeyEvent# */
beans: true,
/**
* @name KeyEvent
* @constructor
*
* @class KeyEvent The KeyEvent object is received by the {@link Tool}'s
* keyboard handlers {@link Tool#onKeyDown}, {@link Tool#onKeyUp},
* The KeyEvent object is the only parameter passed to these functions
* and contains information about the keyboard event.
*/
initialize: function(down, key, character, event) {
this.base(event);
this.type = down ? 'keydown' : 'keyup';
this.key = key;
this.character = character;
},
/**
* The type of key event.
*
* @name KeyEvent#type
* @type String('keydown', 'keyup')
*/
/**
* The string character of the key that caused this key event.
*
* @name KeyEvent#character
* @type string
*/
/**
* The key that caused this key event.
*
* @name KeyEvent#key
* @type string
*/
/**
* @return {string} A string representation of the key event.
*/
toString: function() {
return '{ type: ' + this.type
+ ', key: ' + this.key

View file

@ -15,11 +15,21 @@
*/
var View = this.View = Base.extend({
/** @lends View# */
beans: true,
// DOCS: View: there is alot left to document
// TODO: Add bounds parameter that defines position within canvas?
// Find a good name for these bounds, since #bounds is already the artboard
// bounds of the visible area.
/**
* Creates a view object
* @param {Canvas} canvas
* @constructs View
*
* @class The View object..
*/
initialize: function(canvas) {
// Associate this view with the active paper scope.
this._scope = paper;
@ -88,6 +98,13 @@ var View = this.View = Base.extend({
View.focused = this;
},
/**
* The bounds of the view, i.e. the bounds of the part of the project which
* is visible in the window.
*
* @type Rectangle
* @bean
*/
getViewBounds: function() {
return this._viewBounds;
},
@ -112,6 +129,10 @@ var View = this.View = Base.extend({
this._bounds = null;
},
/**
* @type Size
* @bean
*/
getViewSize: function() {
return this._viewBounds.getSize();
},
@ -120,16 +141,28 @@ var View = this.View = Base.extend({
this._viewBounds.setSize.apply(this._viewBounds, arguments);
},
/**
* @type Size
* @bean
*/
getBounds: function() {
if (!this._bounds)
this._bounds = this._matrix._transformBounds(this._viewBounds);
return this._bounds;
},
/**
* @type Size
* @bean
*/
getSize: function() {
return this.getBounds().getSize();
},
/**
* @type Point
* @bean
*/
getCenter: function() {
return this.getBounds().getCenter();
},
@ -138,6 +171,10 @@ var View = this.View = Base.extend({
this.scrollBy(Point.read(arguments).subtract(this.getCenter()));
},
/**
* @type number
* @bean
*/
getZoom: function() {
return this._zoom;
},
@ -148,6 +185,9 @@ var View = this.View = Base.extend({
this._zoom = zoom;
},
/**
* @param {Point} point
*/
scrollBy: function(point) {
this._transform(new Matrix().translate(Point.read(arguments).negate()));
},
@ -214,12 +254,17 @@ var View = this.View = Base.extend({
},
/**
* Handler to be called whenever a view gets resized.
* Handler function that is called whenever a view gets resized.
*
* @type function
*/
onResize: null,
/**
* Handler to be called on each frame of an animation.
* Handler function to be called on each frame of an animation.
*
* @type function
* @bean
*/
getOnFrame: function() {
return this._onFrame;