#66: Tooltips auf Konfigurationstab, Verarbeitungslauf-Tab und Toolbar
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+35
@@ -72,6 +72,8 @@ import javafx.scene.control.Tab;
|
||||
import javafx.scene.control.TabPane;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.control.TitledPane;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.util.Duration;
|
||||
import javafx.scene.input.Clipboard;
|
||||
import javafx.scene.input.ClipboardContent;
|
||||
import javafx.scene.input.KeyCode;
|
||||
@@ -1277,6 +1279,12 @@ public final class GuiConfigurationEditorWorkspace {
|
||||
}
|
||||
|
||||
private void configureActionBar() {
|
||||
// Tooltips für Toolbar-Buttons gemäß Spezifikation
|
||||
applyTooltip(newButton, GuiTooltipTexts.TOOLBAR_NEU);
|
||||
applyTooltip(openButton, GuiTooltipTexts.TOOLBAR_OEFFNEN);
|
||||
applyTooltip(saveButton, GuiTooltipTexts.TOOLBAR_SPEICHERN);
|
||||
applyTooltip(saveAsButton, GuiTooltipTexts.TOOLBAR_SPEICHERN_UNTER);
|
||||
|
||||
HBox actionBar = new HBox(10, newButton, openButton, saveButton, saveAsButton);
|
||||
actionBar.setAlignment(Pos.CENTER_LEFT);
|
||||
actionBar.setPadding(new Insets(16, 0, 0, 0));
|
||||
@@ -1364,12 +1372,14 @@ public final class GuiConfigurationEditorWorkspace {
|
||||
TextField sourceFolderField = boundTextField(
|
||||
editorState.values().sourceFolder(),
|
||||
val -> updateValues(editorState.values().withSourceFolder(val)));
|
||||
applyTooltip(sourceFolderField, GuiTooltipTexts.PFADE_QUELLORDNER);
|
||||
Label sourceFolderErrorLabel = createFieldErrorLabel();
|
||||
fieldErrorLabels.put("source.folder", sourceFolderErrorLabel);
|
||||
|
||||
TextField targetFolderField = boundTextField(
|
||||
editorState.values().targetFolder(),
|
||||
val -> updateValues(editorState.values().withTargetFolder(val)));
|
||||
applyTooltip(targetFolderField, GuiTooltipTexts.PFADE_ZIELORDNER);
|
||||
Label targetFolderErrorLabel = createFieldErrorLabel();
|
||||
fieldErrorLabels.put("target.folder", targetFolderErrorLabel);
|
||||
|
||||
@@ -1394,12 +1404,14 @@ public final class GuiConfigurationEditorWorkspace {
|
||||
TextField sqliteField = boundTextField(
|
||||
editorState.values().sqliteFile(),
|
||||
val -> updateValues(editorState.values().withSqliteFile(val)));
|
||||
applyTooltip(sqliteField, GuiTooltipTexts.PFADE_SQLITE);
|
||||
Label sqliteErrorLabel = createFieldErrorLabel();
|
||||
fieldErrorLabels.put("sqlite.file", sqliteErrorLabel);
|
||||
|
||||
TextField promptField = boundTextField(
|
||||
editorState.values().promptTemplateFile(),
|
||||
val -> updateValues(editorState.values().withPromptTemplateFile(val)));
|
||||
applyTooltip(promptField, GuiTooltipTexts.PFADE_PROMPT);
|
||||
Label promptErrorLabel = createFieldErrorLabel();
|
||||
fieldErrorLabels.put("prompt.template.file", promptErrorLabel);
|
||||
|
||||
@@ -1487,6 +1499,7 @@ public final class GuiConfigurationEditorWorkspace {
|
||||
providerComboBox.setConverter(new AiProviderFamilyStringConverter());
|
||||
providerComboBox.getItems().addAll(AiProviderFamily.CLAUDE, AiProviderFamily.OPENAI_COMPATIBLE);
|
||||
providerComboBox.setValue(initialProvider);
|
||||
applyTooltip(providerComboBox, GuiTooltipTexts.PROVIDER_COMBOBOX);
|
||||
|
||||
// --- "Modelle neu laden" button ---
|
||||
Button reloadModelsButton = new Button("Modelle neu laden");
|
||||
@@ -1753,6 +1766,7 @@ public final class GuiConfigurationEditorWorkspace {
|
||||
pState.model(),
|
||||
val -> updateProviderField(family, pState2 -> new GuiProviderConfigurationState(
|
||||
pState2.baseUrl(), val, pState2.timeoutSeconds(), pState2.apiKey())));
|
||||
modelContainer.applyTooltip(GuiTooltipTexts.PROVIDER_MODELL);
|
||||
modelFieldContainers.put(family, modelContainer);
|
||||
modelCatalogCoordinator.registerFieldContainer(family, modelContainer);
|
||||
Label modelError = createFieldErrorLabel();
|
||||
@@ -1846,12 +1860,14 @@ public final class GuiConfigurationEditorWorkspace {
|
||||
TextField maxPagesField = boundTextField(
|
||||
editorState.values().maxPages(),
|
||||
val -> updateValues(editorState.values().withMaxPages(val)));
|
||||
applyTooltip(maxPagesField, GuiTooltipTexts.LIMITS_MAX_PAGES);
|
||||
grid.add(new Label("Max. Seiten:"), 0, row);
|
||||
grid.add(maxPagesField, 1, row);
|
||||
|
||||
TextField maxCharsField = boundTextField(
|
||||
editorState.values().maxTextCharacters(),
|
||||
val -> updateValues(editorState.values().withMaxTextCharacters(val)));
|
||||
applyTooltip(maxCharsField, GuiTooltipTexts.LIMITS_MAX_TEXT_CHARACTERS);
|
||||
grid.add(new Label("Max. Zeichen:"), 2, row);
|
||||
grid.add(maxCharsField, 3, row);
|
||||
row++;
|
||||
@@ -1860,6 +1876,7 @@ public final class GuiConfigurationEditorWorkspace {
|
||||
TextField maxTitleLengthField = boundTextField(
|
||||
editorState.values().maxTitleLength(),
|
||||
val -> updateValues(editorState.values().withMaxTitleLength(val)));
|
||||
applyTooltip(maxTitleLengthField, GuiTooltipTexts.LIMITS_MAX_TITLE_LENGTH);
|
||||
grid.add(new Label("Max. Titellänge:"), 0, row);
|
||||
grid.add(maxTitleLengthField, 1, row);
|
||||
|
||||
@@ -1914,9 +1931,11 @@ public final class GuiConfigurationEditorWorkspace {
|
||||
|
||||
validateButton.setId("validate-button");
|
||||
validateButton.setOnAction(e -> runValidationAction());
|
||||
applyTooltip(validateButton, GuiTooltipTexts.TOOLBAR_VALIDIEREN);
|
||||
|
||||
technicalTestsButton.setId("technical-tests-button");
|
||||
technicalTestsButton.setOnAction(e -> runTechnicalTestsAction());
|
||||
applyTooltip(technicalTestsButton, GuiTooltipTexts.TOOLBAR_TECHNISCHE_TESTS);
|
||||
|
||||
HBox buttonRow = new HBox(8, validateButton, technicalTestsButton);
|
||||
buttonRow.setAlignment(Pos.CENTER_LEFT);
|
||||
@@ -2838,6 +2857,22 @@ public final class GuiConfigurationEditorWorkspace {
|
||||
: exception.getMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt einen Tooltip mit einheitlicher Anzeigeverzögerung auf das angegebene Control.
|
||||
* <p>
|
||||
* Alle Tooltips in dieser Klasse werden über diese Methode gesetzt, damit ein konsistentes
|
||||
* Erscheinungsbild gewährleistet ist. Darf nur auf dem JavaFX Application Thread aufgerufen werden.
|
||||
*
|
||||
* @param control der Button oder ein anderes {@link javafx.scene.control.Control}, das den
|
||||
* Tooltip erhalten soll; darf nicht {@code null} sein
|
||||
* @param text der Tooltip-Text; darf nicht leer sein
|
||||
*/
|
||||
private static void applyTooltip(javafx.scene.control.Control control, String text) {
|
||||
Tooltip tooltip = new Tooltip(text);
|
||||
tooltip.setShowDelay(Duration.millis(300));
|
||||
control.setTooltip(tooltip);
|
||||
}
|
||||
|
||||
/**
|
||||
* Speichert den Pfad einer gerade geladenen Konfigurationsdatei.
|
||||
* Der Pfad wird in den Java Preferences gespeichert und beim nächsten Start
|
||||
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
package de.gecheckt.pdf.umbenenner.adapter.in.gui;
|
||||
|
||||
/**
|
||||
* Zentrale Konstantenklasse für alle Tooltip-Texte der GUI.
|
||||
* <p>
|
||||
* Diese Klasse ist die einzige autoritative Quelle für Tooltip-Beschriftungen aller
|
||||
* interaktiven Elemente in der Desktop-Oberfläche. Alle Tooltip-Strings werden hier
|
||||
* definiert und von den jeweiligen UI-Klassen referenziert. Streustrings im
|
||||
* UI-Code sind unzulässig.
|
||||
* <p>
|
||||
* Tooltip-Texte für Status-Icons werden <em>nicht</em> hier gepflegt – sie stammen
|
||||
* ausschließlich aus {@link de.gecheckt.pdf.umbenenner.adapter.in.gui.batchrun.ProcessingStatusPresentation},
|
||||
* die die autoritative Quelle für alle statusbezogenen Darstellungsinformationen ist.
|
||||
* <p>
|
||||
* Alle Texte sind deutschsprachig gemäß Spezifikation.
|
||||
* Diese Klasse enthält keine JavaFX-Typen und ist nicht instanziierbar.
|
||||
*/
|
||||
public final class GuiTooltipTexts {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Toolbar-Buttons
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/** Tooltip für den Button „Neu". */
|
||||
public static final String TOOLBAR_NEU =
|
||||
"Neue Konfiguration erstellen.";
|
||||
|
||||
/** Tooltip für den Button „Öffnen". */
|
||||
public static final String TOOLBAR_OEFFNEN =
|
||||
"Bestehende Konfigurationsdatei (.properties) öffnen.";
|
||||
|
||||
/** Tooltip für den Button „Speichern". */
|
||||
public static final String TOOLBAR_SPEICHERN =
|
||||
"Aktuelle Konfiguration speichern.";
|
||||
|
||||
/** Tooltip für den Button „Speichern unter". */
|
||||
public static final String TOOLBAR_SPEICHERN_UNTER =
|
||||
"Konfiguration unter neuem Dateipfad speichern.";
|
||||
|
||||
/** Tooltip für den Button „Validieren". */
|
||||
public static final String TOOLBAR_VALIDIEREN =
|
||||
"Aktuelle Eingaben auf Vollständigkeit und Korrektheit prüfen.";
|
||||
|
||||
/** Tooltip für den Button „Technische Tests ausführen". */
|
||||
public static final String TOOLBAR_TECHNISCHE_TESTS =
|
||||
"Dateipfade, Datenbankverbindung und KI-Erreichbarkeit prüfen.";
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Konfigurationstab – Pfade
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/** Tooltip für das Eingabefeld „Quellordner". */
|
||||
public static final String PFADE_QUELLORDNER =
|
||||
"Ordner mit den zu verarbeitenden PDF-Dateien. Inhalt wird nicht verändert.";
|
||||
|
||||
/** Tooltip für das Eingabefeld „Zielordner". */
|
||||
public static final String PFADE_ZIELORDNER =
|
||||
"Ordner für die umbenannten Kopien.";
|
||||
|
||||
/** Tooltip für das Eingabefeld „SQLite-Datei". */
|
||||
public static final String PFADE_SQLITE =
|
||||
"Datenbank für Verarbeitungsergebnisse und Datei-Historie.";
|
||||
|
||||
/** Tooltip für das Eingabefeld „Prompt-Datei". */
|
||||
public static final String PFADE_PROMPT =
|
||||
"Externe Textdatei mit den KI-Anweisungen.";
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Konfigurationstab – Provider
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/** Tooltip für die Provider-ComboBox. */
|
||||
public static final String PROVIDER_COMBOBOX =
|
||||
"Der KI-Dienst, der die Dateinamen generiert.";
|
||||
|
||||
/** Tooltip für das Modell-Eingabefeld (ComboBox oder manuelles TextField). */
|
||||
public static final String PROVIDER_MODELL =
|
||||
"Das konkrete Sprachmodell des gewählten Providers.";
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Konfigurationstab – Verarbeitungslimits
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/** Tooltip für das Eingabefeld „max.text.characters". */
|
||||
public static final String LIMITS_MAX_TEXT_CHARACTERS =
|
||||
"Maximale Zeichenzahl aus dem PDF-Text. Höhere Werte = mehr Kontext, höhere Kosten.";
|
||||
|
||||
/** Tooltip für das Eingabefeld „max.pages". */
|
||||
public static final String LIMITS_MAX_PAGES =
|
||||
"Maximale Seitenzahl, die aus einem PDF gelesen wird.";
|
||||
|
||||
/** Tooltip für das Eingabefeld „max.title.length". */
|
||||
public static final String LIMITS_MAX_TITLE_LENGTH =
|
||||
"Maximale Länge des Dateinamens in Zeichen (ohne Datum und Erweiterung). Gültig: 10–120.";
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Verarbeitungslauf-Tab – Dateiname-Editor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/** Tooltip für den Button „Dateiname übernehmen". */
|
||||
public static final String DATEINAME_UEBERNEHMEN =
|
||||
"Benennt die Zieldatei um und aktualisiert die Datenbank. Nicht rückgängig zu machen.";
|
||||
|
||||
/** Tooltip für den Button „Zurücksetzen auf KI-Vorschlag". */
|
||||
public static final String DATEINAME_ZURUECKSETZEN =
|
||||
"Stellt den KI-generierten Namen wieder her, ohne zu speichern.";
|
||||
|
||||
/** Nicht instanziierbar – reine Konstantenklasse. */
|
||||
private GuiTooltipTexts() {
|
||||
throw new UnsupportedOperationException("Nicht instanziierbar");
|
||||
}
|
||||
}
|
||||
+9
@@ -6,17 +6,20 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import de.gecheckt.pdf.umbenenner.adapter.in.gui.GuiTooltipTexts;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.in.DocumentCompletionStatus;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.util.Duration;
|
||||
|
||||
/**
|
||||
* Detailbereich-Komponente für die Bearbeitung des Zieldateinamens einer selektierten
|
||||
@@ -86,9 +89,15 @@ public final class FileNameEditorPane {
|
||||
|
||||
saveButton.setId("filename-editor-save-button");
|
||||
saveButton.setOnAction(e -> fireSaveRequest());
|
||||
Tooltip saveTooltip = new Tooltip(GuiTooltipTexts.DATEINAME_UEBERNEHMEN);
|
||||
saveTooltip.setShowDelay(Duration.millis(300));
|
||||
saveButton.setTooltip(saveTooltip);
|
||||
|
||||
resetButton.setId("filename-editor-reset-button");
|
||||
resetButton.setOnAction(e -> resetToAiProposal());
|
||||
Tooltip resetTooltip = new Tooltip(GuiTooltipTexts.DATEINAME_ZURUECKSETZEN);
|
||||
resetTooltip.setShowDelay(Duration.millis(300));
|
||||
resetButton.setTooltip(resetTooltip);
|
||||
|
||||
HBox buttonRow = new HBox(8, saveButton, resetButton);
|
||||
buttonRow.setAlignment(Pos.CENTER_LEFT);
|
||||
|
||||
+22
@@ -8,7 +8,9 @@ import javafx.geometry.Pos;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.util.Duration;
|
||||
|
||||
/**
|
||||
* A container that switches between a non-editable {@link ComboBox} and a manual {@link TextField}
|
||||
@@ -169,6 +171,26 @@ public final class GuiModelFieldContainer extends StackPane {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt einen Tooltip mit einheitlicher Anzeigeverzögerung auf beide internen Controls
|
||||
* (ComboBox und TextField). Damit erscheint der Tooltip unabhängig davon, welches der
|
||||
* beiden Controls gerade sichtbar ist.
|
||||
* <p>
|
||||
* Darf nur auf dem JavaFX Application Thread aufgerufen werden.
|
||||
*
|
||||
* @param tooltipText der anzuzeigende Tooltip-Text; darf nicht leer sein
|
||||
*/
|
||||
public void applyTooltip(String tooltipText) {
|
||||
Objects.requireNonNull(tooltipText, "tooltipText darf nicht null sein");
|
||||
Tooltip comboTooltip = new Tooltip(tooltipText);
|
||||
comboTooltip.setShowDelay(Duration.millis(300));
|
||||
comboBox.setTooltip(comboTooltip);
|
||||
|
||||
Tooltip textTooltip = new Tooltip(tooltipText);
|
||||
textTooltip.setShowDelay(Duration.millis(300));
|
||||
textField.setTooltip(textTooltip);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the JavaFX node that represents this container and can be added to the scene graph.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user