Bug 425227 - Orion Editor Content Assist Improvements
- Made popup look slicker: better shading, rounded corners, got rid of scroll bars unless popup is hovered
- Distiguished between the name of a proposal and its description where possible for templates, HTML and Javascript content assist.
- Disabled non-inferred proposals by default

--Signed-off-by: Elijah El-Haddad <elijahe@ca.ibm.com>
diff --git a/bundles/org.eclipse.orion.client.editor/web/orion/editor/contentassist.css b/bundles/org.eclipse.orion.client.editor/web/orion/editor/contentassist.css
index 34577b5..f8ea647 100644
--- a/bundles/org.eclipse.orion.client.editor/web/orion/editor/contentassist.css
+++ b/bundles/org.eclipse.orion.client.editor/web/orion/editor/contentassist.css
@@ -1,24 +1,30 @@
 .contentassist {

-	font-size:10pt;

-	font-family: "Consolas", "Monaco", "Vera Mono", "monospace";

+	font-size:9pt;

 	display: none;

 	background-color: white;

 	position: fixed;

 	top: 100px;

 	left: 100px;

-	border: 1px solid #DDD;

 	z-index:100;

 	cursor: default;

-	overflow: auto;

 	min-width: 70px;

 	min-height: 50px;

 	max-width: 350px;

-	max-height: 150px;

+	max-height: 162px;

+	overflow: hidden;

 	white-space: nowrap;

+	border-radius: 5px;

+	box-shadow: rgba(0, 0, 0, 0.3) 2px 2px 10px;

+	line-height: 18px;

+	padding-bottom: 3px;

 }

 

 .contentassist:focus {

-	border: 1px solid #666;

+	outline: none;

+}

+

+.contentassist:hover {

+	overflow-y: auto;

 }

 

 .contentassist .proposal-emphasis {

@@ -35,8 +41,14 @@
 .contentassist .proposal-noemphasis {

 	background-color: aliceblue;

 	font-weight: lighter;

+	color: black;

+}

+

+.contentassist .proposal-noemphasis-title {

+	background-color: aliceblue;

 	color: grey;

 }

+

 .contentassist .proposal-hr {

 	/* display as horizontal rule */

 	border: 0;

@@ -44,20 +56,26 @@
     border-top: 1px solid rgba(0, 0, 0, 0.1);

     border-bottom: 1px solid rgba(255, 255, 255, 0.3);

 }

+

 .contentassist .proposal-default {

 	/* nothing */

 }

 

+.contentassist .proposal-name {

+	font-weight: bold;

+}

+

+

+.contentassist>div:hover {

+	background-color: #fab467;

+}

+

 .contentassist .selected {

-	/* background-color: #a6bfe1; */

-	background-color: #FEC;

+	 background-color: rgb(48, 135, 179);

+	 color: white;

 }

 

 

 .contentassist>div {

-	padding: 1px 3px 0 3px;

+	padding: 1px 3px 0 5px;

 }

-

-.contentassist>div:hover {

-	background-color: #EAF2FE;

-}
\ No newline at end of file
diff --git a/bundles/org.eclipse.orion.client.editor/web/orion/editor/htmlContentAssist.js b/bundles/org.eclipse.orion.client.editor/web/orion/editor/htmlContentAssist.js
index a2914eb..96d3e5c 100644
--- a/bundles/org.eclipse.orion.client.editor/web/orion/editor/htmlContentAssist.js
+++ b/bundles/org.eclipse.orion.client.editor/web/orion/editor/htmlContentAssist.js
@@ -31,32 +31,38 @@
 	var templates = [

 		{

 			prefix: "<img", //$NON-NLS-0$

-			description: "<img> - HTML image element",

+			name: "<img>", //$NON-NLS-0$

+			description: " - HTML image element", //$NON-NLS-0$

 			template: "<img src=\"${cursor}\" alt=\"${Image}\"/>" //$NON-NLS-0$

 		},

 		{

 			prefix: "<a", //$NON-NLS-0$

-			description: "<a> - HTML anchor element",

+			name: "<a>", //$NON-NLS-0$

+			description: " - HTML anchor element", //$NON-NLS-0$

 			template: "<a href=\"${cursor}\"></a>" //$NON-NLS-0$

 		},

 		{

 			prefix: "<ul", //$NON-NLS-0$

-			description: "<ul> - HTML unordered list",

+			name: "<ul>", //$NON-NLS-0$

+			description: " - HTML unordered list",  //$NON-NLS-0$

 			template: "<ul>\n\t<li>${cursor}</li>\n</ul>" //$NON-NLS-0$

 		},

 		{

 			prefix: "<ol", //$NON-NLS-0$

-			description: "<ol> - HTML ordered list",

+			name: "<ol>", //$NON-NLS-0$

+			description: " - HTML ordered list", //$NON-NLS-0$

 			template: "<ol>\n\t<li>${cursor}</li>\n</ol>" //$NON-NLS-0$

 		},

 		{

 			prefix: "<dl", //$NON-NLS-0$

-			description: "<dl> - HTML definition list",

+			name: "<dl>", //$NON-NLS-0$

+			description: " - HTML definition list", //$NON-NLS-0$

 			template: "<dl>\n\t<dt>${cursor}</dt>\n\t<dd></dd>\n</dl>" //$NON-NLS-0$

 		},

 		{

 			prefix: "<table", //$NON-NLS-0$

-			description: "<table> - basic HTML table",

+			name: "<table>", //$NON-NLS-0$

+			description: " - basic HTML table", //$NON-NLS-0$

 			template: "<table>\n\t<tr>\n\t\t<td>${cursor}</td>\n\t</tr>\n</table>" //$NON-NLS-0$

 		}

 	];

diff --git a/bundles/org.eclipse.orion.client.editor/web/orion/editor/jsTemplateContentAssist.js b/bundles/org.eclipse.orion.client.editor/web/orion/editor/jsTemplateContentAssist.js
index 2ec54b1..0448ad1 100644
--- a/bundles/org.eclipse.orion.client.editor/web/orion/editor/jsTemplateContentAssist.js
+++ b/bundles/org.eclipse.orion.client.editor/web/orion/editor/jsTemplateContentAssist.js
@@ -57,112 +57,104 @@
 	var templates = [
 		{
 			prefix: "if", //$NON-NLS-0$
-			description: "if - if statement",
+			name: "if",  //$NON-NLS-0$
+			description: " - if statement", //$NON-NLS-0$
 			template: "if (${condition}) {\n\t${cursor}\n}" //$NON-NLS-0$
 		},
 		{
 			prefix: "if", //$NON-NLS-0$
-			description: "if - if else statement",
+			name: "if", //$NON-NLS-0$
+			description: " - if else statement", //$NON-NLS-0$
 			template: "if (${condition}) {\n\t${cursor}\n} else {\n\t\n}" //$NON-NLS-0$
 		},
 		{
 			prefix: "for", //$NON-NLS-0$
-			description: "for - iterate over array",
+			name: "for", //$NON-NLS-0$
+			description: " - iterate over array", //$NON-NLS-0$
 			template: "for (var ${i}=0; ${i}<${array}.length; ${i}++) {\n\t${cursor}\n}" //$NON-NLS-0$
 		},
 		{
 			prefix: "for", //$NON-NLS-0$
-			description: "for - iterate over array with local var",
+			name: "for", //$NON-NLS-0$
+			description: " - iterate over array with local var", //$NON-NLS-0$
 			template: "for (var ${i}=0; ${i}<${array}.length; ${i}++) {\n\tvar ${value} = ${array}[${i}];\n\t${cursor}\n}" //$NON-NLS-0$
 		},
 		{
 			prefix: "for", //$NON-NLS-0$
-			description: "for..in - iterate over properties of an object",
+			name: "for..in", //$NON-NLS-0$
+			description: " - iterate over properties of an object", //$NON-NLS-0$
 			template: "for (var ${property} in ${object}) {\n\tif (${object}.hasOwnProperty(${property})) {\n\t\t${cursor}\n\t}\n}" //$NON-NLS-0$
 		},
 		{
 			prefix: "while", //$NON-NLS-0$
-			description: "while - while loop with condition",
+			name: "while", //$NON-NLS-0$
+			description: " - while loop with condition", //$NON-NLS-0$
 			template: "while (${condition}) {\n\t${cursor}\n}" //$NON-NLS-0$
 		},
 		{
 			prefix: "do", //$NON-NLS-0$
-			description: "do - do while loop with condition",
+			name: "do", //$NON-NLS-0$
+			description: " - do while loop with condition", //$NON-NLS-0$
 			template: "do {\n\t${cursor}\n} while (${condition});" //$NON-NLS-0$
 		},
 		{
 			prefix: "switch", //$NON-NLS-0$
-			description: "switch - switch case statement",
+			name: "switch", //$NON-NLS-0$
+			description: " - switch case statement", //$NON-NLS-0$
 			template: "switch (${expression}) {\n\tcase ${value1}:\n\t\t${cursor}\n\t\tbreak;\n\tdefault:\n}" //$NON-NLS-0$
 		},
 		{
 			prefix: "case", //$NON-NLS-0$
-			description: "case - case statement",
+			name: "case", //$NON-NLS-0$
+			description: " - case statement", //$NON-NLS-0$
 			template: "case ${value}:\n\t${cursor}\n\tbreak;" //$NON-NLS-0$
 		},
 		{
 			prefix: "try", //$NON-NLS-0$
-			description: "try - try..catch statement",
+			name: "try", //$NON-NLS-0$
+			description: " - try..catch statement", //$NON-NLS-0$
 			template: "try {\n\t${cursor}\n} catch (${err}) {\n}" //$NON-NLS-0$
 			},
 		{
 			prefix: "try", //$NON-NLS-0$
-			description: "try - try..catch statement with finally block",
+			name: "try", //$NON-NLS-0$
+			description: " - try..catch statement with finally block", //$NON-NLS-0$
 			template: "try {\n\t${cursor}\n} catch (${err}) {\n} finally {\n}" //$NON-NLS-0$
 		},
 		{
-			prefix: "var", //$NON-NLS-0$
-			description: "var - variable declaration",
-			template: "var ${name};" //$NON-NLS-0$
-		},
-		{
-			prefix: "var", //$NON-NLS-0$
-			description: "var - variable declaration with value",
-			template: "var ${name} = ${value};" //$NON-NLS-0$
-		},
-		{
-			prefix: "let", //$NON-NLS-0$
-			description: "let - local scope variable declaration",
-			template: "let ${name};" //$NON-NLS-0$
-		},
-		{
-			prefix: "let", //$NON-NLS-0$
-			description: "let - local scope variable declaration with value",
-			template: "let ${name} = ${value};" //$NON-NLS-0$
-		},
-		{
-			prefix: "return", //$NON-NLS-0$
-			description: "return - return result",
-			template: "return ${result};" //$NON-NLS-0$
-		},
-		{
 			prefix: "typeof", //$NON-NLS-0$
-			description: "typeof - typeof statement",
+			name: "typeof", //$NON-NLS-0$
+			description: " - typeof statement", //$NON-NLS-0$
 			template: "typeof ${object} === \"${type:" + fromJSON(typeofValues) + "}\"" //$NON-NLS-1$ //$NON-NLS-0$
 		},
 		{
 			prefix: "instanceof", //$NON-NLS-0$
-			description: "instanceof - instanceof statement",
+			name: "instanceof", //$NON-NLS-0$
+			description: " - instanceof statement", //$NON-NLS-0$
 			template: "${object} instanceof ${type}" //$NON-NLS-0$
 		},
 		{
 			prefix: "with", //$NON-NLS-0$
-			description: "with - with statement",
+			name: "with", //$NON-NLS-0$
+			description: " - with statement", //$NON-NLS-0$
 			template: "with (${object}) {\n\t${cursor}\n}" //$NON-NLS-0$
 		},
 		{
 			prefix: "function", //$NON-NLS-0$
-			description: "function - function declaration",
+			name: "function", //$NON-NLS-0$
+			description: " - function declaration",  //$NON-NLS-0$
 			template: "function ${name} (${parameter}) {\n\t${cursor}\n}" //$NON-NLS-0$
 		},
 		{
 			prefix: "nls", //$NON-NLS-0$
-			description: "string - non NLS",
+			name: "nls", //$NON-NLS-0$
+			description: " - non NLS string", //$NON-NLS-0$
 			template: "${cursor} //$NON-NLS-${0}$" //$NON-NLS-0$
 		},
 		{
 			prefix: "log", //$NON-NLS-0$
-			description: "log - console log",
+			name: "log", //$NON-NLS-0$
+			description: " - console log", //$NON-NLS-0$
 			template: "console.log(${object});" //$NON-NLS-0$
 		}
 	];
diff --git a/bundles/org.eclipse.orion.client.editor/web/orion/editor/templates.js b/bundles/org.eclipse.orion.client.editor/web/orion/editor/templates.js
index bb06a5e..11e49a7 100644
--- a/bundles/org.eclipse.orion.client.editor/web/orion/editor/templates.js
+++ b/bundles/org.eclipse.orion.client.editor/web/orion/editor/templates.js
@@ -26,10 +26,11 @@
 	var delimiterVar = "${delimiter}"; //$NON-NLS-0$

 	var cursorVar = "${cursor}"; //$NON-NLS-0$

 	

-	function Template (prefix, description, template) {

+	function Template (prefix, description, template, name) {

 		this.prefix = prefix;

 		this.description = description;

 		this.template = template;

+		this.name = name;

 		this._parse();

 	}

 	Template.prototype = /** @lends orion.editor.Template.prototype */ {

@@ -89,9 +90,11 @@
 			}

 			return {

 				proposal: proposal,

+				name: this.name,

 				description: this.description,

 				groups: newGroups,

-				escapePosition: startOffset + escapePosition

+				escapePosition: startOffset + escapePosition,

+				style: 'noemphasis'

 			};

 		},

 		match: function(prefix) {

@@ -139,17 +142,16 @@
 		addTemplates: function(json) {

 			var templates = this.getTemplates();

 			for (var j = 0; j < json.length; j++) {

-				templates.push(new Template(json[j].prefix, json[j].description, json[j].template));

+				templates.push(new Template(json[j].prefix, json[j].description, json[j].template, json[j].name));

 			}

 		},

 		computeProposals: function(buffer, offset, context) {

 			var prefix = this.getPrefix(buffer, offset, context);

 			var proposals = [];

-			if (!this.isValid(prefix, buffer, offset, context)) {

-				return proposals;

+			if (this.isValid(prefix, buffer, offset, context)) {

+				proposals = proposals.concat(this.getTemplateProposals(prefix, offset, context));

+				proposals = proposals.concat(this.getKeywordProposals(prefix));

 			}

-			proposals = proposals.concat(this.getTemplateProposals(prefix, offset, context));

-			proposals = proposals.concat(this.getKeywordProposals(prefix));

 			return proposals;

 		},

 		getKeywords: function() {

@@ -176,6 +178,14 @@
 		getTemplateProposals: function(prefix, offset, context) {

 			var proposals = [];

 			var templates = this.getTemplates();

+			if (0 < templates.length) {

+				proposals[0] = {

+					proposal: '',

+					description: 'Templates',

+					style: 'noemphasis_title',

+					unselectable: true

+				};

+			}

 			for (var t = 0; t < templates.length; t++) {

 				var template = templates[t];

 				if (template.match(prefix)) {

diff --git a/bundles/org.eclipse.orion.client.javascript/web/javascript/contentAssist/contentAssist.js b/bundles/org.eclipse.orion.client.javascript/web/javascript/contentAssist/contentAssist.js
index e76837f..98643ce 100644
--- a/bundles/org.eclipse.orion.client.javascript/web/javascript/contentAssist/contentAssist.js
+++ b/bundles/org.eclipse.orion.client.javascript/web/javascript/contentAssist/contentAssist.js
@@ -214,8 +214,8 @@
 		return string.substring(prefix.length);
 	}
 
-	function createProposalDescription(propName, propType, env) {
-		return propName + " : " + typeUtils.createReadableType(propType, env);
+	function createProposalDescription(propType, env) {
+		return " : " + typeUtils.createReadableType(propType, env);
 	}
 
 	function createInferredProposals(targetTypeName, env, completionKind, prefix, replaceStart, proposals, relevance) {
@@ -231,6 +231,7 @@
 		// add a separator proposal
 		proposals['---dummy' + relevance] = {
 			proposal: '',
+			name: '',
 			description: '---------------------------------',
 			relevance: relevance -1,
 			style: 'hr',
@@ -273,9 +274,10 @@
 					if (propTypeObj.type === 'FunctionType') {
 						res = calculateFunctionProposal(propName,
 								propTypeObj, replaceStart - 1);
-						var funcDesc = res.completion + " : " + typeUtils.createReadableType(propTypeObj, env);
+						var funcDesc = " : " + typeUtils.createReadableType(propTypeObj, env);
 						proposals["$"+propName] = {
 							proposal: res.completion,
+							name: res.completion,
 							description: funcDesc,
 							positions: res.positions,
 							escapePosition: replaceStart + res.completion.length,
@@ -288,7 +290,8 @@
 						proposals["$"+propName] = {
 							proposal: propName,
 							relevance: relevance,
-							description: createProposalDescription(propName, propTypeObj, env),
+							name: propName,
+							description: createProposalDescription(propTypeObj, env),
 							style: 'emphasis',
 							overwrite: true
 						};
@@ -317,7 +320,8 @@
 						var res = calculateFunctionProposal(prop, propType, replaceStart - 1);
 						proposals[prop] = {
 							proposal: removePrefix(prefix, res.completion),
-							description: createProposalDescription(prop, propType, environment),
+							name: prop,
+							description: createProposalDescription(propType, environment),
 							positions: res.positions,
 							escapePosition: replaceStart + res.completion.length,
 							// prioritize methods over fields
@@ -328,7 +332,8 @@
 					} else {
 						proposals[prop] = {
 							proposal: removePrefix(prefix, prop),
-							description: createProposalDescription(prop, propType, environment),
+							name: prop,
+							description: createProposalDescription(propType, environment),
 							relevance: -100,
 							style: 'noemphasis'
 						};
@@ -348,6 +353,7 @@
 		if (proposalAdded) {
 			proposals['---dummy'] = {
 				proposal: '',
+				name: '',
 				description: 'Non-inferred proposals',
 				relevance: -98,
 				style: 'noemphasis',
@@ -677,8 +683,8 @@
 				return 1;
 			}
 
-			var ldesc = l.description.toLowerCase();
-			var rdesc = r.description.toLowerCase();
+			var ldesc = l.name.toLowerCase();
+			var rdesc = r.name.toLowerCase();
 			if (ldesc < rdesc) {
 				return -1;
 			} else if (rdesc < ldesc) {
@@ -782,7 +788,7 @@
 					var target = typeInf.inferTypes(root, environment, self.lintOptions);
 					var proposalsObj = { };
 					createInferredProposals(target, environment, completionKind.kind, context.prefix, offset - context.prefix.length, proposalsObj);
-					if (!context.inferredOnly) {
+					if (context.includeNonInferred) {
 						// include the entire universe as potential proposals
 						createNoninferredProposals(environment, context.prefix, offset - context.prefix.length, proposalsObj);
 					}
diff --git a/bundles/org.eclipse.orion.client.javascript/web/js-tests/contentAssistTests.js b/bundles/org.eclipse.orion.client.javascript/web/js-tests/contentAssistTests.js
index f4b9ee3..2d0dbc2 100644
--- a/bundles/org.eclipse.orion.client.javascript/web/js-tests/contentAssistTests.js
+++ b/bundles/org.eclipse.orion.client.javascript/web/js-tests/contentAssistTests.js
@@ -63,7 +63,7 @@
 				return new Deferred().resolve(buffer);
 			}
 		};
-		return assist.computeContentAssist(mockContext, {offset: offset, prefix : prefix, inferredOnly : true });
+		return assist.computeContentAssist(mockContext, {offset: offset, prefix : prefix, includeNonInferred: true });
 	}
 
 	function testProposal(proposal, text, description) {