Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
637 changes: 636 additions & 1 deletion examples/scatter_plot.html

Large diffs are not rendered by default.

30 changes: 29 additions & 1 deletion src/command/describe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import type { BrailleViewModel } from '@state/viewModel/brailleViewModel';
import type { TextViewModel } from '@state/viewModel/textViewModel';
import type { BoxBrailleState, LineBrailleState, NonEmptyTraceState } from '@type/state';
import type { Command } from './command';
import { TraceType } from '@type/grammar';
import { Scope } from '@type/event';
import { TraceType } from '@type/grammar';

/**
* Abstract base class for describe commands.
Expand Down Expand Up @@ -417,6 +417,12 @@ export class AnnouncePositionCommand extends DescribeCommand {
return;
}

// Grid mode: announce axis ranges without points
if (state.text.gridPoints !== undefined && state.text.range && state.text.crossRange) {
this.announceGridPosition(state);
return;
}

// Get position from audio.panning (contains x, y, rows, cols)
const { panning } = state.audio;
const { x, y, rows, cols } = panning;
Expand Down Expand Up @@ -491,6 +497,28 @@ export class AnnouncePositionCommand extends DescribeCommand {
}
}

/**
* Announces position for grid navigation mode.
* Shows axis ranges without the points list.
*/
private announceGridPosition(state: NonEmptyTraceState): void {
const { text } = state;
const xRange = text.range!;
const yRange = text.crossRange!;

if (this.textService.isTerse()) {
this.textViewModel.update(
`${xRange.min} through ${xRange.max}, ${yRange.min} through ${yRange.max}`,
);
} else {
const xLabel = text.main.label || 'x';
const yLabel = text.cross.label || 'y';
this.textViewModel.update(
`${xLabel} is ${xRange.min} through ${xRange.max}, ${yLabel} is ${yRange.min} through ${yRange.max}`,
);
}
}

/**
* Announces position for boxplots with section information.
* Uses braille state which normalizes box position regardless of orientation.
Expand Down
69 changes: 67 additions & 2 deletions src/model/abstract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import type {
import type { Trace } from './plot';
import { NavigationService } from '@service/navigation';
import { TraceType } from '@type/grammar';
import { Constant } from '@util/constant';

const DEFAULT_SUBPLOT_TITLE = 'unavailable';

Expand Down Expand Up @@ -253,6 +254,68 @@ export abstract class AbstractPlot<State> implements Movable, Observable<State>,
public moveToPoint(_x: number, _y: number): void {
// implement basic stuff, assuming something like highlightValues that holds the points and boxes
}

/**
* Sets whether grid navigation mode is active. Override in traces that support grid navigation.
*/
/**
* Returns true if this trace supports compare (lower/higher value) navigation.
* Override to false for trace types that don't use compare modes (e.g., scatter).
*/
public supportsCompareMode(): boolean {
return true;
}

/**
* Returns the display name for the default data navigation mode.
* Override to provide a trace-specific name (e.g., "ROW AND COLUMN NAVIGATION" for scatter).
*/
public dataModeName(): string {
return Constant.DATA_MODE;
}

public setGridMode(_enabled: boolean): void {
// No-op for traces that don't support grid navigation.
}

/**
* Returns true if this trace supports grid navigation.
*/
public supportsGridMode(): boolean {
return false;
}

/**
* Grid navigation: move up one cell. Returns false if at boundary.
*/
public moveGridUp(): boolean {
this.notifyRotorBounds();
return false;
}

/**
* Grid navigation: move down one cell. Returns false if at boundary.
*/
public moveGridDown(): boolean {
this.notifyRotorBounds();
return false;
}

/**
* Grid navigation: move left one cell. Returns false if at boundary.
*/
public moveGridLeft(): boolean {
this.notifyRotorBounds();
return false;
}

/**
* Grid navigation: move right one cell. Returns false if at boundary.
*/
public moveGridRight(): boolean {
this.notifyRotorBounds();
return false;
}
}

export abstract class AbstractTrace extends AbstractPlot<TraceState> implements Trace {
Expand All @@ -276,8 +339,10 @@ export abstract class AbstractTrace extends AbstractPlot<TraceState> implements
this.type = layer.type;
this.title = layer.title ?? DEFAULT_SUBPLOT_TITLE;

this.xAxis = layer.axes?.x ?? DEFAULT_X_AXIS;
this.yAxis = layer.axes?.y ?? DEFAULT_Y_AXIS;
const axisX = layer.axes?.x;
const axisY = layer.axes?.y;
this.xAxis = (typeof axisX === 'object' ? axisX.label : axisX) ?? DEFAULT_X_AXIS;
this.yAxis = (typeof axisY === 'object' ? axisY.label : axisY) ?? DEFAULT_Y_AXIS;
this.fill = layer.axes?.fill ?? DEFAULT_FILL_AXIS;
}

Expand Down
Loading
Loading