| Index: client/web/model.dart
|
| diff --git a/client/web/model.dart b/client/web/model.dart
|
| index 87401a2c5ee5fde847759ed6704c5ddca817ba38..a45197bfbd4995ad24ef017f548b6530ad236122 100644
|
| --- a/client/web/model.dart
|
| +++ b/client/web/model.dart
|
| @@ -7,50 +7,86 @@ import 'dart:html' as html;
|
| import 'dart:json';
|
| import 'ast.dart';
|
|
|
| +// TODO(jacobr): specify the version # in the JSON file.
|
| String svnRevisionNumber = "15605";
|
|
|
| -String _activeReferenceId;
|
| +/**
|
| + * Reference id of [currentElement].
|
| + *
|
| + * Stored in addition to [currentElement] as [currentElement] may
|
| + * not yet be available if the data model for the library it is part of has
|
| + * not yet been loaded.
|
| + */
|
| +String _currentReferenceId;
|
|
|
| -/// Current state of the application.
|
| +/**
|
| + * Current library the user is browsing if any.
|
| + */
|
| LibraryElement currentLibrary;
|
| +
|
| +/**
|
| + * Current type the user is viewing if any.
|
| + * Should be either a [ClassElement] or a [TypedefElement].
|
| + */
|
| Element currentType;
|
| +/**
|
| + * Current member of either [currentLibrary] or [currentType] that the user is
|
| + * viewing.
|
| + */
|
| Element currentMember;
|
| +
|
| +/**
|
| + * Element corresponding to [_currentReferenceId].
|
| + * The most specific element of [currentLibrary]. [currentType], and
|
| + * [currentMember].
|
| + */
|
| Element currentElement;
|
|
|
| +/**
|
| + * Recomputes the Elements part of the current active state from the data model.
|
| + *
|
| + * This method should be invoked after additional libraries are loaded from the
|
| + * server or after the user navigates to a different element in the UI.
|
| + */
|
| void _recomputeActiveState() {
|
| currentLibrary = null;
|
| currentType = null;
|
| currentMember = null;
|
| currentElement = null;
|
| - if (_activeReferenceId != null) {
|
| - var path = lookupReferenceId(_activeReferenceId).path;
|
| -
|
| - if (path.length > 0) {
|
| - currentLibrary = path[0];
|
| - }
|
| - if (path.length > 1) {
|
| - if (path[1] is ClassElement || path[1] is TypedefElement) {
|
| - currentType = path[1];
|
| - if (path.length > 2) {
|
| - currentMember = path[2];
|
| + if (_currentReferenceId != null) {
|
| + var referenceElement = lookupReferenceId(_currentReferenceId);
|
| + if (referenceElement != null) {
|
| + var path = referenceElement.path;
|
| + if (path.length > 0) {
|
| + currentLibrary = path[0];
|
| + }
|
| + if (path.length > 1) {
|
| + if (path[1] is ClassElement || path[1] is TypedefElement) {
|
| + currentType = path[1];
|
| + if (path.length > 2) {
|
| + currentMember = path[2];
|
| + }
|
| + } else {
|
| + currentMember = path[1];
|
| }
|
| + }
|
| + if (currentMember != null) {
|
| + currentElement = currentMember;
|
| + } else if (currentType != null) {
|
| + currentElement = currentType;
|
| } else {
|
| - currentMember = path[1];
|
| + currentElement = currentLibrary;
|
| }
|
| }
|
| - if (currentMember != null) {
|
| - currentElement = currentMember;
|
| - } else if (currentType != null) {
|
| - currentElement = currentType;
|
| - } else {
|
| - currentElement = currentLibrary;
|
| - }
|
| }
|
| }
|
|
|
| +/**
|
| + * Scrolls the [currentElement] into view.
|
| + */
|
| void scrollIntoView() {
|
| // TODO(jacobr): there should be a cleaner way to run code that executes
|
| - // after the UI updates.
|
| + // after the UI updates. https://github.com/dart-lang/web-ui/issues/188
|
| html.window.setTimeout(() {
|
| if (currentElement != null) {
|
| for (var e in html.queryAll('[data-id="${currentElement.id}"]')) {
|
| @@ -60,7 +96,10 @@ void scrollIntoView() {
|
| }, 0);
|
| }
|
|
|
| -onDataModelChanged() {
|
| +/**
|
| + * Invoke every time the data model changes.
|
| + */
|
| +void _onDataModelChanged() {
|
| _recomputeActiveState();
|
| scrollIntoView();
|
| }
|
| @@ -70,7 +109,7 @@ onDataModelChanged() {
|
| * etc.
|
| */
|
| String kindCssClass(Element element) {
|
| - String classes = 'kind kind-${normalizedKind(element)}';
|
| + String classes = 'kind kind-${_normalizedKind(element)}';
|
| if (element.isPrivate == true) {
|
| classes = '$classes private';
|
| } else if (element is MethodElementBase && element.isStatic) {
|
| @@ -89,12 +128,7 @@ String kindCssClass(Element element) {
|
| return classes;
|
| }
|
|
|
| -String normalizedKind(obj) {
|
| - if (obj is Element) return normalizedKindFromElement(obj);
|
| - return obj;
|
| -}
|
| -
|
| -String normalizedKindFromElement(Element element) {
|
| +String _normalizedKind(Element element) {
|
| var kind = element.kind;
|
| var name = element.name;
|
| if (kind == 'method' && element.isOperator) {
|
| @@ -108,7 +142,7 @@ String normalizedKindFromElement(Element element) {
|
| }
|
|
|
| String toUserVisibleKind(Element element) {
|
| - return KIND_TITLES[normalizedKind(element)];
|
| + return KIND_TITLES[_normalizedKind(element)];
|
| }
|
|
|
| /**
|
| @@ -116,6 +150,8 @@ String toUserVisibleKind(Element element) {
|
| */
|
| String permalink(var obj) {
|
| var data = {'id': obj.refId};
|
| + // TODO(jacobr): evaluate whether the persistent UI state will stay just a
|
| + // single reference ID in which case this is overkill.
|
| return "#!${JSON.stringify(data)}";
|
| }
|
|
|
| @@ -131,7 +167,7 @@ void loadStateFromUrl() {
|
| // TODO(jacobr): redirect to default page or better yet attempt to fixup.
|
| }
|
| }
|
| - _activeReferenceId = data['id'];
|
| + _currentReferenceId = data['id'];
|
| _recomputeActiveState();
|
| scrollIntoView();
|
| }
|
| @@ -150,37 +186,20 @@ Future loadModel() {
|
| md.setImplicitLinkResolver(_resolveNameReference);
|
| var completer = new Completer();
|
| // TODO(jacobr): shouldn't have to get this from the parent directory.
|
| - new html.HttpRequest.get('../static/apidoc.json', onSuccess(html.HttpRequest req) {
|
| + new html.HttpRequest.get('../static/apidoc.json', (req) {
|
| for (var libraryJson in JSON.parse(req.responseText)) {
|
| var library = new LibraryElement(libraryJson, null);
|
| libraries[library.id] = library;
|
| }
|
| - onDataModelChanged();
|
| + _onDataModelChanged();
|
| completer.complete(true);
|
| });
|
| return completer.future;
|
| }
|
|
|
| -/** XXX NOT USED TODO(jacobr) remove.
|
| -class DocComment {
|
| - final String text;
|
| -
|
| - /**
|
| - * Non-null if the comment is inherited from another declaration.
|
| - */
|
| - final inheritedFrom; // InterfaceMirror?
|
| -
|
| - DocComment(this.text, [this.inheritedFrom = null]) {
|
| - assert(text != null && !text.trim().isEmpty);
|
| - }
|
| -
|
| - SafeHtml get html => new SafeHtml.unsafe(md.markdownToHtml(text));
|
| -
|
| - String toString() => text;
|
| -}
|
| -
|
| -*/
|
| -
|
| +// TODO(jacobr): remove this method and resolve refences to types in the json
|
| +// generation. That way the existing correct logic in Dart2Js can be used rather
|
| +// than this rather busted logic.
|
| /**
|
| * This will be called whenever a doc comment hits a `[name]` in square
|
| * brackets. It will try to figure out what the name refers to and link or
|
| @@ -209,9 +228,11 @@ md.Node _resolveNameReference(String name) {
|
| }
|
|
|
| // See if it's another member of the current type.
|
| - // TODO(jacobr): fixme. this is wrong... members are by id now not simple string name...
|
| + // TODO(jacobr): fixme. this is wrong... members are by id now not simple
|
| + // string name...
|
| if (currentType != null) {
|
| - final foundMember = currentType.members[name];
|
| + // TODO(jacobr): this should be foundMember = currentType.members[name];
|
| + final foundMember = null;
|
| if (foundMember != null) {
|
| return makeLink(permalink(foundMember));
|
| }
|
| @@ -243,7 +264,8 @@ md.Node _resolveNameReference(String name) {
|
| if (match == null) return null;
|
| var foundType = currentLibrary.classes[match[1]];
|
| if (foundType == null) return null;
|
| - var foundMember = foundType.members[match[2]];
|
| + // TODO(jacobr): should be foundMember = foundType.members[match[2]];
|
| + var foundMember = null;
|
| if (foundMember == null) return null;
|
| return makeLink(permalink(foundMember));
|
| })();
|
| @@ -255,7 +277,8 @@ md.Node _resolveNameReference(String name) {
|
| }
|
|
|
| // See if it's a top-level member in the current library.
|
| - var foundMember = currentLibrary.members[name];
|
| + // TODO(jacobr): should be foundMember = currentLibrary.members[name];
|
| + var foundMember = null;
|
| if (foundMember != null) {
|
| return makeLink(permalink(foundMember));
|
| }
|
|
|