var ARROW_IMG_SRC = '';
var ARROW_WIDTH = 33;
var ARROW_HEIGHT = 40;
var CONV_FACTOR = 96.0;
// Required for callbacks
var plugin;
var rootCanvas;
var pageCanvas;
var imgArrow;
var tooltip;
var SelectNodes = parent.SelectNodes
if (!window.SilverlightDisplay)
window.SilverlightDisplay = {};
SilverlightDisplay.Drawing = function()
{
}
SilverlightDisplay.Drawing.prototype =
{
handleLoad: function(xaml_plugin, userContext, rootElement)
{
plugin = xaml_plugin;
imgArrow = null;
this.tooltip = null;
this.strLastShape = ""; // Name of the last shape that created an event
this.shapeSelIndex = -1;
this.shapeSel = null;
this.root = rootElement;
rootCanvas = rootElement;
// Find the page's canvas
for (var i = 0; i < rootCanvas.Children.Count; i++)
{
var child = rootCanvas.Children.GetItem(i);
if (child.toString () == "Canvas" && child.Name == "D")
{
pageCanvas = child;
break;
}
}
this.scaleX = 1;
this.scaleY = 1;
var strTransform = '';
rootCanvas.RenderTransform = plugin.Content.CreateFromXAML(strTransform);
parent.viewMgr.origWidth = pageCanvas.Width;
parent.viewMgr.origWH = pageCanvas.Width / pageCanvas.Height;
rootElement.addEventListener ("LostFocus", Silverlight.createDelegate (this, this.handleLostFocus));
this.addListenersToShapes (pageCanvas);
},
onResize: function(width, height)
{
// Calculate the new scale
this.scaleX = width / rootCanvas.Width;
this.scaleY = height / rootCanvas.Height;
rootCanvas.RenderTransform.ScaleX = this.scaleX;
rootCanvas.RenderTransform.ScaleY = this.scaleY;
plugin.width = width;
plugin.height = height;
},
addListenersToShapes: function(canvasNode)
{
// Add listeners to all the shapes with properties
for (var i = 0; i < canvasNode.Children.Count; i++)
{
var child = canvasNode.Children.GetItem(i);
if (child.toString () == "Canvas" && child.Name != "")
{
this.addListenersToShapes (child); // Recursive call
}
else
{
continue;
}
var shapeID = child.Name.substring (1, child.Name.length); // Remove the _
var shapeNode = parent.parent.FindShapeXML (pageID, shapeID);
if(shapeNode)
{
var tmpProp = SelectNodes(shapeNode, "Prop").length > 0;
var tmpNodes = false;
if (!tmpProp)
tmpNodes = SelectNodes(shapeNode, "Scratch/B/SolutionXML/HLURL:Hyperlinks/HLURL:Hyperlink");
if (tmpProp || tmpNodes.length > 0)
{
child.addEventListener ("MouseEnter", Silverlight.createDelegate (this, this.handleMouseEnter));
child.addEventListener ("MouseLeftButtonDown", Silverlight.createDelegate (this, this.handleMouseDown));
child.addEventListener ("MouseLeftButtonUp", Silverlight.createDelegate (this, this.handleMouseUp));
child.addEventListener ("MouseLeave", Silverlight.createDelegate (this, this.handleMouseLeave));
if (tmpNodes.length > 0)
child.Cursor = "Hand";
}
}
}
},
handleKeyDown: function(sender, eventArgs)
{
},
getTextBlock: function(text, left, top)
{
return '';
},
removeTooltip: function()
{
if (this.tooltip != null)
{
// Remove the tooltip from the Canvas object.
pageCanvas.Children.Remove(this.tooltip);
}
this.tooltip = null;
},
addTooltip: function(sender, eventArgs, type)
{
// Determine whether the tooltip is created.
if (this.tooltip == null)
{
var strHL, strProps;
if (type == 'focus')
{
strHL = parent.parent.strFocusHLTooltipText;
strProps = parent.parent.strFocusPropsTooltipText;
}
else
{
strHL = parent.parent.strHLTooltipText;
strProps = parent.parent.strPropsTooltipText;
}
// Build the tooltip string
var shapeIDStr = sender.name;
var shapeID = parseInt(shapeIDStr.substring(1, shapeIDStr.length));
var shapeNode = parent.parent.FindShapeXML (pageID, shapeID);
var txtBlocks = new Array(3);
var border = 2;
var iHeight = border;
var iWidth = 0;
if ( shapeNode != null )
{
var textNode = SelectNodes(shapeNode, "Text");
if (textNode != null && textNode.length > 0)
{
var strNodeTitle = textNode[0].textContent;
if (!strNodeTitle)
strNodeTitle = textNode[0].text;
var strTxtBlock = this.getTextBlock (strNodeTitle, border, iHeight);
txtBlocks[0] = plugin.content.createFromXaml (strTxtBlock, false);
iHeight += txtBlocks[0].ActualHeight;
iWidth = Math.max (iWidth, txtBlocks[0].ActualWidth + border * 2);
}
// Show the prop tooltip only when there are
// properties in the shape and the details pane is available
var propNode = SelectNodes(shapeNode, "Prop");
if (propNode != null && propNode.length > 0 &&
parent.frmToolbar.widgets != null && parent.frmToolbar.widgets.Details != null)
{
var strTxtBlock = this.getTextBlock (strProps, border, iHeight);
txtBlocks[1] = plugin.content.createFromXaml (strTxtBlock);
iHeight += txtBlocks[1].ActualHeight;
iWidth = Math.max (iWidth, txtBlocks[1].ActualWidth + border * 2);
}
var hlObj = parent.parent.GetHLAction (shapeNode, pageID, shapeID);
if (hlObj != null && (hlObj.DoFunction.length > 0 || hlObj.Hyperlink.length > 0))
{
var strTxtBlock = this.getTextBlock (strHL, border, iHeight);
txtBlocks[2] = plugin.content.createFromXaml (strTxtBlock);
iHeight += txtBlocks[2].ActualHeight;
iWidth = Math.max (iWidth, txtBlocks[2].ActualWidth + border * 2);
}
}
if(iWidth == 0)
return;
// Define the XAML fragment for the background of the tooltip.
var xamlFragment = '';
// Create the XAML fragment for the tooltip.
this.tooltip = plugin.content.createFromXaml (xamlFragment, false);
// Position the tooltip at a relative x/y coordinate value.
var cursorPosition = eventArgs.getPosition (pageCanvas);
this.tooltip["Canvas.Left"] = cursorPosition.x;
this.tooltip["Canvas.Top"] = cursorPosition.y + 20 * (1 / this.scaleY);
if(cursorPosition.x + this.tooltip.Width > pageCanvas.Width)
{
this.tooltip["Canvas.Left"] = pageCanvas.Width - this.tooltip.Width;
}
else if(cursorPosition.y + this.tooltip.Height + 20 > pageCanvas.Height)
{
this.tooltip["Canvas.Top"] = pageCanvas.Height - this.tooltip.Height;
}
}
// Add the tooltip to the Canvas object.
pageCanvas.Children.Add (this.tooltip);
for (var i = 0; i < txtBlocks.length; i++)
{
if (txtBlocks[i] != null)
this.tooltip.Children.Add (txtBlocks[i]);
}
setTimeout("if(window.SilverlightObj.strLastShape == '" + sender.name + "') window.SilverlightObj.removeTooltip()", 2000);
},
handleMouseEnter: function(sender, eventArgs)
{
if (this.tooltip != null)
this.removeTooltip ();
this.addTooltip (sender, eventArgs, 'mouse');
this.strLastShape = sender.name;
},
handleMouseDown: function(sender, eventArgs)
{
clickMenu ();
},
handleDownloaderLoad: function(downloader, eventArgs)
{
var plugin = sender.getHost();
var xamlPage = plugin.content.CreateFromXamlDownloader(downloader, "");
var root = sender.findName("rootCanvas");
root.Children.Add(xamlPage);
},
handleMouseUp: function(sender, eventArgs)
{
if(this.shapeSel != null)
this.shapeSel.Opacity = 1.0;
this.shapeSel = sender;
this.shapeSel.Opacity = 0.5;
var shapeIDStr = sender.name;
var shapeID = parseInt(shapeIDStr.substring(1, shapeIDStr.length));
parent.OnShapeClick(pageID, shapeID, null, eventArgs);
},
handleMouseLeave: function(sender, eventArgs)
{
this.removeTooltip();
},
handleLostFocus: function(sender, eventArgs)
{
if(this.shapeSel != null)
this.shapeSel.Opacity = 1.0;
this.shapeSel = null;
},
getIndexFromName: function(strName)
{
var children = pageCanvas.Children;
for(var i = 0; i < children.Count; i++)
{
var child = children.GetItem(i);
if(child.Name == strName)
return i;
}
return -1;
},
isSelectable: function(shape)
{
if(shape == null)
return false;
if(shape.Name && shape.Name.length >= 2)
{
var shapeID = shape.Name.substring (1, shape.Name.length); // Remove the _
var shapeNode = parent.parent.FindShapeXML (pageID, shapeID);
if(shapeNode)
{
if (SelectNodes(shapeNode, "Prop").length > 0 ||
SelectNodes(shapeNode, "Scratch/B/SolutionXML/HLURL:Hyperlinks/HLURL:Hyperlink").length > 0)
{
return true;
}
}
}
return false;
},
selectNextShape: function()
{
if(this.shapeSel == null)
{
this.shapeSel = this.nextShape(pageCanvas);
}
else
{
this.shapeSel.Opacity = 1.0;
this.shapeSel = this.nextShape(this.shapeSel);
}
if(this.shapeSel)
this.shapeSel.Opacity = 0.5;
return this.shapeSel;
},
selectPrevShape: function()
{
if(this.shapeSel == null)
{
this.shapeSel = this.prevShape(pageCanvas);
}
else
{
this.shapeSel.Opacity = 1.0;
this.shapeSel = this.prevShape(this.shapeSel);
}
if(this.shapeSel)
this.shapeSel.Opacity = 0.5;
return this.shapeSel;
},
// Called when we gain the focus for the first time from tabbing
startHandlingTabs: function(front)
{
if(front)
return (this.selectNextShape() != null);
else
return (this.selectPrevShape() != null);
},
nextShape: function(startShape, currShape, lastVisited) // currShape and currIndex should only be used by this function itself
{
// Visit
if(currShape != null && startShape != currShape && this.isSelectable(currShape))
{
return currShape;
}
if(currShape == null)
{
currShape = startShape;
}
// Check this nodes children, making sure we don't recheck nodes as we traverse upwards
var shapeFound = null;
if(currShape.toString () == 'Canvas' && currShape.Children.Count != 0)
{
var start = 0;
if(lastVisited != null)
{
for(var i = 0; i < currShape.Children.Count; i++)
{
if(currShape.Children.GetItem(i).Name == lastVisited.Name)
{
start = i + 1;
break;
}
}
}
for(var i = start; i < currShape.Children.Count; i++)
{
shapeFound = this.nextShape(startShape, currShape.Children.GetItem(i));
if(shapeFound)
return shapeFound;
}
}
if(currShape == startShape && startShape.Name && startShape.Name != "D") // We searched all child nodes and now need to search parent nodes
{
return this.nextShape(currShape.GetParent(), null, currShape);
}
return null;
},
// Traverses upwards until it finds a possibility of child shapes
prevShape: function(currShape)
{
if(currShape == pageCanvas)
{
return this.RLVSearch(currShape);
}
// Start traversing R->L starting to the left of the currShape
var parent = currShape.GetParent();
var startIndex;
while(currShape.Name != pageCanvas.Name)
{
for(startIndex = parent.Children.Count - 1; startIndex >= 0; startIndex--)
{
if(parent.Children.GetItem(startIndex).Name == currShape.Name)
break;
}
startIndex--;
if(startIndex != -1)
return this.RLVSearch(parent, startIndex)
parent = parent.GetParent();
currShape = currShape.GetParent();
}
return null;
},
// Traverses downwards until it finds a child shape, otherwise it tries to hop up again
RLVSearch: function(currShape, startIndex, rootShape)
{
if(currShape.toString () == 'Canvas' && currShape.Children.Count != 0)
{
// R to L search
if(startIndex == null)
startIndex = currShape.Children.Count - 1;
if(rootShape == null)
rootShape = currShape;
for(var i = startIndex; i >= 0; i--)
{
var shapeFound = this.RLVSearch(currShape.Children.GetItem(i),null,rootShape);
if(shapeFound)
return shapeFound;
}
if(this.isSelectable(currShape))
return currShape;
}
// We can still hop up
if(currShape != pageCanvas && currShape == rootShape)
return this.prevShape(currShape);
return null;
},
getBounds: function(shape)
{
var strTag = shape.Tag;
var bounds = new Bounds();
bounds.x = getValueFromTag(strTag, "x");
bounds.y = getValueFromTag(strTag, "y");
bounds.width = getValueFromTag(strTag, "width");
bounds.height = getValueFromTag(strTag, "height");
return bounds;
}
}
function getValueFromTag(tag, propName)
{
var start = tag.indexOf('"' + propName + '"') + propName.length + 3;
var end = tag.indexOf(',', start);
if(end == -1) end = tag.indexOf('\\', start);
return tag.substring(start,end);
}
function SetXAMLLocation(pageID, shapeID, pinX, pinY)
{
clickMenu ();
var xVal = CONV_FACTOR * pinX;
var yVal = rootCanvas.Height - (CONV_FACTOR * pinY);
var centeredX = xVal - Math.round(ARROW_WIDTH / 2);
var xamlFragment = '';
if(imgArrow)
rootCanvas.Children.Remove(imgArrow);
imgArrow = plugin.content.createFromXaml(xamlFragment, false);
var boolNeedToScroll = false;
var doc = document;
if( !( (xVal - ARROW_WIDTH / 2) > doc.body.scrollLeft && (xVal + ARROW_WIDTH / 2) < (doc.body.scrollLeft + doc.body.clientWidth) ))
{
boolNeedToScroll = true;
}
if( !( (yVal - ARROW_HEIGHT) > doc.body.scrollTop && (yVal + ARROW_HEIGHT) < (doc.body.scrollTop + doc.body.clientHeight) ))
{
boolNeedToScroll = true;
}
if( boolNeedToScroll == true )
{
window.scrollTo( xVal - doc.body.clientWidth / 2, yVal - doc.body.clientHeight / 2);
}
rootCanvas.Children.Add(imgArrow);
setTimeout("RemoveArrow()", 2000);
}
function RemoveArrow()
{
if(imgArrow)
rootCanvas.Children.Remove(imgArrow);
imgArrow = null;
}
function XAMLZoomChange(size)
{
if(size)
{
if(size == "up")
{
size = zoomLast + 50;
}
else if(size == "down")
{
size = zoomLast - 50;
}
size = parseInt(size);
if(typeof(size) != "number")
size = 100;
}
else
{
size = 100;
}
clickMenu ();
viewMgr.zoomLast = size;
var zoomFactor = size/100;
var width = plugin.clientWidth;
var height = plugin.clientHeight;
var margin = parseInt(document.body.style.margin) * 2;
var clientWidth = document.body.clientWidth;
var clientHeight = document.body.clientHeight;
// Get the scroll properties
var newScrollLeft = document.body.scrollLeft;
var newScrollTop = document.body.scrollTop;
// ?Miscalculate the drawable width
var winwidth = clientWidth - margin;
var winheight = clientHeight - margin;
// Calculate the ratio to turn pixel coordinates of the image into screen coordinates
var widthRatio = winwidth / width;
var heightRatio = winheight / height;
// Calculate the new size and maintain aspect ratio
if (widthRatio < heightRatio)
{
width = zoomFactor * winwidth;
height = width / this.origWH;
}
else
{
height = zoomFactor * winheight;
width = height * this.origWH;
}
drawing.onResize(Math.max(width, 1), Math.max(height, 1));
// Resave the new size (also saved in this.zoomLast)
this.sizeLast = size;
// Calculate the center screen coordinate (includes offset for scrolling)
var centerX = (zoomFactor / viewMgr.zoomFactor) * (newScrollLeft + (clientWidth / 2) - this.s.posLeft);
var centerY = (zoomFactor / viewMgr.zoomFactor) * (newScrollTop + (clientHeight / 2) - this.s.posTop);
viewMgr.zoomFactor = zoomFactor;
// TODO Add padding if we are zoomed out, use less if zoomed in (width and height)
if (width <= clientWidth)
{
this.s.posLeft = Math.max( 0, (clientWidth / 2) - (width / 2));
}
else
{
var left = centerX - (clientWidth / 2);
if ( left >= 0 )
{
this.s.posLeft = 0;
newScrollLeft = left;
}
else
{
this.s.posLeft = -left;
newScrollLeft = 0;
}
}
if (height <= clientHeight)
{
this.s.posTop = Math.max( 0, (clientHeight / 2) - (height / 2));
}
else
{
var top = centerY - (clientHeight / 2);
if ( top >= 0 )
{
this.s.posTop = 0;
newScrollTop = top;
}
else
{
this.s.posTop = -top;
newScrollTop = 0;
}
}
window.scrollTo(newScrollLeft, newScrollTop);
// TODO Make the image visible
this.s.visibility = "visible";
var newXOffsetPercent = document.body.scrollLeft / plugin.width;
var newYOffsetPercent = document.body.scrollTop / plugin.height;
var newWidthPercent = document.body.clientWidth / plugin.width;
var newHeightPercent = document.body.clientHeight / plugin.height;
if (viewMgr.viewChanged)
{
viewMgr.viewChanged (newXOffsetPercent, newYOffsetPercent, newWidthPercent, newHeightPercent);
}
if (viewMgr.PostZoomProcessing)
{
viewMgr.PostZoomProcessing(size);
}
}
function XAMLOnScroll()
{
if (viewMgr.viewChanged)
{
var newXOffsetPercent = document.body.scrollLeft / plugin.width;
var newYOffsetPercent = document.body.scrollTop / plugin.height;
viewMgr.viewChanged (newXOffsetPercent, newYOffsetPercent, null, null);
}
}
function XAMLOnResize ()
{
if (viewMgr.zoomLast == 100)
{
viewMgr.Zoom(100);
}
if (viewMgr.viewChanged)
{
var newWidthPercent = document.body.clientWidth / plugin.width;
var newHeightPercent = document.body.clientHeight / plugin.height;
viewMgr.viewChanged (null, null, newWidthPercent, newHeightPercent);
}
}
function XAMLSetView (xOffsetPercent, yOffsetPercent)
{
var leftPixelOffset = xOffsetPercent * plugin.clientWidth;
var topPixelOffset = yOffsetPercent * plugin.clientHeight;
window.scrollTo (leftPixelOffset - this.s.posLeft, topPixelOffset - this.s.posTop);
if (viewMgr.PostSetViewProcessing)
{
viewMgr.PostSetViewProcessing();
}
}
//********************************Silverlight.Thumbnail*****************************************
SilverlightDisplay.Thumbnail = function()
{
this.plugin = null;
this.rootCanvas = null;
this.pageCanvas = null;
this.callbackIndex = null;
this.scale = null;
}
SilverlightDisplay.Thumbnail.prototype =
{
handleLoad: function(rootElement)
{
this.plugin = rootElement.getHost();
this.rootCanvas = rootElement;
// Find the page's canvas
for (var i = 0; i < this.rootCanvas.Children.Count; i++)
{
var child = this.rootCanvas.Children.GetItem(i);
if (child.toString () == "Canvas" && child.Name == "D")
{
this.pageCanvas = child;
break;
}
}
// Fit the canvas into the space given by the zoom window
if(this.rootCanvas.Width > this.rootCanvas.Height)
{
this.scale = this.plugin.clientWidth / this.rootCanvas.Width;
this.rootCanvas['Canvas.Top'] = (this.rootCanvas.Width - this.rootCanvas.Height) / 2 * this.scale;
this.rootCanvas['Canvas.Left'] = 0;
}
else
{
this.scale = this.plugin.clientHeight / this.rootCanvas.Height;
this.rootCanvas['Canvas.Left'] = (this.rootCanvas.Height - this.rootCanvas.Width) / 2 * this.scale;
this.rootCanvas['Canvas.Top'] = 0;
}
var strTransform = '';
this.rootCanvas.RenderTransform = this.plugin.Content.CreateFromXAML(strTransform);
}
}
function Bounds(x, y, width, height)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}