Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(156)

Side by Side Diff: samples-dev/swarm/SwarmViews.dart

Issue 2828603002: Format samples and samples-dev directories. (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « samples-dev/swarm/SwarmState.dart ('k') | samples-dev/swarm/UIState.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of swarmlib; 5 part of swarmlib;
6 6
7 // TODO(jacobr): there is a lot of dead code in this class. Checking is as is 7 // TODO(jacobr): there is a lot of dead code in this class. Checking is as is
8 // and then doing a large pass to remove functionality that doesn't make sense 8 // and then doing a large pass to remove functionality that doesn't make sense
9 // given the UI layout. 9 // given the UI layout.
10 10
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 openKeyPresses = new Set.from([13 /*enter*/, 79 /*o*/]), 63 openKeyPresses = new Set.from([13 /*enter*/, 79 /*o*/]),
64 backKeyPresses = new Set.from([8 /*delete*/, 27 /*escape*/]), 64 backKeyPresses = new Set.from([8 /*delete*/, 27 /*escape*/]),
65 nextPageKeyPresses = new Set.from([78 /*n*/]), 65 nextPageKeyPresses = new Set.from([78 /*n*/]),
66 previousPageKeyPresses = new Set.from([80 /*p*/]), 66 previousPageKeyPresses = new Set.from([80 /*p*/]),
67 nextPrevShown = false { 67 nextPrevShown = false {
68 topView = new CompositeView('top-view', false, false, false); 68 topView = new CompositeView('top-view', false, false, false);
69 69
70 headerView = new HeaderView(swarm); 70 headerView = new HeaderView(swarm);
71 topView.addChild(headerView); 71 topView.addChild(headerView);
72 72
73 sliderMenu = new SliderMenu(swarm.sections.sectionTitles, 73 sliderMenu = new SliderMenu(swarm.sections.sectionTitles, (sectionTitle) {
74 (sectionTitle) { 74 swarm.state.moveToNewSection(sectionTitle);
75 swarm.state.moveToNewSection(sectionTitle); 75 _onSectionSelected(sectionTitle);
76 _onSectionSelected(sectionTitle); 76 // Start with no articles selected.
77 // Start with no articles selected. 77 swarm.state.selectedArticle.value = null;
78 swarm.state.selectedArticle.value = null; 78 });
79 });
80 topView.addChild(sliderMenu); 79 topView.addChild(sliderMenu);
81 addChild(topView); 80 addChild(topView);
82 81
83 bottomView = new CompositeView('bottom-view', false, false, false); 82 bottomView = new CompositeView('bottom-view', false, false, false);
84 addChild(bottomView); 83 addChild(bottomView);
85 84
86 sections = new ConveyorView(); 85 sections = new ConveyorView();
87 sections.viewSelected = _onSectionTransitionEnded; 86 sections.viewSelected = _onSectionTransitionEnded;
88 } 87 }
89 88
90 SectionView get currentSection { 89 SectionView get currentSection {
91 var view = sections.selectedView; 90 var view = sections.selectedView;
92 // TODO(jmesserly): this code works around a bug in the DartC --optimize 91 // TODO(jmesserly): this code works around a bug in the DartC --optimize
93 if (view == null) { 92 if (view == null) {
94 view = sections.childViews[0]; 93 view = sections.childViews[0];
95 sections.selectView(view); 94 sections.selectView(view);
96 } 95 }
97 return view; 96 return view;
98 } 97 }
99 98
100 void afterRender(Element node) { 99 void afterRender(Element node) {
101 _createSectionViews(); 100 _createSectionViews();
102 attachWatch(swarm.state.currentArticle, (e) { _refreshCurrentArticle(); }); 101 attachWatch(swarm.state.currentArticle, (e) {
103 attachWatch(swarm.state.storyMaximized, (e) { _refreshMaximized(); }); 102 _refreshCurrentArticle();
103 });
104 attachWatch(swarm.state.storyMaximized, (e) {
105 _refreshMaximized();
106 });
104 } 107 }
105 108
106 void _refreshCurrentArticle() { 109 void _refreshCurrentArticle() {
107 if (!swarm.state.inMainView) { 110 if (!swarm.state.inMainView) {
108 _animateToStory(swarm.state.currentArticle.value); 111 _animateToStory(swarm.state.currentArticle.value);
109 } else { 112 } else {
110 _animateToMainView(); 113 _animateToMainView();
111 } 114 }
112 } 115 }
113 116
114 /** 117 /**
115 * Animates back from the story view to the main grid view. 118 * Animates back from the story view to the main grid view.
116 */ 119 */
117 void _animateToMainView() { 120 void _animateToMainView() {
118 sliderMenu.removeClass('hidden'); 121 sliderMenu.removeClass('hidden');
119 storyView.addClass('hidden-story'); 122 storyView.addClass('hidden-story');
120 currentSection.storyMode = false; 123 currentSection.storyMode = false;
121 124
122 headerView.startTransitionToMainView(); 125 headerView.startTransitionToMainView();
123 126
124 currentSection.dataSourceView.reattachSubview( 127 currentSection.dataSourceView
125 detachedView.source, detachedView, true); 128 .reattachSubview(detachedView.source, detachedView, true);
126 129
127 storyView.node.onTransitionEnd.first.then((e) { 130 storyView.node.onTransitionEnd.first.then((e) {
128 currentSection.hidden = false; 131 currentSection.hidden = false;
129 // TODO(rnystrom): Should move this "mode" into SwarmState and have 132 // TODO(rnystrom): Should move this "mode" into SwarmState and have
130 // header view respond to change events itself. 133 // header view respond to change events itself.
131 removeChild(storyView); 134 removeChild(storyView);
132 storyView = null; 135 storyView = null;
133 detachedView.removeClass('sel'); 136 detachedView.removeClass('sel');
134 detachedView = null; 137 detachedView = null;
135 }); 138 });
(...skipping 14 matching lines...) Expand all
150 // and the user has clicked to see a new story. 153 // and the user has clicked to see a new story.
151 removeChild(storyView); 154 removeChild(storyView);
152 155
153 // Create the new story view and place in the frame. 156 // Create the new story view and place in the frame.
154 storyView = addChild(new StoryContentView(swarm, item)); 157 storyView = addChild(new StoryContentView(swarm, item));
155 } else { 158 } else {
156 // We are animating from the main view to the story view. 159 // We are animating from the main view to the story view.
157 // TODO(jmesserly): make this code better 160 // TODO(jmesserly): make this code better
158 final view = currentSection.findView(source); 161 final view = currentSection.findView(source);
159 162
160 final newPosition = FxUtil.computeRelativePosition( 163 final newPosition =
161 view.node, bottomView.node); 164 FxUtil.computeRelativePosition(view.node, bottomView.node);
162 currentSection.dataSourceView.detachSubview(view.source); 165 currentSection.dataSourceView.detachSubview(view.source);
163 detachedView = view; 166 detachedView = view;
164 167
165 FxUtil.setPosition(view.node, newPosition); 168 FxUtil.setPosition(view.node, newPosition);
166 bottomView.addChild(view); 169 bottomView.addChild(view);
167 view.addClass('sel'); 170 view.addClass('sel');
168 currentSection.storyMode = true; 171 currentSection.storyMode = true;
169 172
170 // Create the new story view. 173 // Create the new story view.
171 storyView = new StoryContentView(swarm, item); 174 storyView = new StoryContentView(swarm, item);
(...skipping 18 matching lines...) Expand all
190 if (swarm.state.storyMaximized.value) { 193 if (swarm.state.storyMaximized.value) {
191 _animateDataSourceToMaximized(); 194 _animateDataSourceToMaximized();
192 } else { 195 } else {
193 _animateDataSourceToMinimized(); 196 _animateDataSourceToMinimized();
194 } 197 }
195 } 198 }
196 199
197 void _animateDataSourceToMaximized() { 200 void _animateDataSourceToMaximized() {
198 FxUtil.setWebkitTransform(topView.node, 0, -HeaderView.HEIGHT); 201 FxUtil.setWebkitTransform(topView.node, 0, -HeaderView.HEIGHT);
199 if (detachedView != null) { 202 if (detachedView != null) {
200 FxUtil.setWebkitTransform(detachedView.node, 0, 203 FxUtil.setWebkitTransform(
201 -DataSourceView.TAB_ONLY_HEIGHT); 204 detachedView.node, 0, -DataSourceView.TAB_ONLY_HEIGHT);
202 } 205 }
203 } 206 }
204 207
205 void _animateDataSourceToMinimized() { 208 void _animateDataSourceToMinimized() {
206 if (detachedView != null) { 209 if (detachedView != null) {
207 FxUtil.setWebkitTransform(detachedView.node, 0, 0); 210 FxUtil.setWebkitTransform(detachedView.node, 0, 0);
208 FxUtil.setWebkitTransform(topView.node, 0, 0); 211 FxUtil.setWebkitTransform(topView.node, 0, 0);
209 } 212 }
210 } 213 }
211 214
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 322
320 /** A back button that sends the user back to the front page. */ 323 /** A back button that sends the user back to the front page. */
321 class SwarmBackButton extends View { 324 class SwarmBackButton extends View {
322 Swarm swarm; 325 Swarm swarm;
323 326
324 SwarmBackButton(this.swarm) : super(); 327 SwarmBackButton(this.swarm) : super();
325 328
326 Element render() => new Element.html('<div class="back-arrow button"></div>'); 329 Element render() => new Element.html('<div class="back-arrow button"></div>');
327 330
328 void afterRender(Element node) { 331 void afterRender(Element node) {
329 addOnClick((e) { _backToMain(swarm.state); }); 332 addOnClick((e) {
333 _backToMain(swarm.state);
334 });
330 } 335 }
331 } 336 }
332 337
333 /** Top view constaining the title and standard buttons. */ 338 /** Top view constaining the title and standard buttons. */
334 class HeaderView extends CompositeView { 339 class HeaderView extends CompositeView {
335 // TODO(jacobr): make this value be coupled with the CSS file. 340 // TODO(jacobr): make this value be coupled with the CSS file.
336 static const HEIGHT = 80; 341 static const HEIGHT = 80;
337 Swarm swarm; 342 Swarm swarm;
338 343
339 View _title; 344 View _title;
(...skipping 18 matching lines...) Expand all
358 363
359 // TODO(rnystrom): No more web/text mode (it's just text) so get rid of 364 // TODO(rnystrom): No more web/text mode (it's just text) so get rid of
360 // these. 365 // these.
361 _webBackButton = addChild(new WebBackButton()); 366 _webBackButton = addChild(new WebBackButton());
362 _webForwardButton = addChild(new WebForwardButton()); 367 _webForwardButton = addChild(new WebForwardButton());
363 _newWindowButton = addChild(View.div('new-window-button button')); 368 _newWindowButton = addChild(View.div('new-window-button button'));
364 } 369 }
365 370
366 void afterRender(Element node) { 371 void afterRender(Element node) {
367 // Respond to changes to whether the story is being shown as text or web. 372 // Respond to changes to whether the story is being shown as text or web.
368 attachWatch(swarm.state.storyTextMode, (e) { refreshWebStoryButtons(); }); 373 attachWatch(swarm.state.storyTextMode, (e) {
374 refreshWebStoryButtons();
375 });
369 376
370 _title.addOnClick((e) { _backToMain(swarm.state); }); 377 _title.addOnClick((e) {
378 _backToMain(swarm.state);
379 });
371 380
372 // Wire up the events. 381 // Wire up the events.
373 _configButton.addOnClick((e) { 382 _configButton.addOnClick((e) {
374 // Bring up the config dialog. 383 // Bring up the config dialog.
375 if (this._configDialog == null) { 384 if (this._configDialog == null) {
376 // TODO(terry): Cleanup, HeaderView shouldn't be tangled with main view. 385 // TODO(terry): Cleanup, HeaderView shouldn't be tangled with main view.
377 this._configDialog = new ConfigHintDialog(swarm.frontView, () { 386 this._configDialog = new ConfigHintDialog(swarm.frontView, () {
378 swarm.frontView.removeChild(this._configDialog); 387 swarm.frontView.removeChild(this._configDialog);
379 this._configDialog = null; 388 this._configDialog = null;
380 389
(...skipping 30 matching lines...) Expand all
411 420
412 // On click of the new window button, show web article in new window/tab. 421 // On click of the new window button, show web article in new window/tab.
413 _newWindowButton.addOnClick((e) { 422 _newWindowButton.addOnClick((e) {
414 String currentArticleSrcUrl = swarm.state.currentArticle.value.srcUrl; 423 String currentArticleSrcUrl = swarm.state.currentArticle.value.srcUrl;
415 window.open(currentArticleSrcUrl, '_blank'); 424 window.open(currentArticleSrcUrl, '_blank');
416 }); 425 });
417 426
418 startTransitionToMainView(); 427 startTransitionToMainView();
419 } 428 }
420 429
421
422 /** 430 /**
423 * Refreshes whether or not the buttons specific to the display of a story in 431 * Refreshes whether or not the buttons specific to the display of a story in
424 * the web perspective are visible. 432 * the web perspective are visible.
425 */ 433 */
426 void refreshWebStoryButtons() { 434 void refreshWebStoryButtons() {
427 bool webButtonsHidden = true; 435 bool webButtonsHidden = true;
428 436
429 if (swarm.state.currentArticle.value != null) { 437 if (swarm.state.currentArticle.value != null) {
430 // Set if web buttons are hidden 438 // Set if web buttons are hidden
431 webButtonsHidden = swarm.state.storyTextMode.value; 439 webButtonsHidden = swarm.state.storyTextMode.value;
432 } 440 }
433 441
434 _webBackButton.hidden = webButtonsHidden; 442 _webBackButton.hidden = webButtonsHidden;
435 _webForwardButton.hidden = webButtonsHidden; 443 _webForwardButton.hidden = webButtonsHidden;
436 _newWindowButton.hidden = webButtonsHidden; 444 _newWindowButton.hidden = webButtonsHidden;
437 } 445 }
438 446
439 void startTransitionToMainView() { 447 void startTransitionToMainView() {
440 _title.removeClass('in-story'); 448 _title.removeClass('in-story');
441 _backButton.removeClass('in-story'); 449 _backButton.removeClass('in-story');
442 450
443 _configButton.removeClass('in-story'); 451 _configButton.removeClass('in-story');
444 _refreshButton.removeClass('in-story'); 452 _refreshButton.removeClass('in-story');
445 _infoButton.removeClass('in-story'); 453 _infoButton.removeClass('in-story');
446 454
447 refreshWebStoryButtons(); 455 refreshWebStoryButtons();
448 } 456 }
449 457
450 void endTransitionToStoryView() { 458 void endTransitionToStoryView() {
451 _title.addClass('in-story'); 459 _title.addClass('in-story');
452 _backButton.addClass('in-story'); 460 _backButton.addClass('in-story');
453 461
454 _configButton.addClass('in-story'); 462 _configButton.addClass('in-story');
455 _refreshButton.addClass('in-story'); 463 _refreshButton.addClass('in-story');
456 _infoButton.addClass('in-story'); 464 _infoButton.addClass('in-story');
457 } 465 }
458 } 466 }
459 467
460
461 /** A back button for the web view of a story that is equivalent to clicking 468 /** A back button for the web view of a story that is equivalent to clicking
462 * "back" in the browser. */ 469 * "back" in the browser. */
463 // TODO(rnystrom): We have nearly identical versions of this littered through 470 // TODO(rnystrom): We have nearly identical versions of this littered through
464 // the sample apps. Should consolidate into one. 471 // the sample apps. Should consolidate into one.
465 class WebBackButton extends View { 472 class WebBackButton extends View {
466 WebBackButton() : super(); 473 WebBackButton() : super();
467 474
468 Element render() { 475 Element render() {
469 return new Element.html('<div class="web-back-button button"></div>'); 476 return new Element.html('<div class="web-back-button button"></div>');
470 } 477 }
471 478
472 void afterRender(Element node) { 479 void afterRender(Element node) {
473 addOnClick((e) { back(); }); 480 addOnClick((e) {
481 back();
482 });
474 } 483 }
475 484
476 /** Equivalent to [window.history.back] */ 485 /** Equivalent to [window.history.back] */
477 static void back() { 486 static void back() {
478 window.history.back(); 487 window.history.back();
479 } 488 }
480 } 489 }
481 490
482 /** A back button for the web view of a story that is equivalent to clicking 491 /** A back button for the web view of a story that is equivalent to clicking
483 * "forward" in the browser. */ 492 * "forward" in the browser. */
484 // TODO(rnystrom): We have nearly identical versions of this littered through 493 // TODO(rnystrom): We have nearly identical versions of this littered through
485 // the sample apps. Should consolidate into one. 494 // the sample apps. Should consolidate into one.
486 class WebForwardButton extends View { 495 class WebForwardButton extends View {
487 WebForwardButton() : super(); 496 WebForwardButton() : super();
488 497
489 Element render() { 498 Element render() {
490 return new Element.html('<div class="web-forward-button button"></div>'); 499 return new Element.html('<div class="web-forward-button button"></div>');
491 } 500 }
492 501
493 void afterRender(Element node) { 502 void afterRender(Element node) {
494 addOnClick((e) { forward(); }); 503 addOnClick((e) {
504 forward();
505 });
495 } 506 }
496 507
497 /** Equivalent to [window.history.forward] */ 508 /** Equivalent to [window.history.forward] */
498 static void forward() { 509 static void forward() {
499 window.history.forward(); 510 window.history.forward();
500 } 511 }
501 } 512 }
502 513
503 /** 514 /**
504 * A factory that creates a view for data sources. 515 * A factory that creates a view for data sources.
505 */ 516 */
506 class DataSourceViewFactory implements ViewFactory<Feed> { 517 class DataSourceViewFactory implements ViewFactory<Feed> {
507 Swarm swarm; 518 Swarm swarm;
508 519
509 DataSourceViewFactory(this.swarm) {} 520 DataSourceViewFactory(this.swarm) {}
510 521
511 View newView(Feed data) => new DataSourceView(data, swarm); 522 View newView(Feed data) => new DataSourceView(data, swarm);
512 523
513 int get width => ArticleViewLayout.getSingleton().width; 524 int get width => ArticleViewLayout.getSingleton().width;
514 int get height => null; // Width for this view isn't known. 525 int get height => null; // Width for this view isn't known.
515 } 526 }
516 527
517
518 /** 528 /**
519 * A view for the items from a single data source. 529 * A view for the items from a single data source.
520 * Shows a title and a list of items. 530 * Shows a title and a list of items.
521 */ 531 */
522 class DataSourceView extends CompositeView { 532 class DataSourceView extends CompositeView {
523 // TODO(jacobr): make this value be coupled with the CSS file. 533 // TODO(jacobr): make this value be coupled with the CSS file.
524 static const TAB_ONLY_HEIGHT = 34; 534 static const TAB_ONLY_HEIGHT = 34;
525 535
526 final Feed source; 536 final Feed source;
527 VariableSizeListView<Article> itemsView; 537 VariableSizeListView<Article> itemsView;
528 538
529 DataSourceView(this.source, Swarm swarm) : super('query') { 539 DataSourceView(this.source, Swarm swarm) : super('query') {
530
531 // TODO(jacobr): make the title a view or decide it is sane for a subclass 540 // TODO(jacobr): make the title a view or decide it is sane for a subclass
532 // of component view to manually add some DOM cruft. 541 // of component view to manually add some DOM cruft.
533 node.nodes.add(new Element.html( 542 node.nodes.add(new Element.html('<h2>${source.title}</h2>'));
534 '<h2>${source.title}</h2>'));
535 543
536 // TODO(jacobr): use named arguments when available. 544 // TODO(jacobr): use named arguments when available.
537 itemsView = addChild(new VariableSizeListView<Article>( 545 itemsView = addChild(new VariableSizeListView<Article>(
538 source.articles, 546 source.articles,
539 new ArticleViewFactory(swarm), 547 new ArticleViewFactory(swarm),
540 true, /* scrollable */ 548 true,
541 true, /* vertical */ 549 /* scrollable */
542 swarm.state.currentArticle, /* selectedItem */ 550 true,
551 /* vertical */
552 swarm.state.currentArticle,
553 /* selectedItem */
543 !Device.supportsTouch /* snapToArticles */, 554 !Device.supportsTouch /* snapToArticles */,
544 false /* paginate */, 555 false /* paginate */,
545 true /* removeClippedViews */, 556 true /* removeClippedViews */,
546 !Device.supportsTouch /* showScrollbar */)); 557 !Device.supportsTouch /* showScrollbar */));
547 itemsView.addClass('story-section'); 558 itemsView.addClass('story-section');
548 559
549 node.nodes.add(new Element.html('<div class="query-name-shadow"></div>')); 560 node.nodes.add(new Element.html('<div class="query-name-shadow"></div>'));
550 561
551 // Clicking the view (i.e. its title area) unmaximizes to show the entire 562 // Clicking the view (i.e. its title area) unmaximizes to show the entire
552 // view. 563 // view.
553 node.onMouseDown.listen((e) { 564 node.onMouseDown.listen((e) {
554 swarm.state.storyMaximized.value = false; 565 swarm.state.storyMaximized.value = false;
555 }); 566 });
556 } 567 }
557 } 568 }
558 569
559 /** A button that toggles between states. */ 570 /** A button that toggles between states. */
560 class ToggleButton extends View { 571 class ToggleButton extends View {
561 EventListeners onChanged; 572 EventListeners onChanged;
562 List<String> states; 573 List<String> states;
563 574
564 ToggleButton(this.states) 575 ToggleButton(this.states)
565 : super(), 576 : super(),
566 onChanged = new EventListeners(); 577 onChanged = new EventListeners();
567 578
568 Element render() => new Element.tag('button'); 579 Element render() => new Element.tag('button');
569 580
570 void afterRender(Element node) { 581 void afterRender(Element node) {
571 state = states[0]; 582 state = states[0];
572 node.onClick.listen((event) { toggle(); }); 583 node.onClick.listen((event) {
584 toggle();
585 });
573 } 586 }
574 587
575 String get state { 588 String get state {
576 final currentState = node.innerHtml; 589 final currentState = node.innerHtml;
577 assert(states.indexOf(currentState, 0) >= 0); 590 assert(states.indexOf(currentState, 0) >= 0);
578 return currentState; 591 return currentState;
579 } 592 }
580 593
581 void set state(String state) { 594 void set state(String state) {
582 assert(states.indexOf(state, 0) >= 0); 595 assert(states.indexOf(state, 0) >= 0);
583 node.innerHtml = state; 596 node.innerHtml = state;
584 onChanged.fire(null); 597 onChanged.fire(null);
585 } 598 }
586 599
587 void toggle() { 600 void toggle() {
588 final oldState = state; 601 final oldState = state;
589 int index = states.indexOf(oldState, 0); 602 int index = states.indexOf(oldState, 0);
590 index = (index + 1) % states.length; 603 index = (index + 1) % states.length;
591 state = states[index]; 604 state = states[index];
592 } 605 }
593 } 606 }
594 607
595 /** 608 /**
596 * A factory that creates a view for generic items. 609 * A factory that creates a view for generic items.
597 */ 610 */
598 class ArticleViewFactory implements VariableSizeViewFactory<Article> { 611 class ArticleViewFactory implements VariableSizeViewFactory<Article> {
599 Swarm swarm; 612 Swarm swarm;
600 613
601 ArticleViewLayout layout; 614 ArticleViewLayout layout;
602 ArticleViewFactory(this.swarm) 615 ArticleViewFactory(this.swarm) : layout = ArticleViewLayout.getSingleton();
603 : layout = ArticleViewLayout.getSingleton();
604 616
605 View newView(Article item) => new ArticleView(item, swarm, layout); 617 View newView(Article item) => new ArticleView(item, swarm, layout);
606 618
607 int getWidth(Article item) => layout.width; 619 int getWidth(Article item) => layout.width;
608 int getHeight(Article item) => layout.computeHeight(item); 620 int getHeight(Article item) => layout.computeHeight(item);
609 } 621 }
610 622
611 class ArticleViewMetrics { 623 class ArticleViewMetrics {
612 final int height; 624 final int height;
613 final int titleLines; 625 final int titleLines;
(...skipping 16 matching lines...) Expand all
630 static const TOTAL_MARGIN = 16 * 2 + 70; 642 static const TOTAL_MARGIN = 16 * 2 + 70;
631 static const MIN_TITLE_HEIGHT = 36; 643 static const MIN_TITLE_HEIGHT = 36;
632 static const MAX_TITLE_LINES = 2; 644 static const MAX_TITLE_LINES = 2;
633 static const MAX_BODY_LINES = 4; 645 static const MAX_BODY_LINES = 4;
634 646
635 MeasureText measureTitleText; 647 MeasureText measureTitleText;
636 MeasureText measureBodyText; 648 MeasureText measureBodyText;
637 649
638 int width; 650 int width;
639 static ArticleViewLayout _singleton; 651 static ArticleViewLayout _singleton;
640 ArticleViewLayout() : 652 ArticleViewLayout()
641 measureBodyText = new MeasureText(BODY_FONT), 653 : measureBodyText = new MeasureText(BODY_FONT),
642 measureTitleText = new MeasureText(TITLE_FONT) { 654 measureTitleText = new MeasureText(TITLE_FONT) {
643 num screenWidth = window.screen.width; 655 num screenWidth = window.screen.width;
644 width = DESKTOP_WIDTH; 656 width = DESKTOP_WIDTH;
645 } 657 }
646 658
647 static ArticleViewLayout getSingleton() { 659 static ArticleViewLayout getSingleton() {
648 if (_singleton == null) { 660 if (_singleton == null) {
649 _singleton = new ArticleViewLayout(); 661 _singleton = new ArticleViewLayout();
650 } 662 }
651 return _singleton; 663 return _singleton;
652 } 664 }
653 665
654 int computeHeight(Article item) { 666 int computeHeight(Article item) {
655 if (item == null) { 667 if (item == null) {
656 // TODO(jacobr): find out why this is happening.. 668 // TODO(jacobr): find out why this is happening..
657 print('Null item encountered.'); 669 print('Null item encountered.');
658 return 0; 670 return 0;
659 } 671 }
660 672
661 return computeLayout(item, null, null).height; 673 return computeLayout(item, null, null).height;
662 } 674 }
663 675
664 /** 676 /**
665 * titleContainer and snippetContainer may be null in which case the size is 677 * titleContainer and snippetContainer may be null in which case the size is
666 * computed but no actual layout is performed. 678 * computed but no actual layout is performed.
667 */ 679 */
668 ArticleViewMetrics computeLayout(Article item, 680 ArticleViewMetrics computeLayout(
669 StringBuffer titleBuffer, 681 Article item, StringBuffer titleBuffer, StringBuffer snippetBuffer) {
670 StringBuffer snippetBuffer) {
671 int titleWidth = width - BODY_MARGIN_LEFT; 682 int titleWidth = width - BODY_MARGIN_LEFT;
672 683
673 if (item.hasThumbnail) { 684 if (item.hasThumbnail) {
674 titleWidth = width - TITLE_MARGIN_LEFT; 685 titleWidth = width - TITLE_MARGIN_LEFT;
675 } 686 }
676 687
677 final titleLines = measureTitleText.addLineBrokenText(titleBuffer, 688 final titleLines = measureTitleText.addLineBrokenText(
678 item.title, titleWidth, MAX_TITLE_LINES); 689 titleBuffer, item.title, titleWidth, MAX_TITLE_LINES);
679 final bodyLines = measureBodyText.addLineBrokenText(snippetBuffer, 690 final bodyLines = measureBodyText.addLineBrokenText(
680 item.textBody, width - BODY_MARGIN_LEFT, MAX_BODY_LINES); 691 snippetBuffer, item.textBody, width - BODY_MARGIN_LEFT, MAX_BODY_LINES);
681 692
682 int height = bodyLines * LINE_HEIGHT + TOTAL_MARGIN; 693 int height = bodyLines * LINE_HEIGHT + TOTAL_MARGIN;
683 694
684 if (bodyLines == 0) { 695 if (bodyLines == 0) {
685 height = 92; 696 height = 92;
686 } 697 }
687 698
688 return new ArticleViewMetrics(height, titleLines, bodyLines); 699 return new ArticleViewMetrics(height, titleLines, bodyLines);
689 } 700 }
690 } 701 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
734 // Remove the snippet entirely if it's empty. This keeps it from taking up 745 // Remove the snippet entirely if it's empty. This keeps it from taking up
735 // space and pushing the padding down. 746 // space and pushing the padding down.
736 if ((item.textBody == null) || (item.textBody.trim() == '')) { 747 if ((item.textBody == null) || (item.textBody.trim() == '')) {
737 node.querySelector('.snippet').remove(); 748 node.querySelector('.snippet').remove();
738 } 749 }
739 750
740 return node; 751 return node;
741 } 752 }
742 753
743 void afterRender(Element node) { 754 void afterRender(Element node) {
744
745 // Select this view's item. 755 // Select this view's item.
746 addOnClick((e) { 756 addOnClick((e) {
747 // Mark the item as read, so it shows as read in other views 757 // Mark the item as read, so it shows as read in other views
748 item.unread.value = false; 758 item.unread.value = false;
749 759
750 final oldArticle = swarm.state.currentArticle.value; 760 final oldArticle = swarm.state.currentArticle.value;
751 swarm.state.currentArticle.value = item; 761 swarm.state.currentArticle.value = item;
752 swarm.state.storyTextMode.value = true; 762 swarm.state.storyTextMode.value = true;
753 if (oldArticle == null) { 763 if (oldArticle == null) {
754 swarm.state.pushToHistory(); 764 swarm.state.pushToHistory();
(...skipping 29 matching lines...) Expand all
784 * article that is currently outside of the visible area. 794 * article that is currently outside of the visible area.
785 */ 795 */
786 void _updateViewForSelectedArticle() { 796 void _updateViewForSelectedArticle() {
787 Article selArticle = swarm.state.selectedArticle.value; 797 Article selArticle = swarm.state.selectedArticle.value;
788 if (swarm.state.hasArticleSelected) { 798 if (swarm.state.hasArticleSelected) {
789 // Ensure that the selected article is visible in the view. 799 // Ensure that the selected article is visible in the view.
790 if (!swarm.state.inMainView) { 800 if (!swarm.state.inMainView) {
791 // Story View. 801 // Story View.
792 swarm.frontView.detachedView.itemsView.showView(selArticle); 802 swarm.frontView.detachedView.itemsView.showView(selArticle);
793 } else { 803 } else {
794 if(swarm.frontView.currentSection.inCurrentView(selArticle)) { 804 if (swarm.frontView.currentSection.inCurrentView(selArticle)) {
795 // Scroll horizontally if needed. 805 // Scroll horizontally if needed.
796 swarm.frontView.currentSection.dataSourceView.showView( 806 swarm.frontView.currentSection.dataSourceView
797 selArticle.dataSource); 807 .showView(selArticle.dataSource);
798 DataSourceView dataView = swarm.frontView.currentSection 808 DataSourceView dataView =
799 .findView(selArticle.dataSource); 809 swarm.frontView.currentSection.findView(selArticle.dataSource);
800 if(dataView != null) { 810 if (dataView != null) {
801 dataView.itemsView.showView(selArticle); 811 dataView.itemsView.showView(selArticle);
802 } 812 }
803 } 813 }
804 } 814 }
805 } 815 }
806 } 816 }
807 817
808 String getDataUriForImage(final img) { 818 String getDataUriForImage(final img) {
809 // TODO(hiltonc,jimhug) eval perf of this vs. reusing one canvas element 819 // TODO(hiltonc,jimhug) eval perf of this vs. reusing one canvas element
810 final CanvasElement canvas = new CanvasElement( 820 final CanvasElement canvas =
811 height: img.height, width: img.width); 821 new CanvasElement(height: img.height, width: img.width);
812 822
813 final CanvasRenderingContext2D ctx = canvas.getContext("2d"); 823 final CanvasRenderingContext2D ctx = canvas.getContext("2d");
814 ctx.drawImage(img, 0, 0, img.width, img.height); 824 ctx.drawImage(img, 0, 0, img.width, img.height);
815 825
816 return canvas.toDataUrl("image/png"); 826 return canvas.toDataUrl("image/png");
817 } 827 }
818 828
819 /** 829 /**
820 * Update this view's selected appearance based on the currently selected 830 * Update this view's selected appearance based on the currently selected
821 * Article. 831 * Article.
(...skipping 19 matching lines...) Expand all
841 final Swarm swarm; 851 final Swarm swarm;
842 final Article item; 852 final Article item;
843 853
844 View _pagedStory; 854 View _pagedStory;
845 855
846 StoryContentView(this.swarm, this.item) : super(); 856 StoryContentView(this.swarm, this.item) : super();
847 857
848 get childViews => [_pagedStory]; 858 get childViews => [_pagedStory];
849 859
850 Element render() { 860 Element render() {
851 final storyContent = new Element.html( 861 final storyContent =
852 '<div class="story-content">${item.htmlBody}</div>'); 862 new Element.html('<div class="story-content">${item.htmlBody}</div>');
853 for (Element element in storyContent.querySelectorAll( 863 for (Element element in storyContent.querySelectorAll(
854 "iframe, script, style, object, embed, frameset, frame")) { 864 "iframe, script, style, object, embed, frameset, frame")) {
855 element.remove(); 865 element.remove();
856 } 866 }
857 _pagedStory = new PagedContentView(new View.fromNode(storyContent)); 867 _pagedStory = new PagedContentView(new View.fromNode(storyContent));
858 868
859 // Modify all links to open in new windows.... 869 // Modify all links to open in new windows....
860 // TODO(jacobr): would it be better to add an event listener on click that 870 // TODO(jacobr): would it be better to add an event listener on click that
861 // intercepts these instead? 871 // intercepts these instead?
862 for (AnchorElement anchor in storyContent.querySelectorAll('a')) { 872 for (AnchorElement anchor in storyContent.querySelectorAll('a')) {
(...skipping 26 matching lines...) Expand all
889 class SectionView extends CompositeView { 899 class SectionView extends CompositeView {
890 final Section section; 900 final Section section;
891 final Swarm swarm; 901 final Swarm swarm;
892 final DataSourceViewFactory _viewFactory; 902 final DataSourceViewFactory _viewFactory;
893 final View loadingText; 903 final View loadingText;
894 ListView<Feed> dataSourceView; 904 ListView<Feed> dataSourceView;
895 PageNumberView pageNumberView; 905 PageNumberView pageNumberView;
896 final PageState pageState; 906 final PageState pageState;
897 907
898 SectionView(this.swarm, this.section, this._viewFactory) 908 SectionView(this.swarm, this.section, this._viewFactory)
899 : super('section-view'), 909 : super('section-view'),
900 loadingText = new View.html('<div class="loading-section"></div>'), 910 loadingText = new View.html('<div class="loading-section"></div>'),
901 pageState = new PageState() { 911 pageState = new PageState() {
902 addChild(loadingText); 912 addChild(loadingText);
903 } 913 }
904 914
905 /** 915 /**
906 * Hides the loading text, reloads the data sources, and shows them. 916 * Hides the loading text, reloads the data sources, and shows them.
907 */ 917 */
908 void showSources() { 918 void showSources() {
909 loadingText.node.style.display = 'none'; 919 loadingText.node.style.display = 'none';
910 920
911 // Lazy initialize the data source view. 921 // Lazy initialize the data source view.
912 if (dataSourceView == null) { 922 if (dataSourceView == null) {
913 // TODO(jacobr): use named arguments when available. 923 // TODO(jacobr): use named arguments when available.
914 dataSourceView = new ListView<Feed>( 924 dataSourceView = new ListView<Feed>(
915 section.feeds, _viewFactory, 925 section.feeds,
926 _viewFactory,
916 true /* scrollable */, 927 true /* scrollable */,
917 false /* vertical */, 928 false /* vertical */,
918 null /* selectedItem */, 929 null /* selectedItem */,
919 true /* snapToItems */, 930 true /* snapToItems */,
920 true /* paginate */, 931 true /* paginate */,
921 true /* removeClippedViews */, 932 true /* removeClippedViews */,
922 false, /* showScrollbar */ 933 false,
934 /* showScrollbar */
923 pageState); 935 pageState);
924 dataSourceView.addClass("data-source-view"); 936 dataSourceView.addClass("data-source-view");
925 addChild(dataSourceView); 937 addChild(dataSourceView);
926 938
927 pageNumberView = addChild(new PageNumberView(pageState)); 939 pageNumberView = addChild(new PageNumberView(pageState));
928 940
929 node.style.opacity = '1'; 941 node.style.opacity = '1';
930 } else { 942 } else {
931 addChild(dataSourceView); 943 addChild(dataSourceView);
932 addChild(pageNumberView); 944 addChild(pageNumberView);
(...skipping 30 matching lines...) Expand all
963 * [Feed]. 975 * [Feed].
964 */ 976 */
965 DataSourceView findView(Feed dataSource) { 977 DataSourceView findView(Feed dataSource) {
966 return dataSourceView.getSubview(dataSourceView.findIndex(dataSource)); 978 return dataSourceView.getSubview(dataSourceView.findIndex(dataSource));
967 } 979 }
968 980
969 bool inCurrentView(Article article) { 981 bool inCurrentView(Article article) {
970 return dataSourceView.findIndex(article.dataSource) != null; 982 return dataSourceView.findIndex(article.dataSource) != null;
971 } 983 }
972 } 984 }
OLDNEW
« no previous file with comments | « samples-dev/swarm/SwarmState.dart ('k') | samples-dev/swarm/UIState.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698