Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add hover byte status #502

Merged
merged 5 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions media/editor/dataDisplayContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,13 @@ export class DisplayContext {
});

this.selectionChangeEmitter.addListener(() => this.publishSelections());
this.hoverChangeEmitter.addListener(() => {
// publishes the new hovered byte
messageHandler.sendEvent({
type: MessageType.SetHoveredByte,
hovered: this._hoveredByte?.byte,
})
});
}

/**
Expand Down
8 changes: 8 additions & 0 deletions shared/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const enum MessageType {
ReloadFromDisk,
StashDisplayedOffset,
GoToOffset,
SetHoveredByte,
SetFocusedByte,
SetFocusedByteRange,
SetSelectedCount,
Expand Down Expand Up @@ -145,6 +146,12 @@ export interface SetSelectedCountMessage {
focused?: number;
}

/** Sets the hovered byte in the editor */
export interface SetHoveredByteMessage {
type: MessageType.SetHoveredByte;
hovered?: number;
}

/** Saves the current offset shown in the editor. */
export interface StashDisplayedOffsetMessage {
type: MessageType.StashDisplayedOffset;
Expand Down Expand Up @@ -254,6 +261,7 @@ export type FromWebviewMessage =
| ClearDataInspectorMessage
| SetInspectByteMessage
| SetSelectedCountMessage
| SetHoveredByteMessage
| ReadyRequestMessage
| UpdateEditorSettings
| PasteMessage
Expand Down
6 changes: 4 additions & 2 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import { showGoToOffset } from "./goToOffset";
import { HexEditorProvider } from "./hexEditorProvider";
import { HexEditorRegistry } from "./hexEditorRegistry";
import { showSelectBetweenOffsets } from "./selectBetweenOffsets";
import StatusSelectionCount from "./statusSelectionCount";
import StatusFocus from "./statusFocus";
import StatusHoverAndSelection from "./statusHoverAndSelection";

function readConfigFromPackageJson(extension: vscode.Extension<any>): {
extId: string;
Expand Down Expand Up @@ -69,7 +70,8 @@ export function activate(context: vscode.ExtensionContext): void {
}
},
);
context.subscriptions.push(new StatusSelectionCount(registry));
context.subscriptions.push(new StatusFocus(registry));
context.subscriptions.push(new StatusHoverAndSelection(registry));
context.subscriptions.push(goToOffsetCommand);
context.subscriptions.push(selectBetweenOffsetsCommand);
context.subscriptions.push(openWithCommand);
Expand Down
17 changes: 16 additions & 1 deletion src/hexDocument.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export class HexDocument extends Disposable implements vscode.CustomDocument {
public lastSave = 0;

private _selectionState: ISelectionState = { selected: 0 };

private _hoverState: number | undefined = undefined;
/** Search provider for the document. */
public readonly searchProvider = new SearchProvider();

Expand Down Expand Up @@ -161,6 +161,21 @@ export class HexDocument extends Disposable implements vscode.CustomDocument {
this._onDidChangeSelectionState.fire(state);
}

private readonly _onDidChangeHoverState = this._register(
new vscode.EventEmitter<number | undefined>(),
);

public readonly onDidChangeHoverState = this._onDidChangeHoverState.event;

public get hoverState() {
return this._hoverState;
}

public set hoverState(byte: number | undefined) {
this._hoverState = byte;
this._onDidChangeHoverState.fire(byte);
}

private readonly _onDidRevert = this._register(new vscode.EventEmitter<void>());

/**
Expand Down
4 changes: 3 additions & 1 deletion src/hexEditorProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,9 @@ export class HexEditorProvider implements vscode.CustomEditorProvider<HexDocumen
case MessageType.SetSelectedCount:
document.selectionState = message;
break;

case MessageType.SetHoveredByte:
document.hoverState = message.hovered;
break;
case MessageType.ReadRangeRequest:
const data = await document.readBuffer(message.offset, message.bytes);
return { type: MessageType.ReadRangeResponse, data: getCorrectArrayBuffer(data) };
Expand Down
24 changes: 7 additions & 17 deletions src/statusSelectionCount.ts → src/statusFocus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import { HexEditorRegistry } from "./hexEditorRegistry";
const numberFormat = new Intl.NumberFormat();

/**
* this is a class to represent the status bar item that displays the number of selected bytes
* Displays the focused byte in a StatusBarItem
*
* @class StatusSelectionCount
* @class StatusFocus
*/
export default class StatusSelectionCount extends Disposable {
export default class StatusFocus extends Disposable {
private readonly item: vscode.StatusBarItem;
private readonly docChangeListener = this._register(new DisposableValue());

Expand All @@ -38,25 +38,15 @@ export default class StatusSelectionCount extends Disposable {
trackDocument(registry.activeDocument);
}

update({ focused, selected }: ISelectionState): void {
if (focused === undefined && selected === 0) {
return;
}

update({ focused }: ISelectionState): void {
const nFocus = focused !== undefined ? numberFormat.format(focused) : undefined;
const nSelected = selected > 1 ? numberFormat.format(selected) : undefined;
if (nFocus && nSelected) {
this.item.text = vscode.l10n.t("Byte {0}/0x{1} ({2}/0x{3} selected)", nFocus, focused!.toString(16).toUpperCase(), nSelected, selected.toString(16).toUpperCase());
} else if (nSelected) {
this.item.text = vscode.l10n.t("{0}/0x{1} selected", nSelected, selected.toString(16).toUpperCase());
} else if (nFocus) {
this.item.text = vscode.l10n.t("Byte {0}/0x{1}", nFocus, focused!.toString(16).toUpperCase());
if (nFocus) {
this.item.text = vscode.l10n.t("{0}/0x{1}", nFocus, focused!.toString(16).toUpperCase());
this.item.show();
} else {
this.item.hide();
return;
}

this.item.show();
}

show() {
Expand Down
79 changes: 79 additions & 0 deletions src/statusHoverAndSelection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import * as vscode from "vscode";
import { Disposable, DisposableValue } from "./dispose";
import { HexDocument } from "./hexDocument";
import { HexEditorRegistry } from "./hexEditorRegistry";

const numberFormat = new Intl.NumberFormat();

/**
* Displays the hovered byte and the selection count in a StatusBarItem
*
* @class StatusHoverAndSelection
*/
export default class StatusHoverAndSelection extends Disposable {
private readonly item: vscode.StatusBarItem;
private readonly docChangeListener = this._register(new DisposableValue());

constructor(registry: HexEditorRegistry) {
super();

this.item = this._register(
// Primary Badge, so appears first
vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 101),
);

const trackDocument = (doc: HexDocument | undefined) => {
if (doc) {
this._register(doc.onDidChangeHoverState(() => this.update(doc)));
this._register(doc.onDidChangeSelectionState(() => this.update(doc)));
this.update(doc);
this.show();
} else {
this.hide();
}
};

this._register(registry.onDidChangeActiveDocument(trackDocument));
trackDocument(registry.activeDocument);
}

update({ hoverState, selectionState }: HexDocument): void {
const { selected } = selectionState;
const nHovered = hoverState !== undefined ? numberFormat.format(hoverState) : undefined;
const nSelected = selected > 1 ? numberFormat.format(selected) : undefined;
if (nHovered && nSelected) {
this.item.text = vscode.l10n.t(
"{0}/0x{1} ({2}/0x{3} selected)",
nHovered,
hoverState!.toString(16).toUpperCase(),
nSelected,
selected!.toString(16).toUpperCase(),
);
} else if (nHovered) {
this.item.text = vscode.l10n.t("{0}/0x{1}", nHovered, hoverState!.toString(16).toUpperCase());
} else if (nSelected) {
this.item.text = vscode.l10n.t(
"{0}/0x{1} selected",
nSelected,
selected!.toString(16).toUpperCase(),
);
} else {
// Hiding the element creates a flashing effect so instead set it
// to an empty string
this.item.text = vscode.l10n.t("");
}

this.item.show();
}

show() {
this.item.show();
}

hide() {
this.item.hide();
}
}
Loading