Skip to content

Commit

Permalink
- adding the tooltip above incompatible speed limit tag
Browse files Browse the repository at this point in the history
  • Loading branch information
Caracol3 committed Jul 10, 2024
1 parent c60f824 commit 9a512a5
Show file tree
Hide file tree
Showing 8 changed files with 232 additions and 121 deletions.
1 change: 0 additions & 1 deletion ui-speedspacechart/src/components/SpeedSpaceChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import ElectricalProfileLayer from './layers/ElectricalProfileLayer';
import SettingsPanel from './common/SettingsPanel';
import InteractionButtons from './common/InteractionButtons';
import SpeedLimitTagsLayer from './layers/SpeedLimitTagsLayer';
import { LAYERS_HEIGHTS } from './const';

export type SpeedSpaceChartProps = {
width: number;
Expand Down
16 changes: 8 additions & 8 deletions ui-speedspacechart/src/components/common/DetailsBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ const DetailsBox = ({
modeText,
}: DetailsBoxProps) => {
const { MARGIN_TOP, MARGIN_BOTTOM, MARGIN_LEFT, MARGIN_RIGHT } = MARGINS;
const { detailsBoxDisplay } = store;
const { energySource, tractionStatus, declivities, electricalProfiles, powerRestrictions } =
store.detailsBoxDisplay;

let rightOffset = 0;
let bottomOffset = 0;
Expand Down Expand Up @@ -62,18 +63,17 @@ const DetailsBox = ({
<span>--</span>
<span>±--</span>
</div>
{(detailsBoxDisplay.energySource || detailsBoxDisplay.tractionStatus) &&
(modeText || effortText) && <hr />}
{detailsBoxDisplay.energySource && modeText && <span id="mode-text">{modeText}</span>}
{detailsBoxDisplay.tractionStatus && effortText && <span id="effort-text">{effortText}</span>}
{(energySource || tractionStatus) && (modeText || effortText) && <hr />}
{energySource && modeText && <span id="mode-text">{modeText}</span>}
{tractionStatus && effortText && <span id="effort-text">{effortText}</span>}
{electricalModeText && (
<div id="electrical-mode-text">
<p>{electricalModeText}</p>
{detailsBoxDisplay.electricalProfiles && <p>{electricalProfileText}</p>}
{electricalProfiles && <p>{electricalProfileText}</p>}
</div>
)}
{detailsBoxDisplay.powerRestrictions && <span id="power-restriction">--</span>}
{detailsBoxDisplay.declivities && (
{powerRestrictions && <span id="power-restriction">--</span>}
{declivities && (
<>
<hr />
<span id="previous-gradient-text">{`${previousGradientText} ‰`}</span>
Expand Down
27 changes: 27 additions & 0 deletions ui-speedspacechart/src/components/common/Tooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react';

type TooltipProps = {
cursorX: number;
cursorY: number;
height: number;
text: string;
};
const Tooltip = ({ cursorX, cursorY, height, text }: TooltipProps) => {
const tooltipWidth = 246;

return (
<div
id="tooltip"
className="absolute"
style={{
marginTop: cursorY,
marginLeft: cursorX - tooltipWidth / 2,
maxHeight: height,
}}
>
<span>{text}</span>
</div>
);
};

export default Tooltip;
232 changes: 137 additions & 95 deletions ui-speedspacechart/src/components/helpers/drawElements/speedLimitTags.ts
Original file line number Diff line number Diff line change
@@ -1,141 +1,183 @@
import { Store } from '../../../types/chartTypes';
import { Store, tooltipInfos } from '../../../types/chartTypes';
import {
clearCanvas,
createSvgBlobUrl,
// createSvgBlobUrl,
drawLinearLayerBackground,
drawRoundedRect,
drawSeparatorLinearLayer,
loadSvgImage,
// loadSvgImage,
maxPositionValues,
positionOnGraphScale,
} from '../../utils';
import { LAYERS_HEIGHTS, MARGINS } from '../../const';
import { drawSvgImageWithColor } from '../../utils';
import { LAYERS_HEIGHTS, LINEAR_LAYERS_BACKGROUND_COLOR, MARGINS } from '../../const';
// import { drawSvgImageWithColor } from '../../utils';

import questionSvg from '../../../../../ui-icons/icons/question-16.svg?raw';
import alertFillSvg from '../../../../../ui-icons/icons/alert-fill-16.svg?raw';
// import questionSvg from '../../../../../icons/question-16.svg?raw';
// import alertFillSvg from '../../../../../ui-icons/alert-fill-16.svg?raw';

const questionBlobUrl = createSvgBlobUrl(questionSvg);
const alertFillBlobUrl = createSvgBlobUrl(alertFillSvg);

const { CURVE_MARGIN_SIDES } = MARGINS;
// const questionBlobUrl = createSvgBlobUrl(questionSvg);
// const alertFillBlobUrl = createSvgBlobUrl(alertFillSvg);

export const drawSpeedLimitTags = async (
ctx: CanvasRenderingContext2D,
width: number,
marginTop: number,
store: Store
) => {
const { speedLimitTags, ratioX, leftOffset } = store;

const { MARGIN_BOTTOM, MARGIN_LEFT } = MARGINS;

if (!speedLimitTags) return;
): Promise<tooltipInfos | null> => {
const {
speedLimitTags,
ratioX,
leftOffset,
layersDisplay: { electricalProfiles, powerRestrictions },
cursor,
} = store;

const { MARGIN_BOTTOM, MARGIN_LEFT, MARGIN_RIGHT } = MARGINS;

if (!speedLimitTags) return null;
clearCanvas(ctx, width, LAYERS_HEIGHTS.SPEED_LIMIT_TAGS_HEIGHT);

ctx.save();
ctx.translate(leftOffset, 0);

const { maxPosition } = maxPositionValues(store);

ctx.fillStyle = 'black';
ctx.strokeStyle = 'black';
ctx.lineWidth = 1;
// const questionImage = await loadSvgImage(questionBlobUrl);
// const alertFillImage = await loadSvgImage(alertFillBlobUrl);

const questionImage = await loadSvgImage(questionBlobUrl);
const alertFillImage = await loadSvgImage(alertFillBlobUrl);
let speedLimitTagsBackgroundColor = LINEAR_LAYERS_BACKGROUND_COLOR.FIRST;

if (electricalProfiles && powerRestrictions) {
speedLimitTagsBackgroundColor = LINEAR_LAYERS_BACKGROUND_COLOR.THIRD;
} else if (electricalProfiles || powerRestrictions) {
speedLimitTagsBackgroundColor = LINEAR_LAYERS_BACKGROUND_COLOR.SECOND;
}

drawSeparatorLinearLayer(ctx, 'rgba(0,0,0,0.1)', MARGINS, width, MARGIN_BOTTOM + 1);

drawLinearLayerBackground(
ctx,
'white',
speedLimitTagsBackgroundColor,
MARGINS,
width,
MARGIN_BOTTOM,
LAYERS_HEIGHTS.SPEED_LIMIT_TAGS_HEIGHT - 1
);

for (let index = 0; index < speedLimitTags.boundaries.length; index++) {
const RECT_HEIGHT = 17;
const yPosition = 12;
const RECTANGLE_SPACING = 1;
const TEXT_RIGHT_PADDING = 8;
const FIRST_TAG_LEFT_PADDING = 8;
// const ICON_WIDTH = 16;
// const ICON_HEIGHT = 16;
const ICON_OFFSET = 4;
const TEXT_PADDING_TOP = 1;

let tooltip: tooltipInfos | null = null;

speedLimitTags.boundaries.forEach((boundary, index) => {
const tag = speedLimitTags.values[index];
if (tag.speed_limit_tags_type === 'tag') {
const rectHeight = 17;
const yPosition = 12;

const x = positionOnGraphScale(
speedLimitTags.boundaries[index],
maxPosition,
width,
ratioX,
MARGINS
);

const profileWidth =
positionOnGraphScale(
speedLimitTags.boundaries[index + 1],
maxPosition,
width,
ratioX,
MARGINS
) -
x -
1;

ctx.fillStyle = tag.color;
ctx.strokeStyle = tag.color;
ctx.lineWidth = 1;

// General rectangle
ctx.beginPath();
ctx.rect(x + 1, yPosition, profileWidth - 2, rectHeight);
ctx.closePath();
ctx.stroke();
ctx.fillRect(x + 1, yPosition, profileWidth - 2, rectHeight);

// Text background-color adjustment
ctx.fillStyle = tag.color;
const textWidth = ctx.measureText(tag.tag_name).width + 8 + (index === 0 ? 8 : 0);
ctx.fillRect(x, yPosition, textWidth, rectHeight);

// Fill the second rectangle with a different color
if (tag.color === '#216482') {
ctx.fillStyle = '#E5F7FF';
} else if (tag.color === '#D91C1C') {
ctx.fillStyle = '#F15981';
} else if (tag.color === '#494641') {
ctx.fillStyle = '#F2F0E4';
} else {
if (tag && tag.speed_limit_tags_type === 'tag') {
const x = positionOnGraphScale(boundary, maxPosition, width, ratioX, MARGINS);
const nextBoundary = speedLimitTags.boundaries[index + 1];

if (nextBoundary !== undefined) {
const tagWidth =
positionOnGraphScale(nextBoundary, maxPosition, width, ratioX, MARGINS) -
x -
RECTANGLE_SPACING;

ctx.fillStyle = tag.color;
}
ctx.fillRect(x + 1 + textWidth, yPosition, profileWidth - textWidth - 2, rectHeight);
ctx.strokeStyle = tag.color;
ctx.lineWidth = 1;

// Draw text or icon
if (tag.tag_name === 'incompatible' || tag.tag_name === 'missing_from_train') {
const image = tag.tag_name === 'incompatible' ? alertFillImage : questionImage;
ctx.beginPath();
ctx.rect(x, yPosition, tagWidth - RECTANGLE_SPACING, RECT_HEIGHT);
ctx.closePath();
ctx.stroke();
ctx.fillRect(x, yPosition, tagWidth - RECTANGLE_SPACING, RECT_HEIGHT);

// Draw the rounded square background
ctx.fillStyle = tag.color;
const iconWidth = 24;
const iconHeight = 24;
const iconXPosition = x + (profileWidth - iconWidth) / 2;
const iconYPosition = yPosition - 4;
const cornerRadius = 4;

// Draw the rounded rectangle using the utility function
drawRoundedRect(ctx, iconXPosition, iconYPosition, iconWidth, iconHeight, cornerRadius);

// Draw the icon inside the rounded square
drawSvgImageWithColor(ctx, image, iconXPosition + 4, iconYPosition + 4, 16, 16, '#fff');
} else {
ctx.fillStyle = 'white';
ctx.font = '600 12px "IBM Plex Sans"';
ctx.textAlign = 'left';
ctx.textBaseline = 'middle';
ctx.fillText(tag.tag_name, x + 4, yPosition + 1 + rectHeight / 2);
const textWidth =
ctx.measureText(tag.tag_name).width +
TEXT_RIGHT_PADDING +
(index === 0 ? FIRST_TAG_LEFT_PADDING : 0);
ctx.fillRect(x, yPosition, textWidth, RECT_HEIGHT);

if (tag.color === '#216482') {
ctx.fillStyle = '#E5F7FF';
} else if (tag.color === '#D91C1C') {
ctx.fillStyle = '#F15981';
} else if (tag.color === '#494641') {
ctx.fillStyle = '#F2F0E4';
} else {
ctx.fillStyle = tag.color;
}
ctx.fillRect(x + 1 + textWidth, yPosition, tagWidth - textWidth - 2, RECT_HEIGHT);

if (tag.tag_name === 'incompatible' || tag.tag_name === 'missing_from_train') {
// const image = tag.tag_name === 'incompatible' ? alertFillImage : questionImage;

ctx.fillStyle = tag.color;
const iconBackgroundWidth = 24;
const iconBackgroundHeight = 24;
const iconXPosition = x + (tagWidth - iconBackgroundWidth) / 2;
const iconYPosition = yPosition - ICON_OFFSET;
const cornerRadius = 4;

drawRoundedRect(
ctx,
iconXPosition,
iconYPosition,
iconBackgroundWidth,
iconBackgroundHeight,
cornerRadius
);

// drawSvgImageWithColor(
// ctx,
// image,
// iconXPosition + ICON_OFFSET,
// iconYPosition + ICON_OFFSET,
// ICON_WIDTH,
// ICON_HEIGHT,
// '#FFFFFF'
// );

if (tag.tag_name === 'incompatible' && cursor.x && cursor.y) {
if (
cursor.x >= x - MARGIN_LEFT + leftOffset &&
cursor.x <= x - MARGIN_LEFT + leftOffset + tagWidth &&
cursor.y >= marginTop - yPosition &&
cursor.y <= marginTop - yPosition + RECT_HEIGHT
) {
tooltip = {
cursorX: cursor.x + MARGIN_LEFT,
cursorY: yPosition,
text: 'Incompatible avec l’infrastructure',
};
console.log(tooltip);
}
}
} else {
ctx.fillStyle = 'white';
ctx.font = '600 12px "IBM Plex Sans"';
ctx.textAlign = 'left';
ctx.textBaseline = 'middle';
const textPosition = index === 0 ? x + FIRST_TAG_LEFT_PADDING : x + 4;
ctx.fillText(tag.tag_name, textPosition, yPosition + TEXT_PADDING_TOP + RECT_HEIGHT / 2);
}
}
}
}
});

drawSeparatorLinearLayer(ctx, 'rgba(0,0,0,0.1)', MARGINS, width, marginTop);
ctx.restore();

// prevent overlapping with margins left and right
ctx.clearRect(0, 0, MARGIN_LEFT, LAYERS_HEIGHTS.SPEED_LIMIT_TAGS_HEIGHT);
ctx.clearRect(width - MARGIN_RIGHT, 0, width, LAYERS_HEIGHTS.SPEED_LIMIT_TAGS_HEIGHT);

return tooltip;
};
Loading

0 comments on commit 9a512a5

Please sign in to comment.