Changelog — ApocalyInterfaceLib
Phase 7 — Repro UIs + build + doc
Commit 4 — Build Maven local + documentation complète (2026-05-23)
Build & distribution
build.gradle— publication Maven complétée :groupId,artifactId,versionet métadonnées POM (name,description) explicitement déclarés dans le blocpublishing. Coordonnées publiées :ca.tawess123.apocalyinterface:apocalyinterfacelib:1.0.0. La tâche./gradlew publishToMavenLocalétait déjà fonctionnelle via le pluginmaven-publish; les coordonnées sont maintenant lisibles sans ambiguïté dans le POM généré.src/main/resources/META-INF/mods.toml— conforme §7.2 (vérifié) :displayTest="IGNORE_ALL_VERSION", dépendances Forge et Minecraft enside="CLIENT".
Documentation — audit et trous comblés
Audit widget/conteneur vs docs reference : aucun widget ni conteneur manquant.
Fichiers créés :
docs/README.md— vue d'ensemble du projet, démarrage rapide, structure de la docdocs/guide/01-installation.md— lignes exactesbuild.gradle(mavenLocal()+fg.deobf(...)) et blocmods.tomlpour un mod consommateur ; guide reproductible pour brancher le mod Clan sur la libdocs/guide/02-premier-ecran.md— exemple complet copiable de A à Z basé surClanHubDemoScreen: classe, ouverture depuis packet S2C, refresh, clés i18n requisesdocs/guide/03-widgets.md— catalogue commenté des 11 widgets +visibleIf, avec liens versreference/widgets/docs/guide/04-layout.md— système de layout : Column, Row, Card, Grid, Spacer, Divider, ScrollableColumn ; tableau récapitulatif ; note scroll global automatiquedocs/guide/05-i18n.md— guide i18n complet : structure de fichiers, conventions de nommage des clés, usage dans chaque type de widget, fallbackLocaleResolverdocs/reference/data-source.md— référence manquante : interfaceDataSource<T>, source statique vs lambda, widgets acceptant un DataSource, pattern avecupdate(), scope v1/v2
Critère de réussite
./gradlew publishToMavenLocalpublie le JAR avec les coordonnéesca.tawess123.apocalyinterface:apocalyinterfacelib:1.0.0dans le dépôt Maven local. Un mod consommateur peut ajoutermavenLocal()+fg.deobf("ca.tawess123.apocalyinterface:apocalyinterfacelib:1.0.0")dans sonbuild.gradleet le bloc[[dependencies.monmod]]dansmods.toml— la lib charge et l'API publique est accessible. La documentation couvre tous les widgets, layouts, screens et concepts clés.
Commit 3 — visibleIf : visibilité conditionnelle sur tous les widgets (2026-05-23)
Principe
visibleIf(boolean) est un raccourci de builder qui conditionne la visibilité d'un widget.
Un widget invisible prend zéro pixel dans le layout — ni rendu, ni compté dans la hauteur, et les widgets suivants remontent. Tout gap autour du widget masqué est également absorbé.
API publique — Interface Widget
api/widget/Widget.java— ajout de la méthodedefault boolean isVisible()retournanttrue. Contrat : les conteneurs appellentisVisible()avant toute opération de layout ou de rendu sur leurs enfants.
API publique — Widgets (builder)
Tous les widgets suivants exposent désormais .visibleIf(boolean) dans leur builder :
Label,Button,KeyValueRow,ProgressBar,SearchFieldItemIcon,TabBar,ScrollableList<T>,ClickableList<T>,SlotGrid
Chaque widget stocke le booléen et override isVisible(). La valeur par défaut est true — aucun écran existant ne change de comportement (rétrocompatibilité totale).
API publique — Conteneurs
Column,Card—visible(boolean)fluent sur l'instance ; logique mise à jour pour sauter les enfants invisibles dansgetPreferredHeight,render,mouseClicked,mouseScrolled,keyPressed,charTyped. Le gap n'est ajouté qu'entre deux widgets visibles consécutifs.Row— idem ; la largeur disponible est redistribuée entre les enfants visibles uniquement (childWidthrecalculé surcountVisible()).ScrollableColumn—visibleIf(boolean)dans leBuilder;render,mouseClicked,mouseScrolledetsyncControllertravaillent sur la liste filtréevisibleChildren().
Avertissement sécurité (documenté explicitement)
visibleIf est un confort d'affichage — pas de sécurité. Masquer un bouton côté client ne protège aucune action serveur. Toute action sensible doit être revérifiée côté serveur.
Mod démo
VisibilityDemoScreen.java(nouveau) — toucheV: 3 boutons (toggle, cible, dessous). Clic sur toggle → cible disparaît et bouton dessous remonte immédiatement. Clic à nouveau → réapparaît.KeyBindings.java— ajout keybindV(open_visibility) ouvrantVisibilityDemoScreen- Lang files
en_us/fr_ca— 7 nouvelles clésvisibility.*
Documentation
docs/reference/widgets/visibleif.md— référence complète : principe, API par type, comportement du gap, pattern toggle avecinit(), avertissement sécurité mis en évidence, démo in-game
Critère de réussite
Touche
Ven jeu → écran Démo visibleIf. Clic « Masquer » → bouton central disparaît, bouton en dessous remonte (zéro gap orphelin). Clic « Afficher » → bouton réapparaît. Tous les autres écrans (J,M,C,R,H) inchangés.
Commit 2 — ScrollableColumn : zone scrollable interne (2026-05-23)
Nouveauté
api/layout/ScrollableColumn— nouveau conteneur à hauteur fixe qui scrolle ses enfants en interne (molette, scissor, mini scrollbar). RéutiliseScrollController(1 enfant = 1 ligne). LefixedHeightdoit être un multiple exact de(hauteur_enfant + gap)pour éviter tout enfant à moitié coupé.
Démo mise à jour
ClanHubDemoScreen— pattern card sticky +ScrollableColumnde boutons. 9 boutons, 5 visibles (fixedHeight = 116 px = 5×20+4×4).ScrollableColumnconservée en champ final → scroll préservé au refresh.
Documentation
docs/reference/layout/scrollable-column.md— ajouté.
Commit 1 — Color overrides sur tous les widgets publics (2026-05-23)
Principe
Chaque option est optionnelle. Si non précisée, le widget lit la constante par défaut dans
ApocalyColors — aucun écran existant ne change d'apparence (rétrocompatibilité totale).
API publique — Widgets
-
api/widget/Label.java— ajout.color(int argb): surcharge directe de la couleur du texte, complémentaire aux raccourcis.accent()/.muted()/.title()existants. -
api/widget/KeyValueRow.java— ajout.keyColor(int argb)(défaut :TEXT) et.valueColor(int argb)(défaut :ACCENT) : chaque côté de la ligne est colorable indépendamment. -
api/widget/Button.java— ajout.borderColor(int argb)(bordure au repos actif) et.accentColor(int argb)(bordure + texte au survol actif). La lib dérive automatiquement les états désactivés en appliquant un facteur ×0,4 sur R, G, B (alpha préservé)..textColor(int)existant est conservé et compatible. -
api/widget/ProgressBar.java— ajout.backgroundColor(int argb)(défaut :PANEL_BG)..fillColor(int)existant est conservé.
API publique — Layout
api/layout/Card.java— ajout.borderColor(int argb)fluent (défaut :SUB_BORDER) : surcharge la bordure 1 px du sous-panneau. ImportApocalyColorsajouté.
API publique — Screen
api/screen/ApocalyScreen.java— ajout de deux setters protégés finals :borderColor(int argb)ettitleColor(int argb), à appeler dans le constructeur de la sous-classe. Stockés sur l'instance, ré-appliqués à chaqueinit()etupdate().
Core interne
core/render/PanelRenderer.java— restructuration : les versions sans couleur délèguent aux nouvelles surchargesdrawPanel(..., borderColor, titleColor)etdrawSubPanel(..., borderColor). Rétrocompatibilité totale des appelants existants.core/layout/PanelHost.java— ajout des champsborderColor/titleColor(-1= thème par défaut) et des setterssetBorderColor(int)/setTitleColor(int); le rendu utilise la surcharge colorée dePanelRenderer.
Mod démo
DemoScreen.java— ajout section « Surcharge de couleurs » :Label.color(0xFF00CCFF)— cyan vifButtonpar défaut (repère orange) côte à côte avecButton.accentColor(SUCCESS)(vert)Card.borderColor(0xFF7755FF)(bordure violette) contenant unKeyValueRowavec.keyColor(MUTED_TEXT)et.valueColor(0xFFFFCC44)(or)
- Lang files
en_us/fr_ca— 5 nouvelles cléscolor.*
Documentation
docs/reference/widgets/label.md—.color(int)ajouté au builderdocs/reference/widgets/key-value-row.md—.keyColor/.valueColorajoutésdocs/reference/widgets/button.md—.borderColor/.accentColorajoutés, tableau des états mis à jour avec la logique de dérivationdocs/reference/widgets/progress-bar.md—.backgroundColorajoutédocs/reference/layout/card.md—.borderColorajoutédocs/reference/screen/apocaly-screen.md— section « Surcharge de couleurs du panneau » ajoutée
Critère de réussite
Touche
Jen jeu → faire défiler jusqu'à la section « Surcharge de couleurs ». Vérifier : label cyan visible, bouton vert au survol (≠ orange par défaut), bordure violette de la Card. Tous les autres écrans (hub, marchand, container, refresh) affichent toujours les couleurs orange / cyan du thème — aucune régression.
Phase 6 — DataSource + refresh (2026-05-23)
Commit 1 — update() + démo refresh (2026-05-23)
API publique (api/screen/)
api/screen/ApocalyScreen.java— ajout depublic final void update(): relancebuildLayout()et recalcule le layout sans fermer ni recréer l'écran (SPEC §6.3). La position de défilement courante est préservée automatiquement viaPanelHost.getScrollOffset()/setScrollOffset()— exactement le même mécanisme que la persistance du scroll au resize. LesDataSourcestatiques (DataSource.of(val)) capturent la valeur fraîche à chaquebuildLayout: aucun mécanisme supplémentaire n'est requis pour afficher des données mises à jour.
DataSource (§6.2) — confirmé conforme
DataSource.of(value)présent depuis Phase 3, conforme à la spec.Label,KeyValueRow,ProgressBaracceptent tous unDataSource<T>via leur builder depuis Phase 3–4 — aucune modification nécessaire.
Mod démo (client/)
RefreshDemoScreen.java(nouveau) — écran de démonstration Phase 6 :- Champs d'instance
pointsetmembresmis à jour à chaque clic du bouton Cardavec 3KeyValueRowet unProgressBar(membres/10) — valeurs recréées viaDataSource.of(...)à chaquebuildLayoutappelé parupdate()- Bouton « Simuler refresh » :
points += 50; membres = min(membres+1,10); update() ScrollableListde 12 membres (5 lignes visibles) pour valider que le scroll est préservé au refresh
- Champs d'instance
KeyBindings.java— ajout keybindR(open_refresh) ouvrantRefreshDemoScreen- Lang files
en_us/fr_ca— clésrefresh.*+key.open_refresh
Critère de réussite
Touche
Ren jeu → écran Phase 6. Clic sur « Simuler refresh » → Points et barre de progression se mettent à jour instantanément, sans fermer l'écran. Faire défiler la liste jusqu'en bas, puis cliquer refresh → la liste reste en position (scroll préservé).
Documentation
docs/reference/screen/apocaly-screen.md— ajout section « Refresh dynamique (§6.3) »update()dans le tableau API + note dans les « Notes »
Phase 5 — Container + slots vanilla (2026-05-23 →)
Commit 1 — Spacer + Divider (2026-05-23)
API publique (api/layout/)
api/layout/Spacer.java— espace vide de hauteur configurable (SPEC §4.2) : factorySpacer.of(int height).renderne fait rien ;getPreferredHeightretourne la hauteur configurée. Complète le gap global d'uneColumnpour un espacement ponctuel entre groupes logiques.api/layout/Divider.java— ligne de séparation horizontale 1 px (SPEC §4.2) : couleur par défautApocalyColors.DIVIDER(0x55FFFFFF). FactoryDivider.create()+Divider.builder().color(int).build()pour couleur personnalisée.RenderSystem.enableBlend()appelé avant le fill (couleur semi-transparente).
Mod démo
DemoScreen.java— ajout d'unSpacer(6)+Divider+Spacer(6)entre la section Clan Hub (Phase 3) et la section ScrollableList (Phase 4), pour valider visuellement les deux widgets.
Documentation
docs/reference/layout/spacer.md— factory, comportement, note gap vs spacerdocs/reference/layout/divider.md— factory, builder color, pattern combiné avec Spacer
Commit 5 — Démo 3×3 slots (2026-05-23)
Mod démo (client/container/)
TestContainerMenu.java— ajout de 9 slots (grille 3×3) dans unSimpleContainer. Positions calculées pour s'aligner pixel-parfaitement avecSlotGrid:x = 11 + col×20,y = 32 + row×20(stride 20 px = 18 slot + 2 gap).SLOT_ORIGIN_X = 11(fond àleftPos+10= début de la zone de contenu),SLOT_ORIGIN_Y = 32(fond àtopPos+31= DIVIDER_OFFSET + 1 + CONTENT_TOP_GAP). Constantes exposées en package-private pour référence depuisTestContainerScreen.TestContainerScreen.java—buildLayoutremplacé : uniquement unSlotGridsurthis.menu.slots+screenOrigin(this.leftPos, this.topPos).
Critère de réussite
Touche
Cen jeu → 9 slots stylés Apocaly (fond noir translucide + bordure blanche) disposés en 3×3 dans le panneau, sans fond gris vanilla. Items déposés dans les slots apparaissent par-dessus les fonds.
Commit 4 — SlotGrid (2026-05-23)
API publique (api/widget/)
api/widget/SlotGrid.java— widget fond de slots vanilla (SPEC §4.3) : litslot.x/slot.ydu menu (source de vérité), dessine fondSLOT_BG18×18 px- contour 1 px
SUB_BORDERà(leftPos + slot.x - 1, topPos + slot.y - 1). Rendu dansrenderBg()— les fonds apparaissent sous les items (Forge les dessine par-dessus viaAbstractContainerScreen.render()). Builder.slots(List<Slot>)+.screenOrigin(leftPos, topPos).getPreferredHeight=maxY − minY + 18(span des fonds réels depuis les positions du menu).
- contour 1 px
API publique — Thème
api/theme/ApocalyColors— ajoutSLOT_BG = 0x80050505(fond slot, noir 50 % alpha).
Documentation
docs/reference/widgets/slot-grid.md— contrat alignement Menu = source de vérité, formule de positionnementleftPos + slot.x - 1, avertissement MenuType null (démo client-only vs production DeferredRegister), ordre de rendu critique
Commit 3 — ApocalyContainerScreen<T> (2026-05-23)
API publique (api/screen/)
api/screen/ApocalyContainerScreen.java— classe de base pour les écrans à inventaire (SPEC §4.1) : étendAbstractContainerScreen<T extends AbstractContainerMenu>.imageWidth/imageHeightfixés dans le constructeur avantsuper.init()—AbstractContainerScreen.init()calculeleftPos/topPosà partir de ces valeurs ; les fixer après causerait un désalignement panneau/slots. Méthode abstraitebuildLayout(Row root)— la Row racine couvre la zone de contenu sous le divider.renderBg()dessine le panneau Apocaly à(leftPos, topPos)— même origine que les slots vanilla, garantissant l'alignement pixel-parfait.renderLabels()vide (titre déjà dans le panneau). Propagation événements : layout en priorité, puis vanilla (slots).
Mod démo (client/container/)
TestContainerMenu.java—AbstractContainerMenuminimal (MenuType null— client-only, pas de réseau), sans slots.stillValid → true,quickMoveStack → EMPTY.TestContainerScreen.java—ApocalyContainerScreen<TestContainerMenu>, panneau 220 × 120,buildLayout: une colonne avec unLabelet unKeyValueRowindiquant « 0 slots (commit 5) ».KeyBindings.java— ajout keybindC(open_container) ouvrantTestContainerScreen.- Lang files
en_us/fr_ca— cléscontainer.title,container.label.info,container.row.slots,open_container.
Critère de réussite
Touche
Cen jeu → panneau Apocaly centré (fond translucide, bordures jaunes, barre de titre), sans fond gris vanilla visible derrière.
Documentation
docs/reference/screen/apocaly-container-screen.md— pipeline de rendu, pi ège initialisation, contrat Menu = source de vérité des positions de slots
Commit 2 — Grid (2026-05-23)
API publique (api/layout/)
api/layout/Grid.java— grille à N colonnes (SPEC §4.2) : distribution équitable de largeur identique àRow, hauteur de cellule = max des hauteurs préférées. Nombre de lignes calculé par division entière avec plafond(nbEnfants + cols - 1) / cols— une grille de 5 enfants sur 3 colonnes produit bien 2 lignes. Builder.columns(int)(obligatoire),.gap(int),.add(Widget). Propagation événements :mouseClicked/mouseScrolledpar hit-test de cellule ;keyPressed/charTypedséquentiels sur tous les enfants.
Mod démo
DemoScreen.java— ajout section « Grille » :Grid3 colonnes avec 5ItemIcon(Diamant, Émeraude, Or, Fer, Charbon) pour valider explicitement le cas d'un nombre d'enfants non multiple du nombre de colonnes (2 lignes, dernière incomplète).- Lang files
en_us/fr_ca— clésection.grid.
Documentation
docs/reference/layout/grid.md— distribution de largeur/hauteur, division plafond, propagation d'événements, note SlotGrid vs Grid
Bonus — Écrans multi-panneaux (hors roadmap SPEC) (2026-05-22)
Commit 2 — ApocalyMultiScreen + démo Marchand (2026-05-22)
API publique (api/screen/)
api/screen/PanelConfig.java— descripteur d'un panneau : titre (Component), largeur (px) et fonction de layout (Consumer<Column>). Constructeur statiquePanelConfig.of(title, width, layout).api/screen/ApocalyMultiScreen.java— nouvelle classe de base pour les écrans à N panneaux côte à côte : méthode abstraitebuildPanels()retournantList<PanelConfig>. Comportement : groupe centré horizontalement, hauteur partagée (max des hauteurs désirées, clampée à l'écran), espacementPANEL_GAPentre panneaux, scroll indépendant par panneau persisté entre lesinit(). Propagation d'événements : premier consommateur de la liste remporte (mouseClicked / mouseScrolled / keyPressed / charTyped).
API publique — Dimensions
api/theme/ApocalyDimensions— ajoutPANEL_GAP = 8 px.
Mod démo
MarchandDemoScreen.java— écran 3 panneaux : Boutique (140 px, SearchField + ClickableList 8 articles), Détails (170 px, nom dynamique + KeyValueRow prix/stock/ vendeur + ProgressBar disponibilité + 2 boutons Acheter/Vendre), Inventaire (120 px, solde accent + Row de 3 ItemIcon + KeyValueRow achats/ventes). Sélection d'un article dans la boutique met à jour le panneau détails viaonSelect → init().KeyBindings.java— ajout keybindM(open_marchand) ouvrantMarchandDemoScreen.- Lang files
en_us/fr_ca— 20 nouvelles clésapocalyinterfacedemo.marchand.*.
Documentation
docs/reference/screen/apocaly-multi-screen.md— référence complète : API, comportement layout, propagation événements, exemple 3 colonnes, notes d'usage.docs/SPEC.md §4.1— ajout deApocalyMultiScreendans les classes de base.
Commit 1 — PanelHost (refactor interne) (2026-05-22)
Core interne (core/layout/)
core/layout/PanelHost.java— encapsule toute la logique d'un panneau individuel : construction du layout (layout(screenHeight)), assignation de position (place(left, top, height)), rendu complet (fond/bordure/titre/scissor/scrollbar), propagation événements, persistance du scroll (getScrollOffset/setScrollOffset).api/screen/ApocalyScreen— refactorisé pour déléguer entièrement àPanelHost; l'API publique (buildLayout(Column), constructeurs, événements) est inchangée.
Correctif — Overflow scroll (2026-05-22)
Bug corrigé
En GUI scale « normal » (écran MC plus petit en coordonnées GUI), un écran avec 15+ widgets produisait un panneau plus haut que l'écran : le contenu débordait verticalement hors de l'affichage.
core/layout/LayoutEngine
computeMaxPanelHeight(int screenHeight)— nouvelle méthode : retournemax(60, screenHeight - 2×SCREEN_EDGE_MARGIN), équivalent duMath.min(DESIRED_H, height-8)du mod Clan.computeVisibleContentHeight(int panelHeight)— nouvelle méthode : inverse decomputePanelHeight, calcule la hauteur de la zone de contenu visible dans un panneau clampé.
api/screen/ApocalyScreen
init()— clamp la hauteur du panneau viacomputeMaxPanelHeightavant de centrer. Le décalagepixelScrollOffsetest conservé entre lesinit()(resize) et reclampé à la plage[0, max(0, total - visible)].render()— si le contenu déborde : appliqueenableScissor / disableScissorsur la zone de contenu, puis délègue àdrawScrollBar(). Sans débordement : rendu identique à avant.mouseScrolled()— les widgets enfants (ScrollableList, ClickableList) conservent la priorité ; si aucun enfant ne consomme et quemaxScroll > 0, le décalage écran est mis à jour (12 px / unité de molette).drawScrollBar()(privé) — pisteBUTTON_BORDER3 px + curseurBORDERjaune proportionnel dans la marge droite du panneau.
Documentation
docs/reference/screen/apocaly-screen.md— section « Overflow scroll » ajoutée.
Phase 4 — Widgets avancés (2026-05-22 →)
Commit 7 — TabBar (2026-05-22)
API publique (api/widget/)
api/widget/TabBar.java— barre d'onglets horizontale (SPEC §4.3) : largeur équitable par onglet, onglet actif → fondHEADER_BG+ soulignementBORDER2 px + texteTITLE, survol inactif →BUTTON_HOVER_BG+HOVER_TEXT. Record interneTab(labelKey, onSelect). Builder.tab(String, Runnable)+.activeTab(int). Clic onglet actif ignoré.activeIndexclampé à[0, tabs.size()-1].
Mod démo
DemoScreen.java— ajout section « Barre d'onglets » : 3 onglets (Membres / Stats / Items). Clic →init()relayout. Onglet 0 : ScrollableList membres ; onglet 1 : KeyValueRow victoires/défaites ; onglet 2 : Row de 3 ItemIcon.- Lang files — ajout
section.tabs,tab.membres/stats/items,tab.content.victoires/defaites(EN + FR-CA)
Documentation
docs/reference/widgets/tab-bar.md— tableau visuel des états, patterninit()pour switcher de contenu
Commit 6 — ItemIcon + Row (2026-05-22)
API publique — Nouveau conteneur de layout
api/layout/Row.java— pendant horizontal deColumn(SPEC §4.2) : distribution égale de la largeur(total − (n−1)×gap) / n, hauteur = max des enfants. PropagemouseClicked/mouseScrolled(filtre par X),keyPressed/charTyped(tous enfants).
API publique — Nouveau widget
api/widget/ItemIcon.java— item MC 16 × 16 px centré dans la zone allouée (SPEC §4.3) :renderItem+renderItemDecorationsoptionnel (count + durabilité) +renderTooltipvanilla au survol. Stack vide → rien dessiné. Builder.item(Item)/.item(ItemStack),.showCount(boolean),.showTooltip(boolean).
Mod démo
DemoScreen.java— ajout section « Icônes d'items » :Rowavec 3ItemIcon(Diamant, Émeraude, Lingot de Fer ×5 avec count).- Lang files — ajout
section.items(EN + FR-CA)
Documentation
docs/reference/layout/row.md— distribution de largeur, tableau de propagation d'événementsdocs/reference/widgets/item-icon.md— builder, comportement stack vide, usage Row
Commit 5 — SearchField + hooks keyPressed/charTyped (2026-05-22)
API publique — Interface Widget
api/widget/Widget.java— ajout de deux méthodesdefault:keyPressed(int, int, int)etcharTyped(char, int), retournantfalse(non-consommé). Contrat identique àmouseClicked.
API publique — Conteneurs de layout
api/layout/Column.java— ajoutkeyPressed/charTyped: itère tous les enfants (pas de filtre par position — les events clavier sont non-positionnés).api/layout/Card.java— idem.
API publique — Screen de base
api/screen/ApocalyScreen.java— ajoutkeyPressed/charTypedfinal: délégation àroot, puissupersi non consommé.
API publique — Nouveau widget
api/widget/SearchField.java— champ de saisie stylé Apocaly (SPEC §4.3) : wrappingEditBoxavecsetBordered(false), fondPANEL_BG, bordureBUTTON_BORDER/BORDER(focus), placeholder i18nMUTED_TEXT,onChange(Consumer<String>), rebuild préservant texte et focus si la largeur change. Taper « j » focalisé écrit « j » (événement consommé, aucun keybind déclenché).
Mod démo
DemoScreen.java— ajout section « Champ de recherche » :SearchField+Labeldynamique affichant la valeur courante (DataSource lambda).- Lang files — ajout
section.search,search.placeholder,search.value(EN + FR-CA)
Documentation
docs/reference/widgets/search-field.md— comportement focus/bordure, note filtrage v2
Commit 4 — ProgressBar (2026-05-22)
API publique (api/widget/)
api/widget/ProgressBar.java— barre de progression (SPEC §4.3) : hauteur fixe 14 px,DataSource<Float>pour valeur dynamique,.value(float)raccourci statique,.labelKey(String)i18n,.showPercent(boolean),.fillColor(int)pour couleurs sémantiques. Fond PANEL_BG, remplissage ACCENT, contour BUTTON_BORDER, texte centré TEXT.
Mod démo
DemoScreen.java— ajout section « Barres de progression » : XP 45% (ACCENT), Jobs 78% (SUCCESS), HP 20% (DANGER).- Lang files — ajout
section.progress,bar.xp,bar.jobs,bar.hp(EN + FR-CA)
Documentation
docs/reference/widgets/progress-bar.md— builder, couleurs sémantiques, constante HEIGHT
Commit 3 — ClickableList<T> (2026-05-22)
API publique (api/widget/)
api/widget/ClickableList.java— liste défilante cliquable (SPEC §4.3) : réutiliseScrollableList.RowRenderer<T>, fondHOVER_FILLavant le renderer,onSelect(Consumer<T>)au clic gauche, scroll/indicateur/scissor identiques àScrollableList. La coloration podium est laissée au mod consommateur.
Mod démo
DemoScreen.java— ajout section « Liste cliquable » : 4 lignes visibles, clic →Labeldynamique (DataSourcelambda) affiche le membre sélectionné.- Lang files — ajout
section.click_list,label.selected(EN + FR-CA)
Documentation
docs/reference/widgets/clickable-list.md— contrat, builder, note podium générique
Commit 2 — ScrollableList<T> (2026-05-22)
API publique (api/widget/)
api/widget/ScrollableList.java— liste défilante générique (SPEC §4.3) : interface imbriquéeRowRenderer<T>, builder.items/.visibleRows/.rowHeight/.rowRenderer, filtrage par index +enableScissor/disableScissor, indicateur i18nscroll.positionenMUTED_TEXTbas-droite,mouseScrolleddélégué àScrollController.
Mod démo
DemoScreen.java— ajout section « Liste défilante » : 12 membres fictifs, 5 lignes visibles, rowHeight 14 px, renderer texte simple.assets/apocalyinterfacedemo/lang/en_us.json— ajoutsection.scroll_listassets/apocalyinterfacedemo/lang/fr_ca.json— idem FR-CA
Documentation
docs/reference/widgets/scrollable-list.md— contrat, builder, RowRenderer, clés i18n
Commit 1 — ScrollController (2026-05-22)
Core interne (core/scroll/)
core/scroll/ScrollController.java— contrôleur de défilement centralisé (SPEC §5.4) :scrollOffset,totalRows,visibleRows,mouseScrolled(delta)avec clamp,canScroll(),getIndicatorText()i18n via cléapocalyinterface.scroll.position.
Assets — Lang files
en_us.json— ajoutapocalyinterface.scroll.position:"Scroll: %s/%s"fr_ca.json— ajoutapocalyinterface.scroll.position:"Défilement : %s/%s"fr_fr.json— idem FR-FR
Documentation
docs/reference/scroll-controller.md— contrat, API, comportement du clamp, clés i18n
Phase 3 — Layout + widgets de base (2026-05-21)
Bibliothèque — API publique (api/)
api/widget/Widget.java— interface racine (SPEC §4.6) :setBounds,render,getPreferredHeight,mouseClicked,mouseScrolled.setBoundsest toujours appelé avantgetPreferredHeight(contrat de layout).api/data/DataSource.java— provider statique/dynamique (SPEC §6.2) :get()+ factoryof(T).api/screen/ApocalyScreen.java— classe de base abstraite :init()/render()/mouseClicked()/mouseScrolled()enfinal,buildLayout(Column)abstraite. Largeur par défaut 240 px.api/layout/Column.java— empilage vertical,create()/withGap(int),add(Widget)chaînable, gap par défaut 4 px. ImplémenteWidget.api/layout/Card.java— sous-panneau encadré (SUB_BG+SUB_BORDER1 px), marge interneCARD_PADDING(6 px). ImplémenteWidget.api/widget/Label.java— texte mono-ligne i18n, builder :text/value/accent/muted/title/centered.api/widget/KeyValueRow.java— ligne clé (gauche,TEXT) + valeur (droite,ACCENT), builder :key/value.api/widget/Button.java— bouton 4 états (SPEC §3.6), builder :text/onClick/command/disabled/textColor.
Bibliothèque — Core interne (core/)
core/layout/LayoutEngine.java— calcul du rectangle de panneau :computePanelHeight,computePanelX,computePanelY,computeContentY.core/render/PanelRenderer.java— ajoutdrawSubPanel(gfx, x, y, w, h)pourCard.core/render/RenderUtils.java— surchargeoutline(gfx, x, y, w, h, color)à 1 px.
API publique — Thème
api/theme/ApocalyColors.java— ajout 9 constantes bouton-états (SPEC §3.6) :BUTTON_HOVER_BG,BUTTON_DISABLED_BG/HOVER_BG,BUTTON_BORDER,BUTTON_DISABLED_BORDER/HOVER_BORDER,BUTTON_TEXT,BUTTON_DISABLED_TEXT/HOVER_TEXT.api/theme/ApocalyDimensions.java— ajoutCARD_PADDING = 6.
Mod démo
DemoScreen.java— remplacé : étend désormaisApocalyScreen, plus aucun importcore/. Affiche le haut du Clan Hub : Card avec 3KeyValueRow+ 3Button.assets/apocalyinterfacedemo/lang/fr_ca.json— nouvelles clés Phase 3 (screen, rows, boutons).assets/apocalyinterfacedemo/lang/en_us.json— idem en EN-US.
Documentation
docs/reference/screen/apocaly-screen.md— référenceApocalyScreendocs/reference/layout/column.md— référenceColumndocs/reference/layout/card.md— référenceCarddocs/reference/widgets/label.md— référenceLabeldocs/reference/widgets/key-value-row.md— référenceKeyValueRowdocs/reference/widgets/button.md— référenceButton
Critère « done » Phase 3
Column/Card/Label/KeyValueRow/Buttonfonctionnels,ApocalyScreenremplaceScreenpour le mod démo, keybindJouvre un écran reproduisant le haut du Clan Hub (card d'infos + 3 boutons) sans aucun calcul de coordonnées dans le code consommateur.
Phase 2 — Theme + i18n + rendu du panneau (2026-05-20)
Bibliothèque — API publique (api/theme/)
ApocalyColors.java— palette complète ARGB (§3.2 + §3.3 du SPEC) : panneaux, bordures, texte, sémantique, podium, difficultéApocalyDimensions.java— constantes de dimensions (§3.4) : épaisseurs, hauteurs, marges, espacementsApocalyTheme.java— façade publique avec singletonDEFAULT; extensible pour la v2 (thèmes alternatifs)
Bibliothèque — Core interne (core/)
core/theme/ThemeManager.java— singleton interne retournant le thème actif (DEFAULTen v1)core/render/PanelRenderer.java—drawPanel()reproduisant l'ordre exact §3.5 : fond, 4 bordures 2 px, barre de titre, divider, titre centré avec ombrecore/render/RenderUtils.java— primitivesfill()etoutline()surGuiGraphicscore/render/TextUtils.java—ellipsize()viafont.plainSubstrByWidth+ suffixe « … »core/i18n/LocaleResolver.java— wrapComponent.translatableavec fallback gracieux (clé absente → affiche la clé brute)
Assets — Lang files
assets/apocalyinterface/lang/en_us.json— clés internes lib :screen.close,scroll.indicatorassets/apocalyinterface/lang/fr_ca.json— idem en FR-CAassets/apocalyinterface/lang/fr_fr.json— idem en FR-FRassets/apocalyinterfacedemo/lang/en_us.json— ajout clépanel.demoassets/apocalyinterfacedemo/lang/fr_ca.json— ajout clépanel.demo
Mod démo
DemoScreen.java— affiche un panneau Apocaly centré (220 × 150 px) avec titre traduit viaPanelRenderer.drawPanel(); keybindJpermet le test visuel in-game
Documentation
docs/reference/colors.md— référence complète de la palette + états des boutonsdocs/reference/panel.md— documentation dePanelRenderer: ordre de dessin, paramètres, primitives
Critère « done » Phase 2
ApocalyColors/ApocalyDimensionsaccessibles,fr_ca/en_uschargés, keybindJaffiche un panneau stylé reproduisant le style Clan (fond translucide, 4 bordures jaunes, barre de titre, divider, titre centré).
Phase 1 — Setup projet Forge + mod démo (2026-05-20)
Bibliothèque (apocalyinterfacelib)
Constants.java—MOD_ID = "apocalyinterfacelib"ApocalyInterfaceLib.java— classe@Modprincipale ; setup viaFMLClientSetupEventuniquement (client-only)mods.toml— configurédisplayTest="IGNORE_ALL_VERSION", dépendances Forge/MC enside="CLIENT"gradle.properties—mod_group_idcorrigé enca.tawess123.apocalyinterface- Lang files — structure créée pour
en_us,fr_ca,fr_fr(vides, prêts pour Phase 2+) - Boilerplate MDK (
com.example.examplemod) supprimé
Mod démo (apocalyinterfacedemo)
ApocalyInterfaceLibDemo.java— classe@Moddu mod démo, même JAR de devKeyBindings.java— keybindJ(configurable) enregistré viaRegisterKeyMappingsEvent; tick listener ouvre l'écranDemoScreen.java— écran vide (renderBackground+ titre) ; sera enrichi à chaque phase- Lang files — traductions EN/FR-CA des libellés du keybind
Critère « done » Phase 1
Lib + mod démo chargent en jeu, keybind
Jouvre un écran vide.
Prochaine phase → Phase 5 : containers + slots vanilla (ApocalyContainerScreen, Spacer, Divider, Grid, SlotGrid)