dart-sdk/samples-dev/swarm/SwarmState.dart
Aske Simon Christensen 4004194c29 Clean up super calls in swarm.
Remove redundant super calls and move all other super calls to the end
of the initializer list, as required by Dart 2.

Change-Id: I2b0968b9c6508d00a3379c225470d5d9c0ec9f78
Reviewed-on: https://dart-review.googlesource.com/69967
Reviewed-by: Stephen Adams <sra@google.com>
Commit-Queue: Stephen Adams <sra@google.com>
2018-08-21 17:56:13 +00:00

295 lines
10 KiB
Dart

// Copyright (c) 2011, 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.
part of swarmlib;
/**
* The top-level class for the UI state. UI state is essentially a "model" from
* the view's perspective but whose data just describes the UI itself. It
* contains data like the currently selected story, etc.
*/
// TODO(jimhug): Split the two classes here into framework and app-specific.
class SwarmState extends UIState {
/** Core data source for the app. */
final Sections _dataModel;
/**
* Which article the user is currently viewing, or null if they aren't
* viewing an Article.
*/
final ObservableValue<Article> currentArticle;
/**
* Which article the user currently has selected (for traversing articles
* via keyboard shortcuts).
*/
final ObservableValue<Article> selectedArticle;
/**
* True if the story view is maximized and the top and bottom UI elements
* are hidden.
*/
final ObservableValue<bool> storyMaximized;
/**
* True if the maximized story, if any, is being displayed in text mode
* rather than as an embedded web-page.
*/
final ObservableValue<bool> storyTextMode;
/**
* Which article the user currently has selected (by keyboard shortcuts),
* or null if an article isn't selected by the keyboard.
*/
BiIterator<Article> _articleIterator;
/**
* Which feed is currently selected (for keyboard shortcuts).
*/
BiIterator<Feed> _feedIterator;
/**
* Which section is currently selected (for keyboard shortcuts).
*/
BiIterator<Section> _sectionIterator;
SwarmState(this._dataModel)
: currentArticle = new ObservableValue<Article>(null),
selectedArticle = new ObservableValue<Article>(null),
storyMaximized = new ObservableValue<bool>(false),
storyTextMode = new ObservableValue<bool>(true) {
startHistoryTracking();
// TODO(efortuna): consider having this class just hold observable
// currentIndecies instead of iterators with observablevalues..
_sectionIterator = new BiIterator<Section>(_dataModel.sections);
_feedIterator = new BiIterator<Feed>(_sectionIterator.current.feeds);
_articleIterator = new BiIterator<Article>(_feedIterator.current.articles);
currentArticle.addChangeListener((e) {
_articleIterator.jumpToValue(currentArticle.value);
});
}
/**
* Registers an event to fire on any state change
*
* TODO(jmesserly): fix this so we don't have to enumerate all of our fields
* again. One idea here is UIState becomes Observable, Observables have
* parents and notifications bubble up the parent chain.
*/
void addChangeListener(ChangeListener listener) {
_sectionIterator.currentIndex.addChangeListener(listener);
_feedIterator.currentIndex.addChangeListener(listener);
_articleIterator.currentIndex.addChangeListener(listener);
currentArticle.addChangeListener(listener);
}
Map<String, String> toHistory() {
final data = {};
data['section'] = currentSection.id;
data['feed'] = currentFeed.id;
if (currentArticle.value != null) {
data['article'] = currentArticle.value.id;
}
return data;
}
void loadFromHistory(Map values) {
// TODO(jimhug): There's a better way of doing this...
if (values['section'] != null) {
_sectionIterator
.jumpToValue(_dataModel.findSectionById(values['section']));
} else {
_sectionIterator = new BiIterator<Section>(_dataModel.sections);
}
if (values['feed'] != null && currentSection != null) {
_feedIterator.jumpToValue(currentSection.findFeed(values['feed']));
} else {
_feedIterator = new BiIterator<Feed>(_sectionIterator.current.feeds);
}
if (values['article'] != null && currentFeed != null) {
currentArticle.value = currentFeed.findArticle(values['article']);
_articleIterator.jumpToValue(currentArticle.value);
} else {
_articleIterator =
new BiIterator<Article>(_feedIterator.current.articles);
currentArticle.value = null;
}
storyMaximized.value = false;
}
/**
* Move the currentArticle pointer to the next item in the Feed.
*/
void goToNextArticle() {
currentArticle.value = _articleIterator.next();
selectedArticle.value = _articleIterator.current;
}
/**
* Move the currentArticle pointer to the previous item in the Feed.
*/
void goToPreviousArticle() {
currentArticle.value = _articleIterator.previous();
selectedArticle.value = _articleIterator.current;
}
/**
* Move the selectedArticle pointer to the next item in the Feed.
*/
void goToNextSelectedArticle() {
selectedArticle.value = _articleIterator.next();
}
/**
* Move the selectedArticle pointer to the previous item in the Feed.
*/
void goToPreviousSelectedArticle() {
selectedArticle.value = _articleIterator.previous();
}
/**
* Move the pointers for selectedArticle to point to the next
* Feed.
*/
void goToNextFeed() {
var newFeed = _feedIterator.next();
int oldIndex = _articleIterator.currentIndex.value;
_articleIterator = new BiIterator<Article>(
newFeed.articles, _articleIterator.currentIndex.listeners);
_articleIterator.currentIndex.value = oldIndex;
selectedArticle.value = _articleIterator.current;
}
/**
* Move the pointers for selectedArticle to point to the previous
* DataSource.
*/
void goToPreviousFeed() {
var newFeed = _feedIterator.previous();
int oldIndex = _articleIterator.currentIndex.value;
_articleIterator = new BiIterator<Article>(
newFeed.articles, _articleIterator.currentIndex.listeners);
_articleIterator.currentIndex.value = oldIndex;
selectedArticle.value = _articleIterator.current;
}
/**
* Move to the next section (page) of feeds in the UI.
* @param index the previous index (how far down in a given feed)
* from the Source we are moving from.
* This method takes sliderMenu in the event that it needs to move
* to a previous section, it can notify the UI to update.
*/
void goToNextSection(SliderMenu sliderMenu) {
//TODO(efortuna): move sections?
var oldSection = currentSection;
int oldIndex = _articleIterator.currentIndex.value;
sliderMenu.selectNext(true);
// This check prevents our selector from wrapping around when we try to
// go to the "next section", but we're already at the last section.
if (oldSection != _sectionIterator.current) {
_feedIterator = new BiIterator<Feed>(
_sectionIterator.current.feeds, _feedIterator.currentIndex.listeners);
_articleIterator = new BiIterator<Article>(_feedIterator.current.articles,
_articleIterator.currentIndex.listeners);
_articleIterator.currentIndex.value = oldIndex;
selectedArticle.value = _articleIterator.current;
}
}
/**
* Move to the previous section (page) of feeds in the UI.
* @param index the previous index (how far down in a given feed)
* from the Source we are moving from.
* @param oldSection the original starting section (before the slider
* menu moved)
* This method takes sliderMenu in the event that it needs to move
* to a previous section, it can notify the UI to update.
*/
void goToPreviousSection(SliderMenu sliderMenu) {
//TODO(efortuna): don't pass sliderMenu here. Just update in view!
var oldSection = currentSection;
int oldIndex = _articleIterator.currentIndex.value;
sliderMenu.selectPrevious(true);
// This check prevents our selector from wrapping around when we try to
// go to the "previous section", but we're already at the first section.
if (oldSection != _sectionIterator.current) {
_feedIterator = new BiIterator<Feed>(
_sectionIterator.current.feeds, _feedIterator.currentIndex.listeners);
// Jump to back of feed set if we are moving backwards through sections.
_feedIterator.currentIndex.value = _feedIterator.list.length - 1;
_articleIterator = new BiIterator<Article>(_feedIterator.current.articles,
_articleIterator.currentIndex.listeners);
_articleIterator.currentIndex.value = oldIndex;
selectedArticle.value = _articleIterator.current;
}
}
/**
* Set the selected story as the current story (for viewing in the larger
* Story View.)
*/
void selectStoryAsCurrent() {
currentArticle.value = _articleIterator.current;
selectedArticle.value = _articleIterator.current;
}
/**
* Remove our currentArticle selection, to move back to the Main Grid view.
*/
void clearCurrentArticle() {
currentArticle.value = null;
}
/**
* Set the selectedArticle as the first item in that section (UI page).
*/
void goToFirstArticleInSection() {
selectedArticle.value = _articleIterator.current;
}
/**
* Returns true if the UI is currently in the Story View state.
*/
bool get inMainView => currentArticle.value == null;
/**
* Returns true if we currently have an Article selected (for keyboard
* shortcuts browsing).
*/
bool get hasArticleSelected => selectedArticle.value != null;
/**
* Mark the current article as read
*/
bool markCurrentAsRead() {
currentArticle.value.unread.value = false;
}
/**
* The user has moved to a new section (page). This can occur either
* if the user clicked on a section page, or used keyboard shortcuts.
* The default behavior is to move to the first article in the first
* column. The location of the selected item depends on the previous
* selected item location if the user used keyboard shortcuts. These
* are manipulated in goToPrevious/NextSection().
*/
void moveToNewSection(String sectionTitle) {
_sectionIterator.currentIndex.value =
_dataModel.findSectionIndex(sectionTitle);
_feedIterator = new BiIterator<Feed>(
_sectionIterator.current.feeds, _feedIterator.currentIndex.listeners);
_articleIterator = new BiIterator<Article>(_feedIterator.current.articles,
_articleIterator.currentIndex.listeners);
}
Section get currentSection => _sectionIterator.current;
Feed get currentFeed => _feedIterator.current;
}