diff --git a/ivette/src/dome/renderer/dome.tsx b/ivette/src/dome/renderer/dome.tsx
index ca8b9031be924e67ab2b2893b24f6b6b1672a34f..ade2d71019d066cc7ecf28f354bf7e9d73e05ee7 100644
--- a/ivette/src/dome/renderer/dome.tsx
+++ b/ivette/src/dome/renderer/dome.tsx
@@ -561,12 +561,13 @@ export function useUpdate(...events: Event<any>[]) {
 
 /**
    Hook to re-render when a Promise returns.
+   The promise will be typically created by using `React.useMemo()`.
    The hook returns three informations:
    - result: the promise result if it succeeds, undefined otherwise;
    - error: the promise error if it fails, undefined otherwise;
    - loading: the promise status, true if the promise is still running.
 */
-export function usePromiseNoMemo<T> (job: Promise<T>) {
+export function usePromise<T>(job: Promise<T>) {
   const [result, setResult] = React.useState<T | undefined>();
   const [error, setError] = React.useState<Error | undefined>();
   const [loading, setLoading] = React.useState(true);
@@ -581,24 +582,6 @@ export function usePromiseNoMemo<T> (job: Promise<T>) {
   return { result, error, loading };
 }
 
-/* Internal type alias */
-type Dependencies = React.DependencyList | undefined
-
-/**
-   Hook to re-render when a Promise returns.
-   The promise construction is memoized.
-   The hook returns three informations:
-   - result: the promise result if it succeeds, undefined otherwise;
-   - error: the promise error if it fails, undefined otherwise;
-   - loading: the promise status, true if the promise is still running.
-*/
-export function usePromise<T> (job: () => Promise<T>, deps: Dependencies) {
-  const depsArray: any[] = [];
-  deps?.forEach(depsArray.push);
-  const memoized = React.useMemo<Promise<T>>(job, [job, ...depsArray]);
-  return usePromiseNoMemo(memoized);
-}
-
 /* Internal type alias */
 type Serialize<A> = (a: A) => string;
 
@@ -610,7 +593,7 @@ type Serialize<A> = (a: A) => string;
 */
 export function useCache<K, V>(r: (k: K) => V, s?: Serialize<K>): (k: K) => V {
   const [ cache ] = React.useState(new Map<string, V>());
-  const serialize = React.useCallback((k: K) => s ? s(k) : `${k}`, [s]);
+  const serialize = React.useMemo(() => s ? s : (k: K) => `${k}`, [s]);
   const get = React.useCallback((k: K): V => {
     const id = serialize(k);
     if (cache.has(id))
diff --git a/ivette/src/dome/renderer/themes.tsx b/ivette/src/dome/renderer/themes.tsx
index 924c1bcc8f62d6a153515689b6918ffc31174a6e..fc24cb2bd4ec9f1fea98e3c17a7bde85eb131c3d 100644
--- a/ivette/src/dome/renderer/themes.tsx
+++ b/ivette/src/dome/renderer/themes.tsx
@@ -71,7 +71,7 @@ async function getNativeTheme(): Promise<ColorTheme> {
 
 export function useColorTheme(): [ColorTheme, (upd: ColorSettings) => void] {
   Dome.useUpdate(NativeThemeUpdated);
-  const { result: current } = Dome.usePromiseNoMemo(getNativeTheme());
+  const { result: current } = Dome.usePromise(getNativeTheme());
   const [pref, setTheme] = Settings.useGlobalSettings(ColorThemeSettings);
   return [current ?? jColorTheme(pref), setTheme];
 }
diff --git a/ivette/src/frama-c/kernel/SourceCode.tsx b/ivette/src/frama-c/kernel/SourceCode.tsx
index 82569f911589208f66759651514a00776546449e..ee222433767d50953af8b5cbd2388ab532db0633 100644
--- a/ivette/src/frama-c/kernel/SourceCode.tsx
+++ b/ivette/src/frama-c/kernel/SourceCode.tsx
@@ -83,7 +83,7 @@ export default function SourceCode(): JSX.Element {
   const [fontSize] = Settings.useGlobalSettings(Preferences.EditorFontSize);
 
   // Updating the buffer content.
-  const { result } = Dome.usePromise(async () => {
+  const text = React.useMemo(async () => {
     const onError = (): string => {
       if (file)
         D.error(`Fail to load source code file ${file}`);
@@ -91,6 +91,7 @@ export default function SourceCode(): JSX.Element {
     };
     return System.readFile(file).catch(onError);
   }, [file]);
+  const { result } = Dome.usePromise(text);
   React.useEffect(() => buffer.setValue(result), [buffer, result]);
 
   /* Last location selected by a click in the source code. */
diff --git a/ivette/src/frama-c/plugins/eva/index.tsx b/ivette/src/frama-c/plugins/eva/index.tsx
index 2dce3870cfc337300a6712af2fb454d4cacf0ca3..e88ef8411b0bdab3e466c3d81b0c29bcfc5d26ed 100644
--- a/ivette/src/frama-c/plugins/eva/index.tsx
+++ b/ivette/src/frama-c/plugins/eva/index.tsx
@@ -24,86 +24,16 @@
 // --- Eva Values
 // --------------------------------------------------------------------------
 
-// React & Dome
-import React from 'react';
-import * as Dome from 'dome';
 import * as Ivette from 'ivette';
-import * as Server from 'frama-c/server';
-import { GlobalState, useGlobalState } from 'dome/data/states';
-import { Vfill } from 'dome/layout/boxes';
-import { IconButton } from 'dome/controls/buttons';
-import { AutoSizer } from 'react-virtualized';
-import { Model } from './model';
-
-// Locals
-import { ProbeInfos } from './probeinfos';
-import { Dimension, ValuesPanel } from './valuetable';
-import { AlarmsInfos, StackInfos } from './valueinfos';
+import { } from 'frama-c/plugins/eva/state';
 import { } from './Summary';
 import { } from './Coverage';
 import './style.css';
 
-import { EvaTable } from 'frama-c/plugins/eva/state';
-
-// --------------------------------------------------------------------------
-// --- Values Component
-// --------------------------------------------------------------------------
-
-const globalModelState = new GlobalState(new Model());
-
-function ValuesComponent(): JSX.Element {
-  const [model] = useGlobalState(globalModelState);
-  model.mount();
-  Dome.useUpdate(model.changed, model.laidout);
-  Server.onShutdown(() => model.unmount());
-  const [zoom, setZoom] = Dome.useNumberSettings('eva-zoom-factor', 0);
-  return (
-    <>
-      <Ivette.TitleBar>
-        <IconButton
-          enabled={zoom > 0}
-          icon="ZOOM.OUT"
-          onClick={() => setZoom(zoom - 1)}
-        />
-        <IconButton
-          enabled={zoom < 20}
-          icon="ZOOM.IN"
-          onClick={() => setZoom(zoom + 1)}
-        />
-      </Ivette.TitleBar>
-      <Vfill>
-        <ProbeInfos model={model} />
-        <Vfill>
-          <AutoSizer>
-            {(dim: Dimension) => (
-              <ValuesPanel
-                zoom={zoom}
-                model={model}
-                {...dim}
-              />
-            )}
-          </AutoSizer>
-        </Vfill>
-        <AlarmsInfos model={model} />
-        <StackInfos model={model} />
-      </Vfill>
-    </>
-  );
-}
-
 // --------------------------------------------------------------------------
 // --- Export Component
 // --------------------------------------------------------------------------
 
-Ivette.registerComponent({
-  id: 'frama-c.plugins.values',
-  group: 'frama-c.plugins',
-  rank: 1,
-  label: 'Eva Values',
-  title: 'Values inferred by the Eva analysis',
-  children: <ValuesComponent />,
-});
-
 Ivette.registerView({
   id: 'summary',
   rank: 1,
@@ -124,13 +54,4 @@ Ivette.registerView({
   ],
 });
 
-Ivette.registerComponent({
-  id: 'frama-c.plugins.values.test',
-  group: 'frama-c.plugins',
-  rank: 1,
-  label: 'Test Eva Values',
-  title: 'Values inferred by the Eva analysis',
-  children: <EvaTable />,
-});
-
 // --------------------------------------------------------------------------
diff --git a/ivette/src/frama-c/plugins/eva/state.tsx b/ivette/src/frama-c/plugins/eva/state.tsx
index acbd6b7059bc6257061c80eff596293b90662db7..2ec22a8465a91ab4475971ea8b79a3a6eae67f31 100644
--- a/ivette/src/frama-c/plugins/eva/state.tsx
+++ b/ivette/src/frama-c/plugins/eva/state.tsx
@@ -1,3 +1,25 @@
+/* ************************************************************************ */
+/*                                                                          */
+/*   This file is part of Frama-C.                                          */
+/*                                                                          */
+/*   Copyright (C) 2007-2022                                                */
+/*     CEA (Commissariat à l'énergie atomique et aux énergies               */
+/*          alternatives)                                                   */
+/*                                                                          */
+/*   you can redistribute it and/or modify it under the terms of the GNU    */
+/*   Lesser General Public License as published by the Free Software        */
+/*   Foundation, version 2.1.                                               */
+/*                                                                          */
+/*   It is distributed in the hope that it will be useful,                  */
+/*   but WITHOUT ANY WARRANTY; without even the implied warranty of         */
+/*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
+/*   GNU Lesser General Public License for more details.                    */
+/*                                                                          */
+/*   See the GNU Lesser General Public License version 2.1                  */
+/*   for more details (enclosed in the file licenses/LGPLv2.1).             */
+/*                                                                          */
+/* ************************************************************************ */
+
 import React from 'react';
 import * as Ivette from 'ivette';
 import * as Dome from 'dome/dome';
@@ -5,7 +27,6 @@ import * as States from 'frama-c/states';
 import * as Server from 'frama-c/server';
 import * as Ast from 'frama-c/kernel/api/ast';
 import * as Values from 'frama-c/plugins/eva/api/values';
-import { evaluation } from 'frama-c/plugins/eva/api/values';
 
 import { classes } from 'dome/misc/utils';
 import { Icon } from 'dome/controls/icons';
@@ -18,9 +39,7 @@ import { Inset, Button, ButtonGroup } from 'dome/frame/toolbars';
 
 type Request<A, B> = (a: A) => Promise<B>;
 type StateToDisplay = 'Before' | 'After' | 'Both' | 'None'
-
-type callstack = 'Consolidated' | Values.callstack
-const isConsolidated = (c: callstack): boolean => c === 'Consolidated';
+type callstack = 'Summary' | Values.callstack
 
 function useCallstacksCache(): Request<Ast.marker[], callstack[]> {
   const get = React.useCallback((markers) => {
@@ -32,9 +51,7 @@ function useCallstacksCache(): Request<Ast.marker[], callstack[]> {
   return Dome.useCache(get, toString);
 }
 
-type Status = 'True' | 'False' | 'Unknown'
-type Alarm = [ Status, string ]
-
+type Alarm = [ 'True' | 'False' | 'Unknown', string ]
 function getAlarmStatus(alarms: Alarm[]): string {
   if (alarms.length === 0) return 'none';
   if (alarms.find(([st, _]) => st === 'False')) return 'False';
@@ -51,6 +68,11 @@ function MarkerStatusClass(status: MarkerStatus): string {
   return 'eva-header-' + kind.toLowerCase() + (focused ? '-focused' : '');
 }
 
+function isPinnedMarker(status: MarkerStatus): boolean {
+  if (status === 'JustFocused') return false;
+  const [ kind ] = status;
+  return kind === 'Pinned';
+}
 
 
 
@@ -62,27 +84,36 @@ interface Callsite {
 
 function useCallsitesCache(): Request<callstack, Callsite[]> {
   const get = React.useCallback((c) => {
-    if (!isConsolidated(c)) return Server.send(Values.getCallstackInfo, c);
+    if (c !== 'Summary') return Server.send(Values.getCallstackInfo, c);
     else return Promise.resolve([]);
   }, []);
   return Dome.useCache(get);
 }
 
 interface CallsiteCellProps {
-  byCallstacks: boolean;
-  state: StateToDisplay;
-  index?: number;
+  callstack: callstack | 'Header';
+  getCallsites: Request<callstack, Callsite[]>;
   selectedClass?: string;
 }
 
-function CallsiteCell(props: CallsiteCellProps): JSX.Element {
-  const { byCallstacks, state, index:n, selectedClass = '' } = props;
-  const activeClass = byCallstacks ? 'eva-table-callsite-active' : '';
+function makeStackTitle(calls: Callsite[]): string {
+  const cs = calls.slice(1);
+  if (cs.length > 0)
+    return `Callstack: ${cs.map((c) => c.callee).join(' \u2190 ')}`;
+  return 'Callstack Details';
+}
+
+async function CallsiteCell(props: CallsiteCellProps): Promise<JSX.Element> {
+  const { callstack: c, getCallsites, selectedClass = '' } = props;
+  const activeClass = 'eva-table-callsite-active';
   const callClass = classes('eva-table-callsite', activeClass, selectedClass);
-  const callVisibility = state === 'None' ? 'hidden' : 'visible';
+  const callsites = c !== 'Header' ? await getCallsites(c) : [];
+  const infos =
+    c === 'Header' ? 'Corresponding callstack' :
+      c === 'Summary' ? 'Summary' : makeStackTitle(callsites);
   return (
-    <td className={callClass} style={{ visibility: callVisibility }}>
-      {byCallstacks ? (n !== undefined ? (n === 0 ? '∑' : n) : '#') : ''}
+    <td className={callClass} title={infos}>
+      {c === 'Header' ? '#' : c === 'Summary' ? '∑' : c}
     </td>
   );
 }
@@ -96,10 +127,10 @@ interface Location {
 
 interface Evaluation {
   errors?: string;
-  vBefore?: evaluation;
-  vAfter?: evaluation;
-  vThen?: evaluation;
-  vElse?: evaluation;
+  vBefore?: Values.evaluation;
+  vAfter?: Values.evaluation;
+  vThen?: Values.evaluation;
+  vElse?: Values.evaluation;
 }
 
 interface Probe extends Location {
@@ -116,7 +147,7 @@ function useProbeCache(): Request<Location, Probe> {
   const get = React.useCallback(async (loc: Location): Promise<Probe> => {
     const infos = await Server.send(Values.getProbeInfo, loc.target);
     const evaluate: Request<callstack, Evaluation> = (c) => {
-      const callstack = isConsolidated(c) ? undefined : c as Values.callstack;
+      const callstack = c === 'Summary' ? undefined : c as Values.callstack;
       return Server.send(Values.getValues, { ...loc, callstack });
     };
     return { ...loc, ...infos, evaluate };
@@ -199,7 +230,8 @@ async function StackInfos(props: StackInfosProps): Promise<JSX.Element> {
       </Cell>
     );
   };
-  return <Hpack className="eva-info">{callsites.map(makeCallsite)}</Hpack>;
+  const children = React.Children.toArray(callsites.map(makeCallsite));
+  return <Hpack className="eva-info">{children}</Hpack>;
 }
 
 
@@ -219,12 +251,7 @@ function SelectedProbeInfos(props: ProbeInfosProps): JSX.Element {
   const stmt = probe?.stmt;
   const target = probe?.target;
   const visible = code !== undefined;
-  let pinned = false;
-  if (status && status !== 'JustFocused') {
-    const [ kind ] = status;
-    pinned = kind === 'Pinned';
-  }
-
+  const pinned = status ? isPinnedMarker(status) : false;
   return (
     <Hpack className="eva-probeinfo">
       <div
@@ -288,6 +315,7 @@ interface ProbeHeaderProps {
   probe: Probe;
   status: MarkerStatus;
   state: StateToDisplay;
+  pinProbe: (pin: boolean) => void;
   selectProbe: () => void;
   removeProbe: () => void;
   setSelection: (a: States.SelectionActions) => void;
@@ -297,12 +325,12 @@ async function ProbeHeader(props: ProbeHeaderProps): Promise<JSX.Element> {
   const { probe, status, state, setSelection } = props;
   const { code = '(error)', stmt, target, fct } = probe;
   const color = MarkerStatusClass(status);
-  const { selectProbe, removeProbe } = props;
+  const { selectProbe, removeProbe, pinProbe } = props;
 
   // Computing the number of columns. By design, either vAfter or vThen and
   // vElse are empty. Also by design (hypothesis), it is not function of the
   // considered callstacks, so we check on the consolidated.
-  const evaluation = await probe.evaluate('Consolidated');
+  const evaluation = await probe.evaluate('Summary');
   const { vBefore, vAfter, vThen, vElse } = evaluation;
   let span = 0;
   if ((state === 'Before' || state === 'Both') && vBefore) span += 1;
@@ -312,6 +340,7 @@ async function ProbeHeader(props: ProbeHeaderProps): Promise<JSX.Element> {
 
   const loc: States.SelectionActions = { location: { fct, marker: target} };
   const onClick = (): void => { setSelection(loc); selectProbe(); };
+  const onDoubleClick = (): void => pinProbe(!isPinnedMarker(status));
   const onContextMenu = (): void => {
     const items: Dome.PopupMenuItem[] = [];
     const removeLabel = `Remove column for ${code}`;
@@ -324,6 +353,7 @@ async function ProbeHeader(props: ProbeHeaderProps): Promise<JSX.Element> {
       className={color}
       colSpan={span}
       onClick={onClick}
+      onDoubleClick={onDoubleClick}
       onContextMenu={onContextMenu}
     >
       <span className='dome-text-cell'>{code}</span>
@@ -338,18 +368,15 @@ interface ProbeValuesProps {
   probe: Probe;
   status: MarkerStatus;
   state: StateToDisplay;
-  selectCallstack: () => void;
   addLoc: (loc: Location) => void;
   selectedClass?: string;
 }
 
 function ProbeValues(props: ProbeValuesProps): Request<callstack, JSX.Element> {
-  const { probe, state, selectedClass = '' } = props;
-  const { selectCallstack, addLoc } = props;
+  const { probe, state, selectedClass = '', addLoc } = props;
   const className = classes('eva-table-values', selectedClass);
 
   // Building common parts
-  const onClick = selectCallstack;
   const onContextMenu = (evaluation: Values.evaluation) => (): void => {
     const { value, pointedVars } = evaluation;
     const items: Dome.PopupMenuItem[] = [];
@@ -372,10 +399,10 @@ function ProbeValues(props: ProbeValuesProps): Request<callstack, JSX.Element> {
     function td(e: Values.evaluation, state: string): JSX.Element {
       const status = getAlarmStatus(e.alarms);
       const alarmClass = `eva-alarms eva-alarm-${status}`;
-      const title = 'At least one alarm is raised in one callstack';
+      const kind = callstack === 'Summary' ? 'one' : 'this';
+      const title = `At least one alarm is raised in ${kind} callstack`;
       return (
         <td
-          onClick={onClick}
           className={className}
           onContextMenu={onContextMenu(e)}
         >
@@ -406,11 +433,13 @@ interface FunctionProps {
   state: StateToDisplay;
   close: () => void;
   getProbe: Request<Location, Probe>;
+  pinProbe: (probe: Probe, pin: boolean) => void;
   selectProbe: (probe: Probe) => void;
   removeProbe: (probe: Probe) => void;
   addLoc: (loc: Location) => void;
   folded: boolean;
   setFolded: (folded: boolean) => void;
+  getCallsites: Request<callstack, Callsite[]>;
   byCallstacks: boolean;
   getCallstacks: Request<Ast.marker[], callstack[]>;
   setByCallstacks: (byCallstack: boolean) => void;
@@ -421,17 +450,17 @@ interface FunctionProps {
 
 async function FunctionSection(props: FunctionProps): Promise<JSX.Element> {
   const { fct, state, folded, isSelectedCallstack } = props;
-  const { byCallstacks, setSelection } = props;
+  const { byCallstacks, setSelection, getCallsites } = props;
   const { addLoc, getCallstacks: getCS } = props;
   const { setFolded, setByCallstacks, close } = props;
-  const callsiteProps = { byCallstacks, state };
   const displayTable = folded ? 'none' : 'table';
+  const headerCall = await CallsiteCell({ getCallsites, callstack: 'Header' });
 
   /* Compute relevant callstacks */
   const markers: Ast.marker[] = [];
   props.markers.forEach((_, m) => markers.push(m));
   const computedCallstacks = byCallstacks ? (await getCS(markers) ?? []) : [];
-  const callstacks = [ 'Consolidated' as callstack ].concat(computedCallstacks);
+  const callstacks = [ 'Summary' as callstack ].concat(computedCallstacks);
 
   const probes: [ Promise<Probe>, MarkerStatus ][] = [];
   props.markers.forEach(async (status, target) => {
@@ -441,24 +470,29 @@ async function FunctionSection(props: FunctionProps): Promise<JSX.Element> {
 
   const headers = await Promise.all(probes.map(async ([ promise, status ]) => {
     const probe = await promise;
+    const pinProbe = (pin: boolean): void => props.pinProbe(probe, pin);
     const selectProbe = (): void => props.selectProbe(probe);
     const removeProbe = (): void => props.removeProbe(probe);
-    const fcts = { selectProbe, removeProbe, setSelection };
+    const fcts = { selectProbe, pinProbe, removeProbe, setSelection };
     return ProbeHeader({ probe, status, state, ...fcts });
   }));
 
-  const values = await Promise.all(callstacks.map(async (callstack, index) => {
+  const values = await Promise.all(callstacks.map(async (callstack) => {
     const isSelected = isSelectedCallstack(callstack);
-    const selector = isSelected && callstack !== 'Consolidated';
+    const selector = isSelected && callstack !== 'Summary';
     const selectedClass = selector ? 'eva-table-selected-row' : '';
-    const call = CallsiteCell({ ...callsiteProps, selectedClass, index });
+    const call = await CallsiteCell({ selectedClass, getCallsites, callstack });
+    const onClick = (): void => props.selectCallstack(callstack);
     const vs = await Promise.all(probes.map(async ([ promise, status ]) => {
       const probe = await promise;
-      const selectCallstack = (): void => props.selectCallstack(callstack);
-      const fcts = { addLoc, selectCallstack, selectedClass };
+      const fcts = { addLoc, selectedClass };
       return ProbeValues({ probe, status, state, ...fcts })(callstack);
     }));
-    return <tr key={index}>{call}{React.Children.toArray(vs)}</tr>;
+    return (
+      <tr key={callstack} onClick={onClick}>{call}
+        {React.Children.toArray(vs)}
+      </tr>
+    );
   }));
 
   return (
@@ -486,15 +520,17 @@ async function FunctionSection(props: FunctionProps): Promise<JSX.Element> {
           onClick={close}
         />
       </Hpack>
-      <table className='eva-table' style={{ display: displayTable }}>
-        <tbody>
-          <tr>
-            <CallsiteCell {...callsiteProps} />
-            {React.Children.toArray(headers)}
-          </tr>
-          {React.Children.toArray(values)}
-        </tbody>
-      </table>
+      <div style={{ overflowX: 'auto' }}>
+        <table className='eva-table' style={{ display: displayTable }}>
+          <tbody>
+            <tr>
+              {headerCall}
+              {React.Children.toArray(headers)}
+            </tr>
+            {React.Children.toArray(values)}
+          </tbody>
+        </table>
+      </div>
     </div>
   );
 }
@@ -543,11 +579,19 @@ class FunctionInfos {
     const fct = focusedLoc?.fct;
     const { pinned, tracked } = this;
     const markers = new Map<Ast.marker, MarkerStatus>();
-    if (fct && focused)
-      if (fct === this.fct && !pinned.has(focused) && !tracked.has(focused))
+    if (focused && fct && fct === this.fct) {
+      if (pinned.has(focused))
+        markers.set(focused, [ 'Pinned', true ]);
+      else if (tracked.has(focused))
+        markers.set(focused, [ 'Tracked', true ]);
+      else
         markers.set(focused, 'JustFocused');
-    pinned.forEach((p) => markers.set(p, [ 'Pinned', p === focused ]));
-    tracked.forEach((t) => markers.set(t, [ 'Tracked', t === focused ]));
+    }
+    const add = (marker: Ast.marker, kind: 'Pinned' | 'Tracked'): void => {
+      if (marker !== focused) markers.set(marker, [ kind, false ]);
+    };
+    pinned.forEach((p) => add(p, 'Pinned'));
+    tracked.forEach((t) => add(t, 'Tracked'));
     return markers;
   }
 
@@ -654,14 +698,12 @@ class FunctionsManager {
 
 
 
-export function EvaTable(): JSX.Element {
-  const [ selection, setSelection ] = States.useSelection();
+function EvaTable(): JSX.Element {
+  const [ selection, select ] = States.useSelection();
   const [ state, setState ] = React.useState<StateToDisplay>('Before');
-  const [ cs, setCS ] = React.useState<callstack>('Consolidated');
+  const [ cs, setCS ] = React.useState<callstack>('Summary');
   const [ fcts ] = React.useState(new FunctionsManager());
-
-  const [ cpt, setCpt ] = React.useState(0);
-  const forceUpdate = React.useCallback(() => setCpt(cpt + 1), [cpt, setCpt]);
+  const [ tac, setTic ] = React.useState(false);
 
   const getProbe = useProbeCache();
   const getCallsites = useCallsitesCache();
@@ -672,74 +714,78 @@ export function EvaTable(): JSX.Element {
     const target = selection?.current?.marker;
     const fct = selection?.current?.fct;
     const loc = (target && fct) ? { target, fct } : undefined;
-    const doUpdate = (probe: Probe): void => {
-      if (fct && probe.code) fcts.newFunction(fct);
-      setFocus(probe);
-    };
+    const f = (p: Probe): void => { if (fct && p.code) fcts.newFunction(fct); };
+    const doUpdate = (p: Probe): void => { f(p) ; setFocus(p); };
     fcts.clean(loc);
     if (loc) getProbe(loc).then(doUpdate);
     else setFocus(undefined);
   }, [ fcts, selection, getProbe, setFocus ]);
 
-  const setLocPin = (loc: Location, pin: boolean): void => {
+  const setLocPin = React.useCallback((loc: Location, pin: boolean): void => {
     if (pin) fcts.pin(loc);
     else fcts.unpin(loc);
-    forceUpdate();
-  };
+    setTic(!tac);
+  }, [fcts, setTic, tac]);
 
-  const removeProbe = React.useCallback((probe: Probe): void => {
+  const remove = React.useCallback((probe: Probe): void => {
     fcts.removeLocation(probe);
     if (probe.target === focus?.target)
       setFocus(undefined);
     fcts.clean(undefined);
-    forceUpdate();
-  }, [ fcts, focus, setFocus, forceUpdate ]);
+    setTic(!tac);
+  }, [ fcts, focus, setFocus, tac ]);
 
-  const { result: functions } = Dome.usePromise(() => {
+  const functionsPromise = React.useMemo(() => {
     const ps = fcts.map((infos, fct) => {
       const { byCallstacks, folded } = infos;
       const isSelectedCallstack = (c: callstack): boolean => c === cs;
       const setFolded = (folded: boolean): void => {
         fcts.setFolded(fct, folded);
-        forceUpdate();
+        setTic(!tac);
       };
       const setByCS = (byCS: boolean): void => {
         fcts.setByCallstacks(fct, byCS);
-        forceUpdate();
+        setTic(!tac);
       };
       return {
         fct,
         markers: infos.markers(focus),
         state,
-        close: () => { fcts.delete(fct); forceUpdate(); },
+        close: () => { fcts.delete(fct); setTic(!tac); },
+        pinProbe: setLocPin,
         getProbe,
         selectProbe: setFocus,
-        removeProbe,
-        addLoc: (loc: Location) => { fcts.pin(loc); forceUpdate(); },
+        removeProbe: remove,
+        addLoc: (loc: Location) => { fcts.pin(loc); setTic(!tac); },
         folded,
         setFolded,
+        getCallsites,
         byCallstacks,
         getCallstacks,
         setByCallstacks: setByCS,
-        selectCallstack: (c: callstack) => { setCS(c); forceUpdate(); },
+        selectCallstack: (c: callstack) => { setCS(c); setTic(!tac); },
         isSelectedCallstack,
-        setSelection,
+        setSelection: select,
       };
     });
     return Promise.all(ps.map(FunctionSection));
-  }, [ fcts, setFocus, removeProbe, cpt ]);
+  },
+  [ cs, fcts, focus, tac, getCallsites, setLocPin,
+    getCallstacks, getProbe, remove, select, state
+  ]);
+  const { result: functions } = Dome.usePromise(functionsPromise);
 
-  const { result: alarmsInfos } = Dome.usePromise(() => {
-    return AlarmsInfos(focus)(cs);
-  }, [ focus, cs ]);
+  const alarmsProm = React.useMemo(() => AlarmsInfos(focus)(cs), [ focus, cs ]);
+  const { result: alarmsInfos } = Dome.usePromise(alarmsProm);
 
-  const { result: stackInfos } = Dome.usePromise(async () => {
+  const stackInfosPromise = React.useMemo(async () => {
     const callsites = await getCallsites(cs);
     const tgt = selection.current?.marker;
     const p = (c: Callsite): boolean => c.stmt !== undefined && c.stmt === tgt;
     const isSelected = callsites.find(p) !== undefined;
-    return StackInfos({ callsites, isSelected, setSelection });
-  }, [ cs, setSelection ]);
+    return StackInfos({ callsites, isSelected, setSelection: select });
+  }, [ cs, select, getCallsites, selection ]);
+  const { result: stackInfos } = Dome.usePromise(stackInfosPromise);
 
   return (
     <>
@@ -748,11 +794,11 @@ export function EvaTable(): JSX.Element {
         probe={focus}
         status={fcts.status(focus)}
         setLocPin={setLocPin}
-        removeProbe={removeProbe}
+        removeProbe={remove}
         state={state}
-        setState={(s) => { setState(s); forceUpdate(); }}
+        setState={setState}
       />
-      <Vfill style={{ overflow: 'auto' }}>
+      <Vfill style={{ overflowY: 'auto' }}>
         {React.Children.toArray(functions)}
       </Vfill>
       {alarmsInfos}
@@ -760,3 +806,15 @@ export function EvaTable(): JSX.Element {
     </>
   );
 }
+
+
+
+Ivette.registerComponent({
+  id: 'frama-c.plugins.values',
+  group: 'frama-c.plugins',
+  rank: 1,
+  label: 'Eva Values',
+  title: 'Values inferred by the Eva analysis',
+  children: <EvaTable />,
+});
+