Skip to content

Commit 78d4abb

Browse files
authored
Merge pull request #356 from Dessia-tech/feat/highlight-objects
Highlight Objects
2 parents eff392c + f17838f commit 78d4abb

File tree

9 files changed

+80
-13
lines changed

9 files changed

+80
-13
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

88
## [0.23.0]
9+
10+
### Feat
11+
- Add events (Subject) to emit shape hovering and clicking
12+
- Highlight shapes when corresponding function is called from wrapper software
13+
914
### Fix
1015
- Remove offline mode
1116

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,15 @@
99
"build": "npm run instrument && NODE_ENV=production webpack --config webpack.config.js",
1010
"dev": "npm run instrument && NODE_ENV=development webpack --config webpack-dev.config.cjs",
1111
"cov": "npm run instrument && NODE_ENV=coverage webpack --config webpack-dev.config.cjs",
12-
1312
"format": "prettier --write \"src/**/*.ts\"",
1413
"lint": "tslint -p tsconfig.json",
1514
"start": "http-server -a localhost -p 3030",
16-
1715
"merge_reports": "mochawesome-merge cypress/results/*.json > cypress/results/full_report.json",
1816
"generate_mochawesome_report": "marge cypress/results/full_report.json --reportDir cypress/results",
19-
2017
"cy:run-base": "cypress run --env type=base --browser firefox",
2118
"cy:run-actual": "node ./cypress_run_report.cjs",
2219
"cy:run-open": "cypress open --env type=actual",
2320
"cy:open": "npm run cov & start-server-and-test start http-get://localhost:3030 cy:run-open",
24-
2521
"test": "npm run cov && start-server-and-test start http-get://localhost:3030 cy:run-actual",
2622
"base-test": "npm run cov && start-server-and-test start http-get://localhost:3030 cy:run-base"
2723
},
@@ -78,6 +74,7 @@
7874
"fs": "^0.0.1-security",
7975
"html-webpack-plugin": "^5.5.0",
8076
"ignore-errors": "^2.0.0",
77+
"rxjs": "^7.8.1",
8178
"ts-loader": "^9.2.6",
8279
"typedoc": "^0.23.28",
8380
"webpack": "^5.75.0"

plot_data/core.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,6 @@ class Sample(ReferencedObject):
165165

166166
def __init__(self, values, reference_path: str = "#", name: str = ""):
167167
self.values = values
168-
self.reference_path = reference_path
169168
super().__init__(type_="sample", reference_path=reference_path, name=name)
170169

171170
def to_dict(self, use_pointers: bool = True, memo=None, path: str = '#', id_method=True,

src/baseShape.ts

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { DEFAULT_SHAPE_COLOR, HOVERED_SHAPE_COLOR, CLICKED_SHAPE_COLOR, SELECTED
22
import { hslToArray, colorHsl } from "./colors"
33
import { Hatching } from "./styles"
44
import { DataInterface } from "./dataInterfaces"
5+
import { highlightShape } from "./interactions"
6+
57

68
export class Vertex {
79
constructor(public x: number = 0, public y: number = 0) { }
@@ -82,16 +84,51 @@ export class InteractiveObject {
8284

8385
public mouseClick: Vertex = null;
8486

85-
public isHovered: boolean = false;
86-
public isClicked: boolean = false;
87+
private _isHovered: boolean = false;
88+
private _isClicked: boolean = false;
8789
public isSelected: boolean = false;
8890
public isScaled: boolean = true;
8991
public isFilled: boolean = true;
9092
public visible: boolean = true;
9193
public inFrame: boolean = true; // TODO: remove it
9294

95+
public referencePath: string = "#";
96+
9397
constructor() { };
9498

99+
public get isHovered(): boolean{
100+
return this._isHovered;
101+
};
102+
set isHovered(hovered: boolean) {
103+
if (hovered !== this._isHovered && this.referencePath !== "#") {
104+
// The first check is important, otherwise we fire the event every mouse move.
105+
// The second is for dev purpose, should we keep it ?
106+
const highlightData = {
107+
referencePath: this.referencePath,
108+
highlight: hovered,
109+
select: false
110+
}
111+
highlightShape.next(highlightData);
112+
}
113+
this._isHovered = hovered;
114+
}
115+
116+
public get isClicked(): boolean {
117+
return this._isClicked;
118+
}
119+
set isClicked(clicked: boolean) {
120+
if (clicked != this._isClicked && this.referencePath !== "#") {
121+
// Same than isHovered
122+
const highlightData = {
123+
referencePath: this.referencePath,
124+
highlight: clicked,
125+
select: true
126+
}
127+
highlightShape.next(highlightData);
128+
}
129+
this._isClicked = clicked;
130+
}
131+
95132
public getBounds(): [Vertex, Vertex] { return [new Vertex(0, 1), new Vertex(0, 1)] }
96133

97134
protected updateTooltipOrigin(matrix: DOMMatrix): void { }
@@ -161,7 +198,9 @@ export class InteractiveObject {
161198

162199
public mouseDown(mouseDown: Vertex) { if (this.isHovered) this.mouseClick = mouseDown.copy() }
163200

164-
public mouseMove(context: CanvasRenderingContext2D, mouseCoords: Vertex): void { this.isHovered = this.isPointInShape(context, mouseCoords) }
201+
public mouseMove(context: CanvasRenderingContext2D, mouseCoords: Vertex): void {
202+
this.isHovered = this.isPointInShape(context, mouseCoords);
203+
}
165204

166205
public mouseUp(keepState: boolean): void {
167206
this.isClicked = this.isHovered ? !this.isClicked : (keepState ? this.isClicked : false);

src/core.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export * from "./constants";
66
export * from './figures';
77
export * from "./shapeFunctions";
88
export * from "./functions";
9+
export * from "./interactions";
910
export * from "./multiplot";
1011
export * from "./primitives";
1112
export * from './remoteFigure';

src/figures.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { Axis, ParallelAxis } from "./axes"
1010
import { ShapeCollection, GroupCollection, PointSet } from "./collections"
1111
import { RemoteFigure } from "./remoteFigure"
1212
import { DataInterface } from "./dataInterfaces"
13+
import { HighlightData } from "./interactions"
1314

1415
export class Figure extends RemoteFigure {
1516
constructor(
@@ -1170,6 +1171,21 @@ export class Draw extends Frame {
11701171
public sendRubberBandsMultiplot(figures: Figure[]): void {}
11711172

11721173
protected receiveRubberBandFromFigure(figure: Figure): void {}
1174+
1175+
public highlightFromReferencePath(highlightData: HighlightData) {
1176+
const highlight = highlightData.highlight;
1177+
const shapes = this.getShapesFromPath(highlightData.referencePath);
1178+
shapes.forEach((shape) => {
1179+
highlightData.select ?
1180+
shape.isClicked = highlight :
1181+
shape.isHovered = highlight;
1182+
});
1183+
this.draw();
1184+
}
1185+
1186+
private getShapesFromPath(referencePath: string): Shape[] {
1187+
return this.relativeObjects.shapes.filter((s) => s.referencePath === referencePath);
1188+
}
11731189
}
11741190

11751191
export class PrimitiveGroupContainer extends Draw {

src/interactions.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { Subject } from "rxjs"
2+
3+
export interface HighlightData {
4+
referencePath: string,
5+
highlight: boolean,
6+
select: boolean
7+
}
8+
9+
export const highlightShape: Subject<HighlightData> = new Subject();

src/shapeFunctions.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ export function deserialize(data: { [key: string]: any }, scale: Vertex): Shape
2020
else if (data.type_ == "rectangle") shape = Rect.deserialize(data, scale);
2121
else if (data.type_ == "roundrectangle") shape = RoundRect.deserialize(data, scale);
2222
else throw new Error(`${data.type_} deserialization is not implemented.`);
23-
shape.deserializeStyle(data)
23+
shape.deserializeStyle(data);
24+
shape.referencePath = data?.reference_path ?? "#";
2425
return shape
2526
}
2627

0 commit comments

Comments
 (0)