Package cssutils :: Package stylesheets :: Module medialist |
[hide private]
[frames] | no frames]

# Source Code for Module cssutils.stylesheets.medialist

      1  """
      2  MediaList implements DOM Level 2 Style Sheets MediaList.
      3
      4  TODO:
      5      - delete: maybe if deleting from all, replace *all* with all others?
      6      - is unknown media an exception?
      7  """
      8  __all__ = ['MediaList']
      9  __docformat__ = 'restructuredtext'
     10  __version__ = '$Id: medialist.py 1116 2008-03-05 13:52:23Z cthedot $'
     11
     12  import xml.dom
     13  import cssutils
     14  from cssutils.css import csscomment
     15  from mediaquery import MediaQuery
     16
     17 -class MediaList(cssutils.util.Base, cssutils.util.ListSeq):
     18      """
     19      Provides the abstraction of an ordered collection of media,
     20      without defining or constraining how this collection is
     21      implemented.
     22
     23      A media is always an instance of MediaQuery.
     24
     25      An empty list is the same as a list that contains the medium "all".
     26
     27      Properties
     28      ==========
     29      length:
     30          The number of MediaQuery objects in the list.
     31      mediaText: of type DOMString
     32          The parsable textual representation of this MediaList
     33      self: a list (cssutils)
     34          All MediaQueries in this MediaList
     35      wellformed:
     36          if this list is wellformed
     37
     38      Format
     39      ======
     40      ::
     41
     42          medium [ COMMA S* medium ]*
     43
     44      New::
     45
     46          <media_query> [, <media_query> ]*
     47      """
     48 -    def __init__(self, mediaText=None, readonly=False):
     49          """
     50          mediaText
     51              unicodestring of parsable comma separared media
     52              or a list of media
     53          """
     54          super(MediaList, self).__init__()
     55
     56          if isinstance(mediaText, list):
     57              mediaText = u','.join(mediaText)
     58
     59          if mediaText:
     60              self.mediaText = mediaText
     61
     62          self._readonly = readonly
     63
     64      length = property(lambda self: len(self),
     65          doc="(DOM readonly) The number of media in the list.")
     66
     67 -    def _getMediaText(self):
     68          """
     69          returns serialized property mediaText
     70          """
     71          return cssutils.ser.do_stylesheets_medialist(self)
     72
     73 -    def _setMediaText(self, mediaText):
     74          """
     75          mediaText
     76              simple value or comma-separated list of media
     77
     78          DOMException
     79
     80          - SYNTAX_ERR: (MediaQuery)
     81            Raised if the specified string value has a syntax error and is
     82            unparsable.
     83          - NO_MODIFICATION_ALLOWED_ERR: (self)
     84            Raised if this media list is readonly.
     85          """
     86          self._checkReadonly()
     87          wellformed = True
     88          tokenizer = self._tokenize2(mediaText)
     89          newseq = []
     90
     91          expected = None
     92          while True:
     93              # find all upto and including next ",", EOF or nothing
     94              mqtokens = self._tokensupto2(tokenizer, listseponly=True)
     95              if mqtokens:
     96                  if self._tokenvalue(mqtokens[-1]) == ',':
     97                      expected = mqtokens.pop()
     98                  else:
     99                      expected = None
    100
    101                  mq = MediaQuery(mqtokens)
    102                  if mq.wellformed:
    103                      newseq.append(mq)
    104                  else:
    105                      wellformed = False
    106                      self._log.error(u'MediaList: Invalid MediaQuery: %s' %
    107                                      self._valuestr(mqtokens))
    108              else:
    109                  break
    110
    111          # post condition
    112          if expected:
    113              wellformed = False
    114              self._log.error(u'MediaList: Cannot end with ",".')
    115
    116          if wellformed:
    117              del self[:]
    118              for mq in newseq:
    119                  self.appendMedium(mq)
    120
    121      mediaText = property(_getMediaText, _setMediaText,
    122          doc="""(DOM) The parsable textual representation of the media list.
    123              This is a comma-separated list of media.""")
    124
    125      wellformed = property(lambda self: True)
    126
    127 -    def __prepareset(self, newMedium):
    128          # used by appendSelector and __setitem__
    129          self._checkReadonly()
    130
    131          if not isinstance(newMedium, MediaQuery):
    132              newMedium = MediaQuery(newMedium)
    133
    134          if newMedium.wellformed:
    135              return newMedium
    136
    137 -    def __setitem__(self, index, newMedium):
    138          """
    139          overwrites ListSeq.__setitem__
    140
    141          Any duplicate items are **not** removed.
    142          """
    143          newMedium = self.__prepareset(newMedium)
    144          if newMedium:
    145              self.seq[index] = newMedium
    146          # TODO: remove duplicates?
    147
    148 -    def appendMedium(self, newMedium):
    149          """
    150          (DOM)
    151          Adds the medium newMedium to the end of the list. If the newMedium
    152          is already used, it is first removed.
    153
    154          newMedium
    155              a string or a MediaQuery object
    156
    157          returns if newMedium is wellformed
    158
    159          DOMException
    160
    161          - INVALID_CHARACTER_ERR: (self)
    162            If the medium contains characters that are invalid in the
    163            underlying style language.
    164          - NO_MODIFICATION_ALLOWED_ERR: (self)
    165            Raised if this list is readonly.
    166          """
    167          newMedium = self.__prepareset(newMedium)
    168
    169          if newMedium:
    170              mts = [self._normalize(mq.mediaType) for mq in self]
    171              newmt = self._normalize(newMedium.mediaType)
    172
    173              if newmt in mts:
    174                  self.deleteMedium(newmt)
    175                  self.seq.append(newMedium)
    176              elif u'all' == newmt:
    177                  # remove all except handheld (Opera)
    178                  h = None
    179                  for mq in self:
    180                      if mq.mediaType == u'handheld':
    181                          h = mq
    182                  del self[:]
    183                  self.seq.append(newMedium)
    184                  if h:
    185                      self.append(h)
    186              elif u'all' in mts:
    187                  if u'handheld' == newmt:
    188                      self.seq.append(newMedium)
    189              else:
    190                  self.seq.append(newMedium)
    191
    192              return True
    193
    194          else:
    195              return False
    196
    197 -    def append(self, newMedium):
    198          "overwrites ListSeq.append"
    199          self.appendMedium(newMedium)
    200
    201 -    def deleteMedium(self, oldMedium):
    202          """
    203          (DOM)
    204          Deletes the medium indicated by oldMedium from the list.
    205
    206          DOMException
    207
    208          - NO_MODIFICATION_ALLOWED_ERR: (self)
    209            Raised if this list is readonly.
    210          - NOT_FOUND_ERR: (self)
    211            Raised if oldMedium is not in the list.
    212          """
    213          self._checkReadonly()
    214          oldMedium = self._normalize(oldMedium)
    215
    216          for i, mq in enumerate(self):
    217              if self._normalize(mq.mediaType) == oldMedium:
    218                  del self[i]
    219                  break
    220          else:
    221              raise xml.dom.NotFoundErr(
    222                  u'"%s" not in this MediaList' % oldMedium)
    223
    224 -    def item(self, index):
    225          """
    226          (DOM)
    227          Returns the mediaType of the index'th element in the list.
    228          If index is greater than or equal to the number of media in the
    229          list, returns None.
    230          """
    231          try:
    232              return self[index].mediaType
    233          except IndexError:
    234              return None
    235
    236 -    def __repr__(self):
    237          return "cssutils.stylesheets.%s(mediaText=%r)" % (
    238                  self.__class__.__name__, self.mediaText)
    239
    240 -    def __str__(self):
    241          return "<cssutils.stylesheets.%s object mediaText=%r at 0x%x>" % (
    242                  self.__class__.__name__, self.mediaText, id(self))
    243