kanban — u_pbt_kanban #
← Référence des composants · Sommaire du guide
kanban est un tableau de cartes rangées en colonnes — les étapes d'un travail : à faire, en cours, en revue, terminé. L'utilisateur glisse une carte d'une colonne à l'autre, ou la monte et la descend dans la sienne ;
ue_card_movedvous dit laquelle, d'où, vers où et à quelle place. Chaque carte montre un titre, des étiquettes colorées, son responsable, une échéance qui rougit en retard et un badge ; chaque colonne a sa limite de travail en cours et se replie. Le tableau se remplit à la main ou depuis un DataStore, qui reçoit les déplacements.
▶ Le voir en vrai — Application de démonstration, tuile Kanban board : l'aperçu, le code qui le produit et cette page, côte à côte.
En bref #
| Userobject | u_pbt_kanban |
| Classes d'items | n_pbt_kanban_column (of_column(key)), n_pbt_kanban_card (of_card(key)) |
| Sert à | Suivre un flux de travail : tickets, tâches, commandes, candidatures |
| Principe | Une carte a une clé unique sur tout le tableau ; sa colonne est un état qui change à chaque déplacement |
| Options opt-in | ib_veto_moves, ib_write_back, ib_reorderable, ib_toolbar, ib_add_button, ib_quick_add |
Démarrage rapide #
// The columns, in the order of the work
uo_board.of_add_column(/*key*/ "todo", /*title*/ "To do")
uo_board.of_add_column(/*key*/ "doing", /*title*/ "In progress")
uo_board.of_add_column(/*key*/ "done", /*title*/ "Done")
// The cards : a key unique on the board, a column, a title
uo_board.of_add_card(/*key*/ "t1", /*column*/ "todo", /*title*/ "Login page")
uo_board.of_add_card(/*key*/ "t2", /*column*/ "doing", /*title*/ "Crash on save")
uo_board.of_card(/*key*/ "t2").is_tags = "Bug"
uo_board.of_card(/*key*/ "t2").is_assignee = "Alan Turing"
// event ue_card_moved of uo_board : (string as_key, string as_from_column,
// string as_to_column, long al_position, long al_from_position)
// Save the new state of the task
UPDATE tasks SET status = :as_to_column WHERE id = :as_key;
Colonnes, cartes et places #
Une colonne se désigne par sa clé, une carte aussi — et la clé d'une carte est unique sur tout le tableau, pas seulement dans sa colonne : une carte garde sa clé quand elle change de colonne, ses poignées restent valables et chaque événement la nomme seule. La colonne d'une carte se lit par of_card(key).of_column(), sa place par of_position() ; une place se compte à partir de 1, cartes masquées comprises.
Une colonne a une limite de travail en cours (il_limit) : son en-tête compte 3/5, et elle rougit au-delà. La limite est souple — la carte arrive quand même ; pour une limite stricte, refusez le déplacement dans ue_card_moving en comparant il_limit à of_visible_count() de la colonne, ce que compte l'en-tête (une carte masquée ne compte pas). ib_done marque la colonne du travail terminé : ses cartes ne sont jamais en retard. Une colonne se replie en bande étroite (son chevron, ib_collapsed) ; on y dépose encore une carte, qui va en dernier.
Un déplacement de l'utilisateur (glisser, Ctrl + flèches, ou la carte soulevée par Espace et posée) et un déplacement de votre code (of_move_card) lèvent le même ue_card_moved, comme SelectItem lève l'événement du clic. Avec ib_veto_moves, ue_card_moving est posé avant, aux deux : renvoyer FALSE laisse la carte où elle est, et of_move_card rend alors -4.
Avec ib_reorderable = true, l'utilisateur réordonne aussi les colonnes : il glisse l'en-tête d'une colonne (une barre d'accent verticale montre où elle tombera, Échap annule) ou presse Ctrl + Maj + Gauche / Droite. ue_column_moved donne la colonne et ses deux places, comptées à partir de 1 parmi toutes les colonnes ; of_move_column fait la même chose depuis votre code et lève le même événement, ue_column_moving étant posé avant avec ib_veto_moves. Désactivé par défaut : les colonnes sont le processus de votre application. Ce que l'utilisateur a arrangé — l'ordre des colonnes et leur repli — se lit par of_get_layout, se rend par of_set_layout, et chaque changement lève ue_layout_changed avec la disposition entière : enregistrez-la, rendez-la au prochain lancement.
Le contenu d'une carte #
Une carte montre son titre (is_title), son texte (is_text, coupé après quatre lignes), ses étiquettes (is_tags, séparées par des virgules, colorées par is_tag_tones : Bug=danger|UI=info), son responsable (is_assignee, un avatar rond avec ses initiales), son échéance (is_due, aaaa-mm-jj : rouge une fois dépassée, orange le jour même, comparée à is_today ou à la date du poste) et un badge (is_badge). Titre, texte et badge acceptent le balisage riche.
Le corps des cartes peut s'écrire par un modèle, is_card_template : du texte riche où {customer} est un champ de la carte — un des vôtres (of_set_field), une colonne du DataStore d'où elle vient, ou un champ intégré (title, text, tags, assignee, initials, badge, due, column, column_title, key). {due:dddd d mmmm} écrit une date comme un format d'affichage de DataWindow (les jetons d dd ddd dddd m mm mmm mmmm yy yyyy, un texte entre guillemets doubles — hors guillemets, une lettre d, m ou y est un jeton —, [shortdate] et [longdate] dans la langue de l'affichage), {?amount}…{/amount} garde un morceau quand le champ dit quelque chose, {!amount}…{/amount} quand il ne dit rien, {x:raw} garde une valeur comme balisage, {{ }} sont des accolades. Une valeur est toujours affichée telle quelle, jamais lue comme balisage.
// A field of our own, then the body of every card
uo_board.of_set_field(/*key*/ "t1", /*field*/ "customer", /*value*/ "Acme")
uo_board.is_card_template = "{?customer}For [b]{customer}[/b]{/customer}{?due} - due {due:d mmm}{/due}"
Depuis un DataStore #
of_from_datastore fait une carte de chaque ligne d'un DataStore, d'un DataWindow ou d'un DataWindowChild — l'appel est le même, et un DataWindow est écrit en retour lui-même. Sa clé est le RowID de la ligne — of_card(key).of_row() rend le numéro de sa ligne tant que le DataStore n'est ni vidé ni relu — ou la valeur de la colonne ROLE_KEY. Une ligne dont la clé est vide, invalide, déjà vue ou tenue par une carte ajoutée à la main n'est pas chargée : l'appel rend 0 et of_get_last_error la nomme par son numéro — donnez à vos cartes à la main des clés qui ne sont pas des nombres. Une colonne joue un rôle quand elle en porte le nom (title, text, tags, assignee, due, badge, color, order, column, key) ou quand of_map le dit. La colonne ROLE_COLUMN dit dans quelle colonne du tableau est la carte ; une valeur qu'aucune colonne ne porte reçoit sa propre colonne, à la fin — une valeur qui contient / ou | y prend une clé où ils deviennent - (R&D-QA) et garde sa valeur, celle qu'un déplacement réécrit ; une valeur vide n'est pas chargée (of_get_last_error la nomme), une valeur CHAR complétée d'espaces trouve sa colonne. Une colonne née d'une valeur part une fois vide, sauf si votre code lui a posé une propriété ou une couleur. ROLE_ORDER range les cartes d'une colonne : le rang est la place d'une carte parmi les cartes du DataStore de sa colonne, à partir de 1 (une carte ajoutée à la main ne prend pas de rang). Avec une clé ROLE_KEY, un second chargement, of_map et of_reload_row mettent les cartes à jour en place : une carte qui revient garde ses drapeaux, ses champs et sa poignée. Avec la clé RowID, un second of_from_datastore est un nouveau chargement : PowerBuilder redonne les mêmes RowID après un Reset ou un Retrieve, à d'autres enregistrements — toutes les cartes des anciennes lignes partent (leur poignée est libérée) et les cartes sont refaites ; of_map et of_reload_row restent en place. Une carte que votre code a retirée ne revient pas avec of_map : sa ligne reste dans le DataStore, le prochain of_from_datastore la relit. Les dates et les décimaux sont lus selon les réglages régionaux du poste (un champ décimal se lit 1234.5). Toutes les colonnes sont des champs du modèle.
Avec ib_write_back = true, une carte d'une ligne écrit sa nouvelle colonne dans la ligne (et, avec ROLE_ORDER, les rangs des deux colonnes) avant de bouger — la ligne est retrouvée par son RowID et par rien d'autre : ue_card_moved lit le DataStore à jour, l'Update reste à vous. La colonne reçoit la valeur de la colonne visée (R&D/QA, jamais sa clé R&D-QA). Tout ou rien : une valeur que le DataStore refuse — la colonne ou un rang — remet ce qui était déjà écrit, laisse la carte où elle était (elle ne part jamais pour revenir) et lève ue_write_back_failed ; of_move_card rend alors -4. Un seul déplacement de l'utilisateur s'écrit à la fois : un geste fait avant que le précédent soit écrit est ignoré, et dit. Après avoir changé une ligne vous-même, of_reload_row la renvoie au tableau.
// The columns of the board : the values of the status column
uo_board.of_add_column(/*key*/ "open", /*title*/ "Open")
uo_board.of_add_column(/*key*/ "active", /*title*/ "Active")
uo_board.of_add_column(/*key*/ "closed", /*title*/ "Closed")
// Which column of the DataStore plays which role
uo_board.of_map(/*role*/ u_pbt_kanban.ROLE_COLUMN, /*column*/ "status")
uo_board.of_map(/*role*/ u_pbt_kanban.ROLE_ASSIGNEE, /*column*/ "owner")
uo_board.of_map(/*role*/ u_pbt_kanban.ROLE_ORDER, /*column*/ "rank")
// A move goes into the DataStore, then the rows become cards
uo_board.ib_write_back = true
uo_board.of_from_datastore(/*ads*/ ids_tasks)
Propriétés #
| Propriété | Type | Défaut | Rôle | ||
|---|---|---|---|---|---|
is_card_template | string | "" | Le corps de chaque carte, écrit par un modèle (voir plus haut). Vide : le texte de la carte (is_text). La recherche lit ce que le modèle écrit | ||
is_count_template | string | "" | Le compteur de l'en-tête de chaque colonne, écrit par un modèle : {count} les cartes visibles, {limit} la limite (vide sans limite), {shown} les cartes que garde la recherche, {sum:points} la somme d'un champ sur les cartes visibles (un des vôtres ou une colonne du DataStore), {title} et {key} de la colonne ; {?limit}…{/limit} garde un morceau quand il y a une limite. Vide : 3, 3/5, 1 . 3/5 pendant une recherche. Au-delà de sa limite la colonne rougit quoi que dise le modèle, et son en-tête le dit au lecteur d'écran. {sum:} lit un nombre écrit au point ou dans la langue de l'affichage (1,250 en anglais) ; un texte ne compte pas. Sans clé, le compte et la somme sont ceux des cartes que la démo dessine | ||
is_tag_tones | string | "" | Le ton de chaque étiquette, étiquette=ton joints par ` | : Bug=danger | UI=info. Tons : TONE_SUCCESS, TONE_WARN, TONE_DANGER, TONE_INFO (l'accent), TONE_NEUTRAL`. Une étiquette trouve son ton quelle que soit sa casse ; une étiquette absente, ou un ton inconnu, est neutre |
is_today | string | "" | Le jour auquel les échéances sont comparées, aaaa-mm-jj ; vide : la date du poste. Une date qui n'en est pas une est refusée : l'ancienne reste, of_get_last_error dit pourquoi | ||
is_filter | string | "" | La recherche : seules restent les cartes dont le titre, le corps, les étiquettes, le responsable, le badge, la clé, un champ à vous ou une colonne du DataStore contiennent ce texte, sans tenir compte de la casse ni des accents. Le compteur d'une colonne dit alors d'abord les cartes trouvées (1 . 3). La zone de recherche de la barre d'outils l'écrit aussi : lue en direct | ||
ib_toolbar | boolean | false | Une barre d'outils au-dessus du tableau, avec une zone de recherche qui écrit is_filter (Échap la vide) | ||
ib_add_button | boolean | false | Un bouton + Ajouter une carte au pied de chaque colonne ouverte : il lève ue_new_requested. Un double-clic dans la partie vide d'une colonne le lève aussi, bouton ou non | ||
ib_quick_add | boolean | false | Ajout rapide : le bouton + Ajouter une carte et la touche Inser ouvrent un champ de titre au pied de la colonne ; Entrée lève ue_new_requested avec le titre tapé (un titre vide ne demande rien), le champ reste ouvert pour la carte suivante, Échap le ferme. Le tableau n'ajoute toujours rien : votre code ajoute la carte | ||
ib_read_only | boolean | false | L'utilisateur ne déplace rien : ni glisser, ni Ctrl + flèches, ni Suppr, ni bouton d'ajout. Il sélectionne et ouvre toujours les cartes ; votre code les déplace toujours | ||
ib_reorderable | boolean | false | L'utilisateur réordonne les colonnes : il glisse leur en-tête ou presse Ctrl + Maj + Gauche / Droite ; ue_column_moved puis ue_layout_changed suivent. ib_read_only l'arrête aussi ; votre code les déplace toujours (of_move_column). Lu en direct | ||
ib_veto_moves | boolean | false | Opt-in : demander ue_card_moving avant chaque déplacement, de l'utilisateur comme de of_move_card. Désactivé par défaut, comme tout événement annulable de la bibliothèque | ||
ib_write_back | boolean | false | Un tableau alimenté par of_from_datastore : une carte d'une ligne écrit sa nouvelle colonne (et les rangs, avec ROLE_ORDER) dans le DataStore avant de bouger ; une valeur refusée la laisse en place (ue_write_back_failed, of_move_card rend -4). Une carte ajoutée à la main n'est jamais écrite | ||
ii_column_width | integer | 272 | La largeur d'une colonne ouverte, en pixels, de 180 à 600 (une valeur hors bornes y est ramenée) ; 0 : les colonnes ouvertes se partagent la largeur du tableau, 180 pixels au moins chacune. Le tableau défile de côté quand les colonnes ne tiennent pas | ||
is_theme_style | string | "" | Style visuel du composant (constantes THEME_STYLE_*) ; vide = celui de l'application, suivi à chaque changement | ||
is_theme_mode | string | "" | Variante claire ou sombre (constantes THEME_MODE_*) ; vide = celle de l'application, suivie à chaque changement | ||
il_theme_accent | long | -1 | Couleur d'accent de ce composant (-1 = l'accent de l'application, ou celui du thème) | ||
is_tooltip | string | "" | Info-bulle simple affichée au survol du composant | ||
is_super_tooltip_title | string | "" | Titre de l'info-bulle enrichie (prend le pas sur is_tooltip) | ||
is_super_tooltip_text | string | "" | Texte de l'info-bulle enrichie (balisage riche accepté) | ||
is_super_tooltip_image | string | "" | Image de l'info-bulle enrichie |
Propriétés d'une colonne — n_pbt_kanban_column #
Sa poignée, par of_column(key). Son of_count() compte les cartes qu'elle contient et son of_keys_at(n) rend la clé de la n-ième, dans leur ordre ; of_child_keys les rend toutes en une seule lecture.
| Propriété | Type | Défaut | Rôle |
|---|---|---|---|
is_title | string | "" | Titre de la colonne. Accepte le balisage riche. Vide, la colonne montre sa clé |
il_limit | long | 0 | Limite de travail en cours : 0, aucune. Avec une limite l'en-tête dit 3/5, et la colonne rougit dès qu'elle en contient plus ; pendant un glisser au-dessus d'une colonne pleine, elle le montre. Limite souple : refusez dans ue_card_moving pour une limite stricte |
ib_collapsed | boolean | false | true replie la colonne en bande étroite : son titre écrit vers le bas et son compteur restent, ses cartes se cachent, on y dépose encore une carte (en dernier). ue_column_toggled suit, comme pour un clic sur son chevron. Lu en direct |
ib_visible | boolean | true | false retire la colonne et ses cartes du tableau ; elles gardent leur place et leur ordre |
ib_done | boolean | false | La colonne du travail terminé : ses cartes ne sont jamais montrées en retard ni à échéance |
of_keys_at (long al_index) → string | — | — | La clé de la carte au rang al_index (à partir de 1) dans la colonne, dans leur ordre ; vide au-delà. Une carte se désignant par sa clé seule, c'est ce que prend of_card |
of_child_keys (ref string as_keys[]) → long | — | — | Remplit as_keys[] des clés de toutes les cartes de la colonne, dans leur ordre — ce que donne of_keys_at(1..n) — et rend leur nombre, en une seule lecture : parcourir 2 000 cartes par of_keys_at relit la liste 2 000 fois |
of_position ( ) → long | — | — | Rend la place de la colonne sur le tableau maintenant, à partir de 1 parmi toutes les colonnes (masquées comprises) — l'utilisateur a pu la déplacer ; 0 quand le tableau ne la contient pas |
of_visible_count ( ) → long | — | — | Rend le nombre de cartes visibles de la colonne, ce que son en-tête compte face à il_limit (2/3) : une carte masquée par ib_visible ne compte pas, une carte hors de la recherche compte ; of_count() les compte toutes. Le nombre à comparer à il_limit pour une limite stricte ; 0 quand le tableau ne contient pas la colonne |
is_tooltip | string | "" | Info-bulle simple affichée au survol de l'item |
is_super_tooltip_title | string | "" | Titre de l'info-bulle enrichie de l'item (prend le pas sur is_tooltip) |
is_super_tooltip_text | string | "" | Texte de l'info-bulle enrichie de l'item (balisage riche accepté) |
is_super_tooltip_image | string | "" | Image de l'info-bulle enrichie de l'item |
il_accent | long | -1 | Accent de la colonne : la barre au-dessus d'elle et son compteur le prennent, jamais ses cartes (-1 = celui du composant) |
il_back_color | long | -1 | Fond de la colonne, en RGB(r,v,b) (-1 = ce que donne le thème) |
il_text_color | long | -1 | Couleur du texte de la colonne (-1 = ce que donne le thème) |
il_back_color_hover | long | -1 | Fond de l'en-tête de la colonne sous le pointeur (-1 = ce que donne le thème). Les couleurs d'une colonne s'arrêtent à ses cartes |
il_text_color_hover | long | -1 | Couleur du texte de l'en-tête de la colonne sous le pointeur (-1 = ce que donne le thème) |
Propriétés d'une carte — n_pbt_kanban_card #
| Propriété | Type | Défaut | Rôle |
|---|---|---|---|
is_title | string | "" | Titre de la carte, en gras. Accepte le balisage riche. Vide, la carte montre sa clé |
is_text | string | "" | Texte sous le titre, coupé après quatre lignes (balisage accepté). Affiché tant que is_card_template est vide |
is_tags | string | "" | Étiquettes, séparées par des virgules : Bug, UI. Chacune est une pastille colorée par is_tag_tones |
is_assignee | string | "" | La personne à qui la carte est confiée : un avatar rond avec ses initiales, de la même couleur à chaque chargement, le nom en info-bulle |
is_due | string | "" | Échéance, aaaa-mm-jj ("" : aucune) : rouge une fois dépassée, orange le jour même, jamais dans une colonne ib_done. Une date qui n'en est pas une est refusée : l'ancienne reste, of_get_last_error du tableau dit pourquoi |
is_badge | string | "" | Petit badge en haut à droite (balisage accepté) : une estimation, un nombre, dans l'accent |
ib_visible | boolean | true | false retire la carte du tableau ; elle garde sa clé, sa colonne et sa place, et ne compte plus dans sa colonne |
ib_read_only | boolean | false | L'utilisateur ne peut ni glisser cette carte, ni la déplacer au clavier, ni demander sa suppression ; votre code la déplace toujours |
of_column ( ) → string | — | — | La clé de la colonne où est la carte maintenant — l'utilisateur a pu la déplacer. Lecture seule : une carte se déplace par of_move_card |
of_position ( ) → long | — | — | Rend la place de la carte dans sa colonne maintenant, à partir de 1 (cartes masquées comprises), 0 quand le tableau ne la contient pas |
of_row ( ) → long | — | — | Rend le numéro de ligne d'aujourd'hui, dans les lignes données à of_from_datastore, de la ligne d'où vient la carte — après un tri, un filtre ou la suppression d'autres lignes ; 0 pour une carte ajoutée à la main ou dont la ligne est partie |
is_tooltip | string | "" | Info-bulle simple affichée au survol de l'item |
is_super_tooltip_title | string | "" | Titre de l'info-bulle enrichie de l'item (prend le pas sur is_tooltip) |
is_super_tooltip_text | string | "" | Texte de l'info-bulle enrichie de l'item (balisage riche accepté) |
is_super_tooltip_image | string | "" | Image de l'info-bulle enrichie de l'item |
il_accent | long | -1 | Accent de la carte : une bande sur son bord de début, son anneau de sélection et son badge le prennent ; il passe avant la couleur d'une colonne ROLE_COLOR. -1 = celui du composant, sans bande |
il_back_color | long | -1 | Fond de la carte, en RGB(r,v,b) (-1 = ce que donne le thème) |
il_text_color | long | -1 | Couleur du texte de la carte (-1 = ce que donne le thème) |
il_back_color_hover | long | -1 | Fond de la carte sous le pointeur (-1 = ce que donne le thème) |
il_text_color_hover | long | -1 | Couleur du texte de la carte sous le pointeur (-1 = ce que donne le thème) |
Trois lectures de la poignée, en lecture seule : of_column() rend la clé de la colonne où est la carte maintenant, of_position() sa place dans cette colonne à partir de 1 (0 si le tableau ne la contient pas), of_row() le numéro de sa ligne dans le DataStore (0 pour une carte ajoutée à la main). Une carte se déplace par of_move_card du tableau.
Méthodes #
| Méthode | Rôle | |
|---|---|---|
of_add_card (string as_key, string as_column, string as_title) | Ajoute une carte au bas d'une colonne. Sa clé est unique sur tout le tableau. Rend 0 une fois ajoutée, -5 pour une clé vide, contenant / ou ` | , déjà prise (une carte d'un DataStore comprise), ou une colonne inconnue, -2` quand le composant n'est pas créé |
of_add_column (string as_key, string as_title) | Ajoute une colonne à droite du tableau. Rend 0 une fois ajoutée, -5 pour une clé vide, contenant / ou ` | , ou déjà prise, -2` quand le composant n'est pas créé |
of_card (string as_key) | Rend la poignée d'une carte (créée au premier accès, libérée quand la carte est retirée) | |
of_clear ( ) | Vide le tableau : colonnes, cartes (celles d'un DataStore comprises) et leurs poignées ; les options restent. Rend 0 une fois appliqué, -2 quand le composant n'est pas créé | |
of_clear_cards ( ) | Retire toutes les cartes et leurs poignées, garde les colonnes : pour recharger les cartes. Rend 0 une fois appliqué, -2 quand le composant n'est pas créé | |
of_clear_selection ( ) | Ne laisse aucune carte sélectionnée : ue_selection_changed suit avec une clé vide ; rien de sélectionné, rien n'est levé. Rend 0 une fois appliqué, -2 quand le composant n'est pas créé | |
of_column (string as_key) | Rend la poignée d'une colonne (créée au premier accès, libérée quand la colonne est retirée) | |
of_from_datastore (datastore ads) | Fait une carte de chaque ligne du DataStore (voir plus haut). Un second chargement met les cartes à jour en place avec une clé ROLE_KEY, les refait avec la clé RowID ; les cartes des lignes parties s'en vont, celles ajoutées à la main restent ; une ligne non chargée est nommée par of_get_last_error. Rend 0 une fois chargé, -5 quand le DataStore n'est pas valide ou n'a pas de colonne, -2 quand le composant n'est pas créé | |
of_from_datastore (datawindow adw) | La même chose depuis les lignes d'un DataWindow — celui que l'utilisateur voit à côté : ib_write_back écrit dans ce DataWindow. Rend 0 une fois chargé, -5 quand le DataWindow n'est pas valide, n'a pas de colonne ou ne peut pas partager ses lignes (ShareData), -2 quand le composant n'est pas créé | |
of_from_datastore (datawindowchild adwc) | La même chose depuis les lignes d'un DataWindowChild (une liste déroulante DataWindow, un état imbriqué), écrit en retour par ib_write_back. Rend 0 une fois chargé, -5 quand il n'est pas valide, n'a pas de colonne ou ne peut pas partager ses lignes (ShareData), -2 quand le composant n'est pas créé | |
of_get_field (string as_key, string as_field) | Lit un champ d'une carte, en direct : un des vôtres, une colonne de son DataStore ou un champ intégré (column_title, initials…). Une chaîne vide quand elle n'en a pas | |
of_get_last_error ( ) | Pourquoi le dernier appel a échoué : une méthode qui a rendu -5 ou -4, une date refusée (is_due, is_today), les lignes qu'un chargement a laissées de côté, par leur numéro. Vidée par chaque appel ; sinon la dernière erreur de la bibliothèque | |
of_get_layout ( ) | Ce que l'utilisateur a arrangé, en JSON : {"columns":[{"key":"todo","collapsed":false},...]} — chaque colonne dans son ordre (masquées comprises), avec son repli. À enregistrer puis à rendre à of_set_layout. Titres, limites et cartes sont à vous : pas dedans. Lu en direct | |
of_map (string as_role, string as_column) | Donne un rôle à une colonne du DataStore (ROLE_KEY, ROLE_COLUMN, ROLE_TITLE, ROLE_TEXT, ROLE_TAGS, ROLE_ASSIGNEE, ROLE_DUE, ROLE_BADGE, ROLE_COLOR, ROLE_ORDER). Après of_from_datastore, les lignes sont relues en place : une carte déplacée reste où elle a été lâchée et garde ses drapeaux et sa poignée. Une colonne vide rend le rôle à la colonne qui porte son nom. Une carte que votre code a retirée ne revient pas. Rend 0 une fois posé, -5 pour un rôle inconnu ou une colonne que le DataStore n'a pas, -2 quand le composant n'est pas créé | |
of_move_card (string as_key, string as_column, long al_position) | Déplace une carte vers une colonne, à une place comptée à partir de 1 (au-delà de la dernière : à la fin), comme un glisser : question avec ib_veto_moves, puis ue_card_moved, et, avec ib_write_back, le DataStore écrit avant le déplacement. Rend 0 une fois déplacée (ou déjà à cette place : rien n'est levé), -4 quand ue_card_moving a refusé, que le DataStore a refusé la nouvelle colonne ou un rang (la carte reste, ue_write_back_failed, of_get_last_error dit pourquoi) ou que le tableau attend la page (un appel depuis une minuterie pendant une lecture : ni la question ni l'écriture ne peuvent se faire), -5 pour une carte ou une colonne inconnue, -2 quand le composant n'est pas créé | |
of_move_column (string as_key, long al_position) | Déplace une colonne à une place comptée à partir de 1 parmi toutes les colonnes, masquées comprises (au-delà de la dernière : la dernière), comme un glisser de son en-tête : question avec ib_veto_moves, puis ue_column_moved et ue_layout_changed. Ni ib_reorderable ni ib_read_only n'arrêtent votre code. Rend 0 une fois déplacée (ou déjà à cette place : rien n'est levé), -4 quand ue_column_moving a refusé, -5 pour une colonne inconnue, -2 quand le composant n'est pas créé | |
of_reload_row (long al_row) | Renvoie au tableau une ligne du DataStore d'of_from_datastore, relue maintenant, après que votre code l'a changée ; sa carte est mise à jour en place (drapeaux, champs et poignée restent) et suit sa colonne et son rang. Rend 0 une fois envoyée, -5 quand rien n'est lié, que la ligne n'existe pas, que sa clé est tenue par une carte ajoutée à la main, que sa valeur de colonne est vide ou que sa valeur ROLE_KEY n'est plus la clé de sa carte — une clé est une identité : après un Update qui donne les clés, rechargez par of_from_datastore (of_get_last_error le dit, rien n'a changé), -2 quand le composant n'est pas créé | |
of_remove_card (string as_key) | Retire une carte et libère sa poignée ; la retirer sélectionnée vide la sélection. Rend 0 une fois retirée, -5 pour une carte inconnue, -2 quand le composant n'est pas créé | |
of_remove_column (string as_key) | Retire une colonne et toutes ses cartes, avec leurs poignées. Rend 0 une fois retirée, -5 pour une colonne inconnue, -2 quand le composant n'est pas créé | |
of_reset ( ) | Vide le tableau, oublie le DataStore et remet chaque propriété à sa valeur par défaut. Rend 0 une fois appliqué, -2 quand le composant n'est pas créé | |
of_select_card (string as_key) | Sélectionne une carte comme un clic, sans déplacer la vue (comme SelectRow d'un DataWindow), et ue_selection_changed suit. Rend 0 une fois sélectionnée (ou déjà sélectionnée : rien n'est levé), -5 pour une carte inconnue ou non dessinée (masquée, dans une colonne repliée ou masquée, hors de la recherche, au-delà du plafond de démonstration), -2 quand le composant n'est pas créé | |
of_selected_key ( ) | La clé de la carte sélectionnée, quel que soit qui l'a sélectionnée ; vide si aucune. Lue en direct | |
of_set_field (string as_key, string as_field, string as_value) | Donne à une carte un champ à vous, pour is_card_template ; il passe avant une colonne du DataStore du même nom. Un nom de champ : lettres, chiffres et _, sans chiffre en tête. Rend 0 une fois posé, -5 pour une carte inconnue ou un nom qui n'en est pas un, -2 quand le composant n'est pas créé | |
of_set_layout (string as_layout_json) | Rend une disposition lue par of_get_layout ou reçue par ue_layout_changed : les colonnes qu'elle nomme dans son ordre, puis les autres dans le leur, chacune avec son repli ; une colonne inconnue du tableau est ignorée. ue_layout_changed est levé une fois si quelque chose a changé (ni ue_column_moved ni ue_column_toggled : elle remet un état). Rend 0 une fois appliquée, -5 quand le texte est vide ou n'est pas un objet JSON, -2 quand le composant n'est pas créé |
Événements #
| Événement | Déclenché quand |
|---|---|
ue_card_moved (string as_key, string as_from_column, string as_to_column, long al_position, long al_from_position) | Une carte a été déplacée : glissée, déplacée au clavier, ou par votre code (of_move_card). Les deux clés de colonne (la même pour un déplacement dans une colonne), al_position sa place dans la colonne d'arrivée et al_from_position celle qu'elle a quittée, à partir de 1. La carte est déjà en place ; avec ib_write_back, le DataStore est déjà écrit |
ue_card_moving (string as_key, string as_from_column, string as_to_column, long al_position) → boolean | Annulable, posé avant un déplacement, seulement quand ib_veto_moves = true : glisser, clavier et of_move_card. Renvoyer FALSE laisse la carte où elle est. C'est l'endroit d'une limite stricte : of_column(as_to_column).of_visible_count() >= il_limit |
ue_card_clicked (string as_key) | Une carte a été cliquée (et sélectionnée). Pas à la fin d'un glisser |
ue_card_opened (string as_key) | Double-clic sur une carte, ou Entrée : ouvrez votre éditeur |
ue_card_rclicked (string as_key, long al_x, long al_y) | Clic droit sur une carte (sélectionnée d'abord). al_x, al_y sont des pixels d'écran ; pour un menu PowerBuilder, PopMenu(PointerX(), PointerY()) de votre fenêtre |
ue_column_moved (string as_key, long al_from, long al_to) | Une colonne a été déplacée (ib_reorderable) : son en-tête glissé, Ctrl + Maj + Gauche / Droite, ou votre code (of_move_column). al_from et al_to sont ses places parmi toutes les colonnes, masquées comprises, à partir de 1. La colonne est déjà en place ; ue_layout_changed suit |
ue_column_moving (string as_key, long al_from, long al_to) → boolean | Annulable, posé avant qu'une colonne bouge, seulement quand ib_veto_moves = true (le même opt-in que les cartes) : glisser de l'en-tête, clavier et of_move_column. Renvoyer FALSE laisse la colonne où elle est, et of_move_column rend -4 |
ue_column_rclicked (string as_key, long al_x, long al_y) | Clic droit sur l'en-tête d'une colonne. Pixels d'écran, comme ue_card_rclicked |
ue_column_toggled (string as_key, boolean ab_collapsed) | Une colonne s'est repliée (ab_collapsed = TRUE) ou ouverte : son chevron, un double-clic sur sa bande, le clavier sur son en-tête (Entrée ou Espace replient ou ouvrent, + ouvre, - replie), ou son ib_collapsed posé par votre code |
ue_delete_requested (string as_key) | Suppr a été pressée sur la carte sélectionnée. Le tableau ne retire rien : of_remove_card une fois votre application d'accord. Jamais sur une carte ou un tableau en lecture seule |
ue_layout_changed (string as_layout_json) | La disposition a changé : une colonne déplacée ou repliée, par l'utilisateur ou par votre code, ou of_set_layout. as_layout_json est la disposition entière, telle que la rend of_get_layout : enregistrez-la |
ue_new_requested (string as_column, string as_title) | L'utilisateur demande une nouvelle carte dans une colonne : son bouton + Ajouter une carte, la touche Inser ou un double-clic dans sa partie vide ; as_title est le titre tapé dans le champ d'ajout rapide (ib_quick_add), vide sinon. Le tableau n'ajoute rien : of_add_card, après votre propre boîte de dialogue si vous voulez |
ue_selection_changed (string as_from_key, string as_key) | La carte sélectionnée a changé : clic, clavier, votre code (of_select_card, of_clear_selection), ou la carte sélectionnée a quitté le dessin (retirée, masquée, repliée, hors recherche : as_key est alors vide) |
ue_write_back_failed (string as_key, string as_col, string as_value, string as_reason) | ib_write_back : le DataStore a refusé la nouvelle colonne d'une carte déplacée (une valeur que sa colonne ne tient pas, une ligne supprimée depuis le chargement). Un rang refusé aussi (as_reason commence alors par « the rank of row »). Rien ne reste écrit : ce qui l'était est remis. La carte n'a pas bougé (le DataStore est écrit avant le déplacement), ue_card_moved n'est pas levé et of_move_card rend -4 |
ue_ready ( ) | Le composant a fini de charger ; tout ce qui a été envoyé avant a été rejoué |
ue_runtime_missing ( ) | Le runtime WebView2 est absent : le composant reste vide |
ue_bg_color (long al_color) | Le composant a calculé sa couleur de fond de thème ; l'userobject l'a déjà adoptée (backcolor) |
Clavier et souris #
- Glisser une carte : au-delà de 5 pixels, un fantôme suit le pointeur, la colonne visée s'éclaire et une barre d'accent montre où la carte tombera ; le tableau et la colonne défilent près de leurs bords, et continuent tant que le pointeur y reste. Échap annule.
- Flèches : la carte au-dessus, au-dessous, ou au même rang dans la colonne voisine ; une colonne repliée, ou qui ne dessine aucune carte, est atteinte par son en-tête. Début / Fin : la première, la dernière de la colonne.
- Ctrl + Haut / Bas monte ou descend la carte dans sa colonne ; Ctrl + Gauche / Droite la passe dans la colonne voisine ouverte, au même rang (une colonne repliée est sautée ; Espace puis les flèches s'y arrêtent). Lu de droite à gauche, Gauche et Droite s'inversent.
- Espace soulève la carte sélectionnée : les flèches la promènent (une barre montre où elle tombera), Espace ou Entrée la pose — la même question et la même écriture qu'un glisser —, Échap la remet en place. Un lecteur d'écran entend chaque étape.
- Les en-têtes sont toujours atteignables : Haut sur la première carte, Gauche / Droite d'un en-tête à l'autre ; sur un en-tête, Entrée ou Espace replie ou rouvre la colonne, + la rouvre, - la replie, Bas revient à la première carte.
- Entrée ou double-clic ouvre la carte, Suppr demande sa suppression, Inser demande une nouvelle carte dans la colonne (sur une carte ou un en-tête), clic droit sur une carte ou un en-tête : son événement.
- Le tableau est un seul arrêt de Tab : la carte sélectionnée le prend, sinon la première carte, sinon le premier en-tête.
- Avec
ib_reorderable: glisser l'en-tête d'une colonne la déplace (une barre verticale montre où elle tombera, Échap annule) ; Ctrl + Maj + Gauche / Droite, sur une carte ou sur un en-tête, déplace sa colonne, inversé de droite à gauche.
Exemples #
Une limite stricte et une règle de passage #
// Once, after the board is built : ask before each move
uo_board.ib_veto_moves = true
// event ue_card_moving of uo_board : a card reaches Done only from Review
if as_to_column = "done" and as_from_column <> "review" then return false
// and a column past its limit takes no more card (what its header counts :
// the visible cards)
if as_to_column <> as_from_column then
if this.of_column(/*key*/ as_to_column).il_limit > 0 and this.of_column(/*key*/ as_to_column).of_visible_count() >= this.of_column(/*key*/ as_to_column).il_limit then return false
end if
return true
Retrouver ses colonnes au prochain lancement #
// Once, after the board is built : the user may move the columns
uo_board.ib_reorderable = true
// The layout stored at the last start, if any
uo_board.of_set_layout(/*layout_json*/ ProfileString(gs_ini, "board", "layout", ""))
// event ue_layout_changed of uo_board : store every change
SetProfileString(gs_ini, "board", "layout", as_layout_json)
Ouvrir une carte dans votre fenêtre #
// event ue_card_opened of uo_board : the row of the card, edited in your window
OpenWithParm(w_task_edit, uo_board.of_card(/*key*/ as_key).of_row())
// The row may have changed : the card follows it
uo_board.of_reload_row(/*row*/ uo_board.of_card(/*key*/ as_key).of_row())
Un tableau d'équipe : points, largeur partagée, ajout rapide #
// The estimate of a card, a field of our own
uo_board.of_set_field(/*key*/ "t1", /*field*/ "points", /*value*/ "5")
// Every header : its cards, its limit, the sum of the points of its cards
uo_board.is_count_template = "{count}{?limit}/{limit}{/limit} - {sum:points} pts"
// The open columns share the width of the board
uo_board.ii_column_width = 0
// + Add a card opens a title field at the foot of the column
uo_board.ib_add_button = true
uo_board.ib_quick_add = true
// event ue_new_requested of uo_board : the card typed, with a key of ours
uo_board.of_add_card(/*key*/ "new" + String(Cpu()), /*column*/ as_column, /*title*/ as_title)
Bonnes pratiques #
- Peu de colonnes, nommées par l'étape et non par la personne : cinq ou six se lisent d'un coup d'œil.
- Une limite de travail en cours sur les colonnes actives : c'est elle qui fait d'un tableau un outil de pilotage.
- Enregistrez dans
ue_card_moved(ou laissezib_write_backécrire le DataStore) : le tableau montre le nouvel état avant que la base ne le sache. - Un modèle court : deux lignes de corps suffisent, le détail va dans votre fenêtre d'édition.
- Des étiquettes à ton constant :
Bugtoujours en rouge, d'une fenêtre à l'autre. - Des clés qui ne sont pas des nombres pour vos cartes à la main, sur un tableau alimenté par un DataStore : une carte de clé
12empêche la ligne de RowID 12 d'être chargée (of_get_last_errorle dit). - Une clé de la donnée (
ROLE_KEY) quand les lignes sont relues : avec la clé RowID, un nouveauof_from_datastorerefait les cartes.
Hérité du socle commun #
Ces membres existent sur tous les composants visuels — ils ne sont pas propres à celui-ci. Ils sont détaillés une seule fois, dans les chapitres transverses ; cette table dit seulement où les lire.
| Membres | Rôle | Détaillé dans |
|---|---|---|
of_count · of_keys_at · of_has | Parcourir ce que le composant contient | 3.2 Les items |
of_reset | Remettre le composant à zéro | 3.6 Remettre un composant à zéro : of_reset() |
of_register_shortcut · of_clear_shortcuts | Raccourcis clavier du composant | 3.5 Les raccourcis clavier |
of_is_created · of_is_ready · of_get_last_error | S'il est né, s'il est prêt, ce qui a échoué | 3.7 Diagnostic |
of_save_as_png · of_save_as_jpg | Exporter le rendu en image | 3.8 Exporter le rendu en image |
of_set_redraw | Grouper les modifications en un seul repaint | 3.10 Bonnes pratiques |
of_preload_icons | Icônes affichées sans délai | Affichage instantané : of_icon |
of_set_translation | Traduire un libellé du composant | 5.2 Adapter un libellé : of_set_translation |
of_focus_webview | Donner le focus au composant | 6.4 Clavier et focus |
of_print · of_print_to_pdf | Imprimer, ou écrire un PDF | 6.9 Imprimer |
of_set_property · of_get_property · of_component_name | Piloter une propriété par son nom | 3.1 Le moteur de propriétés |
is_accessible_name · is_accessible_description | Le nom et la description que dit un lecteur d'écran | 3.4 Propriétés et events optionnels |
Deux aides ne sont pas héritées : of_icon et of_escape_markup vivent sur n_pbt_utils. Déclarez-en une — n_pbt_utils lnv_utils, rien à créer — et appelez-les dessus.