mirror of
https://github.com/jtgans/g13gui.git
synced 2025-06-20 00:14:09 -04:00
g13gui: Make observers use setProperty and properties
This makes them behave in a much more pythonic way.
This commit is contained in:
parent
6daf662698
commit
d2881a0e6e
@ -41,13 +41,5 @@ class GtkObserver(Observer):
|
||||
overridden.
|
||||
"""
|
||||
(subject, changeType, key, data) = self._observerQueue.get()
|
||||
self.gtkSubjectChanged(subject, changeType, key, data)
|
||||
Observer.onSubjectChanged(self, subject, changeType, key, data)
|
||||
self._observerQueue.task_done()
|
||||
|
||||
def gtkSubjectChanged(self, subject, changeType, key, data=None):
|
||||
"""Subject notification handler.
|
||||
|
||||
Runs on the UI thread, and must be overridden by subclasses.
|
||||
"""
|
||||
raise NotImplementedError(
|
||||
"%s did not override Observer#gtkSubjectChanged" % (type(self)))
|
||||
|
@ -11,26 +11,6 @@ class ChangeType(Enum):
|
||||
MODIFY = 2
|
||||
|
||||
|
||||
class Observer(object):
|
||||
def onSubjectChanged(self, subject, changeType, key, data=None):
|
||||
"""Event handler for observer notifications.
|
||||
|
||||
Each subclass of Observer MUST override this method. There is no default
|
||||
method for handling events of this nature.
|
||||
|
||||
subject[object]: the subject object that sent the event notifying something
|
||||
changed in its data model.
|
||||
changeType[ChangeType]: the type of change that occurred.
|
||||
key[string]: a required name for what field changed.
|
||||
data[object]: an optional context-dependent object, dict, or
|
||||
None, specifying what changed. In the case of an ADD or MODIFY,
|
||||
whatChanged should be the new data. In the case of a DELETE, it should
|
||||
be the old data (or None).
|
||||
"""
|
||||
raise NotImplementedError(
|
||||
"%s did not override Observer#onSubjectChanged!" % (type(self)))
|
||||
|
||||
|
||||
class Subject(object):
|
||||
"""Simple class to handle the subject-side of the Observer pattern."""
|
||||
|
||||
@ -89,13 +69,78 @@ class Subject(object):
|
||||
|
||||
self._changes = []
|
||||
|
||||
def setProperty(self, propertyName, value, notify=True):
|
||||
propertyName = '_' + propertyName
|
||||
self.__dict__[propertyName] = value
|
||||
self.addChange(ChangeType.MODIFY, propertyName, value)
|
||||
if notify:
|
||||
self.notifyChanged()
|
||||
|
||||
|
||||
class Observer(object):
|
||||
def _makeChangeTriggerKeys(self, changeType, keys):
|
||||
result = []
|
||||
if keys != Subject.AllKeys:
|
||||
for key in keys:
|
||||
result.append((changeType, key))
|
||||
else:
|
||||
result.append((changeType, keys))
|
||||
|
||||
return result
|
||||
|
||||
def changeTrigger(self, callback,
|
||||
changeType=None, keys=Subject.AllKeys):
|
||||
if '_changeTriggers' not in self.__dict__:
|
||||
self._changeTriggers = {}
|
||||
for key in self._makeChangeTriggerKeys(changeType, keys):
|
||||
self._changeTriggers[key] = callback
|
||||
|
||||
def onSubjectChanged(self, subject, changeType, key, data=None):
|
||||
"""Generic event handler dispatcher for observer notifications.
|
||||
|
||||
Each subclass of Observer MUST call setChangeTrigger to register a
|
||||
callback method in its __init__.
|
||||
|
||||
subject[object]: the subject object that sent the event notifying
|
||||
something changed in its data model.
|
||||
changeType[ChangeType]: the type of change that occurred.
|
||||
key[string]: a required name for what field changed.
|
||||
data[object]: an optional context-dependent object, dict, or
|
||||
None, specifying what changed. In the case of an ADD or MODIFY,
|
||||
whatChanged should be the new data. In the case of a DELETE, it
|
||||
should be the old data (or None).
|
||||
"""
|
||||
if '_changeTriggers' not in self.__dict__:
|
||||
raise NotImplementedError(
|
||||
'onSubjectChanged(%s, %s, %s, %s) fired with no '
|
||||
'listeners registered!' %
|
||||
(subject, changeType, key, data))
|
||||
|
||||
found = False
|
||||
triggers = (
|
||||
self._changeTriggers.get((None, Subject.AllKeys)),
|
||||
self._changeTriggers.get((changeType, Subject.AllKeys)),
|
||||
self._changeTriggers.get((None, key)),
|
||||
self._changeTriggers.get((changeType, key)))
|
||||
|
||||
for trigger in triggers:
|
||||
if trigger:
|
||||
found = True
|
||||
trigger(subject, changeType, key, data)
|
||||
|
||||
if not found:
|
||||
raise NotImplementedError(
|
||||
'onSubjectChanged(%s, %s, %s, %s) fired without a listener!'
|
||||
% (subject, changeType, key, data))
|
||||
|
||||
|
||||
class ObserverTestCase(Observer, unittest.TestCase):
|
||||
def __init__(self, methodName):
|
||||
unittest.TestCase.__init__(self, methodName)
|
||||
self.changeTrigger(self.changed)
|
||||
self.clearChanges()
|
||||
|
||||
def onSubjectChanged(self, subject, type, key, data=None):
|
||||
def changed(self, subject, type, key, data=None):
|
||||
self.changes.insert(0, {
|
||||
'subject': subject,
|
||||
'type': type,
|
||||
|
@ -3,6 +3,8 @@
|
||||
import unittest
|
||||
import observer
|
||||
|
||||
from builtins import property
|
||||
|
||||
|
||||
class TestIncorrectObserver(observer.Observer):
|
||||
def __hash__(self):
|
||||
@ -10,7 +12,16 @@ class TestIncorrectObserver(observer.Observer):
|
||||
|
||||
|
||||
class TestSubject(observer.Subject):
|
||||
pass
|
||||
def __init__(self):
|
||||
self._value = None
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
return self._value
|
||||
|
||||
@value.setter
|
||||
def value(self, value):
|
||||
self.setProperty('value', value)
|
||||
|
||||
|
||||
class ObserverTestCase(observer.ObserverTestCase):
|
||||
|
Loading…
Reference in New Issue
Block a user