blob: 0fe6908b1644696d3d91b9d504605f500315ed04 [file] [log] [blame]
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library observable.src.observable;
import 'package:meta/meta.dart';
import 'change_notifier.dart';
import 'records.dart';
/// Represents an object with observable state or properties.
///
/// The interface does not require any specific technique to implement
/// observability. You may implement it in the following ways:
/// - Extend or mixin [ChangeNotifier]
/// - Implement the interface yourself and provide your own implementation
abstract class Observable<C extends ChangeRecord> {
// To be removed when https://github.com/dart-lang/observable/issues/10
final ChangeNotifier<C> _delegate = ChangeNotifier<C>();
// Whether Observable was not given a type.
final bool _isNotGeneric = C == dynamic || C == ChangeRecord;
/// Emits a list of changes when the state of the object changes.
///
/// Changes should produced in order, if significant.
Stream<List<C>> get changes => _delegate.changes;
/// May override to be notified when [changes] is first observed.
@protected
@mustCallSuper
@Deprecated('Use ChangeNotifier instead to have this method available')
// REMOVE IGNORE when https://github.com/dart-lang/observable/issues/10
// ignore: invalid_use_of_protected_member
void observed() => _delegate.observed();
/// May override to be notified when [changes] is no longer observed.
@protected
@mustCallSuper
@Deprecated('Use ChangeNotifier instead to have this method available')
// REMOVE IGNORE when https://github.com/dart-lang/observable/issues/10
// ignore: invalid_use_of_protected_member
void unobserved() => _delegate.unobserved();
/// True if this object has any observers.
@Deprecated('Use ChangeNotifier instead to have this method available')
bool get hasObservers => _delegate.hasObservers;
/// If [hasObservers], synchronously emits [changes] that have been queued.
///
/// Returns `true` if changes were emitted.
@Deprecated('Use ChangeNotifier instead to have this method available')
// REMOVE IGNORE when https://github.com/dart-lang/observable/issues/10
// ignore: invalid_use_of_protected_member
bool deliverChanges() => _delegate.deliverChanges();
/// Notify that the [field] name of this object has been changed.
///
/// The [oldValue] and [newValue] are also recorded. If the two values are
/// equal, no change will be recorded.
///
/// For convenience this returns [newValue].
///
/// ## Deprecated
///
/// All [Observable] objects will no longer be required to emit change records
/// when any property changes. For example, `ObservableList` will only emit
/// on `ObservableList.changes`, instead of on `ObservableList.listChanges`.
///
/// If you are using a typed `implements/extends Observable<C>`, it is illegal
/// to call this method - will throw an [UnsupportedError] when called.
@Deprecated('Use PropertyChangeNotifier')
T notifyPropertyChange<T>(
Symbol field,
T oldValue,
T newValue,
) {
if (hasObservers && oldValue != newValue) {
if (_isNotGeneric) {
notifyChange(
PropertyChangeRecord(
this,
field,
oldValue,
newValue,
) as C,
);
} else {
// Internal specific patch: Just do nothing.
//
// Generic typed Observable does not support.
}
}
return newValue;
}
/// Schedules [change] to be delivered.
///
/// If [change] is omitted then [ChangeRecord.ANY] will be sent.
///
/// If there are no listeners to [changes], this method does nothing.
@Deprecated('Use ChangeNotifier instead to have this method available')
void notifyChange([C change]) => _delegate.notifyChange(change);
}