Commit 099ac066 authored by Laurent Wouters's avatar Laurent Wouters
Browse files

Refactored the rendering process in preparation of language selection

parent f15b54e53aa2
......@@ -321,6 +321,7 @@ export class TabCommand {
this.isAutomatic = true;
this.selectedSource = "";
this.selectedView = "";
this.selectedLanguage = "";
}
/**
* Whether the user activated the extension for this tab
......@@ -338,6 +339,10 @@ export class TabCommand {
* The identifier of the selected view (if not automatic)
*/
selectedView: string;
/**
* The selected language (if not automatic)
*/
selectedLanguage: string;
/**
* Updates this command with the specified one
......@@ -400,6 +405,7 @@ export class TabData {
this.command.isAutomatic = true;
this.command.selectedSource = "";
this.command.selectedView = "";
this.command.selectedLanguage = "";
this.mainSource = NO_DATA;
this.sources = [];
this.primaryTopic = null;
......
......@@ -19,8 +19,12 @@
******************************************************************************/
import * as $rdf from "rdflib";
import { definition, application, implementation } from "@logilab/libview";
import { definition, implementation } from "@logilab/libview";
import { DEFAULT_DESCRIPTOR_TRIPLES } from "./view-defaults";
import {
ViewRenderer,
RenderingContext
} from "@logilab/libview/build/lib/application";
export class RdfTriplesRendering implements implementation.ViewImplementation {
descriptor: definition.ViewDescriptor;
......@@ -36,9 +40,8 @@ export class RdfTriplesRendering implements implementation.ViewImplementation {
}
render(
renderer: application.ViewRenderer,
store: $rdf.Formula,
root: string,
renderer: ViewRenderer,
context: RenderingContext,
target: string
): HTMLElement {
let result = document.createElement("div");
......@@ -74,7 +77,7 @@ export class RdfTriplesRendering implements implementation.ViewImplementation {
thead.appendChild(tr);
table.appendChild(thead);
let tbody = document.createElement("tbody");
store.statements
context.store.statements
.sort(
(a: $rdf.Statement, b: $rdf.Statement): number => {
var r = a.subject.value.localeCompare(b.subject.value);
......@@ -85,7 +88,7 @@ export class RdfTriplesRendering implements implementation.ViewImplementation {
}
)
.map((triple: $rdf.Statement) => {
tbody.appendChild(renderRdfTriple(renderer, triple));
tbody.appendChild(renderRdfTriple(context, triple));
});
table.appendChild(tbody);
result.appendChild(table);
......@@ -95,18 +98,18 @@ export class RdfTriplesRendering implements implementation.ViewImplementation {
}
function renderRdfTriple(
renderer: application.ViewRenderer,
context: RenderingContext,
triple: $rdf.Statement
): HTMLElement {
let tr = document.createElement("tr");
tr.appendChild(renderRdfNode(renderer, triple.subject));
tr.appendChild(renderRdfNode(renderer, triple.predicate));
tr.appendChild(renderRdfNode(renderer, triple.object));
tr.appendChild(renderRdfNode(context, triple.subject));
tr.appendChild(renderRdfNode(context, triple.predicate));
tr.appendChild(renderRdfNode(context, triple.object));
return tr;
}
function renderRdfNode(
renderer: application.ViewRenderer,
context: RenderingContext,
node: $rdf.Node
): HTMLElement {
let result = document.createElement("td");
......@@ -120,7 +123,7 @@ function renderRdfNode(
sub.href = nodeIRI.uri;
sub.onclick = (event: Event) => {
event.preventDefault();
renderer.onMoveTo(nodeIRI.uri);
context.event.onRequestNavigateTo(nodeIRI.uri);
return false;
};
sub.appendChild(document.createTextNode(nodeIRI.uri));
......
......@@ -30,7 +30,10 @@ import {
import { loadRdfStore } from "../common/rdf";
import "chrome";
import { application, definition, implementation } from "@logilab/libview";
import * as $rdf from "rdflib";
import {
RenderingContext,
ViewRenderer
} from "@logilab/libview/build/lib/application";
require("../common/view-defaults-impl");
/**
......@@ -51,14 +54,29 @@ function onUpdateActivate(tabData: TabData): void {
.then((registry: definition.ViewRegistry) => {
currentApp.registry = registry;
implementation
.newRenderer(
currentApp,
registry,
getResourceContent,
tabData.command.isAutomatic ? null : tabData.command.selectedView
)
.newRenderer(registry, getResourceContent)
.then((renderer: application.ViewRenderer) => {
currentApp.onContent(renderer, store, tabData.primaryTopic);
let context = {
event: {
onRequestNavigateTo: function(uri: string) {
getTabId().then((tabId: number) => {
onNavigateTabTo(tabId, uri);
});
}
},
root: tabData.primaryTopic,
store: store,
options: {}
} as RenderingContext;
context.options[tabData.primaryTopic] = {
view: tabData.command.isAutomatic
? null
: tabData.command.selectedView,
language: tabData.command.isAutomatic
? null
: tabData.command.selectedLanguage
};
currentApp.onContent(renderer, context);
})
.catch((reason: any) => {
currentApp.onError(reason.toString());
......@@ -102,8 +120,7 @@ enum StateType {
class State {
stateType: StateType;
message: string;
content: $rdf.Formula;
root: string;
context: RenderingContext;
}
/**
......@@ -118,8 +135,7 @@ class MainViewer implements application.Application {
this.state = {
stateType: StateType.Loading,
message: "Loading",
content: null,
root: null
context: null
};
this.registry = null;
this.renderer = null;
......@@ -140,17 +156,12 @@ class MainViewer implements application.Application {
* @param content The content
* @param root The URI of the root resource
*/
public onContent(
renderer: application.ViewRenderer,
content: $rdf.Formula,
root: string
): void {
public onContent(renderer: ViewRenderer, context: RenderingContext): void {
this.renderer = renderer;
this.state = {
stateType: StateType.Displaying,
message: "",
content: content,
root: root
context: context
};
this.onUpdate();
}
......@@ -163,8 +174,7 @@ class MainViewer implements application.Application {
this.state = {
stateType: StateType.Error,
message: description,
content: null,
root: null
context: null
};
this.onUpdate();
}
......@@ -207,9 +217,8 @@ class MainViewer implements application.Application {
sub.appendChild(div);
} else if (this.state.stateType == StateType.Displaying) {
let result = this.renderer.render(
this.state.content,
this.state.root,
this.state.root
this.state.context,
this.state.context.root
);
if (result == null || result == undefined) {
let div = document.createElement("div");
......
......@@ -35,40 +35,84 @@ export interface ViewRendering {
}
/**
* A renderer for an application
* The user events that can occur in a rendered view
*/
export interface ViewRenderer {
export interface UserEvents {
/**
* Reacts to a user clicking on a link to a new resource
* @param uri The uri of the resource
*/
onMoveTo(uri: string): void;
onRequestNavigateTo(uri: string): void;
}
/**
* The options (command) for the renderer for a particular target
*/
export interface TargetRenderingOptions {
/**
* The identifier of the view to be used for the rendering
*/
view?: string;
/**
* The language to use
*/
language?: string;
}
/**
* The options (command) for the renderer per targets
*/
export interface RenderingOptions {
/**
* The rendering options per target
*/
[target: string]: TargetRenderingOptions;
}
/**
* Represents the context of a rendering
*/
export interface RenderingContext {
/**
* The RDF store holding the data to be rendered
*/
store: $rdf.Formula;
/**
* The root resource
*/
root: string;
/**
* The current rendering options
*/
options: RenderingOptions;
/**
* The handler of user events
*/
event: UserEvents;
}
/**
* A renderer for an application
*/
export interface ViewRenderer {
/**
* Renders a resource belonging to an RDF store
* @param store The RDF store holding the data to be rendered
* @param root The root resource
* @param context The context for the rendering
* @param target The target resource for this view
*/
render(store: $rdf.Formula, root: string, target: string): ViewRendering;
render(context: RenderingContext, target: string): ViewRendering;
}
/**
* The public interface for the application
*/
export interface Application {
/**
* Reacts to a user clicking on a link to a new resource
* @param uri The uri of the resource
*/
onMoveTo(uri: string): void;
/**
* Sets the content for the application
* @param content The content
* @param root The URI of the root resource
* @param renderer The renderer to use
* @param context The context for the rendering
*/
onContent(renderer: ViewRenderer, content: $rdf.Formula, root: string): void;
onContent(renderer: ViewRenderer, context: RenderingContext): void;
/**
* Sets the application on error
......
......@@ -19,7 +19,11 @@
******************************************************************************/
import * as $rdf from "rdflib";
import { ViewRenderer, Application, ViewRendering } from "./application";
import {
ViewRenderer,
ViewRendering,
RenderingContext
} from "./application";
import {
ViewDescriptor,
ViewRegistry,
......@@ -44,14 +48,12 @@ export interface ViewImplementation {
/**
* Renders a resource belonging to an RDF store
* @param renderer The parent renderer
* @param store The RDF store holding the data to be rendered
* @param root The root resource
* @param context The current rendering context
* @param target The target resource for this view
*/
render(
renderer: ViewRenderer,
store: $rdf.Formula,
root: string,
context: RenderingContext,
target: string
): HTMLElement;
}
......@@ -219,27 +221,14 @@ function resolveViewFor(
class ViewRendererImpl implements ViewRenderer {
/**
* Initializes a renderer
* @param application The parent application
* @param registry The registry to use
* @param implementations The view implementations
* @param forceView Forces the selection of a specific view
*/
constructor(
application: Application,
registry: ViewRegistry,
implementations: ViewImplementations,
forceView: string = null
) {
this.application = application;
constructor(registry: ViewRegistry, implementations: ViewImplementations) {
this.registry = registry;
this.implementations = implementations;
this.forceView = forceView;
}
/**
* The parent application
*/
application: Application;
/**
* The registry to use
*/
......@@ -248,41 +237,34 @@ class ViewRendererImpl implements ViewRenderer {
* The view implementations
*/
implementations: ViewImplementations;
/**
* Forces the selection of a specific view
*/
forceView: string;
/**
* Reacts to a user clicking on a link to a new resource
* @param uri The uri of the resource
*/
onMoveTo(uri: string): void {
this.application.onMoveTo(uri);
}
/**
* Renders a resource belonging to an RDF store
* @param store The RDF store holding the data to be rendered
* @param root The root resource
* @param context The context for the rendering
* @param target The target resource for this view
*/
render(store: $rdf.Formula, root: string, target: string = root): ViewRendering {
render(context: RenderingContext, target: string): ViewRendering {
var view = null;
if (this.forceView != null && this.forceView != "") {
let options = context.options[target];
if (
options != null &&
options != undefined &&
options.view != undefined &&
options.view != undefined
) {
// try to use the forced view
view = this.implementations[this.forceView];
view = view = this.implementations[options.view];
}
if (view == null || view == undefined) {
// try to resolve a view
view = resolveViewFor(this.implementations, store, target);
view = resolveViewFor(this.implementations, context.store, target);
}
if (view == null || view == undefined) {
// cannot resolve a view ...
return null;
}
return {
dom: view.render(this, store, root, target),
dom: view.render(this, context, target),
viewId: view.descriptor.identifier
};
}
......@@ -290,16 +272,12 @@ class ViewRendererImpl implements ViewRenderer {
/**
* Creates a new view renderer
* @param application The current application
* @param registry The view registry to use
* @param resolver The content resolver to use
* @param forceView Forces the selection of a specific view
*/
export function newRenderer(
application: Application,
registry: ViewRegistry,
resolver: ViewResourceContentResolver,
forceView: string = null
resolver: ViewResourceContentResolver
): Promise<ViewRenderer> {
return new Promise<ViewRenderer>(
(
......@@ -308,12 +286,7 @@ export function newRenderer(
) => {
loadImplementations(registry, resolver).then(
(impls: ViewImplementations) => {
let renderer = new ViewRendererImpl(
application,
registry,
impls,
forceView
);
let renderer = new ViewRendererImpl(registry, impls);
resolve(renderer);
}
);
......
......@@ -29,6 +29,10 @@ import * as $rdf from "rdflib";
import Vue from "vue";
/// <reference path="./vue.d.ts" />
import PersonImpl from "./PersonImpl.vue";
import {
ViewRenderer,
RenderingContext
} from "@logilab/libview/build/lib/application";
/**
* The descritptor for the default Dbpedia person view
......@@ -123,12 +127,11 @@ class FoaFPersonRendering implements implementation.ViewImplementation {
}
render(
renderer: application.ViewRenderer,
store: $rdf.Formula,
root: string,
renderer: ViewRenderer,
context: RenderingContext,
target: string
): HTMLElement {
let person = loadPerson(store, target);
let person = loadPerson(context.store, target);
let result = document.createElement("div");
let vm = new Vue({
data: {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment