Repository navigation
TableView pt BR
🌐 Esta página em: English · Português · Español · Français · Deutsch
TableView é uma janela para uma grade maior que qualquer tela, nos DOIS eixos, como o TableView
do Flutter: você descreve até onde cada linha e cada coluna alcança, entrega a ele um construtor que
responde a célula numa linha e numa coluna, e diz quantas das primeiras linhas e colunas ficam
fixadas. Ele constrói só as células à vista mais uma margem ao redor, então a planilha inteira do
Excel, 1 048 576 linhas por 16 384 colunas, custa o que uma tela cheia custa. É write-once: o mesmo
C# roda como pintura de GPU no Photon e como DOM no web.
TableView(
rows: new UniformTableSpans(1_048_576 + 1, 28),
columns: new SparseTableSpans(16_384 + 1, 96, new Dictionary<int, double> { [0] = 48, [3] = 180 }),
cellBuilder: (row, column) => Text(row == 0 ? $"{column}" : $"{row}:{column}", TypeRole.Caption),
pinnedRows: 1,
pinnedColumns: 1,
width: SizeValue.Fill,
height: SizeValue.Fill,
label: "Sheet")A tela /table do sample do dashboard é esta grade, com cada célula mostrando o próprio endereço, uma
linha de cabeçalho e uma coluna de números de linha fixadas.
Cada eixo é um TableSpans: quantas linhas (ou colunas) há, até onde elas alcançam no total, e as
duas perguntas que o viewport faz, onde o índice i começa (OffsetOf) e qual índice está num
deslocamento (IndexAt).
-
UniformTableSpans(count, extent): toda linha (ou coluna) alcança a mesma distância. Todo deslocamento é uma multiplicação. -
SparseTableSpans(count, extent, extents): uma extensão padrão, e as poucas que têm a sua própria, como numa planilha em que alguém alargou a coluna D. As exceções ficam ordenadas com uma soma acumulada, então um deslocamento custa uma busca binária sobre elas, por mais longo que seja o eixo. - O seu próprio: derive de
TableSpanse respondaCount,Total,ExtentOf,OffsetOfeIndexAt.
Os deslocamentos são double nos dois alvos: um milhão de linhas de 28 chegam a 29 360 128, além de
onde um float ainda conta ponto a ponto.
A tabela constrói as linhas e colunas que o viewport mostra mais overscan (3 por padrão) além de
cada borda. A janela tem histerese: uma rolagem que mantém o que está visível dentro das células já
construídas não constrói nada, e o viewport move essas células por conta própria. A tabela só
constrói de novo quando as linhas ou colunas visíveis saem delas.
Uma célula tem como chave a sua posição ("row:column"), então uma célula que continua na janela
mantém o elemento, e o estado, quando a janela se move.
O primeiro frame é construído para uma janela comum (1 024 × 768) em vez de para nada, então já mostra células; o viewport então reporta o tamanho real dele e o frame seguinte constrói para esse tamanho.
pinnedRows e pinnedColumns mantêm as primeiras linhas no topo e as primeiras colunas no início
enquanto o resto rola. O viewport desenha quatro faixas, cada uma sob o próprio corte: o canto, que
nunca se move; as linhas fixadas, que se movem para o lado junto com a grade; as colunas fixadas,
que descem junto com ela; e o corpo, que se move nos dois sentidos. Uma célula é desenhada na faixa
da sua primeira linha e da sua primeira coluna.
As marks são desenhadas POR CIMA das células, sobre o intervalo que cada uma cobre, e não recebem
toque nem foco: uma seleção, um contorno, a faixa de uma busca. Cada uma é um TableViewCell feito com
mark: true, e seus rows e columns dizem quantas linhas e colunas ela cobre:
TableViewCell(row: 4, column: 2, Box(new BoxStyle { BorderWidth = 2, BorderColor = theme.FocusRing }),
mark: true, rows: 3, columns: 2)Uma marca que cruza a borda de uma faixa fixada é cortada ali, um pedaço por faixa, então aparece em cada faixa que alcança e se esconde onde passa por baixo de uma.
O viewport É DONO do próprio deslocamento, nos dois alvos: o navegador não rola nada. Isso não é questão de gosto. Um navegador desenha um elemento com no máximo 16 777 214 px de altura, e as linhas do Excel chegam a 29 milhões, então uma grade que o navegador rolasse nunca alcançaria a última linha. A tabela move as células por transform no lugar disso, e desenha as próprias barras de rolagem.
- Uma roda e um trackpad movem os dois eixos. Os deltas precisos de um trackpad movem a grade como os dedos movem; um passo da roda do mouse desliza até onde chega. Shift vira uma roda vertical para o outro eixo.
- As barras de rolagem ficam em faixas nas bordas final e inferior. Um polegar arrasta, e um toque na trilha move uma página em direção ao ponteiro.
- Um dedo que percorre mais que um slop de 12 pontos arrasta a grade, e soltar o dedo enquanto ela se move a lança com inércia. Um toque que nunca percorre distância continua sendo um toque na célula sob ele.
- O que a grade não consegue absorver numa borda passa para o rolador ao redor, então uma página continua rolando quando a grade chega ao fim.
- O teclado: a tabela é ela mesma uma parada do Tab, antes dos controles das suas células. Com o foco, as setas movem um passo, PageUp e PageDown uma página, Home e End até a primeira e a última linha, e com Control ou Command até a primeira e a última coluna também. O Tab visita os controles das células linha a linha.
- Um mouse ou o ponteiro de um trackpad num celular ou num tablet pressiona as células, como num desktop; só um dedo arrasta.
- Com movimento reduzido, cada passo chega de uma vez.
request rola em seu nome, uma vez por versão:
request: new TableScrollRequest(version) { Reveal = new TableRange(1_048_575, 0) }Offset põe a grade num deslocamento; Reveal traz um intervalo à vista, livre das faixas
fixadas. Uma requisição é atendida quando a sua Version é nova, então entregar a mesma a cada
build não faz nada duas vezes. Ela vale até a pessoa mover a grade, então um layout que se
assenta em duas passadas, uma linha que mede a tabela antes e depois dos seus irmãos fixos, ainda a
leva aonde a última passada diz.
onScrolled diz onde a grade está (um TableOffset, na horizontal e na vertical) e
onViewportChanged qual o tamanho da parte em que as células rolam, cada um uma vez por mudança.
Uma tabela É uma janela, então dê uma a ela: um tamanho fixo, ou SizeValue.Fill dentro de algo que
tenha tamanho. Um eixo Fill sem limite, que é o que uma página que rola naquele eixo entrega ao seu
conteúdo, assume a extensão visível do rolador mais próximo ao redor, ou a da janela, e o log de
desenvolvimento avisa isso uma vez, nomeando a extensão que assumiu. O conteúdo dela nunca decide o
tamanho dela, e uma largura própria maior que o espaço que o pai dá é limitada a esse espaço, nos
dois alvos.
O viewport é um grupo nomeado por label, sobre as células que ele mantém. As células que ele não
mantém não estão na árvore de jeito nenhum, em nenhum dos alvos. O Tab alcança os controles das células
que ele mantém, e um controle que recebe o foco fora da janela é rolado até ficar à vista, livre das
faixas fixadas. Uma marca nunca é parada do Tab, e um leitor de tela não a alcança.
TableView é um componente sobre um nó do vocabulário, TableViewport, que posiciona os
TableViewCells que recebe e carrega o modelo de rolagem (ITableScrollModel, implementado por
TableScroll). Um componente que decide a própria janela, como o Spreadsheet
vai fazer, pode compor o nó diretamente com o mesmo modelo: os realizadores alimentam o modelo com a
roda, o ponteiro e o relógio, e desenham o que ele responde.
🏁 Comece aqui
🏗️ Arquitetura
- Visão geral da arquitetura
- Componentes write-once
- Superfície declarativa
- Arquitetura de pacotes
- Componentes
- Estilo
- Localização
- Analytics e GTM
📱 Write-once
- Motor Photon
- Design System
- Capacidades
- Armazenamento
- Formulários
- Editor de código
- Visualização de tabela
- Markdown
- Mermaid
- Renderização de Email
⚙️ Compilação
⚡ Runtime
🔌 Servidor
🎨 Ecossistema
🚀 Desenvolvimento