Skip to content
Snippets Groups Projects
Commit f826c0e3 authored by Loïc Correnson's avatar Loïc Correnson
Browse files

[ivette/eva] zoom cell

parent ff3cdc83
No related branches found
No related tags found
No related merge requests found
...@@ -50,29 +50,39 @@ function ProbeEditor() { ...@@ -50,29 +50,39 @@ function ProbeEditor() {
const label = probe?.label; const label = probe?.label;
const code = probe?.code; const code = probe?.code;
const rank = probe?.rank; const rank = probe?.rank;
const byCS = probe?.byCallstacks;
const stmt = rank ? `@S${rank}` : undefined; const stmt = rank ? `@S${rank}` : undefined;
const byCS = probe?.byCallstacks;
const stacks = model.getStacks(probe).length; const stacks = model.getStacks(probe).length;
const stackable = byCS || stacks > 1;
const { cols, rows } = sizeof(code); const { cols, rows } = sizeof(code);
const width = WSIZER.dimension(cols) + 4; const width = WSIZER.dimension(cols) + 4;
const height = HSIZER.dimension(rows) + 3; const height = HSIZER.dimension(rows) + 3;
const visible = probe ? !!code : model.getRowCount() > 0; const visible = probe ? !!code : model.getRowCount() > 0;
const zoomed = probe?.zoomed;
const zoomable = probe?.zoomable;
const visibility = visible ? 'visible' : 'hidden'; const visibility = visible ? 'visible' : 'hidden';
return ( return (
<Hpack style={{ visibility }} className="eva-probe"> <Hpack style={{ visibility }} className="eva-probe">
<Label className="eva-probe-label">{label && `${label}:`}</Label> <Label className="eva-probe-label">{label && `${label}:`}</Label>
<div style={{ width, height }} className="eva-probe-code"> <div style={{ minWidth: width, height }} className="eva-probe-code">
<SizedArea cols={cols} rows={rows}>{code}</SizedArea> <SizedArea cols={cols} rows={rows}>{code}</SizedArea>
</div> </div>
<Code className="eva-probe-stmt">{stmt}</Code> <Code className="eva-probe-stmt">{stmt}</Code>
<IconButton <IconButton
className="eva-probe-button" className="eva-probe-button"
visible={byCS || stacks > 0} display={stackable}
selected={byCS} selected={byCS}
icon="ITEMS.LIST" icon="ITEMS.LIST"
title={`Details by callstack (${stacks})`} title={`Details by callstack (${stacks})`}
onClick={() => { if (probe) probe.setByCallstacks(!byCS); }} onClick={() => { if (probe) probe.setByCallstacks(!byCS); }}
/> />
<IconButton
className="eva-probe-button"
display={zoomable}
selected={zoomed}
icon="SEARCH"
onClick={() => { if (probe) probe.setZoomed(!zoomed); }}
/>
<IconButton <IconButton
className="eva-probe-button" className="eva-probe-button"
kind={transient ? 'selected' : 'warning'} kind={transient ? 'selected' : 'warning'}
...@@ -94,7 +104,7 @@ interface TableCellProps { ...@@ -94,7 +104,7 @@ interface TableCellProps {
row: Row; row: Row;
} }
const CELLPADDING = 4; const CELLPADDING = 12;
function TableCell(props: TableCellProps) { function TableCell(props: TableCellProps) {
const model = useModel(); const model = useModel();
...@@ -118,8 +128,10 @@ function TableCell(props: TableCellProps) { ...@@ -118,8 +128,10 @@ function TableCell(props: TableCellProps) {
const atpoint = rank && ( const atpoint = rank && (
<span className="eva-probe-stmt">@S{rank}</span> <span className="eva-probe-stmt">@S{rank}</span>
); );
const text =
label ? <span className="dome-text-label">{label}</span> : code;
contents = ( contents = (
<span className="dome-text-label">{label ?? code}{atpoint}</span> <span className="dome-text-code">{text}{atpoint}</span>
); );
} }
break; break;
...@@ -158,11 +170,15 @@ function TableCell(props: TableCellProps) { ...@@ -158,11 +170,15 @@ function TableCell(props: TableCellProps) {
setSelection({ location }); setSelection({ location });
} }
}; };
const onDoubleClick = () => {
if (probe && probe.zoomable) probe.setZoomed(!probe.zoomed);
};
return ( return (
<div <div
className={className} className={className}
style={style} style={style}
onClick={onClick} onClick={onClick}
onDoubleClick={onDoubleClick}
> >
{contents} {contents}
</div> </div>
...@@ -190,6 +206,7 @@ function TableRow(props: TableRowProps) { ...@@ -190,6 +206,7 @@ function TableRow(props: TableRowProps) {
{sk === undefined ? '#' : `${1 + sk}`} {sk === undefined ? '#' : `${1 + sk}`}
</div> </div>
); );
const style: React.CSSProperties = { left: row.stacks ? 0 : 12 };
const contents = probes.map((probe) => ( const contents = probes.map((probe) => (
<TableCell <TableCell
key={probe.marker} key={probe.marker}
...@@ -199,7 +216,7 @@ function TableRow(props: TableRowProps) { ...@@ -199,7 +216,7 @@ function TableRow(props: TableRowProps) {
)); ));
return ( return (
<Hpack className={className} style={props.style}> <Hpack className={className} style={props.style}>
<div className="eva-row"> <div style={style} className="eva-row">
{header} {header}
{contents} {contents}
</div> </div>
...@@ -217,9 +234,13 @@ interface Dimension { ...@@ -217,9 +234,13 @@ interface Dimension {
height: number; height: number;
} }
function ValuesPanel(props: Dimension) { interface ValuesPanelProps extends Dimension {
zoom: number;
}
function ValuesPanel(props: ValuesPanelProps) {
const model = useModel(); const model = useModel();
const { width, height } = props; const { zoom, width, height } = props;
// --- reset line cache // --- reset line cache
const listRef = React.useRef<VariableSizeList>(null); const listRef = React.useRef<VariableSizeList>(null);
Dome.useEvent(model.laidout, () => { Dome.useEvent(model.laidout, () => {
...@@ -239,7 +260,7 @@ function ValuesPanel(props: Dimension) { ...@@ -239,7 +260,7 @@ function ValuesPanel(props: Dimension) {
const [selection] = States.useSelection(); const [selection] = States.useSelection();
React.useEffect(() => { React.useEffect(() => {
const target = Ast.jMarker(selection?.current?.marker); const target = Ast.jMarker(selection?.current?.marker);
model.setLayout({ margin, target }); model.setLayout({ zoom, margin, target });
}); });
// --- render list // --- render list
return ( return (
...@@ -263,14 +284,31 @@ function ValuesPanel(props: Dimension) { ...@@ -263,14 +284,31 @@ function ValuesPanel(props: Dimension) {
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
function ValuesComponent() { function ValuesComponent() {
const [zoom, setZoom] = Dome.useNumberSettings('eva-zoom-factor', 0);
return ( return (
<> <>
<TitleBar /> <TitleBar>
<IconButton
enabled={zoom > 0}
icon="ZOOM.OUT"
onClick={() => setZoom(zoom - 1)}
/>
<IconButton
enabled={zoom < 20}
icon="ZOOM.IN"
onClick={() => setZoom(zoom + 1)}
/>
</TitleBar>
<Vfill> <Vfill>
<ProbeEditor /> <ProbeEditor />
<Vfill> <Vfill>
<AutoSizer> <AutoSizer>
{(dim: Dimension) => <ValuesPanel {...dim} />} {(dim: Dimension) => (
<ValuesPanel
zoom={zoom}
{...dim}
/>
)}
</AutoSizer> </AutoSizer>
</Vfill> </Vfill>
</Vfill> </Vfill>
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
import { callstack } from 'frama-c/api/plugins/eva/values'; import { callstack } from 'frama-c/api/plugins/eva/values';
import { Probe } from './probes'; import { Probe } from './probes';
import { StacksCache } from './stacks'; import { StacksCache } from './stacks';
import { Size, EMPTY, addH, ValueCache } from './cells'; import { Size, EMPTY, leq, addH, ValueCache } from './cells';
export interface LayoutProps { export interface LayoutProps {
zoom?: number; zoom?: number;
...@@ -63,16 +63,19 @@ export class LayoutEngine { ...@@ -63,16 +63,19 @@ export class LayoutEngine {
private buffer: Probe[] = []; private buffer: Probe[] = [];
private rows: Row[] = []; private rows: Row[] = [];
crop(s: Size): Size { crop(zoomed: boolean, s: Size): Size {
const cols = zoomed ? s.cols : Math.min(s.cols, this.hcrop);
const rows = zoomed ? s.rows : Math.min(s.rows, this.vcrop);
return { return {
cols: Math.max(HCROP, Math.min(s.cols, this.hcrop)), cols: Math.max(HCROP, cols),
rows: Math.max(VCROP, Math.min(s.rows, this.vcrop)), rows: Math.max(VCROP, rows),
}; };
} }
push(p: Probe) { push(p: Probe) {
const probeSize = this.values.getProbeSize(p.marker); const probeSize = this.values.getProbeSize(p.marker);
const s = this.crop(probeSize); const s = this.crop(p.zoomed, probeSize);
p.zoomable = p.zoomed || !leq(probeSize, s);
p.minCols = s.cols; p.minCols = s.cols;
p.maxCols = Math.max(p.minCols, probeSize.cols); p.maxCols = Math.max(p.minCols, probeSize.cols);
const stmt = p.byCallstacks ? p.stmt : undefined; const stmt = p.byCallstacks ? p.stmt : undefined;
......
...@@ -54,6 +54,8 @@ export class Probe { ...@@ -54,6 +54,8 @@ export class Probe {
minCols: number = LabelSize; minCols: number = LabelSize;
maxCols: number = LabelSize; maxCols: number = LabelSize;
byCallstacks = false; byCallstacks = false;
zoomed = false;
zoomable = false;
constructor(state: StateCallbacks, marker: Ast.marker) { constructor(state: StateCallbacks, marker: Ast.marker) {
this.marker = marker; this.marker = marker;
...@@ -106,6 +108,13 @@ export class Probe { ...@@ -106,6 +108,13 @@ export class Probe {
} }
} }
setZoomed(zoomed: boolean) {
if (zoomed !== this.zoomed) {
this.zoomed = zoomed;
this.state.forceLayout();
}
}
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// --- Ordering // --- Ordering
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
......
...@@ -57,6 +57,7 @@ ...@@ -57,6 +57,7 @@
.eva-row { .eva-row {
display: flex; display: flex;
position: relative;
flex: 0 1 auto; flex: 0 1 auto;
height: 100%; height: 100%;
border-bottom: thin solid black; border-bottom: thin solid black;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment