1/*
2 * Copyright 2006, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Stephan A��mus <superstippi@gmx.de>
7 */
8
9#include "Observable.h"
10
11#include <stdio.h>
12#include <typeinfo>
13
14#include <OS.h>
15
16#include "Observer.h"
17
18// constructor
19Observable::Observable()
20	: fObservers(2),
21	  fSuspended(0),
22	  fPendingNotifications(false)
23{
24}
25
26// destructor
27Observable::~Observable()
28{
29	if (fObservers.CountItems() > 0) {
30		char message[256];
31		Observer* o = (Observer*)fObservers.ItemAt(0);
32		sprintf(message, "Observable::~Observable() - %" B_PRId32
33						 " observers still watching, first: %s\n",
34						 fObservers.CountItems(), typeid(*o).name());
35		debugger(message);
36	}
37}
38
39// AddObserver
40bool
41Observable::AddObserver(Observer* observer)
42{
43	if (observer && !fObservers.HasItem((void*)observer)) {
44		return fObservers.AddItem((void*)observer);
45	}
46	return false;
47}
48
49// RemoveObserver
50bool
51Observable::RemoveObserver(Observer* observer)
52{
53	return fObservers.RemoveItem((void*)observer);
54}
55
56// CountObservers
57int32
58Observable::CountObservers() const
59{
60	return fObservers.CountItems();
61}
62
63// ObserverAtFast
64Observer*
65Observable::ObserverAtFast(int32 index) const
66{
67	return (Observer*)fObservers.ItemAtFast(index);
68}
69
70// #pragma mark -
71
72// Notify
73void
74Observable::Notify() const
75{
76	if (!fSuspended) {
77		BList observers(fObservers);
78		int32 count = observers.CountItems();
79		for (int32 i = 0; i < count; i++)
80			((Observer*)observers.ItemAtFast(i))->ObjectChanged(this);
81		fPendingNotifications = false;
82	} else {
83		fPendingNotifications = true;
84	}
85}
86
87// SuspendNotifications
88void
89Observable::SuspendNotifications(bool suspend)
90{
91	if (suspend)
92		fSuspended++;
93	else
94		fSuspended--;
95
96	if (fSuspended < 0) {
97		fprintf(stderr, "Observable::SuspendNotifications(false) - "
98						"error: suspend level below zero!\n");
99		fSuspended = 0;
100	}
101
102	if (!fSuspended && fPendingNotifications)
103		Notify();
104}
105
106