summaryrefslogtreecommitdiff
path: root/filter/source
diff options
context:
space:
mode:
authorMarco Cecchetti <mrcekets@gmail.com>2012-05-26 12:53:19 +0200
committerMarco Cecchetti <mrcekets@gmail.com>2012-06-15 10:14:58 +0200
commit232490f3fba15bc9b6cb94723645fbc21b3c0f26 (patch)
tree7c9bf3046101283fbdf6fa1cebf845e0a09565b5 /filter/source
parentd6b82f7bcb5123db56eb9acf4a3f3c2c90319606 (diff)
In order to enable future support for slide transitions has been needed
to modify the part of the presentation engine handling the slides navigation feature. A new structure for slide and master page elements has been designed. The following new classes have been implemented: MasterPageView, TextFieldHandler, SlideNumberFieldHandler. The following classes have been modified: MetaDocument, MetaSlide, MasterPage, PlaceholderShape, Thumbnail. The following classes have been modified and renamed: TextField -> TextFieldContentProvider, FixedTextField -> FixedTextProvider, VariableDateTimeField -> CurrentDateTimeProvider, SlideNumberField -> SlideNumberProvider.
Diffstat (limited to 'filter/source')
-rw-r--r--filter/source/svg/presentation_engine.js1387
1 files changed, 984 insertions, 403 deletions
diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js
index 98eab2fb5825..6aeabe123d82 100644
--- a/filter/source/svg/presentation_engine.js
+++ b/filter/source/svg/presentation_engine.js
@@ -332,6 +332,8 @@ function getDefaultMouseHandlerDictionary()
// index mode
mouseHandlerDict[INDEX_MODE][MOUSE_DOWN]
= function( aEvt ) { return toggleSlideIndex(); };
+// mouseHandlerDict[INDEX_MODE][MOUSE_MOVE]
+// = function( aEvt ) { return theSlideIndexPage.updateSelection( aEvt ); };
return mouseHandlerDict;
}
@@ -646,7 +648,8 @@ var aOOOAttrDateTimeFormat = 'date-time-format';
var aOOOAttrTextAdjust = 'text-adjust';
-// Placeholder class names
+// element class names
+var aPageClassName = 'Page';
var aSlideNumberClassName = 'Slide_Number';
var aDateTimeClassName = 'Date/Time';
var aFooterClassName = 'Footer';
@@ -801,6 +804,13 @@ function log( message )
}
}
+function warning( bCondition, sMessage )
+{
+ if( bCondition )
+ log( sMessage );
+ return bCondition;
+}
+
function getNSAttribute( sNSPrefix, aElem, sAttrName )
{
if( !aElem ) return null;
@@ -910,6 +920,105 @@ function getSafeIndex( nIndex, nMin, nMax )
return nIndex;
}
+function isTextFieldElement( aElement )
+{
+ var sClassName = aElement.getAttribute( 'class' );
+ return ( sClassName === aSlideNumberClassName ) ||
+ ( sClassName === aFooterClassName ) ||
+ ( sClassName === aHeaderClassName ) ||
+ ( sClassName === aDateTimeClassName );
+}
+
+
+
+function tempWrapMasterPages()
+{
+ var aSlideGroupElement = document.createElementNS( NSS['svg'], 'g' );
+ aSlideGroupElement.setAttribute( 'class', 'SlideGroup' );
+ //aSlideGroupElement.onmousedown = function( aEvt ) { return mouseHandlerDispatch( aEvt, MOUSE_DOWN ); };
+ //aSlideGroupElement.setAttribute( 'visibility', 'hidden' );
+
+
+ var aDrawPageSet = getElementsByClassName(ROOT_NODE, 'Slide');
+ ROOT_NODE.insertBefore( aSlideGroupElement, aDrawPageSet[0] );
+
+ var aMasterPageSet = getElementsByClassName(ROOT_NODE, 'Master_Slide');
+ if( aMasterPageSet )
+ {
+ var aDefsElement = document.createElementNS( NSS['svg'], 'defs' );
+
+ ROOT_NODE.insertBefore( aDefsElement, aMasterPageSet[0] );
+ var i;
+ for( i = 0; i < aMasterPageSet.length; ++i)
+ {
+ var aMasterPage = ROOT_NODE.removeChild( aMasterPageSet[i] );
+ aDefsElement.appendChild( aMasterPage );
+ }
+ }
+}
+
+function tempCreateSlideView( aPageElement )
+{
+ if( !aPageElement )
+ return;
+
+ var aSlideGroupElement = getElementByClassName( ROOT_NODE, 'SlideGroup' );
+
+ var sId = aPageElement.getAttribute( 'id' );
+ var sName = aPageElement.getAttributeNS( NSS['ooo'], 'name' );
+ var sClipPath = aPageElement.getAttribute( 'clip-path' );
+
+ aPageElement.removeAttribute( 'id' );
+ aPageElement.removeAttributeNS( NSS['ooo'], 'name' );
+ aPageElement.removeAttribute( 'visibility' );
+ aPageElement.removeAttribute( 'clip-path' );
+ aPageElement.setAttribute( 'class', aPageClassName );
+
+ var aVisibilityStatusElement = document.createElementNS( NSS['svg'], 'g' );
+ aVisibilityStatusElement.setAttribute( 'visibility', 'hidden' );
+
+ var aSlideElement = document.createElementNS( NSS['svg'], 'g' );
+ aSlideElement.setAttribute( 'id', sId );
+ aSlideElement.setAttributeNS( NSS['ooo'], 'name', sName );
+ aSlideElement.setAttribute( 'clip-path', sClipPath );
+ aSlideElement.setAttribute( 'class', 'Slide' );
+ aVisibilityStatusElement.appendChild( aSlideElement );
+
+ aPageElement.parentNode.removeChild( aPageElement );
+ aSlideElement.appendChild( aPageElement );
+ aSlideGroupElement.appendChild( aVisibilityStatusElement );
+}
+
+function tempModMasterPage( aMasterPageElement, sId )
+{
+ if( !aMasterPageElement )
+ return;
+
+
+ var aBackgroundObjectsElement =
+ getElementByClassName( aMasterPageElement, 'BackgroundObjects' );
+
+ var aBackgroundShapesElement = document.createElementNS( NSS['svg'], 'g' );
+ aBackgroundShapesElement.setAttribute( 'id', 'bs-' + sId );
+ aBackgroundShapesElement.setAttribute( 'class', 'BackgroundShapes' );
+
+
+ if( aBackgroundObjectsElement.hasChildNodes() )
+ {
+ var aChildNode = aBackgroundObjectsElement.firstElementChild;
+ while( aChildNode )
+ {
+ var aNextChildNode= aChildNode.nextElementSibling;
+ if( !isTextFieldElement( aChildNode ) )
+ {
+ aBackgroundObjectsElement.removeChild( aChildNode );
+ aBackgroundShapesElement.appendChild( aChildNode );
+ }
+ aChildNode = aNextChildNode;
+ }
+ }
+ aBackgroundObjectsElement.appendChild( aBackgroundShapesElement );
+}
// ------------------------------------------------------------------------------------------ //
@@ -978,31 +1087,59 @@ aAnimatedElementDebugPrinter.off();
// ------------------------------------------------------------------------------------------ //
-/******************
- ** Core Classes **
- ******************/
-
-/** Class MetaDocument **
- * This class provides a pool of properties related to the whole presentation and
- * it is responsible for initializing the set of MetaSlide objects that handle
- * the meta information for each slide.
+/************************
+ *** Core Classes ***
+ ************************/
+
+/** Class MetaDocument
+ * This class provides a pool of properties related to the whole presentation.
+ * Moreover it is responsible for:
+ * - initializing the set of MetaSlide objects that handle the meta information
+ * for each slide;
+ * - creating a map with key an id and value the svg element containing
+ * the animations performed on the slide with such an id.
+ *
*/
-function MetaDocument( aMetaDocElem )
+function MetaDocument()
{
+ // TODO to be implemented in C++
+ tempWrapMasterPages();
+
+ // We look for the svg element that provides the following presentation
+ // properties:
+ // - the number of slides in the presentation;
+ // - the type of numbering used in the presentation.
+ // Moreover it wraps svg elements providing meta information on each slide
+ // and svg elements providing content and properties of each text field.
+ var aMetaDocElem = document.getElementById( aOOOElemMetaSlides );
+ assert( aMetaDocElem, 'MetaDocument: the svg element with id:' + aOOOElemMetaSlides + 'is not valid.');
+
+ // We initialize general presentation properties:
+ // - the number of slides in the presentation;
this.nNumberOfSlides = parseInt( aMetaDocElem.getAttributeNS( NSS['ooo'], aOOOAttrNumberOfSlides ) );
assert( typeof this.nNumberOfSlides == 'number' && this.nNumberOfSlides > 0,
'MetaDocument: number of slides is zero or undefined.' );
- this.startSlideNumber = 0;
+ // - the index of the slide to show when the presentation starts;
+ this.nStartSlideNumber = 0;
+ // - the numbering type used in the presentation, default type is arabic.
this.sPageNumberingType = aMetaDocElem.getAttributeNS( NSS['ooo'], aOOOAttrNumberingType ) || 'arabic';
+
+ // The collections for handling properties of each slide, svg elements
+ // related to master pages and content and properties of text fields.
this.aMetaSlideSet = new Array();
this.aMasterPageSet = new Object();
- this.aTextFieldSet = new Array();
- this.slideNumberField = new SlideNumberField( this.startSlideNumber + 1, this.sPageNumberingType );
+ this.aTextFieldHandlerSet = new Object();
+ this.aTextFieldContentProviderSet = new Array();
+ this.aSlideNumberProvider = new SlideNumberProvider( this.nStartSlideNumber + 1, this.sPageNumberingType );
+ // We create a map with key an id and value the svg element containing
+ // the animations performed on the slide with such an id.
+ this.bIsAnimated = false;
this.aSlideAnimationsMap = new Object();
this.initSlideAnimationsMap();
-
+ // We initialize the set of MetaSlide objects that handle the meta
+ // information for each slide.
for( var i = 0; i < this.nNumberOfSlides; ++i )
{
var sMetaSlideId = aOOOElemMetaSlide + '_' + i;
@@ -1010,21 +1147,55 @@ function MetaDocument( aMetaDocElem )
}
assert( this.aMetaSlideSet.length == this.nNumberOfSlides,
'MetaDocument: aMetaSlideSet.length != nNumberOfSlides.' );
- //this.aMetaSlideSet[ this.startSlideNumber ].show();
}
-MetaDocument.prototype.initPlaceholderShapes = function()
+MetaDocument.prototype =
{
- this.aMetaSlideSet[0].initPlaceholderShapes();
-};
+/*** public methods ***/
+
+/** getCurrentSlide
+ *
+ * @return
+ * The MetaSlide object handling the current slide.
+ */
+getCurrentSlide : function()
+{
+ return this.aMetaSlideSet[nCurSlide];
+},
+
+/** setCurrentSlide
+ *
+ * @param nSlideIndex
+ * The index of the slide to show.
+ */
+setCurrentSlide : function( nSlideIndex )
+{
+ if( nSlideIndex >= 0 && nSlideIndex < this.nNumberOfSlides )
+ {
+ if( nCurSlide !== undefined )
+ this.aMetaSlideSet[nCurSlide].hide();
+ this.aMetaSlideSet[nSlideIndex].show();
+ nCurSlide = nSlideIndex;
+ }
+ else
+ {
+ log('MetaDocument.setCurrentSlide: slide index out of range: ' + nSlideIndex );
+ }
+},
+
+/*** private methods ***/
-MetaDocument.prototype.initSlideAnimationsMap = function()
+initSlideAnimationsMap : function()
{
var aAnimationsSection = document.getElementById( 'presentation-animations' );
if( aAnimationsSection )
{
var aAnimationsDefSet = aAnimationsSection.getElementsByTagName( 'defs' );
+ // we have at least one slide with animations ?
+ this.bIsAnimated = ( typeof aAnimationsDefSet.length =='number' &&
+ aAnimationsDefSet.length > 0 );
+
for( var i = 0; i < aAnimationsDefSet.length; ++i )
{
var sSlideId = aAnimationsDefSet[i].getAttributeNS( NSS['ooo'], aOOOAttrSlide );
@@ -1035,433 +1206,880 @@ MetaDocument.prototype.initSlideAnimationsMap = function()
}
}
}
-};
-
+}
+}; // end MetaDocument prototype
-/** Class MetaSlide **
- * This class is responsible for managing the visibility of all master page shapes
- * and background related to a given slide element; it performs the creation and
- * the initialization of each Text Field object.
+/** Class MetaSlide
+ * This class is responsible for:
+ * - parsing and initializing slide properties;
+ * - creating a MasterSlide object that provides direct access to the target
+ * master slide and its sub-elements;
+ * - initializing text field content providers;
+ * - initializing the slide animation handler.
+ *
+ * @param sMetaSlideId
+ * The string representing the id attribute of the meta-slide element.
+ * @param aMetaDoc
+ * The MetaDocument global object.
*/
function MetaSlide( sMetaSlideId, aMetaDoc )
{
this.theDocument = document;
this.id = sMetaSlideId;
this.theMetaDoc = aMetaDoc;
+
+ // We get a reference to the meta-slide element.
this.element = this.theDocument.getElementById( this.id );
- assert( this.element, 'MetaSlide: meta_slide element <' + this.id + '> not found.' );
- // - Initialize the Slide Element -
+ assert( this.element,
+ 'MetaSlide: meta_slide element <' + this.id + '> not found.' );
+
+ // We get a reference to the slide element.
this.slideId = this.element.getAttributeNS( NSS['ooo'], aOOOAttrSlide );
this.slideElement = this.theDocument.getElementById( this.slideId );
+ assert( this.slideElement,
+ 'MetaSlide: slide element <' + this.slideId + '> not found.' );
+ this.nSlideNumber = parseInt( this.slideId.substr(2) );
+
+ // ------------------------------
+ // TODO: to be implemented in C++
+ tempCreateSlideView(this.slideElement);
+ this.slideElement = this.theDocument.getElementById( this.slideId );
assert( this.slideElement, 'MetaSlide: slide element <' + this.slideId + '> not found.' );
- // - Initialize the Target Master Page Element -
+ // ------------------------------
+
+ // Each slide element is wrapped by a <g> element that is responsible for
+ // the slide element visibility. In fact the visibility attribute has
+ // to be set on the parent of the slide element and not directly on
+ // the slide element. The reason is that in index mode each slide
+ // rendered in a thumbnail view is targeted by a <use> element, however
+ // when the visibility attribute is set directly on the referred slide
+ // element its visibility is not overridden by the visibility attribute
+ // defined by the targeting <use> element. The previous solution was,
+ // when the user switched to index mode, to set up the visibility attribute
+ // of all slides rendered in a thumbnail to 'visible'.
+ // Obviously the slides were not really visible because the grid of
+ // thumbnails was above them, anyway Firefox performance was really bad.
+ // The workaround of setting up the visibility attribute on the slide
+ // parent element let us to make visible a slide in a <use> element
+ // even if the slide parent element visibility is set to 'hidden'.
+ this.aVisibilityStatusElement = this.slideElement.parentNode;
+
+ // We get a reference to the draw page element, where all shapes specific
+ // of this slide live.
+ this.pageElement = getElementByClassName( this.slideElement, aPageClassName );
+ assert( this.pageElement,
+ 'MetaSlide: page element <' + this.slideId + '> not found.' );
+
+ // We initialize the MasterPage object that provides direct access to
+ // the target master page element.
this.masterPage = this.initMasterPage();
- // - Initialize Background -
- //this.aBackground = getElementByClassName( this.aSlide, 'Background' );
- // - Initialize Visibility Properties -
+
+ // We initialize visibility properties of the target master page elements.
this.nAreMasterObjectsVisible = this.initVisibilityProperty( aOOOAttrMasterObjectsVisibility, VISIBLE );
this.nIsBackgroundVisible = this.initVisibilityProperty( aOOOAttrBackgroundVisibility, VISIBLE );
this.nIsPageNumberVisible = this.initVisibilityProperty( aOOOAttrPageNumberVisibility, HIDDEN );
this.nIsDateTimeVisible = this.initVisibilityProperty( aOOOAttrDateTimeVisibility, VISIBLE );
this.nIsFooterVisible = this.initVisibilityProperty( aOOOAttrFooterVisibility, VISIBLE );
this.nIsHeaderVisible = this.initVisibilityProperty( aOOOAttrHeaderVisibility, VISIBLE );
- // - Initialize Master Page Text Fields (Placeholders)-
- this.aMPTextFieldSet = new Object();
- this.aMPTextFieldSet[aSlideNumberClassName] = this.initSlideNumberField();
- this.aMPTextFieldSet[aDateTimeClassName] = this.initDateTimeField( aOOOAttrDateTimeField );
- this.aMPTextFieldSet[aFooterClassName] = this.initFixedTextField( aOOOAttrFooterField );
- this.aMPTextFieldSet[aHeaderClassName] = this.initFixedTextField( aOOOAttrHeaderField );
-
- // - Initialize Slide Animations Handler
+
+ // This property tell us if the date/time field need to be updated
+ // each time the slide is shown. It is initialized in
+ // the initDateTimeFieldContentProvider method.
+ this.bIsDateTimeVariable = undefined;
+
+ // We initialize the objects responsible to provide the content to text field.
+ this.aTextFieldContentProviderSet = new Object();
+ this.aTextFieldContentProviderSet[aSlideNumberClassName] = this.initSlideNumberFieldContentProvider();
+ this.aTextFieldContentProviderSet[aDateTimeClassName] = this.initDateTimeFieldContentProvider( aOOOAttrDateTimeField );
+ this.aTextFieldContentProviderSet[aFooterClassName] = this.initFixedTextFieldContentProvider( aOOOAttrFooterField );
+ this.aTextFieldContentProviderSet[aHeaderClassName] = this.initFixedTextFieldContentProvider( aOOOAttrHeaderField );
+
+ // We initialize the SlideAnimationsHandler object
this.aSlideAnimationsHandler = new SlideAnimations( aSlideShow.getContext() );
this.aSlideAnimationsHandler.importAnimations( this.getSlideAnimationsRoot() );
this.aSlideAnimationsHandler.parseElements();
+
+ // this statement is used only for debugging
if( false && this.aSlideAnimationsHandler.aRootNode )
log( this.aSlideAnimationsHandler.aRootNode.info( true ) );
+
}
-/*** MetaSlide methods ***/
MetaSlide.prototype =
{
- /*** public methods ***/
- hide : function()
- {
- checkElemAndSetAttribute( this.slideElement, 'visibility', 'hidden' );
-
- this.masterPage.hide();
- this.masterPage.hideBackground();
+/*** public methods ***/
- var aFieldSet = this.aMPTextFieldSet;
- var aShapeSet = this.masterPage.aPlaceholderShapeSet;
- if( aFieldSet[aSlideNumberClassName] ) aFieldSet[aSlideNumberClassName].hide( aShapeSet[aSlideNumberClassName] );
- if( aFieldSet[aDateTimeClassName] ) aFieldSet[aDateTimeClassName].hide( aShapeSet[aDateTimeClassName] );
- if( aFieldSet[aFooterClassName] ) aFieldSet[aFooterClassName].hide( aShapeSet[aFooterClassName] );
- if( aFieldSet[aHeaderClassName] ) aFieldSet[aHeaderClassName].hide( aShapeSet[aHeaderClassName] );
- },
+/** show
+ * Set the visibility property of the slide to 'inherit'.
+ */
+show : function()
+{
+ this.updateMasterPageView();
+ this.aVisibilityStatusElement.setAttribute( 'visibility', 'inherit' );
+},
- hideExceptMaster : function()
- {
- checkElemAndSetAttribute( this.slideElement, 'visibility', 'hidden' );
- },
+/** hide
+ * Set the visibility property of the slide to 'hidden'.
+ */
+hide : function()
+{
+ this.aVisibilityStatusElement.setAttribute( 'visibility', 'hidden' );
+},
- show : function()
+/** updateMasterPageView
+ * On first call it creates a master page view element and insert it at
+ * the begin of the slide element. Moreover it updates the text fields
+ * included in the master page view.
+ */
+updateMasterPageView : function()
+{
+ // The master page view element is generated and attached on first time
+ // the slide is shown.
+ if( !this.aMasterPageView )
{
- checkElemAndSetAttribute( this.slideElement, 'visibility', 'visible' );
-
- this.masterPage.setVisibility( this.nAreMasterObjectsVisible );
- this.masterPage.setVisibilityBackground( this.nIsBackgroundVisible );
-
-
- this.setTextFieldVisibility( aSlideNumberClassName, this.nIsPageNumberVisible );
- this.setTextFieldVisibility( aDateTimeClassName, this.nIsDateTimeVisible );
- this.setTextFieldVisibility( aFooterClassName, this.nIsFooterVisible );
- this.setTextFieldVisibility( aHeaderClassName, this.nIsHeaderVisible );
- },
+ this.aMasterPageView = new MasterPageView( this );
+ this.aMasterPageView.attachToSlide();
+ }
+ this.aMasterPageView.update();
+},
- getMasterPageId : function()
- {
- return this.masterPage.id;
- },
+/*** private methods ***/
+initMasterPage : function()
+{
+ var sMasterPageId = this.element.getAttributeNS( NSS['ooo'], aOOOAttrMaster );
- getMasterPageElement : function()
+ // Check that the master page handler object has not already been
+ // created by an other slide that target the same master page.
+ if( !this.theMetaDoc.aMasterPageSet.hasOwnProperty( sMasterPageId ) )
{
- return this.masterPage.element;
- },
+ this.theMetaDoc.aMasterPageSet[ sMasterPageId ] = new MasterPage( sMasterPageId );
- getBackground : function()
- {
- return getElementByClassName( this.slideElement, 'Background' );
- },
+ // We initialize aTextFieldHandlerSet[ sMasterPageId ] to an empty
+ // collection.
+ this.theMetaDoc.aTextFieldHandlerSet[ sMasterPageId ] = new Object();
+ }
+ return this.theMetaDoc.aMasterPageSet[ sMasterPageId ];
+},
- getMasterPageBackground : function()
- {
- return this.masterPage.background;
- },
+initVisibilityProperty : function( aVisibilityAttribute, nDefaultValue )
+{
+ var nVisibility = nDefaultValue;
+ var sVisibility = getOOOAttribute( this.element, aVisibilityAttribute );
+ if( sVisibility )
+ nVisibility = aVisibilityValue[ sVisibility ];
+ return nVisibility;
+},
- /*** private methods ***/
- initMasterPage : function()
- {
- var sMasterPageId = this.element.getAttributeNS( NSS['ooo'], aOOOAttrMaster );
- if( !this.theMetaDoc.aMasterPageSet.hasOwnProperty( sMasterPageId ) )
- this.theMetaDoc.aMasterPageSet[ sMasterPageId ] = new MasterPage( sMasterPageId );
- return this.theMetaDoc.aMasterPageSet[ sMasterPageId ];
- },
+initSlideNumberFieldContentProvider : function()
+{
+ return this.theMetaDoc.aSlideNumberProvider;
+},
- initVisibilityProperty : function( aVisibilityAttribute, nDefaultValue )
- {
- var nVisibility = nDefaultValue;
- var sVisibility = getOOOAttribute( this.element, aVisibilityAttribute );
- if( sVisibility )
- nVisibility = aVisibilityValue[ sVisibility ];
- return nVisibility;
- },
+initDateTimeFieldContentProvider : function( aOOOAttrDateTimeField )
+{
+ var sTextFieldId = getOOOAttribute( this.element, aOOOAttrDateTimeField );
+ if( !sTextFieldId ) return null;
- initSlideNumberField : function()
- {
- return this.theMetaDoc.slideNumberField;
- },
+ var nLength = aOOOElemTextField.length + 1;
+ var nIndex = parseInt(sTextFieldId.substring( nLength ) );
+ if( typeof nIndex != 'number') return null;
- initDateTimeField : function( aOOOAttrDateTimeField )
+ if( !this.theMetaDoc.aTextFieldContentProviderSet[ nIndex ] )
{
- var sTextFieldId = getOOOAttribute( this.element, aOOOAttrDateTimeField );
- if( !sTextFieldId ) return null;
-
- var nLength = aOOOElemTextField.length + 1;
- var nIndex = parseInt(sTextFieldId.substring( nLength ) );
- if( typeof nIndex != 'number') return null;
-
- if( !this.theMetaDoc.aTextFieldSet[ nIndex ] )
+ var aTextField;
+ var aTextFieldElem = document.getElementById( sTextFieldId );
+ var sClassName = getClassAttribute( aTextFieldElem );
+ if( sClassName == 'FixedDateTimeField' )
{
- var aTextField;
- var aTextFieldElem = document.getElementById( sTextFieldId );
- var sClassName = getClassAttribute( aTextFieldElem );
- if( sClassName == 'FixedDateTimeField' )
- {
- aTextField = new FixedTextField( aTextFieldElem );
- }
- else if( sClassName == 'VariableDateTimeField' )
- {
- aTextField = new VariableDateTimeField( aTextFieldElem );
- }
- else
- {
- aTextField = null;
- }
- this.theMetaDoc.aTextFieldSet[ nIndex ] = aTextField;
+ aTextField = new FixedTextProvider( aTextFieldElem );
+ this.bIsDateTimeVariable = false;
}
- return this.theMetaDoc.aTextFieldSet[ nIndex ];
- },
-
- initFixedTextField : function( aOOOAttribute )
- {
- var sTextFieldId = getOOOAttribute( this.element, aOOOAttribute );
- if( !sTextFieldId ) return null;
-
- var nLength = aOOOElemTextField.length + 1;
- var nIndex = parseInt( sTextFieldId.substring( nLength ) );
- if( typeof nIndex != 'number') return null;
-
- if( !this.theMetaDoc.aTextFieldSet[ nIndex ] )
+ else if( sClassName == 'VariableDateTimeField' )
{
- var aTextFieldElem = document.getElementById( sTextFieldId );
- this.theMetaDoc.aTextFieldSet[ nIndex ]
- = new FixedTextField( aTextFieldElem );
+ aTextField = new CurrentDateTimeProvider( aTextFieldElem );
+ this.bIsDateTimeVariable = true;
}
- return this.theMetaDoc.aTextFieldSet[ nIndex ];
- },
+ else
+ {
+ aTextField = null;
+ }
+ this.theMetaDoc.aTextFieldContentProviderSet[ nIndex ] = aTextField;
+ }
+ return this.theMetaDoc.aTextFieldContentProviderSet[ nIndex ];
+},
- setTextFieldVisibility : function( sClassName, nVisible )
- {
- var aTextField = this.aMPTextFieldSet[ sClassName ];
- var aPlaceholderShape = this.masterPage.aPlaceholderShapeSet[ sClassName ];
- if( !aTextField ) return;
- aTextField.setVisibility( this.nAreMasterObjectsVisible & nVisible, aPlaceholderShape );
- },
+initFixedTextFieldContentProvider : function( aOOOAttribute )
+{
+ var sTextFieldId = getOOOAttribute( this.element, aOOOAttribute );
+ if( !sTextFieldId ) return null;
- getSlideAnimationsRoot : function()
+ var nLength = aOOOElemTextField.length + 1;
+ var nIndex = parseInt( sTextFieldId.substring( nLength ) );
+ if( typeof nIndex != 'number') return null;
+
+ if( !this.theMetaDoc.aTextFieldContentProviderSet[ nIndex ] )
{
- return this.theMetaDoc.aSlideAnimationsMap[ this.slideId ];
+ var aTextFieldElem = document.getElementById( sTextFieldId );
+ this.theMetaDoc.aTextFieldContentProviderSet[ nIndex ]
+ = new FixedTextProvider( aTextFieldElem );
}
+ return this.theMetaDoc.aTextFieldContentProviderSet[ nIndex ];
+},
-};
+getSlideAnimationsRoot : function()
+{
+ return this.theMetaDoc.aSlideAnimationsMap[ this.slideId ];
+}
+
+}; // end MetaSlide prototype
/** Class MasterPage **
- * This class gives access to a master page element, its background and
- * each placeholder shape present in the master page element.
+ * This class gives direct access to a master page element and to the following
+ * elements included in the master page:
+ * - the background element,
+ * - the background objects group element,
+ * - the background shapes group element.
+ * Moreover for each text field element a Placeholder object is created which
+ * manages the text field element itself.
+ *
+ * The master page element structure is the following:
+ * <g class='Master_Slide'>
+ * <g class='Background'>
+ * background image
+ * </g>
+ * <g class='BackgroundObjects'>
+ * <g class='BackgroundFields'>
+ * <g class='Date/Time'>
+ * date/time placeholder
+ * </g>
+ * <g class='Header'>
+ * header placeholder
+ * </g>
+ * <g class='Footer'>
+ * footer placeholder
+ * </g>
+ * <g class='Slide_Number'>
+ * slide number placeholder
+ * </g>
+ * </g>
+ * <g class='BackgroundShapes'>
+ * shapes
+ * </g>
+ * </g>
+ * </g>
+ *
+ * @param sMasterPageId
+ * A string representing the value of the id attribute of the master page
+ * element to be handled.
*/
function MasterPage( sMasterPageId )
{
this.id = sMasterPageId;
+
+ // The master page element to be handled.
+ this.element = document.getElementById( this.id );
+ assert( this.element,
+ 'MasterPage: master page element <' + this.id + '> not found.' );
+
+ // ------------------------------
+ // TODO: to be implemented in C++
+ tempModMasterPage( this.element, this.id );
this.element = document.getElementById( this.id );
assert( this.element, 'MasterPage: master page element <' + this.id + '> not found.' );
+ // ------------------------------
+
+ // The master page background element and its id attribute.
this.background = getElementByClassName( this.element, 'Background' );
- this.backgroundId = this.background.getAttribute( 'id' );
- this.backgroundVisibility = initVisibilityProperty( this.background );
+ if( this.background )
+ {
+ this.backgroundId = this.background.getAttribute( 'id' );
+// this.backgroundVisibility = initVisibilityProperty( this.background );
+ }
+ else
+ {
+ this.backgroundId = '';
+ log( 'MasterPage: the background element is not valid.' );
+ }
+
+ // The background objects group element that contains every element presents
+ // on the master page except the background element.
this.backgroundObjects = getElementByClassName( this.element, 'BackgroundObjects' );
- this.backgroundObjectsId = this.backgroundObjects.getAttribute( 'id' );
- this.backgroundObjectsVisibility = initVisibilityProperty( this.backgroundObjects );
+ if( this.backgroundObjects )
+ {
+ this.backgroundObjectsId = this.backgroundObjects.getAttribute( 'id' );
+// this.backgroundObjectsVisibility = initVisibilityProperty( this.backgroundObjects );
+ }
+ else
+ {
+ this.backgroundObjectsId = '';
+ log( 'MasterPage: the background objects element is not valid.' );
+ }
+
+ // The background shapes group element that contains all the shape of
+ // the master page that are not text fields.
+ this.backgroundShapes = getElementByClassName( this.backgroundObjects, 'BackgroundShapes' );
+ if( this.backgroundShapes )
+ {
+ this.backgroundShapesId = this.backgroundShapes.getAttribute( 'id' );
+ }
+ else
+ {
+ this.backgroundShapesId = '';
+ log( 'MasterPage: the background shapes element is not valid.' );
+ }
+
+ // We populate the collection of placeholders.
this.aPlaceholderShapeSet = new Object();
this.initPlaceholderShapes();
+
+ this.removeVisibilityAttributes();
}
-/*** MasterPage methods ***/
MasterPage.prototype =
{
- /*** public method ***/
- setVisibility : function( nVisibility )
- {
- this.backgroundObjectsVisibility = setElementVisibility( this.backgroundObjects, this.backgroundObjectsVisibility, nVisibility );
- },
-
- setVisibilityBackground : function( nVisibility )
- {
- this.backgroundVisibility = setElementVisibility( this.background, this.backgroundVisibility, nVisibility );
- },
+/*** private methods ***/
- hide : function()
- {
- this.setVisibility( HIDDEN );
- },
-
- show : function()
- {
- this.setVisibility( VISIBLE );
- },
+initPlaceholderShapes : function()
+{
+ this.aPlaceholderShapeSet[ aSlideNumberClassName ] = new PlaceholderShape( this, aSlideNumberClassName );
+ this.aPlaceholderShapeSet[ aDateTimeClassName ] = new PlaceholderShape( this, aDateTimeClassName );
+ this.aPlaceholderShapeSet[ aFooterClassName ] = new PlaceholderShape( this, aFooterClassName );
+ this.aPlaceholderShapeSet[ aHeaderClassName ] = new PlaceholderShape( this, aHeaderClassName );
+},
- hideBackground : function()
- {
- this.setVisibilityBackground( HIDDEN );
- },
+removeVisibilityAttributes : function()
+{
+ this.element.removeAttribute( 'visibility' );
+ this.background.removeAttribute( 'visibility' );
+ this.backgroundObjects.removeAttribute( 'visibility' );
+}
- showBackground : function()
- {
- this.setVisibilityBackground( VISIBLE );
- },
+}; // end MasterPage prototype
- /*** private method ***/
- initPlaceholderShapes : function()
- {
- this.aPlaceholderShapeSet[ aSlideNumberClassName ] = new PlaceholderShape( this, aSlideNumberClassName );
- this.aPlaceholderShapeSet[ aDateTimeClassName ] = new PlaceholderShape( this, aDateTimeClassName );
- this.aPlaceholderShapeSet[ aFooterClassName ] = new PlaceholderShape( this, aFooterClassName );
- this.aPlaceholderShapeSet[ aHeaderClassName ] = new PlaceholderShape( this, aHeaderClassName );
- }
-};
-
-/** Class PlaceholderShape **
- * This class manages the visibility and the text content of a placeholder shape.
+/** Class PlaceholderShape
+ * This class provides direct access to a text field element and
+ * to the embedded placeholder element.
+ * Moreover it set up the text adjustment and position for the placeholder
+ * element.
+ * Note: the text field element included in a master page is used only as
+ * a template element, it is cloned for each specific text content
+ * (see the TextFieldContentProvider class and its derived classes).
+ *
+ * @param aMasterPage
+ * The master page object to which the text field to be handled belongs.
+ * @param sClassName
+ * A string representing the value of the class attribute of the text
+ * field element to be handled.
*/
function PlaceholderShape( aMasterPage, sClassName )
{
this.masterPage = aMasterPage;
this.className = sClassName;
+
this.element = null;
this.textElement = null;
-
this.init();
}
/* public methods */
-PlaceholderShape.prototype.setTextContent = function( sText )
+PlaceholderShape.prototype.isValid = function()
{
- if( !this.textElement )
+ return ( this.element && this.textElement );
+};
+
+/* private methods */
+
+/** init
+ * In case a text field element of class type 'className' exists and such
+ * an element embeds a placeholder element, the text adjustment and position
+ * of the placeholder element is set up.
+ */
+PlaceholderShape.prototype.init = function()
+{
+
+ var aTextFieldElement = getElementByClassName( this.masterPage.backgroundObjects, this.className );
+ if( aTextFieldElement )
{
- log( 'error: PlaceholderShape.setTextContent: text element is not valid in placeholder of type '
- + this.className + ' that belongs to master slide ' + this.masterPage.id );
- return;
+ aTextFieldElement.removeAttribute( 'visibility' ); // TODO to be handled in C++ ?
+
+ var aPlaceholderElement = getElementByClassName( aTextFieldElement, 'PlaceholderText' );
+ if( aPlaceholderElement )
+ {
+ // Each text field element has an invisible rectangle that can be
+ // regarded as the text field bounding box.
+ // We exploit such a feature and the exported text adjust attribute
+ // value in order to set up correctly the position and text
+ // adjustment for the placeholder element.
+ var aSVGRectElemSet = aTextFieldElement.getElementsByTagName( 'rect' );
+ // As far as text field element exporting is implemented it should
+ // be only one <rect> element!
+ if( aSVGRectElemSet.length === 1)
+ {
+ var aRect = new Rectangle( aSVGRectElemSet[0] );
+ var sTextAdjust = getOOOAttribute( aTextFieldElement, aOOOAttrTextAdjust ) || 'left';
+ var sTextAnchor, sX;
+ if( sTextAdjust == 'left' )
+ {
+ sTextAnchor = 'start';
+ sX = String( aRect.left );
+ }
+ else if( sTextAdjust == 'right' )
+ {
+ sTextAnchor = 'end';
+ sX = String( aRect.right );
+ }
+ else if( sTextAdjust == 'center' )
+ {
+ sTextAnchor = 'middle';
+ var nMiddle = ( aRect.left + aRect.right ) / 2;
+ sX = String( parseInt( String( nMiddle ) ) );
+ }
+ if( sTextAnchor )
+ aPlaceholderElement.setAttribute( 'text-anchor', sTextAnchor );
+ if( sX )
+ aPlaceholderElement.setAttribute( 'x', sX );
+
+ this.element = aTextFieldElement;
+ this.textElement = aPlaceholderElement;
+ }
+ }
}
- this.textElement.textContent = sText;
};
-PlaceholderShape.prototype.setVisibility = function( nVisibility )
+/** Class MasterPageView
+ * This class is used to creates a svg element of class MasterPageView and its
+ * sub-elements.
+ * It is also responsible for updating the content of the included text fields.
+ *
+ * MasterPageView element structure:
+ *
+ * <g class='MasterPageView'>
+ * <use class='Background'> // reference to master page background element
+ * <g class='BackgroundObjects'>
+ * <g class='BackgroundFields'>
+ * <g class='Slide_Number'> // a cloned element
+ * ...
+ * </g>
+ * <use class='Date/Time'> // reference to a clone
+ * <use class='Footer'>
+ * <use class='Header'>
+ * </g>
+ * <use class='BackgroundShapes'> // reference to the group of shapes on the master page
+ * </g>
+ * </g>
+ *
+ * Sub-elements are present only if they are visible.
+ *
+ * @param aMetaSlide
+ * The MetaSlide object managing the slide element that targets
+ * the master page view element created by an instance of MasterPageView.
+ */
+function MasterPageView( aMetaSlide )
+{
+ this.aMetaSlide = aMetaSlide;
+ this.aSlideElement = aMetaSlide.slideElement;
+ this.aPageElement = aMetaSlide.pageElement;
+ this.aMasterPage = aMetaSlide.masterPage;
+ this.aMPVElement = this.createElement();
+ this.bIsAttached = false;
+}
+
+/*** public methods ***/
+
+/** attachToSlide
+ * Prepend the master slide view element to the slide element.
+ */
+MasterPageView.prototype.attachToSlide = function()
{
- if( !this.element )
+ if( !this.bIsAttached )
{
- return;
+ var aInsertedElement = this.aSlideElement.insertBefore( this.aMPVElement, this.aPageElement );
+ assert( aInsertedElement === this.aMPVElement,
+ 'MasterPageView.attachToSlide: aInsertedElement != this.aMPVElement' );
+
+ this.bIsAttached = true;
}
- this.element.setAttribute( 'visibility', aVisibilityAttributeValue[nVisibility] );
};
-PlaceholderShape.prototype.show = function()
+/** detachFromSlide
+ * Remove the master slide view element from the slide element.
+ */
+MasterPageView.prototype.detachFromSlide = function()
{
- this.setVisibility( VISIBLE );
+ if( this.bIsAttached )
+ {
+ this.aSlideElement.removeChild( this.aMPVElement );
+ this.bIsAttached = false;
+ }
};
-PlaceholderShape.prototype.hide = function()
+/** update
+ * Update the content of text fields placed on the master page.
+ */
+MasterPageView.prototype.update = function()
{
- this.setVisibility( HIDDEN );
+ if( this.aDateTimeFieldHandler && this.aMetaSlide.bIsDateTimeVariable )
+ this.aDateTimeFieldHandler.update();
};
-/* private methods */
-PlaceholderShape.prototype.init = function()
+/*** private methods ***/
+
+MasterPageView.prototype.createElement = function()
{
- var aShapeElem = getElementByClassName( this.masterPage.backgroundObjects, this.className );
- if( !aShapeElem ) return;
+ var theDocument = document;
+ var aMasterPageViewElement = theDocument.createElementNS( NSS['svg'], 'g' );
+ assert( aMasterPageViewElement,
+ 'MasterPageView.createElement: failed to create a master page view element.' );
+ aMasterPageViewElement.setAttribute( 'class', 'MasterPageView' );
- this.element = aShapeElem;
- this.element.setAttribute( 'visibility', 'hidden' );
+ // init the Background element
+ if( this.aMetaSlide.nIsBackgroundVisible )
+ {
+ this.aBackgroundElement = theDocument.createElementNS( NSS['svg'], 'use' );
+ this.aBackgroundElement.setAttribute( 'class', 'Background' );
+ setNSAttribute( 'xlink', this.aBackgroundElement,
+ 'href', '#' + this.aMasterPage.backgroundId );
- this.textElement = getElementByClassName( this.element , 'PlaceholderText' );
- if( !this.textElement ) return;
+ // node linking
+ aMasterPageViewElement.appendChild( this.aBackgroundElement );
+ }
+ // init the BackgroundObjects element
+ if( this.aMetaSlide.nAreMasterObjectsVisible )
+ {
+ this.aBackgroundObjectsElement = theDocument.createElementNS( NSS['svg'], 'g' );
+ this.aBackgroundObjectsElement.setAttribute( 'class', 'BackgroundObjects' );
- var aSVGRectElemSet = this.element.getElementsByTagName( 'rect' );
- if( aSVGRectElemSet.length != 1) return;
+ // create background fields group
+ this.aBackgroundFieldsElement = theDocument.createElementNS( NSS['svg'], 'g' );
+ this.aBackgroundFieldsElement.setAttribute( 'class', 'BackgroundFields' );
- var aRect = new Rectangle( aSVGRectElemSet[0] );
+ // clone and initialize text field elements
+ var aPlaceholderShapeSet = this.aMasterPage.aPlaceholderShapeSet;
+ var aTextFieldContentProviderSet = this.aMetaSlide.aTextFieldContentProviderSet;
+ // where cloned elements are appended
+ var aDefsElement = this.aMetaSlide.element.parentNode;
+ var aTextFieldHandlerSet = this.aMetaSlide.theMetaDoc.aTextFieldHandlerSet;
+ var sMasterSlideId = this.aMasterPage.id;
- var sTextAdjust = getOOOAttribute( this.element, aOOOAttrTextAdjust ) || 'left';
- var sTextAnchor, sX;
- if( sTextAdjust == 'left' )
- {
- sTextAnchor = 'start';
- sX = String( aRect.left );
- }
- else if( sTextAdjust == 'right' )
- {
- sTextAnchor = 'end';
- sX = String( aRect.right );
- }
- else if( sTextAdjust == 'center' )
- {
- sTextAnchor = 'middle';
- var nMiddle = ( aRect.left + aRect.right ) / 2;
- sX = String( parseInt( String( nMiddle ) ) );
- }
+ // Slide Number Field
+ // The cloned element is appended directly to the field group element
+ // since there is no slide number field content shared between two slide
+ // (because the slide number of two slide is always different).
+ if( aPlaceholderShapeSet[aSlideNumberClassName] &&
+ aPlaceholderShapeSet[aSlideNumberClassName].isValid() &&
+ this.aMetaSlide.nIsPageNumberVisible )
+ {
+ this.aSlideNumberFieldHandler =
+ new SlideNumberFieldHandler( aPlaceholderShapeSet[aSlideNumberClassName],
+ aTextFieldContentProviderSet[aSlideNumberClassName] );
+ this.aSlideNumberFieldHandler.update( this.aMetaSlide.nSlideNumber );
+ this.aSlideNumberFieldHandler.appendTo( this.aBackgroundFieldsElement );
+ }
+ // Date/Time field
+ if( this.aMetaSlide.nIsDateTimeVisible )
+ {
+ this.aDateTimeFieldHandler =
+ this.initTextFieldHandler( aDateTimeClassName, aPlaceholderShapeSet,
+ aTextFieldContentProviderSet, aDefsElement,
+ aTextFieldHandlerSet, sMasterSlideId );
+ }
+
+ // Footer Field
+ if( this.aMetaSlide.nIsFooterVisible )
+ {
+ this.aFooterFieldHandler =
+ this.initTextFieldHandler( aFooterClassName, aPlaceholderShapeSet,
+ aTextFieldContentProviderSet, aDefsElement,
+ aTextFieldHandlerSet, sMasterSlideId );
+ }
+
+ // Header Field
+ if( this.aMetaSlide.nIsHeaderVisible )
+ {
+ this.aHeaderFieldHandler =
+ this.initTextFieldHandler( aHeaderClassName, aPlaceholderShapeSet,
+ aTextFieldContentProviderSet, aDefsElement,
+ aTextFieldHandlerSet, sMasterSlideId );
+ }
+
+ // init BackgroundShapes element
+ this.aBackgroundShapesElement = theDocument.createElementNS( NSS['svg'], 'use' );
+ this.aBackgroundShapesElement.setAttribute( 'class', 'BackgroundShapes' );
+ setNSAttribute( 'xlink', this.aBackgroundShapesElement,
+ 'href', '#' + this.aMasterPage.backgroundShapesId );
- this.textElement.setAttribute( 'text-anchor', sTextAnchor );
- this.textElement.setAttribute( 'x', sX );
+ // node linking
+ this.aBackgroundObjectsElement.appendChild( this.aBackgroundFieldsElement );
+ this.aBackgroundObjectsElement.appendChild( this.aBackgroundShapesElement );
+ aMasterPageViewElement.appendChild( this.aBackgroundObjectsElement );
+ }
+
+ return aMasterPageViewElement;
};
+MasterPageView.prototype.initTextFieldHandler =
+function( sClassName, aPlaceholderShapeSet, aTextFieldContentProviderSet,
+ aDefsElement, aTextFieldHandlerSet, sMasterSlideId )
+{
+ var aTextFieldHandler = null;
+ if( aPlaceholderShapeSet[sClassName] &&
+ aPlaceholderShapeSet[sClassName].isValid() )
+ {
+ var sTextFieldContentProviderId = aTextFieldContentProviderSet[sClassName].sId;
+ // We create only one single TextFieldHandler object (and so one only
+ // text field clone) per master slide and text content.
+ if ( !aTextFieldHandlerSet[ sMasterSlideId ][ sTextFieldContentProviderId ] )
+ {
+ aTextFieldHandlerSet[ sMasterSlideId ][ sTextFieldContentProviderId ] =
+ new TextFieldHandler( aPlaceholderShapeSet[sClassName],
+ aTextFieldContentProviderSet[sClassName] );
+ aTextFieldHandler = aTextFieldHandlerSet[ sMasterSlideId ][ sTextFieldContentProviderId ];
+ aTextFieldHandler.update();
+ aTextFieldHandler.appendTo( aDefsElement );
+ }
+ else
+ {
+ aTextFieldHandler = aTextFieldHandlerSet[ sMasterSlideId ][ sTextFieldContentProviderId ];
+ }
-// ------------------------------------------------------------------------------------------ //
-/********************************
- ** Text Field Class Hierarchy **
- ********************************/
+ // We create a <use> element referring to the cloned text field and
+ // append it to the field group element.
+ var aTextFieldElement = document.createElementNS( NSS['svg'], 'use' );
+ aTextFieldElement.setAttribute( 'class', sClassName );
+ setNSAttribute( 'xlink', aTextFieldElement,
+ 'href', '#' + aTextFieldHandler.sId );
+ // node linking
+ this.aBackgroundFieldsElement.appendChild( aTextFieldElement );
+ }
+ return aTextFieldHandler;
+};
-/** Class TextField **
- * This class is the root abstract class of the hierarchy.
- * The 'shapeElement' property is the shape element to which
- * this TextField object provides the text content.
+/** Class TextFieldHandler
+ * This class clone a text field field of a master page and set up
+ * the content of the cloned element on demand.
+ *
+ * @param aPlaceholderShape
+ * A PlaceholderShape object that provides the text field to be cloned.
+ * @param aTextContentProvider
+ * A TextContentProvider object to which the actual content updating is
+ * demanded.
*/
-function TextField( aTextFieldElem )
-{
- this.bIsUpdated = false;
+function TextFieldHandler( aPlaceholderShape, aTextContentProvider )
+{
+ this.aPlaceHolderShape = aPlaceholderShape;
+ this.aTextContentProvider = aTextContentProvider;
+ assert( this.aTextContentProvider,
+ 'TextFieldHandler: text content provider not defined.' );
+ this.sId = 'tf' + String( TextFieldHandler.getUniqueId() );
+ // The cloned text field element to be handled.
+ this.aTextFieldElement = null;
+ // The actual <text> element where the field content has to be placed.
+ this.aTextPlaceholderElement = null;
+ this.cloneElement();
}
-/*** TextField public methods ***/
-TextField.prototype.getShapeElement = function()
+/*** private methods ***/
+
+TextFieldHandler.CURR_UNIQUE_ID = 0;
+
+TextFieldHandler.getUniqueId = function()
+{
+ ++TextFieldHandler.CURR_UNIQUE_ID;
+ return TextFieldHandler.CURR_UNIQUE_ID;
+};
+
+TextFieldHandler.prototype.cloneElement = function()
{
- return this.shapeElement;
+ assert( this.aPlaceHolderShape && this.aPlaceHolderShape.isValid(),
+ 'TextFieldHandler.cloneElement: placeholder shape is not valid.' );
+ // The cloned text field element.
+ this.aTextFieldElement = this.aPlaceHolderShape.element.cloneNode( true /* deep clone */ );
+ assert( this.aTextFieldElement,
+ 'TextFieldHandler.cloneElement: aTextFieldElement is not defined' );
+ this.aTextFieldElement.setAttribute( 'id', this.sId );
+ // The actual <text> element where the field content has to be placed.
+ this.aTextPlaceholderElement = getElementByClassName( this.aTextFieldElement, 'PlaceholderText' );
+ assert( this.aTextPlaceholderElement,
+ 'TextFieldHandler.cloneElement: aTextPlaceholderElement is not defined' );
};
-TextField.prototype.setVisibility = function( nVisibility, aPlaceholderShape )
+/*** public methods ***/
+
+/** appendTo
+ * Append the cloned text field element to a svg element.
+ *
+ * @param aParentNode
+ * The svg element to which the cloned text field has to be appended.
+ */
+TextFieldHandler.prototype.appendTo = function( aParentNode )
{
- if( !this.bIsUpdated )
+ if( !this.aTextFieldElement )
{
- if( nVisibility )
- {
- this.update( aPlaceholderShape );
- this.bIsUpdated = true;
- }
- aPlaceholderShape.setVisibility( nVisibility );
+ log( 'TextFieldHandler.appendTo: aTextFieldElement is not defined' );
+ return;
}
- else if( !nVisibility )
+ if( !aParentNode )
{
- aPlaceholderShape.hide();
- this.bIsUpdated = false;
+ log( 'TextFieldHandler.appendTo: parent node is not defined' );
+ return;
}
+
+ aParentNode.appendChild( this.aTextFieldElement );
};
-TextField.prototype.show = function( aPlaceholderShape )
+/** setTextContent
+ * Modify the content of the cloned text field.
+ *
+ * @param sText
+ * A string representing the new content of the cloned text field.
+ */
+TextFieldHandler.prototype.setTextContent = function( sText )
{
- this.setVisibility( VISIBLE, aPlaceholderShape );
+ if( !this.aTextPlaceholderElement )
+ {
+ log( 'TextFieldHandler.setTextContent: text element is not valid in placeholder of type '
+ + this.className + ' that belongs to master slide ' + this.masterPage.id );
+ return;
+ }
+ this.aTextPlaceholderElement.textContent = sText;
};
-TextField.prototype.hide = function( aPlaceholderShape )
+/** update
+ * Update the content of the handled text field. The new content is provided
+ * directly from the TextContentProvider data member.
+ */
+TextFieldHandler.prototype.update = function()
+{
+ if( !this.aTextContentProvider )
+ log('TextFieldHandler.update: text content provider not defined.');
+ else
+ this.aTextContentProvider.update( this );
+};
+
+/** SlideNumberFieldHandler
+ * This class clone the slide number field of a master page and set up
+ * the content of the cloned element on demand.
+ *
+ * @param aPlaceholderShape
+ * A PlaceholderShape object that provides the slide number field
+ * to be cloned.
+ * @param aTextContentProvider
+ * A SlideNumberProvider object to which the actual content updating is
+ * demanded.
+ */
+function SlideNumberFieldHandler( aPlaceholderShape, aTextContentProvider )
+{
+ SlideNumberFieldHandler.superclass.constructor.call( this, aPlaceholderShape, aTextContentProvider );
+}
+extend( SlideNumberFieldHandler, TextFieldHandler );
+
+/*** public methods ***/
+
+/** update
+ * Update the content of the handled slide number field with the passed number.
+ *
+ * @param nPageNumber
+ * The number representing the new content of the slide number field.
+ */
+SlideNumberFieldHandler.prototype.update = function( nPageNumber )
{
- this.setVisibility( HIDDEN, aPlaceholderShape );
+ // The actual content updating is demanded to the related
+ // SlideNumberProvider instance that have the needed info on
+ // the numbering type.
+ if( !this.aTextContentProvider )
+ log('TextFieldHandler.update: text content provider not defined.');
+ else
+ this.aTextContentProvider.update( this, nPageNumber );
};
+// ------------------------------------------------------------------------------------------ //
+/******************************************************************************
+ * Text Field Content Provider Class Hierarchy
+ *
+ * The following classes are responsible to format and set the text content
+ * of text fields.
+ *
+ ******************************************************************************/
+
+/** Class TextFieldContentProvider
+ * This class is the root abstract class of the hierarchy.
+ *
+ * @param aTextFieldContentElement
+ * The svg element that contains the text content for one or more
+ * master slide text field.
+ */
+function TextFieldContentProvider( aTextFieldContentElement )
+{
+ // This id is used as key for the theMetaDoc.aTextFieldHandlerSet object.
+ if( aTextFieldContentElement )
+ this.sId = aTextFieldContentElement.getAttribute( 'id' );
+}
-/** Class FixedTextField **
+/** Class FixedTextProvider
* This class handles text field with a fixed text.
* The text content is provided by the 'text' property.
+ *
+ * @param aTextFieldContentElement
+ * The svg element that contains the text content for one or more
+ * master slide text field.
*/
-function FixedTextField( aTextFieldElem )
+function FixedTextProvider( aTextFieldContentElement )
{
- TextField.call( this, aTextFieldElem );
- this.text = aTextFieldElem.textContent;
+ FixedTextProvider.superclass.constructor.call( this, aTextFieldContentElement );
+ this.text = aTextFieldContentElement.textContent;
}
-extend( FixedTextField, TextField );
+extend( FixedTextProvider, TextFieldContentProvider );
-FixedTextField.prototype.update = function( aPlaceholderShape )
+/*** public methods ***/
+
+/** update
+ * Set up the content of a fixed text field.
+ *
+ * @param aFixedTextField
+ * An object that implement a setTextContent( String ) method in order
+ * to set the content of a given text field.
+ */
+FixedTextProvider.prototype.update = function( aFixedTextField )
{
- aPlaceholderShape.setTextContent( this.text );
+ aFixedTextField.setTextContent( this.text );
};
-
-/** Class VariableDateTimeField **
- * Provide the text content for the related shape by generating the current
+/** Class CurrentDateTimeProvider
+ * Provide the text content to a date/time field by generating the current
* date/time in the format specified by the 'dateTimeFormat' property.
+ *
+ * @param aTextFieldContentElement
+ * The svg element that contains the date/time format for one or more
+ * master slide date/time field.
*/
-function VariableDateTimeField( aTextFieldElem )
+function CurrentDateTimeProvider( aTextFieldContentElement )
{
- VariableDateTimeField.superclass.constructor.call( this, aTextFieldElem );
- this.dateTimeFormat = getOOOAttribute( aTextFieldElem, aOOOAttrDateTimeFormat );
+ CurrentDateTimeProvider.superclass.constructor.call( this, aTextFieldContentElement );
+ this.dateTimeFormat = getOOOAttribute( aTextFieldContentElement, aOOOAttrDateTimeFormat );
}
-extend( VariableDateTimeField, TextField );
+extend( CurrentDateTimeProvider, TextFieldContentProvider );
/*** public methods ***/
-VariableDateTimeField.prototype.update = function( aPlaceholderShape )
+
+/** update
+ * Set up the content of a variable date/time field.
+ *
+ * @param aDateTimeField
+ * An object that implement a setTextContent( String ) method in order
+ * to set the content of a given text field.
+ */
+CurrentDateTimeProvider.prototype.update = function( aDateTimeField )
{
var sText = this.createDateTimeText( this.dateTimeFormat );
- aPlaceholderShape.setTextContent( sText );
+ aDateTimeField.setTextContent( sText );
};
-VariableDateTimeField.prototype.createDateTimeText = function( sDateTimeFormat )
+/*** private methods ***/
+
+CurrentDateTimeProvider.prototype.createDateTimeText = function( sDateTimeFormat )
{
// TODO handle date/time format
var aDate = new Date();
@@ -1469,37 +2087,57 @@ VariableDateTimeField.prototype.createDateTimeText = function( sDateTimeFormat )
return sDate;
};
-/** Class SlideNumberField **
- * Provides the text content to the related shape by generating
+/** Class SlideNumberProvider
+ * Provides the text content to the related text field by generating
* the current page number in the given page numbering type.
*/
-function SlideNumberField( nInitialSlideNumber, sPageNumberingType )
+function SlideNumberProvider( nInitialSlideNumber, sPageNumberingType )
{
- SlideNumberField.superclass.constructor.call( this, null );
+ SlideNumberProvider.superclass.constructor.call( this, null );
this.nInitialSlideNumber = nInitialSlideNumber;
this.pageNumberingType = sPageNumberingType;
}
-extend( SlideNumberField, TextField );
+extend( SlideNumberProvider, TextFieldContentProvider );
/*** public methods ***/
-SlideNumberField.prototype.getNumberingType = function()
+
+/** getNumberingType
+ *
+ * @return
+ * The page numbering type.
+ */
+SlideNumberProvider.prototype.getNumberingType = function()
{
return this.pageNumberingType;
};
-SlideNumberField.prototype.update = function( aPlaceholderShape )
+/** update
+ * Set up the content of a slide number field.
+ *
+ * @param aSlideNumberField
+ * An object that implement a setTextContent( String ) method in order
+ * to set the content of a given text field.
+ * @param nSlideNumber
+ * An integer representing the slide number.
+ */
+
+SlideNumberProvider.prototype.update = function( aSlideNumberField, nSlideNumber )
{
- var nSlideNumber;
- if( nCurSlide === undefined )
- nSlideNumber = this.nInitialSlideNumber;
- else
- nSlideNumber = nCurSlide + 1;
+ if( nSlideNumber === undefined )
+ {
+ if( nCurSlide === undefined )
+ nSlideNumber = this.nInitialSlideNumber;
+ else
+ nSlideNumber = nCurSlide + 1;
+ }
var sText = this.createSlideNumberText( nSlideNumber, this.getNumberingType() );
- aPlaceholderShape.setTextContent( sText );
+ aSlideNumberField.setTextContent( sText );
};
-SlideNumberField.prototype.createSlideNumberText = function( nSlideNumber, sNumberingType )
+/*** private methods ***/
+
+SlideNumberProvider.prototype.createSlideNumberText = function( nSlideNumber, sNumberingType )
{
// TODO handle page numbering type
return String( nSlideNumber );
@@ -1601,6 +2239,7 @@ SlideIndexPage.prototype.createPageElement = function()
var aPageElement = document.createElementNS( NSS['svg'], 'g' );
aPageElement.setAttribute( 'id', this.pageElementId );
aPageElement.setAttribute( 'display', 'none' );
+ aPageElement.setAttribute( 'visibility', 'visible' );
// the slide index page background
var sPageBgColor = this.pageBgColor + ';';
@@ -1747,9 +2386,10 @@ function Thumbnail( aSlideIndexPage, nIndex )
this.thumbnailId = 'thumbnail' + this.index;
this.thumbnailElement = this.createThumbnailElement();
this.slideElement = getElementByClassName( this.thumbnailElement, 'Slide' );
- this.backgroundElement = getElementByClassName( this.thumbnailElement, 'Background' );
- this.backgroundObjectsElement = getElementByClassName( this.thumbnailElement, 'BackgroundObjects' );
this.borderElement = getElementByClassName( this.thumbnailElement, 'Border' );
+ this.mouseAreaElement = getElementByClassName( this.thumbnailElement, 'MouseArea' );
+ //this.mouseAreaElement.setAttribute( 'onmouseover', 'theSlideIndexPage.aThumbnailSet[' + this.index + '].onMouseOver()' );
+ //this.mouseAreaElement.onmousedown = mouseHandlerDictionary[INDEX_MODE][MOUSE_DOWN];
this.aTransformSet = new Array( 3 );
this.visibility = VISIBLE;
this.isSelected = false;
@@ -1821,7 +2461,7 @@ Thumbnail.prototype.updateView = function()
this.aTransformSet[1] = 'scale(' + this.container.scaleFactor + ')';
var sTransformAttrValue = this.computeTransform();
this.thumbnailElement.setAttribute( 'transform', sTransformAttrValue );
- this.thumbnailElement.setAttribute( 'onmouseover', 'theSlideIndexPage.aThumbnailSet[' + this.index + '].onMouseOver()' );
+ this.mouseAreaElement.setAttribute( 'onmouseover', 'theSlideIndexPage.aThumbnailSet[' + this.index + '].onMouseOver()' );
};
/** update
@@ -1835,33 +2475,14 @@ Thumbnail.prototype.update = function( nIndex )
if( this.slideIndex == nIndex ) return;
var aMetaSlide = theMetaDoc.aMetaSlideSet[nIndex];
+ aMetaSlide.updateMasterPageView();
setNSAttribute( 'xlink', this.slideElement, 'href', '#' + aMetaSlide.slideId );
- if( aMetaSlide.nIsBackgroundVisible )
- {
- setNSAttribute( 'xlink', this.backgroundElement, 'href', '#' + aMetaSlide.masterPage.backgroundId );
- this.backgroundElement.setAttribute( 'visibility', 'inherit' );
- }
- else
- {
- this.backgroundElement.setAttribute( 'visibility', 'hidden' );
- }
- if( aMetaSlide.nAreMasterObjectsVisible )
- {
- setNSAttribute( 'xlink', this.backgroundObjectsElement, 'href', '#' + aMetaSlide.masterPage.backgroundObjectsId );
- this.backgroundObjectsElement.setAttribute( 'visibility', 'inherit' );
- }
- else
- {
- this.backgroundObjectsElement.setAttribute( 'visibility', 'hidden' );
- }
this.slideIndex = nIndex;
};
Thumbnail.prototype.clear = function( nIndex )
{
setNSAttribute( 'xlink', this.slideElement, 'href', '' );
- setNSAttribute( 'xlink', this.backgroundElement, 'href', '' );
- setNSAttribute( 'xlink', this.backgroundObjectsElement, 'href', '' );
};
/* private methods */
@@ -1871,28 +2492,17 @@ Thumbnail.prototype.createThumbnailElement = function()
aThumbnailElement.setAttribute( 'id', this.thumbnailId );
aThumbnailElement.setAttribute( 'display', 'inherit' );
- var aMouseAreaElement = document.createElementNS( NSS['svg'], 'use' );
- setNSAttribute( 'xlink', aMouseAreaElement, 'href', '#' + this.container.thumbnailMouseAreaTemplateId );
- aMouseAreaElement.setAttribute( 'class', 'MouseArea' );
- aThumbnailElement.appendChild( aMouseAreaElement );
-
- var aBackgroundElement = document.createElementNS( NSS['svg'], 'use' );
- setNSAttribute( 'xlink', aBackgroundElement, 'href', '' );
- aBackgroundElement.setAttribute( 'visibility', 'inherit');
- aBackgroundElement.setAttribute( 'class', 'Background' );
- aThumbnailElement.appendChild( aBackgroundElement );
-
- var aBackgroundObjectsElement = document.createElementNS( NSS['svg'], 'use' );
- setNSAttribute( 'xlink', aBackgroundObjectsElement, 'href', '' );
- aBackgroundObjectsElement.setAttribute( 'visibility', 'inherit');
- aBackgroundObjectsElement.setAttribute( 'class', 'BackgroundObjects' );
- aThumbnailElement.appendChild( aBackgroundObjectsElement );
-
var aSlideElement = document.createElementNS( NSS['svg'], 'use' );
setNSAttribute( 'xlink', aSlideElement, 'href', '' );
aSlideElement.setAttribute( 'class', 'Slide' );
aThumbnailElement.appendChild( aSlideElement );
+ var aMouseAreaElement = document.createElementNS( NSS['svg'], 'use' );
+ setNSAttribute( 'xlink', aMouseAreaElement, 'href', '#' + this.container.thumbnailMouseAreaTemplateId );
+ aMouseAreaElement.setAttribute( 'class', 'MouseArea' );
+ aMouseAreaElement.setAttribute( 'opacity', 0.0 );
+ aThumbnailElement.appendChild( aMouseAreaElement );
+
var aBorderElement = document.createElementNS( NSS['svg'], 'use' );
setNSAttribute( 'xlink', aBorderElement, 'href', '#' + this.container.thumbnailBorderTemplateId );
aBorderElement.setAttribute( 'stroke', this.sNormalBorderColor );
@@ -1943,12 +2553,11 @@ function init()
HEIGHT = ROOT_NODE.viewBox.animVal.height;
}
- var aMetaDocElem = document.getElementById( aOOOElemMetaSlides );
- assert( aMetaDocElem, 'init: meta document element not found' );
aSlideShow = new SlideShow();
- theMetaDoc = new MetaDocument( aMetaDocElem );
+ theMetaDoc = new MetaDocument();
+ aSlideShow.bIsEnabled = theMetaDoc.bIsAnimated;
theSlideIndexPage = new SlideIndexPage();
- aSlideShow.displaySlide( theMetaDoc.startSlideNumber );
+ aSlideShow.displaySlide( theMetaDoc.nStartSlideNumber, false );
//=====================================//
// ===== timing test ===== //
@@ -2005,12 +2614,12 @@ function dispatchEffects(dir)
if( !bRet )
{
- switchSlide( 1 );
+ switchSlide( 1, false );
}
}
else
{
- switchSlide( dir );
+ switchSlide( dir, false );
}
}
@@ -2059,19 +2668,12 @@ function displayIndex( offsetNumber )
*/
function toggleSlideIndex()
{
- var suspendHandle = ROOT_NODE.suspendRedraw(500);
- var aMetaSlideSet = theMetaDoc.aMetaSlideSet;
+ //var suspendHandle = ROOT_NODE.suspendRedraw(500);
if( currentMode == SLIDE_MODE )
{
- aMetaSlideSet[nCurSlide].hide();
- var counter;
- for( counter = 0; counter < aMetaSlideSet.length; ++counter )
- {
- checkElemAndSetAttribute( aMetaSlideSet[counter].slideElement, 'visibility', 'inherit' );
- aMetaSlideSet[counter].masterPage.setVisibilityBackground( INHERIT );
- aMetaSlideSet[counter].masterPage.setVisibility( INHERIT );
- }
+
+ theMetaDoc.getCurrentSlide().hide();
INDEX_OFFSET = -1;
indexSetPageSlide( nCurSlide );
theSlideIndexPage.show();
@@ -2082,20 +2684,12 @@ function toggleSlideIndex()
theSlideIndexPage.hide();
var nNewSlide = theSlideIndexPage.selectedSlideIndex;
- for( counter = 0; counter < aMetaSlideSet.length; ++counter )
- {
- var aMetaSlide = aMetaSlideSet[counter];
- aMetaSlide.slideElement.setAttribute( 'visibility', 'hidden' );
- aMetaSlide.masterPage.setVisibilityBackground( HIDDEN );
- aMetaSlide.masterPage.setVisibility( HIDDEN );
- }
-
aSlideShow.displaySlide( nNewSlide, true );
currentMode = SLIDE_MODE;
}
- ROOT_NODE.unsuspendRedraw(suspendHandle);
- ROOT_NODE.forceRedraw();
+ //ROOT_NODE.unsuspendRedraw(suspendHandle);
+ //ROOT_NODE.forceRedraw();
}
/** Function that exit from the index mode without changing the shown slide
@@ -7716,11 +8310,9 @@ SlideShow.prototype.displaySlide = function( nNewSlide, bSkipSlideTransition )
else if( nNewSlide >= nSlides )
nNewSlide = 0;
- var newMetaSlide = null;
if( ( currentMode === INDEX_MODE ) && ( nNewSlide === nCurSlide ) )
{
- newMetaSlide = aMetaDoc.aMetaSlideSet[nNewSlide];
- newMetaSlide.show();
+ aMetaDoc.getCurrentSlide().show();
return;
}
@@ -7731,8 +8323,6 @@ SlideShow.prototype.displaySlide = function( nNewSlide, bSkipSlideTransition )
var oldMetaSlide = aMetaDoc.aMetaSlideSet[nOldSlide];
if( this.isEnabled() )
{
- // hide current slide
- oldMetaSlide.hide();
if( oldMetaSlide.aSlideAnimationsHandler.isAnimated() )
{
// force end animations
@@ -7742,36 +8332,27 @@ SlideShow.prototype.displaySlide = function( nNewSlide, bSkipSlideTransition )
this.dispose();
}
}
- else
- {
- oldMetaSlide.hide();
- }
+ }
+
+ if( !bSkipSlideTransition )
+ {
+ // create slide transition and add to activity queue
+ // to be implemented
+ aMetaDoc.setCurrentSlide( nNewSlide );
+ }
+ else
+ {
+ aMetaDoc.setCurrentSlide( nNewSlide );
}
// handle new slide
- nCurSlide = nNewSlide;
- newMetaSlide = aMetaDoc.aMetaSlideSet[nNewSlide];
if( this.isEnabled() )
{
- // prepare to show a new slide
this.notifySlideStart( nNewSlide );
- if( !bSkipSlideTransition )
- {
- // create slide transition and add to activity queue
- // to be implemented
- }
-
- // show next slide and start animations
- newMetaSlide.show();
- newMetaSlide.aSlideAnimationsHandler.start();
+ aMetaDoc.getCurrentSlide().aSlideAnimationsHandler.start();
this.update();
}
- else
- {
- newMetaSlide.show();
- }
-
/*
@@ -7987,7 +8568,7 @@ TimerEventQueue.prototype.addEvent = function( aEvent )
this.DBG( 'TimerEventQueue.addEvent invoked' );
if( !aEvent )
{
- log( 'error: TimerEventQueue.addEvent: null event' );
+ log( 'TimerEventQueue.addEvent: null event' );
return false;
}