Files
weave-scope/client/app/scripts/selectors/resource-view/zoom.js
Filip Barl 69fd397217 Initial version of the resource view (#2296)
* Added resource view selector button

* Showing resource boxes in the resource view

* Crude CPU resource view prototype

* Improved the viewMode state logic

* Extracted zooming into a separate wrapper component

* Split the layout selectors between graph-view and resource-view

* Proper zooming logic for the resource view

* Moved all node networks utils to selectors

* Improved the zoom caching logic

* Further refactoring of selectors

* Added sticky labels to the resource boxes

* Added panning translation limits in the resource view

* Renamed GridModeSelector -> ViewModeSelector

* Polished the topology resource view selection logic

* Search bar hidden in the resource view

* Added per-layer topology names to the resource view

* Made metric selectors work for the resource view

* Adjusted the viewport selectors

* Renamed viewport selector to canvas (+ maximal zoom fix)

* Showing more useful metric info in the resource box labels

* Fetching only necessary nodes for the resource view

* Refactored the resource view layer component

* Addressed first batch UI comments (from the Scope meeting)

* Switch to deep zooming transform in the resource view to avoid SVG precision errors

* Renamed and moved resource view components

* Polished all the resource view components

* Changing the available metrics selection

* Improved and polished the state transition logic for the resource view

* Separated zoom limits from the zoom active state

* Renaming and bunch of comments

* Addressed all the UI comments (@davkal + @fons)

* Made graph view selectors independent from resource view selectors
2017-03-24 14:51:53 +01:00

102 lines
3.2 KiB
JavaScript

import { createSelector } from 'reselect';
import { Map as makeMap } from 'immutable';
import { RESOURCES_LAYER_HEIGHT } from '../../constants/styles';
import { canvasMarginsSelector, canvasWidthSelector, canvasHeightSelector } from '../canvas';
import { activeLayoutCachedZoomSelector } from '../zooming';
import {
layerVerticalPositionByTopologyIdSelector,
layoutNodesByTopologyIdSelector,
} from './layout';
// This is used to determine the maximal zoom factor.
const minNodeWidthSelector = createSelector(
[
layoutNodesByTopologyIdSelector,
],
layoutNodes => layoutNodes.flatten(true).map(n => n.get('width')).min()
);
const resourceNodesBoundingRectangleSelector = createSelector(
[
layerVerticalPositionByTopologyIdSelector,
layoutNodesByTopologyIdSelector,
],
(verticalPositions, layoutNodes) => {
if (layoutNodes.size === 0) return null;
const flattenedNodes = layoutNodes.flatten(true);
const xMin = flattenedNodes.map(n => n.get('offset')).min();
const yMin = verticalPositions.toList().min();
const xMax = flattenedNodes.map(n => n.get('offset') + n.get('width')).max();
const yMax = verticalPositions.toList().max() + RESOURCES_LAYER_HEIGHT;
return makeMap({ xMin, xMax, yMin, yMax });
}
);
// Compute the default zoom settings for given resources.
export const resourcesDefaultZoomSelector = createSelector(
[
resourceNodesBoundingRectangleSelector,
canvasMarginsSelector,
canvasWidthSelector,
canvasHeightSelector,
],
(boundingRectangle, canvasMargins, width, height) => {
if (!boundingRectangle) return makeMap();
const { xMin, xMax, yMin, yMax } = boundingRectangle.toJS();
// The default scale takes all the available horizontal space and 70% of the vertical space.
const scaleX = (width / (xMax - xMin)) * 1.0;
const scaleY = (height / (yMax - yMin)) * 0.7;
// This translation puts the graph in the center of the viewport, respecting the margins.
const translateX = ((width - ((xMax + xMin) * scaleX)) / 2) + canvasMargins.left;
const translateY = ((height - ((yMax + yMin) * scaleY)) / 2) + canvasMargins.top;
return makeMap({
translateX,
translateY,
scaleX,
scaleY,
});
}
);
export const resourcesZoomLimitsSelector = createSelector(
[
resourcesDefaultZoomSelector,
resourceNodesBoundingRectangleSelector,
minNodeWidthSelector,
canvasWidthSelector,
],
(defaultZoom, boundingRectangle, minNodeWidth, width) => {
if (defaultZoom.isEmpty()) return makeMap();
const { xMin, xMax, yMin, yMax } = boundingRectangle.toJS();
return makeMap({
// Maximal zoom is such that the smallest box takes the whole canvas.
maxScale: width / minNodeWidth,
// Minimal zoom is equivalent to the initial one, where the whole layout matches the canvas.
minScale: defaultZoom.get('scaleX'),
minTranslateX: xMin,
maxTranslateX: xMax,
minTranslateY: yMin,
maxTranslateY: yMax,
});
}
);
export const resourcesZoomStateSelector = createSelector(
[
resourcesDefaultZoomSelector,
activeLayoutCachedZoomSelector,
],
// All the cached fields override the calculated default ones.
(resourcesDefaultZoom, cachedZoomState) => resourcesDefaultZoom.merge(cachedZoomState)
);