Skip to content

Commit 0ad5ca8

Browse files
authored
Merge pull request #79 from CentreForDigitalHumanities/feature/actual-proof-svg
Visualize the actual proofs of the current problem with the TableauSVG component
2 parents 04fc5db + 35c84db commit 0ad5ca8

20 files changed

Lines changed: 702 additions & 252 deletions
Lines changed: 54 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,54 @@
1-
<ul ngbNav #nav="ngbNav" [(activeId)]="active" class="nav-tabs flex-nowrap">
2-
<li [ngbNavItem]="1">
3-
<button ngbNavLink>
4-
<fa-icon
5-
[icon]="faSquarePollHorizontal"
6-
class="me-2"
7-
aria-hidden="true"
8-
/>
9-
<span i18n>Syntactic parses</span>
10-
</button>
11-
<ng-template ngbNavContent>
12-
<la-annotation-parse-results />
13-
</ng-template>
14-
</li>
15-
<li [ngbNavItem]="2">
16-
<button ngbNavLink>
17-
<fa-icon [icon]="faTree" class="me-2" aria-hidden="true" />
18-
<span i18n>Tableau / Proof</span>
19-
</button>
20-
<ng-template ngbNavContent>
21-
<la-annotation-tableau />
22-
</ng-template>
23-
</li>
24-
<li [ngbNavItem]="3">
25-
<button ngbNavLink>
26-
<fa-icon [icon]="faPenNib" class="me-2" aria-hidden="true" />
27-
<span i18n>Comments / History</span>
28-
</button>
29-
<ng-template ngbNavContent>
30-
<la-annotation-comments />
31-
</ng-template>
32-
</li>
33-
</ul>
34-
35-
<div [ngbNavOutlet]="nav" class="mt-2"></div>
1+
@let proofs = proofs$ | async;
2+
3+
<ul ngbNav #nav="ngbNav" [(activeId)]="active" class="nav-tabs flex-nowrap">
4+
<li [ngbNavItem]="1">
5+
<button ngbNavLink>
6+
<fa-icon
7+
[icon]="faSquarePollHorizontal"
8+
class="me-2"
9+
aria-hidden="true"
10+
/>
11+
<span i18n>Syntactic parses</span>
12+
</button>
13+
<ng-template ngbNavContent>
14+
<la-annotation-parse-results />
15+
</ng-template>
16+
</li>
17+
<li [ngbNavItem]="2">
18+
<button ngbNavLink>
19+
<b class="me-2" aria-hidden></b>
20+
<span i18n>Proof / Entailment</span>
21+
</button>
22+
<ng-template ngbNavContent>
23+
<section class="overflow-x-scroll">
24+
@if (proofs) {
25+
<la-tableau-svg [tree]="proofs.entailment"></la-tableau-svg>
26+
}
27+
</section>
28+
</ng-template>
29+
</li>
30+
<li [ngbNavItem]="3">
31+
<button ngbNavLink>
32+
<b class="me-2" aria-hidden></b>
33+
<span i18n>Proof / Contradiction</span>
34+
</button>
35+
<ng-template ngbNavContent>
36+
<section class="overflow-x-scroll">
37+
@if (proofs) {
38+
<la-tableau-svg [tree]="proofs.contradiction"></la-tableau-svg>
39+
}
40+
</section>
41+
</ng-template>
42+
</li>
43+
<li [ngbNavItem]="4">
44+
<button ngbNavLink>
45+
<fa-icon [icon]="faPenNib" class="me-2" aria-hidden="true" />
46+
<span i18n>Comments / History</span>
47+
</button>
48+
<ng-template ngbNavContent>
49+
<la-annotation-comments />
50+
</ng-template>
51+
</li>
52+
</ul>
53+
54+
<div [ngbNavOutlet]="nav" class="mt-2"></div>
Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,37 @@
1-
import { Component } from "@angular/core";
1+
import { Component, inject } from "@angular/core";
2+
import { CommonModule } from "@angular/common";
23
import { FontAwesomeModule } from "@fortawesome/angular-fontawesome";
34
import { NgbNavModule } from "@ng-bootstrap/ng-bootstrap";
45
import {
56
faSquarePollHorizontal,
6-
faTree,
77
faPenNib,
88
} from "@fortawesome/free-solid-svg-icons";
9+
10+
import { ParseService } from "@/services/parse.service";
911
import { AnnotationParseResultsComponent } from "../annotation-parse-results/annotation-parse-results.component";
10-
import { AnnotationTableauComponent } from "../annotation-tableau/annotation-tableau.component";
12+
import { TableauSVG } from '../tableau-svg/tableau-svg.component';
1113
import { AnnotationCommentsComponent } from "../annotation-comments/annotation-comments.component";
1214

1315
@Component({
1416
selector: "la-annotation-menu",
1517
standalone: true,
1618
imports: [
19+
CommonModule,
1720
NgbNavModule,
1821
FontAwesomeModule,
1922
AnnotationParseResultsComponent,
20-
AnnotationTableauComponent,
23+
TableauSVG,
2124
AnnotationCommentsComponent,
2225
],
2326
templateUrl: "./annotation-menu.component.html",
2427
styleUrl: "./annotation-menu.component.scss",
2528
})
2629
export class AnnotationMenuComponent {
30+
private parseService = inject(ParseService);
31+
public readonly proofs$ = this.parseService.proofs$;
32+
2733
public active = 1;
2834

2935
public faSquarePollHorizontal = faSquarePollHorizontal;
30-
public faTree = faTree;
3136
public faPenNib = faPenNib;
3237
}

frontend/src/app/annotate/annotation-tableau/annotation-tableau.component.html

Lines changed: 0 additions & 3 deletions
This file was deleted.

frontend/src/app/annotate/annotation-tableau/annotation-tableau.component.spec.ts

Lines changed: 0 additions & 22 deletions
This file was deleted.

frontend/src/app/annotate/annotation-tableau/annotation-tableau.component.ts

Lines changed: 0 additions & 11 deletions
This file was deleted.

frontend/src/app/annotate/annotation-tableau/annotation-tableau.component.scss renamed to frontend/src/app/annotate/tableau-svg/tableau-node.component.scss

File renamed without changes.
Lines changed: 33 additions & 0 deletions
Loading
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { Component, ElementRef, Input, Output, ViewChild, EventEmitter } from '@angular/core';
2+
import { Dimensions } from '@/types';
3+
4+
@Component({
5+
selector: "[node]",
6+
standalone: true,
7+
imports: [],
8+
templateUrl: "./tableau-node.component.svg",
9+
styleUrl: "./tableau-node.component.scss",
10+
})
11+
export class TableauNode {
12+
@Input()
13+
public id?: number;
14+
15+
@Input()
16+
public mod?: string;
17+
18+
@Input()
19+
public args?: string;
20+
21+
@Input()
22+
public sign?: boolean;
23+
24+
@Input()
25+
public head: string = '';
26+
27+
@Input()
28+
public end: boolean = false;
29+
30+
@Input()
31+
public rule?: string;
32+
33+
@ViewChild('idText')
34+
idText?: ElementRef<SVGTextElement>;
35+
36+
@ViewChild('headText')
37+
headText?: ElementRef<SVGTextElement>;
38+
39+
@ViewChild('modText')
40+
modText?: ElementRef<SVGTextElement>;
41+
42+
@ViewChild('argsText')
43+
argsText?: ElementRef<SVGTextElement>;
44+
45+
@ViewChild('ruleText')
46+
ruleText?: ElementRef<SVGTextElement>;
47+
48+
@Output()
49+
public onSize = new EventEmitter<Dimensions>();
50+
51+
padding = 5;
52+
height = 20;
53+
54+
idW = 0;
55+
modX = 0;
56+
modW = 0;
57+
headX = 0;
58+
headW = 0;
59+
argsX = 0;
60+
argsW = 0;
61+
totalW = 0;
62+
63+
ngAfterViewChecked() {
64+
this.idW = this.idText ? this.idText.nativeElement.getComputedTextLength() + this.padding : 0;
65+
this.modX = this.idW;
66+
this.modW = this.modText ? this.modText.nativeElement.getComputedTextLength() + this.padding : 0;
67+
this.argsW = this.argsText ? this.argsText.nativeElement.getComputedTextLength() + this.padding : 0;
68+
this.headW = this.headText ? this.headText.nativeElement.getComputedTextLength() : 0;
69+
this.headX = this.modX + this.modW;
70+
this.argsX = this.headX + this.headW + this.padding;
71+
72+
const mainW = (
73+
this.headText ?
74+
this.argsW + this.idW + this.headW + this.modW :
75+
0
76+
);
77+
78+
const ruleW = this.ruleText ? this.ruleText.nativeElement.getComputedTextLength() : 0;
79+
this.totalW = Math.max(mainW, ruleW)
80+
81+
this.onSize.emit({width: this.totalW, height: this.height});
82+
}
83+
84+
}
Lines changed: 3 additions & 2 deletions
Loading
Lines changed: 12 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { Component, ChangeDetectorRef} from '@angular/core';
1+
import { Component, ChangeDetectorRef, ElementRef, input } from '@angular/core';
22
import { CommonModule } from "@angular/common";
33
import { Subject } from "rxjs";
4-
import { Dimensions } from '@/types';
4+
import { Dimensions, ProofTree } from '@/types';
55
import { TableauTree } from './tableau-tree.component';
66

77
@Component({
@@ -13,10 +13,15 @@ import { TableauTree } from './tableau-tree.component';
1313
})
1414
export class TableauSVG {
1515

16+
public readonly tree = input.required<ProofTree>();
17+
1618
treeDimensions$ = new Subject<Dimensions>();
1719
treeDimensions: Dimensions = {width:0, height: 0};
1820

19-
constructor(private cdref: ChangeDetectorRef) {}
21+
constructor(
22+
private cdref: ChangeDetectorRef,
23+
private element: ElementRef
24+
) {}
2025

2126
onTreeSize(size: Dimensions) {
2227
this.treeDimensions = size;
@@ -25,59 +30,9 @@ export class TableauSVG {
2530
ngAfterViewChecked() {
2631
this.treeDimensions$.next(this.treeDimensions);
2732
this.cdref.detectChanges();
28-
}
29-
30-
tree: any = {
31-
nodes: [
32-
{idx: 1, term: 'every@man@(be@work)', bg: 'honeydew'},
33-
{idx: 2, term: 'every@(who@(be@work)@person)@(λ1,a@(expensive@car)@(λ2,have@2@1))', bg: 'honeydew'},
34-
{idx: 3, term: 'every@man@(λ3,a@car@(λ2,own@2@3))', bg: 'mistyrose'},
35-
{idx: 4, term: 'be@work', label: 'c1', rule: 'up_mon_fun_some[1,3]', bg: 'honeydew'},
36-
{idx: 5, term: '(λ3,a@car@(λ2,own@2@3))', label: 'c1', rule: 'up_mon_fun_some[1,3]', bg: 'mistyrose'},
37-
{idx: 6, term: 'man', label: 'c1', rule: 'up_mon_fun_some[1,3]', bg: 'honeydew'},
38-
{idx: 7, term: 'a@car@(λ2,own@2@c1)', rule: 'pull_arg[5]', bg: 'mistyrose'},
39-
{idx: 8, term: 'work', label: 'c1', rule: 'aux_verb[4]', bg: 'honeydew'},
40-
{idx: 9, term: 'be@work', label: 'c1', rule: 'tr_every_c[1,6], [c1]', bg: 'honeydew'},
41-
{idx: 8, term: 'work', label: 'c1', rule: 'aux_verb[9]', bg: 'honeydew'},
42-
],
43-
subtrees: [
44-
{
45-
nodes: [
46-
{idx: 10, term: 'who@(be@work)@person', label: 'c1', rule: 'tr_every[2],[c1]', bg: 'mistyrose'},
47-
],
48-
subtrees: [
49-
{
50-
nodes: [
51-
{idx: 13, term: 'be@work', label: 'c1', rule: 'fl_conj_who[10]', bg: 'mistyrose'},
52-
{idx: 16, term: 'work', label: 'c1', rule: 'aux_verb[13]', bg: 'mistyrose'},
53-
{end: true, rule: 'cl_subcat[16,8]'}
54-
],
55-
},
56-
{
57-
nodes: [
58-
{idx: 14, term: 'person', label: 'c1', rule: 'fl_conj_who[10]', bg: 'mistyrose'},
59-
{end: true, rule: 'cl_subsumption[14,6]'}
60-
]
61-
}
62-
]
63-
},
64-
{
65-
nodes: [
66-
{idx: 11, term: 'who@(be@work)@person', label: 'c1', rule: 'tr_every[2],[c1]', bg: 'honeydew'},
67-
{idx: 12, term: '(λ1,a@(expensive@car)@(λ2,have@2@1))', label: 'c1', rule: 'tr_every[2],[c1]', bg: 'honeydew'},
68-
{idx: 15, term: 'a@(expensive@car)@(λ2,have@2@c1)', label: 'c1', rule: 'pull_arg[12]', bg: 'honeydew'},
69-
{idx: 17, term: 'be@work', label: 'c1', rule: 'tr_conj_who[11]', bg: 'honeydew'},
70-
{idx: 18, term: 'person', label: 'c1', rule: 'tr_conj_who[11]' , bg: 'honeydew'},
71-
{idx: 8, term: 'work', label: 'c1', rule: 'aux_verb[17]', bg: 'honeydew'},
72-
{idx: 19, term: 'a@(expensive@car)', label: '(λ2,have@2@c1)', rule: 'same_args[15,7]', bg: 'honeydew'},
73-
{idx: 20, term: 'a@car', label: '(λ2,have@2@c1)', rule: 'same_args[15,7]', bg: 'mistyrose'},
74-
{idx: 21, term: 'expensive@car', label: 'c2', rule: 'up_mon_fun[19,20]', bg: 'honeydew'},
75-
{idx: 22, term: 'car', label: 'c2', rule: 'up_mon_fun[19,20]', bg: 'mistyrose'},
76-
{idx: 23, term: 'car', label: 'c2', rule:'int_mod_tr[21]', bg: 'honeydew'},
77-
{idx: 24, term: 'expensive', label: 'c2', rule:'int_mod_tr[21]', bg: 'honeydew'},
78-
{end: true, rule: 'cl_subsmption[23,22]'}
79-
]
80-
}
81-
]
33+
const width = this.treeDimensions.width;
34+
if (width) this.element.nativeElement.parentElement.scroll({
35+
left: Math.max(0, width / 2 - 500)
36+
});
8237
}
8338
}

0 commit comments

Comments
 (0)