Skip to content

Commit

Permalink
Avoid line break when editing a value while Auto Fit is enabled (#132)
Browse files Browse the repository at this point in the history
- Ensure that editing takes as much space as display
- Use CSS to set styles on elements
- Avoid large number of updates by guarding auto-fit group calculation

Fixes #112

Co-authored-by: Philip Langer <[email protected]>
  • Loading branch information
martin-fleck-at and planger authored May 8, 2024
1 parent b0046d4 commit 1ec6ea9
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 19 deletions.
37 changes: 37 additions & 0 deletions media/memory-table.css
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@
width: 2px;
}

/* == Hover == */

.hoverable:hover {
border-bottom: 1px dotted var(--vscode-editorHoverWidget-border);
}
Expand Down Expand Up @@ -158,3 +160,38 @@
.memory-hover .variable-hover .value.type {
color: var(--vscode-debugTokenExpression-name);
}

/* == Data Edit == */

.byte-group {
font-family: var(--vscode-editor-font-family);
margin-right: 2px;
padding: 0 1px; /* we use this padding to balance out the 2px that are needed for the editing */
}

.byte-group:last-child {
margin-right: 0px;
}

.byte-group:has(> .data-edit) {
outline: 1px solid var(--vscode-inputOption-activeBorder);
outline-offset: 1px;
padding: 0px; /* editing takes two more pixels cause the input field will cut off the characters otherwise. */
}

.data-edit {
padding: 0;
outline: 0;
border: none;
text-indent: 1px;
min-height: unset;
height: 2ex;
background: unset;
margin: 0;
}

.data-edit:enabled:focus {
outline: none;
border: none;
text-indent: 1px;
}
30 changes: 12 additions & 18 deletions src/webview/columns/data-column.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,7 @@ export class EditableDataColumnRow extends React.Component<EditableDataColumnRow
const next = address + 1n;
if (maus.length % options.mausPerGroup === 0) {
this.applyEndianness(maus, options);
const isLast = next >= range.endAddress;
const style: React.CSSProperties | undefined = isLast ? undefined : DataColumn.Styles.byteGroupStyle;
groups.push(this.renderGroup(maus, groupStartAddress, next, style));
groups.push(this.renderGroup(maus, groupStartAddress, next));
groupStartAddress = next;
maus = [];
}
Expand All @@ -82,12 +80,11 @@ export class EditableDataColumnRow extends React.Component<EditableDataColumnRow
return groups;
}

protected renderGroup(maus: React.ReactNode, startAddress: bigint, endAddress: bigint, style?: React.CSSProperties): React.ReactNode {
protected renderGroup(maus: React.ReactNode, startAddress: bigint, endAddress: bigint): React.ReactNode {
return <span
className='byte-group hoverable'
data-column='data'
data-range={`${startAddress}-${endAddress}`}
style={style}
key={startAddress.toString(16)}
onDoubleClick={this.setGroupEdit}
>
Expand Down Expand Up @@ -138,21 +135,16 @@ export class EditableDataColumnRow extends React.Component<EditableDataColumnRow
}

protected renderEditingGroup(editedRange: BigIntMemoryRange): React.ReactNode {
const isLast = editedRange.endAddress === this.props.range.endAddress;
const defaultValue = this.createEditingGroupDefaultValue(editedRange);

const style: React.CSSProperties = {
...decorationService.getDecoration(editedRange.startAddress)?.style,
width: `calc(${defaultValue.length}ch + 10px)`,
padding: '0 4px',
marginRight: isLast ? undefined : DataColumn.Styles.byteGroupStyle.marginRight,
minHeight: 'unset',
border: '1px solid var(--vscode-inputOption-activeBorder)',
background: 'unset'
width: `calc(${defaultValue.length}ch + 2px)` // we balance the two pixels with padding on the group
};

return <InputText key={editedRange.startAddress.toString(16)}
ref={this.inputText}
className='data-edit'
maxLength={defaultValue.length}
defaultValue={defaultValue}
onBlur={this.onBlur}
Expand Down Expand Up @@ -232,10 +224,10 @@ export class EditableDataColumnRow extends React.Component<EditableDataColumnRow

export namespace DataColumn {
export namespace Styles {
// `margin-right: 2px` per group (see memory-table.css)
export const MARGIN_RIGHT_PX = 2;
export const byteGroupStyle: React.CSSProperties = {
marginRight: `${DataColumn.Styles.MARGIN_RIGHT_PX}px`
};
// `padding: 0 1px` applies 1px right and left per group (see memory-table.css)
export const PADDING_RIGHT_LEFT_PX = 2;
}

/**
Expand All @@ -255,11 +247,13 @@ export namespace DataColumn {
const columnWidth = elementInnerWidth(element);
// The browser also rounds the character width
const charactersWidth = Math.round((characterWidthInContainer(element, '0') + Number.EPSILON) * 100) / 100;
const groupWidth = charactersWidth
* 2 // characters per byte
const charactersPerByte = 2;
const groupWidth = (
charactersWidth
* charactersPerByte
* options.bytesPerMau
* options.mausPerGroup
+ Styles.MARGIN_RIGHT_PX;
) + Styles.MARGIN_RIGHT_PX + Styles.PADDING_RIGHT_LEFT_PX;
// Accommodate the non-existent margin of the final element.
const maxGroups = Math.max((columnWidth + Styles.MARGIN_RIGHT_PX) / groupWidth, 1);

Expand Down
6 changes: 5 additions & 1 deletion src/webview/components/memory-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,11 @@ export class MemoryTable extends React.PureComponent<MemoryTableProps, MemoryTab
this.setState(prev => ({ ...prev, selection: null }));
}

this.ensureGroupsPerRowToRenderIsSet();
const hasDisplayChanged = prevProps.bytesPerMau !== this.props.bytesPerMau || prevProps.mausPerGroup !== this.props.mausPerGroup ||
(prevProps.groupsPerRow !== 'Autofit' && this.props.groupsPerRow === 'Autofit');
if (hasDisplayChanged) {
this.ensureGroupsPerRowToRenderIsSet();
}
if (this.props.memory !== undefined && this.props.scrollingBehavior === 'Auto-Append') {
this.ensureSufficientVisibleRowsForScrollbar();

Expand Down

0 comments on commit 1ec6ea9

Please sign in to comment.