Vue d’ensemble
La ligne de dates est un contrôle qui affiche les dates réelles (lun., mar., mer., ...) dans des cellules placées sur une ou plusieurs lignes. Elle tient compte des fuseaux horaires, suit les intervalles de temps actuellement sélectionnés ainsi que l’intervalle de temps actuellement survolé. Elle déclenche également des événements chaque fois que la plage temporelle visible change (par exemple après un défilement vers la gauche ou la droite).

Résolutions d’échelle
La ligne de dates peut afficher de une à cinq lignes. Chaque ligne est appelée « échelle de ligne de dates » et chacune de ces échelles affiche une « résolution ». Une résolution se compose d’une unité temporelle (p. ex. jour, semaine, mois), d’un motif de formatage et d’une quantité. La quantité permet de spécifier des résolutions telles que « 5 minutes », « 15 minutes », etc. La liste complète des résolutions actuellement affichées par la ligne de dates peut être récupérée en appelant getScaleResolutions().
Un exemple d’utilisation de cette méthode est fourni par la couche système GridLinesLayer. Elle appelle cette méthode pour utiliser les résolutions afin de calculer les positions des lignes de grille verticales. Pour cela, la classe Resolution propose les méthodes truncate() pour aller au début d’une unité (p. ex. le début d’une journée) et increment() pour passer à l’unité suivante (p. ex. le jour suivant). Pour plus d’informations sur Resolution, veuillez consulter la documentation du modèle de ligne de dates.
Unité temporelle principale
Une ligne de dates à trois échelles pourrait, par exemple, afficher les résolutions « mois », « semaine » et « jour ». La plus petite résolution, « jour », est affichée en bas de la ligne de dates. L’unité temporelle ChronoUnit.DAYS utilisée par cette résolution est également appelée « unité temporelle principale ». La valeur courante de cette unité est stockée dans la propriété en lecture seule primaryTemporalUnit. La valeur de cette propriété est utilisée lors de l’interrogation des activités depuis les référentiels d’activités. Ainsi, le référentiel peut décider du niveau de détail du résultat de son invocation ou si certaines activités ne doivent pas être affichées du tout.
La classe WeekendCalendar est un bon exemple d’utilisation de l’unité temporelle principale. Elle implémente Calendar, qui est une extension de ActivityRepository. Le rôle de WeekendCalendar est de retourner les jours de week-end (samedi, dimanche) pour un intervalle de temps donné. Lorsqu’elle est invoquée, elle ne retourne rien si l’unité temporelle principale est trop grande ou trop petite. Il n’est pas pertinent de retourner des informations de week-end si l’utilisateur consulte actuellement des minutes ou des décennies.
Fuseau horaire
La ligne de dates doit connaître le fuseau horaire pour lequel elle affiche les dates (p. ex. EST ou GMT). Elle dispose donc de la propriété zoneIdProperty(). Celle-ci est modifiable et peut être définie via setZoneId(). La valeur de cette propriété peut être rendue visible dans le contrôle en appelant setZoneId(true).
Modèle de sélection
Le contrôle de ligne de dates permet à l’utilisateur d’effectuer une sélection simple ou multiple d’intervalles de temps en cliquant avec le bouton principal de la souris tout en maintenant la touche modificatrice de raccourci enfoncée (CTRL sous Windows / Linux, Option sur Mac). La prise en charge de la sélection simple ou multiple dépend de la valeur de selectionModeProperty().
Seuls les intervalles actuellement visibles dans l’une des lignes / échelles peuvent être sélectionnés. Ainsi, si la ligne de dates affiche actuellement des semaines et des jours, l’utilisateur ne peut sélectionner que des semaines entières ou des jours entiers. La liste des intervalles sélectionnés peut être récupérée en appelant getSelectedTimeIntervals().
Intervalle de temps survolé
Lorsque le curseur de la souris survole la ligne de dates, cela signifie également qu’il survole un intervalle de temps. Selon la résolution affichée dans la ligne / échelle de ligne de dates à l’emplacement donné de la souris, l’intervalle peut être une semaine entière ou un seul jour. Quel qu’il soit, l’intervalle est stocké dans la propriété en lecture seule hoverTimeIntervalProperty().
Événements
Les applications peuvent écouter les événements de défilement émis par la ligne de dates lorsqu’elles doivent réagir aux changements de la plage temporelle actuellement visible. Pour cela, on passe un écouteur d’événements à la méthode setOnVisibleRangeChanged() ou on appelle addEventListener(DatelineScrollingEvent.ANY, myListener).
Fabrique de cellules
Le contrôle de ligne de dates peut afficher différents types d’unités temporelles. ChronoUnit (lun., mar., mer., ...) et SimpleUnit (1, 2, 3, 4, ...) sont pris en charge par défaut. Chaque type d’unité possède sa propre représentation visuelle. Pour permettre cela, le contrôle de ligne de dates délègue la création des cellules de ligne de dates à une fabrique enfichable préalablement associée à un type d’unité temporelle spécifique.
setCellFactory(SimpleUnit.class, unit -> new SimpleUnitDatelineCell());
setCellFactory(ChronoUnit.class, unit -> new ChronoUnitDatelineCell());
Modèle de ligne de dates
Le modèle de ligne de dates fournit au contrôle de ligne de dates diverses informations afin qu’il puisse se mettre en page correctement.
- Résolutions – une résolution définit quelle unité temporelle afficher (p. ex. les heures) et comment la formater. Elle contient aussi l’information indiquant si elle peut être affichée dans une échelle supérieure, inférieure ou intermédiaire. Chaque modèle définit généralement une longue liste de telles résolutions. Plus les résolutions sont nombreuses, plus le contrôle de ligne de dates devient flexible pour le zoom avant et arrière.
- Fuseaux horaires – le contrôle de ligne de dates permet à l’utilisateur de basculer entre différents fuseaux horaires. Le modèle définit les zones disponibles.
- Nombre d’échelles – le contrôle de ligne de dates se compose d’un ensemble d’échelles de ligne de dates (supérieure, inférieure, plusieurs échelles intermédiaires). Le modèle peut être utilisé pour définir le nombre d’échelles actuellement visibles, minimal et maximal que l’utilisateur peut choisir d’afficher.
- Unités temporelles – le contrôle de ligne de dates rappelle le modèle pour rechercher l’unité temporelle « suivante » après avoir échoué ou réussi à créer une échelle pour l’unité courante.
Le modèle de ligne de dates est un modèle typé. FlexGanttFX est fourni avec deux spécialisations : ChronoUnitDatelineModel et SimpleUnitDatelineModel.
Modèle de ligne de dates pour ChronoUnit
La classe ChronoUnitDatelineModel est une spécialisation pour le type temporel ChronoUnit, qui fait partie du JDK 8. Elle nécessite des résolutions d’échelle de type ChronoUnitResolution. Le listing suivant est l’implémentation de ce modèle et illustre comment définir et ajouter des résolutions, ainsi que la façon dont la résolution est utilisée pour passer d’une unité temporelle à la suivante.
package com.flexganttfx.model.dateline;
import java.time.temporal.ChronoUnit;
import static com.flexganttfx.model.dateline.Resolution.Position.*;
import static java.time.temporal.ChronoUnit.*;
/**
* The chrono unit dateline model is a specialization of the dateline model that works
* in combination with the {@link ChronoUnit}. The chrono unit basically represents standard
* calendar units ranging from milliseconds to thousands of years.
*
* @since 1.0
*/
public final class ChronoUnitDatelineModel extends DatelineModel<ChronoUnit> {
/**
* Constructs a new dateline model with a long list of predefined
* resolutions of type {@link ChronoUnitResolution}.
*
* @since 1.0
*/
public ChronoUnitDatelineModel() {
addResolution(new ChronoUnitResolution(MILLIS, "EEEE, dd. MMMM yyyy, HH:mm:ss:SSS", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(MILLIS, "EEEE, dd.MM.yy, HH:mm:ss:SSS", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(MILLIS, "E, dd.MM.yy, HH:mm:ss:SSS", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(MILLIS, "dd.MM.yy, HH:mm:ss:SSS", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(MILLIS, "dd.MM, HH:mm:ss:SSS", 1, TOP));
addResolution(new ChronoUnitResolution(MILLIS, "SSS", 1, BOTTOM));
addResolution(new ChronoUnitResolution(MILLIS, "SSS", 5, BOTTOM));
addResolution(new ChronoUnitResolution(MILLIS, "SSS", 10, BOTTOM));
addResolution(new ChronoUnitResolution(MILLIS, "SSS", 15, BOTTOM));
addResolution(new ChronoUnitResolution(SECONDS, "EEEE, dd. MMMM yyyy, HH:mm:ss", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(SECONDS, "EEEE, dd.MM.yy, HH:mm:ss", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(SECONDS, "E, dd.MM.yy, HH:mm:ss", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(SECONDS, "dd.MM.yy, HH:mm:ss", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(SECONDS, "dd.MM, HH:mm:ss", 1, MIDDLE));
addResolution(new ChronoUnitResolution(SECONDS, "HH:mm:ss", 1, MIDDLE));
addResolution(new ChronoUnitResolution(SECONDS, "ss", 1, BOTTOM));
addResolution(new ChronoUnitResolution(SECONDS, "ss", 5, BOTTOM));
addResolution(new ChronoUnitResolution(SECONDS, "ss", 10, BOTTOM));
addResolution(new ChronoUnitResolution(SECONDS, "ss", 15, BOTTOM));
addResolution(new ChronoUnitResolution(MINUTES, "EEEE, dd. MMMM yyyy, HH:mm", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(MINUTES, "EEEE, dd.MM.yy, HH:mm", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(MINUTES, "E, dd.MM.yy, HH:mm", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(MINUTES, "dd.MM.yy, HH:mm", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(MINUTES, "dd.MM, HH:mm", 1, TOP));
addResolution(new ChronoUnitResolution(MINUTES, "HH:mm", 1, MIDDLE));
addResolution(new ChronoUnitResolution(MINUTES, "mm", 1, BOTTOM));
addResolution(new ChronoUnitResolution(MINUTES, "mm", 5, BOTTOM));
addResolution(new ChronoUnitResolution(MINUTES, "mm", 10, BOTTOM));
addResolution(new ChronoUnitResolution(MINUTES, "mm", 15, BOTTOM));
addResolution(new ChronoUnitResolution(HOURS, "EEEE, dd. MMMM yyyy, HH:mm", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(HOURS, "EEEE, dd.MM.yy, HH:mm", 1, TOP, BOTTOM, ONLY));
addResolution(new ChronoUnitResolution(HOURS, "E, dd.MM.yy, HH:mm", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(HOURS, "dd.MM.yy, HH:mm", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(HOURS, "dd.MM, HH:mm", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(HOURS, "H:mm", 1, MIDDLE, BOTTOM));
addResolution(new ChronoUnitResolution(HOURS, "H:mm", 3, MIDDLE, BOTTOM));
addResolution(new ChronoUnitResolution(HOURS, "H:mm", 6, MIDDLE, BOTTOM));
addResolution(new ChronoUnitResolution(DAYS, "EEEE d. MMMM yyyy", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(DAYS, "EEEE d. MMMM yy", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(DAYS, "E, d. MMMM yy", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(DAYS, "E, d. MMMM", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(DAYS, "E, dd.MM.yy", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(DAYS, "EEEE dd", 1, MIDDLE, BOTTOM));
addResolution(new ChronoUnitResolution(DAYS, "E dd", 1, MIDDLE, BOTTOM));
addResolution(new ChronoUnitResolution(DAYS, "dd.MM", 1, MIDDLE, BOTTOM));
addResolution(new ChronoUnitResolution(DAYS, "dd", 1, BOTTOM));
addResolution(new ChronoUnitResolution(WEEKS, "'W' w, EEEE d. MMMM yy", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(WEEKS, "'W' w, d. MMMM yy", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(WEEKS, "'W' w, d. MMMM", 1));
addResolution(new ChronoUnitResolution(WEEKS, "'W' w, E, dd.MM.yy", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(WEEKS, "'W' w, dd.MM.yy", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(WEEKS, "'W' w, dd.MM", 1, BOTTOM));
addResolution(new ChronoUnitResolution(WEEKS, "'W' w", 1, MIDDLE, BOTTOM));
addResolution(new ChronoUnitResolution(MONTHS, "MMMM yyyy", 1, TOP, ONLY));
addResolution(new ChronoUnitResolution(MONTHS, "MMMM", 1, MIDDLE, BOTTOM));
addResolution(new ChronoUnitResolution(MONTHS, "MMM", 1, MIDDLE, BOTTOM));
addResolution(new ChronoUnitResolution(MONTHS, "M", 1, MIDDLE, BOTTOM));
addResolution(new ChronoUnitResolution(YEARS, "yyyy", 1));
addResolution(new ChronoUnitResolution(DECADES, "yyyy", 1));
addResolution(new ChronoUnitResolution(CENTURIES, "yyyy", 1));
addResolution(new ChronoUnitResolution(MILLENNIA, "yyyy", 1));
}
@Override
public final ChronoUnit nextTemporalUnit(ChronoUnit unit) {
switch (unit) {
case NANOS:
return MICROS;
case MICROS:
return MILLIS;
case MILLIS:
return SECONDS;
case SECONDS:
return MINUTES;
case MINUTES:
return HOURS;
case HOURS:
return DAYS;
case DAYS:
return WEEKS;
case WEEKS:
return MONTHS;
case MONTHS:
return YEARS;
case YEARS:
return DECADES;
case DECADES:
return CENTURIES;
case CENTURIES:
return MILLENNIA;
default:
/*
* We are ignoring HALF DAYS.
*/
return null;
}
}
}
Modèle de ligne de dates pour SimpleUnit
La classe SimpleUnitDatelineModel est une spécialisation pour le type temporel SimpleUnit fourni avec FlexGanttFX. Elle nécessite des résolutions d’échelle de type SimpleUnitResolution. L’implémentation de cette classe de modèle ci-dessous montre pourquoi l’unité est appelée « simple ».
package com.flexganttfx.model.dateline;
import com.flexganttfx.model.util.SimpleUnit;
public final class SimpleUnitDatelineModel extends DatelineModel<SimpleUnit> {
public SimpleUnitDatelineModel() {
for (SimpleUnit unit : SimpleUnit.values()) {
addResolution(new SimpleUnitResolution(unit, "", 1));
}
}
@Override
public SimpleUnit nextTemporalUnit(SimpleUnit unit) {
int ordinal = unit.ordinal();
if (ordinal < SimpleUnit.values().length - 1) {
return SimpleUnit.values()[ordinal + 1];
}
return null;
}
}
Fuseaux horaires
Le modèle de ligne de dates gère une liste d’identifiants de zones, utilisée par l’interface utilisateur pour créer des éléments de menu pour chaque identifiant. Ainsi, l’utilisateur peut facilement basculer de l’un à l’autre. La liste par défaut est configurée dans la classe DatelineModel comme ceci :
/**
* Constructs a new model and populates the list of available zone IDs.
*/
protected DatelineModel() {
addZoneId("Europe/Berlin");
addZoneId("America/New_York");
addZoneId("Australia/Darwin");
addZoneId("Australia/Sydney");
addZoneId("America/Argentina/Buenos_Aires");
addZoneId("Africa/Cairo");
addZoneId("America/Anchorage");
addZoneId("America/Sao_Paulo");
addZoneId("Asia/Dhaka");
addZoneId("Africa/Harare");
addZoneId("America/St_Johns");
addZoneId("America/Chicago");
addZoneId("Asia/Shanghai");
addZoneId("Africa/Addis_Ababa")
addZoneId("Europe/Paris");
addZoneId("America/Indiana/Indianapolis");
addZoneId("Asia/Kolkata");
addZoneId("Asia/Tokyo");
addZoneId("Pacific/Apia");
addZoneId("Asia/Yerevan");
addZoneId("Pacific/Auckland");
addZoneId("Asia/Karachi");
addZoneId("America/Phoenix");
addZoneId("America/Puerto_Rico");
addZoneId("America/Los_Angeles");
addZoneId("Pacific/Guadalcanal");
addZoneId("Asia/Ho_Chi_Minh");
}