Format samples and samples-dev directories.

BUG=
R=sra@google.com

Review-Url: https://codereview.chromium.org/2828603002 .
This commit is contained in:
Jacob Richman 2017-04-19 07:30:14 -07:00
parent ed2d79a872
commit b33097b9b4
64 changed files with 1340 additions and 1189 deletions

View file

@ -13,7 +13,6 @@ part of swarmlib;
* This class or something similar belongs in the standard DOM library.
*/
class App {
App() {}
/** Begins executing code in this [App]. */
@ -32,10 +31,10 @@ class App {
Timer.run(onLoad);
} else {
window.onContentLoaded.listen(
// TODO(sigmund): Consider eliminating the call to "wrap", for
// instance, modify event listeners to always wrap, or extend DOM code
// to intercept the beginning & end of each event loop
EventBatch.wrap((Event event) => onLoad()));
// TODO(sigmund): Consider eliminating the call to "wrap", for
// instance, modify event listeners to always wrap, or extend DOM code
// to intercept the beginning & end of each event loop
EventBatch.wrap((Event event) => onLoad()));
}
}
@ -52,8 +51,7 @@ class App {
// Swap and reload the cache if ready
if (!swapAndReloadCache()) {
// Otherwise wait until an update to the cache is ready
window.applicationCache.onUpdateReady.listen(
(e) => swapAndReloadCache());
window.applicationCache.onUpdateReady.listen((e) => swapAndReloadCache());
}
}

View file

@ -5,7 +5,6 @@ part of swarmlib;
* a set of items. (Bi-directional)
*/
class BiIterator<E> {
/**
* Provides forward and backward iterator functionality to keep track
* which item is currently selected.
@ -18,7 +17,7 @@ class BiIterator<E> {
List<E> list;
BiIterator(this.list, [List<ChangeListener> oldListeners = null])
: currentIndex = new ObservableValue<int>(0) {
: currentIndex = new ObservableValue<int>(0) {
if (oldListeners != null) {
currentIndex.listeners = oldListeners;
}

File diff suppressed because one or more lines are too long

View file

@ -16,13 +16,14 @@ class ConfigHintDialog extends DialogView {
}
ConfigHintDialog._impl(this._parent, this._doneHandler, View content)
: super('Feed configuration', '', content);
: super('Feed configuration', '', content);
void onDone() { _doneHandler(); }
void onDone() {
_doneHandler();
}
static View makeContent() {
return new View.html(
'''
return new View.html('''
<div>
Add or remove feeds in
<a href="https://www.google.com/reader" target="_blank">

View file

@ -15,8 +15,7 @@ class Sections extends IterableBase<Section> {
int get length => _sections.length;
List<String> get sectionTitles =>
_sections.map((s) => s.title).toList();
List<String> get sectionTitles => _sections.map((s) => s.title).toList();
void refresh() {
// TODO(jimhug): http://b/issue?id=5351067
@ -50,24 +49,25 @@ class Sections extends IterableBase<Section> {
int nSections = decoder.readInt();
final sections = new List<Section>();
for (int i=0; i < nSections; i++) {
for (int i = 0; i < nSections; i++) {
sections.add(Section.decode(decoder));
}
callback(new Sections(sections));
}
static void initializeFromUrl(bool useCannedData,
void callback(Sections sections)) {
static void initializeFromUrl(
bool useCannedData, void callback(Sections sections)) {
if (Sections.runningFromFile || useCannedData) {
initializeFromData(CannedData.data['user.data'], callback);
} else {
// TODO(jmesserly): display an error if we fail here! Silent failure bad.
HttpRequest.getString('data/user.data').then(
EventBatch.wrap((responseText) {
// TODO(jimhug): Nice response if get error back from server.
// TODO(jimhug): Might be more efficient to parse request
// in sections.
initializeFromData(responseText, callback);
HttpRequest
.getString('data/user.data')
.then(EventBatch.wrap((responseText) {
// TODO(jimhug): Nice response if get error back from server.
// TODO(jimhug): Might be more efficient to parse request
// in sections.
initializeFromData(responseText, callback);
}));
}
}
@ -94,7 +94,6 @@ class Sections extends IterableBase<Section> {
bool get isEmpty => length == 0;
}
/** A collection of data sources representing a page in the UI. */
class Section {
final String id;
@ -116,7 +115,7 @@ class Section {
final nSources = decoder.readInt();
final feeds = new ObservableList<Feed>();
for (int j=0; j < nSources; j++) {
for (int j = 0; j < nSources; j++) {
feeds.add(Feed.decode(decoder));
}
return new Section(sectionId, sectionTitle, feeds);
@ -137,8 +136,8 @@ class Feed {
ObservableValue<bool> error; // TODO(jimhug): Check if dead code.
Feed(this.id, this.title, this.iconUrl, {this.description: ''})
: articles = new ObservableList<Article>(),
error = new ObservableValue<bool>(false);
: articles = new ObservableList<Article>(),
error = new ObservableValue<bool>(false);
static Feed decode(Decoder decoder) {
final sourceId = decoder.readString();
@ -147,7 +146,7 @@ class Feed {
final feed = new Feed(sourceId, sourceTitle, sourceIcon);
final nItems = decoder.readInt();
for (int i=0; i < nItems; i++) {
for (int i = 0; i < nItems; i++) {
feed.articles.add(Article.decodeHeader(feed, decoder));
}
return feed;
@ -160,7 +159,6 @@ class Feed {
void refresh() {}
}
/** A single article or posting to display. */
class Article {
final String id;
@ -179,7 +177,8 @@ class Article {
Article(this.dataSource, this.id, this.date, this.title, this.author,
this.srcUrl, this.hasThumbnail, this.textBody,
{htmlBody: null, bool unread: true, this.error: false})
: unread = new ObservableValue<bool>(unread), this._htmlBody = htmlBody;
: unread = new ObservableValue<bool>(unread),
this._htmlBody = htmlBody;
String get htmlBody {
_ensureLoaded();
@ -187,8 +186,10 @@ class Article {
}
String get dataUri {
return SwarmUri.encodeComponent(id).replaceAll('%2F', '/').
replaceAll('%253A', '%3A');
return SwarmUri
.encodeComponent(id)
.replaceAll('%2F', '/')
.replaceAll('%253A', '%3A');
}
String get thumbUrl {
@ -232,9 +233,9 @@ class Article {
final author = decoder.readString();
final dateInSeconds = decoder.readInt();
final snippet = decoder.readString();
final date =
new DateTime.fromMillisecondsSinceEpoch(dateInSeconds*1000, isUtc: true);
return new Article(source, id, date, title, author, srcUrl, hasThumbnail,
snippet);
final date = new DateTime.fromMillisecondsSinceEpoch(dateInSeconds * 1000,
isUtc: true);
return new Article(
source, id, date, title, author, srcUrl, hasThumbnail, snippet);
}
}

View file

@ -19,7 +19,7 @@ class Decoder {
// For more info, see appengine/encoder.py.
int readInt() {
var r = 0;
for (var i=0; ; i++) {
for (var i = 0;; i++) {
var v = data.codeUnitAt(index++);
r |= (v & 0x3F) << (6 * i);
if ((v & 0x40) == 0) break;
@ -29,15 +29,14 @@ class Decoder {
bool readBool() {
final ch = data[index++];
assert (ch == 'T' || ch == 'F');
assert(ch == 'T' || ch == 'F');
return ch == 'T';
}
String readString() {
int len = readInt();
String s = data.substring(index, index+len);
String s = data.substring(index, index + len);
index += len;
return s;
}
}

View file

@ -15,13 +15,14 @@ class HelpDialog extends DialogView {
Function _doneHandler;
HelpDialog(this._parent, this._doneHandler)
: super('Information', '', makeContent());
: super('Information', '', makeContent());
void onDone() { _doneHandler(); }
void onDone() {
_doneHandler();
}
static View makeContent() {
return new View.html(
'''
return new View.html('''
<div>
<p>

View file

@ -23,7 +23,9 @@ class Swarm extends App {
/** Observable UI state. */
SwarmState state;
Swarm({bool useCannedData : false}) : super(), onLoadFired = false {
Swarm({bool useCannedData: false})
: super(),
onLoadFired = false {
Sections.initializeFromUrl(useCannedData, (currSections) {
sections = currSections;
state = new SwarmState(sections);

View file

@ -54,18 +54,17 @@ class SwarmState extends UIState {
BiIterator<Section> _sectionIterator;
SwarmState(this._dataModel)
: super(),
currentArticle = new ObservableValue<Article>(null),
selectedArticle = new ObservableValue<Article>(null),
storyMaximized = new ObservableValue<bool>(false),
storyTextMode = new ObservableValue<bool>(true) {
: super(),
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);
_articleIterator = new BiIterator<Article>(_feedIterator.current.articles);
currentArticle.addChangeListener((e) {
_articleIterator.jumpToValue(currentArticle.value);
@ -99,8 +98,8 @@ class SwarmState extends UIState {
void loadFromHistory(Map values) {
// TODO(jimhug): There's a better way of doing this...
if (values['section'] != null) {
_sectionIterator.jumpToValue(_dataModel.
findSectionById(values['section']));
_sectionIterator
.jumpToValue(_dataModel.findSectionById(values['section']));
} else {
_sectionIterator = new BiIterator<Section>(_dataModel.sections);
}
@ -125,7 +124,7 @@ class SwarmState extends UIState {
* Move the currentArticle pointer to the next item in the Feed.
*/
void goToNextArticle() {
currentArticle.value = _articleIterator.next();
currentArticle.value = _articleIterator.next();
selectedArticle.value = _articleIterator.current;
}
@ -159,8 +158,8 @@ class SwarmState extends UIState {
var newFeed = _feedIterator.next();
int oldIndex = _articleIterator.currentIndex.value;
_articleIterator = new BiIterator<Article>(newFeed.articles,
_articleIterator.currentIndex.listeners);
_articleIterator = new BiIterator<Article>(
newFeed.articles, _articleIterator.currentIndex.listeners);
_articleIterator.currentIndex.value = oldIndex;
selectedArticle.value = _articleIterator.current;
@ -174,11 +173,11 @@ class SwarmState extends UIState {
var newFeed = _feedIterator.previous();
int oldIndex = _articleIterator.currentIndex.value;
_articleIterator = new BiIterator<Article>(newFeed.articles,
_articleIterator.currentIndex.listeners);
_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.
@ -195,10 +194,9 @@ class SwarmState extends UIState {
// 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,
_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;
@ -223,12 +221,11 @@ class SwarmState extends UIState {
// 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);
_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 = new BiIterator<Article>(_feedIterator.current.articles,
_articleIterator.currentIndex.listeners);
_articleIterator.currentIndex.value = oldIndex;
selectedArticle.value = _articleIterator.current;
@ -287,10 +284,9 @@ class SwarmState extends UIState {
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,
_feedIterator = new BiIterator<Feed>(
_sectionIterator.current.feeds, _feedIterator.currentIndex.listeners);
_articleIterator = new BiIterator<Article>(_feedIterator.current.articles,
_articleIterator.currentIndex.listeners);
}

View file

@ -70,13 +70,12 @@ class FrontView extends CompositeView {
headerView = new HeaderView(swarm);
topView.addChild(headerView);
sliderMenu = new SliderMenu(swarm.sections.sectionTitles,
(sectionTitle) {
swarm.state.moveToNewSection(sectionTitle);
_onSectionSelected(sectionTitle);
// Start with no articles selected.
swarm.state.selectedArticle.value = null;
});
sliderMenu = new SliderMenu(swarm.sections.sectionTitles, (sectionTitle) {
swarm.state.moveToNewSection(sectionTitle);
_onSectionSelected(sectionTitle);
// Start with no articles selected.
swarm.state.selectedArticle.value = null;
});
topView.addChild(sliderMenu);
addChild(topView);
@ -99,8 +98,12 @@ class FrontView extends CompositeView {
void afterRender(Element node) {
_createSectionViews();
attachWatch(swarm.state.currentArticle, (e) { _refreshCurrentArticle(); });
attachWatch(swarm.state.storyMaximized, (e) { _refreshMaximized(); });
attachWatch(swarm.state.currentArticle, (e) {
_refreshCurrentArticle();
});
attachWatch(swarm.state.storyMaximized, (e) {
_refreshMaximized();
});
}
void _refreshCurrentArticle() {
@ -121,8 +124,8 @@ class FrontView extends CompositeView {
headerView.startTransitionToMainView();
currentSection.dataSourceView.reattachSubview(
detachedView.source, detachedView, true);
currentSection.dataSourceView
.reattachSubview(detachedView.source, detachedView, true);
storyView.node.onTransitionEnd.first.then((e) {
currentSection.hidden = false;
@ -157,8 +160,8 @@ class FrontView extends CompositeView {
// TODO(jmesserly): make this code better
final view = currentSection.findView(source);
final newPosition = FxUtil.computeRelativePosition(
view.node, bottomView.node);
final newPosition =
FxUtil.computeRelativePosition(view.node, bottomView.node);
currentSection.dataSourceView.detachSubview(view.source);
detachedView = view;
@ -197,8 +200,8 @@ class FrontView extends CompositeView {
void _animateDataSourceToMaximized() {
FxUtil.setWebkitTransform(topView.node, 0, -HeaderView.HEIGHT);
if (detachedView != null) {
FxUtil.setWebkitTransform(detachedView.node, 0,
-DataSourceView.TAB_ONLY_HEIGHT);
FxUtil.setWebkitTransform(
detachedView.node, 0, -DataSourceView.TAB_ONLY_HEIGHT);
}
}
@ -326,7 +329,9 @@ class SwarmBackButton extends View {
Element render() => new Element.html('<div class="back-arrow button"></div>');
void afterRender(Element node) {
addOnClick((e) { _backToMain(swarm.state); });
addOnClick((e) {
_backToMain(swarm.state);
});
}
}
@ -365,9 +370,13 @@ class HeaderView extends CompositeView {
void afterRender(Element node) {
// Respond to changes to whether the story is being shown as text or web.
attachWatch(swarm.state.storyTextMode, (e) { refreshWebStoryButtons(); });
attachWatch(swarm.state.storyTextMode, (e) {
refreshWebStoryButtons();
});
_title.addOnClick((e) { _backToMain(swarm.state); });
_title.addOnClick((e) {
_backToMain(swarm.state);
});
// Wire up the events.
_configButton.addOnClick((e) {
@ -418,7 +427,6 @@ class HeaderView extends CompositeView {
startTransitionToMainView();
}
/**
* Refreshes whether or not the buttons specific to the display of a story in
* the web perspective are visible.
@ -433,7 +441,7 @@ class HeaderView extends CompositeView {
_webBackButton.hidden = webButtonsHidden;
_webForwardButton.hidden = webButtonsHidden;
_newWindowButton.hidden = webButtonsHidden;
_newWindowButton.hidden = webButtonsHidden;
}
void startTransitionToMainView() {
@ -457,7 +465,6 @@ class HeaderView extends CompositeView {
}
}
/** A back button for the web view of a story that is equivalent to clicking
* "back" in the browser. */
// TODO(rnystrom): We have nearly identical versions of this littered through
@ -470,7 +477,9 @@ class WebBackButton extends View {
}
void afterRender(Element node) {
addOnClick((e) { back(); });
addOnClick((e) {
back();
});
}
/** Equivalent to [window.history.back] */
@ -491,7 +500,9 @@ class WebForwardButton extends View {
}
void afterRender(Element node) {
addOnClick((e) { forward(); });
addOnClick((e) {
forward();
});
}
/** Equivalent to [window.history.forward] */
@ -514,12 +525,11 @@ class DataSourceViewFactory implements ViewFactory<Feed> {
int get height => null; // Width for this view isn't known.
}
/**
* A view for the items from a single data source.
* Shows a title and a list of items.
*/
class DataSourceView extends CompositeView {
class DataSourceView extends CompositeView {
// TODO(jacobr): make this value be coupled with the CSS file.
static const TAB_ONLY_HEIGHT = 34;
@ -527,19 +537,20 @@ class DataSourceView extends CompositeView {
VariableSizeListView<Article> itemsView;
DataSourceView(this.source, Swarm swarm) : super('query') {
// TODO(jacobr): make the title a view or decide it is sane for a subclass
// of component view to manually add some DOM cruft.
node.nodes.add(new Element.html(
'<h2>${source.title}</h2>'));
node.nodes.add(new Element.html('<h2>${source.title}</h2>'));
// TODO(jacobr): use named arguments when available.
itemsView = addChild(new VariableSizeListView<Article>(
source.articles,
new ArticleViewFactory(swarm),
true, /* scrollable */
true, /* vertical */
swarm.state.currentArticle, /* selectedItem */
true,
/* scrollable */
true,
/* vertical */
swarm.state.currentArticle,
/* selectedItem */
!Device.supportsTouch /* snapToArticles */,
false /* paginate */,
true /* removeClippedViews */,
@ -562,14 +573,16 @@ class ToggleButton extends View {
List<String> states;
ToggleButton(this.states)
: super(),
onChanged = new EventListeners();
: super(),
onChanged = new EventListeners();
Element render() => new Element.tag('button');
void afterRender(Element node) {
state = states[0];
node.onClick.listen((event) { toggle(); });
node.onClick.listen((event) {
toggle();
});
}
String get state {
@ -599,8 +612,7 @@ class ArticleViewFactory implements VariableSizeViewFactory<Article> {
Swarm swarm;
ArticleViewLayout layout;
ArticleViewFactory(this.swarm)
: layout = ArticleViewLayout.getSingleton();
ArticleViewFactory(this.swarm) : layout = ArticleViewLayout.getSingleton();
View newView(Article item) => new ArticleView(item, swarm, layout);
@ -637,9 +649,9 @@ class ArticleViewLayout {
int width;
static ArticleViewLayout _singleton;
ArticleViewLayout() :
measureBodyText = new MeasureText(BODY_FONT),
measureTitleText = new MeasureText(TITLE_FONT) {
ArticleViewLayout()
: measureBodyText = new MeasureText(BODY_FONT),
measureTitleText = new MeasureText(TITLE_FONT) {
num screenWidth = window.screen.width;
width = DESKTOP_WIDTH;
}
@ -665,19 +677,18 @@ class ArticleViewLayout {
* titleContainer and snippetContainer may be null in which case the size is
* computed but no actual layout is performed.
*/
ArticleViewMetrics computeLayout(Article item,
StringBuffer titleBuffer,
StringBuffer snippetBuffer) {
ArticleViewMetrics computeLayout(
Article item, StringBuffer titleBuffer, StringBuffer snippetBuffer) {
int titleWidth = width - BODY_MARGIN_LEFT;
if (item.hasThumbnail) {
titleWidth = width - TITLE_MARGIN_LEFT;
}
final titleLines = measureTitleText.addLineBrokenText(titleBuffer,
item.title, titleWidth, MAX_TITLE_LINES);
final bodyLines = measureBodyText.addLineBrokenText(snippetBuffer,
item.textBody, width - BODY_MARGIN_LEFT, MAX_BODY_LINES);
final titleLines = measureTitleText.addLineBrokenText(
titleBuffer, item.title, titleWidth, MAX_TITLE_LINES);
final bodyLines = measureBodyText.addLineBrokenText(
snippetBuffer, item.textBody, width - BODY_MARGIN_LEFT, MAX_BODY_LINES);
int height = bodyLines * LINE_HEIGHT + TOTAL_MARGIN;
@ -741,7 +752,6 @@ class ArticleView extends View {
}
void afterRender(Element node) {
// Select this view's item.
addOnClick((e) {
// Mark the item as read, so it shows as read in other views
@ -791,13 +801,13 @@ class ArticleView extends View {
// Story View.
swarm.frontView.detachedView.itemsView.showView(selArticle);
} else {
if(swarm.frontView.currentSection.inCurrentView(selArticle)) {
if (swarm.frontView.currentSection.inCurrentView(selArticle)) {
// Scroll horizontally if needed.
swarm.frontView.currentSection.dataSourceView.showView(
selArticle.dataSource);
DataSourceView dataView = swarm.frontView.currentSection
.findView(selArticle.dataSource);
if(dataView != null) {
swarm.frontView.currentSection.dataSourceView
.showView(selArticle.dataSource);
DataSourceView dataView =
swarm.frontView.currentSection.findView(selArticle.dataSource);
if (dataView != null) {
dataView.itemsView.showView(selArticle);
}
}
@ -807,8 +817,8 @@ class ArticleView extends View {
String getDataUriForImage(final img) {
// TODO(hiltonc,jimhug) eval perf of this vs. reusing one canvas element
final CanvasElement canvas = new CanvasElement(
height: img.height, width: img.width);
final CanvasElement canvas =
new CanvasElement(height: img.height, width: img.width);
final CanvasRenderingContext2D ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, img.width, img.height);
@ -848,8 +858,8 @@ class StoryContentView extends View {
get childViews => [_pagedStory];
Element render() {
final storyContent = new Element.html(
'<div class="story-content">${item.htmlBody}</div>');
final storyContent =
new Element.html('<div class="story-content">${item.htmlBody}</div>');
for (Element element in storyContent.querySelectorAll(
"iframe, script, style, object, embed, frameset, frame")) {
element.remove();
@ -896,9 +906,9 @@ class SectionView extends CompositeView {
final PageState pageState;
SectionView(this.swarm, this.section, this._viewFactory)
: super('section-view'),
loadingText = new View.html('<div class="loading-section"></div>'),
pageState = new PageState() {
: super('section-view'),
loadingText = new View.html('<div class="loading-section"></div>'),
pageState = new PageState() {
addChild(loadingText);
}
@ -912,14 +922,16 @@ class SectionView extends CompositeView {
if (dataSourceView == null) {
// TODO(jacobr): use named arguments when available.
dataSourceView = new ListView<Feed>(
section.feeds, _viewFactory,
section.feeds,
_viewFactory,
true /* scrollable */,
false /* vertical */,
null /* selectedItem */,
true /* snapToItems */,
true /* paginate */,
true /* removeClippedViews */,
false, /* showScrollbar */
false,
/* showScrollbar */
pageState);
dataSourceView.addClass("data-source-view");
addChild(dataSourceView);

View file

@ -60,8 +60,8 @@ abstract class UIState {
// TODO(jmesserly): [state] should be an Object, and we should pass it to
// the state parameter instead of as a #hash URL. Right now we're working
// around b/4582542.
window.history.pushState(null,
'${document.title}', '${document.title}#$state');
window.history
.pushState(null, '${document.title}', '${document.title}#$state');
}
/**

View file

@ -31,7 +31,7 @@ abstract class VariableSizeViewFactory<D> {
/** A collection of event listeners. */
class EventListeners {
var listeners;
EventListeners() {
EventListeners() {
listeners = new List();
}
@ -46,7 +46,6 @@ class EventListeners {
}
}
/**
* Private view class used to store placeholder views for detatched ListView
* elements.
@ -98,8 +97,7 @@ abstract class ListViewLayout<D> {
* Returns an interval specifying what views are currently visible given a
* particular [:offset:].
*/
Interval computeVisibleInterval(num offset, num viewLength,
num bufferLength);
Interval computeVisibleInterval(num offset, num viewLength, num bufferLength);
}
/**
@ -138,19 +136,19 @@ class GenericListView<D> extends View {
* and update the view appropriately.
*/
GenericListView(
this._layout,
this._data,
this._scrollable,
this._vertical,
this._selectedItem,
this._snapToItems,
this._paginate,
this._removeClippedViews,
this._showScrollbar,
this._pages)
: super(),
_activeInterval = new Interval(0, 0),
_itemViews = new Map<int, View>() {
this._layout,
this._data,
this._scrollable,
this._vertical,
this._selectedItem,
this._snapToItems,
this._paginate,
this._removeClippedViews,
this._showScrollbar,
this._pages)
: super(),
_activeInterval = new Interval(0, 0),
_itemViews = new Map<int, View>() {
// TODO(rnystrom): Move this into enterDocument once we have an exitDocument
// that we can use to unregister it.
if (_scrollable) {
@ -216,16 +214,16 @@ class GenericListView<D> extends View {
_containerElem,
_vertical /* verticalScrollEnabled */,
!_vertical /* horizontalScrollEnabled */,
true /* momentumEnabled */,
() {
num width = _layout.getWidth(_viewLength);
num height = _layout.getHeight(_viewLength);
width = width != null ? width : 0;
height = height != null ? height : 0;
return new Size(width, height);
},
_paginate && _snapToItems ?
Scroller.FAST_SNAP_DECELERATION_FACTOR : 1);
true /* momentumEnabled */, () {
num width = _layout.getWidth(_viewLength);
num height = _layout.getHeight(_viewLength);
width = width != null ? width : 0;
height = height != null ? height : 0;
return new Size(width, height);
},
_paginate && _snapToItems
? Scroller.FAST_SNAP_DECELERATION_FACTOR
: 1);
scroller.onContentMoved.listen((e) => renderVisibleItems(false));
if (_pages != null) {
watch(_pages.target, (s) => _onPageSelected());
@ -251,14 +249,16 @@ class GenericListView<D> extends View {
if (_data is ObservableList<D>) {
ObservableList<D> observable = _data;
attachWatch(observable, (EventSummary e) {
if (e.target == observable) {
onDataChange();
}
});
if (e.target == observable) {
onDataChange();
}
});
}
if (_selectedItem != null) {
addOnClick((Event e) { _onClick(e); });
addOnClick((Event e) {
_onClick(e);
});
}
if (_selectedItem != null) {
@ -286,7 +286,6 @@ class GenericListView<D> extends View {
style.overflow = 'hidden';
}
void onResize() {
int lastViewLength = _viewLength;
scheduleMicrotask(() {
@ -322,10 +321,12 @@ class GenericListView<D> extends View {
}
void _decelStart() {
num currentTarget = scroller.verticalEnabled ?
scroller.currentTarget.y : scroller.currentTarget.x;
num current = scroller.verticalEnabled ?
scroller.contentOffset.y : scroller.contentOffset.x;
num currentTarget = scroller.verticalEnabled
? scroller.currentTarget.y
: scroller.currentTarget.x;
num current = scroller.verticalEnabled
? scroller.contentOffset.y
: scroller.contentOffset.x;
num targetIndex = _layout.getSnapIndex(currentTarget, _viewLength);
if (current != currentTarget) {
// The user is throwing rather than statically releasing.
@ -333,8 +334,8 @@ class GenericListView<D> extends View {
// as long as they made at least a minimal throw gesture.
num currentIndex = _layout.getSnapIndex(current, _viewLength);
if (currentIndex == targetIndex &&
(currentTarget - current).abs() > SNAP_TO_NEXT_THROW_THRESHOLD &&
-_layout.getOffset(targetIndex) != currentTarget) {
(currentTarget - current).abs() > SNAP_TO_NEXT_THROW_THRESHOLD &&
-_layout.getOffset(targetIndex) != currentTarget) {
num snappedCurrentPosition = -_layout.getOffset(targetIndex);
targetIndex = getNextIndex(targetIndex, currentTarget < current);
}
@ -349,7 +350,7 @@ class GenericListView<D> extends View {
} else {
// Update the target page only after we are all done animating.
if (_pages != null) {
_pages.target.value =_layout.getPage(targetIndex, _viewLength);
_pages.target.value = _layout.getPage(targetIndex, _viewLength);
}
}
}
@ -367,16 +368,16 @@ class GenericListView<D> extends View {
}
void _onPageSelected() {
if (_pages.target !=
_layout.getPage(_activeInterval.start, _viewLength)) {
if (_pages.target != _layout.getPage(_activeInterval.start, _viewLength)) {
_throwTo(_layout.getOffset(
_layout.getPageStartIndex(_pages.target.value, _viewLength)));
}
}
num get _offset {
return scroller.verticalEnabled ?
scroller.getVerticalOffset() : scroller.getHorizontalOffset();
return scroller.verticalEnabled
? scroller.getVerticalOffset()
: scroller.getHorizontalOffset();
}
/**
@ -396,12 +397,12 @@ class GenericListView<D> extends View {
}
if (_pages != null) {
_pages.current.value =
_layout.getPage(targetInterval.start, _viewLength);
_pages.current.value = _layout.getPage(targetInterval.start, _viewLength);
}
if (_pages != null) {
_pages.length.value = _data.length > 0 ?
_layout.getPage(_data.length - 1, _viewLength) + 1 : 0;
_pages.length.value = _data.length > 0
? _layout.getPage(_data.length - 1, _viewLength) + 1
: 0;
}
if (!_removeClippedViews) {
@ -418,23 +419,27 @@ class GenericListView<D> extends View {
// Remove views that are not needed anymore
for (int i = _activeInterval.start,
end = Math.min(targetInterval.start, _activeInterval.end);
i < end; i++) {
end = Math.min(targetInterval.start, _activeInterval.end);
i < end;
i++) {
_removeView(i);
}
for (int i = Math.max(targetInterval.end, _activeInterval.start);
i < _activeInterval.end; i++) {
i < _activeInterval.end;
i++) {
_removeView(i);
}
// Add new views
for (int i = targetInterval.start,
end = Math.min(_activeInterval.start, targetInterval.end);
i < end; i++) {
end = Math.min(_activeInterval.start, targetInterval.end);
i < end;
i++) {
_addView(i);
}
for (int i = Math.max(_activeInterval.end, targetInterval.start);
i < targetInterval.end; i++) {
i < targetInterval.end;
i++) {
_addView(i);
}
@ -462,7 +467,7 @@ class GenericListView<D> extends View {
final view = _itemViews[index];
_addViewHelper(view, index);
childViewAdded(view);
return view;
return view;
}
final view = _newView(index);
@ -523,7 +528,7 @@ class GenericListView<D> extends View {
currentPosition =
FxUtil.computeRelativePosition(view.node, _containerElem);
}
assert (_itemViews[index] is _PlaceholderView);
assert(_itemViews[index] is _PlaceholderView);
view.enterDocument();
_itemViews[index].node.replaceWith(view.node);
_itemViews[index] = view;
@ -531,7 +536,9 @@ class GenericListView<D> extends View {
FxUtil.setTranslate(view.node, currentPosition.x, currentPosition.y, 0);
// The view's position is unchanged except now re-parented to
// the list view.
Timer.run(() { _positionSubview(view.node, index); });
Timer.run(() {
_positionSubview(view.node, index);
});
} else {
_positionSubview(view.node, index);
}
@ -551,7 +558,7 @@ class GenericListView<D> extends View {
}
void _positionSubview(Element node, int index) {
if (_vertical) {
if (_vertical) {
FxUtil.setTranslate(node, 0, _layout.getOffset(index), 0);
} else {
FxUtil.setTranslate(node, _layout.getOffset(index), 0, 0);
@ -609,8 +616,8 @@ class FixedSizeListViewLayout<D> implements ListViewLayout<D> {
List<D> _data;
bool _paginate;
FixedSizeListViewLayout(this.itemViewFactory, this._data, this._vertical,
this._paginate);
FixedSizeListViewLayout(
this.itemViewFactory, this._data, this._vertical, this._paginate);
void onDataChange() {}
@ -622,7 +629,6 @@ class FixedSizeListViewLayout<D> implements ListViewLayout<D> {
return _vertical ? itemViewFactory.height : itemViewFactory.width;
}
int getWidth(int viewLength) {
return _vertical ? itemViewFactory.width : getLength(viewLength);
}
@ -647,15 +653,14 @@ class FixedSizeListViewLayout<D> implements ListViewLayout<D> {
}
int getLength(int viewLength) {
int itemLength =
_vertical ? itemViewFactory.height : itemViewFactory.width;
int itemLength = _vertical ? itemViewFactory.height : itemViewFactory.width;
if (viewLength == null || viewLength == 0) {
return itemLength * _data.length;
} else if (_paginate) {
if (_data.length > 0) {
final pageLength = getPageLength(viewLength);
return getPage(_data.length - 1, viewLength)
* pageLength + Math.max(viewLength, pageLength);
return getPage(_data.length - 1, viewLength) * pageLength +
Math.max(viewLength, pageLength);
} else {
return 0;
}
@ -705,23 +710,30 @@ class FixedSizeListViewLayout<D> implements ListViewLayout<D> {
* Simple list view class where each item has fixed width and height.
*/
class ListView<D> extends GenericListView<D> {
/**
* Creates a new ListView for the given data. If [:_data:] is an
* [:ObservableList<T>:] then it will listen to changes to the list and
* update the view appropriately.
*/
ListView(List<D> data, ViewFactory<D> itemViewFactory, bool scrollable,
bool vertical, ObservableValue<D> selectedItem,
[bool snapToItems = false,
bool paginate = false,
bool removeClippedViews = false,
bool showScrollbar = false,
PageState pages = null])
: super(new FixedSizeListViewLayout<D>(itemViewFactory, data, vertical,
paginate),
data, scrollable, vertical, selectedItem, snapToItems, paginate,
removeClippedViews, showScrollbar, pages);
bool vertical, ObservableValue<D> selectedItem,
[bool snapToItems = false,
bool paginate = false,
bool removeClippedViews = false,
bool showScrollbar = false,
PageState pages = null])
: super(
new FixedSizeListViewLayout<D>(
itemViewFactory, data, vertical, paginate),
data,
scrollable,
vertical,
selectedItem,
snapToItems,
paginate,
removeClippedViews,
showScrollbar,
pages);
}
/**
@ -738,18 +750,18 @@ class VariableSizeListViewLayout<D> implements ListViewLayout<D> {
VariableSizeViewFactory<D> itemViewFactory;
Interval _lastVisibleInterval;
VariableSizeListViewLayout(this.itemViewFactory, data, this._vertical,
this._paginate) :
_data = data,
_lastVisibleInterval = new Interval(0, 0) {
VariableSizeListViewLayout(
this.itemViewFactory, data, this._vertical, this._paginate)
: _data = data,
_lastVisibleInterval = new Interval(0, 0) {
_itemOffsets = <int>[];
_lengths = <int>[];
_itemOffsets.add(0);
}
void onDataChange() {
_itemOffsets.clear();
_itemOffsets.add(0);
_itemOffsets.clear();
_itemOffsets.add(0);
_lengths.clear();
}
@ -800,12 +812,12 @@ class VariableSizeListViewLayout<D> implements ListViewLayout<D> {
num lengthFromAllButLastElement = 0;
if (_itemOffsets.length > 2) {
lengthFromAllButLastElement =
(getOffset(_itemOffsets.length - 2) -
getOffset(0)) *
(_data.length / (_itemOffsets.length - 2));
(getOffset(_itemOffsets.length - 2) - getOffset(0)) *
(_data.length / (_itemOffsets.length - 2));
}
return (lengthFromAllButLastElement +
Math.max(viewLength, _lengths[_lengths.length - 1])).toInt();
Math.max(viewLength, _lengths[_lengths.length - 1]))
.toInt();
} else {
if (_lengths.length == 1) {
return Math.max(viewLength, _lengths[0]);
@ -821,7 +833,7 @@ class VariableSizeListViewLayout<D> implements ListViewLayout<D> {
} else {
// Hack so that _lengths[length - 1] is available.
getOffset(_data.length);
return (getOffset(_data.length - 1) - getOffset(0)) +
return (getOffset(_data.length - 1) - getOffset(0)) +
Math.max(_lengths[_lengths.length - 1], viewLength);
}
}
@ -830,7 +842,8 @@ class VariableSizeListViewLayout<D> implements ListViewLayout<D> {
if (index >= _itemOffsets.length) {
int offset = _itemOffsets[_itemOffsets.length - 1];
for (int i = _itemOffsets.length; i <= index; i++) {
int length = _vertical ? itemViewFactory.getHeight(_data[i - 1])
int length = _vertical
? itemViewFactory.getHeight(_data[i - 1])
: itemViewFactory.getWidth(_data[i - 1]);
offset += length;
_itemOffsets.add(offset);
@ -860,13 +873,11 @@ class VariableSizeListViewLayout<D> implements ListViewLayout<D> {
}
Interval computeVisibleInterval(
num offset, num viewLength, num bufferLength) {
num offset, num viewLength, num bufferLength) {
offset = offset.toInt();
int start = _findFirstItemBefore(
-offset - bufferLength,
int start = _findFirstItemBefore(-offset - bufferLength,
_lastVisibleInterval != null ? _lastVisibleInterval.start : 0);
int end = _findFirstItemAfter(
-offset + viewLength + bufferLength,
int end = _findFirstItemAfter(-offset + viewLength + bufferLength,
_lastVisibleInterval != null ? _lastVisibleInterval.end : 0);
_lastVisibleInterval = new Interval(start, Math.max(start, end));
_lastOffset = offset;
@ -896,21 +907,25 @@ class VariableSizeListViewLayout<D> implements ListViewLayout<D> {
}
class VariableSizeListView<D> extends GenericListView<D> {
VariableSizeListView(List<D> data,
VariableSizeViewFactory<D> itemViewFactory,
bool scrollable,
bool vertical,
ObservableValue<D> selectedItem,
[bool snapToItems = false,
bool paginate = false,
bool removeClippedViews = false,
bool showScrollbar = false,
PageState pages = null])
: super(new VariableSizeListViewLayout(itemViewFactory, data, vertical,
paginate),
data, scrollable, vertical, selectedItem, snapToItems,
paginate, removeClippedViews, showScrollbar, pages);
VariableSizeListView(List<D> data, VariableSizeViewFactory<D> itemViewFactory,
bool scrollable, bool vertical, ObservableValue<D> selectedItem,
[bool snapToItems = false,
bool paginate = false,
bool removeClippedViews = false,
bool showScrollbar = false,
PageState pages = null])
: super(
new VariableSizeListViewLayout(
itemViewFactory, data, vertical, paginate),
data,
scrollable,
vertical,
selectedItem,
snapToItems,
paginate,
removeClippedViews,
showScrollbar,
pages);
}
/** A back button that is equivalent to clicking "back" in the browser. */
@ -924,7 +939,6 @@ class BackButton extends View {
}
}
// TODO(terry): Maybe should be part of ButtonView class in appstack/view?
/** OS button. */
class PushButtonView extends View {
@ -943,7 +957,6 @@ class PushButtonView extends View {
}
}
// TODO(terry): Add a drop shadow around edge and corners need to be rounded.
// Need to support conveyor for contents of dialog so it's not
// larger than the parent window.
@ -968,8 +981,8 @@ class DialogView extends View {
</div>
</div>''');
_done = new PushButtonView('Done', 'done-button',
EventBatch.wrap((e) => onDone()));
_done = new PushButtonView(
'Done', 'done-button', EventBatch.wrap((e) => onDone()));
final titleArea = node.querySelector('.dialog-title-area');
titleArea.nodes.add(_done.node);
@ -980,5 +993,5 @@ class DialogView extends View {
}
/** Override to handle dialog done. */
void onDone() { }
void onDone() {}
}

View file

@ -44,8 +44,7 @@ class AnimationScheduler {
CssStyleDeclaration _safariHackStyle;
int _frameCount = 0;
AnimationScheduler()
: _callbacks = new List<CallbackData>() {
AnimationScheduler() : _callbacks = new List<CallbackData>() {
if (_isMobileSafari) {
// TODO(jacobr): find a better workaround for the issue that 3d transforms
// sometimes don't render on iOS without forcing a layout.
@ -72,8 +71,7 @@ class AnimationScheduler {
* pending callback.
*/
int requestAnimationFrame(AnimationCallback callback,
[Element element = null,
num minTime = null]) {
[Element element = null, num minTime = null]) {
final callbackData = new CallbackData(callback, minTime);
_requestAnimationFrameHelper(callbackData);
return callbackData.id;
@ -85,8 +83,9 @@ class AnimationScheduler {
}
void _setupInterval() {
window.requestAnimationFrame(
(num ignored) { _step(); });
window.requestAnimationFrame((num ignored) {
_step();
});
}
void _step() {

View file

@ -10,7 +10,6 @@ part of base;
* Utils for device detection.
*/
class Device {
/**
* The regular expression for detecting an iPhone or iPod.
*/

View file

@ -14,7 +14,9 @@ class Dom {
Timer.run(f);
} else {
// TODO(jacobr): give this event a named property.
window.onContentLoaded.listen((Event e) { f(); });
window.onContentLoaded.listen((Event e) {
f();
});
}
}

View file

@ -21,8 +21,7 @@ class Env {
* cancel the pending callback.
*/
static int requestAnimationFrame(AnimationCallback callback,
[Element element = null,
num minTime = null]) {
[Element element = null, num minTime = null]) {
if (_animationScheduler == null) {
_animationScheduler = new AnimationScheduler();
}

View file

@ -11,8 +11,7 @@ class Size {
num width;
num height;
Size(num this.width, num this.height) {
}
Size(num this.width, num this.height) {}
bool operator ==(Size other) {
return other != null && width == other.width && height == other.height;
@ -127,8 +126,9 @@ class Size {
* Returns this Size object, after optional scaling.
*/
Size scaleToFit(Size target) {
num s = aspectRatio() > target.aspectRatio() ?
target.width / width : target.height / height;
num s = aspectRatio() > target.aspectRatio()
? target.width / width
: target.height / height;
return scale(s);
}

View file

@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
library base;
import 'dart:html';
import 'dart:async';
import 'dart:math';

View file

@ -43,7 +43,6 @@ part of layout;
// - Optimize for the case of no content sized tracks
// - Optimize for the "incremental update" cases
class GridLayout extends ViewLayout {
/** Configuration parameters defined in CSS. */
final GridTrackList rows;
final GridTrackList columns;
@ -72,22 +71,18 @@ class GridLayout extends ViewLayout {
Dimension _dimension;
GridLayout(Positionable view)
: super(view),
rows = _GridTrackParser.parse(view.customStyle['grid-rows']),
columns = _GridTrackParser.parse(view.customStyle['grid-columns']),
template = _GridTemplateParser.parse(view.customStyle['grid-template']),
rowSizing = _GridTrackParser.parseTrackSizing(
view.customStyle['grid-row-sizing']),
columnSizing = _GridTrackParser.parseTrackSizing(
view.customStyle['grid-column-sizing']) {
: super(view),
rows = _GridTrackParser.parse(view.customStyle['grid-rows']),
columns = _GridTrackParser.parse(view.customStyle['grid-columns']),
template = _GridTemplateParser.parse(view.customStyle['grid-template']),
rowSizing = _GridTrackParser
.parseTrackSizing(view.customStyle['grid-row-sizing']),
columnSizing = _GridTrackParser
.parseTrackSizing(view.customStyle['grid-column-sizing']) {
_rowTracks = rows != null ? rows.tracks : new List<GridTrack>();
_columnTracks = columns != null ? columns.tracks : new List<GridTrack>();
}
int get currentWidth => _gridWidth;
int get currentHeight => _gridHeight;
@ -152,11 +147,8 @@ class GridLayout extends ViewLayout {
*/
// Note: spec does not correctly doc all the parameters to this function.
void _computeUsedBreadthOfTracks(List<GridTrack> tracks) {
// TODO(jmesserly): as a performance optimization we could cache this
final items = view.childViews
.map((view_) => view_.layout)
.toList();
final items = view.childViews.map((view_) => view_.layout).toList();
CollectionUtils.sortBy(items, (item) => _getSpanCount(item));
// 1. Initialize per Grid Track variables
@ -192,8 +184,8 @@ class GridLayout extends ViewLayout {
// maxBreadth value until RemainingSpace is exhausted.
// Note: it's not spec'd what to pass as the accumulator, but usedBreadth
// seems right.
_distributeSpaceToTracks(tracks, _getRemainingSpace(tracks),
USED_BREADTH, false);
_distributeSpaceToTracks(
tracks, _getRemainingSpace(tracks), USED_BREADTH, false);
// Spec wording is confusing about which direction this assignment happens,
// but this is the way that makes sense.
@ -204,8 +196,8 @@ class GridLayout extends ViewLayout {
// 6. Grow all Grid Tracks having a fraction as their maxSizing
final tempBreadth = _calcNormalizedFractionBreadth(tracks);
for (final t in tracks) {
t.usedBreadth = Math.max(t.usedBreadth,
tempBreadth * t.maxSizing.fractionValue);
t.usedBreadth =
Math.max(t.usedBreadth, tempBreadth * t.maxSizing.fractionValue);
}
_computeTrackPositions(tracks);
@ -255,7 +247,6 @@ class GridLayout extends ViewLayout {
* freeSpace less the sum of the current UsedBreadths.
*/
num _calcNormalizedFractionBreadth(List<GridTrack> tracks) {
final fractionTracks = tracks.where((t) => t.maxSizing.isFraction).toList();
// Note: the spec has various bugs in this function, such as mismatched
@ -295,11 +286,10 @@ class GridLayout extends ViewLayout {
*/
void _distributeSpaceToTracks(List<GridTrack> tracks, num freeSpace,
_BreadthAccumulator breadth, bool ignoreMaxBreadth) {
// TODO(jmesserly): in some cases it would be safe to sort the passed in
// list in place. Not always though.
tracks = CollectionUtils.orderBy(tracks,
(t) => t.maxBreadth - breadth.getSize(t));
tracks = CollectionUtils.orderBy(
tracks, (t) => t.maxBreadth - breadth.getSize(t));
// Give each Grid Track an equal share of the space, but without exceeding
// their maxBreadth values. Because there are different MaxBreadths
@ -341,9 +331,10 @@ class GridLayout extends ViewLayout {
*/
void _distributeSpaceBySpanCount(List<ViewLayout> items,
ContentSizeMode sizeMode, _BreadthAccumulator breadth) {
items = items.where((item) =>
_hasContentSizedTracks(_getTracks(item), sizeMode, breadth)).toList();
items = items
.where((item) =>
_hasContentSizedTracks(_getTracks(item), sizeMode, breadth))
.toList();
var tracks = [];
@ -368,8 +359,7 @@ class GridLayout extends ViewLayout {
if (spanCountFinished) {
for (final t in tracks) {
breadth.setSize(t,
Math.max(breadth.getSize(t), t.updatedBreadth));
breadth.setSize(t, Math.max(breadth.getSize(t), t.updatedBreadth));
}
tracks = [];
}
@ -382,12 +372,10 @@ class GridLayout extends ViewLayout {
*/
static bool _hasContentSizedTracks(Iterable<GridTrack> tracks,
ContentSizeMode sizeMode, _BreadthAccumulator breadth) {
for (final t in tracks) {
final fn = breadth.getSizingFunction(t);
if (sizeMode == ContentSizeMode.MAX && fn.isMaxContentSized ||
sizeMode == ContentSizeMode.MIN && fn.isContentSized) {
// Make sure we don't cross a fractional track
return tracks.length == 1 || !tracks.any((t_) => t_.isFractional);
}
@ -396,8 +384,8 @@ class GridLayout extends ViewLayout {
}
/** Ensures that the numbered track exists. */
void _ensureTrack(List<GridTrack> tracks, TrackSizing sizing,
int start, int span) {
void _ensureTrack(
List<GridTrack> tracks, TrackSizing sizing, int start, int span) {
// Start is 1-based. Make it 0-based.
start -= 1;
@ -515,7 +503,8 @@ class GridLayout extends ViewLayout {
int _getSpanCount(ViewLayout item) {
GridLayoutParams childLayout = item.layoutParams;
return (_dimension == Dimension.WIDTH ?
childLayout.columnSpan : childLayout.rowSpan);
return (_dimension == Dimension.WIDTH
? childLayout.columnSpan
: childLayout.rowSpan);
}
}

View file

@ -24,44 +24,41 @@ class GridLayoutParams extends LayoutParams {
GridItemAlignment rowAlign;
GridItemAlignment columnAlign;
GridLayoutParams(Positionable view, GridLayout layout)
: super(view.node) {
GridLayoutParams(Positionable view, GridLayout layout) : super(view.node) {
// TODO(jmesserly): this can be cleaned up a lot by just passing "view"
// into the parsers.
rowAlign = new GridItemAlignment.fromString(
view.customStyle['grid-row-align']);
columnAlign = new GridItemAlignment.fromString(
view.customStyle['grid-column-align']);
rowAlign =
new GridItemAlignment.fromString(view.customStyle['grid-row-align']);
columnAlign =
new GridItemAlignment.fromString(view.customStyle['grid-column-align']);
layer = StringUtils.parseInt(view.customStyle['grid-layer'], 0);
rowSpan = StringUtils.parseInt(view.customStyle['grid-row-span']);
columnSpan = StringUtils.parseInt(view.customStyle['grid-column-span']);
var line = _GridItemParser.parse(
view.customStyle['grid-row'], layout.rows);
var line = _GridItemParser.parse(view.customStyle['grid-row'], layout.rows);
if (line != null) {
row = line.start;
if (line.length != null) {
if (rowSpan != null) {
throw new UnsupportedError(
'grid-row-span cannot be with grid-row that defines an end');
'grid-row-span cannot be with grid-row that defines an end');
}
rowSpan = line.length;
}
}
line = _GridItemParser.parse(
view.customStyle['grid-column'], layout.columns);
line =
_GridItemParser.parse(view.customStyle['grid-column'], layout.columns);
if (line != null) {
column = line.start;
if (line.length != null) {
if (columnSpan != null) {
throw new UnsupportedError(
'grid-column-span cannot be with grid-column that defines an end');
'grid-column-span cannot be with grid-column that defines an end');
}
columnSpan = line.length;
}
@ -73,8 +70,10 @@ class GridLayoutParams extends LayoutParams {
// error handling. For now, throw an error on a misconfigured view.
// CSS is designed to be a permissive language, though, so we should do
// better and resolve conflicts more intelligently.
if (row != null || column != null ||
rowSpan != null || columnSpan != null) {
if (row != null ||
column != null ||
rowSpan != null ||
columnSpan != null) {
throw new UnsupportedError(
'grid-cell cannot be used with grid-row and grid-column');
}
@ -89,15 +88,14 @@ class GridLayoutParams extends LayoutParams {
column = rect.column;
rowSpan = rect.rowSpan;
columnSpan = rect.columnSpan;
} else {
// Apply default row, column span values.
if (rowSpan == null) rowSpan = 1;
if (columnSpan == null) columnSpan = 1;
if (row == null && column == null) {
throw new UnsupportedError('grid-flow is not implemented'
+ ' so at least one row or one column must be defined');
throw new UnsupportedError('grid-flow is not implemented' +
' so at least one row or one column must be defined');
}
if (row == null) row = 1;

View file

@ -13,18 +13,18 @@ class _Parser {
// TODO(jmesserly): shouldn't need this optimization, but dart_json parser
// found that they needed this.
static const A_BIG = 65; // 'A'.codeUnitAt(0)
static const Z_BIG = 90; // 'Z'.codeUnitAt(0)
static const A_SMALL = 97; // 'a'.codeUnitAt(0)
static const Z_SMALL = 122; // 'z'.codeUnitAt(0)
static const TAB = 9; // '\t'.codeUnitAt(0)
static const NEW_LINE = 10; // '\n'.codeUnitAt(0)
static const LINE_FEED = 13; // '\r'.codeUnitAt(0)
static const SPACE = 32; // ' '.codeUnitAt(0)
static const ZERO = 48; // '0'.codeUnitAt(0)
static const NINE = 57; // '9'.codeUnitAt(0)
static const DOT = 46; // '.'.codeUnitAt(0)
static const R_PAREN = 41; // ')'.codeUnitAt(0)
static const A_BIG = 65; // 'A'.codeUnitAt(0)
static const Z_BIG = 90; // 'Z'.codeUnitAt(0)
static const A_SMALL = 97; // 'a'.codeUnitAt(0)
static const Z_SMALL = 122; // 'z'.codeUnitAt(0)
static const TAB = 9; // '\t'.codeUnitAt(0)
static const NEW_LINE = 10; // '\n'.codeUnitAt(0)
static const LINE_FEED = 13; // '\r'.codeUnitAt(0)
static const SPACE = 32; // ' '.codeUnitAt(0)
static const ZERO = 48; // '0'.codeUnitAt(0)
static const NINE = 57; // '9'.codeUnitAt(0)
static const DOT = 46; // '.'.codeUnitAt(0)
static const R_PAREN = 41; // ')'.codeUnitAt(0)
final String _src;
int _offset;
@ -74,8 +74,8 @@ class _Parser {
}
bool _maybeEatMultiLineComment() {
if (_maybeEat('/*', /*eatWhitespace:*/false)) {
while (!_maybeEat('*/', /*eatWhitespace:*/false)) {
if (_maybeEat('/*', /*eatWhitespace:*/ false)) {
while (!_maybeEat('*/', /*eatWhitespace:*/ false)) {
if (_offset >= length) {
_error('expected */');
}
@ -330,9 +330,9 @@ class _GridTrackParser extends _Parser {
final Map<String, int> _lineNames;
_GridTrackParser._internal(String src)
: super(src),
_tracks = new List<GridTrack>(),
_lineNames = new Map<String, int>();
: super(src),
_tracks = new List<GridTrack>(),
_lineNames = new Map<String, int>();
/** Parses the grid-rows and grid-columns CSS properties into object form. */
static GridTrackList parse(String str) {
@ -465,7 +465,6 @@ class _GridTrackParser extends _Parser {
}
}
/**
* Exception thrown because the grid style properties had incorrect values.
*/

View file

@ -24,7 +24,6 @@ class GridTrackList {
GridTrackList(this.tracks, this.lineNames) {}
}
/** Represents a row or a column. */
class GridTrack {
/**
@ -62,7 +61,6 @@ class GridTrack {
bool get isFractional => minSizing.isFraction || maxSizing.isFraction;
}
/** Represents the grid-row-align or grid-column-align. */
class GridItemAlignment {
// TODO(jmesserly): should this be stored as an int for performance?
@ -70,14 +68,15 @@ class GridItemAlignment {
// 'start' | 'end' | 'center' | 'stretch'
GridItemAlignment.fromString(String value)
: this.value = (value == null) ? 'stretch' : value {
switch (this.value) {
case 'start': case 'end': case 'center': case 'stretch':
: this.value = (value == null) ? 'stretch' : value {
switch (this.value) {
case 'start':
case 'end':
case 'center':
case 'stretch':
break;
default:
throw new UnsupportedError(
'invalid row/column alignment "$value"');
throw new UnsupportedError('invalid row/column alignment "$value"');
}
}
@ -98,7 +97,6 @@ class GridItemAlignment {
}
}
/**
* Represents a grid-template. Used in conjunction with a grid-cell to
* place cells in the grid, without needing to specify the exact row/column.
@ -108,8 +106,8 @@ class GridTemplate {
final int _numRows;
GridTemplate(List<String> rows)
: _rects = new Map<int, _GridTemplateRect>(),
_numRows = rows.length {
: _rects = new Map<int, _GridTemplateRect>(),
_numRows = rows.length {
_buildRects(rows);
}
@ -145,7 +143,7 @@ class GridTemplate {
final rect = _rects[cell.codeUnitAt(0)];
if (rect == null) {
throw new UnsupportedError(
'grid-cell "$cell" not found in parent\'s grid-template');
'grid-cell "$cell" not found in parent\'s grid-template');
}
return rect;
}
@ -155,10 +153,12 @@ class GridTemplate {
class _GridTemplateRect {
int row, column, rowSpan, columnSpan, _count, _char;
_GridTemplateRect(this._char, this.row, this.column)
: rowSpan = 1, columnSpan = 1, _count = 1 {}
: rowSpan = 1,
columnSpan = 1,
_count = 1 {}
void add(int r, int c) {
assert (r >= row && c >= column);
assert(r >= row && c >= column);
_count++;
rowSpan = Math.max(rowSpan, r - row + 1);
columnSpan = Math.max(columnSpan, c - column + 1);
@ -176,7 +176,6 @@ class _GridTemplateRect {
}
}
/**
* Used to return a row/column and span during parsing of grid-row and
* grid-column during parsing.

View file

@ -42,8 +42,8 @@ class FixedSizing extends SizingFunction {
bool _contentSized;
FixedSizing(this.length, [this.units = 'px'])
: super(),
_contentSized = false {
: super(),
_contentSized = false {
if (units != 'px' && units != '%') {
// TODO(jmesserly): support other unit types
throw new UnsupportedError('Units other than px and %');
@ -73,7 +73,6 @@ class FixedSizing extends SizingFunction {
String toString() => 'FixedSizing: ${length}${units} $_contentSized';
}
/**
* Fraction is a non-negative floating-point number followed by 'fr'. Each
* fraction value takes a share of the remaining space proportional to its
@ -99,7 +98,9 @@ class MinContentSizing extends SizingFunction {
class MaxContentSizing extends SizingFunction {
const MaxContentSizing() : super();
bool get isMaxContentSized { return true; }
bool get isMaxContentSized {
return true;
}
String toString() => 'MaxContentSizing';
}
@ -113,8 +114,8 @@ class TrackSizing {
final SizingFunction max;
const TrackSizing.auto()
: min = const MinContentSizing(),
max = const MaxContentSizing();
: min = const MinContentSizing(),
max = const MaxContentSizing();
TrackSizing(this.min, this.max) {}
@ -134,7 +135,10 @@ abstract class _BreadthAccumulator {
class _UsedBreadthAccumulator implements _BreadthAccumulator {
const _UsedBreadthAccumulator();
void setSize(GridTrack t, num value) { t.usedBreadth = value; }
void setSize(GridTrack t, num value) {
t.usedBreadth = value;
}
num getSize(GridTrack t) => t.usedBreadth;
SizingFunction getSizingFunction(GridTrack t) => t.minSizing;
@ -143,9 +147,11 @@ class _UsedBreadthAccumulator implements _BreadthAccumulator {
class _MaxBreadthAccumulator implements _BreadthAccumulator {
const _MaxBreadthAccumulator();
void setSize(GridTrack t, num value) { t.maxBreadth = value; }
void setSize(GridTrack t, num value) {
t.maxBreadth = value;
}
num getSize(GridTrack t) => t.maxBreadth;
SizingFunction getSizingFunction(GridTrack t) => t.maxSizing;
}

View file

@ -21,7 +21,6 @@ abstract class Positionable {
void doLayout();
}
/**
* Caches the layout parameters that were specified in CSS during a layout
* computation. These values are immutable during a layout.
@ -128,8 +127,7 @@ class ViewLayout {
int get borderHeight => borderTopWidth + borderBottomWidth;
/** Implements the custom layout computation. */
void measureLayout(Future<Size> size, Completer<bool> changed) {
}
void measureLayout(Future<Size> size, Completer<bool> changed) {}
/**
* Positions the view within its parent container.
@ -182,7 +180,7 @@ class ViewLayout {
}
int measureContent(ViewLayout parent, Dimension dimension,
[ContentSizeMode mode = null]) {
[ContentSizeMode mode = null]) {
if (dimension == Dimension.WIDTH) {
return measureWidth(parent, mode);
} else if (dimension == Dimension.HEIGHT) {
@ -193,11 +191,9 @@ class ViewLayout {
int measureWidth(ViewLayout parent, ContentSizeMode mode) {
final style = layoutParams.style;
if (mode == ContentSizeMode.MIN) {
return _styleToPixels(
style.minWidth, currentWidth, parent.currentWidth);
return _styleToPixels(style.minWidth, currentWidth, parent.currentWidth);
} else if (mode == ContentSizeMode.MAX) {
return _styleToPixels(
style.maxWidth, currentWidth, parent.currentWidth);
return _styleToPixels(style.maxWidth, currentWidth, parent.currentWidth);
}
}

View file

@ -47,16 +47,21 @@ class ChangeEvent {
/** Factory constructor for property change events. */
ChangeEvent.property(
this.target, this.propertyName, this.newValue, this.oldValue)
: type = UPDATE, index = null;
: type = UPDATE,
index = null;
/** Factory constructor for list change events. */
ChangeEvent.list(
this.target, this.type, this.index, this.newValue, this.oldValue)
: propertyName = null;
: propertyName = null;
/** Factory constructor for [GLOBAL] change events. */
ChangeEvent.global(this.target)
: type = GLOBAL, newValue = null, oldValue = null, propertyName = null, index = null;
: type = GLOBAL,
newValue = null,
oldValue = null,
propertyName = null,
index = null;
}
/** A collection of change events on a single observable instance. */

View file

@ -11,7 +11,6 @@ part of observable;
* AbstractObservable, which works with this class to implement batching.
*/
class EventBatch {
/** The current active batch, if any. */
static EventBatch current;
@ -88,7 +87,7 @@ class EventBatch {
int uid = obj.uid;
EventSummary summary = summaries[uid];
if (summary == null) {
assert (!sealed);
assert(!sealed);
summary = new EventSummary(obj);
summaries[uid] = summary;
}

View file

@ -35,10 +35,8 @@ abstract class Observable {
bool removeChangeListener(ChangeListener listener);
}
/** Common functionality for observable objects. */
class AbstractObservable implements Observable {
/** Unique id to identify this model in an event batch. */
final int uid;
@ -59,8 +57,8 @@ class AbstractObservable implements Observable {
}
AbstractObservable([Observable this.parent = null])
: uid = EventBatch.genUid(),
listeners = new List<ChangeListener>();
: uid = EventBatch.genUid(),
listeners = new List<ChangeListener>();
bool addChangeListener(ChangeListener listener) {
if (listeners.indexOf(listener, 0) == -1) {
@ -82,8 +80,8 @@ class AbstractObservable implements Observable {
}
void recordPropertyUpdate(String propertyName, newValue, oldValue) {
recordEvent(new ChangeEvent.property(
this, propertyName, newValue, oldValue));
recordEvent(
new ChangeEvent.property(this, propertyName, newValue, oldValue));
}
void recordListUpdate(int index, newValue, oldValue) {
@ -92,13 +90,13 @@ class AbstractObservable implements Observable {
}
void recordListInsert(int index, newValue) {
recordEvent(new ChangeEvent.list(
this, ChangeEvent.INSERT, index, newValue, null));
recordEvent(
new ChangeEvent.list(this, ChangeEvent.INSERT, index, newValue, null));
}
void recordListRemove(int index, oldValue) {
recordEvent(new ChangeEvent.list(
this, ChangeEvent.REMOVE, index, null, oldValue));
recordEvent(
new ChangeEvent.list(this, ChangeEvent.REMOVE, index, null, oldValue));
}
void recordGlobalChange() {
@ -113,7 +111,7 @@ class AbstractObservable implements Observable {
if (EventBatch.current != null) {
// Already in a batch, so just add it.
assert (!EventBatch.current.sealed);
assert(!EventBatch.current.sealed);
// TODO(sigmund): measure the performance implications of this indirection
// and consider whether caching the summary object in this instance helps.
var summary = EventBatch.current.getEvents(this);
@ -121,22 +119,23 @@ class AbstractObservable implements Observable {
} else {
// Not in a batch, so create a one-off one.
// TODO(rnystrom): Needing to do ignore and (null) here is awkward.
EventBatch.wrap((ignore) { recordEvent(event); })(null);
EventBatch.wrap((ignore) {
recordEvent(event);
})(null);
}
}
}
/** A growable list that fires events when it's modified. */
class ObservableList<T>
extends AbstractObservable
class ObservableList<T> extends AbstractObservable
implements List<T>, Observable {
/** Underlying list. */
// TODO(rnystrom): Make this final if we get list.remove().
List<T> _internal;
ObservableList([Observable parent = null])
: super(parent), _internal = new List<T>();
: super(parent),
_internal = new List<T>();
T operator [](int index) => _internal[index];
@ -246,7 +245,8 @@ class ObservableList<T>
if (srcStart < dstStart) {
for (int i = srcStart + count - 1, j = dstStart + count - 1;
i >= srcStart; i--, j--) {
i >= srcStart;
i--, j--) {
dst[j] = src[i];
}
} else {
@ -288,8 +288,8 @@ class ObservableList<T>
throw new UnimplementedError();
}
dynamic fold(var initialValue,
dynamic combine(var previousValue, T element)) {
dynamic fold(
var initialValue, dynamic combine(var previousValue, T element)) {
throw new UnimplementedError();
}
@ -303,11 +303,15 @@ class ObservableList<T>
List<T> take(int count) => _internal.take(count);
bool every(bool f(T element)) => _internal.every(f);
bool any(bool f(T element)) => _internal.any(f);
void forEach(void f(T element)) { _internal.forEach(f); }
void forEach(void f(T element)) {
_internal.forEach(f);
}
String join([String separator = ""]) => _internal.join(separator);
dynamic firstWhere(bool test(T value), {Object orElse()}) {
return _internal.firstWhere(test, orElse: orElse);
}
dynamic lastWhere(bool test(T value), {Object orElse()}) {
return _internal.lastWhere(test, orElse: orElse);
}
@ -316,7 +320,7 @@ class ObservableList<T>
bool remove(T element) => throw new UnimplementedError();
void removeWhere(bool test(T element)) => throw new UnimplementedError();
void retainWhere(bool test(T element)) => throw new UnimplementedError();
List<T> toList({bool growable:true}) => throw new UnimplementedError();
List<T> toList({bool growable: true}) => throw new UnimplementedError();
Set<T> toSet() => throw new UnimplementedError();
Iterable<T> takeWhile(bool test(T value)) => throw new UnimplementedError();
Iterable<T> skipWhile(bool test(T value)) => throw new UnimplementedError();
@ -324,14 +328,15 @@ class ObservableList<T>
T singleWhere(bool test(T value)) {
return _internal.singleWhere(test);
}
T elementAt(int index) {
return _internal.elementAt(index);
}
Map<int, T> asMap() {
return _internal.asMap();
}
bool get isEmpty => length == 0;
bool get isNotEmpty => !isEmpty;
@ -346,7 +351,8 @@ class ObservableList<T>
/** A wrapper around a single value whose change can be observed. */
class ObservableValue<T> extends AbstractObservable {
ObservableValue(T value, [Observable parent = null])
: super(parent), _value = value;
: super(parent),
_value = value;
T get value => _value;

View file

@ -24,8 +24,12 @@ class BezierPhysics {
* bezier when the final velocity is zero. This is a special case for which
* these control points are constants.
*/
static const List<num> _FINAL_VELOCITY_ZERO_BEZIER =
const [_ONE_THIRD, _TWO_THIRDS, _TWO_THIRDS, 1];
static const List<num> _FINAL_VELOCITY_ZERO_BEZIER = const [
_ONE_THIRD,
_TWO_THIRDS,
_TWO_THIRDS,
1
];
/**
* Given consistent kinematics parameters for constant acceleration, returns
@ -34,9 +38,8 @@ class BezierPhysics {
* Returns a list [:[x1, y1, x2, y2]:] representing the intermediate control
* points of the cubic Bezier.
*/
static List<num> calculateCubicBezierFromKinematics(
num initialVelocity, num finalVelocity, num totalTime,
num totalDisplacement) {
static List<num> calculateCubicBezierFromKinematics(num initialVelocity,
num finalVelocity, num totalTime, num totalDisplacement) {
// Total time must be greater than 0.
assert(!GoogleMath.nearlyEquals(totalTime, 0) && totalTime > 0);
// Total displacement must not be 0.
@ -51,8 +54,8 @@ class BezierPhysics {
}
List<num> controlPoint = _tangentLinesToQuadraticBezier(
initialVelocity, finalVelocity, totalTime, totalDisplacement);
controlPoint = _normalizeQuadraticBezier(controlPoint[0], controlPoint[1],
totalTime, totalDisplacement);
controlPoint = _normalizeQuadraticBezier(
controlPoint[0], controlPoint[1], totalTime, totalDisplacement);
return _quadraticToCubic(controlPoint[0], controlPoint[1]);
}
@ -86,8 +89,7 @@ class BezierPhysics {
* [y2] The y-coordinate of the end point.
* Returns a list [:[x1, y1]:] representing the intermediate control point.
*/
static List<num> _normalizeQuadraticBezier(
num x1, num y1, num x2, num y2) {
static List<num> _normalizeQuadraticBezier(num x1, num y1, num x2, num y2) {
// The end point must not lie on any axes.
assert(!GoogleMath.nearlyEquals(x2, 0) && !GoogleMath.nearlyEquals(y2, 0));
return [x1 / x2, y1 / y2];

View file

@ -69,10 +69,8 @@ class ClickBuster {
*/
DoubleLinkedQueueEntry<num> entry = _coordinates.firstEntry();
while (entry != null) {
if (_hitTest(entry.element,
entry.nextEntry().element,
coord.x,
coord.y)) {
if (_hitTest(
entry.element, entry.nextEntry().element, coord.x, coord.y)) {
entry.nextEntry().remove();
entry.remove();
return;
@ -96,9 +94,9 @@ class ClickBuster {
final coord = new Coordinate.fromClient(te.touches[0]);
_coordinates.add(coord.x);
_coordinates.add(coord.y);
new Timer(
const Duration(milliseconds: _TIME_THRESHOLD),
() { _removeCoordinate(coord.x, coord.y); });
new Timer(const Duration(milliseconds: _TIME_THRESHOLD), () {
_removeCoordinate(coord.x, coord.y);
});
_toggleTapHighlights(true);
}
@ -180,27 +178,29 @@ class ClickBuster {
if (_coordinates == null) {
// Listen to clicks on capture phase so they can be busted before anything
// else gets a chance to handle them.
Element.clickEvent.forTarget(document, useCapture: true).listen(
(e) { _onClick(e); });
Element.focusEvent.forTarget(document, useCapture: true).listen(
(e) { _lastPreventedTime = 0; });
Element.clickEvent.forTarget(document, useCapture: true).listen((e) {
_onClick(e);
});
Element.focusEvent.forTarget(document, useCapture: true).listen((e) {
_lastPreventedTime = 0;
});
// Listen to touchstart on capture phase since it must be called prior to
// every click or else we will accidentally prevent the click even if we
// don't call preventGhostClick.
Function startFn = (e) { _onTouchStart(e); };
Function startFn = (e) {
_onTouchStart(e);
};
if (!Device.supportsTouch) {
startFn = mouseToTouchCallback(startFn);
}
var stream;
if (Device.supportsTouch) {
stream = Element.touchStartEvent.forTarget(document, useCapture:true);
stream = Element.touchStartEvent.forTarget(document, useCapture: true);
} else {
stream = Element.mouseDownEvent.forTarget(document, useCapture:true);
stream = Element.mouseDownEvent.forTarget(document, useCapture: true);
}
EventUtil.observe(document,
stream,
startFn, true);
EventUtil.observe(document, stream, startFn, true);
_coordinates = new DoubleLinkedQueue<num>();
}

View file

@ -8,7 +8,6 @@ part of touch;
* Common events related helpers.
*/
class EventUtil {
/**
* Add an event listener to an element.
* The event callback is specified by [handler].
@ -16,14 +15,18 @@ class EventUtil {
* If [removeHandlerOnFocus] is true the handler is removed when there is any
* focus event, and added back on blur events.
*/
static void observe(/*Element or Document*/ element,
Stream stream, Function handler,
[bool removeHandlerOnFocus = false]) {
static void observe(
/*Element or Document*/ element, Stream stream, Function handler,
[bool removeHandlerOnFocus = false]) {
var subscription = stream.listen(handler);
// TODO(jacobr): this remove on focus behavior seems really ugly.
if (removeHandlerOnFocus) {
element.onFocus.listen((e) { subscription.cancel(); });
element.onBlur.listen((e) { subscription.cancel(); });
element.onFocus.listen((e) {
subscription.cancel();
});
element.onBlur.listen((e) {
subscription.cancel();
});
}
}

View file

@ -37,10 +37,12 @@ class FxUtil {
}
/** Apply a -webkit-transform using translate3d to an HTML element. */
static void setWebkitTransform(
Element el, num x, num y, [num z = 0,
num rotation = null, num scale = null,
num originX = null, num originY = null]) {
static void setWebkitTransform(Element el, num x, num y,
[num z = 0,
num rotation = null,
num scale = null,
num originX = null,
num originY = null]) {
final style = el.style;
// TODO(jacobr): create a helper class that simplifies building
// transformation matricies that will be set as CSS styles. We should

View file

@ -8,7 +8,6 @@ part of touch;
* Represents a point in 2 dimensional space.
*/
class Coordinate {
/**
* X-value
*/
@ -19,8 +18,7 @@ class Coordinate {
*/
num y;
Coordinate([num this.x = 0, num this.y = 0]) {
}
Coordinate([num this.x = 0, num this.y = 0]) {}
/**
* Gets the coordinates of a touch's location relative to the window's
@ -66,7 +64,6 @@ class Coordinate {
* Represents the interval { x | start <= x < end }.
*/
class Interval {
final num start;
final num end;
@ -83,8 +80,7 @@ class Interval {
int get hashCode => throw new UnimplementedError();
Interval union(Interval other) {
return new Interval(Math.min(start, other.start),
Math.max(end, other.end));
return new Interval(Math.min(start, other.start), Math.max(end, other.end));
}
bool contains(num value) {

View file

@ -54,16 +54,15 @@ class InfiniteScroller {
Element _bottomDiv;
Element _bottomLoadingDiv;
InfiniteScroller(Scroller scroller,
Function onTopScroll, Function onBottomScroll,
double offsetTop, [double offsetBottom = null])
InfiniteScroller(Scroller scroller, Function onTopScroll,
Function onBottomScroll, double offsetTop,
[double offsetBottom = null])
: _scroller = scroller,
_onTopScroll = onTopScroll,
_onBottomScroll = onBottomScroll,
_offsetTop = offsetTop,
_offsetBottom = offsetBottom == null ? offsetTop : offsetBottom,
_lastScrollY = 0.0 {
}
_lastScrollY = 0.0 {}
/**
* Adds the loading divs.
@ -74,10 +73,11 @@ class InfiniteScroller {
* [bottomLoadingDiv] is the div to show at the bottom when waiting for more
* content to load at the end of the page.
*/
void addLoadingDivs([Element topDiv = null,
Element topLoadingDiv = null,
Element bottomDiv = null,
Element bottomLoadingDiv = null]) {
void addLoadingDivs(
[Element topDiv = null,
Element topLoadingDiv = null,
Element bottomDiv = null,
Element bottomLoadingDiv = null]) {
_topDiv = topDiv;
_topLoadingDiv = topLoadingDiv;
_bottomDiv = bottomDiv;
@ -129,14 +129,16 @@ class InfiniteScroller {
* Register the event listeners.
*/
void _registerEventListeners() {
_scroller.onScrollerEnd.listen((Event event) { _onScrollEnd(); });
_scroller.onScrollerEnd.listen((Event event) {
_onScrollEnd();
});
}
/**
* Hides one div and shows another.
*/
void _updateVisibility(bool isLoading, Element element,
Element loadingElement) {
void _updateVisibility(
bool isLoading, Element element, Element loadingElement) {
if (element != null) {
element.style.display = isLoading ? "none" : "";
}

View file

@ -26,15 +26,15 @@ part of touch;
* -webkit-transform style property.
*/
abstract class Momentum {
factory Momentum(MomentumDelegate delegate, [num defaultDecelerationFactor = 1])
=> new TimeoutMomentum(delegate, defaultDecelerationFactor);
factory Momentum(MomentumDelegate delegate,
[num defaultDecelerationFactor = 1]) =>
new TimeoutMomentum(delegate, defaultDecelerationFactor);
bool get decelerating;
num get decelerationFactor;
/**
/**
* Transition end handler. This function must be invoked after any transition
* that occurred as a result of a call to the delegate's onDecelerate callback.
*/
@ -49,14 +49,15 @@ abstract class Momentum {
* Returns true if deceleration has been initiated.
*/
bool start(Coordinate velocity, Coordinate minCoord, Coordinate maxCoord,
Coordinate initialOffset, [num decelerationFactor]);
Coordinate initialOffset,
[num decelerationFactor]);
/**
* Calculate the velocity required to transition between coordinates [start]
* and [target] optionally specifying a custom [decelerationFactor].
*/
Coordinate calculateVelocity(Coordinate start, Coordinate target,
[num decelerationFactor]);
[num decelerationFactor]);
/** Stop decelerating and return the current velocity. */
Coordinate stop();
@ -111,9 +112,8 @@ class _Move {
* class at all.
*/
class Solver {
static num solve(num fn(num), num targetY, num startX,
[int maxIterations = 50]) {
[int maxIterations = 50]) {
num lastX = 0;
num lastY = fn(lastX);
num deltaX;
@ -123,7 +123,7 @@ class Solver {
num x = startX;
num delta = startX;
for (int i = 0; i < maxIterations; i++) {
num y = fn(x);
num y = fn(x);
if (y.round() == targetY.round()) {
return x;
}
@ -141,11 +141,10 @@ class Solver {
// Avoid divide by zero and as a hack just repeat the previous delta.
// Obviously this is a little dangerous and we might not converge.
if (deltaY != 0) {
delta = errorY * deltaX / deltaY;
delta = errorY * deltaX / deltaY;
}
x += delta;
if (minX != null && maxX != null
&& (x > minX || x < maxX)) {
if (minX != null && maxX != null && (x > minX || x < maxX)) {
// Fall back to binary search.
x = (minX + maxX) / 2;
}
@ -194,7 +193,6 @@ class SingleDimensionPhysics {
*/
static const _DECELERATION_FACTOR = 0.97;
static const _MAX_VELOCITY_STATIC_FRICTION = 0.08 * _MS_PER_FRAME;
static const _DECELERATION_FACTOR_STATIC_FRICTION = 0.92;
@ -228,7 +226,6 @@ class SingleDimensionPhysics {
/** The bouncing state. */
int _bouncingState;
num velocity;
num _currentOffset;
@ -239,12 +236,10 @@ class SingleDimensionPhysics {
*/
static const _VELOCITY_GUESS = 20;
SingleDimensionPhysics() : _bouncingState = BouncingState.NOT_BOUNCING {
}
SingleDimensionPhysics() : _bouncingState = BouncingState.NOT_BOUNCING {}
void configure(num minCoord, num maxCoord,
num initialOffset, num customDecelerationFactor_,
num velocity_) {
void configure(num minCoord, num maxCoord, num initialOffset,
num customDecelerationFactor_, num velocity_) {
_bouncingState = BouncingState.NOT_BOUNCING;
_minCoord = minCoord;
_maxCoord = maxCoord;
@ -253,23 +248,22 @@ class SingleDimensionPhysics {
_adjustInitialVelocityAndBouncingState(velocity_);
}
num solve(num initialOffset, num targetOffset,
num customDecelerationFactor_) {
num solve(
num initialOffset, num targetOffset, num customDecelerationFactor_) {
initialOffset = initialOffset.round();
targetOffset = targetOffset.round();
if (initialOffset == targetOffset) {
return 0;
}
return Solver.solve((num velocity_) {
// Don't specify min and max coordinates as we don't need to bother
// with the simulating bouncing off the edges.
configure(null, null, initialOffset.round(),
customDecelerationFactor_, velocity_);
stepAll();
return _currentOffset;
},
targetOffset,
targetOffset > initialOffset ? _VELOCITY_GUESS : -_VELOCITY_GUESS);
// Don't specify min and max coordinates as we don't need to bother
// with the simulating bouncing off the edges.
configure(null, null, initialOffset.round(), customDecelerationFactor_,
velocity_);
stepAll();
return _currentOffset;
}, targetOffset,
targetOffset > initialOffset ? _VELOCITY_GUESS : -_VELOCITY_GUESS);
}
/**
@ -318,16 +312,17 @@ class SingleDimensionPhysics {
}
if (stretchDistance != null) {
if (stretchDistance * velocity < 0) {
_bouncingState = _bouncingState == BouncingState.BOUNCING_BACK ?
BouncingState.NOT_BOUNCING : BouncingState.BOUNCING_AWAY;
_bouncingState = _bouncingState == BouncingState.BOUNCING_BACK
? BouncingState.NOT_BOUNCING
: BouncingState.BOUNCING_AWAY;
velocity += stretchDistance * _PRE_BOUNCE_COEFFICIENT;
} else {
_bouncingState = BouncingState.BOUNCING_BACK;
velocity = stretchDistance > 0 ?
Math.max(stretchDistance * _POST_BOUNCE_COEFFICIENT,
_MIN_STEP_VELOCITY) :
Math.min(stretchDistance * _POST_BOUNCE_COEFFICIENT,
-_MIN_STEP_VELOCITY);
velocity = stretchDistance > 0
? Math.max(
stretchDistance * _POST_BOUNCE_COEFFICIENT, _MIN_STEP_VELOCITY)
: Math.min(stretchDistance * _POST_BOUNCE_COEFFICIENT,
-_MIN_STEP_VELOCITY);
}
} else {
_bouncingState = BouncingState.NOT_BOUNCING;
@ -344,7 +339,7 @@ class SingleDimensionPhysics {
}
void stepAll() {
while(!isDone()) {
while (!isDone()) {
step();
}
}
@ -368,7 +363,6 @@ class SingleDimensionPhysics {
* and timeouts.
*/
class TimeoutMomentum implements Momentum {
SingleDimensionPhysics physicsX;
SingleDimensionPhysics physicsY;
Coordinate _previousOffset;
@ -384,11 +378,11 @@ class TimeoutMomentum implements Momentum {
num _defaultDecelerationFactor;
TimeoutMomentum(this._delegate, [num defaultDecelerationFactor = 1])
: _defaultDecelerationFactor = defaultDecelerationFactor,
_decelerating = false,
_moves = new Queue<_Move>(),
physicsX = new SingleDimensionPhysics(),
physicsY = new SingleDimensionPhysics();
: _defaultDecelerationFactor = defaultDecelerationFactor,
_decelerating = false,
_moves = new Queue<_Move>(),
physicsX = new SingleDimensionPhysics(),
physicsY = new SingleDimensionPhysics();
/**
* Calculate and return the moves for the deceleration motion.
@ -400,9 +394,8 @@ class TimeoutMomentum implements Momentum {
_stepWithoutAnimation();
time += SingleDimensionPhysics._MS_PER_FRAME;
if (_isStepNecessary()) {
_moves.add(new _Move(_nextX, _nextY,
physicsX.velocity,
physicsY.velocity, time));
_moves.add(new _Move(
_nextX, _nextY, physicsX.velocity, physicsY.velocity, time));
_previousOffset.y = _nextY;
_previousOffset.x = _nextX;
}
@ -426,18 +419,18 @@ class TimeoutMomentum implements Momentum {
* The [TouchHandler] requires this function but we don't need to do
* anything here.
*/
void onTransitionEnd() {
}
void onTransitionEnd() {}
Coordinate calculateVelocity(Coordinate start_, Coordinate target,
[num decelerationFactor = null]) {
[num decelerationFactor = null]) {
return new Coordinate(
physicsX.solve(start_.x, target.x, decelerationFactor),
physicsY.solve(start_.y, target.y, decelerationFactor));
}
bool start(Coordinate velocity, Coordinate minCoord, Coordinate maxCoord,
Coordinate initialOffset, [num decelerationFactor = null]) {
Coordinate initialOffset,
[num decelerationFactor = null]) {
_customDecelerationFactor = _defaultDecelerationFactor;
if (decelerationFactor != null) {
_customDecelerationFactor = decelerationFactor;
@ -448,20 +441,19 @@ class TimeoutMomentum implements Momentum {
_stepTimeout = null;
}
assert (_stepTimeout == null);
assert(_stepTimeout == null);
assert(minCoord.x <= maxCoord.x);
assert(minCoord.y <= maxCoord.y);
_previousOffset = initialOffset.clone();
physicsX.configure(minCoord.x, maxCoord.x, initialOffset.x,
_customDecelerationFactor, velocity.x);
_customDecelerationFactor, velocity.x);
physicsY.configure(minCoord.y, maxCoord.y, initialOffset.y,
_customDecelerationFactor, velocity.y);
_customDecelerationFactor, velocity.y);
if (!physicsX.isDone() || !physicsY.isDone()) {
_calculateMoves();
if (!_moves.isEmpty) {
num firstTime = _moves.first.time;
_stepTimeout = Env.requestAnimationFrame(
_step, null, firstTime);
_stepTimeout = Env.requestAnimationFrame(_step, null, firstTime);
_decelerating = true;
return true;
}
@ -492,8 +484,9 @@ class TimeoutMomentum implements Momentum {
// Prune moves that are more than 1 frame behind when we have more
// available moves.
num lastEpoch = timestamp - SingleDimensionPhysics._MS_PER_FRAME;
while (!_moves.isEmpty && !identical(_moves.first, _moves.last)
&& _moves.first.time < lastEpoch) {
while (!_moves.isEmpty &&
!identical(_moves.first, _moves.last) &&
_moves.first.time < lastEpoch) {
_moves.removeFirst();
}
@ -529,8 +522,8 @@ class TimeoutMomentum implements Momentum {
// passed a velocity in to this Momentum implementation.
num velocityScale = SingleDimensionPhysics._MS_PER_FRAME *
SingleDimensionPhysics._INITIAL_VELOCITY_BOOST_FACTOR;
velocity = new Coordinate(
move.vx / velocityScale, move.vy / velocityScale);
velocity =
new Coordinate(move.vx / velocityScale, move.vy / velocityScale);
} else {
velocity = new Coordinate(0, 0);
}

View file

@ -27,8 +27,8 @@ class ScrollWatcher {
Element _scrollerEl;
ScrollWatcher(Scroller scroller)
: _scroller = scroller, _listeners = new List<ScrollListener>() {
}
: _scroller = scroller,
_listeners = new List<ScrollListener>() {}
void addListener(ScrollListener listener) {
_listeners.add(listener);
@ -38,8 +38,7 @@ class ScrollWatcher {
* Send the scroll event to all listeners.
* [decelerating] is true if the offset is changing because of deceleration.
*/
void _dispatchScroll(num scrollX, num scrollY,
[bool decelerating = false]) {
void _dispatchScroll(num scrollX, num scrollY, [bool decelerating = false]) {
for (final listener in _listeners) {
listener.onScrollerMoved(scrollX, scrollY, decelerating);
}
@ -51,7 +50,9 @@ class ScrollWatcher {
*/
void initialize() {
_scrollerEl = _scroller.getElement();
_scroller.onContentMoved.listen((e) { _onContentMoved(e); });
_scroller.onContentMoved.listen((e) {
_onContentMoved(e);
});
}
/**

View file

@ -57,22 +57,24 @@ class Scrollbar implements ScrollListener {
bool _displayOnHover;
bool _hovering = false;
Scrollbar(Scroller scroller, [displayOnHover = true]) :
_displayOnHover = displayOnHover,
_scroller = scroller,
_frame = scroller.getFrame(),
_cachedSize = new Map<String, num>() {
_boundHideFn = () { _showScrollbars(false); };
Scrollbar(Scroller scroller, [displayOnHover = true])
: _displayOnHover = displayOnHover,
_scroller = scroller,
_frame = scroller.getFrame(),
_cachedSize = new Map<String, num>() {
_boundHideFn = () {
_showScrollbars(false);
};
}
bool get _scrollBarDragInProgress => _scrollBarDragInProgressValue;
void set _scrollBarDragInProgress(bool value) {
_scrollBarDragInProgressValue = value;
_toggleClass(_verticalElement, DRAG_CLASS_NAME,
value && _currentScrollVertical);
_toggleClass(_horizontalElement, DRAG_CLASS_NAME,
value && !_currentScrollVertical);
_toggleClass(
_verticalElement, DRAG_CLASS_NAME, value && _currentScrollVertical);
_toggleClass(
_horizontalElement, DRAG_CLASS_NAME, value && !_currentScrollVertical);
}
// TODO(jacobr): move this helper method into the DOM.
@ -121,44 +123,42 @@ class Scrollbar implements ScrollListener {
// instead attach a single global event listener and let data in the
// DOM drive.
_frame.onClick.listen((Event e) {
// Always focus on click as one of our children isn't all focused.
if (!_frame.contains(document.activeElement)) {
scrollerEl.focus();
}
});
// Always focus on click as one of our children isn't all focused.
if (!_frame.contains(document.activeElement)) {
scrollerEl.focus();
}
});
_frame.onMouseOver.listen((Event e) {
final activeElement = document.activeElement;
// TODO(jacobr): don't steal focus from a child element or a truly
// focusable element. Only support stealing focus ffrom another
// element that was given fake focus.
if (activeElement is BodyElement ||
(!_frame.contains(activeElement) &&
activeElement is DivElement)) {
scrollerEl.focus();
}
if (_hovering == false) {
_hovering = true;
_cancelTimeout();
_showScrollbars(true);
refresh();
}
});
final activeElement = document.activeElement;
// TODO(jacobr): don't steal focus from a child element or a truly
// focusable element. Only support stealing focus ffrom another
// element that was given fake focus.
if (activeElement is BodyElement ||
(!_frame.contains(activeElement) && activeElement is DivElement)) {
scrollerEl.focus();
}
if (_hovering == false) {
_hovering = true;
_cancelTimeout();
_showScrollbars(true);
refresh();
}
});
_frame.onMouseOut.listen((e) {
_hovering = false;
// Start hiding immediately if we aren't
// scrolling or already in the process of
// hidng the scrollbar
if (!_scrollInProgress && _timer == null) {
_boundHideFn();
}
});
_hovering = false;
// Start hiding immediately if we aren't
// scrolling or already in the process of
// hidng the scrollbar
if (!_scrollInProgress && _timer == null) {
_boundHideFn();
}
});
}
}
void _onStart(/*MouseEvent | Touch*/ e) {
Element elementOver = e.target;
if (elementOver == _verticalElement ||
elementOver == _horizontalElement) {
if (elementOver == _verticalElement || elementOver == _horizontalElement) {
_currentScrollVertical = elementOver == _verticalElement;
if (_currentScrollVertical) {
_currentScrollStartMouse = e.page.y;
@ -180,15 +180,14 @@ class Scrollbar implements ScrollListener {
_refreshScrollRatioHelper(
_scroller._scrollSize.height, contentSize.height);
} else {
_refreshScrollRatioHelper(_scroller._scrollSize.width,
contentSize.width);
_refreshScrollRatioHelper(_scroller._scrollSize.width, contentSize.width);
}
}
void _refreshScrollRatioHelper(num frameSize, num contentSize) {
num frameTravelDistance = frameSize - _defaultScrollSize(
frameSize, contentSize) -_PADDING_LENGTH * 2;
num frameTravelDistance = frameSize -
_defaultScrollSize(frameSize, contentSize) -
_PADDING_LENGTH * 2;
if (frameTravelDistance < 0.001) {
_currentScrollRatio = 0;
} else {
@ -222,20 +221,19 @@ class Scrollbar implements ScrollListener {
void _onEnd(UIEvent e) {
_scrollBarDragInProgress = false;
// TODO(jacobr): make scrollbar less tightly coupled to the scroller.
_scroller._onScrollerDragEnd.add(
new Event(ScrollerEventType.DRAG_END));
_scroller._onScrollerDragEnd.add(new Event(ScrollerEventType.DRAG_END));
}
/**
* When scrolling ends, schedule a timeout to hide the scrollbars.
*/
void _onScrollerEnd(Event e) {
_cancelTimeout();
_timer = new Timer(const Duration(milliseconds: _DISPLAY_TIME),
_boundHideFn);
_timer =
new Timer(const Duration(milliseconds: _DISPLAY_TIME), _boundHideFn);
_scrollInProgress = false;
}
void onScrollerMoved(num scrollX, num scrollY, bool decelerating) {
if (_scrollInProgress == false) {
// Display the scrollbar and then immediately prepare to hide it...
@ -251,8 +249,8 @@ class Scrollbar implements ScrollListener {
return;
}
_scroller._resize(() {
updateScrollbars(_scroller.getHorizontalOffset(),
_scroller.getVerticalOffset());
updateScrollbars(
_scroller.getHorizontalOffset(), _scroller.getVerticalOffset());
});
}
@ -261,14 +259,12 @@ class Scrollbar implements ScrollListener {
if (_scroller._shouldScrollHorizontally()) {
num scrollPercentX = _scroller.getHorizontalScrollPercent(scrollX);
_updateScrollbar(_horizontalElement, scrollX, scrollPercentX,
_scroller._scrollSize.width,
contentSize.width, 'right', 'width');
_scroller._scrollSize.width, contentSize.width, 'right', 'width');
}
if (_scroller._shouldScrollVertically()) {
num scrollPercentY = _scroller.getVerticalScrollPercent(scrollY);
_updateScrollbar(_verticalElement, scrollY, scrollPercentY,
_scroller._scrollSize.height,
contentSize.height, 'bottom', 'height');
_scroller._scrollSize.height, contentSize.height, 'bottom', 'height');
}
}
@ -309,8 +305,9 @@ class Scrollbar implements ScrollListener {
num _defaultScrollSize(num frameSize, num contentSize) {
return GoogleMath.clamp(
(frameSize -_PADDING_LENGTH * 2) * frameSize / contentSize,
_MIN_SIZE, frameSize -_PADDING_LENGTH * 2);
(frameSize - _PADDING_LENGTH * 2) * frameSize / contentSize,
_MIN_SIZE,
frameSize - _PADDING_LENGTH * 2);
}
/**
@ -319,9 +316,8 @@ class Scrollbar implements ScrollListener {
* specified by [cssPos]. The CSS property to adjust for size (height|width)
* is specified by [cssSize].
*/
void _updateScrollbar(Element element, num offset,
num scrollPercent, num frameSize,
num contentSize, String cssPos, String cssSize) {
void _updateScrollbar(Element element, num offset, num scrollPercent,
num frameSize, num contentSize, String cssPos, String cssSize) {
if (!_cachedSize.containsKey(cssSize)) {
if (offset == null || contentSize < frameSize) {
return;
@ -337,9 +333,9 @@ class Scrollbar implements ScrollListener {
num scrollPx = stretchPercent * (contentSize - frameSize);
num maxSize = _defaultScrollSize(frameSize, contentSize);
num size = Math.max(_MIN_COMPRESSED_SIZE, maxSize - scrollPx);
num maxOffset = frameSize - size -_PADDING_LENGTH * 2;
num pos = GoogleMath.clamp(scrollPercent * maxOffset,
0, maxOffset) + _PADDING_LENGTH;
num maxOffset = frameSize - size - _PADDING_LENGTH * 2;
num pos = GoogleMath.clamp(scrollPercent * maxOffset, 0, maxOffset) +
_PADDING_LENGTH;
pos = pos.round();
size = size.round();
final style = element.style;

View file

@ -44,13 +44,13 @@ void joinFutures(List<Future> futures, Callback callback) {
callback();
}
}
for (Future p in futures) {
p.then(helper);
}
}
class Scroller implements Draggable, MomentumDelegate {
/** Pixels to move each time an arrow key is pressed. */
static const ARROW_KEY_DELTA = 30;
static const SCROLL_WHEEL_VELOCITY = 0.01;
@ -141,18 +141,21 @@ class Scroller implements Draggable, MomentumDelegate {
bool _activeGesture = false;
ScrollWatcher _scrollWatcher;
Scroller(Element scrollableElem, [this.verticalEnabled = false,
this.horizontalEnabled = false,
momentumEnabled = true,
lookupContentSizeDelegate = null,
num defaultDecelerationFactor = 1,
int scrollTechnique = null, bool capture = false])
Scroller(Element scrollableElem,
[this.verticalEnabled = false,
this.horizontalEnabled = false,
momentumEnabled = true,
lookupContentSizeDelegate = null,
num defaultDecelerationFactor = 1,
int scrollTechnique = null,
bool capture = false])
: _momentumEnabled = momentumEnabled,
_lookupContentSizeDelegate = lookupContentSizeDelegate,
_element = scrollableElem,
_frame = scrollableElem.parent,
_scrollTechnique = scrollTechnique != null
? scrollTechnique : ScrollerScrollTechnique.TRANSFORM_3D,
? scrollTechnique
: ScrollerScrollTechnique.TRANSFORM_3D,
_minPoint = new Coordinate(0, 0),
_maxPoint = new Coordinate(0, 0),
_maxOffset = new Coordinate(0, 0),
@ -178,33 +181,28 @@ class Scroller implements Draggable, MomentumDelegate {
});
_frame.onKeyDown.listen((KeyboardEvent e) {
bool handled = false;
// We ignore key events where further scrolling in that direction
// would have no impact which matches default browser behavior with
// nested scrollable areas.
bool handled = false;
// We ignore key events where further scrolling in that direction
// would have no impact which matches default browser behavior with
// nested scrollable areas.
switch(e.keyCode) {
case 33: // page-up
throwDelta(
0,
_scrollSize.height * PAGE_KEY_SCROLL_FRACTION);
handled = true;
break;
case 34: // page-down
throwDelta(
0, -_scrollSize.height * PAGE_KEY_SCROLL_FRACTION);
handled = true;
break;
case 35: // End
throwTo(_maxPoint.x, _minPoint.y,
FAST_SNAP_DECELERATION_FACTOR);
handled = true;
break;
case 36: // Home
throwTo(_maxPoint.x,_maxPoint.y,
FAST_SNAP_DECELERATION_FACTOR);
handled = true;
break;
switch (e.keyCode) {
case 33: // page-up
throwDelta(0, _scrollSize.height * PAGE_KEY_SCROLL_FRACTION);
handled = true;
break;
case 34: // page-down
throwDelta(0, -_scrollSize.height * PAGE_KEY_SCROLL_FRACTION);
handled = true;
break;
case 35: // End
throwTo(_maxPoint.x, _minPoint.y, FAST_SNAP_DECELERATION_FACTOR);
handled = true;
break;
case 36: // Home
throwTo(_maxPoint.x, _maxPoint.y, FAST_SNAP_DECELERATION_FACTOR);
handled = true;
break;
/* TODO(jacobr): enable arrow keys when the don't conflict with other
application keyboard shortcuts.
case 38: // up
@ -230,11 +228,11 @@ class Scroller implements Draggable, MomentumDelegate {
FAST_SNAP_DECELERATION_FACTOR);
break;
*/
}
if (handled) {
e.preventDefault();
}
});
}
if (handled) {
e.preventDefault();
}
});
// The scrollable element must be relatively positioned.
// TODO(jacobr): this assert fires asynchronously which could be confusing.
if (_scrollTechnique == ScrollerScrollTechnique.RELATIVE_POSITIONING) {
@ -284,7 +282,6 @@ class Scroller implements Draggable, MomentumDelegate {
return _onDecelStartStream;
}
/**
* Add a scroll listener. This allows other classes to subscribe to scroll
* notifications from this scroller.
@ -301,8 +298,7 @@ class Scroller implements Draggable, MomentumDelegate {
* Adjust the new calculated scroll position based on the minimum allowed
* position and returns the adjusted scroll value.
*/
num _adjustValue(num newPosition, num minPosition,
num maxPosition) {
num _adjustValue(num newPosition, num minPosition, num maxPosition) {
assert(minPosition <= maxPosition);
if (newPosition < minPosition) {
@ -347,9 +343,7 @@ class Scroller implements Draggable, MomentumDelegate {
_startDeceleration(
_momentum.calculateVelocity(
_contentOffset,
snappedTarget,
decelerationFactor),
_contentOffset, snappedTarget, decelerationFactor),
decelerationFactor);
if (_onDecelStart != null) {
_onDecelStart.add(new Event(ScrollerEventType.DECEL_START));
@ -383,17 +377,18 @@ class Scroller implements Draggable, MomentumDelegate {
_snapContentOffsetToBounds();
_setContentOffset(_contentOffset.x, _contentOffset.y);
}
/**
* Adjusted content size is a size with the combined largest height and width
* of both the content and the frame.
*/
Size _getAdjustedContentSize() {
return new Size(Math.max(_scrollSize.width, _contentSize.width),
Math.max(_scrollSize.height, _contentSize.height));
Math.max(_scrollSize.height, _contentSize.height));
}
// TODO(jmesserly): these should be properties instead of get* methods
num getDefaultVerticalOffset() => _maxPoint.y;
num getDefaultVerticalOffset() => _maxPoint.y;
Element getElement() => _element;
Element getFrame() => _frame;
num getHorizontalOffset() => _contentOffset.x;
@ -408,7 +403,7 @@ class Scroller implements Draggable, MomentumDelegate {
return (x - _minPoint.x) / (_maxPoint.x - _minPoint.x);
}
num getMaxPointY()=> _maxPoint.y;
num getMaxPointY() => _maxPoint.y;
num getMinPointY() => _minPoint.y;
Momentum get momentum => _momentum;
@ -487,10 +482,12 @@ class Scroller implements Draggable, MomentumDelegate {
Coordinate contentStart = _contentStartOffset;
num newX = contentStart.x + _touchHandler.getDragDeltaX();
num newY = contentStart.y + _touchHandler.getDragDeltaY();
newY = _shouldScrollVertically() ?
_adjustValue(newY, _minPoint.y, _maxPoint.y) : 0;
newX = _shouldScrollHorizontally() ?
_adjustValue(newX, _minPoint.x, _maxPoint.x) : 0;
newY = _shouldScrollVertically()
? _adjustValue(newY, _minPoint.y, _maxPoint.y)
: 0;
newX = _shouldScrollHorizontally()
? _adjustValue(newX, _minPoint.x, _maxPoint.x)
: 0;
if (!_activeGesture) {
_activeGesture = true;
_dragInProgress = true;
@ -515,8 +512,7 @@ class Scroller implements Draggable, MomentumDelegate {
return !!(shouldVertical || shouldHorizontal && !verticalish);
}
void onTouchEnd() {
}
void onTouchEnd() {}
/**
* Prepare the scrollable area for possible movement.
@ -570,15 +566,14 @@ class Scroller implements Draggable, MomentumDelegate {
_contentSize = new Size(_element.scrollWidth, _element.scrollHeight);
}
_scrollSize = new Size(_frame.offset.width,
_frame.offset.height);
_scrollSize = new Size(_frame.offset.width, _frame.offset.height);
Size adjusted = _getAdjustedContentSize();
_maxPoint = new Coordinate(-_maxOffset.x, -_maxOffset.y);
_minPoint = new Coordinate(
Math.min(
_scrollSize.width - adjusted.width + _minOffset.x, _maxPoint.x),
Math.min(
_scrollSize.height - adjusted.height + _minOffset.y, _maxPoint.y));
Math.min(_scrollSize.height - adjusted.height + _minOffset.y,
_maxPoint.y));
callback();
});
}
@ -616,7 +611,7 @@ class Scroller implements Draggable, MomentumDelegate {
_setContentOffset(_contentOffset.x, y);
}
/**
/**
* Whether the scrollable area should scroll horizontally. Only
* returns true if the client has enabled horizontal scrolling, and the
* content is wider than the frame.
@ -642,10 +637,8 @@ class Scroller implements Draggable, MomentumDelegate {
* the frame, snap it back in to place.
*/
void _snapContentOffsetToBounds() {
num clampX =
GoogleMath.clamp(_minPoint.x, _contentOffset.x, _maxPoint.x);
num clampY =
GoogleMath.clamp(_minPoint.y, _contentOffset.y, _maxPoint.y);
num clampX = GoogleMath.clamp(_minPoint.x, _contentOffset.x, _maxPoint.x);
num clampY = GoogleMath.clamp(_minPoint.y, _contentOffset.y, _maxPoint.y);
if (_contentOffset.x != clampX || _contentOffset.y != clampY) {
_setContentOffset(clampX, clampY);
}
@ -656,7 +649,7 @@ class Scroller implements Draggable, MomentumDelegate {
* Returns true if deceleration has been initiated.
*/
bool _startDeceleration(Coordinate velocity,
[num decelerationFactor = null]) {
[num decelerationFactor = null]) {
if (!_shouldScrollHorizontally()) {
velocity.x = 0;
}
@ -665,8 +658,8 @@ class Scroller implements Draggable, MomentumDelegate {
}
assert(_minPoint != null); // Min point is not set
assert(_maxPoint != null); // Max point is not set
return _momentum.start(velocity, _minPoint, _maxPoint, _contentOffset,
decelerationFactor);
return _momentum.start(
velocity, _minPoint, _maxPoint, _contentOffset, decelerationFactor);
}
Coordinate stop() {
@ -682,9 +675,13 @@ class Scroller implements Draggable, MomentumDelegate {
}
static Function _getOffsetFunction(int scrollTechnique) {
return scrollTechnique == ScrollerScrollTechnique.TRANSFORM_3D ?
(el, x, y) { FxUtil.setTranslate(el, x, y, 0); } :
(el, x, y) { FxUtil.setLeftAndTop(el, x, y); };
return scrollTechnique == ScrollerScrollTechnique.TRANSFORM_3D
? (el, x, y) {
FxUtil.setTranslate(el, x, y, 0);
}
: (el, x, y) {
FxUtil.setLeftAndTop(el, x, y);
};
}
}

View file

@ -153,8 +153,9 @@ class TouchHandler {
num _correctVelocity(num velocity) {
num absVelocity = velocity.abs();
if (absVelocity > _MAXIMUM_VELOCITY) {
absVelocity = _recentTouchesY.length < 6 ?
_VELOCITY_FOR_INCORRECT_EVENTS : _MAXIMUM_VELOCITY;
absVelocity = _recentTouchesY.length < 6
? _VELOCITY_FOR_INCORRECT_EVENTS
: _MAXIMUM_VELOCITY;
}
return absVelocity * (velocity < 0 ? -1 : 1);
}
@ -165,11 +166,14 @@ class TouchHandler {
* phase.
*/
void enable([bool capture = false]) {
Function onEnd = (e) { _onEnd(e.timeStamp, e); };
_addEventListeners(
_element,
(e) { _onStart(e); },
(e) { _onMove(e); }, onEnd, onEnd, capture);
Function onEnd = (e) {
_onEnd(e.timeStamp, e);
};
_addEventListeners(_element, (e) {
_onStart(e);
}, (e) {
_onMove(e);
}, onEnd, onEnd, capture);
}
/**
@ -218,7 +222,7 @@ class TouchHandler {
* Return the touch of the last event.
*/
Touch _getLastTouch() {
assert (_lastEvent != null); // Last event not set
assert(_lastEvent != null); // Last event not set
return _lastEvent.touches[0];
}
@ -274,8 +278,8 @@ class TouchHandler {
_lastTouchY = clientY;
if (!_dragging &&
((_totalMoveY > _MIN_TRACKING_FOR_DRAG && _draggable.verticalEnabled) ||
(_totalMoveX > _MIN_TRACKING_FOR_DRAG &&
_draggable.horizontalEnabled))) {
(_totalMoveX > _MIN_TRACKING_FOR_DRAG &&
_draggable.horizontalEnabled))) {
_dragging = _draggable.onDragStart(e);
if (!_dragging) {
_endTracking();
@ -337,14 +341,13 @@ class TouchHandler {
* or y component of the recent touch and the second item is the touch time
* stamp. The time of the most recent event is specified by [recentTime].
*/
List<int> _removeOldTouches(List<int> recentTouches,
int recentTime) {
List<int> _removeOldTouches(List<int> recentTouches, int recentTime) {
int count = 0;
final len = recentTouches.length;
assert (len % 2 == 0);
assert(len % 2 == 0);
while (count < len &&
recentTime - recentTouches[count + 1] > _MAX_TRACKING_TIME ||
(len - count) > _MAX_TRACKING_TOUCHES * 2) {
recentTime - recentTouches[count + 1] > _MAX_TRACKING_TIME ||
(len - count) > _MAX_TRACKING_TOUCHES * 2) {
count += 2;
}
return count == 0 ? recentTouches : _removeFirstN(recentTouches, count);
@ -362,9 +365,11 @@ class TouchHandler {
* stamp. The x or y component of the most recent move is specified by
* [recentMove].
*/
List<int> _removeTouchesInWrongDirection(List<int> recentTouches,
int lastMove, int recentMove) {
if (lastMove !=0 && recentMove != 0 && recentTouches.length > 2 &&
List<int> _removeTouchesInWrongDirection(
List<int> recentTouches, int lastMove, int recentMove) {
if (lastMove != 0 &&
recentMove != 0 &&
recentTouches.length > 2 &&
_xor(lastMove > 0, recentMove > 0)) {
return _removeFirstN(recentTouches, recentTouches.length - 2);
}

View file

@ -30,10 +30,9 @@ EventListener mouseToTouchCallback(EventListener callback) {
}
/** Helper method to attach event listeners to a [node]. */
void _addEventListeners(Element node,
EventListener onStart, EventListener onMove, EventListener onEnd,
EventListener onCancel, [bool capture = false]) {
void _addEventListeners(Element node, EventListener onStart,
EventListener onMove, EventListener onEnd, EventListener onCancel,
[bool capture = false]) {
Function removeListeners;
onEndWrapper(e) {
@ -65,14 +64,18 @@ void _addEventListeners(Element node,
};
Element.touchStartEvent.forTarget(node, useCapture: capture).listen((e) {
touchMoveSub = Element.touchMoveEvent.forTarget(
document, useCapture: capture).listen(onMove);
touchEndSub = Element.touchEndEvent.forTarget(
document, useCapture: capture).listen(onEndWrapper);
touchLeaveSub = Element.touchLeaveEvent.forTarget(
document, useCapture: capture).listen(onLeaveWrapper);
touchCancelSub = Element.touchCancelEvent.forTarget(
document, useCapture: capture).listen(onCancelWrapper);
touchMoveSub = Element.touchMoveEvent
.forTarget(document, useCapture: capture)
.listen(onMove);
touchEndSub = Element.touchEndEvent
.forTarget(document, useCapture: capture)
.listen(onEndWrapper);
touchLeaveSub = Element.touchLeaveEvent
.forTarget(document, useCapture: capture)
.listen(onLeaveWrapper);
touchCancelSub = Element.touchCancelEvent
.forTarget(document, useCapture: capture)
.listen(onCancelWrapper);
return onStart(e);
});
} else {
@ -92,12 +95,15 @@ void _addEventListeners(Element node,
};
Element.mouseDownEvent.forTarget(node, useCapture: capture).listen((e) {
mouseMoveSub = Element.mouseMoveEvent.forTarget(
document, useCapture: capture).listen(onMove);
mouseUpSub = Element.mouseUpEvent.forTarget(
document, useCapture: capture).listen(onEndWrapper);
touchCancelSub = Element.touchCancelEvent.forTarget(
document, useCapture: capture).listen(onCancelWrapper);
mouseMoveSub = Element.mouseMoveEvent
.forTarget(document, useCapture: capture)
.listen(onMove);
mouseUpSub = Element.mouseUpEvent
.forTarget(document, useCapture: capture)
.listen(onEndWrapper);
touchCancelSub = Element.touchCancelEvent
.forTarget(document, useCapture: capture)
.listen(onCancelWrapper);
return onStart(e);
});
}
@ -182,20 +188,51 @@ class MockTouch implements Touch {
int get screenX => wrapped.screen.x;
int get screenY {return wrapped.screen.y; }
int get screenY {
return wrapped.screen.y;
}
EventTarget get target => wrapped.target;
double get force { throw new UnimplementedError(); }
Point get page { throw new UnimplementedError(); }
int get radiusX { throw new UnimplementedError(); }
int get radiusY { throw new UnimplementedError(); }
num get rotationAngle { throw new UnimplementedError(); }
Point get screen { throw new UnimplementedError(); }
num get webkitForce { throw new UnimplementedError(); }
int get webkitRadiusX { throw new UnimplementedError(); }
int get webkitRadiusY { throw new UnimplementedError(); }
num get webkitRotationAngle { throw new UnimplementedError(); }
double get force {
throw new UnimplementedError();
}
Point get page {
throw new UnimplementedError();
}
int get radiusX {
throw new UnimplementedError();
}
int get radiusY {
throw new UnimplementedError();
}
num get rotationAngle {
throw new UnimplementedError();
}
Point get screen {
throw new UnimplementedError();
}
num get webkitForce {
throw new UnimplementedError();
}
int get webkitRadiusX {
throw new UnimplementedError();
}
int get webkitRadiusY {
throw new UnimplementedError();
}
num get webkitRotationAngle {
throw new UnimplementedError();
}
}
class MockTouchEvent implements TouchEvent {
@ -205,14 +242,15 @@ class MockTouchEvent implements TouchEvent {
final List<Touch> targetTouches;
final List<Touch> changedTouches;
MockTouchEvent(MouseEvent this.wrapped, List<Touch> this.touches,
List<Touch> this.targetTouches,
List<Touch> this.changedTouches) {}
List<Touch> this.targetTouches, List<Touch> this.changedTouches) {}
bool get bubbles => wrapped.bubbles;
bool get cancelBubble => wrapped.cancelBubble;
void set cancelBubble(bool value) { wrapped.cancelBubble = value; }
void set cancelBubble(bool value) {
wrapped.cancelBubble = value;
}
bool get cancelable => wrapped.cancelable;
@ -222,7 +260,9 @@ class MockTouchEvent implements TouchEvent {
int get eventPhase => wrapped.eventPhase;
void set returnValue(bool value) { wrapped.returnValue = value; }
void set returnValue(bool value) {
wrapped.returnValue = value;
}
bool get returnValue => wrapped.returnValue;
@ -232,11 +272,17 @@ class MockTouchEvent implements TouchEvent {
String get type => wrapped.type;
void preventDefault() { wrapped.preventDefault(); }
void preventDefault() {
wrapped.preventDefault();
}
void stopImmediatePropagation() { wrapped.stopImmediatePropagation(); }
void stopImmediatePropagation() {
wrapped.stopImmediatePropagation();
}
void stopPropagation() { wrapped.stopPropagation(); }
void stopPropagation() {
wrapped.stopPropagation();
}
int get charCode => wrapped.charCode;
@ -265,11 +311,31 @@ class MockTouchEvent implements TouchEvent {
bool get shiftKey => wrapped.shiftKey;
DataTransfer get clipboardData { throw new UnimplementedError(); }
Point get layer { throw new UnimplementedError(); }
Element get matchingTarget { throw new UnimplementedError(); }
Point get page { throw new UnimplementedError(); }
List get path { throw new UnimplementedError(); }
Point get screen { throw new UnimplementedError(); }
/*InputDevice*/ get sourceDevice { throw new UnimplementedError(); }
DataTransfer get clipboardData {
throw new UnimplementedError();
}
Point get layer {
throw new UnimplementedError();
}
Element get matchingTarget {
throw new UnimplementedError();
}
Point get page {
throw new UnimplementedError();
}
List get path {
throw new UnimplementedError();
}
Point get screen {
throw new UnimplementedError();
}
/*InputDevice*/ get sourceDevice {
throw new UnimplementedError();
}
}

View file

@ -11,10 +11,9 @@ typedef num NumericValueSelector<T>(T value);
* TODO(jmesserly): make these top level functions?
*/
class CollectionUtils {
static void insertAt(List arr, int pos, value) {
assert (pos >= 0);
assert (pos <= arr.length);
assert(pos >= 0);
assert(pos <= arr.length);
if (pos == arr.length) {
arr.add(value);

View file

@ -9,8 +9,15 @@ part of utilslib;
*/
class DateUtils {
// TODO(jmesserly): localized strings
static const WEEKDAYS = const ['Monday', 'Tuesday', 'Wednesday', 'Thursday',
'Friday', 'Saturday', 'Sunday'];
static const WEEKDAYS = const [
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday',
'Sunday'
];
static const YESTERDAY = 'Yesterday';
@ -34,9 +41,20 @@ class DateUtils {
int day = int.parse(parts[1]);
final months = const['Jan', 'Feb', 'Mar', 'Apr',
'May', 'Jun', 'Jul', 'Aug',
'Sep', 'Oct', 'Nov', 'Dec'];
final months = const [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec'
];
int month = months.indexOf(parts[2], 0) + 1;
if (month < 0) {
throw 'bad month, expected 3 letter month code, got: ${parts[2]}';
@ -58,7 +76,8 @@ class DateUtils {
int zoneOffset = int.parse(parts[5]) ~/ 100;
// Pretend it's a UTC time
DateTime result = new DateTime.utc(year, month, day, hours, minutes, seconds, 0);
DateTime result =
new DateTime.utc(year, month, day, hours, minutes, seconds, 0);
// Shift it to the proper zone, but it's still a UTC time
result = result.subtract(new Duration(hours: zoneOffset));
// Then render it as a local time
@ -117,7 +136,8 @@ class DateUtils {
*/
static String toRecentTimeString(DateTime then) {
bool datesAreEqual(DateTime d1, DateTime d2) {
return (d1.year == d2.year) && (d1.month == d2.month) &&
return (d1.year == d2.year) &&
(d1.month == d2.month) &&
(d1.day == d2.day);
}
@ -143,6 +163,7 @@ class DateUtils {
if (n >= 10) return "${n}";
return "0${n}";
}
String twoDigitMonth = twoDigits(then.month);
String twoDigitDay = twoDigits(then.day);
return "${then.year}-${twoDigitMonth}-${twoDigitDay}";
@ -180,6 +201,7 @@ class DateUtils {
if (n >= 10) return "${n}";
return "0${n}";
}
String mm =
twoDigits(duration.inMinutes.remainder(Duration.MINUTES_PER_HOUR));
return "${hours}:${mm} ${a}";

View file

@ -11,7 +11,7 @@ class StringUtils {
/**
* Returns either [str], or if [str] is null, the value of [defaultStr].
*/
static String defaultString(String str, [String defaultStr='']) {
static String defaultString(String str, [String defaultStr = '']) {
return str == null ? defaultStr : str;
}

View file

@ -51,12 +51,13 @@ class SwarmUri {
// TODO(terry): Added b/5096547 to track replace should by default behave
// like replaceAll to avoid a problematic usage pattern.
return component.replaceAll(':', '%3A')
.replaceAll('/', '%2F')
.replaceAll('?', '%3F')
.replaceAll('=', '%3D')
.replaceAll('&', '%26')
.replaceAll(' ', '%20');
return component
.replaceAll(':', '%3A')
.replaceAll('/', '%2F')
.replaceAll('?', '%3F')
.replaceAll('=', '%3D')
.replaceAll('&', '%26')
.replaceAll(' ', '%20');
}
/**
@ -67,11 +68,12 @@ class SwarmUri {
static String decodeComponent(String component) {
if (component == null) return component;
return component.replaceAll('%3A', ':')
.replaceAll('%2F', '/')
.replaceAll('%3F', '?')
.replaceAll('%3D', '=')
.replaceAll('%26', '&')
.replaceAll('%20', ' ');
return component
.replaceAll('%3A', ':')
.replaceAll('%2F', '/')
.replaceAll('%3F', '?')
.replaceAll('%3D', '=')
.replaceAll('%26', '&')
.replaceAll('%20', ' ');
}
}

View file

@ -8,7 +8,6 @@ part of view;
* A View that is composed of child views.
*/
class CompositeView extends View {
List<View> childViews;
// TODO(rnystrom): Allowing this to be public is gross. CompositeView should
@ -25,32 +24,34 @@ class CompositeView extends View {
final bool _nestedContainer;
final bool _showScrollbar;
CompositeView(String this._cssName, [nestedContainer = false,
scrollable = false, vertical = false,
showScrollbar = false])
: super(),
_nestedContainer = nestedContainer,
_scrollable = scrollable,
_vertical = vertical,
_showScrollbar = showScrollbar,
childViews = new List<View>() {
}
CompositeView(String this._cssName,
[nestedContainer = false,
scrollable = false,
vertical = false,
showScrollbar = false])
: super(),
_nestedContainer = nestedContainer,
_scrollable = scrollable,
_vertical = vertical,
_showScrollbar = showScrollbar,
childViews = new List<View>() {}
Element render() {
Element node = new Element.html('<div class="$_cssName"></div>');
if (_nestedContainer) {
container = new Element.html('<div class="scroll-container"></div>');
node.nodes.add(container);
} else {
container = node;
}
container = new Element.html('<div class="scroll-container"></div>');
node.nodes.add(container);
} else {
container = node;
}
if (_scrollable) {
scroller = new Scroller(container,
_vertical /* verticalScrollEnabled */,
!_vertical /* horizontalScrollEnabled */,
true /* momementumEnabled */);
scroller = new Scroller(
container,
_vertical /* verticalScrollEnabled */,
!_vertical /* horizontalScrollEnabled */,
true /* momementumEnabled */);
if (_showScrollbar) {
_scrollbar = new Scrollbar(scroller);
}
@ -80,7 +81,9 @@ class CompositeView extends View {
}
void removeChild(View view) {
childViews = childViews.where((e) { return view != e; }).toList();
childViews = childViews.where((e) {
return view != e;
}).toList();
// TODO(rnystrom): Container shouldn't be null. Remove this check.
if (container != null) {
view.node.remove();

View file

@ -26,9 +26,8 @@ class ConveyorView extends CompositeView {
Timer animationTimer;
ConveyorView()
: super('conveyor-view', true),
animationTimer = null {
}
: super('conveyor-view', true),
animationTimer = null {}
Element render() {
final result = super.render();
@ -63,8 +62,9 @@ class ConveyorView extends CompositeView {
if (animate) {
animationTimer = new Timer(
new Duration(milliseconds: ((durationSeconds * 1000).toInt())),
() { _onAnimationEnd(); });
new Duration(milliseconds: ((durationSeconds * 1000).toInt())), () {
_onAnimationEnd();
});
}
// TODO(mattsh), we should set the visibility to hide everything but the
// selected view.

View file

@ -47,7 +47,7 @@ class MeasureText {
String quickTruncate(String text, num lineWidth, int maxLines) {
int targetLength = lineWidth * maxLines ~/ _typicalCharLength;
// Advance to next word break point.
while(targetLength < text.length && !isWhitespace(text[targetLength])) {
while (targetLength < text.length && !isWhitespace(text[targetLength])) {
targetLength++;
}
@ -64,8 +64,8 @@ class MeasureText {
* This function is safe to call with [:sb == null:] in which case just the
* line count is returned.
*/
int addLineBrokenText(StringBuffer sb, String text, num lineWidth,
int maxLines) {
int addLineBrokenText(
StringBuffer sb, String text, num lineWidth, int maxLines) {
// Strip surrounding whitespace. This ensures we create zero lines if there
// is no visible text.
text = text.trim();
@ -112,8 +112,7 @@ class MeasureText {
return lines;
}
void lineBreak(String text, num lineWidth, int maxLines,
Function callback) {
void lineBreak(String text, num lineWidth, int maxLines, Function callback) {
_context.font = font;
int lines = 0;
num currentLength = 0;
@ -128,8 +127,8 @@ class MeasureText {
// Treat the char after the end of the string as whitespace.
bool whitespace = i == len || isWhitespace(text[i]);
if (whitespace && !lastWhitespace) {
num wordLength = _context.measureText(text.substring(
wordStartIndex, i)).width;
num wordLength =
_context.measureText(text.substring(wordStartIndex, i)).width;
// TODO(jimhug): Replace the line above with this one to workaround
// dartium bug - error: unimplemented code
// num wordLength = (i - wordStartIndex) * 17;
@ -146,7 +145,7 @@ class MeasureText {
return;
}
startIndex = wordStartIndex;
currentLength = wordLength;
currentLength = wordLength;
}
lastWordEndIndex = i;
currentLength += _spaceLength;

View file

@ -8,10 +8,10 @@ class PageState {
final ObservableValue<int> current;
final ObservableValue<int> target;
final ObservableValue<int> length;
PageState() :
current = new ObservableValue<int>(0),
target = new ObservableValue<int>(0),
length = new ObservableValue<int>(1);
PageState()
: current = new ObservableValue<int>(0),
target = new ObservableValue<int>(0),
length = new ObservableValue<int>(1);
}
/** Simplifies using a PageNumberView and PagedColumnView together. */
@ -20,8 +20,8 @@ class PagedContentView extends CompositeView {
final PageState pages;
PagedContentView(this.content)
: super('paged-content'),
pages = new PageState() {
: super('paged-content'),
pages = new PageState() {
addChild(new PagedColumnView(pages, content));
addChild(new PageNumberView(pages));
}
@ -85,7 +85,6 @@ class PageNumberView extends View {
* the number of pages using [:scrollWidth:] and [:offsetWidth:].
*/
class PagedColumnView extends View {
static const MIN_THROW_PAGE_FRACTION = 0.01;
final View contentView;
@ -112,15 +111,10 @@ class PagedColumnView extends View {
// the scroller configured the default way.
// TODO(jacobr): use named arguments when available.
scroller = new Scroller(
_container,
false /* verticalScrollEnabled */,
true /* horizontalScrollEnabled */,
true /* momementumEnabled */,
() {
return new Size(_getViewLength(_container), 1);
},
Scroller.FAST_SNAP_DECELERATION_FACTOR);
scroller = new Scroller(_container, false /* verticalScrollEnabled */,
true /* horizontalScrollEnabled */, true /* momementumEnabled */, () {
return new Size(_getViewLength(_container), 1);
}, Scroller.FAST_SNAP_DECELERATION_FACTOR);
scroller.onDecelStart.listen(_snapToPage);
scroller.onScrollerDragEnd.listen(_snapToPage);
@ -193,8 +187,8 @@ class PagedColumnView extends View {
int pageLength = 1;
scheduleMicrotask(() {
if (_container.scrollWidth > _container.offset.width) {
pageLength = (_container.scrollWidth / _computePageSize(_container))
.ceil();
pageLength =
(_container.scrollWidth / _computePageSize(_container)).ceil();
}
pageLength = Math.max(pageLength, 1);
@ -236,13 +230,14 @@ class PagedColumnView extends View {
pageNumber = pageNumber.round();
} else {
if (currentPageNumber == pageNumber.round() &&
(pageNumber - currentPageNumber).abs() > MIN_THROW_PAGE_FRACTION &&
-current + _viewportSize < _getViewLength(_container) &&
current < 0) {
(pageNumber - currentPageNumber).abs() > MIN_THROW_PAGE_FRACTION &&
-current + _viewportSize < _getViewLength(_container) &&
current < 0) {
// The user is trying to throw so we want to round up to the
// nearest page in the direction they are throwing.
pageNumber = currentTarget < current
? currentPageNumber + 1 : currentPageNumber - 1;
? currentPageNumber + 1
: currentPageNumber - 1;
} else {
pageNumber = pageNumber.round();
}
@ -266,8 +261,8 @@ class PagedColumnView extends View {
// Figure out how many columns we're rendering.
// The algorithm ensures we're bigger than the specified min size.
int perPage = Math.max(1,
(_viewportSize + _columnGap) ~/ (_columnWidth + _columnGap));
int perPage = Math.max(
1, (_viewportSize + _columnGap) ~/ (_columnWidth + _columnGap));
// Divide up the viewport between the columns.
int columnSize = (_viewportSize - (perPage - 1) * _columnGap) ~/ perPage;

View file

@ -138,7 +138,7 @@ class SliderMenu extends View {
}
void selectNext(bool animate) {
final result = node.querySelector('.sm-item.sel').nextElementSibling;
final result = node.querySelector('.sm-item.sel').nextElementSibling;
if (result != null) {
selectItem(result, animate);
}
@ -159,7 +159,8 @@ class SliderMenu extends View {
// calculate where we want to put the triangle
scheduleMicrotask(() {
num x = selectedItem.offset.left +
selectedItem.offset.width / 2 - TRIANGLE_WIDTH / 2;
selectedItem.offset.width / 2 -
TRIANGLE_WIDTH / 2;
_moveIndicator(x, animate);
});
} else {

View file

@ -19,7 +19,6 @@ part 'MeasureText.dart';
part 'PagedViews.dart';
part 'SliderMenu.dart';
// TODO(rnystrom): Note! This class is undergoing heavy construction. It will
// temporary support both some old and some new ways of doing things until all
// subclasses are refactored to use the new way. There will be some scaffolding
@ -43,15 +42,13 @@ class View implements Positionable {
// object instead, and integrating with built in CSS properties.
final Map<String, String> customStyle;
View()
: customStyle = new Map<String, String>();
View() : customStyle = new Map<String, String>();
View.fromNode(Element this._node)
: customStyle = new Map<String, String>();
View.fromNode(Element this._node) : customStyle = new Map<String, String>();
View.html(String html)
: customStyle = new Map<String, String>(),
_node = new Element.html(html);
: customStyle = new Map<String, String>(),
_node = new Element.html(html);
// TODO(rnystrom): Get rid of this when all views are refactored to not use
// it.
@ -111,9 +108,9 @@ class View implements Positionable {
* document or not.
*/
bool get isInDocument {
return _node != null
&& node.ownerDocument is HtmlDocument
&& (node.ownerDocument as HtmlDocument).body.contains(node);
return _node != null &&
node.ownerDocument is HtmlDocument &&
(node.ownerDocument as HtmlDocument).body.contains(node);
}
/**
@ -142,7 +139,9 @@ class View implements Positionable {
* Override this to generate the DOM structure for the view.
*/
// TODO(rnystrom): make this method abstract, see b/5015671
Element render() { throw 'abstract'; }
Element render() {
throw 'abstract';
}
/**
* Override this to perform initialization behavior that requires access to
@ -310,7 +309,6 @@ class View implements Positionable {
_resizeSubscription = window.onResize.listen(handler);
}
// Trigger the initial layout.
doLayout();
}
@ -358,8 +356,8 @@ class View implements Positionable {
// TODO(10459): code should not use Completer.sync.
Completer sizeCompleter = new Completer<Size>.sync();
scheduleMicrotask(() {
sizeCompleter.complete(
new Size(_node.client.width, _node.client.height));
sizeCompleter
.complete(new Size(_node.client.width, _node.client.height));
});
layout.measureLayout(sizeCompleter.future, changed);
} else {

View file

@ -33,15 +33,16 @@ void main() {
getStoryNode() => swarm.frontView.storyView.node;
getView(Section section) {
return CollectionUtils.find(swarm.frontView.sections.childViews,
(view) => view.section == section);
return CollectionUtils.find(
swarm.frontView.sections.childViews, (view) => view.section == section);
}
getHistory(Article article) {
final feed = article.dataSource;
return {
'section': CollectionUtils.find(swarm.sections,
(s) => s.feeds.indexOf(feed, 0) >= 0).id,
'section': CollectionUtils
.find(swarm.sections, (s) => s.feeds.indexOf(feed, 0) >= 0)
.id,
'feed': feed.id,
'article': article.id
};
@ -113,7 +114,6 @@ click(Element element) {
element.dispatchEvent(event);
}
/** A proxy so we can intercept history calls */
class UIStateProxy extends SwarmState {
List<Map<String, String>> history;
@ -153,6 +153,7 @@ void _serialInvokeAsync(List closures) {
Timer.run(expectAsync(invokeNext));
}
}
Timer.run(expectAsync(invokeNext));
}
}

View file

@ -6,33 +6,33 @@ part of layout_tests;
class AdaptiveLayout {
// selector, properties<propertyName, value>
static const selectors = const {
'#grid' : const {
'display' : '-dart-grid',
'grid-columns' : 'auto minmax(min-content, 1fr)',
'grid-rows' : 'auto minmax(min-content, 1fr) auto',
'#grid': const {
'display': '-dart-grid',
'grid-columns': 'auto minmax(min-content, 1fr)',
'grid-rows': 'auto minmax(min-content, 1fr) auto',
},
'#title' : const {
'grid-column' : '1',
'grid-row' : '1',
'#title': const {
'grid-column': '1',
'grid-row': '1',
},
'#score' : const {
'grid-column' : '1',
'grid-row' : '3',
'#score': const {
'grid-column': '1',
'grid-row': '3',
},
'#stats' : const {
'grid-column' : '1',
'grid-row' : '2',
'grid-row-align' : 'start',
'#stats': const {
'grid-column': '1',
'grid-row': '2',
'grid-row-align': 'start',
},
'#board' : const {
'grid-column' : '2',
'grid-row' : '1',
'grid-row-span' : '2',
'#board': const {
'grid-column': '2',
'grid-row': '1',
'grid-row-span': '2',
},
'#controls' : const {
'grid-column' : '2',
'grid-row' : '3',
'grid-column-align' : 'center',
'#controls': const {
'grid-column': '2',
'grid-row': '3',
'grid-column-align': 'center',
},
};
}
@ -40,26 +40,26 @@ class AdaptiveLayout {
class SourceIndependencePortrait {
// selector, properties<propertyName, value>
static const selectors = const {
'#grid' : const {
'display' : '-dart-grid',
'grid-template' : '"ta" "sa" "bb" "cc"',
'grid-columns' : 'auto minmax(min-content, 1fr)',
'grid-rows' : 'auto auto minmax(min-content, 1fr) auto',
'#grid': const {
'display': '-dart-grid',
'grid-template': '"ta" "sa" "bb" "cc"',
'grid-columns': 'auto minmax(min-content, 1fr)',
'grid-rows': 'auto auto minmax(min-content, 1fr) auto',
},
'#title' : const {
'grid-cell' : '"t"',
'#title': const {
'grid-cell': '"t"',
},
'#score' : const {
'grid-cell' : '"s"',
'#score': const {
'grid-cell': '"s"',
},
'#stats' : const {
'grid-cell' : '"a"',
'#stats': const {
'grid-cell': '"a"',
},
'#board' : const {
'grid-cell' : '"b"',
'#board': const {
'grid-cell': '"b"',
},
'#controls' : const {
'grid-cell' : '"c"',
'#controls': const {
'grid-cell': '"c"',
},
};
}
@ -67,26 +67,26 @@ class SourceIndependencePortrait {
class SourceIndependenceLandscape {
// selector, properties<propertyName, value>
static const selectors = const {
'#grid' : const {
'display' : '-dart-grid',
'grid-template' : '"tb" "ab" "sc"',
'grid-columns' : 'auto minmax(min-content, 1fr)',
'grid-rows' : 'auto minmax(min-content, 1fr) auto',
'#grid': const {
'display': '-dart-grid',
'grid-template': '"tb" "ab" "sc"',
'grid-columns': 'auto minmax(min-content, 1fr)',
'grid-rows': 'auto minmax(min-content, 1fr) auto',
},
'#title' : const {
'grid-cell' : '"t"',
'#title': const {
'grid-cell': '"t"',
},
'#score' : const {
'grid-cell' : '"s"',
'#score': const {
'grid-cell': '"s"',
},
'#stats' : const {
'grid-cell' : '"a"',
'#stats': const {
'grid-cell': '"a"',
},
'#board' : const {
'grid-cell' : '"b"',
'#board': const {
'grid-cell': '"b"',
},
'#controls' : const {
'grid-cell' : '"c"',
'#controls': const {
'grid-cell': '"c"',
},
};
}
@ -94,33 +94,34 @@ class SourceIndependenceLandscape {
class GridLayering {
// selector, properties<propertyName, value>
static const selectors = const {
'#grid' : const {
'display' : '-dart-grid',
'grid-columns' : '"start" auto "track-start" 0.5fr "thumb-start" auto "fill-split" auto "thumb-end" 0.5fr "track-end" auto "end"',
'#grid': const {
'display': '-dart-grid',
'grid-columns':
'"start" auto "track-start" 0.5fr "thumb-start" auto "fill-split" auto "thumb-end" 0.5fr "track-end" auto "end"',
},
'#lower-label' : const {
'grid-column' : '"start"',
'#lower-label': const {
'grid-column': '"start"',
},
'#track' : const {
'grid-column' : '"track-start" "track-end"',
'grid-row-align' : 'center',
'#track': const {
'grid-column': '"track-start" "track-end"',
'grid-row-align': 'center',
},
'#upper-label' : const {
'grid-column' : '"track-end"',
'#upper-label': const {
'grid-column': '"track-end"',
},
'#lower-fill' : const {
'grid-column' : '"track-start" "fill-split"',
'grid-row-align' : 'center',
'grid-layer' : '5',
'#lower-fill': const {
'grid-column': '"track-start" "fill-split"',
'grid-row-align': 'center',
'grid-layer': '5',
},
'#upper-fill' : const {
'grid-column' : '"fill-split" "track-end"',
'grid-row-align' : 'center',
'grid-layer' : '5',
'#upper-fill': const {
'grid-column': '"fill-split" "track-end"',
'grid-row-align': 'center',
'grid-layer': '5',
},
'#thumb' : const {
'grid-column' : '"thumb-start" "thumb-end"',
'grid-layer' : '10',
'#thumb': const {
'grid-column': '"thumb-start" "thumb-end"',
'grid-layer': '10',
},
};
}
@ -128,14 +129,14 @@ class GridLayering {
class GridLines_5 {
// selector, properties<propertyName, value>
static const selectors = const {
'#grid' : const {
'display' : '-dart-grid',
'grid-columns' : '150px 1fr',
'grid-rows' : '50px 1fr 50px',
'#grid': const {
'display': '-dart-grid',
'grid-columns': '150px 1fr',
'grid-rows': '50px 1fr 50px',
},
'#item1' : const {
'grid-column' : '2',
'grid-row' : '1 4',
'#item1': const {
'grid-column': '2',
'grid-row': '1 4',
},
};
}
@ -143,14 +144,14 @@ class GridLines_5 {
class GridLines_6 {
// selector, properties<propertyName, value>
static const selectors = const {
'#grid' : const {
'display' : '-dart-grid',
'grid-columns' : '150px "item1-start" 1fr "item1-end"',
'grid-rows' : '"item1-start" 50px 1fr 50px "item1-end"',
'#grid': const {
'display': '-dart-grid',
'grid-columns': '150px "item1-start" 1fr "item1-end"',
'grid-rows': '"item1-start" 50px 1fr 50px "item1-end"',
},
'#item1' : const {
'grid-column' : '"item1-start" "item1-end"',
'grid-row' : '"item1-start" "item1-end"',
'#item1': const {
'grid-column': '"item1-start" "item1-end"',
'grid-row': '"item1-start" "item1-end"',
},
};
}
@ -158,20 +159,20 @@ class GridLines_6 {
class GridCells {
// selector, properties<propertyName, value>
static const selectors = const {
'#grid' : const {
'display' : '-dart-grid',
'grid-template' : '"ad" "bd" "cd"',
'grid-columns' : '150px 1fr',
'grid-rows' : '50px 1fr 50px',
'#grid': const {
'display': '-dart-grid',
'grid-template': '"ad" "bd" "cd"',
'grid-columns': '150px 1fr',
'grid-rows': '50px 1fr 50px',
},
'#item2' : const {
'grid-cell' : '"b"',
'grid-row-align' : 'start',
'#item2': const {
'grid-cell': '"b"',
'grid-row-align': 'start',
},
'#item3' : const {
'grid-cell' : '"b"',
'grid-column-align' : 'end',
'grid-row-align' : 'end',
'#item3': const {
'grid-cell': '"b"',
'grid-column-align': 'end',
'grid-row-align': 'end',
},
};
}
@ -179,14 +180,14 @@ class GridCells {
class StartEndingGridlines11a {
// selector, properties<propertyName, value>
static const selectors = const {
'#grid' : const {
'display' : '-dart-grid',
'grid-columns' : '50px 1fr',
'grid-rows' : '"first" 250px 1fr 250px "last"',
'#grid': const {
'display': '-dart-grid',
'grid-columns': '50px 1fr',
'grid-rows': '"first" 250px 1fr 250px "last"',
},
'#item' : const {
'grid-column' : '1 3',
'grid-row' : '"first" "last"',
'#item': const {
'grid-column': '1 3',
'grid-row': '"first" "last"',
},
};
}
@ -194,14 +195,14 @@ class StartEndingGridlines11a {
class StartEndingGridlines11b {
// selector, properties<propertyName, value>
static const selectors = const {
'#grid' : const {
'display' : '-dart-grid',
'grid-columns' : '50px 1fr',
'grid-rows' : '"first" 250px 1fr 250px "last"',
'#grid': const {
'display': '-dart-grid',
'grid-columns': '50px 1fr',
'grid-rows': '"first" 250px 1fr 250px "last"',
},
'#item' : const {
'grid-column' : 'start end',
'grid-row' : 'start end',
'#item': const {
'grid-column': 'start end',
'grid-row': 'start end',
},
};
}
@ -209,22 +210,22 @@ class StartEndingGridlines11b {
class RepeatingColumnsRows {
// selector, properties<propertyName, value>
static const selectors = const {
'#grid' : const {
'display' : '-dart-grid',
'grid-columns' : '10px ("content" 1fr 10px) [4]',
'grid-rows' : '1fr',
'#grid': const {
'display': '-dart-grid',
'grid-columns': '10px ("content" 1fr 10px) [4]',
'grid-rows': '1fr',
},
'#col2' : const {
'grid-column' : '2',
'#col2': const {
'grid-column': '2',
},
'#col4' : const {
'grid-column' : '4',
'#col4': const {
'grid-column': '4',
},
'#col6' : const {
'grid-column' : '6',
'#col6': const {
'grid-column': '6',
},
'#col8' : const {
'grid-column' : '8',
'#col8': const {
'grid-column': '8',
},
};
}
@ -232,22 +233,22 @@ class RepeatingColumnsRows {
class AnonymousGridCells {
// selector, properties<propertyName, value>
static const selectors = const {
'#grid' : const {
'display' : '-dart-grid',
'grid-rows' : '"header" auto "main" 1fr "footer" auto',
'grid-columns' : '1fr',
'#grid': const {
'display': '-dart-grid',
'grid-rows': '"header" auto "main" 1fr "footer" auto',
'grid-columns': '1fr',
},
'#header' : const {
'grid-row' : '"header"',
'grid-column' : 'start',
'#header': const {
'grid-row': '"header"',
'grid-column': 'start',
},
'#main' : const {
'grid-row' : '"main"',
'grid-column' : 'start',
'#main': const {
'grid-row': '"main"',
'grid-column': 'start',
},
'#footer' : const {
'grid-row' : '"footer"',
'grid-column' : 'start',
'#footer': const {
'grid-row': '"footer"',
'grid-column': 'start',
},
};
}
@ -255,26 +256,26 @@ class AnonymousGridCells {
class ImplicitColumnsRows {
// selector, properties<propertyName, value>
static const selectors = const {
'#grid' : const {
'display' : '-dart-grid',
'grid-columns' : '20px',
'grid-rows' : '20px',
'#grid': const {
'display': '-dart-grid',
'grid-columns': '20px',
'grid-rows': '20px',
},
'#A' : const {
'grid-column' : '1',
'grid-row' : '1',
'grid-column-align' : 'start',
'grid-row-align' : 'start',
'#A': const {
'grid-column': '1',
'grid-row': '1',
'grid-column-align': 'start',
'grid-row-align': 'start',
},
'#B' : const {
'grid-column' : '5',
'grid-row' : '1',
'grid-row-span' : '2',
'#B': const {
'grid-column': '5',
'grid-row': '1',
'grid-row-span': '2',
},
'#C' : const {
'grid-column' : '1',
'grid-row' : '2',
'grid-column-span' : '2',
'#C': const {
'grid-column': '1',
'grid-row': '2',
'grid-column-span': '2',
},
};
}
@ -282,22 +283,22 @@ class ImplicitColumnsRows {
class AlignGridItems {
// selector, properties<propertyName, value>
static const selectors = const {
'#grid' : const {
'display' : '-dart-grid',
'grid-columns' : '1fr 1fr',
'grid-rows' : '1fr 1fr',
'#grid': const {
'display': '-dart-grid',
'grid-columns': '1fr 1fr',
'grid-rows': '1fr 1fr',
},
'#A' : const {
'grid-column' : '1',
'grid-row' : '1',
'grid-column-align' : 'start',
'grid-row-align' : 'start',
'#A': const {
'grid-column': '1',
'grid-row': '1',
'grid-column-align': 'start',
'grid-row-align': 'start',
},
'#B' : const {
'grid-column' : '2',
'grid-row' : '2',
'grid-column-align' : 'end',
'grid-row-align' : 'end',
'#B': const {
'grid-column': '2',
'grid-row': '2',
'grid-column-align': 'end',
'grid-row-align': 'end',
},
};
}
@ -305,42 +306,42 @@ class AlignGridItems {
class DrawOrderGridItems {
// selector, properties<propertyName, value>
static const selectors = const {
'#grid' : const {
'display' : '-dart-grid',
'grid-columns' : '1fr 1fr',
'grid-rows' : '1fr 1fr',
'#grid': const {
'display': '-dart-grid',
'grid-columns': '1fr 1fr',
'grid-rows': '1fr 1fr',
},
'#A' : const {
'grid-column' : '1',
'grid-row' : '2',
'grid-column-span' : '2',
'grid-row-align' : 'end',
'#A': const {
'grid-column': '1',
'grid-row': '2',
'grid-column-span': '2',
'grid-row-align': 'end',
},
'#B' : const {
'grid-column' : '1',
'grid-row' : '1',
'grid-layer' : '10',
'#B': const {
'grid-column': '1',
'grid-row': '1',
'grid-layer': '10',
},
'#C' : const {
'grid-column' : '2',
'grid-row' : '1',
'grid-row-align' : 'start',
'margin-left' : '-20px',
'#C': const {
'grid-column': '2',
'grid-row': '1',
'grid-row-align': 'start',
'margin-left': '-20px',
},
'#D' : const {
'grid-column' : '2',
'grid-row' : '2',
'grid-column-align' : 'end',
'grid-row-align' : 'start',
'#D': const {
'grid-column': '2',
'grid-row': '2',
'grid-column-align': 'end',
'grid-row-align': 'start',
},
'#E' : const {
'grid-column' : '1',
'grid-row' : '1',
'grid-column-span' : '2',
'grid-row-span' : '2',
'grid-layer' : '5',
'grid-column-align' : 'center',
'grid-row-align' : 'center',
'#E': const {
'grid-column': '1',
'grid-row': '1',
'grid-column-span': '2',
'grid-row-span': '2',
'grid-layer': '5',
'grid-column-align': 'center',
'grid-row-align': 'center',
},
};
}

View file

@ -66,8 +66,14 @@ void addGridStyles(String width, String height, [String margin = '']) {
void _addColorStyles() {
final grid = document.body.querySelector('#grid');
final colors = const [ 'darkred', 'darkorange', 'darkgoldenrod',
'darkgreen', 'darkblue', 'darkviolet'];
final colors = const [
'darkred',
'darkorange',
'darkgoldenrod',
'darkgreen',
'darkblue',
'darkviolet'
];
int c = 0;
var node = grid.children[0];
while (node != null) {
@ -79,8 +85,7 @@ void _addColorStyles() {
}
class MockCompositeView extends CompositeView {
MockCompositeView(String id, Map styles, List childViews)
: super('') {
MockCompositeView(String id, Map styles, List childViews) : super('') {
node.id = id;
CollectionUtils.copyMap(customStyle, styles);
@ -92,8 +97,8 @@ class MockCompositeView extends CompositeView {
class MockView extends View {
MockView(String id, Map styles)
: super.fromNode(new Element.html(
'<div class="grid-item">MockView-$id</div>')) {
: super.fromNode(
new Element.html('<div class="grid-item">MockView-$id</div>')) {
node.id = id;
CollectionUtils.copyMap(customStyle, styles);
// TODO(jmesserly): this is needed to get horizontal content-sizing to work
@ -101,7 +106,6 @@ class MockView extends View {
}
}
void printMetrics(String example) {
final node = document.body.querySelector('#grid');
String exampleId = example.split(' ')[0];

View file

@ -8,7 +8,7 @@ testAbstractObservable() {
group('addChangeListener()', () {
test('adding the same listener twice returns false the second time', () {
final target = new AbstractObservable();
final listener = (e) { };
final listener = (e) {};
expect(target.addChangeListener(listener), isTrue);
expect(target.addChangeListener(listener), isFalse);
@ -17,10 +17,10 @@ testAbstractObservable() {
test('modifies listeners list', () {
// check that add/remove works, see contents of listeners too
final target = new AbstractObservable();
final l1 = (e) { };
final l2 = (e) { };
final l3 = (e) { };
final l4 = (e) { };
final l1 = (e) {};
final l2 = (e) {};
final l3 = (e) {};
final l4 = (e) {};
expect(target.listeners, orderedEquals([]));

View file

@ -9,21 +9,30 @@ testChangeEvent() {
// create property, list, global and check the proper initialization.
final target = new AbstractObservable();
validateUpdate(
new ChangeEvent.property(target, 'pK', 33, '12'),
target, 'pK', null, 33, '12');
validateUpdate(new ChangeEvent.property(target, 'pK', 33, '12'), target,
'pK', null, 33, '12');
validateUpdate(
new ChangeEvent.list(target, ChangeEvent.UPDATE, 3, 33, '12'),
target, null, 3, 33, '12');
target,
null,
3,
33,
'12');
validateInsert(
new ChangeEvent.list(target, ChangeEvent.INSERT, 3, 33, null),
target, null, 3, 33);
target,
null,
3,
33);
validateRemove(
new ChangeEvent.list(target, ChangeEvent.REMOVE, 3, null, '12'),
target, null, 3, '12');
target,
null,
3,
'12');
validateGlobal(
new ChangeEvent.list(target, ChangeEvent.GLOBAL, null, null, null),

View file

@ -54,15 +54,15 @@ testObservableList() {
called = false;
expect(arr, orderedEquals([1, 2, 3, 1, 3, 4]));
EventBatch.wrap((e) {
arr.add(5); // 1 2 3 1 3 4(5)
arr.add(6); // 1 2 3 1 3 4 5(6)
arr[1] = arr[arr.length - 1]; // 1(6)3 1 3 4 5 6
arr.add(7); // 1 6 3 1 3 4 5 6(7)
arr[5] = arr[8]; // 1 6 3 1 3(7)5 6 7
arr.add(42); // 1 6 3 1 3 7 5 6 7(42)
expect(arr.removeAt(3), equals(1)); // 1 6 3( )3 7 5 6 7 42
expect(arr.removeFirstElement(3), isTrue); // 1 6( ) 3 7 5 6 7 42
expect(arr.removeLast(), equals(42)); // 1 6 3 7 5 6 7( )
arr.add(5); // 1 2 3 1 3 4(5)
arr.add(6); // 1 2 3 1 3 4 5(6)
arr[1] = arr[arr.length - 1]; // 1(6)3 1 3 4 5 6
arr.add(7); // 1 6 3 1 3 4 5 6(7)
arr[5] = arr[8]; // 1 6 3 1 3(7)5 6 7
arr.add(42); // 1 6 3 1 3 7 5 6 7(42)
expect(arr.removeAt(3), equals(1)); // 1 6 3( )3 7 5 6 7 42
expect(arr.removeFirstElement(3), isTrue); // 1 6( ) 3 7 5 6 7 42
expect(arr.removeLast(), equals(42)); // 1 6 3 7 5 6 7( )
expect(arr.removeAllElements(6), equals(2)); // 1( ) 3 7 5( )7
called = true;
})(null);
@ -91,7 +91,9 @@ testObservableList() {
arr.add(4);
arr.add(10);
arr.add(9);
arr.sort((int a, int b) { return a - b; });
arr.sort((int a, int b) {
return a - b;
});
called = true;
})(null);
expect(called, isTrue);

View file

@ -33,7 +33,9 @@ testObservableValue() {
expect(value.value, equals('foo'));
bool called = false;
value.addChangeListener((summary) { called = true; });
value.addChangeListener((summary) {
called = true;
});
// Set it to the same value.
value.value = 'foo';

View file

@ -5,7 +5,7 @@
library touchTests;
import 'dart:html'; // TODO(rnystrom): Only needed to tell architecture.py
// that this is a web test. Come up with cleaner solution.
// that this is a web test. Come up with cleaner solution.
import 'package:unittest/html_config.dart';
import 'package:unittest/unittest.dart';
import '../../../swarm_ui_lib/touch/touch.dart';
@ -39,8 +39,8 @@ class TestMomentumDelegate {
Function onDecelerationEndCallback;
void onDecelerate(num x, num y,
[num duration = 0, String timingFunction = null]) {
onDecelerateCallback(x, y, duration, timingFunction);
[num duration = 0, String timingFunction = null]) {
onDecelerateCallback(x, y, duration, timingFunction);
}
/**

View file

@ -34,8 +34,9 @@ void main() {
return new Element.html('<div class="test"></div>');
};
view.afterRenderFn = (node) { result = '${result}after'; };
view.afterRenderFn = (node) {
result = '${result}after';
};
view.addToDocument(document.body);
expect(result, equals('renderafter'));
@ -44,7 +45,9 @@ void main() {
test('calls enterDocument()', () {
final view = new TestView();
bool entered = false;
view.enterDocumentFn = () { entered = true; };
view.enterDocumentFn = () {
entered = true;
};
view.addToDocument(document.body);
expect(entered, isTrue);
@ -56,7 +59,9 @@ void main() {
final rendered = new Element.html('<div class="node"></div>');
final view = new TestView();
view.renderFn = () => rendered;
view.afterRenderFn = (node) { expect(node, equals(rendered)); };
view.afterRenderFn = (node) {
expect(node, equals(rendered));
};
view.addToDocument(document.body);
});
@ -69,7 +74,9 @@ void main() {
bool entered = false;
final child = new TestView();
child.enterDocumentFn = () { entered = true; };
child.enterDocumentFn = () {
entered = true;
};
// Add the child.
parent.childViews = [child];
@ -83,7 +90,9 @@ void main() {
bool entered = false;
final child = new TestView();
child.enterDocumentFn = () { entered = true; };
child.enterDocumentFn = () {
entered = true;
};
// Add the child.
parent.childViews = [child];
@ -98,7 +107,9 @@ void main() {
var entered = 0;
final child = new TestView();
child.enterDocumentFn = () { entered++; };
child.enterDocumentFn = () {
entered++;
};
// Add the child.
parent.childViews = [child];
@ -120,7 +131,9 @@ void main() {
bool exited = false;
final child = new TestView();
child.exitDocumentFn = () { exited = true; };
child.exitDocumentFn = () {
exited = true;
};
// Remove the child.
parent.childViews = [];
@ -134,7 +147,9 @@ void main() {
bool exited = false;
final child = new TestView();
child.exitDocumentFn = () { exited = true; };
child.exitDocumentFn = () {
exited = true;
};
// Remove the child.
parent.childViews = [];
@ -149,7 +164,9 @@ void main() {
var exited = 0;
final child = new TestView();
child.exitDocumentFn = () { exited++; };
child.exitDocumentFn = () {
exited++;
};
// Add the child.
parent.childViews = [child];
@ -169,10 +186,14 @@ void main() {
var result = '';
final parent = new TestView();
parent.enterDocumentFn = () { result = '${result}parent'; };
parent.enterDocumentFn = () {
result = '${result}parent';
};
final child = new TestView();
child.enterDocumentFn = () { result = '${result}child'; };
child.enterDocumentFn = () {
result = '${result}child';
};
parent.childViews = [child];
@ -189,7 +210,9 @@ class TestView extends View {
Function exitDocumentFn;
List<View> childViews;
TestView() : super(), childViews = [] {
TestView()
: super(),
childViews = [] {
// Default behavior.
renderFn = () => new Element.html('<div class="test"></div>');
afterRenderFn = (node) {};
@ -198,7 +221,15 @@ class TestView extends View {
}
Element render() => renderFn();
void afterRender(Element node) { afterRenderFn(node); }
void enterDocument() { enterDocumentFn(); }
void exitDocument() { exitDocumentFn(); }
void afterRender(Element node) {
afterRenderFn(node);
}
void enterDocument() {
enterDocumentFn();
}
void exitDocument() {
exitDocumentFn();
}
}

View file

@ -42,14 +42,14 @@ void main(List<String> arguments) {
*/
void processArgs(List<String> arguments) {
var parser = new ArgParser();
parser.addOption("changed", help: "the file has changed since the last build",
allowMultiple: true);
parser.addOption("removed", help: "the file was removed since the last build",
allowMultiple: true);
parser.addOption("changed",
help: "the file has changed since the last build", allowMultiple: true);
parser.addOption("removed",
help: "the file was removed since the last build", allowMultiple: true);
parser.addFlag("clean", negatable: false, help: "remove any build artifacts");
parser.addFlag("full", negatable: false, help: "perform a full build");
parser.addFlag("machine",
negatable: false, help: "produce warnings in a machine parseable format");
negatable: false, help: "produce warnings in a machine parseable format");
parser.addFlag("help", negatable: false, help: "display this help and exit");
var args = parser.parse(arguments);
@ -85,11 +85,10 @@ void handleFullBuild() {
var files = <String>[];
Directory.current.list(recursive: true).listen((entity) {
if (entity is File) {
files.add((entity as File).resolveSymbolicLinksSync());
}
},
onDone: () => handleChangedFiles(files));
if (entity is File) {
files.add((entity as File).resolveSymbolicLinksSync());
}
}, onDone: () => handleChangedFiles(files));
}
/**
@ -102,9 +101,7 @@ void handleChangedFiles(List<String> files) {
/**
* Process the given list of removed files.
*/
void handleRemovedFiles(List<String> files) {
}
void handleRemovedFiles(List<String> files) {}
/**
* Convert a .foo file to a .foobar file.

View file

@ -11,6 +11,4 @@ import '../bin/test.dart' as test2;
* This test exists to ensure that the build_dart sample compiles without
* errors.
*/
void main() {
}
void main() {}

View file

@ -11,6 +11,4 @@ import '../test.dart' as test1;
* This test exists to ensure that the build_dart_simple sample compiles
* without errors.
*/
void main() {
}
void main() {}

View file

@ -12,7 +12,7 @@ import 'dart-ext:sample_extension';
class RandomArray {
static SendPort _port;
Future<List<int> > randomArray(int seed, int length) {
Future<List<int>> randomArray(int seed, int length) {
var completer = new Completer();
var replyPort = new RawReceivePort();
var args = new List(3);

View file

@ -54,15 +54,19 @@ Future testNativeExtensions(String snapshotKind) async {
// Copy sample_extension dart files and sample_extension tests to the
// temporary test directory.
for (var file in ['sample_synchronous_extension.dart',
'sample_asynchronous_extension.dart',
'test_sample_synchronous_extension.dart',
'test_sample_asynchronous_extension.dart']) {
for (var file in [
'sample_synchronous_extension.dart',
'sample_asynchronous_extension.dart',
'test_sample_synchronous_extension.dart',
'test_sample_asynchronous_extension.dart'
]) {
await copyFileToDirectory(join(sourceDirectory, file), testDirectory);
}
for (var test in ['test_sample_synchronous_extension.dart',
'test_sample_asynchronous_extension.dart']) {
for (var test in [
'test_sample_synchronous_extension.dart',
'test_sample_asynchronous_extension.dart'
]) {
String script = join(testDirectory, test);
String snapshot;
if (snapshotKind == null) {
@ -70,9 +74,7 @@ Future testNativeExtensions(String snapshotKind) async {
} else {
snapshot = join(testDirectory, "$test.snapshot");
await run(Platform.executable,
['--snapshot=$snapshot',
'--snapshot-kind=$snapshotKind',
script]);
['--snapshot=$snapshot', '--snapshot-kind=$snapshotKind', script]);
}
await run(Platform.executable, [snapshot]);

View file

@ -31,14 +31,18 @@ void checkNormal(List l) {
// Count how many times each byte value occurs. Assert that the counts
// are all within a reasonable (six-sigma) range.
List counts = new List<int>.filled(256, 0);
for (var e in l) { counts[e]++; }
for (var e in l) {
counts[e]++;
}
new RandomArray().randomArray(18, 256000).then(checkCorrelation(counts));
}
Function checkCorrelation(List counts) {
return (List l) {
List counts_2 = new List<int>.filled(256, 0);
for (var e in l) { counts_2[e]++; }
for (var e in l) {
counts_2[e]++;
}
var product = 0;
for (var i = 0; i < 256; ++i) {
check(counts[i] < 1200, "counts[i] < 1200");