Übersicht
Die Dateline ist ein Steuerelement, das die eigentlichen Daten (Mo, Di, Mi, ...) in Zellen anzeigt, die in einer oder mehreren Zeilen angeordnet sind. Die Dateline ist zeitzonen-fähig, verfolgt aktuell ausgewählte Zeitintervalle und das aktuelle Hover-Zeitintervall. Sie löst außerdem Ereignisse aus, wenn sich der sichtbare Zeitbereich ändert (z. B. nach dem Scrollen nach links oder rechts).

Skalierungsauflösungen
Die Dateline kann eine bis fünf Zeilen anzeigen. Jede Zeile wird als „Dateline-Skala" bezeichnet, und jede dieser Skalen zeigt eine „Auflösung" an. Eine Auflösung besteht aus einer temporalen Einheit (z. B. Tag, Woche, Monat), einem Format-Pattern und einer Menge. Die Menge wird benötigt, um Auflösungen wie „5 Minuten", „15 Minuten" usw. anzugeben. Die gesamte Liste der von der Dateline aktuell angezeigten Auflösungen kann durch den Aufruf von getScaleResolutions() abgerufen werden.
Ein Beispiel für die Verwendung dieser Methode ist der System-Layer GridLinesLayer. Er ruft diese Methode auf, um anhand der Auflösungen die Positionen der vertikalen Gitterlinien zu berechnen. Dafür bietet die Klasse Resolution die Methoden
truncate(), um zum Beginn einer Einheit zu gelangen (z. B. Beginn eines Tages), und increment(), um zur nächsten Einheit zu gelangen (z. B. nächster Tag). Weitere Informationen zu Resolution finden Sie in der Dateline-Modell-Dokumentation.
Primäre temporale Einheit
Eine Dateline mit drei Skalen könnte beispielsweise die Auflösungen „Monat", „Woche" und „Tag" anzeigen. Die kleinste Auflösung „Tag" wird am unteren Rand der Dateline angezeigt. Die temporale Einheit ChronoUnit.DAYS, die von dieser
Auflösung verwendet wird, wird auch als „primäre temporale Einheit" bezeichnet. Der aktuelle Wert dieser Einheit wird in der schreibgeschützten Eigenschaft primaryTemporalUnit gespeichert. Dieser Eigenschaftswert wird beim Abfragen von Aktivitäten aus Activity-Repositories verwendet. Auf diese Weise kann das Repository entscheiden, wie detailliert das Ergebnis seiner Ausführung sein soll oder ob bestimmte Aktivitäten gar nicht angezeigt werden.
Ein gutes Beispiel für die Verwendung der primären temporalen Einheit ist die Klasse WeekendCalendar. Sie implementiert Calendar, eine Erweiterung von ActivityRepository. Der Zweck des WeekendCalendar ist es, die Wochenendtage (Samstag, Sonntag) für ein bestimmtes Zeitintervall zurückzugeben. Beim Aufruf wird nichts zurückgegeben, wenn die primäre temporale Einheit zu groß oder zu klein ist. Es macht keinen Sinn, Wochenend-Informationen zurückzugeben, wenn der Benutzer gerade Minuten oder Jahrzehnte betrachtet.
Zeitzone
Die Dateline muss wissen, für welche Zeitzone sie die Daten anzeigt (z. B. EST oder GMT). Daher verfügt sie über die Eigenschaft zoneIdProperty(). Sie ist beschreibbar und kann über setZoneId() gesetzt werden. Der Wert dieser Eigenschaft kann im Steuerelement durch den Aufruf von setZoneId(true) sichtbar gemacht werden.
Auswahlmodell
Das Dateline-Steuerelement ermöglicht dem Benutzer die Einfach- oder Mehrfachauswahl von Zeitintervallen durch Klicken der primären Maustaste bei gleichzeitigem Drücken der Shortcut-Taste (STRG unter Windows / Linux, Option auf dem Mac). Ob Einfach- oder Mehrfachauswahl unterstützt wird, hängt vom Wert der Eigenschaft selectionModeProperty() ab.
Es können nur Intervalle ausgewählt werden, die aktuell in einer der Zeilen / Skalen sichtbar sind. Wenn die Dateline also gerade Wochen und Tage anzeigt, kann der Benutzer nur ganze Wochen oder ganze Tage auswählen. Die Liste der ausgewählten Intervalle kann durch den Aufruf von getSelectedTimeIntervals() abgerufen werden.
Hover-Zeitintervall
Wenn der Mauszeiger über die Dateline bewegt wird, impliziert dies, dass er über einem Zeitintervall schwebt. Abhängig von der in der Dateline-Zeile / -Skala an der jeweiligen Mausposition angezeigten Auflösung kann das Intervall eine ganze Woche oder ein einzelner Tag sein. Das Intervall wird in der schreibgeschützten Eigenschaft hoverTimeIntervalProperty() gespeichert.
Ereignisse
Anwendungen können auf Scroll-Ereignisse der Dateline lauschen, wenn sie auf Änderungen des aktuell sichtbaren Zeitbereichs reagieren müssen. Dies geschieht durch Übergabe eines Ereignis-Listeners an die Methode setOnVisibleRangeChanged() oder durch den Aufruf von addEventListener(DatelineScrollingEvent.ANY, myListener).
Zell-Factory
Das Dateline-Steuerelement kann verschiedene Typen temporaler Einheiten anzeigen. ChronoUnit (Mo, Di, Mi, ...) und
SimpleUnit (1, 2, 3, 4, ...) werden standardmäßig unterstützt. Jeder Einheitentyp hat seine eigene visuelle Darstellung. Um dies zu ermöglichen, delegiert das Dateline-Steuerelement die Erstellung von Dateline-Zellen an eine austauschbare Factory, die zuvor einem bestimmten temporalen Einheitentyp zugeordnet wurde.
setCellFactory(SimpleUnit.class, unit -> new SimpleUnitDatelineCell());
setCellFactory(ChronoUnit.class, unit -> new ChronoUnitDatelineCell());
Dateline-Modell
Das Dateline-Modell versorgt das Dateline-Steuerelement mit verschiedenen Informationen, damit es sich korrekt darstellen kann.
- Auflösungen – eine Auflösung definiert, welche temporale Einheit angezeigt werden soll (z. B. Stunden) und wie sie formatiert wird. Sie enthält auch die Information, ob sie in einer oberen, unteren oder mittleren Skala angezeigt werden kann. Jedes Modell definiert in der Regel eine lange Liste solcher Auflösungen. Je mehr Auflösungen definiert sind, desto flexibler wird das Dateline-Steuerelement beim Hinein- und Herauszoomen.
- Zeitzonen – das Dateline-Steuerelement ermöglicht dem Benutzer den Wechsel zwischen verschiedenen Zeitzonen. Das Modell definiert, welche Zeitzonen verfügbar sind.
- Skalenanzahl – das Dateline-Steuerelement besteht aus einer Menge von Dateline-Skalen (oben, unten, mehrere mittlere Skalen). Das Modell kann verwendet werden, um die aktuell sichtbare, die minimale und die maximale Anzahl von Skalen zu definieren, die der Benutzer wählen kann.
- Temporale Einheiten – das Dateline-Steuerelement ruft das Modell zurück, um die „nächste" temporale Einheit nachzuschlagen, nachdem es entweder fehlgeschlagen ist oder erfolgreich eine Skala für die aktuelle Einheit erstellt hat.
Das Dateline-Modell ist ein typisiertes Modell. FlexGanttFX wird mit zwei Spezialisierungen ausgeliefert: ChronoUnitDatelineModel und
SimpleUnitDatelineModel.
Chrono-Unit-Dateline-Modell
Die Klasse ChronoUnitDatelineModel ist eine Spezialisierung für die temporale Einheit ChronoUnit aus dem JDK 8. Sie erfordert
Skalierungsauflösungen vom Typ ChronoUnitResolution. Das folgende Listing zeigt die Implementierung dieses Modells und
veranschaulicht, wie Auflösungen definiert und hinzugefügt werden und wie die Auflösung verwendet wird, um von einer temporalen Einheit zur nächsten zu gelangen.
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;
}
}
}
Simple-Unit-Dateline-Modell
Die Klasse SimpleUnitDatelineModel ist eine Spezialisierung für die temporale Einheit SimpleUnit, die mit FlexGanttFX ausgeliefert wird. Sie
erfordert Skalierungsauflösungen vom Typ SimpleUnitResolution. Die folgende Implementierung dieser Modellklasse zeigt, warum die Einheit „simple" heißt.
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;
}
}
Zeitzonen
Das Dateline-Modell verwaltet eine Liste von Zeitzonen-IDs, die von der Benutzeroberfläche zur Erstellung von Menüeinträgen für jede ID verwendet wird. So kann der Benutzer einfach zwischen ihnen wechseln. Die Standardliste wird in der Klasse DatelineModel wie folgt eingerichtet:
/**
* 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");
}