You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by zo...@apache.org on 2010/06/01 11:59:38 UTC

svn commit: r949987 - in /incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web: ./ goat/ goat/configuration/ goat/elements/

Author: zoe
Date: Tue Jun  1 09:59:37 2010
New Revision: 949987

URL: http://svn.apache.org/viewvc?rev=949987&view=rev
Log:
ARIES-319 Committing Holly's patch

Added:
    incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/configuration/
    incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/configuration/ComponentAppearance.js
    incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/configuration/Theme.js
    incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/ComponentColorElement.js
    incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/RelationshipElement.js
    incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/TriangleDecorator.js
    incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/TwistieAggregation.js
Modified:
    incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/Component.js
    incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/ElementLayoutManager.js
    incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/Relationship.js
    incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/RelationshipAggregator.js
    incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/RelationshipManager.js
    incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/ServerSideInterface.js
    incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/ElementBase.js
    incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/ElementRegistry.js
    incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/index.html

Modified: incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/Component.js
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/Component.js?rev=949987&r1=949986&r2=949987&view=diff
==============================================================================
--- incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/Component.js (original)
+++ incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/Component.js Tue Jun  1 09:59:37 2010
@@ -1,20 +1,18 @@
 /**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
  */
 dojo.provide("goat.Component");
 dojo.require("dojox.gfx");
@@ -28,234 +26,342 @@ dojo.require("goat.elements.TextComponen
 dojo.require("goat.RelationshipManager");
 dojo.require("goat.ElementLayoutManager");
 
+dojo.require("goat.configuration.Theme");
+dojo.require("goat.configuration.ComponentAppearance");
 
-
-//Component,
+// Component,
 // looks after a component shape on the surface.
 //
 dojo.declare("goat.Component", [], {
 
-	//fixed properties.
-	
-                         /*String*/       id: null,     //must be unique within enclosing component, if any, or globally if none.
-	           /*goat.Component[]*/ children: null,
-	/*goat.elements.ElementBase[]*/ elements: null, //gui display elements within this component, all must extend 'goat.elements.ElementBase'
-	
-	//manager objects.. 
-	/*goat.RelationshipManager*/   relationshipManager: null, //manager for handling all relationships to/from this component.
-	/*goat.ElementLayoutManager*/ elementLayoutManager: null, //manager for arranging elements within a component.
-	/*goat.elements.ElementRegistry*/  elementRegistry: null, //manager for returning appropriate renderers for component elements
-
-	//state.
-	/*boolean*/   hidden: false,    //is component visible on the surface.
-	/*boolean*/ selected: false,    //is mouse currently within our boundary ?
-	/*boolean*/ refreshing: false,  //is a refresh in progress ?
-	
-	//gfx objects
-	/*dojox.gfx.Group*/     group: null,
-	/*dojox.gfx.Surface*/ surface: null,
-	/*dojox.gfx.Rect*/    outline: null,
-		
-	//dimensions/coords - onsurface positioning.
-	/*int*/  x: 0,
-	/*int*/  y: 0,
-	/*int*/  width: null,
-	/*int*/  height: null,
-	
-	/*int*/  minWidth: 150, 
-	/*int*/  minHeight: 80,
-		
-	
-	
-constructor: function(/*dojox.gfx.Surface*/surface, 
-		              /*String*/id, 
-		              /*String[]*/props, 
-		              /*goat.Component[]*/ children) {
-	
-	this.surface=surface;
-	this.x=0;
-	this.y=0;
-	this.height=115;
-	this.width=this.minWidth;
-		
-	//console.log("Adding Box");
+	// fixed properties.
+
+	/* String */id : null, // must be unique within enclosing component, if
+							// any, or globally if none.
+	/* goat.Component[] */children : null,
+	/* goat.elements.ElementBase[] */elements : null, // gui display elements
+													// within this component,
+													// all must extend
+													// 'goat.elements.ElementBase'
+
+	// manager objects..
+	/* goat.RelationshipManager */relationshipManager : null, // manager for
+															// handling all
+															// relationships
+															// to/from this
+															// component.
+	/* goat.ElementLayoutManager */elementLayoutManager : null, // manager for
+																// arranging
+																// elements
+																// within a
+																// component.
+	/* goat.elements.ElementRegistry */elementRegistry : null, // manager for
+																// returning
+																// appropriate
+																// renderers for
+																// component
+																// elements
+
+	// state.
+	/* boolean */hidden : false, // is component visible on the surface.
+	/* boolean */selected : false, // is mouse currently within our boundary ?
+	/* boolean */refreshing : false, // is a refresh in progress ?
+
+	// gfx objects
+	/* dojox.gfx.Group */group : null,
+	/* dojox.gfx.Surface */surface : null,
+	/* dojox.gfx.Rect */outline : null,
+
+	/* goat.configuration.ComponentAppearance */componentAppearance : null,
+	// dimensions/coords - onsurface positioning.
+	/* int */x : 0,
+	/* int */y : 0,
+	/* int */width : null,
+	/* int */height : null,
+
+	/* int */minWidth : 150,
+	/* int */minHeight : 80,
+
+	constructor : function(/* dojox.gfx.Surface */surface,
+	/* String */id,
+	/* String[] */props,
+	/* goat.Component[] */children, /* goat.configuration */theme) {
+
+		this.surface = surface;
+		this.x = 0;
+		this.y = 0;
+		this.height = 115;
+		this.width = this.minWidth;
+
+	// TODO if we have a parent we should pass through their component
+	// appearance */
+	this.componentAppearance = new goat.configuration.ComponentAppearance(
+			theme, null);
+	// console.log("Adding Box");
 	this.initGfx();
-	
-	this.id=id;	
-	this.elements=new Array();
-	
-	this.children=children;	
-	if(this.children!=null){
-		  var type = "component.container";
-		  var element = this.elementRegistry.getProperty(this.group, type, children);
-		  this.elements[type]=element;
-	}	
-		
-	this.elementRegistry = new goat.elements.ElementRegistry(this,props);
+
+	this.id = id;
+	this.elements = new Array();
+
+	this.children = children;
+	if (this.children != null) {
+		var type = "component.container";
+		var element = this.elementRegistry.getProperty(this.group,
+				this.componentAppearance, type, children);
+		this.elements[type] = element;
+	}
+
+	this.elementRegistry = new goat.elements.ElementRegistry(this, props);
 	this.elementRegistry = this.elementRegistry.getRegistry();
-	
+
 	this.updateProperties(props);
-	
-	//console.log("Creating RM");
+
+	// console.log("Creating RM");
 	this.relationshipManager = new goat.RelationshipManager(this);
-	//console.log("Creating ELM");
+	// console.log("Creating ELM");
 	this.elementLayoutManager = new goat.ElementLayoutManager(this);
-		
-	//console.log("Invoking refresh");
+
+	// console.log("Invoking refresh");
 	this.refresh();
 
 	var mover = new dojox.gfx.Moveable(this.group);
-    dojo.connect(mover, "onMoved", this, "onMoved");  
-    
-    this.group.connect("onclick",dojo.hitch(this,"onClick"));
-    this.group.connect("onmouseenter",dojo.hitch(this,"onMouseEnter"));
-    this.group.connect("onmouseleave",dojo.hitch(this,"onMouseLeave"));
-    
-    dojo.publish("goat.component.create",[this]);
-    
-    dojo.subscribe("goat.component.refresh", this, this.onRefresh);
-},
-updateProperties: function(props){
-	//console.log("Processing properties");
-	//console.log(props);
-	
-	this.componentProperties=new Array();
-	for (var key in props){		  
-		  var value = props[key];
-		  //console.log("The fieldname or key is: "+key+" and the value at that field is: "+value);
-		  var type = "component.property."+key;
-		  if(this.elements[type]==null){
-		    var element = this.elementRegistry.getProperty(this, type, value);
-		    this.elements[type]=element;
-		  }else{
+	dojo.connect(mover, "onMoved", this, "onMoved");
+
+	this.group.connect("onclick", dojo.hitch(this, "onClick"));
+	this.group.connect("onmouseenter", dojo.hitch(this, "onMouseEnter"));
+	this.group.connect("onmouseleave", dojo.hitch(this, "onMouseLeave"));
+
+	dojo.publish("goat.component.create", [ this ]);
+
+	dojo.subscribe("goat.component.refresh", this, this.onRefresh);
+},
+updateProperties : function(props) {
+	// console.log("Processing properties");
+	// console.log(props);
+
+	this.componentProperties = new Array();
+	for ( var key in props) {
+		var value = props[key];
+		// console.log("The fieldname or key is: "+key+" and the value at that
+		// field is: "+value);
+		var type = "component.property." + key;
+		if (this.elements[type] == null) {
+			var element = this.elementRegistry.getProperty(this,
+					this.componentAppearance, type, value);
+			this.elements[type] = element;
+		} else {
 			this.elements[type].update(value);
-		  }
-	}	
-	//TODO: what about elements in this.elements that were not present in props, 
-	//      should they be removed from the this.elements array.. currently elements dont
-	//      support a 'remove' method. 
-	//      for now, as components dont need removing, wont worry about this.
-	
-	//console.log("Properties processed.");	
+		}
+	}
+	// TODO: what about elements in this.elements that were not present in
+	// props,
+	// should they be removed from the this.elements array.. currently elements
+	// dont
+	// support a 'remove' method.
+	// for now, as components dont need removing, wont worry about this.
+
+	// console.log("Properties processed.");
 },
-removeSelf: function() {
+removeSelf : function() {
 	this.surface.remove(this.group);
-	dojo.publish("goat.component.delete", [this]);
+	dojo.publish("goat.component.delete", [ this ]);
 },
-initGfx: function() {
+initGfx : function() {
 	this.group = this.surface.createGroup();
-	
-	this.outline = this.group.createRect({x: 0, y: 0, width: this.width, height: this.height, r: 5})
-	.setStroke({width: 2, color: '#808080'})
-	.setFill({type: "linear",  x1: 0, y1: 0, x2: 150, y2: 80,
-			colors: [{ offset: 0, color: "#ffff80" },{ offset: 1, color: "#ffffff" } ]});
-       
+
+	this.outline = this.group.createRect( {
+		x : 0,
+		y : 0,
+		width : this.width,
+		height : this.height,
+		r : 5
+	}).setStroke( {
+		width : 2,
+		color : '#808080'
+	})
+
+	if (this.componentAppearance.useLinearShading()) {
+		this.outline.setFill( {
+			type : "linear",
+			x1 : 0,
+			y1 : 0,
+			x2 : 150,
+			y2 : 80,
+			colors : [ {
+				offset : 0,
+				color : this.componentAppearance.getBackgroundColor()
+			}, {
+				offset : 1,
+				color : "#ffffff"
+			} ]
+		});
+	} else {
+		this.outline.setFill(this.componentAppearance.getBackgroundColor());
+
+	}
+
 },
-refresh: function(){
-	//console.log(">Component.refresh");
+refresh : function() {
+	// console.log(">Component.refresh");
 	this.elementLayoutManager.doLayout();
-	
-	//console.log("Sizing box");
-	//not compatible with component shape property!
-	this.outline.setShape({x: 0, y: 0, width: this.width, height: this.height, r: 5});
-	
-	//console.log("Movng to front");
-	//make sure we can be seen.
+
+	// console.log("Sizing box");
+	// not compatible with component shape property!
+	this.outline.setShape( {
+		x : 0,
+		y : 0,
+		width : this.width,
+		height : this.height,
+		r : 5
+	});
+
+	if (this.componentAppearance.useLinearShading()) {
+		this.outline.setFill( {
+			type : "linear",
+			x1 : 0,
+			y1 : 0,
+			x2 : 150,
+			y2 : 80,
+			colors : [ {
+				offset : 0,
+				color : this.componentAppearance.getBackgroundColor()
+			}, {
+				offset : 1,
+				color : "#ffffff"
+			} ]
+		});
+	} else {
+		this.outline.setFill(this.componentAppearance.getBackgroundColor());
+
+	}
+	// console.log("Movng to front");
+	// make sure we can be seen.
 	this.group.moveToFront();
-	//console.log("<Component.refresh");
+	// console.log("<Component.refresh");
 },
-update: function(id, props, children) {	
-	
-	//console.log("Updating "+id+", processing properties array.. ");
-	
-	//rebuilds the prop array internally
+update : function(id, props, children) {
+
+	// console.log("Updating "+id+", processing properties array.. ");
+
+	// rebuilds the prop array internally
 	this.updateProperties(props);
-	
-	//console.log("Updating "+id+", rebuilding onscreen with new props ");
-	//rebuild the onscreen object with the layout mgr 
+
+	// console.log("Updating "+id+", rebuilding onscreen with new props ");
+	// rebuild the onscreen object with the layout mgr
 	this.refresh();
-	
-	//TODO: update children.
-		
-	//tells everyone who cares that we just did that.
-	dojo.publish("goat.component.update."+this.id,[this]);
-},
-moveToNewPlace: function(x, y) {
-	if(!this.hidden){
-	  this.group.setTransform({dx:x, dy:y});
-    }
+
+	// TODO: update children.
+
+	// tells everyone who cares that we just did that.
+	dojo.publish("goat.component.update." + this.id, [ this ]);
+},
+moveToNewPlace : function(x, y) {
+	if (!this.hidden) {
+		this.group.setTransform( {
+			dx : x,
+			dy : y
+		});
+	}
 	this.x = x;
 	this.y = y;
-	this.updateAfterMove();	
+	this.updateAfterMove();
 },
-toggleHidden: function(){
-	var hideMe = !this.hidden;	
-	if(hideMe){
-		//cheat.. move it off canvas..
-		this.group.setTransform({dx:-1000, dy:-1000});	
-	}else{
-		//bring it back =) good job we remembered where it was supposed to go !
-		this.group.setTransform({dx:this.x, dy:this.y});	
-	}
-		
-	this.hidden = hideMe;
-	dojo.publish("goat.component.hidden",[this.id,hideMe]);
-	dojo.publish("goat.component.hidden."+this.id, [this]);
-},
-onMoved: function(mover, shift) { 
-	//this may stop working once this.group isnt directly within the surface
-	//(ie once child components are renderable)
-    this.x=this.group.matrix.dx;
-    this.y=this.group.matrix.dy;
-    
+toggleHidden : function() {
+	var hideMe = !this.hidden;
+	if (hideMe) {
+		// cheat.. move it off canvas..
+	this.group.setTransform( {
+		dx : -1000,
+		dy : -1000
+	});
+} else {
+	// bring it back =) good job we remembered where it was supposed to go !
+	this.group.setTransform( {
+		dx : this.x,
+		dy : this.y
+	});
+}
+
+this.hidden = hideMe;
+dojo.publish("goat.component.hidden", [ this.id, hideMe ]);
+dojo.publish("goat.component.hidden." + this.id, [ this ]);
+},
+onMoved : function(mover, shift) {
+// this may stop working once this.group isnt directly within the surface
+	// (ie once child components are renderable)
+	this.x = this.group.matrix.dx;
+	this.y = this.group.matrix.dy;
+
 	this.updateAfterMove();
 },
-updateAfterMove: function(){
-	dojo.publish("goat.component.move",[this.id,this.x,this.y]);
-	dojo.publish("goat.component.move."+this.id, [this]);
+updateAfterMove : function() {
+	dojo.publish("goat.component.move", [ this.id, this.x, this.y ]);
+	dojo.publish("goat.component.move." + this.id, [ this ]);
 },
-pulse: function() {
+pulse : function() {
 	var endColor = this.selected ? "#FF3030" : "#808080";
-	dojox.gfx.fx.animateStroke({
-	    shape: this.outline,
-	    duration: 500,
-	    color: {start: "#6F0000", end: endColor},
-	    width: {start:10, end: 2},
-	    join:  {values: ["miter", "bevel", "round"]}
+	dojox.gfx.fx.animateStroke( {
+		shape : this.outline,
+		duration : 500,
+		color : {
+			start : "#6F0000",
+			end : endColor
+		},
+		width : {
+			start : 10,
+			end : 2
+		},
+		join : {
+			values : [ "miter", "bevel", "round" ]
+		}
 	}).play();
 },
-glow: function(){
+glow : function() {
 	var endColor = this.selected ? "#FF3030" : "#808080";
-	//this.outline.setStroke({width: 2, color: '#808080'});
-	dojox.gfx.fx.animateStroke({
-	    shape: this.outline,
-	    duration: 500,
-	    color: {start: "#FF3030", end: endColor},
-	    width: {start: 3, end: 2},
-	    join:  {values: ["miter", "bevel", "round"]}
-	}).play();	
+	// this.outline.setStroke({width: 2, color: '#808080'});
+	dojox.gfx.fx.animateStroke( {
+		shape : this.outline,
+		duration : 500,
+		color : {
+			start : "#FF3030",
+			end : endColor
+		},
+		width : {
+			start : 3,
+			end : 2
+		},
+		join : {
+			values : [ "miter", "bevel", "round" ]
+		}
+	}).play();
 },
-onClick: function() {
+onClick : function() {
 	this.group.moveToFront();
 	this.pulse();
-	dojo.publish("goat.component.onclick."+this.id, [this]);
+	dojo.publish("goat.component.onclick." + this.id, [ this ]);
 },
-onMouseEnter: function() {
-	this.outline.setStroke({width: 3, color: '#FF3030'});
-	this.selected=true;
-	dojo.publish("goat.component.onenter."+this.id, [this]);
+onMouseEnter : function() {
+	this.outline.setStroke( {
+		width : 3,
+		color : '#FF3030'
+	});
+	this.selected = true;
+	dojo.publish("goat.component.onenter." + this.id, [ this ]);
 },
-onMouseLeave: function() {
-	this.selected=false;
+onMouseLeave : function() {
+	this.selected = false;
 	this.glow();
-	dojo.publish("goat.component.onexit."+this.id, [this]);
+	dojo.publish("goat.component.onexit." + this.id, [ this ]);
 },
-onRefresh: function() {
-	if(!this.refreshing){
-		this.refreshing=true;
+onRefresh : function() {
+	if (!this.refreshing) {
+		this.refreshing = true;
 		this.refresh();
-		this.refreshing=false;
+		this.refreshing = false;
 	}
+},
+getComponentAppearance : function() {
+	return this.componentAppearance;
 }
 
 });

Modified: incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/ElementLayoutManager.js
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/ElementLayoutManager.js?rev=949987&r1=949986&r2=949987&view=diff
==============================================================================
--- incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/ElementLayoutManager.js (original)
+++ incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/ElementLayoutManager.js Tue Jun  1 09:59:37 2010
@@ -52,6 +52,13 @@ doLayout: function(){	
 	var maxWidth = 0;
     var sepYPos = new Array();
 	
+    // Go through the rendering in two passes, initialisation and then rendering
+	for ( var elementName in this.owningComponent.elements) {
+		var element = this.owningComponent.elements[elementName];
+		element.apply();
+	}
+
+	
 	//console.log("processing array.. ");
 	//walk through each element in the component, and position it relative to 0,0 inside the component.
 	for(var elementName in this.owningComponent.elements){

Modified: incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/Relationship.js
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/Relationship.js?rev=949987&r1=949986&r2=949987&view=diff
==============================================================================
--- incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/Relationship.js (original)
+++ incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/Relationship.js Tue Jun  1 09:59:37 2010
@@ -18,19 +18,22 @@
  */
 //dojo.provide allows pages use all types declared in this resource
 dojo.provide("goat.Relationship");
-dojo.require("goat.RelationshipElement");
+dojo.require("goat.elements.RelationshipElement");
+dojo.require("goat.elements.TriangleDecorator");
 
 dojo.declare("goat.Relationship", [], {
 
 	key: null,
 	sscRelationship: null,
 	relationshipElements: null,
+	theme: null,
 
-constructor : function(sscRelationship) {
+constructor : function(sscRelationship, theme) {
 	//keep this lightweight.. these can be created ONLY to get the key via the next method.. 
 	//all normal constructor logic lives in activate.
 	this.sscRelationship = sscRelationship;
 	this.relationshipElements=new Array();
+	this.theme = theme;
 },
 getKey : function(){
 	if(this.key==null){
@@ -64,8 +67,38 @@ activate : function(){
 	dojo.forEach(this.sscRelationship.consumedBy, function(component){
 		//console.log("processing relationship prov by "+this.sscRelationship.providedBy.id+" to "+component.id);
 		
+		// What values do we expect for the types?
 		//surface, name, type, fromComponent, toComponent, aspects
-		var r = new goat.RelationshipElement(surface, this.sscRelationship.name, this.sscRelationship.type, components[this.sscRelationship.providedBy.id],components[component.id] );
+		var r = new goat.elements.RelationshipElement(surface, this.sscRelationship.name, this.sscRelationship.type, components[this.sscRelationship.providedBy.id],components[component.id] );
+		// Add a decorator if needed 
+		console.log("type is " + this.sscRelationship.type);
+		if(this.sscRelationship.type=="packageImport"){
+	//		this.typeOffset=5;
+	//		this.stroke = '#F08080';
+		}else if(this.sscRelationship.type=="packageExport"){
+	//		this.stroke = '#80F080';
+	//		this.typeOffset=-5;
+		} else if (this.sscRelationship.type == "serviceExport") {
+										// this.stroke = '#F080F0';
+										// this.typeOffset=10;
+										r
+												.addDecorator(new goat.elements.TriangleDecorator(
+														this.theme));
+									} else if (this.sscRelationship.type == "serviceImport") {
+										// this.stroke = '#8080F0';
+										// this.typeOffset=-10;
+										r
+												.addDecorator(new goat.elements.TriangleDecorator(
+														this.theme));
+									} else if (this.sscRelationship.type == "Service") {
+										//		this.stroke = '#8080F0';
+										//		this.typeOffset=-10;
+										var d = new goat.elements.TriangleDecorator(
+												this.theme);
+										r.addDecorator(d);
+									}
+
+		
 		//console.log("create of relationship element complete");
 		this.relationshipElements.push(r);
 		//hmm.. do we want to reverse-register the relationship like this?

Modified: incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/RelationshipAggregator.js
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/RelationshipAggregator.js?rev=949987&r1=949986&r2=949987&view=diff
==============================================================================
--- incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/RelationshipAggregator.js (original)
+++ incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/RelationshipAggregator.js Tue Jun  1 09:59:37 2010
@@ -25,23 +25,25 @@ dojo.declare("goat.RelationshipAggregato
 		type: null,
 		relationships: null,
 		owningComponent: null,
+		componentAppearance: null,
 		
 		constructor : function(/*goat.Component*/owningComponent, type) {
 			this.type=type;
 			this.relationships=new Object();
 			this.owningComponent = owningComponent;
+			this.componentAppearance = owningComponent.getComponentAppearance();
 			
 			//add this aggregation to the component.
-			var property = this.owningComponent.elementRegistry.getProperty(this.owningComponent, "relationship.aggregation."+this.type, this);
+			var property = this.owningComponent.elementRegistry.getProperty(this.owningComponent, this.componentAppearance, "relationship.aggregation."+this.type, this);
 			this.owningComponent.elements["relationship.aggregation."+this.type]=property;
 		},
-		add: function(/*goat.RelationshipElement*/relationship){
+		add: function(/*goat.elements.RelationshipElement*/relationship){
 			var key = this.getKeyForRelationship(relationship);
 			this.relationships[key] = relationship;
 			//console.log("Aggregator annoucing add to '"+"goat.relationshipaggregator.add."+this.owningComponent.id+"."+"relationship.aggregation."+this.type+"'");
 			dojo.publish("goat.relationshipaggregator.add."+this.owningComponent.id+"."+"relationship.aggregation."+this.type, [relationship]);
 		},
-		remove: function(/*goat.RelationshipElement*/relationship){
+		remove: function(/*goat.elements.RelationshipElement*/relationship){
 			//console.log("RelationshipAggregator handling remove for..");
 			//console.log(relationship);
 			var key = this.getKeyForRelationship(relationship);
@@ -49,7 +51,7 @@ dojo.declare("goat.RelationshipAggregato
 			dojo.publish("goat.relationshipaggregator.remove."+this.owningComponent.id+"."+"relationship.aggregation."+this.type, [relationship]);
 			delete this.relationships[key];
 		},
-		getKeyForRelationship: function(/*goat.RelationshipElement*/relationship){
+		getKeyForRelationship: function(/*goat.elements.RelationshipElement*/relationship){
 			var key = ""+relationship.fromComponent.id+"!"+relationship.toComponent.id+"!"+relationship.name;
 			return key;
 		}

Modified: incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/RelationshipManager.js
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/RelationshipManager.js?rev=949987&r1=949986&r2=949987&view=diff
==============================================================================
--- incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/RelationshipManager.js (original)
+++ incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/RelationshipManager.js Tue Jun  1 09:59:37 2010
@@ -37,7 +37,7 @@ constructor : function(/*goat.Component*
 	dojo.subscribe("goat.relationship.create."+owningComponent.id, this, this.registerRelationship);
 	dojo.subscribe("goat.relationship.remove."+owningComponent.id, this, this.removeRelationship);
 },
-registerRelationship: function(/*goat.RelationshipElement*/relationship){	
+registerRelationship: function(/*goat.elements.RelationshipElement*/relationship){	
 	//console.log(">registerRelationship");
 	//console.log(relationship);
 	var aggregator = this.relationships[relationship.type];
@@ -55,7 +55,7 @@ registerRelationship: function(/*goat.Re
 	aggregator.add(relationship);	
 	//console.log("<registerRelationship");
 },
-removeRelationship: function(/*goat.RelationshipElement*/relationship){
+removeRelationship: function(/*goat.elements.RelationshipElement*/relationship){
 	//console.log("Relationship Manager for "+this.owningComponent.id+" handling removal for relationship..");
 	//console.log(relationship);
 	

Modified: incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/ServerSideInterface.js
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/ServerSideInterface.js?rev=949987&r1=949986&r2=949987&view=diff
==============================================================================
--- incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/ServerSideInterface.js (original)
+++ incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/ServerSideInterface.js Tue Jun  1 09:59:37 2010
@@ -17,6 +17,7 @@
  * under the License.
  */
 //callback from dwr, used to remove everything on a provider switch.
+
 function forgetAboutEverything(){
 	console.log("forgetting about everything.. ");
 	
@@ -57,11 +58,12 @@ function forgetAboutEverything(){
  */
 function addComponent(component) {
     console.log("******************* Component data **************");
-	
+
 	//if we dont know about the id yet, setup a new component.
 	if (components[component.id] == null) {
-		//create the component display object			
-		components[component.id] = new goat.Component( surface, component.id, component.componentProperties);
+		//create the component display object		
+		// pass in null for the children for the moment
+		components[component.id] = new goat.Component( surface, component.id, component.componentProperties, null, theme);
 
 		//put it somewhere sensible.
 		initialLayout.placeComponent(components[component.id]);
@@ -78,7 +80,7 @@ function addRelationship(relationship) {
 	console.log("******************* Relationship data **************");
 	console.log(relationship);
 	
-	var r=new goat.Relationship(relationship);
+	var r=new goat.Relationship(relationship, theme);
 	var key=r.getKey();
 	
 	console.log("checking relationship store for "+key);

Added: incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/configuration/ComponentAppearance.js
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/configuration/ComponentAppearance.js?rev=949987&view=auto
==============================================================================
--- incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/configuration/ComponentAppearance.js (added)
+++ incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/configuration/ComponentAppearance.js Tue Jun  1 09:59:37 2010
@@ -0,0 +1,60 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+// dojo.provide allows pages use all types declared in this resource
+dojo.provide("goat.configuration.ComponentAppearance");
+
+dojo.require("goat.configuration.Theme");
+
+dojo.declare("goat.configuration.ComponentAppearance", [], {
+
+	parentAppearance : null,
+
+	theme : null,
+
+	fontFamily : null,
+	fontStretch : null,
+	textFill : null,
+	lineStyle : null,
+	lineColour : null,
+	lineWidth : null,
+	backgroundColour : null,
+
+	constructor : function(theme, parentAppearance) {
+		this.theme = theme;
+		this.parentAppearance = parentAppearance;
+	},
+	getBackgroundColor : function() {
+		if (this.backgroundColor != null) {
+			return this.backgroundColor;
+		} else if (this.parentAppearance != null) {
+			return parentAppearance.getBackgroundColor();
+		} else {
+			return this.theme.getBundleBackgroundColor();
+		}
+	},
+	setBackgroundColor : function(backgroundColor) {
+		this.backgroundColor = backgroundColor;
+	},
+
+	useLinearShading : function() {
+		return this.theme.shouldUseLinearShading();
+
+	},
+	greyOutInactiveBundles : function() {
+		return this.theme.shouldGreyOutInactiveBundles();
+	},
+});

Added: incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/configuration/Theme.js
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/configuration/Theme.js?rev=949987&view=auto
==============================================================================
--- incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/configuration/Theme.js (added)
+++ incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/configuration/Theme.js Tue Jun  1 09:59:37 2010
@@ -0,0 +1,58 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+// dojo.provide allows pages use all types declared in this resource
+dojo.provide("goat.configuration.Theme");
+
+/*
+ * Still TODO: Read in the configuration from a flat file on the server side
+ * Read in the configuration from a cookie
+ * Provide a GUI for setting the theme aspects
+ * Provide pre-canned themes for users to choose from
+ */
+dojo.declare("goat.configuration.Theme", [], {
+
+	// object properties
+	greyOutInactiveBundles : null,
+	useLinearShading : null,
+	showState : null,
+	showVersion : null,
+	bundleBackgroundColor: "#ffff80",
+
+	constructor : function() {
+		this.greyOutInactiveBundles = true;
+		this.useLinearShading = true;
+		this.showState = true;
+		this.showVersion = true;
+	},
+	shouldGreyOutInactiveBundles: function() {
+		return this.greyOutInactiveBundles;
+	},
+	shouldUseLinearShading: function() {
+		return this.useLinearShading;
+	},
+	getBundleBackgroundColor: function() {
+		return this.bundleBackgroundColor;
+	},
+	getServiceBackgroundColor: function() {
+		return "#FFFF33";
+	},
+	getTriangleSize: function() {
+		return 20;
+	}
+	
+
+});

Added: incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/ComponentColorElement.js
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/ComponentColorElement.js?rev=949987&view=auto
==============================================================================
--- incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/ComponentColorElement.js (added)
+++ incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/ComponentColorElement.js Tue Jun  1 09:59:37 2010
@@ -0,0 +1,67 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+// dojo.provide allows pages use all types declared in this resource
+dojo.provide("goat.elements.ComponentColorElement");
+
+dojo.require("goat.configuration.Theme");
+dojo.require("goat.configuration.ComponentAppearance");
+
+dojo
+		.declare("goat.elements.ComponentColorElement",
+				[ goat.elements.ElementBase ], {
+
+					value : null,
+					componentAppearance: null,
+
+					constructor : function(component, componentAppearance, /* String */type, /* String */
+							value) {
+						this.component = component;
+						this.componentAppearance = componentAppearance;
+						this.value = value;
+						this.type = type;
+						this.hint = "none";
+						console.log("on construction is " + this.value)
+			},
+					getWidth : function() {
+						return 0;
+					},
+					getHeight : function() {
+						return 0;
+					},
+					render : function() {
+						// No special rendering action needed
+					},
+					apply : function() {
+						if (this.type == "component.property.State") {
+							if (this.componentAppearance.greyOutInactiveBundles()) {
+								if (this.value != "ACTIVE") {
+									this.componentAppearance
+											.setBackgroundColor("#808080");
+								}
+							}
+						}
+
+					},
+					update : function(value) {
+						this.value = value;
+					},
+					remove : function() {
+						// no op, we only exist due to the color of the owning
+						// component..
+				}
+
+				});

Modified: incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/ElementBase.js
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/ElementBase.js?rev=949987&r1=949986&r2=949987&view=diff
==============================================================================
--- incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/ElementBase.js (original)
+++ incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/ElementBase.js Tue Jun  1 09:59:37 2010
@@ -19,8 +19,12 @@
 // dojo.provide allows pages use all types declared in this resource
 dojo.provide("goat.elements.ElementBase");
 
+dojo.require("goat.configuration.Theme");
+dojo.require("goat.configuration.ComponentAppearance");
+
 dojo.declare("goat.elements.ElementBase", [], {
 	
+		componentAppearance: null,
 	    type: null,
 	    component: null,
 	    x: 0,
@@ -29,7 +33,7 @@ dojo.declare("goat.elements.ElementBase"
 		height: 0,
 		hint: "top",
 
-		constructor : function(component) {
+		constructor : function(component, componentAppearance) {
 			//not really called (naughty sub-classes dont chain their constructors..)
 	        
 	        //DO NOT put things onscreen during the constructor, delay that until 'render' is invoked if possible.
@@ -45,6 +49,9 @@ dojo.declare("goat.elements.ElementBase"
 			//called to obtain the height of this element for layout purposes
 			return -1;
 		},
+		apply: function() {
+			//called before render to initialise shared characteristics (like colour)
+		},
 		render: function() {
 			//called to add this element to the screen at this.x, this.y
 		},

Modified: incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/ElementRegistry.js
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/ElementRegistry.js?rev=949987&r1=949986&r2=949987&view=diff
==============================================================================
--- incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/ElementRegistry.js (original)
+++ incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/ElementRegistry.js Tue Jun  1 09:59:37 2010
@@ -24,11 +24,13 @@ dojo.provide("goat.elements.ElementRegis
 
 dojo.require("goat.elements.TextComponentProperty");
 dojo.require("goat.elements.ComponentContainer");
-dojo.require("goat.elements.RelationshipAggregation");
-dojo.require("goat.elements.ComponentColorProperty");
+dojo.require("goat.elements.TwistieAggregation");
+dojo.require("goat.elements.ComponentColorElement");
+
+dojo.require("goat.configuration.ComponentAppearance");
 
 dojo.declare("goat.elements.ElementRegistry", [], {
-	
+
 constructor : function() {
 	if(registry==null){
 		registry = this;
@@ -44,17 +46,19 @@ constructor : function() {
 	return registry;
 },
 
-/*goat.elements.ElementBase*/ getProperty : function(component, /*String*/type, /*Object*/value){
+/*goat.elements.ElementBase*/ getProperty : function(component, /*goat.configuration.ComponentAppearance*/ componentAppearance, /*String*/type, /*Object*/value){
 	
+	// TODO fill in the rest of the arguments to the other elements
 	//this sort of resolution needs to be handled by Config.
 	if(type=="component.property.State"){
-		return new goat.elements.ComponentColorProperty(component,type,value);
+		console.log("constructing with " + value)
+		return new goat.elements.ComponentColorElement(component, componentAppearance, type,value);
 	}else if(type.match("^component.property.")=="component.property."){
 		return new goat.elements.TextComponentProperty(component,type,value);
 	}else if(type.match("^component.container")=="component.container"){
 		return new goat.elements.ComponentContainer(component, type, value);
 	}else if(type.match("^relationship.aggregation.")=="relationship.aggregation."){
-		return new goat.elements.RelationshipAggregation(component, type, value);
+		return new goat.elements.TwistieAggregation(component, type, value);
 	}
 	//else.. unknown property.. ignore it.
 }

Added: incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/RelationshipElement.js
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/RelationshipElement.js?rev=949987&view=auto
==============================================================================
--- incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/RelationshipElement.js (added)
+++ incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/RelationshipElement.js Tue Jun  1 09:59:37 2010
@@ -0,0 +1,216 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+dojo.provide("goat.elements.RelationshipElement");
+dojo.require("dojox.gfx");
+dojo.require("dojox.gfx.Moveable");
+dojo.require("goat.Component");
+
+//Relationship
+// represents a line between two components.
+//
+//TODO: 
+// - add methods for pulse & glow.
+// - add methods for line offset adjust & reset
+//   - this will allow lines to move to rows of a twistie, then snap back
+dojo.declare("goat.elements.RelationshipElement", [], {	
+	
+	//relationship properties.
+	fromComponent: null,
+	toComponent: null,
+	name: null,	
+	type: null,
+	
+	//object properties	
+	surface: null,
+	visible: null,
+	typeOffset: 0,
+	
+	//gfx objects
+	line: null,
+	
+	// helper elements
+	decorators: null,
+	
+	//internals
+	stroke: null,
+	
+	//am I deleted?
+	removed: false,
+	
+	//for the up and coming relationship aspect info.. 
+	aspects: null,
+	
+	subs: null,
+	
+constructor: function(surface, name, type, fromComponent, toComponent, aspects) {
+	this.surface=surface;
+	
+	//console.log("Building relationship elt for "+name+" "+type+" from "+fromComponent.id+" to "+toComponent.id+" ");
+	
+	this.name=name;
+    this.type=type;
+	this.fromComponent=fromComponent;
+	this.toComponent=toComponent;
+	this.aspects=aspects;
+	
+	this.stroke = '#000000';
+    this.setStroke();
+	this.updateVisibility();
+	this.updateLine(); 
+		
+	this.subs=new Array();
+	this.subs.push(dojo.subscribe("goat.component.move."+fromComponent.id, this, this.onComponentMove));
+	this.subs.push(dojo.subscribe("goat.component.move."+toComponent.id, this, this.onComponentMove));
+	this.subs.push(dojo.subscribe("goat.component.hidden."+fromComponent.id, this, this.onComponentHidden));
+	this.subs.push(dojo.subscribe("goat.component.hidden."+toComponent.id, this, this.onComponentHidden));
+	this.subs.push(dojo.subscribe("goat.component.onclick."+toComponent.id, this, this.onComponentClick));
+	this.subs.push(dojo.subscribe("goat.component.onclick."+fromComponent.id, this, this.onComponentClick));
+	
+	this.decorators = new Array();
+	
+	//console.log("Publishing relationship create event");
+	dojo.publish("goat.relationship.create."+fromComponent.id,[this]);
+},
+addDecorator: function(decorator) {
+	decorator.setStroke(this.stroke);
+	decorator.setSurface(this.surface);
+	this.decorators.push(decorator);
+},
+setStroke: function(){	
+	
+	//right idea.. wrong approach.. this needs the registry to provide the renderer for this relationship type.
+	
+	if(this.type=="packageImport"){
+		this.typeOffset=5;
+		this.stroke = '#F08080';
+	}else if(this.type=="packageExport"){
+		this.stroke = '#80F080';
+		this.typeOffset=-5;
+	}else if(this.type=="serviceExport"){
+		this.stroke = '#F080F0';
+		this.typeOffset=10;
+	}else if(this.type=="serviceImport"){
+		this.stroke = '#8080F0';
+		this.typeOffset=-10;
+	}
+},
+updateVisibility: function(){
+	if(this.removed){
+		//console.log("uv EEK.. this line should be dead.. and its aliiiiiive "+this.type+" from "+this.fromComponent.id+" to "+this.toComponent.id);
+		//console.log(this);
+	}
+	
+	this.visible = (!this.fromComponent.hidden) && (!this.toComponent.hidden);
+	
+	if(!this.visible){
+		if(this.line==null){
+			// No need to erase a line which doesn't exist ...
+		}else{
+			this.line.setShape({x1: -1000, y1: -1000, x2: -1000, y2: -1000});
+			dojo.forEach(this.decorators, function(decorator){
+				decorator.makeInvisible();
+			});
+
+		}
+	}else{
+		this.updateLine();
+	}
+},
+updateLine: function(){
+	if(this.removed){
+		//console.log("ul EEK.. this line should be dead.. and its aliiiiiive "+this.type+" from "+this.fromComponent.id+" to "+this.toComponent.id);
+		//console.log(this);
+	}
+	
+	if(this.visible){
+		var fromx = this.fromComponent.x + (this.fromComponent.width / 2) + this.typeOffset;
+		var fromy = this.fromComponent.y + (this.fromComponent.height / 2)+ this.typeOffset;
+		var tox = this.toComponent.x + (this.toComponent.width / 2)+ this.typeOffset;
+		var toy = this.toComponent.y + (this.toComponent.height / 2)+ this.typeOffset;
+			
+		if(this.line==null){
+			this.line = this.surface.createLine({x1: fromx, y1: fromy, x2: tox, y2: toy})
+		            .setStroke(this.stroke);
+		}else{
+			this.line.setShape({x1: fromx, y1: fromy, x2: tox, y2: toy});
+		}
+		
+		// Use a normal for loop since we'd have to hitch context with a
+		// dojo.forEach
+			if (this.decorators != null) {
+				for ( var i = 0; i < this.decorators.length; i++) {
+					this.decorators[i].lineUpdated(this.line);
+				}
+			}
+
+			// Our line should be underneath any decorations
+			this.line.moveToBack();
+		}
+	
+},
+removeSelf: function(){
+	//console.log("Line from "+this.fromComponent.id+" to "+this.toComponent.id+" being removed");
+	//console.log(this);
+	if(!this.removed){
+		this.removed = true;
+		
+		//console.log("Line from "+this.fromComponent.id+" to "+this.toComponent.id+" being removed from surface");
+		this.surface.remove(this.line);
+		dojo.forEach(this.decorators, function(decorator){
+			decorator.removeSelf();
+		});
+		//console.log("Line from "+this.fromComponent.id+" to "+this.toComponent.id+" being marked as deleted");
+		
+		//console.log("Removing line subscriptions to components.");
+		dojo.forEach(this.subs, function(sub){
+			//console.log("unsubscribing.. ");
+			//console.log(sub);
+			dojo.unsubscribe(sub);
+		});
+		
+		this.subs = new Array();
+		
+		dojo.publish("goat.relationship.remove."+this.fromComponent.id,[this]);
+	}else{
+		console.log("Line from "+this.fromComponent.id+" to "+this.toComponent.id+" already marked as deleted");
+	}
+},
+getKey: function(){
+	var key = ""+this.fromComponent.id+"!"+this.toComponent.id+"!"+this.type+"!"+this.name;
+},
+onComponentMove: function(component){
+	this.updateLine();
+},
+onComponentHidden: function(component){
+	this.updateVisibility();
+},
+onComponentClick: function(component){
+	if(this.removed){
+		//console.log("occ EEK.. this line should be dead.. and its aliiiiiive "+this.type+" from "+this.fromComponent.id+" to "+this.toComponent.id);
+	}
+	
+	dojox.gfx.fx.animateStroke({
+	    shape: this.line,
+	    duration: 500,
+	    color: {start: "#FF3030", end: this.stroke},
+	    width: {start: 3, end: 2},
+	    join:  {values: ["miter", "bevel", "round"]}
+	}).play();	
+}
+});

Added: incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/TriangleDecorator.js
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/TriangleDecorator.js?rev=949987&view=auto
==============================================================================
--- incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/TriangleDecorator.js (added)
+++ incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/TriangleDecorator.js Tue Jun  1 09:59:37 2010
@@ -0,0 +1,198 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+dojo.provide("goat.elements.TriangleDecorator");
+dojo.require("dojox.gfx");
+dojo.require("dojox.gfx.Moveable");
+dojo.require("goat.Component");
+
+dojo.require("goat.configuration.Theme");
+
+// Triangle decorator
+// represents a triangle decoration for a line (usually representing a service).
+
+dojo.declare("goat.elements.TriangleDecorator", [], {
+
+	// relationship properties.
+	fromComponent : null,
+	toComponent : null,
+	name : null,
+	type : null,
+
+	// object properties
+	surface : null,
+	typeOffset : 0,
+
+	// gfx objects
+	line : null,
+
+	// internals
+	stroke : null,
+	theme : null,
+
+	// am I deleted?
+	removed : false,
+
+	// for the up and coming relationship aspect info..
+	aspects : null,
+
+	constructor : function(theme) {
+		this.theme = theme;
+	},
+	makeInvisible : function() {
+		this.triangle.setShape( {
+			x1 : -1000,
+			y1 : -1000,
+			x2 : -1000,
+			y2 : -1000
+		});
+	},
+	setSurface : function(newSurface) {
+		this.surface = newSurface;
+	},
+	setStroke : function(newStroke) {
+		this.stroke = newStroke;
+	},
+	lineUpdated : function(line) {
+		if (this.removed) {
+			// console.log("ul EEK.. this line should be dead.. and its
+			// aliiiiiive "+this.type+" from "+this.fromComponent.id+" to
+			// "+this.toComponent.id);
+			// console.log(this);
+		}
+
+		if (line != null) {
+			var shape = line.getShape();
+			var fromx = shape.x1;
+			var fromy = shape.y1;
+			var tox = shape.x2;
+			var toy = shape.y2;
+
+			// A somewhat awkwardly named method ...
+			var triangleSize = this.theme.getTriangleSize();
+			var deltax = tox - fromx;
+			var deltay = toy - fromy;
+			// Do a square root to work out the line length
+			// Will this hurt us on performance? An approximation would do
+			// if so ...
+			var lineLength = Math.sqrt(deltax * deltax + deltay * deltay);
+			// Assume the triangles are equilateral
+			var divider = lineLength / triangleSize;
+			// The triangle starts in the middle of the line
+			var tx1 = (fromx + tox) / 2;
+			var ty1 = (fromy + toy) / 2;
+			var tx2 = tx1 - deltax / divider + deltay / divider;
+			var ty2 = ty1 - deltay / divider - deltax / divider;
+			var tx3 = tx1 - deltax / divider - deltay / divider;
+			var ty3 = ty1 - deltay / divider + deltax / divider;
+
+			if (this.triangle == null) {
+				this.triangle = this.surface.createPolyline( [ {
+					x : tx1,
+					y : ty1
+				}, {
+					x : tx2,
+					y : ty2
+				}, {
+					x : tx3,
+					y : ty3
+				}, {
+					x : tx1,
+					y : ty1
+				} ]);
+				this.triangle.setStroke(this.stroke);
+
+			} else {
+				this.triangle.setShape( [ {
+					x : tx1,
+					y : ty1
+				}, {
+					x : tx2,
+					y : ty2
+				}, {
+					x : tx3,
+					y : ty3
+				}, {
+					x : tx1,
+					y : ty1
+				} ]);
+
+				if (this.theme.shouldUseLinearShading()) {
+					this.triangle.setFill( {
+						type : "linear",
+						x1 : tx1,
+						y1 : ty1,
+						x2 : tx2,
+						y2 : ty2,
+						colors : [ {
+							offset : 0,
+							color : this.theme.getServiceBackgroundColor()
+						}, {
+							offset : 1,
+							color : "white"
+						} ]
+					});
+				} else {
+					this.triangle.setFill(this.theme
+							.getServiceBackgroundColor());
+
+				}
+			}
+		}
+	},
+	removeSelf : function() {
+		if (!this.removed) {
+			this.removed = true;
+
+			this.surface.remove(this.triangle);
+			// console.log("Line from "+this.fromComponent.id+" to
+			// "+this.toComponent.id+" being marked as deleted");
+		}
+	},
+	getKey : function() {
+		var key = "" + this.fromComponent.id + "!" + this.toComponent.id + "!"
+				+ this.type + "!" + this.name;
+	},
+	onComponentMove : function(component) {
+		this.updateLine();
+	},
+	onComponentHidden : function(component) {
+		this.updateVisibility();
+	},
+	onComponentClick : function(component) {
+		if (this.removed) {
+			// console.log("occ EEK.. this line should be dead.. and its
+	// aliiiiiive "+this.type+" from "+this.fromComponent.id+" to
+	// "+this.toComponent.id);
+}
+
+dojox.gfx.fx.animateStroke( {
+	shape : this.triangle,
+	duration : 500,
+	color : {
+		start : "#FF3030",
+		end : this.stroke
+	},
+	width : {
+		start : 3,
+		end : 2
+	},
+	join : {
+		values : [ "miter", "bevel", "round" ]
+	}
+}).play();
+}
+});

Added: incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/TwistieAggregation.js
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/TwistieAggregation.js?rev=949987&view=auto
==============================================================================
--- incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/TwistieAggregation.js (added)
+++ incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/goat/elements/TwistieAggregation.js Tue Jun  1 09:59:37 2010
@@ -0,0 +1,136 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+// dojo.provide allows pages use all types declared in this resource
+dojo.provide("goat.elements.TwistieAggregation");
+dojo.require("goat.elements.ElementBase");
+dojo.require("goat.RelationshipAggregator");
+dojo.require("goat.TwistieSection");
+
+/*
+ * this class works .. but isnt very smart.. it's using the old twistie section code, 
+ * which has no way of knowing when it's item list changed inside it.. 
+ * 
+ * to handle this.. this bit of code merely discards & rebuilds the twistie every time
+ * a list change occurs.. this is a little bit overkill.. =)
+ */
+
+dojo.declare("goat.elements.TwistieAggregation", goat.elements.ElementBase, {
+
+		/*goat.RelationshipAggregator*/ content: null,
+		/*goat.TwistieSection*/ twistie: null,
+		group: null,
+		addsub: null,
+		removesub: null,
+		
+		built: false,
+		
+		constructor : function(component, /*String*/ type, /*goat.RelationshipAggregator*/ content) {
+	        //console.log("Building TwistieAggregation element");
+	        
+	        this.component=component;
+			this.type=type;
+			this.content=content;
+			this.hint="row";
+			
+			
+			
+			this.group=this.component.group.createGroup();
+			this.component.group.remove(this.group);
+			
+			this.buildTwistie();
+			
+			//console.log("-Subscribing to.. '"+"goat.relationshipaggregator.add."+this.component.id+"."+this.type+"'");
+			//console.log("-Subscribing to.. '"+"goat.relationshipaggregator.remove."+this.component.id+"."+this.type+"'");
+			
+			this.addsub=dojo.subscribe("goat.relationshipaggregator.add."+this.component.id+"."+this.type, this, this.onAdd);
+			this.removesub=dojo.subscribe("goat.relationshipaggregator.remove."+this.component.id+"."+this.type, this, this.onRemove);		
+		},
+		getContent : function(){
+			return this.content;
+		},
+		getWidth : function(){
+			//console.log("Aggregation Element "+this.type+" for "+this.component.id+" returning a width of "+this.twistie.width);
+			return this.twistie.width;
+		},
+		getHeight: function(){
+			//console.log("Aggregation Element "+this.type+" for "+this.component.id+" returning a height of "+this.twistie.height);
+			return this.twistie.height;
+		},
+		render: function(){
+			if(!this.built){
+				this.built=true;
+				this.component.group.add(this.group);
+			}
+			
+			//console.log("Setting twistie position to .. "+this.x+" "+this.y);
+			this.twistie.updatePosition(this.x,this.y);			
+		},
+		update: function(value){
+			//no-op.. aggregators pull their values from the live content object.
+		},
+		remove: function(value){
+			//console.log("Removing aggregation "+this.type+" from display of component")
+			this.component.group.remove(this.group);
+			dojo.unsubscribe(this.addsub);
+			dojo.unsubscribe(this.removesub);
+		},		
+		onAdd: function(/*RelationshipElement[]*/args){
+			console.log("Aggregation Element notified of Relationship being added");
+			//console.log(args[0]);
+			this.buildTwistie();
+			//notify parent we have altered our size.. 
+		}, 
+		onRemove: function(/*RelationshipElement[]*/args){
+			console.log("Aggregation Element notified of Relationship being removed");
+			//console.log(args[0]);
+			this.buildTwistie();
+			//notify parent we have altered our size.. 
+		}, 
+		buildTwistie: function(){
+			//flush the old twistie.. if we had one!
+			if(this.group!=null){
+				console.log("Flushing old twistie");
+				this.component.group.remove(this.group);
+				this.group=this.component.group.createGroup();
+			}
+			
+			var _this=this;
+			function getItemsCallBack(){
+				//filter out (or blend) duplicates.. 
+				//will become more important when we need to connect various stuff to different anchors
+				var dupeSet = new Object();
+				_this.twistie.items=new Array();
+				for( var relationshipKey in _this.content.relationships ){
+					var /*goat.elements.RelationshipElement*/ relationship = _this.content.relationships[relationshipKey];
+					if(dupeSet[relationship.name]==null){
+						dupeSet[relationship.name]=relationship;
+						_this.twistie.items.push(relationship.name);
+					}
+				}
+				dupeSet=null;
+				
+				_this.twistie.addItemsToDisplay();
+			}	
+			var twistieName = this.type.substring("relationship.aggregation.".length, this.type.length);
+			this.twistie = new goat.TwistieSection(twistieName, this.group, this.component, this.x, this.y, getItemsCallBack);
+			
+			console.log("requesting component refresh as rebuilt twistie may not have same dimensions");
+			this.component.refresh();
+		}		
+});

Modified: incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/index.html
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/index.html?rev=949987&r1=949986&r2=949987&view=diff
==============================================================================
--- incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/index.html (original)
+++ incubator/aries/trunk/samples/goat/goat-web/src/main/resources/web/index.html Tue Jun  1 09:59:37 2010
@@ -72,6 +72,8 @@
 	dojo.require("goat.SimpleInitialLayout");
 	dojo.require("goat.DwrLoadingDialog");
 
+	dojo.require("goat.configuration.Theme");
+	
 	//provides the basic layout when 1st loading up bundles.
     var initialLayout = null;
     //tracks the current provider for the app.
@@ -82,6 +84,8 @@
 	
 	//the global relationship array, indexed by relationship key.
 	var relationships = new Array();	
+
+	var theme = null;
 	
 	//various gfx decls.
 	var container = null, surface = null, surface_size = null;	
@@ -93,6 +97,9 @@
 			width : 1000,
 			height : 1000
 		};
+		//the global theme - in time, we may wish to make its initialization more sophisticated
+		theme = new goat.configuration.Theme();
+
 		initialLayout = new goat.SimpleInitialLayout(1000,1000);
 		var loadingDialog = new goat.DwrLoadingDialog();
 		var componentStatusGrid = new goat.ComponentStatusGrid("stateTableID");