#: c10:ObservedFlower.py
# Demonstration of "observer" pattern.
import sys
sys.path += ['../util']
from Observer import Observer, Observable

class Flower:
  def __init__(self): 
    self.isOpen = 0
    self.openNotifier = Flower.OpenNotifier(self)
    self.closeNotifier= Flower.CloseNotifier(self)
  def open(self): # Opens its petals
    self.isOpen = 1
    self.openNotifier.notifyObservers()
    self.closeNotifier.open()
  def close(self): # Closes its petals
    self.isOpen = 0
    self.closeNotifier.notifyObservers()
    self.openNotifier.close()
  def closing(self): return self.closeNotifier 

  class OpenNotifier(Observable):
    def __init__(self, outer):
      Observable.__init__(self)
      self.outer = outer
      self.alreadyOpen = 0
    def notifyObservers(self):
      if self.outer.isOpen and \
      not self.alreadyOpen:
        self.setChanged()
        Observable.notifyObservers(self)
        self.alreadyOpen = 1
    def close(self): 
      self.alreadyOpen = 0 

  class CloseNotifier(Observable):
    def __init__(self, outer):
      Observable.__init__(self)
      self.outer = outer
      self.alreadyClosed = 0
    def notifyObservers(self):
      if not self.outer.isOpen and \
      not self.alreadyClosed:
        self.setChanged()
        Observable.notifyObservers(self)
        self.alreadyClosed = 1
    def open(self): 
      alreadyClosed = 0 

class Bee:
  def __init__(self, name):
    self.name = name
    self.openObserver = Bee.OpenObserver(self)
    self.closeObserver = Bee.CloseObserver(self)
  # An inner class for observing openings:
  class OpenObserver(Observer):
    def __init__(self, outer):
      self.outer = outer
    def update(self, observable, arg):
      print "Bee " + self.outer.name + \
        "'s breakfast time!"
  # Another inner class for closings:
  class CloseObserver(Observer):
    def __init__(self, outer):
      self.outer = outer
    def update(self, observable, arg):
      print "Bee " + self.outer.name + \
        "'s bed time!"

class Hummingbird:
  def __init__(self, name): 
    self.name = name
    self.openObserver = \
      Hummingbird.OpenObserver(self)
    self.closeObserver = \
      Hummingbird.CloseObserver(self)
  class OpenObserver(Observer):
    def __init__(self, outer):
      self.outer = outer
    def update(self, observable, arg):
      print "Hummingbird " + self.outer.name + \
        "'s breakfast time!"
  class CloseObserver(Observer):
    def __init__(self, outer):
      self.outer = outer
    def update(self, observable, arg):
      print "Hummingbird " + self.outer.name + \
        "'s bed time!"

f = Flower()
ba = Bee("Eric")
bb = Bee("Eric 0.5")
ha = Hummingbird("A")
hb = Hummingbird("B")
f.openNotifier.addObserver(ha.openObserver)
f.openNotifier.addObserver(hb.openObserver)
f.openNotifier.addObserver(ba.openObserver)
f.openNotifier.addObserver(bb.openObserver)
f.closeNotifier.addObserver(ha.closeObserver)
f.closeNotifier.addObserver(hb.closeObserver)
f.closeNotifier.addObserver(ba.closeObserver)
f.closeNotifier.addObserver(bb.closeObserver)
# Hummingbird 2 decides to sleep in:
f.openNotifier.deleteObserver(hb.openObserver)
# A change that interests observers:
f.open()
f.open() # It's already open, no change.
# Bee 1 doesn't want to go to bed:
f.closeNotifier.deleteObserver(ba.closeObserver)
f.close()
f.close() # It's already closed; no change
f.openNotifier.deleteObservers()
f.open()
f.close()
#:~