Skip to content

Commit

Permalink
refactor: generalize 1D apodization panels and options for reuse in 2…
Browse files Browse the repository at this point in the history
…D apodization
  • Loading branch information
hamed-musallam committed Nov 25, 2024
1 parent 7f6b32d commit 40c01bb
Show file tree
Hide file tree
Showing 6 changed files with 502 additions and 376 deletions.
11 changes: 6 additions & 5 deletions src/component/1d/ApodizationLine.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import {
} from 'nmr-processing';

import { useChartData } from '../context/ChartContext.js';
import { useFilterSyncOptions } from '../context/FilterSyncOptionsContext.js';
import { useScaleChecked } from '../context/ScaleContext.js';
import { useActiveSpectrum } from '../hooks/useActiveSpectrum.js';
import useSpectrum from '../hooks/useSpectrum.js';
import { useVerticalAlign } from '../hooks/useVerticalAlign.js';
import useXYReduce, { XYReducerDomainAxis } from '../hooks/useXYReduce.js';
import type { ApodizationOptions } from '../panels/filtersPanel/Filters/hooks/useSharedApodization.js';
import { PathBuilder } from '../utility/PathBuilder.js';

import { getYScale } from './utilities/scale.js';
Expand All @@ -32,16 +34,15 @@ function useWindowYScale() {

export function ApodizationLine() {
const {
toolOptions: {
selectedTool,
data: { apodizationOptions: externalApodizationOptions },
},
toolOptions: { selectedTool },
} = useChartData();
const activeSpectrum = useActiveSpectrum();
const { scaleX } = useScaleChecked();
const spectrum = useSpectrum({ emptyData }) as Spectrum1D;
const xyReduce = useXYReduce(XYReducerDomainAxis.XAxis);
const scaleY = useWindowYScale();
const { sharedFilterOptions: externalApodizationOptions } =
useFilterSyncOptions<ApodizationOptions>();

if (!activeSpectrum?.id || selectedTool !== Filters1D.apodization.name) {
return null;
Expand All @@ -53,7 +54,7 @@ export function ApodizationLine() {

const apodizationOptions = merge(
default1DApodization,
externalApodizationOptions,
externalApodizationOptions?.options,
);
const length = re.length;
const dw = (x[length - 1] - x[0]) / (length - 1);
Expand Down
104 changes: 104 additions & 0 deletions src/component/header/BaseSimpleApodizationOptionsPanel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { Checkbox } from '@blueprintjs/core';

import { useToaster } from '../context/ToasterContext.js';
import ActionButtons from '../elements/ActionButtons.js';
import Label from '../elements/Label.js';
import { NumberInput2Controller } from '../elements/NumberInput2Controller.js';
import { useSharedApodization } from '../panels/filtersPanel/Filters/hooks/useSharedApodization.js';
import type {
ApodizationFilterOptions,
UseSharedApodizationOptions,
} from '../panels/filtersPanel/Filters/hooks/useSharedApodization.js';

import { headerLabelStyle } from './Header.js';
import { HeaderWrapper } from './HeaderWrapper.js';

interface BaseSimpleApodizationOptionsPanelProps
extends Pick<
UseSharedApodizationOptions,
'onApplyDispatch' | 'onChangeDispatch'
> {
filter: ApodizationFilterOptions | null;
}

export function BaseSimpleApodizationOptionsPanel(
props: BaseSimpleApodizationOptionsPanelProps,
) {
const toaster = useToaster();

const { filter, onApplyDispatch, onChangeDispatch } = props;

const { formMethods, submitHandler, handleApplyFilter, handleCancelFilter } =
useSharedApodization(filter, {
applyFilterOnload: true,
onApplyDispatch,
onChangeDispatch,
});

const {
register,
handleSubmit,
control,
formState: { isValid },
watch,
} = formMethods;

const isExponentialActive = watch('options.exponential.apply') || false;

const { onChange: onLivePreviewFieldChange, ...livePreviewFieldOptions } =
register('livePreview');

function handleClick() {
if (!isExponentialActive) {
toaster.show({
intent: 'danger',
message:
'Activate "Exponential" filter from the Processing panel first',
});
}
}

function handleConfirm() {
void handleSubmit((values) => handleApplyFilter(values))();
}

function handleCancel() {
handleCancelFilter();
}

return (
<HeaderWrapper>
<Label title="Line broadening:" shortTitle="LB:" style={headerLabelStyle}>
<NumberInput2Controller
control={control}
name="options.exponential.options.lineBroadening"
debounceTime={250}
stepSize={0.1}
style={{ width: '60px' }}
onValueChange={() => {
submitHandler();
}}
readOnly={!isExponentialActive}
onClick={handleClick}
/>
</Label>

<Label title="Live preview" style={{ label: { padding: '0 5px' } }}>
<Checkbox
{...livePreviewFieldOptions}
onChange={(event) => {
void onLivePreviewFieldChange(event);
submitHandler();
}}
style={{ margin: 0 }}
/>
</Label>

<ActionButtons
disabledDone={!isValid}
onDone={handleConfirm}
onCancel={handleCancel}
/>
</HeaderWrapper>
);
}
96 changes: 29 additions & 67 deletions src/component/header/SimpleApodizationOptionsPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
import { Checkbox } from '@blueprintjs/core';
import { memo } from 'react';
import { memo, useCallback } from 'react';

import type { ExtractFilterEntry } from '../../data/types/common/ExtractFilterEntry.js';
import { useToaster } from '../context/ToasterContext.js';
import ActionButtons from '../elements/ActionButtons.js';
import Label from '../elements/Label.js';
import { NumberInput2Controller } from '../elements/NumberInput2Controller.js';
import { useDispatch } from '../context/DispatchContext.js';
import { useFilter } from '../hooks/useFilter.js';
import { useSharedApodization } from '../panels/filtersPanel/Filters/hooks/useSharedApodization.js';

import { headerLabelStyle } from './Header.js';
import { HeaderWrapper } from './HeaderWrapper.js';
import { BaseSimpleApodizationOptionsPanel } from './BaseSimpleApodizationOptionsPanel.js';

interface ApodizationOptionsInnerPanelProps {
filter: ExtractFilterEntry<'apodization'> | null;
Expand All @@ -19,67 +13,35 @@ interface ApodizationOptionsInnerPanelProps {
function ApodizationOptionsInnerPanel(
props: ApodizationOptionsInnerPanelProps,
) {
const toaster = useToaster();
const { formMethods, submitHandler, handleApplyFilter, handleCancelFilter } =
useSharedApodization(props.filter, { applyFilterOnload: true });

const {
register,
handleSubmit,
control,
formState: { isValid },
watch,
} = formMethods;

const isExponentialActive = watch('options.exponential.apply') || false;

const { onChange: onLivePreviewFieldChange, ...livePreviewFieldOptions } =
register('livePreview');

function handleClick() {
if (!isExponentialActive) {
toaster.show({
intent: 'danger',
message:
'Activate "Exponential" filter from the Processing panel first',
const dispatch = useDispatch();

const applyHandler = useCallback(
(data) => {
const { options } = data;
dispatch({
type: 'APPLY_APODIZATION_FILTER',
payload: { options },
});
}
}
},
[dispatch],
);
const changeHandler = useCallback(
(data) => {
const { livePreview, options } = data;
dispatch({
type: 'CALCULATE_APODIZATION_FILTER',
payload: { livePreview, options: structuredClone(options) },
});
},
[dispatch],
);

return (
<HeaderWrapper>
<Label title="Line broadening:" shortTitle="LB:" style={headerLabelStyle}>
<NumberInput2Controller
control={control}
name="options.exponential.options.lineBroadening"
debounceTime={250}
stepSize={0.1}
style={{ width: '60px' }}
onValueChange={() => {
submitHandler();
}}
readOnly={!isExponentialActive}
onClick={handleClick}
/>
</Label>

<Label title="Live preview" style={{ label: { padding: '0 5px' } }}>
<Checkbox
{...livePreviewFieldOptions}
onChange={(event) => {
void onLivePreviewFieldChange(event);
submitHandler();
}}
style={{ margin: 0 }}
/>
</Label>

<ActionButtons
disabledDone={!isValid}
onDone={() => handleSubmit((values) => handleApplyFilter(values))()}
onCancel={handleCancelFilter}
/>
</HeaderWrapper>
<BaseSimpleApodizationOptionsPanel
filter={props.filter}
onApplyDispatch={applyHandler}
onChangeDispatch={changeHandler}
/>
);
}

Expand Down
Loading

0 comments on commit 40c01bb

Please sign in to comment.