Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | 1x 1x 1x 1689x 1689x 1689x 1689x 1689x 1687x 1687x 1687x 1687x 1687x 1687x 1x 8x 8x 8x 8x 1687x 1687x 95x 16x 16x 5x 1x 4x 1687x 1689x 1689x 1689x 21x 21x | /**
* The two verbs every file row carries: **add it here**, or **open it in a new
* session**.
*
* One pair of marks for every place a file is offered — a store row, a folder
* row in the Files column, the tray under a portal — so that a reader who has
* learnt them once has learnt them everywhere. Both are icons and nothing
* else: a `+` for joining what is on screen, which is the mark the tab strip
* and the Tracks card already use for *more of this*, and a window with a `+`
* where its corner was for a session of its own. The words are in the
* tooltips, which is also where they say what *add* means for this kind of
* file: a map goes beside the map in front as a panel of the deck, anything
* else is drawn on it as a track (§20.5, §24.2).
*
* Both are offered whatever the tab holds. On an empty tab the two land in the
* same place — there is nothing to join and nothing to leave alone — and the
* tooltips say so rather than one of the buttons vanishing: a row that has two
* marks in one store and one mark in the next is a row a reader has to think
* about. A workspace is the one exception, because it is tabs and not a file:
* it opens, and there is nothing it could be *added* to.
*/
import { icon, iconButton } from './icons'
import { isStructureName } from '../annotations/g3d'
export interface RowVerbs {
/** What the row names, for the two tooltips. */
label: string
/** How the file is drawn once opened, which is what *add* has to describe. */
kind: 'map' | 'genome' | 'workspace' | 'unknown'
/** Whether the tab in front holds nothing, which is when the two verbs meet. */
tabEmpty: boolean
onAdd: () => void
onNew: () => void
}
/** The two buttons, in the order they stand on a row: add, then new. */
export function rowVerbs(verbs: RowVerbs): HTMLButtonElement[] {
const fresh = iconButton('new-session', newTitle(verbs), verbs.onNew, {
class: 'btn btn-icon row-verb row-verb-new',
size: 14,
})
if (verbs.kind === 'workspace') return [fresh]
const add = iconButton('plus', addTitle(verbs), verbs.onAdd, {
class: 'btn btn-icon row-verb row-verb-add',
size: 14,
})
return [add, fresh]
}
/**
* The new-session mark on a button that has words as well: a gallery card's
* *open*, a group's *open with its tracks*. The same glyph as the row's second
* verb, so a labelled button and an icon-only one read as one gesture.
*/
export function withNewMark(node: HTMLButtonElement): HTMLButtonElement {
node.prepend(icon('new-session', { size: 13 }))
node.classList.add('btn-marked')
return node
}
function addTitle(verbs: RowVerbs): string {
if (verbs.tabEmpty) return `Open ${verbs.label} in this tab, which is empty.`
if (verbs.kind === 'map') {
return `Add ${verbs.label} to this tab, beside the map in front as a panel of the deck.`
}
// A model is a row of the tracks too, but what a reader sees arrive is the
// cell that draws it (§25.3), so that is what *add* says it does.
return isStructureName(verbs.label)
? `Add ${verbs.label} to this tab, as a 3D model in a cell of its own.`
: `Add ${verbs.label} to this tab, as a track.`
}
function newTitle(verbs: RowVerbs): string {
if (verbs.kind === 'workspace') return `Open ${verbs.label} — a saved session — as its own tab.`
if (verbs.tabEmpty) return `Open ${verbs.label} in a new tab — this one, since it is empty.`
return `Open ${verbs.label} in a new tab — the one in front is left as it is.`
}
|