Skip to content

Commit e1e42cb

Browse files
Merge pull request #577 from lukecotter/feat-timeline-high-res-scaling
feat: timeline scaling for high resolution displays
2 parents 9cfbefd + e3ada75 commit e1e42cb

2 files changed

Lines changed: 36 additions & 24 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Change
1111

12-
- Highlight and copy text to clipboard: Call Tree, Analysis and Database views ([#504][#504])
13-
- Previously the highlighted text would be immediately cleared
12+
- Highlight and copy text to clipboard: Call Tree, Analysis and Database views. ([#504][#504])
13+
- Previously the highlighted text would be immediately cleared.
14+
- Sharper timeline rending on HiDPI displays ([#588][#588]).
1415

1516
### Fixed
1617

@@ -377,6 +378,7 @@ Skipped due to adopting odd numbering for pre releases and even number for relea
377378
[#504]: https://github.com/certinia/debug-log-analyzer/issues/504
378379
[#581]: https://github.com/certinia/debug-log-analyzer/issues/581
379380
[#582]: https://github.com/certinia/debug-log-analyzer/issues/582
381+
[#588]: https://github.com/certinia/debug-log-analyzer/issues/588
380382

381383
<!-- 1.16.1 -->
382384

log-viewer/modules/timeline/Timeline.ts

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,8 @@ let scaleFont: string,
161161
displayWidth: number,
162162
timelineRoot: ApexLog,
163163
lastMouseX: number,
164-
lastMouseY: number;
164+
lastMouseY: number,
165+
dpr = window.devicePixelRatio || 1;
165166

166167
let searchString: string = '';
167168
let matchIndex: number | null = null;
@@ -532,17 +533,27 @@ function resetView() {
532533
}
533534

534535
function resize() {
535-
if (!container) {
536+
if (!container || !ctx) {
536537
return;
537538
}
538-
const { clientWidth: newWidth, clientHeight: newHeight } = container;
539+
540+
dpr ??= window.devicePixelRatio || 1;
541+
const { width: newWidth, height: newHeight } = container.getBoundingClientRect();
539542
isVisible = !!newWidth;
540-
if (newWidth && newHeight && (newWidth !== displayWidth || newHeight !== displayHeight)) {
541-
canvas.width = displayWidth = newWidth;
542-
canvas.height = displayHeight = newHeight;
543-
ctx?.setTransform(1, 0, 0, 1, 0, displayHeight); // shift y-axis down so that 0,0 is bottom-lefts
544543

545-
const newDefaultZoom = newWidth / timelineRoot.exitStamp;
544+
if (newWidth && newHeight && (newWidth !== displayWidth || newHeight !== displayHeight)) {
545+
canvas.width = newWidth * dpr;
546+
canvas.height = newHeight * dpr;
547+
displayWidth = newWidth;
548+
displayHeight = newHeight;
549+
550+
// shift y-axis down so that 0,0 is bottom-lefts
551+
ctx.setTransform(1, 0, 0, 1, 0, canvas.height);
552+
// Scale all drawing operations by the dpr, so you
553+
// don't have to worry about the difference.
554+
ctx.scale(dpr, dpr);
555+
556+
const newDefaultZoom = displayWidth / timelineRoot.exitStamp;
546557
// defaults if not set yet
547558
state.defaultZoom ||= state.zoom ||= newDefaultZoom;
548559

@@ -559,7 +570,7 @@ function resizeFont() {
559570

560571
export function init(timelineContainer: HTMLDivElement, rootMethod: ApexLog) {
561572
container = timelineContainer;
562-
canvas = timelineContainer.querySelector('#timeline') as HTMLCanvasElement;
573+
canvas = timelineContainer.querySelector('#timeline')!;
563574
ctx = canvas.getContext('2d'); // can never be null since context (2d) is a supported type.
564575
timelineRoot = rootMethod;
565576
onInitTimeline();
@@ -589,6 +600,7 @@ function drawTimeLine() {
589600

590601
drawTruncation(ctx);
591602
drawScale(ctx);
603+
592604
ctx.strokeStyle = strokeColor;
593605
ctx.lineWidth = 1;
594606
renderRectangles(ctx);
@@ -648,8 +660,8 @@ function showTooltip(offsetX: number, offsetY: number, shouldIgnoreWidth: boolea
648660
if (!dragging && container && tooltip) {
649661
const depth = getDepth(offsetY);
650662
const tooltipText =
651-
findTimelineTooltip(offsetX, depth, shouldIgnoreWidth) || findTruncatedTooltip(offsetX);
652-
showTooltipWithText(offsetX, offsetY, tooltipText, tooltip, container);
663+
findTimelineTooltip(offsetX, depth, shouldIgnoreWidth) ?? findTruncatedTooltip(offsetX);
664+
showTooltipWithText(offsetX, offsetY, tooltipText, tooltip);
653665
}
654666
}
655667

@@ -755,22 +767,22 @@ function showTooltipWithText(
755767
offsetY: number,
756768
tooltipText: HTMLDivElement | null,
757769
tooltip: HTMLElement,
758-
timelineWrapper: HTMLElement,
759770
) {
760-
if (tooltipText && tooltip && timelineWrapper) {
771+
if (tooltipText && tooltip && container) {
761772
let posLeft = offsetX + 10,
762773
posTop = offsetY + 2;
763774

764775
tooltip.innerHTML = '';
765776
tooltip.appendChild(tooltipText);
766777
tooltip.style.cssText = `left:${posLeft}px; top:${posTop}px; display: block;`;
767778

768-
const xDelta = tooltip.offsetWidth - timelineWrapper.offsetWidth + posLeft;
779+
const { offsetWidth: width, offsetHeight: height } = container;
780+
const xDelta = tooltip.offsetWidth - width + posLeft;
769781
if (xDelta > 0) {
770782
posLeft -= xDelta - 4;
771783
}
772784

773-
const yDelta = tooltip.offsetHeight - timelineWrapper.offsetHeight + posTop;
785+
const yDelta = tooltip.offsetHeight - height + posTop;
774786
if (yDelta > 0) {
775787
posTop -= tooltip.offsetHeight + 4;
776788
}
@@ -802,13 +814,11 @@ function _hideTooltip() {
802814
function onMouseMove(evt: MouseEvent) {
803815
const target = evt.target as HTMLElement;
804816

805-
if (target && (target.id === 'timeline' || target.id === 'tooltip')) {
806-
const clRect = canvas?.getBoundingClientRect();
807-
if (clRect) {
808-
lastMouseX = evt.clientX - clRect.left;
809-
lastMouseY = evt.clientY - clRect.top;
810-
debounce(showTooltip)(lastMouseX, lastMouseY, false);
811-
}
817+
if (target && canvas && (target.id === 'timeline' || target.id === 'tooltip')) {
818+
const { left, top } = canvas.getBoundingClientRect();
819+
lastMouseX = evt.clientX - left;
820+
lastMouseY = evt.clientY - top;
821+
debounce(showTooltip)(lastMouseX, lastMouseY, false);
812822
}
813823
}
814824

0 commit comments

Comments
 (0)