Skip to content

Commit

Permalink
Init push
Browse files Browse the repository at this point in the history
rk0cc committed Sep 4, 2022

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
0 parents commit d17e1e1
Showing 11 changed files with 459 additions and 0 deletions.
30 changes: 30 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/

# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
.vscode/

# Flutter/Dart/Pub related
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
/pubspec.lock
**/doc/api/
.dart_tool/
.packages
build/
10 changes: 10 additions & 0 deletions .metadata
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
revision: ffccd96b62ee8cec7740dab303538c5fc26ac543
channel: stable

project_type: package
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 0.0.1

* TODO: Describe initial release.
29 changes: 29 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
BSD 3-Clause License

Copyright (c) 2022, rk0cc
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Binding Dart collection model to ChangeNotifier in Flutter

This package implemented Dart's collection object with ChangeNotifier that it updated when collection item changed.

## License

BSD-3
5 changes: 5 additions & 0 deletions lib/collection_change_notifier.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
library collection_change_notifier;

export 'src/list/linked_list.dart';
export 'src/list/list.dart';
export 'src/list/queue.dart';
19 changes: 19 additions & 0 deletions lib/src/abstract.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import 'package:flutter/widgets.dart';

/// Totally basic mixin that define implemented collection is binded with
/// [ChangeNotifier].
///
/// Since it shared with [List], [Set], [Map] and other implemented from
/// `dart:collection`, it only provided shared limited properties which both of
/// them exist. Therefore, it should not be exported.
mixin CollectionChangeNotifierMixin on ChangeNotifier {
/// Get how many items contains in this collection or key-value pair for
/// [Map].
int get length;

/// Check this collection does not assigned any items.
bool get isEmpty => length == 0;

/// Check this collection has at least one items assigned.
bool get isNotEmpty => length != 0;
}
47 changes: 47 additions & 0 deletions lib/src/list/linked_list.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import 'dart:collection';

import 'package:flutter/widgets.dart';

import '../abstract.dart';

/// Implemented [ChangeNotifier] features in [LinkedList].
class LinkedListChangeNotifier<E extends LinkedListEntry<E>>
extends LinkedList<E> with ChangeNotifier, CollectionChangeNotifierMixin {
/// Construct a new [LinkedList] with [ChangeNotifier] features.
LinkedListChangeNotifier() : super();

@override
void add(E entry) {
super.add(entry);
notifyListeners();
}

@override
void addAll(Iterable<E> entries) {
super.addAll(entries);
notifyListeners();
}

@override
void addFirst(E entry) {
super.addFirst(entry);
notifyListeners();
}

@override
bool remove(E entry) {
bool rm = super.remove(entry);

if (rm) {
notifyListeners();
}

return rm;
}

@override
void clear() {
super.clear();
notifyListeners();
}
}
165 changes: 165 additions & 0 deletions lib/src/list/list.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import 'dart:collection';

import 'package:flutter/widgets.dart';

import '../abstract.dart';

/// Implemented [ChangeNotifier] feature into [List].
class ListChangeNotifier<E> extends ListBase<E>
with ChangeNotifier, CollectionChangeNotifierMixin {
final List<E> _list;

/// Construct a new [ListChangeNotifier] with empty.
ListChangeNotifier() : _list = [];

/// Construct a new [ListChangeNotifier] from existed [elements].
ListChangeNotifier.from(Iterable<E> elements)
: _list = List.from(elements, growable: true);

/// Set a new [length] of [ListChangeNotifier].
///
/// If set [length] to greater then current one, it assigned `null` to
/// appended index or thrown an error when [E] is not nullable.
@override
set length(int length) {
_list.length = length;
notifyListeners();
}

/// Get how many items assigned into this list.
@override
int get length => _list.length;

/// Get [E] in [index].
@override
E operator [](int index) => _list[index];

/// Assign new [value] from specified [index].
///
/// This action will call [notifyListeners] when assigned.
@override
void operator []=(int index, E value) {
_list[index] = value;
notifyListeners();
}

/// Append a new [element] into this list.
///
/// For assigning multiple [element]s, you **MUST** uses [addAll] instead of
/// wrapping this into a loop which causing build error in Flutter.
///
/// This action will call [notifyListeners] when assigned.
@override
void add(E element) {
_list.add(element);
notifyListeners();
}

/// Append multiple elements as [iterable] into this list.
///
/// This action will call [notifyListeners] when assigned.
@override
void addAll(Iterable<E> iterable) {
_list.addAll(iterable);
notifyListeners();
}

/// Remove all indexed item in this list and [notifyListeners].
@override
void clear() {
_list.clear();
notifyListeners();
}

/// Remove a given [element] in this list and return [bool] that indicate it
/// was in the list or not.
///
/// When it `true`, [notifyListeners] will be called before returning result.
@override
bool remove(Object? element) {
bool rm = _list.remove(element);

if (rm) {
notifyListeners();
}

return rm;
}

/// Remove an item from [index].
///
/// If it removed without throwing [Error], [notifyListeners] will be called
/// before returning removed item [E].
@override
E removeAt(int index) {
E rmi = _list.removeAt(index);
notifyListeners();
return rmi;
}

/// Remove last index item of this list.
///
/// If it removed without throwing [Error], [notifyListeners] will be called
/// before returning removed item [E].
@override
E removeLast() {
E rmi = _list.removeLast();
notifyListeners();
return rmi;
}

/// Remove items with a range of index.
///
/// If it removed without throwing [Error], [notifyListeners] will be called.
@override
void removeRange(int start, int end) {
_list.removeRange(start, end);
notifyListeners();
}

/// Remove items by performing [test].
///
/// It called [notifyListeners] no matter does any item removed or not.
@override
void removeWhere(bool Function(E element) test) {
_list.removeWhere(test);
notifyListeners();
}

/// Replace items in [start] and [end] index to [newContents].
///
/// Once replaced, [notifyListeners] will be called.
@override
void replaceRange(int start, int end, Iterable<E> newContents) {
_list.replaceRange(start, end, newContents);
notifyListeners();
}

/// Retain items by passing [test].
///
/// It called [notifyListeners] whatever items changed.
@override
void retainWhere(bool Function(E element) test) {
_list.retainWhere(test);
notifyListeners();
}

/// Overwrite an indexed item to [iterable] at start [index].
///
/// This will call [notifyListeners].
@override
void setAll(int index, Iterable<E> iterable) {
_list.setAll(index, iterable);
notifyListeners();
}

/// Set items from [start] to [end] to given [iterable].
///
/// If [skipCount] applied, [iterable] will be skipped then start applying
/// item into this list. Finally, call [notifyListeners].
@override
void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
_list.setRange(start, end, iterable, skipCount);
notifyListeners();
}
}
131 changes: 131 additions & 0 deletions lib/src/list/queue.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import 'dart:collection';

import 'package:flutter/widgets.dart';

import '../abstract.dart';

mixin _QueueChangeNotifierMixin<E>
on Queue<E>, ChangeNotifier, CollectionChangeNotifierMixin {
@override
void add(value) {
super.add(value);
notifyListeners();
}

@override
void addAll(Iterable<E> iterable) {
super.addAll(iterable);
notifyListeners();
}

@override
void addFirst(E value) {
super.addFirst(value);
notifyListeners();
}

@override
void addLast(E value) {
super.addLast(value);
notifyListeners();
}

@override
bool remove(Object? value) {
bool rm = super.remove(value);

if (rm) {
notifyListeners();
}

return rm;
}

E _removeGetItem(E Function() getter) {
E rmi = getter();
notifyListeners();
return rmi;
}

@override
E removeFirst() => _removeGetItem(super.removeFirst);

@override
E removeLast() => _removeGetItem(super.removeLast);

@override
void removeWhere(bool Function(E element) test) {
super.removeWhere(test);
notifyListeners();
}

@override
void retainWhere(bool Function(E element) test) {
super.retainWhere(test);
notifyListeners();
}

@override
void clear() {
super.clear();
notifyListeners();
}
}

abstract class QueueChangeNotifier<E>
with ChangeNotifier, CollectionChangeNotifierMixin
implements Queue<E> {
QueueChangeNotifier._();

factory QueueChangeNotifier() = ListQueueChangeNotifier;

factory QueueChangeNotifier.from(Iterable elements) =
ListQueueChangeNotifier.from;

factory QueueChangeNotifier.of(Iterable<E> elements) =
ListQueueChangeNotifier.of;
}

class ListQueueChangeNotifier<E> extends ListQueue<E>
with
ChangeNotifier,
CollectionChangeNotifierMixin,
_QueueChangeNotifierMixin<E>
implements QueueChangeNotifier<E> {
ListQueueChangeNotifier([super.initialCapacity]);

factory ListQueueChangeNotifier.from(Iterable elements) {
ListQueue<E> lq = ListQueue.from(elements);
ListQueueChangeNotifier<E> lqcn = ListQueueChangeNotifier(lq.length);

for (final element in lq) {
lqcn.addLast(element);
}

return lqcn;
}

factory ListQueueChangeNotifier.of(Iterable<E> elements) =>
ListQueueChangeNotifier()..addAll(elements);
}

class DoubleLinkedQueueChangeNotifier<E> extends DoubleLinkedQueue<E>
with
ChangeNotifier,
CollectionChangeNotifierMixin,
_QueueChangeNotifierMixin<E>
implements QueueChangeNotifier<E> {
DoubleLinkedQueueChangeNotifier() : super();

factory DoubleLinkedQueueChangeNotifier.from(Iterable elements) {
DoubleLinkedQueueChangeNotifier<E> dlq = DoubleLinkedQueueChangeNotifier();
for (final e in elements) {
dlq.addLast(e as E);
}

return dlq;
}

factory DoubleLinkedQueueChangeNotifier.of(Iterable<E> elements) =>
DoubleLinkedQueueChangeNotifier()..addAll(elements);
}
13 changes: 13 additions & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: collection_change_notifier
description: Implement change notifier for collection object e.g. List, Set and Map
version: 1.0.0
environment:
sdk: '>=2.18.0 <3.0.0'
flutter: ">=3.3.0"
dependencies:
flutter:
sdk: flutter

dev_dependencies:
flutter_test:
sdk: flutter

0 comments on commit d17e1e1

Please sign in to comment.