| Enhancing the Preview File Writer |
In this chapter you will learn how to enhance the preview writer component to support the dynamic functionality of the real-time preview.
For the static preview writer it was sufficient to output very simple HTML code (see Implementing the Preview Writer). However, to implement a dynamic real-time preview, which allows users to click segments and jump to the corresponding row in the side-by-side editor, the preview needs to implement active elements through the addition of CSS and JavaScript.
The currently selected (i.e. active) segment in the real-time preview should be highlighted, e.g. with a silver background, while unselected segments retain a white background. In our case, this can be best implemented through CSS stylesheets. Therefore, the header of the preview file will contain the following styles, which are applied to the currently selected segment (activesegment) and to the unselected segments (normal).
<style type="text/css">
body {color:grey; font-size:10pt; font-family:@Arial Unicode MS;}
span {color:black; cursor:hand;}
// real-time preview related styles
.activesegment {color:red; background-color:silver; cursor:hand;}
.normal {color:black; background-color:white; cursor:hand;}
</style><script type="text/javascript">
function setActiveStyle(objDivID)
{
document.getElementById(objDivID).className = 'activesegment';
}
function setNormalStyle(objDivID)
{
document.getElementById(objDivID).className = 'normal';
}
</script>// write the HTML header, which contains CSS styles // and JavaScript functions, which can be called from the // preview viewer control private string GetHTMLStart() { string header = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"; header += "<html>\n"; header += "<head>\n"; header += "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n"; header += "<title>" + "Preview" + "</title>\n"; header += "<style type=\"text/css\">\n"; header += "<!--\n"; header += "body{color:grey; font-size:10pt;font-family: @Arial Unicode MS;}\n"; header += "span{color:black;cursor: hand;}\n"; //real-time preview related styles header += ".activesegment{color:red;background-color: silver;cursor: hand;}\n"; header += ".normal{color:black;background-color: white;cursor: hand;}\n"; header += "//-->\n"; header += "</style>\n"; //real-time preview related JavaScript functions header += "<script type=\"text/javascript\">\n"; header += "<!--\n"; header += "function setActiveStyle(objDivID)\n"; header += "{\n"; header += "document.getElementById(objDivID).className = 'activesegment';\n"; header += "}\n"; header += "function setNormalStyle(objDivID)\n"; header += "{\n"; header += "document.getElementById(objDivID).className = 'normal';\n"; header += "}\n"; header += "//-->\n"; header += "</script>\n"; header += "</head>\n"; header += "<body>\n"; return header; }
// start the preview output public void StartOfInput() { _preview = new StreamWriter(OutputProperties.OutputFilePath); _preview.WriteLine(GetHTMLStart()); }
To determine a particular segment to be highlighted in the real-time preview when the user selects it in the side-by-side editor (or vice versa), you require two parameters: the paragraph unit id and the segment id.
First, we add the paragraph unit as a string member to the writer class:
string _paragraphUnitId = String.Empty;Then we enhance the ParagraphUnitStart method to set the value of _paragraphUnitId to the id of the currently selected paragraph unit.
// each paragraph unit should appear in a new line // therefore use a DIV element public override void ParagraphUnitStart(IParagraphUnitProperties properties) { _preview.WriteLine("<div>"); _paragraphUnitId = properties.ParagraphUnitId.Id; }
Next, we make the segments in the real-time preview 'clickable' by outputting the following HTML through the SegmentStart method:
// enclose each segment in a SPAN tag pair public override void SegmentStart(ISegmentPairProperties properties) { _preview.Write("<span id=\"" + properties.Id.Id + "\" onClick=\"window.external.SelectSegment('" + _paragraphUnitId + "','" + properties.Id.Id + "')\" >"); }
Below you see an example of the HTML code the enhanced preview writer will generate for a paragraph unit that contains two segments:
<div>
<span id="5" onclick="window.external.SelectSegment('5445c60d-445a-48ef-8623-8c63d56a9a51','5')">
Prompt me to re-open previously edited documents.
</span>
<span id="6" onclick="window.external.SelectSegment('5445c60d-445a-48ef-8623-8c63d56a9a51','6')">
Opens a dialog box on start-up.
</span>
</div>Your enhanced preview writer class should now look as shown below. Note that the same preview writer can be used both for the internal static and the real-time preview. There is no harm in having the styles and JavaScript functions in the static preview, they will just never be called.
using System; using System.IO; using Sdl.FileTypeSupport.Framework.BilingualApi; using Sdl.FileTypeSupport.Framework.NativeApi; namespace Sdl.Sdk.FileTypeSupport.Samples.SimpleText.Preview { class InternalPreviewWriter : AbstractNativeFileWriter, INativeContentCycleAware { StreamWriter _preview = null; string _paragraphUnitId = String.Empty; public void SetFileProperties(IFileProperties properties) { // not used in this implementation } #region "start output" // start the preview output public void StartOfInput() { _preview = new StreamWriter(OutputProperties.OutputFilePath); _preview.WriteLine(GetHTMLStart()); } #endregion #region "text" // output the translatable strings public override void Text(ITextProperties textInfo) { _preview.Write(textInfo.Text); } #endregion #region "para" #region "para start" // each paragraph unit should appear in a new line // therefore use a DIV element public override void ParagraphUnitStart(IParagraphUnitProperties properties) { _preview.WriteLine("<div>"); _paragraphUnitId = properties.ParagraphUnitId.Id; } #endregion public override void ParagraphUnitEnd() { _preview.Write("</div>"); } #endregion #region "segment" // enclose each segment in a SPAN tag pair public override void SegmentStart(ISegmentPairProperties properties) { _preview.Write("<span id=\"" + properties.Id.Id + "\" onClick=\"window.external.SelectSegment('" + _paragraphUnitId + "','" + properties.Id.Id + "')\" >"); } #endregion public override void SegmentEnd() { _preview.Write("</span>"); } #region "inline tags" // output any inline tags, // which will also apply the corresponding character formatting public override void InlineStartTag(IStartTagProperties tagInfo) { _preview.Write(tagInfo.TagContent); } public override void InlineEndTag(IEndTagProperties tagInfo) { _preview.Write(tagInfo.TagContent); } #endregion #region "end output" // end the preview output public void EndOfInput() { _preview.WriteLine("</body></html>"); _preview.Close(); } #endregion #region "html start" // write the HTML header, which contains CSS styles // and JavaScript functions, which can be called from the // preview viewer control private string GetHTMLStart() { string header = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"; header += "<html>\n"; header += "<head>\n"; header += "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n"; header += "<title>" + "Preview" + "</title>\n"; header += "<style type=\"text/css\">\n"; header += "<!--\n"; header += "body{color:grey; font-size:10pt;font-family: @Arial Unicode MS;}\n"; header += "span{color:black;cursor: hand;}\n"; //real-time preview related styles header += ".activesegment{color:red;background-color: silver;cursor: hand;}\n"; header += ".normal{color:black;background-color: white;cursor: hand;}\n"; header += "//-->\n"; header += "</style>\n"; //real-time preview related JavaScript functions header += "<script type=\"text/javascript\">\n"; header += "<!--\n"; header += "function setActiveStyle(objDivID)\n"; header += "{\n"; header += "document.getElementById(objDivID).className = 'activesegment';\n"; header += "}\n"; header += "function setNormalStyle(objDivID)\n"; header += "{\n"; header += "document.getElementById(objDivID).className = 'normal';\n"; header += "}\n"; header += "//-->\n"; header += "</script>\n"; header += "</head>\n"; header += "<body>\n"; return header; } #endregion } }