grid scroll bars

This commit is contained in:
Jan Prochazka
2021-02-25 10:25:34 +01:00
parent ef910f43a6
commit 2ffd729465
8 changed files with 139 additions and 14 deletions

View File

@@ -1,15 +1,36 @@
<script lang="ts"> <script lang="ts">
import FontIcon from '../icons/FontIcon.svelte';
import DropDownButton from '../widgets/DropDownButton.svelte';
import ColumnLabel from './ColumnLabel.svelte'; import ColumnLabel from './ColumnLabel.svelte';
export let column;
export let conid = undefined; export let conid = undefined;
export let database = undefined; export let database = undefined;
export let column; export let grouping = undefined;
export let order = undefined;
</script> </script>
<div class="header"> <div class="header">
<div class="label"> <div class="label">
{#if grouping}
<span class="grouping">
{grouping == 'COUNT DISTINCT' ? 'distinct' : grouping.toLowerCase()}
</span>
{/if}
<ColumnLabel {...column} /> <ColumnLabel {...column} />
</div> </div>
{#if order == 'ASC'}
<span class="icon">
<FontIcon icon="img sort-asc" />
</span>
{/if}
{#if order == 'DESC'}
<span class="icon">
<FontIcon icon="img sort-desc" />
</span>
{/if}
<DropDownButton />
</div> </div>
<style> <style>

View File

@@ -79,7 +79,7 @@
{value.toString()} {value.toString()}
{/if} {/if}
{#if hintFieldsAllowed && hintFieldsAllowed.includes(col.uniqueName)} {#if hintFieldsAllowed && hintFieldsAllowed.includes(col.uniqueName) && rowData}
<span class="hint">{rowData[col.hintColumnName]}</span> <span class="hint">{rowData[col.hintColumnName]}</span>
{/if} {/if}
</td> </td>

View File

@@ -4,6 +4,8 @@
import ColumnHeaderControl from './ColumnHeaderControl.svelte'; import ColumnHeaderControl from './ColumnHeaderControl.svelte';
import DataGridRow from './DataGridRow.svelte'; import DataGridRow from './DataGridRow.svelte';
import { countColumnSizes, countVisibleRealColumns } from './gridutil'; import { countColumnSizes, countVisibleRealColumns } from './gridutil';
import HorizontalScrollBar from './HorizontalScrollBar.svelte';
import VerticalScrollBar from './VerticalScrollBar.svelte';
export let loadNextData = undefined; export let loadNextData = undefined;
export let grider = undefined; export let grider = undefined;
@@ -17,7 +19,7 @@
let firstVisibleRowScrollIndex = 0; let firstVisibleRowScrollIndex = 0;
let firstVisibleColumnScrollIndex = 0; let firstVisibleColumnScrollIndex = 0;
// $: firstVisibleRowScrollIndex = 0; // $: firstVisibleRowScrollIndex = 0;
$: visibleRowCountUpperBound = 25; // $: visibleRowCountUpperBound = 25;
// $: console.log('grider', grider); // $: console.log('grider', grider);
$: columns = display.allColumns; $: columns = display.allColumns;
@@ -29,6 +31,9 @@
$: gridScrollAreaHeight = containerHeight - 2 * rowHeight; $: gridScrollAreaHeight = containerHeight - 2 * rowHeight;
$: gridScrollAreaWidth = containerWidth - columnSizes.frozenSize - headerColWidth - 32; $: gridScrollAreaWidth = containerWidth - columnSizes.frozenSize - headerColWidth - 32;
$: visibleRowCountUpperBound = Math.ceil(gridScrollAreaHeight / Math.floor(Math.max(1, rowHeight)));
$: visibleRowCountLowerBound = Math.floor(gridScrollAreaHeight / Math.ceil(Math.max(1, rowHeight)));
$: visibleRealColumns = countVisibleRealColumns( $: visibleRealColumns = countVisibleRealColumns(
columnSizes, columnSizes,
firstVisibleColumnScrollIndex, firstVisibleColumnScrollIndex,
@@ -36,12 +41,17 @@
columns columns
); );
$: console.log('visibleRealColumns', visibleRealColumns); // $: console.log('visibleRealColumns', visibleRealColumns);
$: console.log('visibleRowCountUpperBound', visibleRowCountUpperBound);
$: console.log('rowHeight', rowHeight);
$: console.log('containerHeight', containerHeight);
$: realColumnUniqueNames = _.range(columnSizes.realCount).map( $: realColumnUniqueNames = _.range(columnSizes.realCount).map(
realIndex => (columns[columnSizes.realToModel(realIndex)] || {}).uniqueName realIndex => (columns[columnSizes.realToModel(realIndex)] || {}).uniqueName
); );
$: maxScrollColumn = columnSizes.scrollInView(0, columns.length - 1 - columnSizes.frozenCount, gridScrollAreaWidth);
$: { $: {
if (loadNextData && firstVisibleRowScrollIndex + visibleRowCountUpperBound >= grider.rowCount) { if (loadNextData && firstVisibleRowScrollIndex + visibleRowCountUpperBound >= grider.rowCount) {
loadNextData(); loadNextData();
@@ -54,7 +64,7 @@
<table class="table"> <table class="table">
<thead> <thead>
<tr> <tr>
<td class="header-cell" data-row="header" data-col="header" /> <td class="header-cell" data-row="header" data-col="header" bind:clientHeight={rowHeight} />
{#each visibleRealColumns as col (col.uniqueName)} {#each visibleRealColumns as col (col.uniqueName)}
<td <td
class="header-cell" class="header-cell"
@@ -69,10 +79,22 @@
</thead> </thead>
<tbody> <tbody>
{#each _.range(firstVisibleRowScrollIndex, firstVisibleRowScrollIndex + visibleRowCountUpperBound) as rowIndex (rowIndex)} {#each _.range(firstVisibleRowScrollIndex, firstVisibleRowScrollIndex + visibleRowCountUpperBound) as rowIndex (rowIndex)}
<DataGridRow {rowIndex} {grider} {visibleRealColumns} /> <DataGridRow {rowIndex} {grider} {visibleRealColumns} {rowHeight} />
{/each} {/each}
</tbody> </tbody>
</table> </table>
<HorizontalScrollBar
minimum={0}
maximum={maxScrollColumn}
viewportRatio={gridScrollAreaWidth / columnSizes.getVisibleScrollSizeSum()}
on:scroll={e => (firstVisibleColumnScrollIndex = e.detail)}
/>
<VerticalScrollBar
minimum={0}
maximum={grider.rowCount - visibleRowCountUpperBound + 2}
viewportRatio={visibleRowCountUpperBound / grider.rowCount}
on:scroll={e => (firstVisibleRowScrollIndex = e.detail)}
/>
</div> </div>
<style> <style>
@@ -98,7 +120,7 @@
text-align: left; text-align: left;
padding: 0; padding: 0;
margin: 0; margin: 0;
background-color: var(--theme-bg-2); background-color: var(--theme-bg-1);
overflow: hidden; overflow: hidden;
} }
.filter-cell { .filter-cell {

View File

@@ -20,7 +20,7 @@
.map(col => col.uniqueName); .map(col => col.uniqueName);
</script> </script>
<tr> <tr style={`height: ${rowHeight}px`}>
<RowHeaderCell {rowIndex} /> <RowHeaderCell {rowIndex} />
{#each visibleRealColumns as col (col.uniqueName)} {#each visibleRealColumns as col (col.uniqueName)}
<DataGridCell {rowIndex} {rowData} {col} {hintFieldsAllowed} /> <DataGridCell {rowIndex} {rowData} {col} {hintFieldsAllowed} />

View File

@@ -0,0 +1,35 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte';
export let viewportRatio = 0.5;
export let minimum;
export let maximum;
const dispatch = createEventDispatcher();
let width;
let node;
$: contentSize = Math.round(width / viewportRatio);
function handleScroll() {
const position = node.scrollLeft;
const ratio = position / (contentSize - width);
if (ratio < 0) return 0;
const res = ratio * (maximum - minimum + 1) + minimum;
dispatch('scroll', Math.floor(res + 0.3));
}
</script>
<div bind:clientWidth={width} bind:this={node} on:scroll={handleScroll} class="main">
<div style={`width: ${contentSize}px`}>&nbsp;</div>
</div>
<style>
.main {
overflow-x: scroll;
height: 16px;
position: absolute;
bottom: 0;
right: 0;
left: 0;
}
</style>

View File

@@ -0,0 +1,36 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte';
export let viewportRatio = 0.5;
export let minimum;
export let maximum;
const dispatch = createEventDispatcher();
let height;
let node;
$: contentSize = Math.round(height / viewportRatio);
function handleScroll() {
const position = node.scrollTop;
const ratio = position / (contentSize - height);
if (ratio < 0) return 0;
let res = ratio * (maximum - minimum + 1) + minimum;
dispatch('scroll', Math.floor(res + 0.3));
}
</script>
<div bind:clientHeight={height} bind:this={node} on:scroll={handleScroll} class="main">
<div style={`height: ${contentSize}px`}>&nbsp;</div>
</div>
<style>
.main {
overflow-y: scroll;
width: 20px;
position: absolute;
right: 0px;
width: 20px;
bottom: 16px;
top: 0;
}
</style>

View File

@@ -0,0 +1,8 @@
<script>
import FontIcon from '../icons/FontIcon.svelte';
import InlineButton from './InlineButton.svelte';
</script>
<InlineButton square>
<FontIcon icon="icon chevron-down" />
</InlineButton>

View File

@@ -11,9 +11,12 @@
<style> <style>
.outer { .outer {
background: linear-gradient(to bottom, var(--theme-bg-2) 5%, var(--theme-bg-3) 100%); --bg-1: var(--theme-bg-1);
background-color: var(--theme-bg-2); --bg-2: var(--theme-bg-3);
border: 1px solid var(--theme-bg-3);
background: linear-gradient(to bottom, var(--bg-1) 5%, var(--bg-2) 100%);
background-color: var(--bg-1);
border: 1px solid var(--bg-2);
display: inline-block; display: inline-block;
cursor: pointer; cursor: pointer;
vertical-align: middle; vertical-align: middle;
@@ -30,9 +33,9 @@
} }
.outer:hover:not(.disabled) { .outer:hover:not(.disabled) {
border: 1px solid var(--theme-bg-2); border: 1px solid var(--bg-1);
background: linear-gradient(to bottom, var(--theme-bg-3) 5%, var(--theme-bg-2) 100%); background: linear-gradient(to bottom, var(--bg-2) 5%, var(--bg-1) 100%);
background-color: var(--theme-bg-3); background-color: var(--bg-2);
} }
.inner { .inner {