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 1369 2008-07-14 20:14:46Z 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          self._wellformed = False
     56
     57          if isinstance(mediaText, list):
     58              mediaText = u','.join(mediaText)
     59
     60          if mediaText:
     61              self.mediaText = mediaText
     62
     63          self._readonly = readonly
     64
     65      length = property(lambda self: len(self),
     66          doc="(DOM readonly) The number of media in the list.")
     67
     68 -    def _getMediaText(self):
     69          """
     70          returns serialized property mediaText
     71          """
     72          return cssutils.ser.do_stylesheets_medialist(self)
     73
     74 -    def _setMediaText(self, mediaText):
     75          """
     76          mediaText
     77              simple value or comma-separated list of media
     78
     79          DOMException
     80
     81          - SYNTAX_ERR: (MediaQuery)
     82            Raised if the specified string value has a syntax error and is
     83            unparsable.
     84          - NO_MODIFICATION_ALLOWED_ERR: (self)
     85            Raised if this media list is readonly.
     86          """
     87          self._checkReadonly()
     88          wellformed = True
     89          tokenizer = self._tokenize2(mediaText)
     90          newseq = []
     91
     92          expected = None
     93          while True:
     94              # find all upto and including next ",", EOF or nothing
     95              mqtokens = self._tokensupto2(tokenizer, listseponly=True)
     96              if mqtokens:
     97                  if self._tokenvalue(mqtokens[-1]) == ',':
     98                      expected = mqtokens.pop()
     99                  else:
    100                      expected = None
    101
    102                  mq = MediaQuery(mqtokens)
    103                  if mq.wellformed:
    104                      newseq.append(mq)
    105                  else:
    106                      wellformed = False
    107                      self._log.error(u'MediaList: Invalid MediaQuery: %s' %
    108                                      self._valuestr(mqtokens))
    109              else:
    110                  break
    111
    112          # post condition
    113          if expected:
    114              wellformed = False
    115              self._log.error(u'MediaList: Cannot end with ",".')
    116
    117          if wellformed:
    118              del self[:]
    119              for mq in newseq:
    120                  self.appendMedium(mq)
    121              self._wellformed = True
    122
    123      mediaText = property(_getMediaText, _setMediaText,
    124          doc="""(DOM) The parsable textual representation of the media list.
    125              This is a comma-separated list of media.""")
    126
    127      wellformed = property(lambda self: self._wellformed)
    128
    129 -    def __prepareset(self, newMedium):
    130          # used by appendSelector and __setitem__
    131          self._checkReadonly()
    132
    133          if not isinstance(newMedium, MediaQuery):
    134              newMedium = MediaQuery(newMedium)
    135
    136          if newMedium.wellformed:
    137              return newMedium
    138
    139 -    def __setitem__(self, index, newMedium):
    140          """
    141          overwrites ListSeq.__setitem__
    142
    143          Any duplicate items are **not** removed.
    144          """
    145          newMedium = self.__prepareset(newMedium)
    146          if newMedium:
    147              self.seq[index] = newMedium
    148          # TODO: remove duplicates?
    149
    150 -    def appendMedium(self, newMedium):
    151          """
    152          (DOM)
    153          Adds the medium newMedium to the end of the list. If the newMedium
    154          is already used, it is first removed.
    155
    156          newMedium
    157              a string or a MediaQuery object
    158
    159          returns if newMedium is wellformed
    160
    161          DOMException
    162
    163          - INVALID_CHARACTER_ERR: (self)
    164            If the medium contains characters that are invalid in the
    165            underlying style language.
    166          - NO_MODIFICATION_ALLOWED_ERR: (self)
    167            Raised if this list is readonly.
    168          """
    169          newMedium = self.__prepareset(newMedium)
    170
    171          if newMedium:
    172              mts = [self._normalize(mq.mediaType) for mq in self]
    173              newmt = self._normalize(newMedium.mediaType)
    174
    175              if newmt in mts:
    176                  self.deleteMedium(newmt)
    177                  self.seq.append(newMedium)
    178              elif u'all' == newmt:
    179                  # remove all except handheld (Opera)
    180                  h = None
    181                  for mq in self:
    182                      if mq.mediaType == u'handheld':
    183                          h = mq
    184                  del self[:]
    185                  self.seq.append(newMedium)
    186                  if h:
    187                      self.append(h)
    188              elif u'all' in mts:
    189                  if u'handheld' == newmt:
    190                      self.seq.append(newMedium)
    191              else:
    192                  self.seq.append(newMedium)
    193
    194              return True
    195
    196          else:
    197              return False
    198
    199 -    def append(self, newMedium):
    200          "overwrites ListSeq.append"
    201          self.appendMedium(newMedium)
    202
    203 -    def deleteMedium(self, oldMedium):
    204          """
    205          (DOM)
    206          Deletes the medium indicated by oldMedium from the list.
    207
    208          DOMException
    209
    210          - NO_MODIFICATION_ALLOWED_ERR: (self)
    211            Raised if this list is readonly.
    212          - NOT_FOUND_ERR: (self)
    213            Raised if oldMedium is not in the list.
    214          """
    215          self._checkReadonly()
    216          oldMedium = self._normalize(oldMedium)
    217
    218          for i, mq in enumerate(self):
    219              if self._normalize(mq.mediaType) == oldMedium:
    220                  del self[i]
    221                  break
    222          else:
    223              self._log.error(u'"%s" not in this MediaList' % oldMedium,
    224                              error=xml.dom.NotFoundErr)
    225  #            raise xml.dom.NotFoundErr(
    226  #                u'"%s" not in this MediaList' % oldMedium)
    227
    228 -    def item(self, index):
    229          """
    230          (DOM)
    231          Returns the mediaType of the index'th element in the list.
    232          If index is greater than or equal to the number of media in the
    233          list, returns None.
    234          """
    235          try:
    236              return self[index].mediaType
    237          except IndexError:
    238              return None
    239
    240 -    def __repr__(self):
    241          return "cssutils.stylesheets.%s(mediaText=%r)" % (
    242                  self.__class__.__name__, self.mediaText)
    243
    244 -    def __str__(self):
    245          return "<cssutils.stylesheets.%s object mediaText=%r at 0x%x>" % (
    246                  self.__class__.__name__, self.mediaText, id(self))
    247