From 33226981d0ee568df0eca33a2c17581613a0864f Mon Sep 17 00:00:00 2001 From: Nils Petter Fremming Date: Sun, 28 Jul 2024 18:44:17 +0200 Subject: [PATCH 01/10] Fix comment and small stuff --- .../src/architecture/base/commands/BaseCommand.ts | 2 +- .../src/architecture/base/undo/DomainObjectTransaction.ts | 2 +- react-components/src/architecture/base/undo/Transaction.ts | 2 +- .../src/components/Architecture/CommandButton.tsx | 3 ++- .../src/components/Architecture/RevealButtons.tsx | 2 +- react-components/src/components/Architecture/types.ts | 2 +- react-components/src/components/Architecture/utilities.ts | 2 +- react-components/stories/Toolbar.stories.tsx | 4 ++-- 8 files changed, 10 insertions(+), 9 deletions(-) diff --git a/react-components/src/architecture/base/commands/BaseCommand.ts b/react-components/src/architecture/base/commands/BaseCommand.ts index 02dbf816681..4aba464afc7 100644 --- a/react-components/src/architecture/base/commands/BaseCommand.ts +++ b/react-components/src/architecture/base/commands/BaseCommand.ts @@ -40,7 +40,7 @@ export abstract class BaseCommand { } // ================================================== - // VIRTUAL METHODS (To be override) + // VIRTUAL METHODS (To be overridden) // ================================================= public get name(): string { diff --git a/react-components/src/architecture/base/undo/DomainObjectTransaction.ts b/react-components/src/architecture/base/undo/DomainObjectTransaction.ts index 91d37d31a0d..f0e63857349 100644 --- a/react-components/src/architecture/base/undo/DomainObjectTransaction.ts +++ b/react-components/src/architecture/base/undo/DomainObjectTransaction.ts @@ -34,7 +34,7 @@ export class DomainObjectTransaction extends Transaction { } // ================================================== - // VIRTUAL METHODS (To be override) + // VIRTUAL METHODS (To be overridden) // ================================================= protected override undoCore( diff --git a/react-components/src/architecture/base/undo/Transaction.ts b/react-components/src/architecture/base/undo/Transaction.ts index c18a7ba3c1e..0caafb4687e 100644 --- a/react-components/src/architecture/base/undo/Transaction.ts +++ b/react-components/src/architecture/base/undo/Transaction.ts @@ -33,7 +33,7 @@ export abstract class Transaction { } // ================================================== - // VIRTUAL METHODS (To be override) + // VIRTUAL METHODS (To be overridden) // ================================================= protected abstract undoCore( diff --git a/react-components/src/components/Architecture/CommandButton.tsx b/react-components/src/components/Architecture/CommandButton.tsx index a7ef18a2551..9e38d5acc56 100644 --- a/react-components/src/components/Architecture/CommandButton.tsx +++ b/react-components/src/components/Architecture/CommandButton.tsx @@ -1,5 +1,5 @@ /*! - * Copyright 2023 Cognite AS + * Copyright 2024 Cognite AS */ import { type ReactElement, useState, useEffect, useMemo, useCallback } from 'react'; @@ -53,6 +53,7 @@ export const CommandButton = ({ return ( } + disabled={tooltip === undefined} appendTo={document.body} placement={placement}> - - + {selectedLabel} + + + + ); }; + +export function createMenuItem( + command: BaseCommand, + t: TranslateDelegate, + postAction: () => void +): ReactElement { + return ( + { + command.invoke(); + postAction(); + }}> + {command.getLabel(t)} + + ); +} diff --git a/react-components/src/components/Architecture/SettingsButton.tsx b/react-components/src/components/Architecture/SettingsButton.tsx new file mode 100644 index 00000000000..d5e12fa5eb9 --- /dev/null +++ b/react-components/src/components/Architecture/SettingsButton.tsx @@ -0,0 +1,205 @@ +/*! + * Copyright 2024 Cognite AS + */ + +import { useCallback, useEffect, useMemo, useState, type ReactElement } from 'react'; +import { + Button, + Dropdown, + Menu, + Tooltip as CogsTooltip, + type IconType, + Slider +} from '@cognite/cogs.js'; +import { useTranslation } from '../i18n/I18n'; +import { type BaseCommand } from '../../architecture/base/commands/BaseCommand'; +import { useRenderTarget } from '../RevealCanvas/ViewerContext'; +import { + getButtonType, + getDefaultCommand, + getFlexDirection, + getTooltipPlacement, + getIcon +} from './utilities'; +import { LabelWithShortcut } from './LabelWithShortcut'; +import { type TranslateDelegate } from '../../architecture/base/utilities/TranslateKey'; +import { ToggleCommand } from '../../architecture/base/commands/value/ToggleCommand'; +import { SliderCommand } from '../../architecture/base/commands/value/SliderCommand'; +import styled from 'styled-components'; +import { SettingsCommand } from '../../architecture/base/concreteCommands/SettingsCommand'; +import { createButton } from './CommandButtons'; +import { BaseOptionCommand } from '../../architecture/base/commands/BaseOptionCommand'; +import { OptionButton } from './OptionButton'; + +export const SettingsButton = ({ + inputCommand, + isHorizontal = false +}: { + inputCommand: SettingsCommand; + isHorizontal: boolean; +}): ReactElement => { + const renderTarget = useRenderTarget(); + const { t } = useTranslation(); + const command = useMemo(() => getDefaultCommand(inputCommand, renderTarget), []); + + const [isOpen, setOpen] = useState(false); + const [isEnabled, setEnabled] = useState(true); + const [isVisible, setVisible] = useState(true); + const [uniqueId, setUniqueId] = useState(0); + const [icon, setIcon] = useState(undefined); + + const update = useCallback((command: BaseCommand) => { + setEnabled(command.isEnabled); + setVisible(command.isVisible); + setUniqueId(command.uniqueId); + setIcon(getIcon(command)); + }, []); + + useEffect(() => { + update(command); + command.addEventListener(update); + return () => { + command.removeEventListener(update); + }; + }, [command]); + + if (!(command instanceof SettingsCommand)) { + return <>; + } + if (!isVisible) { + return <>; + } + const placement = getTooltipPlacement(isHorizontal); + const tooltip = command.getLabel(t); + const shortcut = command.getShortCutKeys(); + const flexDirection = getFlexDirection(isHorizontal); + const commands = command.commands; + + return ( + } + disabled={tooltip === undefined} + appendTo={document.body} + placement={placement}> + + {commands.map((command, _index): ReactElement | undefined => { + return createMenuItem(command, t); + })} + + }> + ); }; diff --git a/react-components/src/components/Architecture/CommandButtons.tsx b/react-components/src/components/Architecture/CommandButtons.tsx index 74aa4b3a11e..32c6909a699 100644 --- a/react-components/src/components/Architecture/CommandButtons.tsx +++ b/react-components/src/components/Architecture/CommandButtons.tsx @@ -11,13 +11,23 @@ import { CommandButton } from './CommandButton'; import { SettingsButton } from './SettingsButton'; import { SettingsCommand } from '../../architecture/base/concreteCommands/SettingsCommand'; -export function createButton(command: BaseCommand, isHorizontal = false): ReactElement { +export function createButton( + command: BaseCommand, + isHorizontal = false, + usedInSettings = false +): ReactElement { if (command instanceof SettingsCommand) { return ; } else if (command instanceof BaseOptionCommand) { return ; } else { - return ; + return ( + + ); } } diff --git a/react-components/src/components/Architecture/OptionButton.tsx b/react-components/src/components/Architecture/OptionButton.tsx index 82c00cdc5a3..c77f0590d48 100644 --- a/react-components/src/components/Architecture/OptionButton.tsx +++ b/react-components/src/components/Architecture/OptionButton.tsx @@ -68,7 +68,7 @@ export const OptionButton = ({ return <>; } const placement = getTooltipPlacement(isHorizontal); - const tooltip = usedInSettings ? undefined : command.getLabel(t); + const label = usedInSettings ? undefined : command.getLabel(t); const shortcut = command.getShortCutKeys(); const flexDirection = getFlexDirection(isHorizontal); const options = command.options; @@ -77,8 +77,8 @@ export const OptionButton = ({ return (
} - disabled={tooltip === undefined} + content={} + disabled={usedInSettings || label === undefined} appendTo={document.body} placement={placement}> ; } const placement = getTooltipPlacement(isHorizontal); - const tooltip = command.getLabel(t); + const label = command.getLabel(t); const shortcut = command.getShortCutKeys(); const flexDirection = getFlexDirection(isHorizontal); const commands = command.commands; return ( } - disabled={tooltip === undefined} + content={} + disabled={label === undefined} appendTo={document.body} placement={placement}> { setOpen((prevState) => !prevState); @@ -127,7 +127,7 @@ export function createMenuItem( if (command.isToggle) { return createToggle(command, t); } - return createButton(command); + return createButton(command, false, true); } export function createToggle(command: BaseCommand, t: TranslateDelegate): ReactElement { From 4830bf56ee536069f806a334249e5dbd432da20c Mon Sep 17 00:00:00 2001 From: Nils Petter Fremming Date: Mon, 29 Jul 2024 08:55:05 +0200 Subject: [PATCH 06/10] Update SettingsButton.tsx --- .../src/components/Architecture/SettingsButton.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/react-components/src/components/Architecture/SettingsButton.tsx b/react-components/src/components/Architecture/SettingsButton.tsx index ed537a3947c..3d12f975b41 100644 --- a/react-components/src/components/Architecture/SettingsButton.tsx +++ b/react-components/src/components/Architecture/SettingsButton.tsx @@ -90,7 +90,8 @@ export const SettingsButton = ({ style={{ minWidth: '0px', overflow: 'auto', - flexDirection + flexDirection, + padding: '4px 4px' }}> {commands.map((command, _index): ReactElement | undefined => { return createMenuItem(command, t); From 382f239f1cc6b1237fe5807d78957ceac4a0c35f Mon Sep 17 00:00:00 2001 From: Nils Petter Fremming Date: Mon, 29 Jul 2024 08:58:46 +0200 Subject: [PATCH 07/10] Update RevealButtons.tsx --- .../components/Architecture/RevealButtons.tsx | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/react-components/src/components/Architecture/RevealButtons.tsx b/react-components/src/components/Architecture/RevealButtons.tsx index 93438690e5b..8541f38f9e1 100644 --- a/react-components/src/components/Architecture/RevealButtons.tsx +++ b/react-components/src/components/Architecture/RevealButtons.tsx @@ -13,8 +13,15 @@ import { MeasurementTool } from '../../architecture/concrete/measurements/Measur import { KeyboardSpeedCommand } from '../../architecture/base/concreteCommands/KeyboardSpeedCommand'; import { ObservationsTool } from '../../architecture/concrete/observations/ObservationsTool'; import { createButtonFromCommandConstructor } from './CommandButtons'; +import { SettingsCommand } from '../../architecture/base/concreteCommands/SettingsCommand'; +import { SetPointColorTypeCommand } from '../../architecture/base/concreteCommands/SetPointColorTypeCommand'; +import { SetPointShapeCommand } from '../../architecture/base/concreteCommands/SetPointShapeCommand'; +import { SetPointSizeCommand } from '../../architecture/base/concreteCommands/SetPointSizeCommand'; +import { SetQualityCommand } from '../../architecture/base/concreteCommands/SetQualityCommand'; export class RevealButtons { + static Settings = (): ReactElement => createButtonFromCommandConstructor(() => createSettings()); + static FitView = (): ReactElement => createButtonFromCommandConstructor(() => new FitViewCommand()); @@ -46,3 +53,12 @@ export class RevealButtons { static KeyboardSpeed = (): ReactElement => createButtonFromCommandConstructor(() => new KeyboardSpeedCommand()); } + +function createSettings(): SettingsCommand { + const settings = new SettingsCommand(); + settings.add(new SetQualityCommand()); + settings.add(new SetPointSizeCommand()); + settings.add(new SetPointColorTypeCommand()); + settings.add(new SetPointShapeCommand()); + return settings; +} From f44eed20d68380f14e5665144ad3be4dfb6d5a46 Mon Sep 17 00:00:00 2001 From: Nils Petter Fremming Date: Mon, 29 Jul 2024 10:18:49 +0200 Subject: [PATCH 08/10] Add mocked --- .../SetPointColorTypeCommand.ts | 22 ++++++---------- .../concreteCommands/SetPointShapeCommand.ts | 22 ++++++---------- .../concreteCommands/SetPointSizeCommand.ts | 25 +++++++------------ .../base/renderTarget/RevealRenderTarget.ts | 11 +++++++- 4 files changed, 35 insertions(+), 45 deletions(-) diff --git a/react-components/src/architecture/base/concreteCommands/SetPointColorTypeCommand.ts b/react-components/src/architecture/base/concreteCommands/SetPointColorTypeCommand.ts index c1aa27c25a6..34e7d6faa95 100644 --- a/react-components/src/architecture/base/concreteCommands/SetPointColorTypeCommand.ts +++ b/react-components/src/architecture/base/concreteCommands/SetPointColorTypeCommand.ts @@ -2,11 +2,10 @@ * Copyright 2024 Cognite AS */ -import { CognitePointCloudModel, PointColorType } from '@cognite/reveal'; +import { PointColorType } from '@cognite/reveal'; import { BaseOptionCommand } from '../commands/BaseOptionCommand'; import { RenderTargetCommand } from '../commands/RenderTargetCommand'; import { type TranslateKey } from '../utilities/TranslateKey'; -import { type RevealRenderTarget } from '../renderTarget/RevealRenderTarget'; const DEFAULT_OPTIONS: PointColorType[] = [ PointColorType.Rgb, @@ -37,7 +36,8 @@ export class SetPointColorTypeCommand extends BaseOptionCommand { } public override get isEnabled(): boolean { - return getPointClouds(this.renderTarget).next().value !== undefined; + return true; + return this.renderTarget.getPointClouds().next().value !== undefined; } } @@ -45,6 +45,7 @@ export class SetPointColorTypeCommand extends BaseOptionCommand { class OptionCommand extends RenderTargetCommand { private readonly _value: PointColorType; + private static selected = PointColorType.Rgb; public constructor(value: PointColorType) { super(); @@ -57,17 +58,18 @@ class OptionCommand extends RenderTargetCommand { public override get isChecked(): boolean { // Let the first PointCloud decide the color type - const pointCloud = getPointClouds(this.renderTarget).next().value; + const pointCloud = this.renderTarget.getPointClouds().next().value; if (pointCloud === undefined) { - return false; + return OptionCommand.selected === this._value; } return pointCloud.pointColorType === this._value; } public override invokeCore(): boolean { - for (const pointCloud of getPointClouds(this.renderTarget)) { + for (const pointCloud of this.renderTarget.getPointClouds()) { pointCloud.pointColorType = this._value; } + OptionCommand.selected = this._value; return true; } } @@ -76,14 +78,6 @@ class OptionCommand extends RenderTargetCommand { // PRIVATE FUNCTIONS // ================================================== -function* getPointClouds(renderTarget: RevealRenderTarget): Generator { - for (const model of renderTarget.viewer.models) { - if (model instanceof CognitePointCloudModel) { - yield model; - } - } -} - function getTranslateKey(type: PointColorType): TranslateKey { switch (type) { case PointColorType.Rgb: diff --git a/react-components/src/architecture/base/concreteCommands/SetPointShapeCommand.ts b/react-components/src/architecture/base/concreteCommands/SetPointShapeCommand.ts index 0e9f90b8e00..f6d568a23e5 100644 --- a/react-components/src/architecture/base/concreteCommands/SetPointShapeCommand.ts +++ b/react-components/src/architecture/base/concreteCommands/SetPointShapeCommand.ts @@ -2,11 +2,10 @@ * Copyright 2024 Cognite AS */ -import { CognitePointCloudModel, PointShape } from '@cognite/reveal'; +import { PointShape } from '@cognite/reveal'; import { BaseOptionCommand } from '../commands/BaseOptionCommand'; import { RenderTargetCommand } from '../commands/RenderTargetCommand'; import { type TranslateKey } from '../utilities/TranslateKey'; -import { type RevealRenderTarget } from '../renderTarget/RevealRenderTarget'; const DEFAULT_OPTIONS: PointShape[] = [PointShape.Circle, PointShape.Square, PointShape.Paraboloid]; @@ -31,7 +30,8 @@ export class SetPointShapeCommand extends BaseOptionCommand { } public override get isEnabled(): boolean { - return getPointClouds(this.renderTarget).next().value !== undefined; + return true; + return this.renderTarget.getPointClouds().next().value !== undefined; } } @@ -39,6 +39,7 @@ export class SetPointShapeCommand extends BaseOptionCommand { class OptionCommand extends RenderTargetCommand { private readonly _value: PointShape; + private static selected = PointShape.Circle; public constructor(value: PointShape) { super(); @@ -51,17 +52,18 @@ class OptionCommand extends RenderTargetCommand { public override get isChecked(): boolean { // Let the first PointCloud decide the color type - const pointCloud = getPointClouds(this.renderTarget).next().value; + const pointCloud = this.renderTarget.getPointClouds().next().value; if (pointCloud === undefined) { - return false; + return OptionCommand.selected === this._value; } return pointCloud.pointSizeType === this._value; } public override invokeCore(): boolean { - for (const pointCloud of getPointClouds(this.renderTarget)) { + for (const pointCloud of this.renderTarget.getPointClouds()) { pointCloud.pointShape = this._value; } + OptionCommand.selected = this._value; return true; } } @@ -70,14 +72,6 @@ class OptionCommand extends RenderTargetCommand { // PRIVATE FUNCTIONS // ================================================== -function* getPointClouds(renderTarget: RevealRenderTarget): Generator { - for (const model of renderTarget.viewer.models) { - if (model instanceof CognitePointCloudModel) { - yield model; - } - } -} - function getTranslateKey(type: PointShape): TranslateKey { switch (type) { case PointShape.Circle: diff --git a/react-components/src/architecture/base/concreteCommands/SetPointSizeCommand.ts b/react-components/src/architecture/base/concreteCommands/SetPointSizeCommand.ts index ffddcb530ce..38ae584847e 100644 --- a/react-components/src/architecture/base/concreteCommands/SetPointSizeCommand.ts +++ b/react-components/src/architecture/base/concreteCommands/SetPointSizeCommand.ts @@ -2,7 +2,6 @@ * Copyright 2024 Cognite AS */ -import { CognitePointCloudModel } from '@cognite/reveal'; import { type TranslateKey } from '../utilities/TranslateKey'; import { BaseSliderCommand } from '../commands/BaseSliderCommand'; @@ -29,28 +28,22 @@ export class SetPointSizeCommand extends BaseSliderCommand { } public override get isEnabled(): boolean { - for (const model of this.renderTarget.viewer.models) { - if (model instanceof CognitePointCloudModel) { - return true; - } - } - return false; + return true; + return this.renderTarget.getPointClouds().next().value !== undefined; } public override get value(): number { - for (const model of this.renderTarget.viewer.models) { - if (model instanceof CognitePointCloudModel) { - return model.pointSize; - } + // Let the first PointCloud decide the point size + const pointCloud = this.renderTarget.getPointClouds().next().value; + if (pointCloud === undefined) { + return DEFAULT_POINT_SIZE; } - return DEFAULT_POINT_SIZE; + return pointCloud.pointSize; } public override set value(value: number) { - for (const model of this.renderTarget.viewer.models) { - if (model instanceof CognitePointCloudModel) { - model.pointSize = value; - } + for (const pointCloud of this.renderTarget.getPointClouds()) { + pointCloud.pointSize = value; } } } diff --git a/react-components/src/architecture/base/renderTarget/RevealRenderTarget.ts b/react-components/src/architecture/base/renderTarget/RevealRenderTarget.ts index c5c583d4460..5cb692006ba 100644 --- a/react-components/src/architecture/base/renderTarget/RevealRenderTarget.ts +++ b/react-components/src/architecture/base/renderTarget/RevealRenderTarget.ts @@ -8,7 +8,8 @@ import { isFlexibleCameraManager, type Cognite3DViewer, type IFlexibleCameraManager, - CDF_TO_VIEWER_TRANSFORMATION + CDF_TO_VIEWER_TRANSFORMATION, + CognitePointCloudModel } from '@cognite/reveal'; import { Vector3, @@ -148,6 +149,14 @@ export class RevealRenderTarget { return this.viewer.getSceneBoundingBox(); } + public *getPointClouds(): Generator { + for (const model of this.viewer.models) { + if (model instanceof CognitePointCloudModel) { + yield model; + } + } + } + // ================================================== // INSTANCE METHODS // ================================================== From c15f442e82e797dcfdbe597d783d4b4cfaee5088 Mon Sep 17 00:00:00 2001 From: Nils Petter Fremming Date: Mon, 29 Jul 2024 12:37:36 +0200 Subject: [PATCH 09/10] Fix according to review and remove the mock --- .../SetPointColorTypeCommand.ts | 5 +---- .../concreteCommands/SetPointShapeCommand.ts | 5 +---- .../concreteCommands/SetPointSizeCommand.ts | 14 +++++--------- .../base/concreteCommands/SettingsCommand.ts | 4 ++++ .../components/Architecture/SettingsButton.tsx | 17 +++++++++++------ 5 files changed, 22 insertions(+), 23 deletions(-) diff --git a/react-components/src/architecture/base/concreteCommands/SetPointColorTypeCommand.ts b/react-components/src/architecture/base/concreteCommands/SetPointColorTypeCommand.ts index 34e7d6faa95..77855e41882 100644 --- a/react-components/src/architecture/base/concreteCommands/SetPointColorTypeCommand.ts +++ b/react-components/src/architecture/base/concreteCommands/SetPointColorTypeCommand.ts @@ -36,7 +36,6 @@ export class SetPointColorTypeCommand extends BaseOptionCommand { } public override get isEnabled(): boolean { - return true; return this.renderTarget.getPointClouds().next().value !== undefined; } } @@ -45,7 +44,6 @@ export class SetPointColorTypeCommand extends BaseOptionCommand { class OptionCommand extends RenderTargetCommand { private readonly _value: PointColorType; - private static selected = PointColorType.Rgb; public constructor(value: PointColorType) { super(); @@ -60,7 +58,7 @@ class OptionCommand extends RenderTargetCommand { // Let the first PointCloud decide the color type const pointCloud = this.renderTarget.getPointClouds().next().value; if (pointCloud === undefined) { - return OptionCommand.selected === this._value; + return false; } return pointCloud.pointColorType === this._value; } @@ -69,7 +67,6 @@ class OptionCommand extends RenderTargetCommand { for (const pointCloud of this.renderTarget.getPointClouds()) { pointCloud.pointColorType = this._value; } - OptionCommand.selected = this._value; return true; } } diff --git a/react-components/src/architecture/base/concreteCommands/SetPointShapeCommand.ts b/react-components/src/architecture/base/concreteCommands/SetPointShapeCommand.ts index f6d568a23e5..e2fdb16cf9b 100644 --- a/react-components/src/architecture/base/concreteCommands/SetPointShapeCommand.ts +++ b/react-components/src/architecture/base/concreteCommands/SetPointShapeCommand.ts @@ -30,7 +30,6 @@ export class SetPointShapeCommand extends BaseOptionCommand { } public override get isEnabled(): boolean { - return true; return this.renderTarget.getPointClouds().next().value !== undefined; } } @@ -39,7 +38,6 @@ export class SetPointShapeCommand extends BaseOptionCommand { class OptionCommand extends RenderTargetCommand { private readonly _value: PointShape; - private static selected = PointShape.Circle; public constructor(value: PointShape) { super(); @@ -54,7 +52,7 @@ class OptionCommand extends RenderTargetCommand { // Let the first PointCloud decide the color type const pointCloud = this.renderTarget.getPointClouds().next().value; if (pointCloud === undefined) { - return OptionCommand.selected === this._value; + return false; } return pointCloud.pointSizeType === this._value; } @@ -63,7 +61,6 @@ class OptionCommand extends RenderTargetCommand { for (const pointCloud of this.renderTarget.getPointClouds()) { pointCloud.pointShape = this._value; } - OptionCommand.selected = this._value; return true; } } diff --git a/react-components/src/architecture/base/concreteCommands/SetPointSizeCommand.ts b/react-components/src/architecture/base/concreteCommands/SetPointSizeCommand.ts index 38ae584847e..765edc4ad7e 100644 --- a/react-components/src/architecture/base/concreteCommands/SetPointSizeCommand.ts +++ b/react-components/src/architecture/base/concreteCommands/SetPointSizeCommand.ts @@ -5,10 +5,10 @@ import { type TranslateKey } from '../utilities/TranslateKey'; import { BaseSliderCommand } from '../commands/BaseSliderCommand'; -export const DEFAULT_POINT_SIZE = 2; -export const MIN_POINT_SIZE = 0.0; -export const MAX_POINT_SIZE = 4; // Default seems be be 2, but the user probably wants lower values -export const STEP_POINT_SIZE = 0.1; +const DEFAULT_POINT_SIZE = 2; +const MIN_POINT_SIZE = 0.0; +const MAX_POINT_SIZE = 4; // Default seems be be 2, but the user probably wants lower values +const STEP_POINT_SIZE = 0.1; export class SetPointSizeCommand extends BaseSliderCommand { // ================================================== @@ -28,17 +28,13 @@ export class SetPointSizeCommand extends BaseSliderCommand { } public override get isEnabled(): boolean { - return true; return this.renderTarget.getPointClouds().next().value !== undefined; } public override get value(): number { // Let the first PointCloud decide the point size const pointCloud = this.renderTarget.getPointClouds().next().value; - if (pointCloud === undefined) { - return DEFAULT_POINT_SIZE; - } - return pointCloud.pointSize; + return pointCloud?.pointSize ?? DEFAULT_POINT_SIZE; } public override set value(value: number) { diff --git a/react-components/src/architecture/base/concreteCommands/SettingsCommand.ts b/react-components/src/architecture/base/concreteCommands/SettingsCommand.ts index f702120bbed..e9b250f1f56 100644 --- a/react-components/src/architecture/base/concreteCommands/SettingsCommand.ts +++ b/react-components/src/architecture/base/concreteCommands/SettingsCommand.ts @@ -39,6 +39,10 @@ export class SettingsCommand extends RenderTargetCommand { // ================================================== public add(command: BaseCommand): void { + if (this._commands.find((c) => c.equals(command)) !== undefined) { + console.error('Duplicated command given: ' + command.name); + return; + } this._commands.push(command); } diff --git a/react-components/src/components/Architecture/SettingsButton.tsx b/react-components/src/components/Architecture/SettingsButton.tsx index 3d12f975b41..742c8b8efc8 100644 --- a/react-components/src/components/Architecture/SettingsButton.tsx +++ b/react-components/src/components/Architecture/SettingsButton.tsx @@ -86,17 +86,14 @@ export const SettingsButton = ({ appendTo={document.body} placement="auto-start" content={ - {commands.map((command, _index): ReactElement | undefined => { return createMenuItem(command, t); })} - + }>