Skip to content

Commit a7651a0

Browse files
committed
Merge branch 'gh-pages' of https://github.com/LivelyKernel/lively4-core into gh-pages
2 parents f25c047 + 9dfeb7d commit a7651a0

25 files changed

+864
-152
lines changed
523 KB
Loading

doc/journal/2021-02-24.md/index.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
## 2021-02-24
2+
*Author: @JensLincke*
3+
4+
5+
![](generate_drawio_content.png)
6+
7+
### Reverse Engineering
8+
9+
Copy some drawio content and past it into a workspace...
10+
11+
```javascript
12+
import XML from "src/client/xml.js"
13+
14+
lively.get("#drawiosource").value = XML.prettify(decodeURIComponent(
15+
lively.get("#drawiocode").value))
16+
```
17+
18+
That produces some source... and copy and pasting it back into drawio produced actual graphical content.
19+
20+
```javascript
21+
<mxGraphModel>
22+
<root>
23+
<mxCell id="0"/>
24+
<mxCell id="1" parent="0"/>
25+
<UserObject label="[@Olsen2007EUI]" id="2">
26+
<mxCell style="text;whiteSpace=wrap;html=1;fontSize=12;fontColor=#000000;" vertex="1" parent="1">
27+
<mxGeometry x="240" y="220" width="100" height="30" as="geometry"/>
28+
</mxCell>
29+
</UserObject>
30+
<UserObject label="[@Hoho]" id="3">
31+
<mxCell style="text;whiteSpace=wrap;html=1;fontSize=12;fontColor=#000000;" vertex="1" parent="1">
32+
<mxGeometry x="250" y="270" width="100" height="30" as="geometry"/>
33+
</mxCell>
34+
</UserObject>
35+
</root>
36+
</mxGraphModel>
37+
```
38+
39+
### Generating Draw.io Content
40+
41+
So, we can actually generate content
42+
43+
44+
```javascript
45+
46+
var source = `<mxGraphModel>
47+
<root>
48+
<mxCell id="0"/>
49+
<mxCell id="1" parent="0"/>`
50+
51+
var idCounter = 3;
52+
that.childNodes.forEach((ea,index) => {
53+
source += `<UserObject label="[@${ea.key}] ${ea.getAuthors()[0]} ${ea.year}. ${ea.title} " id="${idCounter++}">
54+
<mxCell style="text;whiteSpace=wrap;html=1;fontSize=12;fontColor=#000000;" vertex="1" parent="1">
55+
<mxGeometry x="250" y="${30 *index}" width="600" height="40" as="geometry"/>
56+
</mxCell>
57+
</UserObject>`
58+
59+
})
60+
61+
source += ` </root>
62+
</mxGraphModel>`
63+
64+
65+
```

src/client/fileindex.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -770,7 +770,8 @@ export default class FileIndex {
770770
}).then(r => r.clone().json())
771771

772772
if (!stats.error) {
773-
await this.addFile(url, stats.name, stats.type, stats.size, stats.modified)
773+
let name = url.replace(/.*\//,"")
774+
await this.addFile(url, name, stats.type, stats.size, stats.modified)
774775
}
775776
}
776777

src/client/html.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,13 @@ export default class HTML {
216216
if (node.getAttribute) {
217217

218218
var href = node.getAttribute("href")
219+
if (!href) {
220+
href = node.getAttribute("xlink:href")
221+
if (href) {
222+
var isXLink = true;
223+
}
224+
}
225+
219226
if (href) {
220227
// console.log("FIX LINK ", href)
221228
// #TODO load inplace....

src/client/lively.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1481,6 +1481,7 @@ export default class Lively {
14811481

14821482
return containerPromise.then(comp => {
14831483
if (existingFound) {
1484+
comp.parentElement.focus();
14841485
comp.focus();
14851486
return;
14861487
}

src/client/protocols/bib.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ export class BibScheme extends BibliographyScheme {
2121
var entry = entries[0] || {authors: undefined, keywords: undefined, title: ""}
2222
var key = query
2323
var files = await FileIndex.current().db.files.where("bibkey").equals(key).toArray()
24+
var literatureNotes = await FileIndex.current().db.files
25+
.filter( ea => ea.name.match(key + ".md")).toArray()
26+
2427

2528
var papers = await Literature.db.papers.where("key").equals(key).toArray()
2629

@@ -43,7 +46,7 @@ export class BibScheme extends BibliographyScheme {
4346
if (entry.source) {
4447
content += "<pre>" + entry.source+ "</pre>"
4548
}
46-
content += "<h3>Documents</h3><ul>" + files.map(ea => {
49+
content += "<h3>Documents</h3><ul>" + (files.concat(literatureNotes)).map(ea => {
4750
return `<li><a href="${ea.url}">${ea.name}</a></li>`
4851
}).join("\n") + "</ul>"
4952

src/client/reactive/active-expression/active-expression.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ export const AExprRegistry = {
8181
},
8282

8383
eventListeners() {
84+
if(!this.listeners) return [];
8485
this.listeners = this.listeners.filter(listener => listener.reference);
8586
return this.listeners;
8687
}

src/client/reactive/components/basic/aexpr-timeline.html

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,34 +12,63 @@
1212
#content {
1313
background-color: gray;
1414
}
15+
td {
16+
border: 1px solid black;
17+
padding: 3px;
18+
}
19+
th {
20+
border: 2px solid black;
21+
padding: 2px;
22+
text-align: center;
23+
}
24+
#valuesOverTime {
25+
width: 100%;
26+
border-spacing: 0px;
27+
}
1528
.container {
1629
display: grid;
17-
grid-template-rows: auto 1fr auto;
30+
grid-template-rows: 1fr 3fr auto;
1831
align-items:stretch;
1932
justify-items:stretch;
2033
height: 100%;
34+
overflow: hidden;
2135
}
2236
.row {
2337
display: grid;
2438
grid-template-columns: 1fr 1fr;
2539
align-items:stretch;
2640
justify-items:stretch;
2741
width: 100%;
42+
overflow-y: hidden;
2843
}
2944
.pane {
3045
margin: 1px;
3146
border: 1px solid #d5d5d5;
47+
overflow-y: auto;
48+
}
49+
.variable {
50+
color: #0000FF
3251
}
3352
</style>
3453

3554
<div class="container">
3655
<div class="row">
37-
<div id="aeOverview" class="pane"></div>
38-
<div>
39-
Values over time
56+
<div class="pane">
57+
<h3> AE Overview </h3>
58+
<div id="aeOverview"></div>
59+
</div>
60+
<div class="pane">
61+
<h3> Values over time </h3>
62+
<table id="valuesOverTime">
63+
</table>
64+
Filter: <span class="variable">event</span> => {<input id="filterInput">}
65+
<button id="filterButton">Filter</button>
4066
</div>
4167
</div>
42-
<div id="diagram" class="pane"></div>
68+
<div class="pane">
69+
<h3> Timeline </h3>
70+
<div id="diagram"></div>
71+
</div>
4372
<div id="footer" class="pane">
4473
<p class="infos">
4574
<span id="numberEvents"></span> events <span class="light">found between</span> <br />

src/client/reactive/components/basic/aexpr-timeline.js

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -106,31 +106,44 @@ export default class EventDrops extends Morph {
106106
"themes": { "icons": false }
107107
}
108108
});
109-
109+
110110
this.aeChangedDebounced = (() => this.setAexprs(this.getDataFromSource())).debounce(10, 300);
111111
this.eventsChangedDebounced = (() => this.updateTimeline(this.getDataFromSource())).debounce(100, 1000);
112112
this.activeExpressionsChanged();
113113
//Register to AE changes
114114
AExprRegistry.addEventListener(this, (ae, event) => {
115-
if(event.type === "created" || event.type === "disposed") {
116-
this.activeExpressionsChanged()
115+
if (event.type === "created" || event.type === "disposed") {
116+
this.activeExpressionsChanged();
117117
} else {
118-
this.eventsChanged()
118+
this.eventsChanged();
119119
}
120120
});
121121
//Register to overview selection changes
122122
jQuery(this.aeOverview).on("changed.jstree", (e, data) => {
123123
this.eventsChanged();
124-
})
124+
}
125125
//Register to grouping change
126-
this.groupByLine.addEventListener('change', () => {
126+
);this.groupByLine.addEventListener('change', () => {
127127
if (this.groupByLine.checked) {
128128
this.groupingFunction = this.locationGrouping();
129129
} else {
130130
this.groupingFunction = this.instanceGrouping();
131131
}
132132
this.eventsChanged();
133133
});
134+
//Register to filter changes
135+
this.filterFunction = () => true;
136+
this.filterButton.addEventListener('click', () => {
137+
const inputValue = this.filterInput.value;
138+
if (!inputValue) {
139+
this.filterFunction = () => true;
140+
} else {
141+
this.filterFunction = event => {
142+
return eval(inputValue);
143+
};
144+
}
145+
this.eventsChanged();
146+
});
134147
}
135148

136149
humanizeEventData(event) {
@@ -178,7 +191,6 @@ export default class EventDrops extends Morph {
178191
getGroupingFunction() {
179192
return this.groupingFunction || this.locationGrouping();
180193
}
181-
182194

183195
activeExpressionsChanged() {
184196
this.aeChangedDebounced();
@@ -201,15 +213,19 @@ export default class EventDrops extends Morph {
201213
aexprs[i].timelineID = i;
202214
}
203215
this.updateOverview(aexprs);
204-
this.updateTimeline(aexprs)
216+
this.updateTimeline(aexprs);
205217
}
206218

207219
updateTimeline(aexprs) {
208220
const checkedIndices = jQuery(this.aeOverview).jstree(true).get_bottom_selected();
209221
const selectedAEs = checkedIndices.map(i => aexprs[i - 1]).filter(ae => ae);
222+
this.updateValuesOverTime(selectedAEs);
210223
let scrollBefore = this.diagram.scrollTop;
211224
let groups = selectedAEs.groupBy(this.getGroupingFunction());
212-
groups = Object.keys(groups).map(each => ({ name: each, data: groups[each].flatMap(ae => ae.meta().get('events')) }));
225+
groups = Object.keys(groups).map(each => ({
226+
name: each,
227+
data: groups[each].flatMap(ae => ae.meta().get('events')).filter(this.filterFunction)
228+
}));
213229
this.setData(groups);
214230
if (selectedAEs.length == 0) return;
215231

@@ -238,6 +254,23 @@ export default class EventDrops extends Morph {
238254
this.diagram.scrollTop = scrollBefore;
239255
}
240256

257+
updateValuesOverTime(aexprs) {
258+
const aeWithRelevantEvents = aexprs.map(ae => {
259+
return { ae, events: ae.meta().get('events').filter(event => event.type === "changed value").filter(this.filterFunction) };
260+
});
261+
this.valuesOverTime.innerHTML = "";
262+
263+
for(const {ae, events} of aeWithRelevantEvents) {
264+
if(events.length === 0) continue;
265+
let row = <tr><th>{ae.meta().get('id')}</th></tr>
266+
row.append(<td>{events[0].value.lastValue}</td>);
267+
for(const event of events) {
268+
row.append(<td>{event.value.value}</td>);
269+
}
270+
this.valuesOverTime.append(row);
271+
}
272+
}
273+
241274
updateOverview(aexprs) {
242275
jQuery(this.aeOverview).jstree(true).settings.core.data = this.generateOverviewJSON(aexprs);
243276
jQuery(this.aeOverview).jstree(true).refresh();
@@ -320,4 +353,17 @@ export default class EventDrops extends Morph {
320353
get aeOverview() {
321354
return this.get("#aeOverview");
322355
}
356+
357+
get filterInput() {
358+
return this.get("#filterInput");
359+
}
360+
361+
get filterButton() {
362+
return this.get("#filterButton");
363+
}
364+
365+
get valuesOverTime() {
366+
return this.get("#valuesOverTime");
367+
}
368+
323369
}

src/components/tools/file-chooser.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ import Bindings from "src/client/bindings.js"
55
import {promisedEvent} from "src/client/utils.js"
66

77

8+
/*MD # File Chooser
9+
10+
![](file-chooser.png){width=300px}
11+
12+
MD*/
13+
814
export default class FileChooser extends Morph {
915
async initialize() {
1016
this.registerAttributes(["root"]);

0 commit comments

Comments
 (0)