Picture grid

Pictures grouped by day, each at its own shape, laid out in rows that fill the width. It is for looking at pictures, not for reading names.

Part of a window with a picture grid in two groups, Today and Tuesday, with the second picture selected.

Use it where the picture is the thing: a camera roll, a folder of screenshots. Where people look for a thing by its name, use a row list, in which a picture is a small kind mark. Where each picture has a title and a line under it, as an album does, use CoverGrid, which sets one square shape in columns.

Anatomy

A group under a heading in two rows of pictures at different shapes. Numbered callouts name the heading, a picture, the selection and the gap between rows.
A group of eight pictures under its heading.
  1. HeadingA section heading for each group, from the picture's group.
  2. PictureThe picture at its own shape, cropped only at its corners. It is shown whole, never squared.
  3. SelectionA wash of the main ink at 22 % over the picture, which shows on a photograph. The picture keeps its size. The keyboard's place is a separate ring, so the two read apart (see States).
  4. Gap6 pixels between pictures, across and down. Rows are filled edge to edge, so no row has a ragged end.

A row is filled with pictures until it is no taller than rowHeight, then all its pictures are scaled to share one height. A picture never stands alone on a row: a last picture alone joins the row above. A short last row keeps the usual height rather than growing.

States

Every state is a wash of the main ink on the picture. The picture never changes its shape.

The same group four times, numbered: at rest, under the pointer, selected, and selected under the pointer.
  1. RestThe picture as it is.
  2. Pointer over itThe hover wash, 5 %.
  3. SelectedThe wash at 22 %.
  4. Selected, pointer over itThe same 22 %: there is no step over the selection, as there is in a list.

While the button is down the wash is 22 % too. With the keyboard, the picture the keys act on, the cursor, has the focus ring, 4 pixels outside it. States gives the washes and the ring for every part.

Sizes

A row of three pictures 150 pixels high with a 6-pixel gap measured between two of them and the focus ring on the second.
One row at a row height of 150.
PartValue
Row height200 by default (rowHeight), the most a row is; rows come out a little lower to fill the width
Gap6 pixels (gap)
Heading50 pixels high, over each group
Picture corner8 pixels
Focus ring2 pixels wide, 4 pixels outside the picture (the ring and its gap), corner 12
Room for the ring6 pixels around the grid, kept inside its clip (ringRoom)
Default size900 by 600

Keys and pointer

The grid is one stop for Tab, as a row list is.

Do thisTo
← →Select the picture before or after
↑ ↓Select the picture in the row above or below whose middle is nearest
Shift with the arrowsSelect from where you started to here
Home EndGo to the first or the last picture
Ctrl ASelect every picture
EnterOpen
MenuThe picture's menu
Click, Ctrl-click, Shift-clickSelect one, add or remove one, select a run
Double-clickOpen
Right-clickThe picture's menu; the picture is selected first if it was not

Unlike a list, the grid has no keys for adding without selecting, and no type-to-jump.

Accessibility

Writing

The grid shows no words except the group headings, so the headings do the work: "Today", "Tuesday 22 October". The name is for screen readers, and is the file's own name.

Do and don't

Two rows of pictures at their own shapes, both rows reaching both edges.
DoLet the grid fill each row to both edges. Each picture keeps its shape; the row takes its height from them.
A row of three pictures and a fourth picture alone on the row below, with empty space beside it.
Don'tLeave one picture alone on a row. A lone picture looks like a different kind of thing, so the grid moves it up into the row above.

Code

import Tacit.Kit

PictureGrid {
    id: grid
    width: 900; height: 600
    rowHeight: 200
    pictures: roll.map(p => ({
        source: p.url, ratio: p.width / p.height, group: p.day, name: p.name }))
    onActivated: i => open(roll[i])
    onContextRequested: (i, at) => menu.openAt(grid, at.x, at.y)
}
Property or signalWhat it does
picturesThe pictures in the order shown: source, ratio (width over height; 1.5 if left out), group, name
rowHeight, gapThe usual row height (200) and the gap (6)
labelWhat a screen reader calls the grid
cursor, selection, selectionCountThe picture the keys act on, the selected pictures (an object by index), and how many
selected(), setSelection(indexes)The selected indexes as an array; set them
isSelected(i), clickAt(i, modifiers)Whether a picture is selected; select as a click would
activated(index), contextRequested(index, at)Open, and ask for the picture's menu

Experimental, in Tacit.Kit 0.1.