This is an automated email from the ASF dual-hosted git repository.
rstrickland pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/daffodil-vscode.git
The following commit(s) were added to refs/heads/main by this push:
new 1475de6 Implemented Configurable Data Viewport Geometry
1475de6 is described below
commit 1475de6bc323f14b68859d9e53e25ed33d872662
Author: Robert Strickland <[email protected]>
AuthorDate: Fri Oct 6 11:24:50 2023 -0500
Implemented Configurable Data Viewport Geometry
- Added the ability to hide/show viewports.
- Added the ability to change the amount of bytes per row shown and be
independent of the current display radix.
- Added the ability to increment/decrement the amount of viewport lines
being displayed.
- Reworked CSS for viewport data tables to move from `display:grid;` to
`display:flex;`.
Closes #864
Closes #797
Closes #794
---
.../DataDisplays/CustomByteDisplay/BinaryData.ts | 8 +-
.../CustomByteDisplay/DataLineFeed.svelte | 89 +++++++--
.../DataDisplays/Header/DisplayHeader.svelte | 173 ++++++++---------
.../src/components/Editors/DataEditor.svelte | 114 +++++++++--
.../components/Header/fieldsets/Settings.svelte | 4 +-
.../components/Icons/ViewportVisibilityIcon.svelte | 214 +++++++++++++++++++++
.../src/components/Inputs/Buttons/Button.svelte | 4 +-
src/svelte/src/components/Main.svelte | 40 ++--
src/svelte/src/components/dataEditor.svelte | 21 +-
src/svelte/src/components/globalStyles.css | 28 ++-
src/svelte/src/stores/configuration.ts | 12 +-
src/svelte/src/stores/index.ts | 8 +-
12 files changed, 541 insertions(+), 174 deletions(-)
diff --git
a/src/svelte/src/components/DataDisplays/CustomByteDisplay/BinaryData.ts
b/src/svelte/src/components/DataDisplays/CustomByteDisplay/BinaryData.ts
index 95e75e4..6da7477 100644
--- a/src/svelte/src/components/DataDisplays/CustomByteDisplay/BinaryData.ts
+++ b/src/svelte/src/components/DataDisplays/CustomByteDisplay/BinaryData.ts
@@ -17,15 +17,15 @@
import { SimpleWritable } from '../../../stores/localStore'
import {
- NUM_LINES_DISPLAYED,
type BytesPerRow,
type RadixValues,
- VIEWPORT_CAPACITY_MAX,
} from '../../../stores/configuration'
import {
radixBytePad,
viewport_offset_to_line_num,
} from '../../../utilities/display'
+import { dataDislayLineAmount } from '../../../stores'
+import { get } from 'svelte/store'
export const BYTE_ACTION_DIV_OFFSET: number = 24
@@ -112,7 +112,7 @@ export class ViewportDataStore_t extends
SimpleWritable<ViewportData_t> {
public upperFetchBoundary(bytesPerRow: BytesPerRow): number {
const store = this.storeData()
const boundary =
- store.fileOffset + store.length - NUM_LINES_DISPLAYED * bytesPerRow
+ store.fileOffset + store.length - get(dataDislayLineAmount) * bytesPerRow
return boundary
}
@@ -120,7 +120,7 @@ export class ViewportDataStore_t extends
SimpleWritable<ViewportData_t> {
public lineTopMax(bytesPerRow: BytesPerRow): number {
const vpMaxOffset = Math.max(
0,
- this.storeData().length - NUM_LINES_DISPLAYED * bytesPerRow
+ this.storeData().length - get(dataDislayLineAmount) * bytesPerRow
)
const vpLineTopMax = viewport_offset_to_line_num(
vpMaxOffset + this.storeData().fileOffset,
diff --git
a/src/svelte/src/components/DataDisplays/CustomByteDisplay/DataLineFeed.svelte
b/src/svelte/src/components/DataDisplays/CustomByteDisplay/DataLineFeed.svelte
index 5400cc9..644ec8e 100644
---
a/src/svelte/src/components/DataDisplays/CustomByteDisplay/DataLineFeed.svelte
+++
b/src/svelte/src/components/DataDisplays/CustomByteDisplay/DataLineFeed.svelte
@@ -29,10 +29,11 @@ limitations under the License.
editorActionsAllowed,
dataFeedLineTop,
seekOffsetInput,
+ visableViewports,
+ dataDislayLineAmount,
} from '../../../stores'
import {
EditByteModes,
- NUM_LINES_DISPLAYED,
type RadixValues,
EditActionRestrictions,
VIEWPORT_SCROLL_INCREMENT,
@@ -90,7 +91,7 @@ limitations under the License.
if (fetchBound > $fileMetrics.computedSize)
return (
($fileMetrics.computedSize / $bytesPerRow) * $bytesPerRow -
- NUM_LINES_DISPLAYED * $bytesPerRow
+ $dataDislayLineAmount * $bytesPerRow
)
return fetchBound
@@ -124,7 +125,7 @@ limitations under the License.
}
const INCREMENT_SEGMENT = () => {
$seekOffsetInput = line_num_to_file_offset(
- $dataFeedLineTop + NUM_LINES_DISPLAYED,
+ $dataFeedLineTop + $dataDislayLineAmount,
viewportData.fileOffset,
$bytesPerRow
).toString(addressRadix)
@@ -132,7 +133,7 @@ limitations under the License.
}
const DECREMENT_SEGMENT = () => {
$seekOffsetInput = line_num_to_file_offset(
- $dataFeedLineTop - NUM_LINES_DISPLAYED,
+ $dataFeedLineTop - $dataDislayLineAmount,
viewportData.fileOffset,
$bytesPerRow
).toString(addressRadix)
@@ -175,7 +176,7 @@ limitations under the License.
INCREMENT = 1,
}
- let height = `calc(${NUM_LINES_DISPLAYED} * 20)px`
+ let height = `calc(${$dataDislayLineAmount} * 20)px`
let viewportLines: Array<ViewportLineData> = []
let viewportDataContainer: HTMLDivElement
let selectedByteElement: HTMLDivElement
@@ -195,9 +196,9 @@ limitations under the License.
$: {
totalLinesPerFilesize = Math.ceil($fileMetrics.computedSize / $bytesPerRow)
totalLinesPerViewport = Math.ceil(viewportData.data.length / $bytesPerRow)
- lineTopMaxFile = Math.max(totalLinesPerFilesize - NUM_LINES_DISPLAYED, 0)
+ lineTopMaxFile = Math.max(totalLinesPerFilesize - $dataDislayLineAmount, 0)
lineTopMaxViewport = Math.max(
- totalLinesPerViewport - NUM_LINES_DISPLAYED,
+ totalLinesPerViewport - $dataDislayLineAmount,
0
)
@@ -247,9 +248,9 @@ limitations under the License.
startIndex: number,
dataRadix: RadixValues,
addressRadix: RadixValues,
- endIndex: number = startIndex + (NUM_LINES_DISPLAYED - 1)
+ endIndex: number = startIndex + ($dataDislayLineAmount - 1)
): Array<ViewportLineData> {
- let ret = []
+ let ret: Array<ViewportLineData> = []
for (let i = startIndex; i <= endIndex; i++) {
const viewportLineOffset = i * $bytesPerRow
const fileOffset = viewportLineOffset + viewportData.fileOffset
@@ -438,7 +439,7 @@ limitations under the License.
($fileMetrics.computedSize * (percentageTraversed / 100.0)) /
$bytesPerRow
) * $bytesPerRow
- const firstPageThreshold = $bytesPerRow * NUM_LINES_DISPLAYED
+ const firstPageThreshold = $bytesPerRow * $dataDislayLineAmount
const lastPageThreshold = $fileMetrics.computedSize - firstPageThreshold
if (offset <= firstPageThreshold) {
// scroll to the top because we are somewhere in the first page
@@ -513,6 +514,8 @@ limitations under the License.
<div class="address" id="address">
<b>{viewportLine.offset}</b>
</div>
+
+ {#if $visableViewports === 'physical' || $visableViewports === 'all'}
<div
class="byte-line"
id="physical-line-{i.toString(16).padStart(2, '0')}"
@@ -534,6 +537,8 @@ limitations under the License.
/>
{/each}
</div>
+ {/if}
+ {#if $visableViewports === 'logical' || $visableViewports === 'all'}
<div
class="byte-line"
id="logical-line-{i.toString(16).padStart(2, '0')}"
@@ -555,6 +560,7 @@ limitations under the License.
/>
{/each}
</div>
+ {/if}
</div>
{/each}
@@ -564,7 +570,7 @@ limitations under the License.
selectionActive={$selectionDataStore.active}
currentLine={$dataFeedLineTop}
fileOffset={viewportData.fileOffset}
- maxDisplayLines={NUM_LINES_DISPLAYED}
+ maxDisplayLines={$dataDislayLineAmount}
bind:percentageTraversed
on:indicatorClicked={handleClickedIndicator}
/>
@@ -584,7 +590,7 @@ limitations under the License.
fn={INCREMENT_SEGMENT}
disabledBy={disableIncrement}
width="30pt"
- description="Increment offset by {NUM_LINES_DISPLAYED *
+ description="Increment offset by {$dataDislayLineAmount *
$bytesPerRow} bytes"
tooltipAlwaysEnabled={true}
>
@@ -618,7 +624,7 @@ limitations under the License.
fn={DECREMENT_SEGMENT}
disabledBy={disableDecrement}
width="30pt"
- description="Decrement offset by {NUM_LINES_DISPLAYED *
+ description="Decrement offset by {$dataDislayLineAmount *
$bytesPerRow} bytes"
tooltipAlwaysEnabled={true}
>
@@ -637,6 +643,45 @@ limitations under the License.
>stat_3</span
>
</Button>
+ <span class="separator" />
+ <Button
+ fn={() => {
+ $dataDislayLineAmount += 1
+ viewportLines = generate_line_data(
+ $dataFeedLineTop,
+ dataRadix,
+ addressRadix
+ )
+ }
+ }
+ disabledBy={ (($dataDislayLineAmount+1)*$bytesPerRow >=
VIEWPORT_SCROLL_INCREMENT) }
+ description={"Increment display lines (" + ($dataDislayLineAmount+1) +
")"}
+ tooltipAlwaysEnabled={true}
+ width="30pt"
+ >
+ <span slot="left" class="btn-icon material-symbols-outlined">
+ playlist_add
+ </span>
+ </Button>
+ <Button
+ fn={() => {
+ $dataDislayLineAmount -= 1
+ viewportLines = generate_line_data(
+ $dataFeedLineTop,
+ dataRadix,
+ addressRadix
+ )
+ }
+ }
+ disabledBy={$dataDislayLineAmount === 1}
+ description={"Decrement display lines (" + ($dataDislayLineAmount-1) +
")"}
+ tooltipAlwaysEnabled={true}
+ width="30pt"
+ >
+ <span slot="left" class="btn-icon material-symbols-outlined">
+ playlist_remove
+ </span>
+ </Button>
</FlexContainer>
</FlexContainer>
</div>
@@ -645,6 +690,22 @@ limitations under the License.
span {
font-weight: bold;
}
+ span.separator {
+ border: 1px solid grey;
+ opacity: 0.5;
+ display: flex;
+ flex-direction: column;
+ margin: 0 5px;
+ }
+ span.submit-bpr-input {
+ font-size: 14px;
+ cursor: pointer;
+ margin: 0 5px;
+ }
+ span.submit-bpr-input:hover {
+ font-weight: bold;
+ cursor: pointer;
+ }
div.container {
display: flex;
flex-direction: column;
@@ -659,7 +720,7 @@ limitations under the License.
div.container div.line {
display: flex;
flex-direction: row;
- width: 100%;
+ width: fit-content;
height: 24px;
}
div.container div.line div {
diff --git a/src/svelte/src/components/DataDisplays/Header/DisplayHeader.svelte
b/src/svelte/src/components/DataDisplays/Header/DisplayHeader.svelte
index ce26a4b..e51495f 100644
--- a/src/svelte/src/components/DataDisplays/Header/DisplayHeader.svelte
+++ b/src/svelte/src/components/DataDisplays/Header/DisplayHeader.svelte
@@ -18,7 +18,6 @@ limitations under the License.
import {
addressRadix,
displayRadix,
- editMode,
seekOffset,
seekOffsetInput,
selectionDataStore,
@@ -26,9 +25,9 @@ limitations under the License.
selectionSize,
bytesPerRow,
viewport,
+ visableViewports
} from '../../../stores'
import {
- EditByteModes,
ADDRESS_RADIX_OPTIONS,
type RadixValues,
type BytesPerRow,
@@ -37,21 +36,12 @@ limitations under the License.
import { UIThemeCSSClass } from '../../../utilities/colorScheme'
import { createEventDispatcher } from 'svelte'
import { OffsetSearchType } from '../../Header/fieldsets/SearchReplace'
-
- type ViewportDivSpread = '24px' | '28px' | '68px'
+ import { byteDivWidthFromRadix } from '../../../utilities/display'
const eventDispatcher = createEventDispatcher()
- const bitNumText = '01234567'
- const physicalOffsetSpreads = {
- 16: '24px',
- 10: '28px',
- 8: '28px',
- 2: '68px',
- }
-
- let phyiscalOffsetSpread: ViewportDivSpread
+ let bitIndexStr = '01234567'
let selectionOffsetText: string
- let offsetLine = []
+ let offsetLine: string[] = []
$: {
offsetLine = generate_offset_headers(
@@ -74,20 +64,17 @@ limitations under the License.
displayRadix: RadixValues,
bytesPerRow: BytesPerRow
) {
- let ret = []
+ let ret: string[] = []
if (displayRadix != RADIX_OPTIONS.Binary) {
for (let i = 0; i < bytesPerRow; i++) {
ret.push(i.toString(addressRadix).padStart(2, '0'))
}
} else {
- for (let i = 0; i < 8; i++) {
- ret.push(i.toString(10))
+ for (let i = 0; i < bytesPerRow; i++) {
+ ret.push(i.toString(addressRadix))
}
}
- phyiscalOffsetSpread = physicalOffsetSpreads[
- displayRadix
- ] as ViewportDivSpread
return ret
}
@@ -120,92 +107,102 @@ limitations under the License.
}
$addressRadix = newAddrRadix
}
-
- function clearDataDisplays() {
- eventDispatcher('clearDataDisplays')
- }
</script>
-<div class={$UIThemeCSSClass + ' hd'}>Address</div>
-<div class={$UIThemeCSSClass + ' hd'}>Physical</div>
-<div class={$UIThemeCSSClass + ' hd'}>Logical</div>
-<div class={$UIThemeCSSClass + ' hd'}>Edit</div>
-<div class={$UIThemeCSSClass + ' measure'} style="align-items: center;">
- <select
- class={$UIThemeCSSClass + ' address_type'}
- id="address_numbering"
- on:change={updateAddressValue}
- >
- {#each ADDRESS_RADIX_OPTIONS as { name, value }}
- <option {value}>{name}</option>
- {/each}
- </select>
-</div>
-
-<div class={$UIThemeCSSClass + ' measure physical-viewport-header'}>
- {#if $displayRadix === RADIX_OPTIONS.Binary}
- {#each offsetLine as offset}
- <div class="phyiscal-addr-seg binary" style:width={phyiscalOffsetSpread}>
- <div>{offset}</div>
- <div>{bitNumText}</div>
- </div>
- {/each}
- {:else}
- {#each offsetLine as offset}
- <div class="physical-addr-seg" style:width={phyiscalOffsetSpread}>
- {offset}
- </div>
- {/each}
- {/if}
-</div>
-
-<div class={$UIThemeCSSClass + ' measure logical-viewport-header'}>
- {#each offsetLine as offset}
- <div class="logical-addr-seg">{offset}</div>
- {/each}
-</div>
-
-<div class={$UIThemeCSSClass + ' measure selection'}>
- {#if $selectionDataStore.active && $editMode !== EditByteModes.Single}
- <!-- svelte-ignore a11y-no-static-element-interactions -->
- <div
- class="clear-selection"
- title="Clear selection data"
- on:click={clearDataDisplays}
- on:keypress={clearDataDisplays}
+<div class="headers">
+ <div class="hdr address-header" style:min-width=110px>
+ <div class={$UIThemeCSSClass + ' hd'}>Address</div>
+ <select
+ class={$UIThemeCSSClass + ' address_type'}
+ id="address_numbering"
+ on:change={updateAddressValue}
>
- ✖
- </div>
- <div>
- {selectionOffsetText}
+ {#each ADDRESS_RADIX_OPTIONS as { name, value }}
+ <option {value}>{name}</option>
+ {/each}
+ </select>
+ </div>
+ {#if $visableViewports === 'physical' || $visableViewports === 'all'}
+ <div class="hdr physical-header" >
+ <div class={$UIThemeCSSClass + ' hd'}>Physical</div>
+ <div class={$UIThemeCSSClass + ' measure physical-viewport-header'}>
+ {#if $displayRadix === RADIX_OPTIONS.Binary}
+ {#each offsetLine as offset}
+ <div class="physical-addr-seg binary"
style:min-width={byteDivWidthFromRadix($displayRadix)}>
+ <div>{offset}</div>
+ <div>{bitIndexStr}</div>
+ </div>
+ {/each}
+ {:else}
+ {#each offsetLine as offset}
+ <div class="physical-addr-seg"
style:min-width={byteDivWidthFromRadix($displayRadix)}>
+ {offset}
+ </div>
+ {/each}
+ {/if}
</div>
- {:else}
- <div>
- <sub
- ><i
- >To edit multiple bytes, highlight (by clicking and dragging) a
- selection of bytes</i
- ></sub
- >
+ </div>
+ {/if}
+ {#if $visableViewports === 'logical' || $visableViewports === 'all'}
+ <div class="hdr logical-header" >
+ <div class={$UIThemeCSSClass + ' hd'}>Logical</div>
+ <div
+ class={$UIThemeCSSClass + ' measure logical logical-viewport-header'}
+ style:align-items={$displayRadix === RADIX_OPTIONS.Binary ? 'flex-end' :
'normal'}
+ >
+ {#each offsetLine as offset}
+ <div
+ class="logical-addr-seg"
+
style:min-width={byteDivWidthFromRadix(RADIX_OPTIONS.Hexadecimal)}>{offset}</div>
+ {/each}
</div>
+ </div>
{/if}
</div>
<style lang="scss">
- div.physical-addr-seg,
- div.logical-addr-seg {
+ div.hdr {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ }
+ div.hdr .measure {
+ flex-direction: row;
+ }
+ div.headers {
+ display: flex;
+ flex-direction: row;
+ }
+ div.logical-addr-seg,
+ div.physical-addr-seg {
writing-mode: vertical-lr;
text-orientation: upright;
cursor: default;
+ border-width: 0 2px 0 2px;
+ border-style: solid;
+ border-color: transparent;
}
div.logical-addr-seg {
- width: 24px;
+ width: 20px;
}
- div.div.physical-addr-seg.binary {
+ div.physical-addr-seg.binary {
writing-mode: horizontal-tb;
text-orientation: sideways;
}
div.physical-viewport-header {
- padding-left: 4px;
+ padding-left: 2px;
+ }
+ div.physical-viewport-header ,
+ div.logical-viewport-header {
+ display: flex;
+ }
+ div.physical-header,
+ div.logical-header,
+ div.address-header {
+ background: #2f3e4f;
+ }
+ div.logical-header,
+ div.physical-header {
+ border: 1px solid transparent;
}
</style>
diff --git a/src/svelte/src/components/Editors/DataEditor.svelte
b/src/svelte/src/components/Editors/DataEditor.svelte
index f8d51b1..b80784f 100644
--- a/src/svelte/src/components/Editors/DataEditor.svelte
+++ b/src/svelte/src/components/Editors/DataEditor.svelte
@@ -20,8 +20,11 @@ limitations under the License.
editMode,
selectionDataStore,
regularSizedFile,
+ viewport,
+ selectionSize,
+ addressRadix,
} from '../../stores'
- import { EditByteModes } from '../../stores/configuration'
+ import { EditByteModes, type RadixValues } from '../../stores/configuration'
import { UIThemeCSSClass } from '../../utilities/colorScheme'
import { createEventDispatcher } from 'svelte'
import ContentControls from
'../DataDisplays/Fieldsets/ContentControls.svelte'
@@ -29,6 +32,21 @@ limitations under the License.
import DataView from '../DataDisplays/Fieldsets/DataView.svelte'
const eventDispatcher = createEventDispatcher()
+ let selectionOffsetText: string
+ $: selectionOffsetText = setSelectionOffsetInfo(
+ 'Selection',
+ $viewport.fileOffset + $selectionDataStore.startOffset,
+ $viewport.fileOffset + $selectionDataStore.endOffset,
+ $selectionSize,
+ $addressRadix
+ )
+
+ let displayTextEditorArea: boolean
+ $: displayTextEditorArea = $editMode === EditByteModes.Multiple &&
($selectionDataStore.active || !$regularSizedFile)
+
+ function clearDataDisplays() {
+ eventDispatcher('clearDataDisplays')
+ }
function handleEditorEvent(event: Event) {
switch (event.type) {
case 'input':
@@ -49,26 +67,82 @@ limitations under the License.
}
eventDispatcher('handleEditorEvent', event)
}
+ export function setSelectionOffsetInfo(
+ from: string,
+ start: number,
+ end: number,
+ size: number,
+ radix: RadixValues
+ ): string {
+ return `${from} [${start.toString(radix)} - ${end.toString(
+ radix
+ )}] Size: ${size.toString(radix)} `
+ }
</script>
-<div class="editView" id="edit_view">
- {#if $editMode === EditByteModes.Multiple && ($selectionDataStore.active ||
!$regularSizedFile)}
- <textarea
- class={$UIThemeCSSClass}
- id="selectedContent"
- contenteditable="true"
- on:keyup|nonpassive={handleEditorEvent}
- on:click={handleEditorEvent}
- on:input={handleEditorEvent}
- bind:value={$editorSelection}
- />
+<div
+ class="editView"
+ id="edit_view"
+ style:justify-content={displayTextEditorArea ? 'flex-end' : 'flex-start'}
+>
+ <div class="hdr editor-header" >
+ <div class={$UIThemeCSSClass + ' hd'}>Editor</div>
+ <div class={$UIThemeCSSClass + " measure selection-content"}>
+ {#if $selectionDataStore.active && $editMode !== EditByteModes.Single}
+ <!-- svelte-ignore a11y-no-static-element-interactions -->
+ <div
+ class="clear-selection"
+ title="Clear selection data"
+ on:click={clearDataDisplays}
+ on:keypress={clearDataDisplays}
+ >
+ ✖
+ </div>
+ <div>
+ {selectionOffsetText}
+ </div>
+ {:else}
+ <sub
+ ><i
+ >To edit multiple bytes, highlight (by clicking and dragging) a
+ selection of bytes</i
+ ></sub
+ >
+ {/if}
+ </div>
+ </div>
+ {#if displayTextEditorArea}
+ <textarea
+ class={$UIThemeCSSClass}
+ id="selectedContent"
+ contenteditable="true"
+ on:keyup|nonpassive={handleEditorEvent}
+ on:click={handleEditorEvent}
+ on:input={handleEditorEvent}
+ bind:value={$editorSelection}
+ />
+
+ <FlexContainer>
+ <ContentControls on:applyChanges />
+ </FlexContainer>
+ {:else}
+ <FlexContainer>
+ <DataView on:applyChanges />
+ </FlexContainer>
+ {/if}
- <FlexContainer>
- <ContentControls on:applyChanges />
- </FlexContainer>
- {:else}
- <FlexContainer>
- <DataView on:applyChanges />
- </FlexContainer>
- {/if}
</div>
+
+<style lang="scss">
+ div.hdr {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ background: #2f3e4f;
+ border: 0;
+ }
+ .selection-content {
+ display: flex;
+ width: 100%;
+ }
+</style>
diff --git a/src/svelte/src/components/Header/fieldsets/Settings.svelte
b/src/svelte/src/components/Header/fieldsets/Settings.svelte
index 5a0c841..214b02a 100644
--- a/src/svelte/src/components/Header/fieldsets/Settings.svelte
+++ b/src/svelte/src/components/Header/fieldsets/Settings.svelte
@@ -24,12 +24,11 @@ limitations under the License.
displayRadix,
editorEncoding,
editorActionsAllowed,
- bytesPerRow,
} from '../../../stores'
import FlexContainer from '../../layouts/FlexContainer.svelte'
import { UIThemeCSSClass } from '../../../utilities/colorScheme'
+ import ViewportVisibilityIcon from
'../../Icons/ViewportVisibilityIcon.svelte'
- $: $bytesPerRow = $displayRadix === RADIX_OPTIONS.Binary ? 8 : 16
</script>
<fieldset>
@@ -76,6 +75,7 @@ limitations under the License.
</FlexContainer>
<hr />
+ <ViewportVisibilityIcon dimension={20}/>
</FlexContainer>
</fieldset>
diff --git a/src/svelte/src/components/Icons/ViewportVisibilityIcon.svelte
b/src/svelte/src/components/Icons/ViewportVisibilityIcon.svelte
new file mode 100644
index 0000000..363e24a
--- /dev/null
+++ b/src/svelte/src/components/Icons/ViewportVisibilityIcon.svelte
@@ -0,0 +1,214 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<script lang='ts'>
+ import Tooltip from "../layouts/Tooltip.svelte"
+ import { bytesPerRow, dataDislayLineAmount, visableViewports } from
"../../stores"
+ import { BYTES_PER_ROW_MAX_LINE_NUM, type BytesPerRow } from
"../../stores/configuration"
+
+ export let dimension: number = 20
+ const defaultDimension = 20
+ const minDimension = 15
+ const maxDimension = 30
+
+ let width = valid_dimensions()
+ let height = valid_dimensions()
+ let minWidth = pixel_string(minDimension)
+ let minHeight = pixel_string(minDimension)
+ let maxWidth = pixel_string(maxDimension)
+ let maxHeight = pixel_string(maxDimension)
+
+ let selectionsDisplay = {
+ viewports: false,
+ bytesPerRow: false
+ }
+
+ function valid_dimensions(): string {
+ return (dimension > maxDimension || dimension < minDimension)
+ ? pixel_string(defaultDimension)
+ : pixel_string(dimension)
+ }
+ function pixel_string(value: number): string {
+ return value.toString() + 'px'
+ }
+ function set_bytes_per_row(bytesPerRowSelection: BytesPerRow) {
+ if($dataDislayLineAmount >
BYTES_PER_ROW_MAX_LINE_NUM[bytesPerRowSelection])
+ $dataDislayLineAmount =
BYTES_PER_ROW_MAX_LINE_NUM[bytesPerRowSelection]
+
+ $bytesPerRow = bytesPerRowSelection
+ }
+</script>
+
+<span class="icon-container">
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
+ <Tooltip alwaysEnabled={true} description="Viewports visible:
{$visableViewports}">
+ <span class="setting-icon"
+ style:width
+ style:height
+ style:min-width={ minWidth }
+ style:min-height={ minHeight }
+ style:max-width={ maxWidth }
+ style:max-height={ maxHeight }
+ on:click={() => { selectionsDisplay.viewports =
selectionsDisplay.viewports ? false : true }}
+ >
+ <span
+ style:background-color={ $visableViewports === 'all' ||
$visableViewports === 'physical' ? 'white' : ''}
+ class="viewport physical"
+ />
+ <span
+ style:background-color={ $visableViewports === 'all' ||
$visableViewports === 'logical' ? 'white' : ''}
+ class="viewport logical"
+ />
+ </span>
+ </Tooltip>
+ {#if selectionsDisplay.viewports}
+ <span
+ class='material-symbols-outlined'
+ style:width=15px
+ style:font-size=20px
+ >chevron_right
+ </span>
+ <span class="selections-container">
+ <Tooltip alwaysEnabled={true} description="physical">
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
+ <span
+ class="setting-icon selection physical"
+ on:click={ () => { $visableViewports = 'physical' }}
+ >
+ <span class="viewport" style:background-color={'white'}></span>
+ <span class="viewport"></span>
+ </span>
+ </Tooltip>
+
+ <Tooltip alwaysEnabled={true} description="logical">
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
+ <span
+ class="setting-icon selection logical"
+ on:click={ () => { $visableViewports = 'logical' }}
+ >
+ <span class="viewport"></span>
+ <span class="viewport" style:background-color={'white'}></span>
+ </span>
+ </Tooltip>
+ <Tooltip alwaysEnabled={true} description="all">
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
+ <span
+ class="setting-icon selection all"
+ on:click={ () => { $visableViewports = 'all' }}
+ >
+ <span class="viewport" style:background-color={'white'}></span>
+ <span class="viewport" style:background-color={'white'}></span>
+ </span>
+ </Tooltip>
+ </span>
+ {/if}
+</span>
+
+<!-- BPR Setting Icon -->
+<span class="icon-container">
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
+ <Tooltip alwaysEnabled={true} description="Bytes per row: {$bytesPerRow}">
+ <span class="setting-icon"
+ style:width
+ style:height
+ style:min-width={ minWidth }
+ style:min-height={ minHeight }
+ style:max-width={ maxWidth }
+ style:max-height={ maxHeight }
+ on:click={() => { selectionsDisplay.bytesPerRow =
selectionsDisplay.bytesPerRow ? false : true }}
+ >
+ <span
+ class="material-symbols-outlined"
+ style:display=flex
+ style:align-content=center
+ style:justify-content=center
+ style:font-size=20px
+ >power_input</span>
+ </span>
+ </Tooltip>
+ {#if selectionsDisplay.bytesPerRow}
+ <span
+ class='material-symbols-outlined'
+ style:width=15px
+ style:font-size=20px
+ >chevron_right
+ </span>
+ <span class="selections-container">
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
+ <span
+ class="setting-icon selection "
+ on:click={ () => { set_bytes_per_row(8) }}
+ >8
+ </span>
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
+ <span
+ class="setting-icon selection "
+ on:click={ () => { set_bytes_per_row(16) }}
+ >16
+ </span>
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
+ <span
+ class="setting-icon selection "
+ on:click={ () => { set_bytes_per_row(24) }}
+ >24
+ </span>
+ </span>
+ {/if}
+</span>
+
+<style lang="scss">
+ .icon-container {
+ margin: 2px 0;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ cursor: pointer;
+ }
+ .setting-icon {
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ overflow: hidden;
+ border: 1px solid white;
+ border-radius: 4px;
+ padding: 2px;
+ }
+ .selection {
+ width: 15px;
+ height: 15px;
+ cursor: pointer;
+ }
+ .viewport {
+ border: 1px solid white;
+ border-radius: 2px;
+ margin: 1px;
+ width: 50%;
+ }
+ .selections-container{
+ display: flex;
+ flex-direction: row;
+ justify-content: space-evenly;
+ min-width: 85px;
+ }
+ .icon {
+ display: flex;
+ height: 100%;
+ font-size: x-large;
+ align-items: center;
+ justify-content: center;
+ }
+</style>
diff --git a/src/svelte/src/components/Inputs/Buttons/Button.svelte
b/src/svelte/src/components/Inputs/Buttons/Button.svelte
index bfa5929..644df14 100644
--- a/src/svelte/src/components/Inputs/Buttons/Button.svelte
+++ b/src/svelte/src/components/Inputs/Buttons/Button.svelte
@@ -24,6 +24,7 @@ limitations under the License.
export let fn: (event?: Event) => void
export let disabledBy = false
export let width = ''
+ export let fixedWidth = ''
onMount(() => {
collapseContent = shouldCollapseContent()
@@ -51,6 +52,7 @@ limitations under the License.
class={$UIThemeCSSClass + ' collapsed'}
disabled={disabledBy}
on:click={!disabledBy ? fn : () => {}}
+ style:width={fixedWidth}
>
<FlexContainer
--dir="row"
@@ -68,7 +70,7 @@ limitations under the License.
class={$UIThemeCSSClass}
disabled={disabledBy}
on:click={!disabledBy ? fn : () => {}}
- style:width
+ style:width = { fixedWidth.length > 0 ? fixedWidth : width }
>
<FlexContainer
--dir="row"
diff --git a/src/svelte/src/components/Main.svelte
b/src/svelte/src/components/Main.svelte
index c0291de..ea80ee0 100644
--- a/src/svelte/src/components/Main.svelte
+++ b/src/svelte/src/components/Main.svelte
@@ -21,16 +21,32 @@ limitations under the License.
</script>
<main class="dataEditor">
- <DisplayHeader on:clearDataDisplays />
- <DataViewports
- on:clearDataDisplays
- on:scrolledToTop
- on:scrolledToEnd
- on:applyChanges
- on:handleEditorEvent
- on:scrollBoundary
- on:traverse-file
- on:seek
- />
- <DataEditor on:applyChanges on:handleEditorEvent />
+ <div class="data-viewports">
+ <DisplayHeader on:clearDataDisplays/>
+ <DataViewports
+ on:clearDataDisplays
+ on:scrolledToTop
+ on:scrolledToEnd
+ on:applyChanges
+ on:handleEditorEvent
+ on:scrollBoundary
+ on:traverse-file
+ on:seek
+ />
+ </div>
+ <div class="data-editor">
+ <DataEditor on:applyChanges on:handleEditorEvent on:clearDataDisplays/>
+ </div>
</main>
+
+<style lang="scss">
+ .data-viewports {
+ display: flex;
+ flex-direction: column;
+ }
+ .data-editor {
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ }
+</style>
diff --git a/src/svelte/src/components/dataEditor.svelte
b/src/svelte/src/components/dataEditor.svelte
index c4984bf..2387bbd 100644
--- a/src/svelte/src/components/dataEditor.svelte
+++ b/src/svelte/src/components/dataEditor.svelte
@@ -29,13 +29,13 @@ limitations under the License.
requestable,
selectionDataStore,
selectionSize,
- viewportNumLinesDisplayed,
dataFeedLineTop,
SelectionData_t,
dataFeedAwaitRefresh,
viewport,
searchQuery,
regularSizedFile,
+ dataDislayLineAmount,
} from '../stores'
import {
CSSThemeClass,
@@ -48,8 +48,8 @@ limitations under the License.
import Main from './Main.svelte'
import {
EditByteModes,
- VIEWPORT_SCROLL_INCREMENT,
type BytesPerRow,
+ VIEWPORT_SCROLL_INCREMENT,
} from '../stores/configuration'
import ServerMetrics from './ServerMetrics/ServerMetrics.svelte'
import {
@@ -87,12 +87,15 @@ limitations under the License.
bytesPerRow: BytesPerRow,
viewportStartOffset: number = $viewport.fileOffset
): number {
- const nearestBPRdivisibleOffset = byte_count_divisible_offset(
- offset - viewportStartOffset,
+ const nearestBPRdivisibleTargetFileOffset = byte_count_divisible_offset(
+ offset,
bytesPerRow
)
- const offsetLineNumInViewport = nearestBPRdivisibleOffset / bytesPerRow
- return offsetLineNumInViewport
+ const nearestBPRdivisibleViewportFileOffset = byte_count_divisible_offset(
+ viewportStartOffset,
+ bytesPerRow
+ )
+ return (nearestBPRdivisibleTargetFileOffset -
nearestBPRdivisibleViewportFileOffset) / bytesPerRow
}
function fetchable_content(offset: number): boolean {
@@ -127,8 +130,7 @@ limitations under the License.
$dataFeedAwaitRefresh = true
- offsetArg = byte_count_divisible_offset(offsetArg, $bytesPerRow)
- const fetchOffset = Math.max(0, offsetArg - VIEWPORT_SCROLL_INCREMENT)
+ const fetchOffset = Math.max(0, byte_count_divisible_offset(offsetArg -
(VIEWPORT_SCROLL_INCREMENT-$bytesPerRow), $bytesPerRow))
$dataFeedLineTop = offset_to_viewport_line_number(
offsetArg,
@@ -141,7 +143,7 @@ limitations under the License.
data: {
scrollOffset: fetchOffset,
bytesPerRow: $bytesPerRow,
- numLinesDisplayed: $viewportNumLinesDisplayed,
+ numLinesDisplayed: $dataDislayLineAmount,
},
})
clearDataDisplays()
@@ -321,6 +323,7 @@ limitations under the License.
<!-- svelte-ignore css-unused-selector -->
<style lang="scss">
+
div.test {
display: flex;
flex-wrap: wrap;
diff --git a/src/svelte/src/components/globalStyles.css
b/src/svelte/src/components/globalStyles.css
index 33f6d4c..0a52458 100644
--- a/src/svelte/src/components/globalStyles.css
+++ b/src/svelte/src/components/globalStyles.css
@@ -278,15 +278,10 @@ div.hide-scrollbar::-webkit-scrollbar {
/* Global Style Classes */
.dataEditor {
- display: grid;
- grid-template-columns: 110px max-content max-content auto;
- grid-template-rows: max-content auto;
- /*noinspection CssUnresolvedCustomProperty*/
+ display: flex;
font-family: 'Red Hat Mono';
}
-/* display of binary encoded data takes more space in the physical view */
.dataEditor.binary {
- /* I think this should be 16em instead of 10em for 16 characters, but that
didn't work */
grid-template-columns: max-content max-content 10em auto;
}
.dataEditor div {
@@ -316,8 +311,6 @@ div.hide-scrollbar::-webkit-scrollbar {
display: flex;
font-family: 'Red Hat Mono';
height: 25pt;
- border-width: 0 0 2px 0;
- border-style: solid;
}
.dataEditor div.measure.dark {
display: flex;
@@ -341,7 +334,8 @@ div.hide-scrollbar::-webkit-scrollbar {
.dataEditor div.measure span {
align-self: flex-end;
}
-.dataEditor div.measure div {
+.dataEditor div.measure div,
+.dataEditor div.measure sub {
display: flex;
flex-direction: column;
justify-content: center;
@@ -405,18 +399,15 @@ div.hide-scrollbar::-webkit-scrollbar {
color: #02060b;
}
.dataEditor div.editView {
- display: grid;
- grid-template-columns: 1fr;
- grid-template-rows: 75%;
- grid-row-start: 3;
- grid-row-end: 5;
- gap: 10pt;
- overflow-x: hidden;
- word-break: break-all;
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-end;
+ height: 100%;
margin-left: 4px;
}
.dataEditor div.editView textarea {
width: auto;
+ height: 100%;
}
.dataEditor textarea.selectedContent {
background: #2c2c2c;
@@ -428,6 +419,9 @@ div.hide-scrollbar::-webkit-scrollbar {
float: right;
max-width: 110px;
}
+div.viewport-hdr-content {
+ height: 35px;
+}
.tooltip {
position: relative;
diff --git a/src/svelte/src/stores/configuration.ts
b/src/svelte/src/stores/configuration.ts
index 37e3595..21035de 100644
--- a/src/svelte/src/stores/configuration.ts
+++ b/src/svelte/src/stores/configuration.ts
@@ -19,7 +19,7 @@ export type Radixes = 'Hexadecimal' | 'Decimal' | 'Octal' |
'Binary'
export type RadixValues = 16 | 10 | 8 | 2
-export type BytesPerRow = 16 | 8
+export type BytesPerRow = 16 | 8 | 24
export enum EditByteModes {
Single = 'single',
@@ -108,11 +108,13 @@ export const UNPRINTABLE_CHAR_STAND_IN =
String.fromCharCode(9617)
// Number of bytes to for the viewport to populate
export const VIEWPORT_CAPACITY_MAX = 16 * 64 // 1024, Ωedit maximum viewport
size is 1048576 (1024 * 1024)
-
-// Offset shift amount on viewport data fetch
export const VIEWPORT_SCROLL_INCREMENT = VIEWPORT_CAPACITY_MAX / 2
-// Number of bytes to display in the viewport
-export const NUM_LINES_DISPLAYED = 20
+export const BYTES_PER_ROW_MAX_LINE_NUM: { [k in BytesPerRow]: number } = {
+ 16: Math.floor(VIEWPORT_SCROLL_INCREMENT / 16),
+ 8: Math.floor(VIEWPORT_SCROLL_INCREMENT / 8),
+ 24: Math.floor(VIEWPORT_SCROLL_INCREMENT / 24),
+}
+// Number of bytes to display in the viewport
export const DATA_PROFILE_MAX_LENGTH = 10_000_000
diff --git a/src/svelte/src/stores/index.ts b/src/svelte/src/stores/index.ts
index 5c7eaee..6c1cca9 100644
--- a/src/svelte/src/stores/index.ts
+++ b/src/svelte/src/stores/index.ts
@@ -43,6 +43,7 @@ import {
type RadixValues,
type BytesPerRow,
EditActionRestrictions,
+ VIEWPORT_CAPACITY_MAX,
} from './configuration'
export class SelectionData_t {
@@ -117,7 +118,6 @@ export const rerenderActionElements = writable(false)
// Viewport properties
export const viewport = new ViewportDataStore_t()
-export const viewportNumLinesDisplayed = writable(20)
export const bytesPerRow = writable(16 as BytesPerRow)
export const editingByte = writable(false)
@@ -147,6 +147,10 @@ export const sizeHumanReadable = writable(false)
// tracks the start and end offsets of the current selection
export const selectionDataStore = new SelectionData()
+export const dataDislayLineAmount = writable(20)
+
+export type VisibleViewports = 'physical' | 'logical' | 'all'
+export const visableViewports = writable('all' as VisibleViewports)
// Can the user's selection derive both edit modes?
export const regularSizedFile = derived(fileMetrics, ($fileMetrics) => {
return $fileMetrics.computedSize >= 2
@@ -288,7 +292,7 @@ export const editedByteIsOriginalByte = derived(
([$editorSelection, $selectedByte, $focusedViewportId]) => {
return $focusedViewportId === 'logical'
? $editorSelection === $selectedByte.text
- : $editorSelection.toLowerCase() === $selectedByte.text.toLowerCase()
+ : $editorSelection.toLowerCase() === $selectedByte.text!.toLowerCase()
}
)