Update simulator as per latest lego UI design for sensors. Fix full screen layout issues. (#554)
This commit is contained in:
parent
4825172423
commit
84990d66a9
@ -49,14 +49,14 @@ namespace pxsim.visuals {
|
||||
font-size:16px;
|
||||
}
|
||||
.sim-text.large {
|
||||
font-size:30px;
|
||||
font-size:20px;
|
||||
}
|
||||
.sim-text.number {
|
||||
font-family: Courier, Lato, Work Sans, PT Serif, Source Serif Pro;
|
||||
/*font-weight: bold;*/
|
||||
}
|
||||
.sim-text.inverted {
|
||||
fill:#5A5A5A;
|
||||
fill: #5A5A5A; /*#F12B21;*/
|
||||
}
|
||||
|
||||
.no-drag, .sim-text, .sim-text-pin {
|
||||
@ -74,6 +74,10 @@ namespace pxsim.visuals {
|
||||
stroke: #000;
|
||||
cursor: pointer;
|
||||
}
|
||||
.sim-color-selected {
|
||||
stroke-width: 1px !important;
|
||||
stroke: #A8AAA8 !important;
|
||||
}
|
||||
.sim-color-wheel-half:hover {
|
||||
stroke-width: 1;
|
||||
stroke: #000;
|
||||
@ -136,6 +140,8 @@ namespace pxsim.visuals {
|
||||
|
||||
private cachedControlNodes: { [index: string]: View[] } = {};
|
||||
private cachedDisplayViews: { [index: string]: LayoutElement[] } = {};
|
||||
private cachedCloseIcons: { [index: string]: View } = {};
|
||||
private cachedBackgroundViews: { [index: string]: View } = {};
|
||||
|
||||
private screenCanvas: HTMLCanvasElement;
|
||||
private screenCanvasCtx: CanvasRenderingContext2D;
|
||||
@ -298,8 +304,22 @@ namespace pxsim.visuals {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private getCloseIconView() {
|
||||
return new CloseIconControl(this.element, this.defs, new PortNode(-1), -1);
|
||||
private getCloseIconView(port: number) {
|
||||
if (this.cachedCloseIcons[port]) {
|
||||
return this.cachedCloseIcons[port];
|
||||
}
|
||||
const closeIcon = new CloseIconControl(this.element, this.defs, new PortNode(-1), -1);
|
||||
this.cachedCloseIcons[port] = closeIcon;
|
||||
return closeIcon;
|
||||
}
|
||||
|
||||
private getBackgroundView(port: number) {
|
||||
if (this.cachedBackgroundViews[port]) {
|
||||
return this.cachedBackgroundViews[port];
|
||||
}
|
||||
const backgroundView = new BackgroundViewControl(this.element, this.defs, new PortNode(-1), -1);
|
||||
this.cachedBackgroundViews[port] = backgroundView;
|
||||
return backgroundView;
|
||||
}
|
||||
|
||||
private buildDom() {
|
||||
@ -319,7 +339,7 @@ namespace pxsim.visuals {
|
||||
const brick = new BrickViewPortrait(-1);
|
||||
this.layoutView.setBrick(brick);
|
||||
EV3View.isPreviousBrickLandscape() ? this.layoutView.setlectBrick() : this.layoutView.unselectBrick();
|
||||
|
||||
|
||||
this.resize();
|
||||
|
||||
// Add Screen canvas to board
|
||||
@ -392,29 +412,29 @@ namespace pxsim.visuals {
|
||||
this.layoutView.getLandscapeBrick().kill();
|
||||
|
||||
// Save previous inputs for the next cycle
|
||||
EV3View.previousSelectedInputs = ev3board().getInputNodes().map((node, index) => (this.getDisplayViewForNode(node.id, index).getSelected()) ? node.id : -1)
|
||||
EV3View.previousSeletedOutputs = ev3board().getMotors().map((node, index) => (this.getDisplayViewForNode(node.id, index).getSelected()) ? node.id : -1);
|
||||
EV3View.previousSelectedInputs = {};
|
||||
ev3board().getInputNodes().forEach((node, index) =>
|
||||
EV3View.previousSelectedInputs[index] = (this.getDisplayViewForNode(node.id, index).getSelected()));
|
||||
EV3View.previousSeletedOutputs = {};
|
||||
ev3board().getMotors().forEach((node, index) =>
|
||||
EV3View.previousSeletedOutputs[index] = (this.getDisplayViewForNode(node.id, index).getSelected()));
|
||||
EV3View.previousBrickLandscape = this.layoutView.isBrickLandscape();
|
||||
}
|
||||
|
||||
private static previousSelectedInputs: number[];
|
||||
private static previousSeletedOutputs: number[];
|
||||
private static previousSelectedInputs: pxt.Map<boolean> = {};
|
||||
private static previousSeletedOutputs: pxt.Map<boolean> = {};
|
||||
private static previousBrickLandscape: boolean;
|
||||
|
||||
private static isPreviousInputSelected(index: number, id: number) {
|
||||
if (EV3View.previousSelectedInputs && EV3View.previousSelectedInputs[index] == id) {
|
||||
EV3View.previousSelectedInputs[index] = undefined;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
private static isPreviousInputSelected(index: number) {
|
||||
const previousInput = EV3View.previousSelectedInputs[index];
|
||||
delete EV3View.previousSelectedInputs[index];
|
||||
return previousInput;
|
||||
}
|
||||
|
||||
private static isPreviousOutputSelected(index: number, id: number) {
|
||||
if (EV3View.previousSeletedOutputs && EV3View.previousSeletedOutputs[index] == id) {
|
||||
EV3View.previousSeletedOutputs[index] = undefined;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
private static isPreviousOutputSelected(index: number) {
|
||||
const previousOutput = EV3View.previousSeletedOutputs[index];
|
||||
delete EV3View.previousSeletedOutputs[index];
|
||||
return previousOutput;
|
||||
}
|
||||
|
||||
private static isPreviousBrickLandscape() {
|
||||
@ -463,11 +483,13 @@ namespace pxsim.visuals {
|
||||
const view = this.getDisplayViewForNode(node.id, index);
|
||||
if (!node.didChange() && !view.didChange()) return;
|
||||
if (view) {
|
||||
const isSelected = EV3View.isPreviousInputSelected(index, node.id) || view.getSelected();
|
||||
if (isSelected && !view.getSelected()) view.setSelected(true);
|
||||
const previousSelected = EV3View.isPreviousInputSelected(index);
|
||||
const isSelected = previousSelected != undefined ? previousSelected : view.getSelected();
|
||||
view.setSelected(isSelected);
|
||||
const control = isSelected ? this.getControlForNode(node.id, index, !node.modeChange()) : undefined;
|
||||
const closeIcon = control && view.hasClose() ? this.getCloseIconView() : undefined;
|
||||
this.layoutView.setInput(index, view, control, closeIcon);
|
||||
const closeIcon = control ? this.getCloseIconView(index + 10) : undefined;
|
||||
const backgroundView = control && view.hasBackground() ? this.getBackgroundView(index + 10) : undefined;
|
||||
this.layoutView.setInput(index, view, control, closeIcon, backgroundView);
|
||||
view.updateState();
|
||||
if (control) control.updateState();
|
||||
}
|
||||
@ -485,11 +507,13 @@ namespace pxsim.visuals {
|
||||
const view = this.getDisplayViewForNode(node.id, index);
|
||||
if (!node.didChange() && !view.didChange()) return;
|
||||
if (view) {
|
||||
const isSelected = EV3View.isPreviousOutputSelected(index, node.id) || view.getSelected();
|
||||
if (isSelected && !view.getSelected()) view.setSelected(true);
|
||||
const previousSelected = EV3View.isPreviousOutputSelected(index);
|
||||
const isSelected = previousSelected != undefined ? previousSelected : view.getSelected();
|
||||
view.setSelected(isSelected);
|
||||
const control = isSelected ? this.getControlForNode(node.id, index) : undefined;
|
||||
const closeIcon = control ? this.getCloseIconView() : undefined;
|
||||
this.layoutView.setOutput(index, view, control, closeIcon);
|
||||
const closeIcon = control ? this.getCloseIconView(index) : undefined;
|
||||
const backgroundView = control && view.hasBackground() ? this.getBackgroundView(index) : undefined;
|
||||
this.layoutView.setOutput(index, view, control, closeIcon, backgroundView);
|
||||
view.updateState();
|
||||
if (control) control.updateState();
|
||||
}
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
namespace pxsim.visuals {
|
||||
|
||||
export const CONTROL_WIDTH = 87.5;
|
||||
export const CONTROL_HEIGHT = 175;
|
||||
export const CONTROL_WIDTH = 76.84;
|
||||
export const CONTROL_HEIGHT = 112.72;
|
||||
|
||||
export const CONTROL_TEXT_COLOR = '#000';
|
||||
|
||||
@ -43,28 +43,29 @@ namespace pxsim.visuals {
|
||||
return this.content;
|
||||
}
|
||||
|
||||
public resize(width: number, height: number) {
|
||||
public resize(width: number, height: number, strict?: boolean) {
|
||||
super.resize(width, height);
|
||||
this.updateDimensions(width, height);
|
||||
this.updateDimensions(width, height, strict);
|
||||
}
|
||||
|
||||
private updateDimensions(width: number, height: number) {
|
||||
private updateDimensions(width: number, height: number, strict?: boolean) {
|
||||
if (this.content) {
|
||||
const currentWidth = this.getInnerWidth();
|
||||
const currentHeight = this.getInnerHeight();
|
||||
const newHeight = currentHeight / currentWidth * width;
|
||||
const newWidth = currentWidth / currentHeight * height;
|
||||
if (newHeight > height) {
|
||||
if (strict) {
|
||||
this.content.setAttribute('width', `${width}`);
|
||||
this.content.setAttribute('height', `${height}`);
|
||||
} else if (newHeight > height) {
|
||||
// scale width instead
|
||||
this.content.setAttribute('width', `${newWidth}`);
|
||||
this.content.setAttribute('height', `${height}`);
|
||||
// translate to the middle (width)
|
||||
this.translate(width / 2 - newWidth / 2, 0);
|
||||
this.width = newWidth;
|
||||
} else {
|
||||
this.content.setAttribute('width', `${width}`);
|
||||
this.content.setAttribute('height', `${newHeight}`);
|
||||
// translate to the middle (height)
|
||||
this.translate(0, height / 2 - newHeight / 2);
|
||||
this.height = newHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
42
sim/visuals/controls/backgroundView.ts
Normal file
42
sim/visuals/controls/backgroundView.ts
Normal file
@ -0,0 +1,42 @@
|
||||
|
||||
|
||||
namespace pxsim.visuals {
|
||||
|
||||
export class BackgroundViewControl extends ControlView<PortNode> {
|
||||
private backgroundGroup: SVGGElement;
|
||||
private backgroundRect: SVGRectElement;
|
||||
|
||||
getInnerView() {
|
||||
this.backgroundGroup = svg.elt("g") as SVGGElement;
|
||||
this.backgroundRect = pxsim.svg.child(this.backgroundGroup,
|
||||
"rect", {
|
||||
'x': 0, 'y': 0,
|
||||
'width': '100%',
|
||||
'height': '100%',
|
||||
'style': `fill: #d6edff; stroke: #A8A9A8; stroke-width: 3px; stroke-opacity: 0.2`
|
||||
}) as SVGRectElement;
|
||||
return this.backgroundGroup;
|
||||
}
|
||||
|
||||
buildDom(): SVGElement {
|
||||
this.content = svg.elt("svg", { width: "100%", height: "100%"}) as SVGSVGElement;
|
||||
this.content.appendChild(this.getInnerView());
|
||||
return this.content;
|
||||
}
|
||||
|
||||
public resize(width: number, height: number, strict?: boolean) {
|
||||
super.resize(width, height, strict);
|
||||
this.backgroundRect.setAttribute('stroke-dasharray', `${height + width + height} 1000`);
|
||||
this.backgroundRect.setAttribute('stroke-dashoffset', `-${width}`);
|
||||
}
|
||||
|
||||
getInnerWidth(): number {
|
||||
return 76.84;
|
||||
}
|
||||
|
||||
getInnerHeight(): number {
|
||||
return 173.86;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -9,7 +9,7 @@ namespace pxsim.visuals {
|
||||
this.closeGroup = svg.elt("g") as SVGGElement;
|
||||
this.closeGroup.style.cursor = 'pointer';
|
||||
const circleCloseWrapper = pxsim.svg.child(this.closeGroup, "g");
|
||||
pxsim.svg.child(circleCloseWrapper, "circle", { 'cx': "16", 'cy': "16", 'r': "16", 'style': "fill: #fff" });
|
||||
pxsim.svg.child(circleCloseWrapper, "circle", { 'cx': "16", 'cy': "16", 'r': "16", 'style': "fill: transparent;" });
|
||||
pxsim.svg.child(circleCloseWrapper, "circle", { 'cx': "16", 'cy': "16", 'r': "15", 'style': "fill: none;stroke: #a8aaa8;stroke-width: 2px" });
|
||||
pxsim.svg.child(this.closeGroup, "rect", { 'x': "10", 'y': "16", 'width': "18", 'height': "2", 'transform': "translate(-9.46 17.41) rotate(-45)", 'style': "fill: #a8aaa8" });
|
||||
pxsim.svg.child(this.closeGroup, "rect", { 'x': "18", 'y': "8", 'width': "2", 'height': "18", 'transform': "translate(-9.46 17.41) rotate(-45)", 'style': "fill: #a8aaa8" });
|
||||
@ -18,15 +18,11 @@ namespace pxsim.visuals {
|
||||
}
|
||||
|
||||
buildDom(): SVGElement {
|
||||
this.content = svg.elt("svg", { width: "100%", height: "100%"}) as SVGSVGElement;
|
||||
this.content = svg.elt("svg", { width: "100%", height: "100%", viewBox:"0 0 32 32"}) as SVGSVGElement;
|
||||
this.content.appendChild(this.getInnerView());
|
||||
return this.content;
|
||||
}
|
||||
|
||||
public resize(width: number, height: number) {
|
||||
super.resize(width, height);
|
||||
}
|
||||
|
||||
public getInnerHeight() {
|
||||
return 32;
|
||||
}
|
||||
|
@ -5,28 +5,32 @@ namespace pxsim.visuals {
|
||||
export class ColorGridControl extends ControlView<ColorSensorNode> {
|
||||
private group: SVGGElement;
|
||||
|
||||
private static colorIds = ['red', 'yellow', 'blue', 'green', 'black', 'grey', 'white'];
|
||||
private static colorValue = [5, 4, 2, 3, 1, 7, 6];
|
||||
|
||||
getInnerView() {
|
||||
this.group = svg.elt("g") as SVGGElement;
|
||||
this.group.setAttribute("transform", `translate(2, 2.5) scale(0.6)`)
|
||||
|
||||
const colorIds = ['red', 'yellow', 'blue', 'green', 'black', 'grey'];
|
||||
const colors = ['#f12a21', '#ffd01b', '#006db3', '#00934b', '#000', '#6c2d00'];
|
||||
const colorValue = [5, 4, 2, 3, 1, 7];
|
||||
const colorIds = ['red', 'yellow', 'blue', 'green', 'black', 'grey'];
|
||||
|
||||
let cy = -4;
|
||||
for (let c = 0; c < colorIds.length; c++) {
|
||||
const cx = c % 2 == 0 ? 2.2 : 7.5;
|
||||
if (c % 2 == 0) cy += 5;
|
||||
if (colorIds[c]) {
|
||||
const circle = pxsim.svg.child(this.group, "circle", { 'class': 'sim-color-grid-circle', 'cx': cx, 'cy': cy, 'r': '2', 'style': `fill: ${colors[c]}` });
|
||||
const circle = pxsim.svg.child(this.group, "circle", {
|
||||
'class': `sim-color-grid-circle sim-color-grid-${colorIds[c]}`,
|
||||
'cx': cx, 'cy': cy, 'r': '2', 'style': `fill: ${colors[c]}` });
|
||||
pointerEvents.down.forEach(evid => circle.addEventListener(evid, ev => {
|
||||
this.setColor(colorValue[c]);
|
||||
this.setColor(ColorGridControl.colorValue[c]);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
const whiteCircleWrapper = pxsim.svg.child(this.group, "g", { 'id': 'white-cirlce-wrapper' });
|
||||
pxsim.svg.child(whiteCircleWrapper, "circle", { 'class': 'sim-color-grid-circle', 'cx': 2.2, 'cy': '16', 'r': '2', 'style': `fill: #fff` });
|
||||
pxsim.svg.child(whiteCircleWrapper, "circle", { 'class': 'sim-color-grid-circle sim-color-grid-white', 'cx': 2.2, 'cy': '16', 'r': '2', 'style': `fill: #fff` });
|
||||
pxsim.svg.child(whiteCircleWrapper, "circle", { 'cx': 2.2, 'cy': '16', 'r': '2', 'style': `fill: none;stroke: #94989b;stroke-width: 0.1px` });
|
||||
pointerEvents.down.forEach(evid => whiteCircleWrapper.addEventListener(evid, ev => {
|
||||
this.setColor(6);
|
||||
@ -42,9 +46,34 @@ namespace pxsim.visuals {
|
||||
return 15;
|
||||
}
|
||||
|
||||
public updateState() {
|
||||
if (!this.visible) {
|
||||
return;
|
||||
}
|
||||
const node = this.state;
|
||||
const color = node.getValue();
|
||||
|
||||
for (let c = 0; c < ColorGridControl.colorValue.length; c++) {
|
||||
const colorId = ColorGridControl.colorIds[c];
|
||||
const colorValue = ColorGridControl.colorValue[c];
|
||||
const colorDiv = this.group.getElementsByClassName(`sim-color-grid-${colorId}`)[0] as HTMLElement;
|
||||
|
||||
if (colorValue == color) {
|
||||
pxsim.U.addClass(colorDiv, 'sim-color-selected');
|
||||
} else {
|
||||
pxsim.U.removeClass(colorDiv, 'sim-color-selected');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private setColor(color: number) {
|
||||
const state = this.state;
|
||||
state.setColor(color);
|
||||
const currentColor = state.getValue();
|
||||
if (currentColor == color) {
|
||||
state.setColor(0);
|
||||
} else {
|
||||
state.setColor(color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -15,7 +15,7 @@ namespace pxsim.visuals {
|
||||
}
|
||||
|
||||
private getReporterHeight() {
|
||||
return 58;
|
||||
return 38;
|
||||
}
|
||||
|
||||
private getSliderWidth() {
|
||||
@ -23,10 +23,10 @@ namespace pxsim.visuals {
|
||||
}
|
||||
|
||||
private getSliderHeight() {
|
||||
return 111;
|
||||
return 131;
|
||||
}
|
||||
|
||||
private getMax() {
|
||||
private getMaxValue() {
|
||||
return 100;
|
||||
}
|
||||
|
||||
@ -36,9 +36,9 @@ namespace pxsim.visuals {
|
||||
}
|
||||
const node = this.state;
|
||||
const percentage = node.getValue();
|
||||
const inversePercentage = this.getMax() - percentage;
|
||||
const inversePercentage = this.getMaxValue() - percentage;
|
||||
svg.setGradientValue(this.colorGradient, inversePercentage + "%");
|
||||
this.reporter.textContent = `${parseFloat((percentage).toString()).toFixed(0)}`;
|
||||
this.reporter.textContent = `${parseFloat((percentage).toString()).toFixed(0)}%`;
|
||||
}
|
||||
|
||||
updateColorLevel(pt: SVGPoint, parent: SVGSVGElement, ev: MouseEvent) {
|
||||
@ -47,7 +47,7 @@ namespace pxsim.visuals {
|
||||
const height = bBox.height;
|
||||
let t = Math.max(0, Math.min(1, (height + bBox.top / this.scaleFactor - cur.y / this.scaleFactor) / height));
|
||||
const state = this.state;
|
||||
state.setColor(t * this.getMax());
|
||||
state.setColor(t * this.getMaxValue());
|
||||
}
|
||||
|
||||
getInnerView(parent: SVGSVGElement, globalDefs: SVGDefsElement) {
|
||||
@ -60,7 +60,7 @@ namespace pxsim.visuals {
|
||||
svg.setGradientColors(this.colorGradient, "black", "yellow");
|
||||
|
||||
const reporterGroup = pxsim.svg.child(this.group, "g");
|
||||
reporterGroup.setAttribute("transform", `translate(${this.getWidth() / 2}, 50)`);
|
||||
reporterGroup.setAttribute("transform", `translate(${this.getWidth() / 2}, 20)`);
|
||||
this.reporter = pxsim.svg.child(reporterGroup, "text", { 'text-anchor': 'middle', 'x': 0, 'y': '0', 'class': 'sim-text number large inverted' }) as SVGTextElement;
|
||||
|
||||
const sliderGroup = pxsim.svg.child(this.group, "g");
|
||||
|
@ -7,11 +7,59 @@ namespace pxsim.visuals {
|
||||
private gradient: SVGLinearGradientElement;
|
||||
private slider: SVGGElement;
|
||||
|
||||
private rect: SVGRectElement;
|
||||
|
||||
private reporter: SVGTextElement;
|
||||
|
||||
private static SLIDER_HANDLE_HEIGHT = 26;
|
||||
private static SLIDER_SIDE_PADDING = 6;
|
||||
|
||||
getInnerWidth() {
|
||||
return 111;
|
||||
}
|
||||
|
||||
getInnerHeight() {
|
||||
return 192;
|
||||
}
|
||||
|
||||
private getReporterHeight() {
|
||||
return 38;
|
||||
}
|
||||
|
||||
private getSliderWidth() {
|
||||
return 62;
|
||||
}
|
||||
|
||||
private getSliderHeight() {
|
||||
return 131;
|
||||
}
|
||||
|
||||
private getMaxValue() {
|
||||
return 250; // cm
|
||||
}
|
||||
|
||||
updateState() {
|
||||
if (!this.visible) {
|
||||
return;
|
||||
}
|
||||
const node = this.state;
|
||||
const percentage = node.getValue() / 10; /* convert back to cm */
|
||||
const y = this.getSliderHeight() * percentage / this.getMaxValue();
|
||||
this.slider.setAttribute("transform", `translate(0, ${y - DistanceSliderControl.SLIDER_HANDLE_HEIGHT / 2})`);
|
||||
// Update reporter text
|
||||
this.reporter.textContent = `${parseFloat((percentage).toString()).toFixed(0)}cm`;
|
||||
}
|
||||
|
||||
updateSliderValue(pt: SVGPoint, parent: SVGSVGElement, ev: MouseEvent) {
|
||||
let cur = svg.cursorPoint(pt, parent, ev);
|
||||
const bBox = this.rect.getBoundingClientRect();
|
||||
const height = bBox.height;
|
||||
let t = Math.max(0, Math.min(1, (height + bBox.top / this.scaleFactor - cur.y / this.scaleFactor) / height));
|
||||
|
||||
const state = this.state;
|
||||
state.setDistance((1 - t) * (this.getMaxValue()));
|
||||
}
|
||||
|
||||
getInnerView(parent: SVGSVGElement, globalDefs: SVGDefsElement) {
|
||||
let gid = "gradient-slider-" + this.getPort();
|
||||
this.group = svg.elt("g") as SVGGElement;
|
||||
@ -28,13 +76,14 @@ namespace pxsim.visuals {
|
||||
this.group = svg.elt("g") as SVGGElement;
|
||||
|
||||
const reporterGroup = pxsim.svg.child(this.group, "g");
|
||||
reporterGroup.setAttribute("transform", `translate(${this.getWidth() / 2}, 42)`);
|
||||
reporterGroup.setAttribute("transform", `translate(${this.getWidth() / 2}, 20)`);
|
||||
this.reporter = pxsim.svg.child(reporterGroup, "text", { 'text-anchor': 'middle', 'x': 0, 'y': '0', 'class': 'sim-text number large inverted' }) as SVGTextElement;
|
||||
|
||||
const sliderGroup = pxsim.svg.child(this.group, "g");
|
||||
sliderGroup.setAttribute("transform", `translate(${this.getWidth() / 2 - this.getSliderWidth() / 2}, ${this.getReporterHeight()})`)
|
||||
sliderGroup.setAttribute("transform", `translate(${this.getInnerWidth() / 2 - this.getSliderWidth() / 2}, ${this.getReporterHeight()})`)
|
||||
|
||||
const rect = pxsim.svg.child(sliderGroup, "rect", { 'x': DistanceSliderControl.SLIDER_SIDE_PADDING, 'y': 2, 'width': this.getSliderWidth() - DistanceSliderControl.SLIDER_SIDE_PADDING * 2, 'height': this.getSliderHeight(), 'style': `fill: url(#${gid})` });
|
||||
this.rect = rect as SVGRectElement;
|
||||
|
||||
this.slider = pxsim.svg.child(sliderGroup, "g", { "transform": "translate(0,0)" }) as SVGGElement;
|
||||
const sliderInner = pxsim.svg.child(this.slider, "g");
|
||||
@ -48,7 +97,7 @@ namespace pxsim.visuals {
|
||||
height: this.getInnerHeight(),
|
||||
opacity: 0,
|
||||
cursor: '-webkit-grab'
|
||||
})
|
||||
}) as SVGRectElement;
|
||||
|
||||
let pt = parent.createSVGPoint();
|
||||
let captured = false;
|
||||
@ -72,56 +121,6 @@ namespace pxsim.visuals {
|
||||
return this.group;
|
||||
}
|
||||
|
||||
getInnerHeight() {
|
||||
return 192;
|
||||
}
|
||||
|
||||
getInnerWidth() {
|
||||
return 111;
|
||||
}
|
||||
|
||||
private getReporterHeight() {
|
||||
return 50;
|
||||
}
|
||||
|
||||
private getSliderHeight() {
|
||||
return 110;
|
||||
}
|
||||
|
||||
private getSliderWidth() {
|
||||
return 62;
|
||||
}
|
||||
|
||||
updateState() {
|
||||
if (!this.visible) {
|
||||
return;
|
||||
}
|
||||
const node = this.state;
|
||||
const percentage = node.getValue() / 10; /* convert back to cm */
|
||||
const y = this.getSliderHeight() * percentage / this.getMax();
|
||||
this.slider.setAttribute("transform", `translate(0, ${y - DistanceSliderControl.SLIDER_HANDLE_HEIGHT / 2})`);
|
||||
// Update reporter text
|
||||
this.reporter.textContent = `${parseFloat((percentage).toString()).toFixed(0)}`;
|
||||
}
|
||||
|
||||
private updateSliderValue(pt: SVGPoint, parent: SVGSVGElement, ev: MouseEvent) {
|
||||
let cur = svg.cursorPoint(pt, parent, ev);
|
||||
const height = this.getSliderHeight();
|
||||
const bBox = this.content.getBoundingClientRect();
|
||||
let t = Math.max(0, Math.min(1, (DistanceSliderControl.SLIDER_HANDLE_HEIGHT + height + bBox.top / this.scaleFactor - cur.y / this.scaleFactor) / height))
|
||||
|
||||
const state = this.state;
|
||||
state.setDistance((1 - t) * (this.getMax()));
|
||||
}
|
||||
|
||||
private getMin() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private getMax() {
|
||||
return 250; //cm
|
||||
}
|
||||
|
||||
private getGradientDefinition(): LinearGradientDefinition {
|
||||
return {
|
||||
stops: [
|
||||
|
@ -7,11 +7,60 @@ namespace pxsim.visuals {
|
||||
private gradient: SVGLinearGradientElement;
|
||||
private slider: SVGGElement;
|
||||
|
||||
private rect: SVGRectElement;
|
||||
|
||||
private reporter: SVGTextElement;
|
||||
|
||||
private static SLIDER_HANDLE_HEIGHT = 26;
|
||||
private static SLIDER_SIDE_PADDING = 6;
|
||||
|
||||
getInnerWidth() {
|
||||
return 111;
|
||||
}
|
||||
|
||||
getInnerHeight() {
|
||||
return 192;
|
||||
}
|
||||
|
||||
private getReporterHeight() {
|
||||
return 38;
|
||||
}
|
||||
|
||||
private getSliderWidth() {
|
||||
return 62;
|
||||
}
|
||||
|
||||
private getSliderHeight() {
|
||||
return 131;
|
||||
}
|
||||
|
||||
private getMaxValue() {
|
||||
return 100;
|
||||
}
|
||||
|
||||
updateState() {
|
||||
if (!this.visible) {
|
||||
return;
|
||||
}
|
||||
const node = this.state;
|
||||
const percentage = node.getValue();
|
||||
const y = this.getSliderHeight() * percentage / this.getMaxValue();
|
||||
this.slider.setAttribute("transform", `translate(0, ${y - ProximitySliderControl.SLIDER_HANDLE_HEIGHT / 2})`);
|
||||
// Update reporter text
|
||||
this.reporter.textContent = `${parseFloat((percentage).toString()).toFixed(0)}`;
|
||||
}
|
||||
|
||||
private updateSliderValue(pt: SVGPoint, parent: SVGSVGElement, ev: MouseEvent) {
|
||||
let cur = svg.cursorPoint(pt, parent, ev);
|
||||
const bBox = this.rect.getBoundingClientRect();
|
||||
const height = bBox.height;
|
||||
let t = Math.max(0, Math.min(1, (height + bBox.top / this.scaleFactor - cur.y / this.scaleFactor) / height));
|
||||
|
||||
const state = this.state;
|
||||
const v = Math.floor((1 - t) * (this.getMaxValue()));
|
||||
state.setPromixity(v);
|
||||
}
|
||||
|
||||
getInnerView(parent: SVGSVGElement, globalDefs: SVGDefsElement) {
|
||||
let gid = "gradient-slider-" + this.getId();
|
||||
this.group = svg.elt("g") as SVGGElement;
|
||||
@ -27,13 +76,14 @@ namespace pxsim.visuals {
|
||||
this.group = svg.elt("g") as SVGGElement;
|
||||
|
||||
const reporterGroup = pxsim.svg.child(this.group, "g");
|
||||
reporterGroup.setAttribute("transform", `translate(${this.getWidth() / 2}, 42)`);
|
||||
reporterGroup.setAttribute("transform", `translate(${this.getWidth() / 2}, 20)`);
|
||||
this.reporter = pxsim.svg.child(reporterGroup, "text", { 'text-anchor': 'middle', 'x': 0, 'y': '0', 'class': 'sim-text number large inverted' }) as SVGTextElement;
|
||||
|
||||
const sliderGroup = pxsim.svg.child(this.group, "g");
|
||||
sliderGroup.setAttribute("transform", `translate(${this.getWidth() / 2 - this.getSliderWidth() / 2}, ${this.getReporterHeight()})`)
|
||||
sliderGroup.setAttribute("transform", `translate(${this.getInnerWidth() / 2 - this.getSliderWidth() / 2}, ${this.getReporterHeight()})`)
|
||||
|
||||
const rect = pxsim.svg.child(sliderGroup, "rect", { 'x': ProximitySliderControl.SLIDER_SIDE_PADDING, 'y': 2, 'width': this.getSliderWidth() - ProximitySliderControl.SLIDER_SIDE_PADDING * 2, 'height': this.getSliderHeight(), 'style': `fill: url(#${gid})` });
|
||||
this.rect = rect as SVGRectElement;
|
||||
|
||||
this.slider = pxsim.svg.child(sliderGroup, "g", { "transform": "translate(0,0)" }) as SVGGElement;
|
||||
const sliderInner = pxsim.svg.child(this.slider, "g");
|
||||
@ -71,57 +121,6 @@ namespace pxsim.visuals {
|
||||
return this.group;
|
||||
}
|
||||
|
||||
getInnerHeight() {
|
||||
return 192;
|
||||
}
|
||||
|
||||
getInnerWidth() {
|
||||
return 111;
|
||||
}
|
||||
|
||||
private getReporterHeight() {
|
||||
return 50;
|
||||
}
|
||||
|
||||
private getSliderHeight() {
|
||||
return 110;
|
||||
}
|
||||
|
||||
private getSliderWidth() {
|
||||
return 62;
|
||||
}
|
||||
|
||||
updateState() {
|
||||
if (!this.visible) {
|
||||
return;
|
||||
}
|
||||
const node = this.state;
|
||||
const percentage = node.getValue();
|
||||
const y = this.getSliderHeight() * percentage / this.getMax();
|
||||
this.slider.setAttribute("transform", `translate(0, ${y - ProximitySliderControl.SLIDER_HANDLE_HEIGHT / 2})`);
|
||||
// Update reporter text
|
||||
this.reporter.textContent = `${parseFloat((percentage).toString()).toFixed(0)}`;
|
||||
}
|
||||
|
||||
private updateSliderValue(pt: SVGPoint, parent: SVGSVGElement, ev: MouseEvent) {
|
||||
let cur = svg.cursorPoint(pt, parent, ev);
|
||||
const height = this.getSliderHeight();
|
||||
const bBox = this.content.getBoundingClientRect();
|
||||
let t = Math.max(0, Math.min(1, (ProximitySliderControl.SLIDER_HANDLE_HEIGHT + height + bBox.top / this.scaleFactor - cur.y / this.scaleFactor) / height))
|
||||
|
||||
const state = this.state;
|
||||
const v = Math.floor((1 - t) * (this.getMax()));
|
||||
state.setPromixity(v);
|
||||
}
|
||||
|
||||
private getMin() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private getMax() {
|
||||
return 100;
|
||||
}
|
||||
|
||||
private getGradientDefinition(): LinearGradientDefinition {
|
||||
return {
|
||||
stops: [
|
||||
|
@ -13,10 +13,10 @@ namespace pxsim.visuals {
|
||||
this.group = svg.elt("g") as SVGGElement;
|
||||
|
||||
const sliderGroup = pxsim.svg.child(this.group, "g");
|
||||
sliderGroup.setAttribute("transform", `translate(5, ${10 + this.getTopPadding()})`)
|
||||
sliderGroup.setAttribute("transform", `translate(10,0)`);
|
||||
|
||||
const rotationLine = pxsim.svg.child(sliderGroup, "g");
|
||||
pxsim.svg.child(rotationLine, "path", { 'transform': 'translate(5.11 -31.1)', 'd': 'M68.71,99.5l6.1-8S61.3,79.91,42.69,78.35,12,83.14,6.49,85.63a48.69,48.69,0,0,0-9.6,5.89L3.16,99.3S19.27,87.7,37.51,87.94,68.71,99.5,68.71,99.5Z', 'style': 'fill: #626262' });
|
||||
pxsim.svg.child(rotationLine, "path", { 'transform': 'translate(7.11 -31.1)', 'd': 'M68.71,99.5l6.1-8S61.3,79.91,42.69,78.35,12,83.14,6.49,85.63a48.69,48.69,0,0,0-9.6,5.89L3.16,99.3S19.27,87.7,37.51,87.94,68.71,99.5,68.71,99.5Z', 'style': 'fill: #626262' });
|
||||
|
||||
this.slider = pxsim.svg.child(sliderGroup, "g") as SVGGElement;
|
||||
const handleInner = pxsim.svg.child(sliderGroup, "g");
|
||||
@ -52,8 +52,8 @@ namespace pxsim.visuals {
|
||||
return this.group;
|
||||
}
|
||||
|
||||
private getTopPadding() {
|
||||
return this.getInnerHeight() / 4;
|
||||
getInnerWidth() {
|
||||
return RotationSliderControl.SLIDER_WIDTH * 1.5;
|
||||
}
|
||||
|
||||
updateState() {
|
||||
|
@ -13,6 +13,8 @@ namespace pxsim.visuals {
|
||||
|
||||
export const MAX_MODULE_WIDTH = 100;
|
||||
|
||||
export const CLOSE_ICON_GAP_MULTIPLIER = 0.3;
|
||||
|
||||
export interface LayoutElement extends View {
|
||||
getId(): number;
|
||||
getPort(): number;
|
||||
@ -33,6 +35,9 @@ namespace pxsim.visuals {
|
||||
private inputCloseIcons: View[] = [];
|
||||
private outputCloseIcons: View[] = [];
|
||||
|
||||
private inputBackgroundViews: View[] = [];
|
||||
private outputBackgroundViews: View[] = [];
|
||||
|
||||
private inputWires: WireView[] = [];
|
||||
private outputWires: WireView[] = [];
|
||||
|
||||
@ -119,7 +124,7 @@ namespace pxsim.visuals {
|
||||
else this.setlectBrick();
|
||||
}
|
||||
|
||||
public setInput(port: number, view: LayoutElement, control?: View, closeIcon?: View) {
|
||||
public setInput(port: number, view: LayoutElement, control?: View, closeIcon?: View, backgroundView?: View) {
|
||||
if (this.inputs[port] != view || this.inputControls[port] != control) {
|
||||
if (this.inputs[port]) {
|
||||
// Remove current input
|
||||
@ -131,10 +136,12 @@ namespace pxsim.visuals {
|
||||
}
|
||||
this.inputControls[port] = control;
|
||||
this.inputCloseIcons[port] = closeIcon;
|
||||
this.inputBackgroundViews[port] = backgroundView;
|
||||
|
||||
this.inputContainers[port].clear();
|
||||
this.inputContainers[port].addView(view);
|
||||
|
||||
if (control && backgroundView) this.inputContainers[port].addView(backgroundView);
|
||||
this.inputContainers[port].addView(view);
|
||||
if (control) this.inputContainers[port].addView(control);
|
||||
|
||||
if (view.hasClick()) view.registerClick((ev: any) => {
|
||||
@ -155,7 +162,7 @@ namespace pxsim.visuals {
|
||||
this.position();
|
||||
}
|
||||
|
||||
public setOutput(port: number, view: LayoutElement, control?: View, closeIcon?: View) {
|
||||
public setOutput(port: number, view: LayoutElement, control?: View, closeIcon?: View, backgroundView?: View) {
|
||||
if (this.outputs[port] != view || this.outputControls[port] != control) {
|
||||
if (this.outputs[port]) {
|
||||
// Remove current output
|
||||
@ -167,10 +174,12 @@ namespace pxsim.visuals {
|
||||
}
|
||||
this.outputControls[port] = control;
|
||||
this.outputCloseIcons[port] = closeIcon;
|
||||
this.outputBackgroundViews[port] = backgroundView;
|
||||
|
||||
this.outputContainers[port].clear();
|
||||
this.outputContainers[port].addView(view);
|
||||
|
||||
if (control && backgroundView) this.outputContainers[port].addView(backgroundView);
|
||||
this.outputContainers[port].addView(view);
|
||||
if (control) this.outputContainers[port].addView(control);
|
||||
|
||||
if (view.hasClick()) view.registerClick((ev: any) => {
|
||||
@ -277,35 +286,48 @@ namespace pxsim.visuals {
|
||||
|
||||
const modulePadding = this.getModulePadding();
|
||||
const moduleSpacing = contentWidth / 4;
|
||||
const moduleWidth = this.getInnerModuleWidth();
|
||||
let currentX = this.getModulePadding();
|
||||
let currentY = 0;
|
||||
this.outputs.forEach((n, i) => {
|
||||
this.outputContainers[i].translate(currentX, currentY);
|
||||
this.outputContainers[i].translate(currentX + (this.getAbosluteModuleWidth() - this.getInnerModuleWidth()) / 2, currentY);
|
||||
if (this.outputs[i]) {
|
||||
const view = this.outputs[i];
|
||||
const outputPadding = this.getInnerModuleWidth() * view.getPaddingRatio();
|
||||
const desiredOutputWidth = this.getInnerModuleWidth() - outputPadding * 2;
|
||||
const outputWidth = Math.min(desiredOutputWidth, MAX_MODULE_WIDTH);
|
||||
const outputHeight = this.getModuleHeight();
|
||||
const outputWidth = this.getInnerModuleWidth();
|
||||
|
||||
// Translate and resize view
|
||||
view.resize(outputWidth, outputHeight);
|
||||
const viewHeight = view.getInnerHeight() / view.getInnerWidth() * outputWidth;
|
||||
view.translate(outputPadding + ((desiredOutputWidth - outputWidth) / 2), outputHeight - viewHeight, true);
|
||||
view.resize(outputWidth - outputPadding * 2, outputHeight);
|
||||
// const viewHeight = view.getInnerHeight() / view.getInnerWidth() * outputWidth;
|
||||
// view.translate(outputPadding + ((desiredOutputWidth - outputWidth) / 2), outputHeight - viewHeight, true);
|
||||
const viewHeight = view.getActualHeight();
|
||||
view.translate(outputPadding, outputHeight - viewHeight, true);
|
||||
|
||||
// Resize control
|
||||
const control = this.outputControls[i];
|
||||
if (control) {
|
||||
control.resize(this.getInnerModuleWidth(), outputHeight);
|
||||
const controlWidth = outputWidth;
|
||||
const closeIconOffset = (this.getCloseIconSize() * (1 + CLOSE_ICON_GAP_MULTIPLIER));
|
||||
const controlHeight = outputHeight - closeIconOffset;
|
||||
control.resize(controlWidth, controlHeight);
|
||||
control.translate((controlWidth - control.getActualWidth()) / 2,
|
||||
closeIconOffset + ((controlHeight - control.getActualHeight()) / 2), true)
|
||||
|
||||
// Translate close icon
|
||||
// Translate and resize close icon
|
||||
const closeIcon = this.outputCloseIcons[i];
|
||||
if (closeIcon) {
|
||||
const closeIconWidth = closeIcon.getWidth();
|
||||
closeIcon.translate(this.getInnerModuleWidth() / 2 - closeIconWidth / 2, 0);
|
||||
const closeIconSize = this.getCloseIconSize();
|
||||
closeIcon.resize(closeIconSize, closeIconSize);
|
||||
closeIcon.translate((outputWidth - closeIcon.getActualWidth()) / 2, (CLOSE_ICON_GAP_MULTIPLIER * closeIcon.getActualHeight()), true);
|
||||
}
|
||||
}
|
||||
|
||||
// Resize background
|
||||
const backgroundView = this.inputBackgroundViews[i];
|
||||
if (backgroundView) {
|
||||
backgroundView.resize(this.getInnerModuleWidth(), outputHeight);
|
||||
backgroundView.translate(0, 0, true)
|
||||
}
|
||||
}
|
||||
currentX += moduleSpacing;
|
||||
})
|
||||
@ -341,30 +363,41 @@ namespace pxsim.visuals {
|
||||
currentY += brickHeight + this.getWiringHeight();
|
||||
|
||||
this.inputs.forEach((n, i) => {
|
||||
this.inputContainers[i].translate(currentX, currentY);
|
||||
this.inputContainers[i].translate(currentX + (this.getAbosluteModuleWidth() - this.getInnerModuleWidth()) / 2, currentY);
|
||||
if (this.inputs[i]) {
|
||||
const view = this.inputs[i];
|
||||
const inputPadding = this.getInnerModuleWidth() * view.getPaddingRatio();
|
||||
const desiredInputWidth = this.getInnerModuleWidth() - inputPadding * 2;
|
||||
const inputWidth = Math.min(desiredInputWidth, MAX_MODULE_WIDTH);
|
||||
const inputHeight = this.getModuleHeight();
|
||||
const inputWidth = this.getInnerModuleWidth();
|
||||
|
||||
// Translate and resize view
|
||||
view.resize(inputWidth, inputHeight);
|
||||
view.translate(inputPadding + ((desiredInputWidth - inputWidth) / 2), 0, true);
|
||||
view.resize(inputWidth - inputPadding * 2, inputHeight);
|
||||
const viewHeight = view.getActualHeight();
|
||||
view.translate(inputPadding, 0, true);
|
||||
|
||||
// Resize control
|
||||
const control = this.inputControls[i];
|
||||
if (control) {
|
||||
control.resize(this.getInnerModuleWidth(), inputHeight);
|
||||
const controlWidth = inputWidth;
|
||||
const controlHeight = inputHeight - viewHeight - (this.getCloseIconSize() * (1 + CLOSE_ICON_GAP_MULTIPLIER));
|
||||
control.resize(controlWidth, controlHeight);
|
||||
control.translate((controlWidth - control.getActualWidth()) / 2,
|
||||
viewHeight + ((controlHeight - control.getActualHeight()) / 2), true)
|
||||
|
||||
// Translate and resize close icon
|
||||
const closeIcon = this.inputCloseIcons[i];
|
||||
if (closeIcon) {
|
||||
const closeIconWidth = closeIcon.getWidth();
|
||||
const closeIconHeight = closeIcon.getHeight();
|
||||
closeIcon.translate(this.getInnerModuleWidth() / 2 - closeIconWidth / 2, this.getModuleHeight() - closeIconHeight);
|
||||
const closeIconSize = this.getCloseIconSize();
|
||||
closeIcon.resize(closeIconSize, closeIconSize);
|
||||
closeIcon.translate((inputWidth - closeIcon.getActualWidth()) / 2, inputHeight - ((1 + CLOSE_ICON_GAP_MULTIPLIER) * closeIcon.getActualHeight()), true);
|
||||
}
|
||||
}
|
||||
|
||||
// Resize background
|
||||
const backgroundView = this.inputBackgroundViews[i];
|
||||
if (backgroundView) {
|
||||
backgroundView.resize(this.getInnerModuleWidth(), inputHeight, true);
|
||||
backgroundView.translate(0, 0, true)
|
||||
}
|
||||
}
|
||||
currentX += moduleSpacing;
|
||||
@ -394,7 +427,7 @@ namespace pxsim.visuals {
|
||||
|
||||
public getModuleBounds() {
|
||||
return {
|
||||
width: this.width / 4,
|
||||
width: Math.min(this.getAbosluteModuleWidth(), MAX_MODULE_WIDTH),
|
||||
height: this.getModuleHeight()
|
||||
}
|
||||
}
|
||||
@ -407,8 +440,16 @@ namespace pxsim.visuals {
|
||||
return this.getModuleBounds().width - (this.getModulePadding() * 2);
|
||||
}
|
||||
|
||||
public getAbosluteModuleWidth() {
|
||||
return this.width / 4;
|
||||
}
|
||||
|
||||
public getModuleHeight() {
|
||||
return this.height * MODULE_HEIGHT_RATIO;
|
||||
}
|
||||
|
||||
public getCloseIconSize() {
|
||||
return this.getInnerModuleWidth() / 4;
|
||||
}
|
||||
}
|
||||
}
|
@ -5,6 +5,8 @@ namespace pxsim.visuals {
|
||||
|
||||
private control: ColorGridControl;
|
||||
|
||||
private static sensor_hole_id = 'color_sensor_white_big';
|
||||
|
||||
constructor(port: number) {
|
||||
super(COLOR_SENSOR_SVG, "color", NodeType.ColorSensor, port);
|
||||
}
|
||||
@ -19,7 +21,22 @@ namespace pxsim.visuals {
|
||||
|
||||
public updateState() {
|
||||
super.updateState();
|
||||
// TODO: show different color modes
|
||||
|
||||
const colorState = ev3board().getInputNodes()[this.port];
|
||||
if (!colorState) return;
|
||||
const mode = colorState.getMode();
|
||||
|
||||
switch (mode) {
|
||||
case ColorSensorMode.Colors: this.updateSensorLightVisual('#0062DD'); return; // blue
|
||||
case ColorSensorMode.Reflected: this.updateSensorLightVisual('#F86262'); return; // red
|
||||
case ColorSensorMode.Ambient: this.updateSensorLightVisual('#67C3E2'); return; // light blue
|
||||
}
|
||||
this.updateSensorLightVisual('#ffffff');
|
||||
}
|
||||
|
||||
private updateSensorLightVisual(color: string) {
|
||||
const sensorHole = this.content.getElementById(this.normalizeId(ColorSensorView.sensor_hole_id)) as SVGCircleElement;
|
||||
sensorHole.style.fill = color;
|
||||
}
|
||||
}
|
||||
}
|
@ -107,7 +107,7 @@ namespace pxsim.visuals {
|
||||
public attachEvents() {
|
||||
}
|
||||
|
||||
public resize(width: number, height: number) {
|
||||
public resize(width: number, height: number, strict?: boolean) {
|
||||
super.resize(width, height);
|
||||
this.updateDimensions(width, height);
|
||||
}
|
||||
@ -120,6 +120,7 @@ namespace pxsim.visuals {
|
||||
const newWidth = currentWidth / currentHeight * height;
|
||||
this.content.setAttribute('width', `${width}`);
|
||||
this.content.setAttribute('height', `${newHeight}`);
|
||||
this.height = newHeight;
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,16 +139,22 @@ namespace pxsim.visuals {
|
||||
|
||||
protected updateOpacity() {
|
||||
if (this.rendered) {
|
||||
const opacity = this.selected ? 0.2 : 1;
|
||||
const opacity = this.selected && this.fadeWhenSelected() ? 0.2 : 1;
|
||||
if (this.hasClick() && this.opacity != opacity) {
|
||||
this.opacity = opacity;
|
||||
this.setOpacity(this.opacity);
|
||||
}
|
||||
if (this.hasClick()) {
|
||||
if (this.selected) this.content.style.cursor = "";
|
||||
else this.content.style.cursor = "pointer";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fadeWhenSelected() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected setOpacity(opacity: number) {
|
||||
this.element.setAttribute("opacity", `${opacity}`);
|
||||
}
|
||||
|
@ -6,14 +6,16 @@ namespace pxsim.visuals {
|
||||
|
||||
constructor(xml: string, prefix: string, id: NodeType, port: NodeType) {
|
||||
super(xml, prefix, id, port);
|
||||
// Shown by default
|
||||
this.selected = true;
|
||||
}
|
||||
|
||||
public getSelected() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public hasClose() {
|
||||
protected fadeWhenSelected() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public hasBackground() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -130,11 +130,19 @@ namespace pxsim.visuals {
|
||||
return this.element;
|
||||
}
|
||||
|
||||
public resize(width: number, height: number) {
|
||||
public resize(width: number, height: number, strict?: boolean) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public getActualHeight() {
|
||||
return this.height;
|
||||
}
|
||||
|
||||
public getActualWidth() {
|
||||
return this.width;
|
||||
}
|
||||
|
||||
private updateTransform() {
|
||||
if (this.rendered) {
|
||||
let left = this.left;
|
||||
@ -212,10 +220,6 @@ namespace pxsim.visuals {
|
||||
}
|
||||
}
|
||||
|
||||
public hasClose() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected setChangedState() {
|
||||
this.changed = true;
|
||||
}
|
||||
@ -225,6 +229,10 @@ namespace pxsim.visuals {
|
||||
this.changed = false;
|
||||
return res;
|
||||
}
|
||||
|
||||
public hasBackground() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class SimView<T extends BaseNode> extends View implements LayoutElement {
|
||||
@ -272,9 +280,13 @@ namespace pxsim.visuals {
|
||||
}
|
||||
|
||||
public clear() {
|
||||
const markForRemoval: Element[] = [];
|
||||
forEachElement(this.element.childNodes, e => {
|
||||
this.element.removeChild(e);
|
||||
markForRemoval.push(e);
|
||||
});
|
||||
markForRemoval.forEach(e => {
|
||||
this.element.removeChild(e);
|
||||
})
|
||||
}
|
||||
|
||||
public onComponentInjected() {
|
||||
|
Loading…
Reference in New Issue
Block a user