Definition of the needs
The problem, and what is aimed at
An application draws what it wants, and puts it where it wants. What it does not choose are the icons the framework draws in its own components — the arrow of a nav, the two of the accessibility controls, the boxes of a selector, the fourteen of a presentation. Those come from one set, in one place, and an application that wants others has to rewrite the components that hold them.
What the framework offers besides is one set, under one path, asked for by name. An application that needs two sets has no way to say that the same button is not drawn the same in both: several sets are several drawings of each icon its pages use, and there is one place to put them. One that owns a drawing of its own has no way to add it beside the others. And one whose icons are images rather than line drawings has no way in at all.
The question is therefore: how does a document show the icons that belong to it, without redrawing what it does not care about, and without losing what a local document, a dark mode or a screen reader ask of an icon.
What is aimed at: let an application bring its own icons, whole sets or a handful; let a document be read with the set that suits whoever reads it; keep what the framework holds today, an icon that follows the color of what surrounds it, on a document opened from a disk, without a server and without the internet; and ask an application for the drawings, and for nothing else.
What an application writes to get all that is on icons.html.
Expression of the needs
An application has icons that belong to it, and wants to show them. It does not want to redraw the ones the framework provides and that suit it. It therefore gives the icons it owns, and the framework gives the others.
What it gives is not one set: one of them is complete and the others are not. An application that shows an incomplete one wants the missing names answered by its own complete set, and not by drawings that are not its own. It says which of its sets answers for the others; what came with the tool answers last, and only what neither of them carries.
One application may need several sets: the same button is not always drawn the same way, and what tells one set from the next is its own business. It gives as many as it wants, each under a name, and the reader chooses the one the document is shown with. Changing that choice does not load the page again, and the choice holds from one page to the next.
The reader sees the icons wherever the document is opened, served or taken from a disk. He sees them whatever the mode and the theme he reads in, and at the size he reads the text at: a contrast mode writes the text larger, and an icon that stayed where it was would be small beside it, and harder to aim at when a button holds nothing else. And whoever does not see them is told what they stand for.
Nothing moves when a drawing arrives, and nothing moves when the set changes. The room is therefore declared by the place and not by the drawing, in both its dimensions, since an icon is not always square: a set of flags is not a set of arrows. A drawing of other proportions is held inside that room rather than stretched to it.
An icon may be asked for under a name that no set carries. The page holds and shows the rest, and the console names it, so that whoever wrote the page can correct it.
What is not shown is not sent, and what is going to be shown says the room it takes before it arrives. Both are asked by the RGESN, the French reference for the eco-design of digital services, as WCAG asks that an icon be told to whoever does not see it. Neither is an improvement here: they are conditions.
Elicitation of the needs
Six things are handled, and they are all that is handled.
I1. A name is what an icon is asked for by. It says what the icon stands for, never where it is drawn: the same name is answered by a different drawing from one set to the next.
I2. A drawing is what answers a name. Its form follows from the file it stands in: a line drawing, which takes the color of what surrounds it, or an image, which carries its own.
I3. A ground is what covers a surface: a texture laid on a plain background. It is named as an icon is, and answered the same way, but it designates nothing, and it is asked for by a surface and not by a place.
I4. A set is what holds drawings and grounds under names. It carries part of the names, or all of them, and says which ones it carries. One is the reference set, and answers what the others leave unanswered.
I5. The set in force is the one a document is read with. There is one at a time, and the reader chooses it.
I6. A name it does not carry goes down a chain of two: the fallback set, which the application names among its own, and then the reference set, which belongs to the framework. Either may be absent, and the chain is the same for every name.
Organisation of the needs
I10 Icons of an application
- I11 The author can declare a set of icons that belongs to the application.
- I12 The icons an application brings are shown in place of the ones that came with the tool.
- I13 The author is free to draw only some of the icons, the others being no less shown.
- I14 A name the shown set does not carry is answered all the same, by another set.
- I16 The author says which of the sets answers what the others leave unanswered. What that one does not carry either is answered last, by what came with the tool.
- I15 The author adds an icon by bringing its drawing, and writes nothing else.
- I17 The author can be told the names a set answers, so that a page lays out the drawings it can ask for without listing them by hand.
- I18 The author says where his set stands, wherever that is: beside the page, at the root of the site, or on another host. A set he brings has no reason to stand where the tool stands.
I20 Several sets
- I21 The author can declare several sets, each under a name.
- I22 The reader can choose the set the document is shown with.
- I23 One set is in force at a time, for the whole document.
- I24 The set in force is the same from one page of the document to the next.
- I25 The set in force changes without the page being loaded again.
- I26 A drawing is loaded only when it comes into what the reader sees. RGESN
- I27 A change of set loads again only the drawings the document is showing.
I30 What an icon is made of
- I31 The author can bring line drawings and images, of whatever the file they stand in, in one set. Grounds are I70.
- I32 A line drawing is shown in the color of what surrounds it.
- I33 An icon that carries its colors is shown as it is drawn.
- I34 The element that holds an icon declares the room it takes, in both its dimensions, before the drawing arrives. RGESN
- I37 An image carries the two dimensions the place declared, so that nothing waits for the file to know them. RGESN
- I38 A drawing whose proportions are not those of the place is held inside it, and never stretched.
- I35 Nothing moves around the icon when the drawing arrives.
- I36 An icon is drawn at the size of the text around it, and grows with it.
I70 Grounds
- I71 The author can bring grounds, each under a name, in the sets that carry the icons.
- I72 A surface is covered with the ground of the set in force.
- I73 A surface whose name the shown set does not carry is covered all the same, by the ground of another set.
- I74 What a ground stands for is never told: it stands for nothing.
- I75 Nothing moves around a surface when its ground arrives.
- I76 A surface is covered only while the reader sees it.
I40 Where the document is read
- I41 The reader can see the icons on a document opened from a disk, with no server.
- I42 Nothing is asked of the internet.
- I43 The reader sees the icons in every mode and every theme.
I50 What an icon says
- I51 The reader who does not see the icon is told what it stands for.
- I52 The icon itself is not read out.
I60 What is missing
- I61 Nothing is shown for a name no set carries.
- I62 That name is said in the console, for whoever wrote the page.
- I63 Everything else is shown, and the page holds.
Left for later: showing two sets at the same time, so that they can be compared, and adding a set once the page is open.
What was set aside
These were considered and decided against. They are not missing.
| What | Why |
|---|---|
| Asking for a representation by its path rather than by a name | A path names one drawing. A name is what several sets answer, and without it there is no set to choose from |
| Trying a representation to see whether a set carries it | Where nothing serves the document the try is never answered, and where something does it costs a request for every name a set does not carry. A set says what it carries instead |
| Asking a set to carry every name | Nobody would bring a set for three drawings, and the chain already answers the rest |
| Loading the page again to change the set | It makes the reader pay for the document, its stylesheets and its scripts, to change what is drawn in a few places |
| Loading a whole set when the set in force changes | What is not in view is answered when it comes into view, and most of a set is never seen on one page |
| Holding, for a later change of set, the demands that are out of view | They are answered when they come into view, under the set that is in force then |
| A requirement on the contrast between a representation and its background | It is the theme that carries the pair of colors. A line drawing takes the color of what surrounds it, which ties it to the theme and says it once |
| Two mechanisms, one for the icons and one for the grounds | Two declarations, two fallbacks and two registers, for one need |
| A set that answers a name by drawing it rather than by carrying a drawing | Nothing asks for it |
Merise
MCC — who exchanges what
The organisation is the document, and what runs it. Two external actors exchange with it, and it is cut into two internal ones.
| Actor | What it is |
|---|---|
| Author | Draws the icons, declares the sets, writes the pages that ask for them |
| Reader | Asks for a page, chooses the set it is shown with, reads what is shown |
| Flow | From | To | What |
|---|---|---|---|
| 1 | Author | The document | The sets, each under a name, and what each one carries |
| 2 | Author | The document | The drawings |
| 3 | Reader | The document | The request for a page |
| 4 | Reader | The document | The set the document is to be shown with |
| 5 | The document | Reader | The icons shown, and what each one stands for |
| 6 | The document | Author | The names no set carries |
| Actor | What it holds |
|---|---|
| Sets | The sets that were declared, what each one carries, and where its drawings are |
| Places | The places of the document that ask for an icon, and what is shown at each |
| Flow | From | To | What |
|---|---|---|---|
| 7 | Places | Sets | A name, when a place comes into view |
| 8 | Sets | Places | The drawing that answers it, or nothing |
| 9 | Reader | Sets | The set to put in force (flow 4, once inside) |
| 10 | Sets | Places | The set has changed: what is shown is to be asked for again |
Flows 1 to 4 come from outside and become the external events of the MCT. Flows 5 and 6 leave it and are its results. Nothing else crosses: nothing is asked of a server, nothing is stored, nothing is sent back. I42
MCD — what the data are made of
Five entity classes, the identifier of each one written with a #.
| Class | Properties | What it is |
|---|---|---|
| SET | # name, where_the_drawings_are | A set of icons. One is the reference set, one may be the fallback set, the others are declared and nothing else |
| CONTENT | # content_name, kind, file, /form | What answers a name. Its kind is a drawing, shown at a place, or a ground, laid on a surface. Its file is what the set declared under that name, and its form follows from it. It exists only inside a set, and is identified relatively to it |
| PLACE | # place_id, name_asked, room | Somewhere in the document where an icon is asked for. It says the name it asks for and the room it takes |
| SURFACE | # surface_id, name_asked | Somewhere in the document that is covered. It says the name it asks for, and takes the room it already has |
| READING | # document | The document being read. There is one, and it is shown with one set |
| Relation | Verb | Leg 1 | Leg 2 |
|---|---|---|---|
| R1 | carries | SET (1,n) | CONTENT (1,1) |
| R2 | answers | CONTENT (0,n) | PLACE (0,1) |
| R3 | is shown with | READING (1,1) | SET (0,n) |
| R5 | falls back to | SET (0,1) | SET (0,n) |
| R4 | covers | CONTENT (0,n) | SURFACE (0,1) |
R1 is an aggregation: a content is named inside the set that carries it, and two sets name a content the same way without naming the same content. The set is the aggregating class, the content the aggregated one.
R2 leaves a place with no content, which is the case I61 asks to treat: a name no set carries answers nothing, and the room stays empty. R4 says the same of a surface, which keeps the plain background it had.
Two things are computed, never held: which content answers a place or a surface, which follows from R3 and R1 and changes when the reading is shown with another set I25; and whether a place or a surface is in view, which is what triggers the question I26 I76.
The constraints
On roles. SET takes part in R1 and R3, CONTENT in R1, R2 and R4. A content answers a place or covers a surface, never both, which is an exclusion on roles between R2 and R4: its kind says which of the two it is. Nothing else — no totality, no subset, no equality.
On relations. A content that answers a place is carried by a set, which would be a subset constraint from R2 to R1; the cardinality (1,1) of R1 already says it, and the arrow would add nothing. The same holds of R4. No exclusion, no equality between relations.
What the formalism does not carry is said here. C3 is the one that decides: it restricts R2 by R3, and no arrow between two relations says that.
| No. | Constraint | Comes from |
|---|---|---|
| C1 | A set carries a name once. Two drawings under one name in one set is a set declared twice | R1 |
| C2 | The reference set carries every name asked for by what the organisation draws itself | I14 |
| C3 | A place is answered by the first set of the chain that carries the name: the set in force, then the one it falls back to, then the reference set | R1, R2, R3, R5, I14 I16 |
| C10 | The chain of the fallback has no cycle and is read once: a set that falls back to itself, or to one that falls back to it, answers as if it fell back to nothing | R5 |
| C4 | A place that no set answers is not asked again under the same set in force: what a set carries it has already said | I6 I61 |
| C5 | The form of a content follows from its file, and from nothing else: a set carries line drawings and images side by side, since an author takes the files he has | CONTENT.file, I31 |
| C8 | A content answers places, or covers surfaces, and never both: its kind says which | R2, R4, CONTENT.kind |
| C9 | A surface is never told to whoever does not see it, a ground standing for nothing | I74 |
| C6 | A place declares its room, in both dimensions, before it is answered. The room does not depend on which set answers it, nor on the proportions of the drawing that does | I34 I35 I38 |
| C7 | A place is asked for only while it is in view, and only once under a given set in force | I26 I27 |
| C11 | Where a set stands is written by the page and read as the page writes it: from the page, from the root of the site, from another host, and from where the tool stands only when nothing else is said | I18 |
| C12 | The names a set answers are the names of the chain of C3, said once and in the order of that chain: what the set in force carries, then what answers for it, then the reference set | I17, C3 |
That is why which drawing answers a place is computed and never held: it follows from R3, then from R1, and it changes when the reading is shown with another set.
MCT — the events and the operations
What has to be done, and on what. Not when, not how, not where.
| No. | Event | Kind | Comes from |
|---|---|---|---|
| E1 | Sets are declared | external | Flows 1 and 2 |
| E2 | A page is asked for | external | Flow 3 |
| E3 | A set is chosen | external | Flow 4 |
| E4 | A place or a surface comes into view | internal | OP2, then the reading |
| E5 | The set in force has changed | internal | OP2 |
| What | Says |
|---|---|
| Synchronisation | E1 AND E2 |
| Actions | Hold each set under its name, with what it carries — drawings and grounds — and where they are. Hold which one answers for the others, and the reference set last: those two are the chain a name goes down |
| Result | The sets are known. Always |
| Result | A message: a set declared twice. When two sets bear one name |
Nothing is read here: a set says what it carries, and OP1 believes it. That is what lets OP3 answer without asking. I6
| What | Says |
|---|---|
| Synchronisation | (the sets are known AND E2) OR E3 |
| Actions | Take the set the reader names; the one the page names when he names none; the reference set when neither names one |
| Result | One set in force. Always |
| Result | E5, the set has changed. When the set taken is not the one that was in force |
| Result | E4, for each place and each surface in view. When the reading begins |
A set that was never declared is a set nobody named: the set in force does not change for it. I23
| What | Says |
|---|---|
| Synchronisation | E4 AND a set is in force |
| Actions | Go down the chain — the set in force, the one that answers for the others, the reference set — and stop at the first that carries the name; read what answers, and put it where it was asked for |
| Result | The drawing, at the place. When a set carries the name and the content is a drawing |
| Result | The ground, on the surface. When a set carries the name and the content is a ground |
| Result | The room, left empty, or the plain background kept. When no set carries the name |
| Result | A message: the name no set carries. When no set carries the name |
OP3 is ininterruptible for one demand: a set put in force while a content is being read is taken into account after, by E5, and not during. Nothing moves around what was asked for, the room of a place having been declared before and a surface keeping the one it has. I34 I75
What the content is decides what OP3 produces, and nothing else does: a drawing is shown at a place, a ground is laid on a surface, and neither is ever the other. C8
| What | Says |
|---|---|
| Synchronisation | E5 |
| Actions | Take back what was answered at the places and the surfaces that are in view |
| Result | E4, for each of them. Always |
OP4 answers nothing of its own: it gives OP3 its event back, and for what is in view only. What is not seen is answered when it is seen. I27
One process, four operations. E1 and E2 open it, E3 comes as often as the reader asks, E4 as often as the reading moves, and E5 only when OP2 changes what was in force.
MOT — when, where, and by whom
The operations of the MCT, cut into functional procedures, each triggered by one event.
| PF | From | Triggered by | Duration | Place | In charge | Resources |
|---|---|---|---|---|---|---|
| PF0 | — | The application is built | Once, before anything is read | The machine of the author | Author | The drawings and the grounds, and what gathers them into the document |
| PF1 | OP1 | E1 AND E2 | Once per page, before anything is shown | Where the document is read | The organisation | What the document declares of its sets, and which of them answers for the others |
| PF2 | OP2 | The page opens | Once per page, after PF1 | Where the document is read | The organisation | The address, and what the page names as its default |
| PF3 | OP2 | E3, the reader asks | As often as he asks | Where the document is read | Reader | The sets known by PF1 |
| PF4 | OP3 | E4, a place or a surface comes into view | Once per demand and per set in force | Where the document is read | The organisation | The set in force, and the content — read where it stands when the document is served, taken from what PF0 gathered when it is not |
| PF5 | OP4 | E5, the set has changed | Once per change, on what is in view only | Where the document is read | The organisation | The places and the surfaces PF4 has answered |
PF0 is what the MCT does not show: a document read where nothing serves it cannot go and get anything, so what it will need has to be gathered into it beforehand. That happens elsewhere, at another time, and under the responsibility of the author — which is why a set meant for such a document is gathered as the reference set is. I41
Everything else happens where the document is read. Nothing is done elsewhere, and nothing is kept from one opening to the next: PF1 and PF2 run again at every opening, and give the same result.
PF2 and PF3 are one operation cut in two, because two events trigger it and two are in charge: the system at the opening, the reader afterwards. What they produce is the same, one set in force. I24
PF4 comes as often as the reading moves, and never before PF2: a demand answered without a set in force would be answered twice. Its resources differ according to whether the document is served or not, and it is the only procedure where that difference is seen.
MLD — the tables
Each entity class becomes a table, its identifier becomes the key.
| Table | Columns | Comes from |
|---|---|---|
| SET | name, where_the_contents_are | The entity class SET |
| CONTENT | set_name, content_name, kind, file | The entity class CONTENT, and R1. The form is not a column: it is read in the file |
| PLACE | place_id, name_asked, room | The entity class PLACE |
| SURFACE | surface_id, name_asked | The entity class SURFACE |
| READING | document, set_in_force | The entity class READING, and R3 |
R1 is an aggregation: the aggregated class takes the key of the aggregating one, so CONTENT holds the name of its set, and the two together tell one content from another. Two sets carry a content under one name without carrying the same content.
R3 has a low cardinality on the side of READING, which is (1,1): the table READING takes the key of SET, under the name of what it says — set_in_force.
R2 and R4 are translated by nothing. Which content answers a place, and which one covers a surface, are computed from the set in force and from what the sets carry: a column would hold an answer that changes as soon as the reading is shown with another set, and would have to be emptied at every change. C3
Not in the tables either: whether a place or a surface is in view. It is read where the document is read, and it changes as the reading moves.
MPD — where each table stands
Here the tool is named, and not before: Whakerexa answers what the needs ask for, and it is the one that is extended. There is no database — the tables are borne by the document, by what runs it, and by what is built before it is read.
| Table | In the source | While running | On screen |
|---|---|---|---|
| SET | What a page declares on wexa.loader.js: a name, a path, and the files it carries, each under the name it answers to. Another attribute names the set that answers for the others |
An object held by the manager of the sets | Nothing of its own |
| CONTENT | A file in the folder of its set on http; a string written into wexa.bundle.js by build_bundle_js.py on file:// |
The markup or the address, once read, in the cache of the manager | The icon, or the ground |
| PLACE | An element that names its icon and declares its room, in calc(var(--font-size) * n) for each of its two dimensions |
That same element | The room, then the drawing |
| SURFACE | An element that names its ground | That same element | The plain background, then the ground over it |
| READING | Nothing | The name of the set in force, held beside the sets | What the document is shown with, and the name written in the address, as the theme is |
Two things the tables do not hold are read from the browser: whether a
place is in view, which IntersectionObserver answers, and the
size of the text around an icon, which the font size of the element
answers.
The reference set is wexa_statics/icons/mono-svg/. What a
set says it carries is what makes the chain work with no request: on
file:// a request would never be answered, and on
http it would cost one for every name a set does not carry,
at every step of the chain. I6
MOpT — where the code goes
| Module | What it does | Procedure |
|---|---|---|
| sets | Holds the sets, what each one carries, where its contents are, and which form they take | PF1 |
| choice | Holds the set in force, changes it, and says it in the address | PF2, PF3 |
| reading | Reads a content, from a file or from what was gathered into the document. The only one that knows where a content comes from | PF4 |
| placing | Puts a content where it was asked for, and the only one that knows a line drawing from an image and a drawing from a ground | PF4 |
| watching | Says when a place or a surface comes into view, and when it leaves | the trigger of PF4 |
| register | Holds what has been answered, so that a change of set asks again for that and nothing else | PF5 |
| gathering | Writes the contents of a set into the document, for a document read where nothing serves it | PF0 |
Under wexa_statics/js/, one file per class, as the framework
already writes them. The module that gathers is a script of
scripts/, run before a release, beside the one that builds
the bundle.
SVGIconsManager answered for reading and for placing at once,
and for one set only. It is what the modules above took apart, and it is
gone.
The decisions of the tool
What the levels above do not decide, and what the code will show. They belong here: they are choices about the tool, and they could not be made before it was named.
D1. One package holds what customises the look. The manager of the themes and the one of the sets hold the same kind of state — a name in force, read in the address and written back — and they answer the same need on two matters. They are written together rather than apart.
D1b. The manager is held under Wexa.iconsets.
Wexa.icons is the name of the older manager, which the
components of the framework still call: taking it would leave them
without icons. The two names live side by side until D2 is done, and
D2 is a broken promise for whoever calls
Wexa.icons.get().
D2. What reads and what places are taken apart.
SVGIconsManager did both, for one set. Reading changes when a
document is served or not; placing changes when a content is a line, an
image or a ground. They do not change for the same reasons, so they are
not one class. The older one is removed, and Wexa.icons is
the new manager: what it holds of the old are get() and
inject(), which the components of the framework call.
D3. A place declares its room counted on the font size, in
calc(var(--font-size) * n) as the framework counts every
size, and in both dimensions. One declaration holds three needs: the room
kept before the image arrives I34, the size that follows the text I36,
and the two dimensions an image is given so that nothing waits for the
file to know them I37. A drawing of other proportions is held inside
that room I38: the place is what does not change from one set to the
next, so it is the place that decides the shape.
D4. A set is declared on the loader, beside the themes, and not in a call written in every page. A page says what it brings where it already says what it loads, and names there the set that answers for the others.
D7. A set is declared in one line: its name, its place, its files. The name is what stands before the first colon and the files what stands after the last one, so that the place between the two keeps the colon of an address that carries a host. The files are written and not asked for: it is what lets a name fall back with no request at all, on a document read from a disk as on one that is served I41 I42.
D8. The names a set answers are computed, never held. They follow the chain of C3 and change with the set in force, exactly as the drawing that answers a place does. A page that lays them out asks for them when it lays them out I17.
D9. The demand is carried by the element that means something — a button, a link, a heading — and never by an element written for the icon alone. What the icon stands for is said by that element and not by the drawing I51: an element written for the drawing alone would carry something that names nothing, and a reader who does not see it would be told nothing. It is also what keeps the drawing out of the reading I52, the element that holds it being what is announced.
D6. The chain has two links and no more. A set that answers for the others, then the reference set. Letting each set name the one it falls back to would make a chain of any length, which nobody asked for, and which would have to be walked at every name and guarded against cycles.
D5. What a set carries is gathered into the document at build time, by a tool the author runs. It is the only way a document read with nothing serving it can answer a name. Only the line drawings are gathered — an image is answered by its address, which a document finds beside itself.
D5b. What is gathered is written on the namespace of the framework,
as Wexa.gatheredIcons, and not under a name of its own. The
style guide of the project asks that a global be avoided; the framework
already holds one, Wexa, and a second would be one too many.
The file that carries the drawings is loaded before Whakerexa is there, so
it makes that object if it has to and wexa.js adds to what it
finds. What an older build left under a name of its own is read as
well: the decision changes where the list is written, not what a document
already carrying one can do.
It is a script and not a file of settings. A browser refuses
fetch() on a file:// address, and that address is
the one case this file exists for I41 I42: a .json could
not be read there, while a script is run. Served, nothing of this is
needed — a drawing is asked for when a place demands it — so a file of
settings would fail where it would be useful, and add a request where it
would not.
It is a list and not a call on a class: a file loaded by a page cannot know when the framework will be there, and a list waits without asking anything. Its name says a list and not a constant — the page fills it, the loader empties it. And a list is all it is, so an author whose tools are his own writes it as he likes: nothing of the framework runs to produce it, and nothing of it is asked at the moment it is read.
UML
The classes that carry the data
They come from the MLD, one class per table, and they are set at construction. What they give back is a string or a copy.
| Class | From | What it is |
|---|---|---|
IconSet | SET | A set: its name, where its contents stand, the form they take, and the names it carries |
IconContent | CONTENT | What answers a name: its kind, a drawing or a ground, and its source |
IconDemand | PLACE, SURFACE | An element that asks for a name. Its kind says whether it is a place or a surface |
PLACE and SURFACE become one class: they differ by what answers them, which C8 says is the kind of the content, and by nothing they hold themselves. READING becomes no class at all — the set in force is a name, held by the one that changes it.
The classes that do the work
One per module of the MOpT, and each one is the only one that knows what it knows.
| Class | Module | What it does |
|---|---|---|
IconSets | sets | Holds the declared sets and the reference one. Says which set answers a name, and never reads anything |
IconChoice | choice | Holds the set in force, changes it, reads it in the address and writes it there |
IconReader | reading | Reads a content. The only one that knows a file from what was gathered into the document |
IconPlacer | placing | Puts a content where it was asked for. The only one that knows a line drawing from an image, and a drawing from a ground |
IconWatcher | watching | Says when a demand comes into view. The only one that reads the rendering |
IconRegister | register | Holds the demands that were answered, and gives back those in view |
IconManager | — | Calls the others in order, and is the only one that catches an error |
What each one promises: IconSets reads nothing and asks
nothing, which is what makes it testable without a document;
IconReader is the only one that goes and gets a content;
IconPlacer is the only one that changes the document shown;
IconManager is the only one that writes a try.
The states of a demand
| State | What is true |
|---|---|
| Written | The element names what it asks for and, for a place, declares its room. Nothing is shown |
| Watched | The demand is known, and waits to come into view |
| Answered | A content is where it was asked for, and the demand is held for a later change of set |
| Unanswered | No set carried the name. The room stays empty, and the console has said it |
A change of the set in force takes an answered demand back to watched, and only those in view. An unanswered one is not tried again under the same set: what a set carries it has already said. C4
The sequence when the page opens
- The page declares its sets;
IconSetsholds them, the one that answers for the others, then the reference set: that is the chain. IconChoicereads the address, then what the page names, then falls back on the first set of the chain.IconWatcheris given the demands of the document.- A demand comes into view:
IconSetssays which set answers its name. IconReaderreads the content;IconPlacerputs it where it was asked for.IconRegisterholds the demand.- The reader chooses another set:
IconChoicesays so,IconRegistergives back what is in view, and step 4 begins again for those.
Step 1 before step 2, and step 2 before step 4: a demand answered before a set is in force would be answered twice, and would move what is around it.
The error policy
| Level | What happens | What is done |
|---|---|---|
| 1 | Nothing can be done: not one set, not even the reference one | An exception, caught by IconManager, said in the console |
| 2 | One demand is concerned: no set carries the name, or the content cannot be read | No exception. The room stays empty, and the rest of the page holds |
| 3 | The author has to know: a name nobody carries, a set declared twice | No exception. A message in the console, and the work goes on |
Exceptions are raised at the lowest level and caught at the highest. An error must never do worse than the absence of the program: without it a page shows no icon and reads all the same.
The contracts, class by class
How to read them
+ public, - private, / derived and
never held, {readOnly} does not change after construction,
{ordered} the order matters. pre is what has to be
true on the way in, and what the operation does not check; post is
what the caller can count on.
Two rules hold everywhere: a name that answers nothing gives back an empty
string, an empty array or an empty map, never null; and the
fields of a data class are set at construction and give back a copy.
The data classes
| Operation | Signature | Contract |
|---|---|---|
| constructor | (name, base, files) | pre: name and base are not empty; files names a file under each name it answers to, and may be empty. post: the object does not change any more |
| get name | (): String | post: the name the set was declared under |
| carries | (name: String): Boolean | pre: none. post: true when the set declared that name. Reads nothing and asks nothing. I6 |
| addressOf | (name: String): String | pre: the set carries the name. post: where the content stands, from the base of the set and the file declared under that name |
| /formOf | (name: String): IconForm | pre: the set carries the name. post: line when the file is an SVG, image otherwise. Read in the file, never held. C5 |
carries() answers from what was declared, never from what
exists: that is the whole of decision 2.
| Operation | Signature | Contract |
|---|---|---|
| constructor | (name, kind, form, source) | pre: name is not empty; kind is a drawing or a ground; source is what was read. post: the object does not change any more |
| get kind | (): IconKind | post: drawing or ground. It says what answers a place and what covers a surface. C8 |
| get form | (): IconForm | post: line or image, read in the file it stands in |
| get source | (): String | post: the markup of a line drawing, or the address of an image. Never empty |
| Operation | Signature | Contract |
|---|---|---|
| constructor | (element, name, kind) | pre: element is not null; name is not empty; kind is a place or a surface. post: the object does not change any more |
| get name | (): String | post: the name the element asks for |
| get kind | (): DemandKind | post: place or surface. A place holds a room, a surface holds what it already has |
| get element | (): HTMLElement | post: the element itself, never a copy: it is what is written into |
The working classes
| Operation | Signature | Contract |
|---|---|---|
| IconSets.declare | (set: IconSet): void | pre: set is not null. post: the set answers under its name; a name declared twice keeps the first and is said in the console. C1 |
| IconSets.reference | (set: IconSet): void | pre: set is not null. post: it is the set a name falls back to, and it is looked at last. C2 |
| IconSets.fallback | (name: String): void | pre: none. post: the set of that name is the one the others fall back to. A name that was never declared leaves the chain as it was |
| IconSets.setFor | (name: String, inForce: String): IconSet | pre: none. post: the first set of the chain that carries the name — the one in force, the one it falls back to, the reference one — or null when none carries it. Reads nothing. C3, C10 |
| IconChoice.inForce | (): String | post: the name of the set the document is shown with. Never empty: the reference set when nothing else was named |
| IconChoice.put | (name: String): Boolean | pre: none. post: true when the set in force changed, and the address says it; false when the name was already in force or was never declared. I23 I24 |
| IconReader.read | (set: IconSet, name: String): Promise<IconContent> | pre: the set carries the name. post: the content, read where the document is read from; raises UnreadableContent when it cannot be read. The only one that goes and gets anything |
| IconPlacer.place | (demand: IconDemand, content: IconContent): void | pre: the kind of the content answers the kind of the demand. post: the content is where it was asked for, held inside the room the place declared and never stretched to it; an image carries that room in its two dimensions; nothing around it has moved; a line drawing takes the color of what surrounds it, an image keeps its own. I32 I33 I35 I37 I38 I75 |
| IconPlacer.clear | (demand: IconDemand): void | pre: none. post: the demand shows nothing, and keeps its room. Calling it twice does nothing wrong |
| IconWatcher.watch | (demands: IconDemand[], onView): void | pre: none. post: onView is called once per demand when it comes into view, and again after clear(). Reads the rendering, and decides nothing. I26 I76 |
| IconRegister.hold | (demand: IconDemand): void | pre: none. post: the demand is given back by inView() |
| IconRegister.inView | (): IconDemand[] | post: those of the held demands that are in view, in no order. May be empty. I27 |
| IconManager.constructor | (sets, named, watcher) | pre: sets is not null. post: one set in force. A watcher is made when none is given: a test gives one, being unable to wait for a rendering |
| IconManager.run | (root): Promise<void> | post: every demand in view is answered or left empty; never raises; kept when everything is done |
| IconManager.show | (name: String): Promise<void> | pre: none. post: the document is shown with that set; the demands in view are answered again and no others; never raises. I25 I27 |
IconSets.setFor() is the whole of the fallback, and it reads
nothing: it is the one operation that decides, and the one that is tested
without a document.
Three exception classes: IconError, the mother, raised by
nobody; NoSetAtAll, raised when not one set was declared;
UnreadableContent, raised by IconReader.read().
IconManager is the only one that writes a
try.
What is tested, and where
Without a document
IconSets decides the whole chain and reads nothing, so every
rule of it is checked without opening anything: a name the set in force
carries comes from that set; a name it does not carry comes from the set
that answers for the others; a name neither carries comes from the
reference set; a name none of the three carries comes back as nothing; a
set that answers for itself answers as if it answered for nothing; a set
declared twice keeps the first and says so. C1, C2, C3, C10
IconSet.carries() answers from what was declared and never
from what exists, which is checked by declaring names no file stands
behind: the answer is the same. That is the test that holds decision 2, and
it would pass on a machine with no icon at all.
IconChoice reads and writes one name: a set that was never
declared does not become the set in force; putting the one already in
force changes nothing and says so; the name is found again in the address.
I23 I24
IconRegister gives back what it holds, and only what is in
view. I27
With a document
IconPlacer is checked on written markup: a line drawing takes
the color of what surrounds it and an image keeps its own I32 I33; a
ground covers a surface and no place [C8]; what surrounds a demand has the
same size before and after, and the same again with a drawing of other
proportions I35 I38 I75; an image carries the two dimensions the
place declared I37; and clear() leaves the room where it
was.
IconWatcher is checked on a document taller than one screen: a
demand out of view is not announced, and is announced when the reading
reaches it. I26 I76
IconManager is checked on what must not break the page: not one
set declared, a name nobody carries, a content that cannot be read. It
never raises, the page holds, and the console has said the name. I61
I62 I63
Where
In wexa_statics/js/tests/, one file per class, run by
tests.html, as the framework already tests. The tests of the
first section are the ones written first: they are the whole of the
decisions, and they need nothing to run.