# vPresent is an immersive presentation creation and display application.
# Copyright (C) 2007-2008 by Infiscape Corporation
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

import string, sys
import builder
import opendocument

config = opendocument.config
office = opendocument.office

class PresentationBuilder(builder.Builder):
   '''
   Builder for OpenDocument presentations.  This produces a Presentation
   object.
   '''

   def __init__(self, undoStack, parent = None):
      builder.Builder.__init__(self)

      # Bundle up the arguments given to this constructor to pass on to the
      # Presentation constructor later. It is done this way so that a bunch
      # of data members do not have to be added for each of the Presentation
      # constructor arguments. Another way to do this would be to have the
      # constructor for this class take a keyword argument dictionary as the
      # container for the Presentation constructor arguments, but then the
      # interface for constructing PresentationBuilder objects would be
      # obfuscated.
      self.__makePresentation = \
         lambda u = undoStack, p = parent: opendocument.presentation.Presentation(u, p)

      # Document objects.
      self.presentation = None

   def buildContent(self):
      self.presentation = self.__makePresentation()
      self.__makePresentation = None

   def __makeBuilderMethod(self, tag):
      try:
         return getattr(self, 'build_%s' % opendocument.tagToType(tag))
      except AttributeError:
         raise builder.NoBuilderMethodError, "No builder method found for '%s'."%tag

   def buildDocumentNode(self, tag, attrs):
      try:
         start_func = self.__makeBuilderMethod(tag)
         return start_func(attrs)
      except builder.NoBuilderMethodError:
         cls = opendocument.tag_class_map[tag]
         dn = cls(attrs)
         self.presentation.addGenericNode(dn)
         return dn.acceptsChildren()

   def build_draw_FillImage(self, attrs):
      fill_image = opendocument.buildNode('draw:fill-image', attrs)
      self.presentation.addGenericNode(fill_image)
      self.presentation.addFillImage(fill_image)
      return fill_image.acceptsChildren()

   def build_style_Style(self, attrs):
      style = opendocument.buildNode('style:style', attrs)
      self.presentation.addGenericNode(style)
      # Add style to style map.
      self.presentation.addStyle(style)
      return style.acceptsChildren()

   def build_config_ItemMapEntry(self, attrs):
      self.presentation.addConfigItemMapEntry(config.ItemMapEntry(attrs))
      return True

   def build_config_ItemSet(self, attrs):
      self.presentation.addConfigItemSet(config.ItemSet(attrs))
      return True

   def build_config_NamedConfigItemMap(self, attrs):
      self.presentation.addNamedConfigItemMap(config.NamedItemMap(attrs))
      return True

   def build_config_IndexedConfigItemMap(self, attrs):
      self.presentation.addIndexedConfigItemMap(config.IndexedItemMap(attrs))
      return True

   # Add top level documents
   def build_office_DocumentMeta(self, attrs):
      self.presentation.addDocumentMeta(office.DocumentMeta(attrs))
      return True
   def build_office_DocumentContent(self, attrs):
      self.presentation.addDocumentContent(opendocument.bases.office.DocumentContent(attrs))
      return True
   def build_office_DocumentStyles(self, attrs):
      self.presentation.addDocumentStyles(office.DocumentStyles(attrs))
      return True

   def build_draw_Page(self, attrs):
      '''
      @post The new drawing page becomes the active container object.

      @note Activates a container object.
      '''
      p = opendocument.buildNode('draw:page', attrs)
      if not p._attrs.has_key('draw:name'):
         p.draw_name = 'page%d' % (self.presentation.getNumPages() + 1)
      self.presentation.addGenericNode(p)
      return True

   def buildText(self, content):
      self.presentation.addGenericNode(opendocument.PlainText(content))
      return False

   def build_office_EventListeners(self, attrs):
      self.presentation.addEventListners(office.EventListeners(attrs))
      return False

   def build_script_EventListener(self, attrs):
      self.presentation.addEventListner(script.EventListener(attrs))
      return False

   def build_presentation_EventListener(self, attrs):
      self.presentation.addEventListner(EventListener(attrs))
      return False

   def closeContainer(self):
      '''
      Closes the current container object (at least conceptually).  This can
      only be called when the current object in the presentation state is a
      container object.  Basically, this applies to any object under the
      presentation document root that has children.

      @pre The current object (as far as self.presentation is concerned) is a
           container object.
      '''
      self.presentation.closeContainer()

   def finish(self):
      self.presentation.refresh()

   def getPresentation(self):
      '''
      Returns the product (a Presentation object).
      '''
      return self.presentation
