Visibilité conditionnelle (visibleIf)
Chaque widget et conteneur expose une méthode visibleIf(boolean) qui permet de le masquer conditionnellement. Le layout se recalcule automatiquement : les widgets masqués n'occupent aucun pixel.
Fonctionnement
// Widget visible uniquement si le joueur est chef de clan
Button.builder()
.text("monmod.btn.disbandclan")
.command("clan disband")
.visibleIf(isLeader)
.build();
Quand isLeader = false :
- Le bouton n'est pas rendu.
- Il n'occupe aucun espace vertical dans le layout.
- Les widgets en dessous remontent automatiquement.
Quand isLeader = true :
- Le bouton est rendu normalement et occupe sa hauteur.
Reconstruire le layout après un changement
visibleIf prend un boolean évalué au moment du buildLayout. Pour changer la visibilité après l'ouverture de l'écran, il faut déclencher un rebuild.
Pattern avec init() — toggle simple
private boolean showDetails = false;
@Override
protected void buildLayout(Column root) {
root.add(Button.builder()
.text(showDetails ? "monmod.btn.masquer" : "monmod.btn.voir_details")
.onClick(() -> { showDetails = !showDetails; init(); })
.build());
root.add(Card.create()
.add(KeyValueRow.builder()
.key("monmod.row.coordonnees")
.value(DataSource.of("X:128 Y:64 Z:-32"))
.build())
.visibleIf(showDetails));
}
init() vs update()Utilise init() quand tu veux juste reconstruire le layout (visibilité, onglets). Utilise update() quand les données ont changé — update() préserve aussi le scroll, init() le remet à zéro.
Pattern avec plusieurs états
private int activeTab = 0; // 0 = membres, 1 = stats, 2 = historique
@Override
protected void buildLayout(Column root) {
root.add(TabBar.builder()
.tab("monmod.tab.membres", () -> { activeTab = 0; init(); })
.tab("monmod.tab.stats", () -> { activeTab = 1; init(); })
.tab("monmod.tab.historique",() -> { activeTab = 2; init(); })
.activeTab(activeTab)
.build());
root.add(buildMembresPanel().visibleIf(activeTab == 0));
root.add(buildStatsPanel() .visibleIf(activeTab == 1));
root.add(buildHistorique() .visibleIf(activeTab == 2));
}
visibleIf sur les conteneurs
visibleIf fonctionne aussi sur Column, Row et Card :
Card adminCard = Card.create()
.add(Button.builder().text("monmod.btn.kick").command("clan kick").build())
.add(Button.builder().text("monmod.btn.promote").command("clan promote").build())
.visible(isAdmin); // ← Card.visible(), pas visibleIf()
root.add(adminCard);
.visible() sur les conteneursColumn, Row et Card utilisent .visible(boolean) (pas .visibleIf()). Les widgets (Button, Label, etc.) utilisent .visibleIf(boolean). Les deux produisent le même effet.
Avertissement de sécurité
visibleIf est purement cosmétique — il ne sécurise rienMasquer un bouton avec visibleIf(false) empêche l'utilisateur de cliquer dessus dans l'UI. Mais un joueur malveillant peut toujours envoyer la commande ou le packet associé directement.
Toujours valider les permissions côté serveur, indépendamment de ce que l'UI affiche ou masque.
// Côté serveur — toujours re-vérifier :
@SubscribeEvent
public void onCommand(CommandEvent event) {
if (!player.hasPermission(Permission.CLAN_DISBAND)) {
event.setCanceled(true);
}
}
Voir aussi
- Référence Button —
visibleIf - Référence Label —
visibleIf - Référence Card —
.visible() - Recette card sticky + scroll — combinaison Card fixe + contenu conditionnel