C'est toujours agréable de parler avec une application qui se souvient de vos habitudes et comme si vous vous sentez, de ce que vous voulez. Toute bibliothèque ou plate-forme d'interface utilisateur n'a, hélas, que des fonctionnalités de base et un ensemble de composants. Par exemple, si une colonne d'une table ne bouge pas ou ne peut pas être triée par elle, alors une telle application dans laquelle elle est utilisée peut difficilement être appelée conviviale. Heureusement, aujourd'hui, vous ne surprendrez personne avec une telle fonctionnalité. Cependant, tous les programmes ne se souviendront pas de la position de cette colonne et dans la prochaine session, ils l'afficheront au même endroit. Il peut également être gênant de définir la position du séparateur à chaque fois dans SplitPane ou d'entrer les mêmes paramètres de filtre. En règle générale, ces aménagements doivent être fournis par les développeurs eux-mêmes.
Il existe de nombreux exemples de telles améliorations apparemment minimes, mais les solutions proposées par la plate-forme ne sont que deux, et essentiellement elles sont similaires: créez votre propre composant basé sur la base, créez votre skin au composant de base, redéfinissant le comportement. Aucune de ces méthodes n'est facile à implémenter; de plus, chaque composant devra écrire son propre composant adaptateur. J'ai rencontré pas mal de gens à qui cette méthode était plus familière et compréhensible.
Mais il est loin d'être le seul. Que se passe-t-il si nous prenons les capacités de la plate-forme qui prend en charge le modèle de navigateur pour le nœud enfant, et lors de l'ajout ou de la suppression du sous-graphique Node , exécutons un ensemble de plug-ins, chacun étant engagé dans son propre travail spécifique? L'un est capable de tout mémoriser et de tout restaurer lors d'une deuxième session, l'autre - les composants spécifiés sont modifiés par le menu contextuel, ajoutant la fonction de copie de texte. Certains d'entre eux ajoutent trois points à la fin du texte s'il ne convient pas, et lorsque vous survolez la souris, il affiche un indice avec du texte intégral uniquement s'il ne convient pas. Plus important encore, peu importe de quelle bibliothèque se trouve ce composant, si nous pouvons en hériter et redéfinir le comportement dont nous avons besoin. Tout ce dont nous avons besoin dans ce cas est d'apprendre au plugin à travailler avec les composants nécessaires de différentes manières, si nécessaire.
Cela pourrait être un auditeur pour une collection d'enfants:
private final ListChangeListener changeListener = (ListChangeListener<Node>) (ListChangeListener.Change<? extends Node> c) -> { if (c.next()) { c.getAddedSubList().forEach(this::applySettingsForNodeAndAddListenerForItsChild); } };
Ce serait le code de traitement pour chaque nœud modifié:
private void applySettingsForNodeAndAddListenerForItsChild(Node n) { if (!checkApplySettings(n)) { apply(n); ObservableList<Node> children = getChildren(n); if (children != null) { addListnerForUpdateChildren(children); } markNodePropertyApplied(n); } }
Et tel est le code appelant directement le plugin lui-même, qui est enregistré sur ce type de composant:
public Node apply(Node node) { List<SettingsPlugin> settingsPlugins = settingsMap.get(Node.class); if (settingsPlugins != null) { for (SettingsPlugin plugin : settingsPlugins) { node = plugin.apply(node, userSettings.getSettings()); } } List<SettingsPlugin> settingList = settingsMap.get(node.getClass()); if (settingList != null) { for (SettingsPlugin plugin : settingList) { node = plugin.apply(node, userSettings.getSettings()); } } return node; }
Voici l'interface du plugin lui-même:
public interface SettingsPlugin { public Node apply(Node node, Map<String, Object> userSettings); }
Il suffit d'enregistrer l'écouteur une seule fois sur la collection d'éléments enfants Root de l'élément Scene , et sur le reste du sous-graphe, il s'enregistrera lui-même ...
Récemment, je fais une analogie sur les capacités des plates-formes pour les applications de bureau et Web. Il serait intéressant de savoir comment une telle fonctionnalité peut être implémentée sur différents cadres.