mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 10:33:28 +00:00
4004194c29
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>
295 lines
10 KiB
Dart
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;
|
|
}
|