Useful jQuery tips, tricks, and plugins with ASP.NET MVC
Displaying additional image types in XMetaL
1. in 37 minutes Episode 22 Viewing the unviewable: Displaying additional image types in XMetaL Using the InPlaceControl interface to add custom viewer controls Tom Magliery, XML Technology Specialist 12 May 2011 Brought to you by XMetaL Technical Services
2. XMetaL can display images in several common graphics formats (full list in Help) For non-supported formats, XMetaL can use an ActiveX viewer control to display the images You have to supply the viewer You have to do some script customization Purpose of today: show you how to do the script customization Introduction
3. CTM file <OCXReplacement> Associates an ActiveX viewer control with an element Event macros _OnShouldCreate, _OnInitialize, _OnFocus, _OnSynchronize InPlaceControl interface Application.ActiveInPlaceControl gives access to the viewer control during these events Keys to this customization
4. Have an XML element solely dedicated to the special image type: <Visio_Image> Always use viewer control to display this element Need two bits of code: <OCXReplacement> in CTM file _OnInitialize macro Example 1
5. <OCXReplacement> <OCXReplacements> is an optional main element in the CTM file – like <ElementPropertiesList>, <Templates>, etc. Name of your image element Prefix to be used with event macros (can be whatever you want provided the resulting macro name is valid) ... <OCXReplacements> <OCXReplacement> <SelectorName>Visio_Image</SelectorName> <MacroPrefix>VisioViewer</MacroPrefix> <ProgID>VisioViewer.Viewer</ProgID> </OCXReplacement> </OCXReplacements> ... ProgID of your ActiveX viewer control
6. _OnInitialize macro This macro is executed for each <Visio_Image> element in the document. ActiveInPlaceControl object exists for the duration of this macro. Name prefix matches what was in the CTM file. Sets the size for the control. <MACRO name="VisioViewer_OnInitialize" hide="true" lang="JScript"><![CDATA[ varaipc = Application.ActiveInPlaceControl; aipc.Width = 500; aipc.Height = 300; var filename = aipc.Node.getAttribute("href"); aipc.Control.SRC = filename; ]]></MACRO> Node is the element being displayed with this control. Control property gives you access to the IDispatch interface of the viewer control. SRC is a property of the Visio Viewer control. Can also perform other initializations here using the control’s interface, via aipc.Control.*.
7. Use the same image element for built-in and a special image format Use viewer control for special image type <Dual_Purpose_Imagehref=“myVisioDiagram.vsd”/> Fall back to default XMetaL behavior otherwise <Dual_Purpose_Imagehref=“myJPG.jpg”/> Need same code bits as before, plus: <Image> in CTM file _OnShouldCreate macro Example 2
8. Same stuff from before <OCXReplacement> in the CTM – different element name, different macro prefix ... <OCXReplacements> <OCXReplacement> <SelectorName>Dual_Purpose_Image</SelectorName> <MacroPrefix>VV2</MacroPrefix> <ProgID>VisioViewer.Viewer</ProgID> </OCXReplacement> </OCXReplacements> ... _OnInitialize macro does the same thing as before – it’s using the same viewer control <MACRO name="VV2_OnInitialize" hide="true" lang="JScript"><![CDATA[ varaipc = Application.ActiveInPlaceControl; aipc.Width = 500; aipc.Height = 300; var filename = aipc.Node.getAttribute("href"); aipc.Control.SRC = filename; ]]></MACRO>
9. <Image> Handles the fall-back case of built-in image formats. <Dual_Purpose_Image> is designated as an image element in the CTM. ... <Image> <Name>Dual_Purpose_Image</Name> <Source-Attribute>href</Source-Attribute> <Height-Attribute>height</Height-Attribute> <Width-Attribute>width</Width-Attribute> <AltText-Attribute>alt</AltText-Attribute> </Image> ...
10. _OnShouldCreate Use business logic to determine whether XMetaL should be displaying this element in the viewer control in this instance; store the outcome in the ShouldCreate property. Get the href attribute from the element to which this control is (tentatively) attached <MACRO name="VV2_OnShouldCreate" hide="true" lang="JScript"><![CDATA[ varaipc = Application.ActiveInPlaceControl; varhref = aipc.Node.getAttribute("href"); vari = href.lastIndexOf(".vsd"); if (i != -1) { aipc.ShouldCreate = true; } else { aipc.ShouldCreate = false; } ]]></MACRO> Look at the file extension to see if this is a Visio file Set the ShouldCreate property accordingly
11. Using _OnFocus event to manipulate the viewer control Our Visio viewer has APIs for turning on/off various features of the control Suppose we want toolbar, scrollbars, etc. only when the control has focus Example 3
12. _OnFocus This macro is executed both on focus and on blur – when the user clicks in or out of the viewer control. UserMovedIntoControl property is true on “focus” and false on “blur” <MACRO name="VisioViewer_OnFocus" hide="true" lang="JScript"><![CDATA[ varaipc = Application.ActiveInPlaceControl; aipc.Control.AlertsEnabled = aipc.UserMovedIntoControl; aipc.Control.ScrollbarsVisible = aipc.UserMovedIntoControl; aipc.Control.ToolbarVisible = aipc.UserMovedIntoControl; aipc.Control.PageVisible = aipc.UserMovedIntoControl; ]]></MACRO>
13. Using _OnSynchronize event to update the document and/or the control Useful when you need to update data in the viewer control because of changes in the document – or vice versa Bizarre hypothetical example: Suppose we have an element in our document that we wish to reflect the current “zoom” level of the Visio control Example 4
14. _OnSynchronize Macro is executed whenever the document changes and whenever focus leaves the viewer control. UpdateFromDocument=true if the control may need updating because the document state has changed; false if it’s the other way around. This is our bizarre “zoom” data element <MACRO name="VisioViewer_OnSynchronize" hide="true" lang="JScript"><![CDATA[ varaipc = Application.ActiveInPlaceControl; varndlist = aipc.Document.GetElementsByTagName("Author"); if (!aipc.UpdateFromDocument) { var zoom = aipc.Control.Zoom; ndlist.item(0).firstChild.nodeValue = zoom; } else { var value = ndlist.item(0).firstChild.nodeValue; aipc.Control.Zoom = value; } ]]></MACRO> Set document data based on the control Set control data based on the document
15. If your viewer control API includes events, you can write script in XMetaL to handle the events If your viewer has an event called “SomeEvent”, you can write a macro like this: When the viewer fires the event, XMetaL will execute this macro ActiveInPlaceControl.NextEventParam property allows you to access the arguments of the event Unfortunately no example to show today :-( (Non)-example:Events in the viewer control <MACRO name="VisioViewer_SomeEvent" hide="true" lang="JScript"><![CDATA[ // In here you do whatever you need to handle this event ]]></MACRO>
16. If you require more than one viewer control, and if all the image types use the same <Image> element, some additional scripting is required CTM file can only have one <OCXReplacement> for each DTD element But you can define additional OCXReplacements dynamically in script Relevant APIs: DOMDocumentType.addInPlaceControl() InPlaceControl.userData A little too much for an example here today! (Non)-example:More than one custom viewer
17. XMetaL DITA customization uses this technique – recursively! – to display SVG graphics XMetaL’s viewer control is Internet Explorer IE (through 8) does not natively support SVG either – requires you to install a plugin So XMetaL hands the image over to IE, which in turn hands it over to your SVG plugin SVG in DITA in XMetaL
18. XMetaL Community Forums http://forums.xmetal.com/ JustSystems Partner Center http://justpartnercenter.com/ Ask us for help (partner tech support) partnersupport-na@justsystems.com Resources