OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library model; | 5 library model; |
6 | 6 |
7 import 'package:web_ui/observe.dart'; | 7 import 'package:polymer/polymer.dart'; |
8 import 'package:web_ui/observe/html.dart'; | |
9 | 8 |
10 @observable | 9 final appModel = new AppModel._(); |
11 class ViewModel { | |
12 bool isVisible(Todo todo) => todo != null && | |
13 ((showIncomplete && !todo.done) || (showDone && todo.done)); | |
14 | 10 |
15 bool get showIncomplete => locationHash != '#/completed'; | 11 class AppModel extends ObservableBase { |
| 12 final ObservableList<Todo> todos = new ObservableList<Todo>(); |
| 13 @observable int doneCount; |
| 14 @observable int remaining; |
| 15 @observable List<Todo> visibleTodos; |
| 16 @observable bool hasCompleteTodos; |
16 | 17 |
17 bool get showDone => locationHash != '#/active'; | 18 bool _allChecked; |
18 } | |
19 | 19 |
20 final ViewModel viewModel = new ViewModel(); | 20 AppModel._() { |
| 21 new ListPathObserver(todos, 'done').changes.listen(_updateTodoDone); |
| 22 windowLocation.changes.listen(_updateVisibleTodos); |
| 23 _updateTodoDone(null); |
| 24 } |
21 | 25 |
22 // The real model: | 26 _updateTodoDone(_) { |
| 27 // TODO(jmesserly): we should try using Polymer Expressions and filters |
| 28 // instead of computing so many things. |
| 29 doneCount = todos.fold(0, (count, t) => count + (t.done ? 1 : 0)); |
| 30 hasCompleteTodos = doneCount > 0; |
| 31 remaining = todos.length - doneCount; |
23 | 32 |
24 @observable | 33 _allChecked = notifyPropertyChange(const Symbol('allChecked'), |
25 class AppModel { | 34 _allChecked, todos.length > 0 && remaining == 0); |
26 final ObservableList<Todo> todos = new ObservableList<Todo>(); | |
27 | 35 |
28 bool get allChecked => todos.length > 0 && todos.every((t) => t.done); | 36 _updateVisibleTodos(_); |
| 37 } |
29 | 38 |
30 set allChecked(bool value) => todos.forEach((t) { t.done = value; }); | 39 _updateVisibleTodos(_) { |
| 40 bool filterDone = null; |
| 41 if (windowLocation.hash == '#/completed') { |
| 42 filterDone = true; |
| 43 } else if (windowLocation.hash == '#/active') { |
| 44 filterDone = false; |
| 45 } |
31 | 46 |
32 int get doneCount => | 47 visibleTodos = todos.where( |
33 todos.fold(0, (count, t) => count + (t.done ? 1 : 0)); | 48 (t) => filterDone == null || t.done == filterDone) |
| 49 .toList(growable: false); |
| 50 } |
34 | 51 |
35 int get remaining => todos.length - doneCount; | 52 // TODO(jmesserly): the @observable here is temporary. |
| 53 bool get allChecked => _allChecked; |
| 54 set allChecked(bool value) { |
| 55 todos.forEach((t) { t.done = value; }); |
| 56 } |
36 | 57 |
37 void clearDone() => todos.removeWhere((t) => t.done); | 58 void clearDone() => todos.removeWhere((t) => t.done); |
38 } | 59 } |
39 | 60 |
40 final AppModel app = new AppModel(); | 61 class Todo extends ObservableBase { |
41 | 62 @observable String task; |
42 @observable | 63 @observable bool done = false; |
43 class Todo { | |
44 String task; | |
45 bool done = false; | |
46 | 64 |
47 Todo(this.task); | 65 Todo(this.task); |
48 | 66 |
49 String toString() => "$task ${done ? '(done)' : '(not done)'}"; | 67 String toString() => "$task ${done ? '(done)' : '(not done)'}"; |
50 } | 68 } |
OLD | NEW |