mini clock tool
This commit is contained in:
+29
@@ -0,0 +1,29 @@
|
|||||||
|
### IntelliJ IDEA ###
|
||||||
|
out/
|
||||||
|
!**/src/main/**/out/
|
||||||
|
!**/src/test/**/out/
|
||||||
|
|
||||||
|
### Eclipse ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
bin/
|
||||||
|
!**/src/main/**/bin/
|
||||||
|
!**/src/test/**/bin/
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
### Mac OS ###
|
||||||
|
.DS_Store
|
||||||
Generated
+8
@@ -0,0 +1,8 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
Generated
+8
@@ -0,0 +1,8 @@
|
|||||||
|
<component name="ArtifactManager">
|
||||||
|
<artifact type="jar" name="WatchTheClock:jar">
|
||||||
|
<output-path>$PROJECT_DIR$/out/artifacts/WatchTheClock_jar</output-path>
|
||||||
|
<root id="archive" name="WatchTheClock.jar">
|
||||||
|
<element id="module-output" name="WatchTheClock" />
|
||||||
|
</root>
|
||||||
|
</artifact>
|
||||||
|
</component>
|
||||||
Generated
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK">
|
||||||
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+8
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/WatchTheClock.iml" filepath="$PROJECT_DIR$/WatchTheClock.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="JAVA_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
Manifest-Version: 1.0
|
||||||
|
Main-Class: Main
|
||||||
|
|
||||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1,131 @@
|
|||||||
|
import javax.sound.sampled.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
|
public class AlarmLogic {
|
||||||
|
private JTextField hoursField;
|
||||||
|
private JTextField minutesField;
|
||||||
|
private JButton activateButton;
|
||||||
|
private JCheckBox soundCheckbox;
|
||||||
|
private Timer timer;
|
||||||
|
private boolean isActive;
|
||||||
|
private Clip alertSound;
|
||||||
|
|
||||||
|
public AlarmLogic(JTextField hours, JTextField minutes,
|
||||||
|
JButton activateBtn, JCheckBox soundCb) {
|
||||||
|
this.hoursField = hours;
|
||||||
|
this.minutesField = minutes;
|
||||||
|
this.activateButton = activateBtn;
|
||||||
|
this.soundCheckbox = soundCb;
|
||||||
|
this.isActive = false;
|
||||||
|
|
||||||
|
// Sound laden
|
||||||
|
try {
|
||||||
|
AudioInputStream audioStream = AudioSystem.getAudioInputStream(
|
||||||
|
getClass().getResource("/alert.wav"));
|
||||||
|
alertSound = AudioSystem.getClip();
|
||||||
|
alertSound.open(audioStream);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timer für Überprüfung jede Sekunde
|
||||||
|
timer = new Timer(1000, e -> checkAlarm());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void toggleActivation() {
|
||||||
|
if (!isActive) {
|
||||||
|
// Überprüfe Eingaben
|
||||||
|
try {
|
||||||
|
int hours = Integer.parseInt(hoursField.getText());
|
||||||
|
int minutes = Integer.parseInt(minutesField.getText());
|
||||||
|
|
||||||
|
if (hours >= 0 && hours <= 23 && minutes >= 0 && minutes <= 59) {
|
||||||
|
isActive = true;
|
||||||
|
activateButton.setText("Deactivate");
|
||||||
|
activateButton.setBackground(new Color(244, 67, 54));
|
||||||
|
setFieldsEditable(false);
|
||||||
|
timer.start();
|
||||||
|
} else {
|
||||||
|
JOptionPane.showMessageDialog(null,
|
||||||
|
"Bitte gültige Zeit eingeben!\nStunden: 0-23\nMinuten: 0-59",
|
||||||
|
"Ungültige Zeit",
|
||||||
|
JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
JOptionPane.showMessageDialog(null,
|
||||||
|
"Bitte nur Zahlen eingeben!",
|
||||||
|
"Ungültige Eingabe",
|
||||||
|
JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
deactivateAlarm();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkAlarm() {
|
||||||
|
LocalTime now = LocalTime.now();
|
||||||
|
int currentHour = now.getHour();
|
||||||
|
int currentMinute = now.getMinute();
|
||||||
|
|
||||||
|
int targetHour = Integer.parseInt(hoursField.getText());
|
||||||
|
int targetMinute = Integer.parseInt(minutesField.getText());
|
||||||
|
|
||||||
|
if (currentHour == targetHour && currentMinute == targetMinute) {
|
||||||
|
// Alarm auslösen
|
||||||
|
if (soundCheckbox.isSelected() && alertSound != null) {
|
||||||
|
alertSound.loop(Clip.LOOP_CONTINUOUSLY);
|
||||||
|
}
|
||||||
|
|
||||||
|
String currentTime = now.format(DateTimeFormatter.ofPattern("HH:mm"));
|
||||||
|
Object[] options = {"OK", "+5 min"};
|
||||||
|
int choice = JOptionPane.showOptionDialog(null,
|
||||||
|
"Es ist " + currentTime + "!",
|
||||||
|
"Alarm",
|
||||||
|
JOptionPane.DEFAULT_OPTION,
|
||||||
|
JOptionPane.INFORMATION_MESSAGE,
|
||||||
|
null,
|
||||||
|
options,
|
||||||
|
options[0]);
|
||||||
|
|
||||||
|
if (choice == 0) { // OK
|
||||||
|
deactivateAlarm();
|
||||||
|
} else if (choice == 1) { // +5 min
|
||||||
|
if (alertSound != null) {
|
||||||
|
alertSound.stop();
|
||||||
|
alertSound.setFramePosition(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Neue Alarmzeit berechnen (+5 Minuten)
|
||||||
|
LocalTime newAlarmTime = LocalTime.of(targetHour, targetMinute).plusMinutes(5);
|
||||||
|
hoursField.setText(String.valueOf(newAlarmTime.getHour()));
|
||||||
|
minutesField.setText(String.format("%02d", newAlarmTime.getMinute()));
|
||||||
|
|
||||||
|
// Zeige neue Alarmzeit an
|
||||||
|
JOptionPane.showMessageDialog(null,
|
||||||
|
"Neuer Alarm um " + newAlarmTime.format(DateTimeFormatter.ofPattern("HH:mm")),
|
||||||
|
"Schlummerfunktion",
|
||||||
|
JOptionPane.INFORMATION_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deactivateAlarm() {
|
||||||
|
isActive = false;
|
||||||
|
timer.stop();
|
||||||
|
if (alertSound != null) {
|
||||||
|
alertSound.stop();
|
||||||
|
alertSound.setFramePosition(0);
|
||||||
|
}
|
||||||
|
activateButton.setText("Activate");
|
||||||
|
activateButton.setBackground(new Color(76, 175, 80));
|
||||||
|
setFieldsEditable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setFieldsEditable(boolean editable) {
|
||||||
|
hoursField.setEditable(editable);
|
||||||
|
minutesField.setEditable(editable);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
import javax.swing.*;
|
||||||
|
import javax.sound.sampled.*;
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
public class CountdownLogic {
|
||||||
|
private JTextField hoursField;
|
||||||
|
private JTextField minutesField;
|
||||||
|
private JTextField secondsField;
|
||||||
|
private JButton startButton;
|
||||||
|
private JCheckBox soundCheckbox;
|
||||||
|
private Timer timer;
|
||||||
|
private long remainingTime;
|
||||||
|
private boolean isRunning;
|
||||||
|
private Clip alertSound;
|
||||||
|
|
||||||
|
public CountdownLogic(JTextField hours, JTextField minutes, JTextField seconds,
|
||||||
|
JButton startBtn, JCheckBox soundCb) {
|
||||||
|
this.hoursField = hours;
|
||||||
|
this.minutesField = minutes;
|
||||||
|
this.secondsField = seconds;
|
||||||
|
this.startButton = startBtn;
|
||||||
|
this.soundCheckbox = soundCb;
|
||||||
|
this.isRunning = false;
|
||||||
|
|
||||||
|
// Sound laden
|
||||||
|
try {
|
||||||
|
AudioInputStream audioStream = AudioSystem.getAudioInputStream(
|
||||||
|
getClass().getResource("/alert.wav"));
|
||||||
|
alertSound = AudioSystem.getClip();
|
||||||
|
alertSound.open(audioStream);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
timer = new Timer(1000, e -> updateCountdown());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void toggleStartStop() {
|
||||||
|
if (!isRunning) {
|
||||||
|
// Startzeit berechnen
|
||||||
|
long hours = Long.parseLong(hoursField.getText());
|
||||||
|
long minutes = Long.parseLong(minutesField.getText());
|
||||||
|
long seconds = Long.parseLong(secondsField.getText());
|
||||||
|
|
||||||
|
remainingTime = hours * 3600 + minutes * 60 + seconds;
|
||||||
|
|
||||||
|
if (remainingTime > 0) {
|
||||||
|
isRunning = true;
|
||||||
|
startButton.setText("Pause");
|
||||||
|
startButton.setBackground(new Color(255, 152, 0));
|
||||||
|
timer.start();
|
||||||
|
setFieldsEditable(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isRunning = false;
|
||||||
|
startButton.setText("Start");
|
||||||
|
startButton.setBackground(new Color(76, 175, 80));
|
||||||
|
timer.stop();
|
||||||
|
setFieldsEditable(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateCountdown() {
|
||||||
|
if (remainingTime > 0) {
|
||||||
|
remainingTime--;
|
||||||
|
updateDisplay();
|
||||||
|
} else {
|
||||||
|
timer.stop();
|
||||||
|
isRunning = false;
|
||||||
|
startButton.setText("Start");
|
||||||
|
startButton.setBackground(new Color(76, 175, 80));
|
||||||
|
setFieldsEditable(true);
|
||||||
|
|
||||||
|
// Sound in Schleife starten wenn aktiviert
|
||||||
|
if (soundCheckbox.isSelected() && alertSound != null) {
|
||||||
|
alertSound.loop(Clip.LOOP_CONTINUOUSLY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Benachrichtigung anzeigen und danach Sound stoppen
|
||||||
|
JOptionPane.showMessageDialog(null,
|
||||||
|
"Countdown beendet!",
|
||||||
|
"Zeit abgelaufen",
|
||||||
|
JOptionPane.INFORMATION_MESSAGE);
|
||||||
|
|
||||||
|
// Sound stoppen nach OK-Klick
|
||||||
|
if (alertSound != null) {
|
||||||
|
alertSound.stop();
|
||||||
|
alertSound.setFramePosition(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateDisplay() {
|
||||||
|
long hours = remainingTime / 3600;
|
||||||
|
long minutes = (remainingTime % 3600) / 60;
|
||||||
|
long seconds = remainingTime % 60;
|
||||||
|
|
||||||
|
hoursField.setText(String.valueOf(hours));
|
||||||
|
minutesField.setText(String.format("%02d", minutes));
|
||||||
|
secondsField.setText(String.format("%02d", seconds));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setFieldsEditable(boolean editable) {
|
||||||
|
hoursField.setEditable(editable);
|
||||||
|
minutesField.setEditable(editable);
|
||||||
|
secondsField.setEditable(editable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
timer.stop();
|
||||||
|
isRunning = false;
|
||||||
|
startButton.setText("Start");
|
||||||
|
startButton.setBackground(new Color(76, 175, 80));
|
||||||
|
hoursField.setText("0");
|
||||||
|
minutesField.setText("0");
|
||||||
|
secondsField.setText("0");
|
||||||
|
setFieldsEditable(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
+471
@@ -0,0 +1,471 @@
|
|||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import javax.swing.text.AttributeSet;
|
||||||
|
import javax.swing.text.BadLocationException;
|
||||||
|
import javax.swing.text.DocumentFilter;
|
||||||
|
import javax.swing.text.AbstractDocument;
|
||||||
|
import javax.swing.event.HyperlinkEvent;
|
||||||
|
import java.awt.Desktop;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
private static JFrame frame;
|
||||||
|
private static String baseTitle = "WatchTheClock";
|
||||||
|
private static String currentTitle = "";
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// Setze den Anwendungsnamen für Windows
|
||||||
|
System.setProperty("sun.java.command", baseTitle);
|
||||||
|
|
||||||
|
frame = new JFrame(baseTitle);
|
||||||
|
|
||||||
|
// Icon setzen
|
||||||
|
try {
|
||||||
|
Image icon = new ImageIcon(Main.class.getResource("/clock.png")).getImage();
|
||||||
|
frame.setIconImage(icon);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("Icon konnte nicht geladen werden: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
|
frame.setSize(450, 300);
|
||||||
|
frame.setMinimumSize(new Dimension(400, 280));
|
||||||
|
frame.setLocationRelativeTo(null);
|
||||||
|
|
||||||
|
// Erstellt JTabbedPane für die verschiedenen Funktionen
|
||||||
|
JTabbedPane tabbedPane = new JTabbedPane();
|
||||||
|
frame.add(tabbedPane);
|
||||||
|
|
||||||
|
// Fügt die Tabs hinzu
|
||||||
|
tabbedPane.addTab("Stopwatch", createStopwatchPanel());
|
||||||
|
tabbedPane.addTab("Countdown", createCountdownPanel());
|
||||||
|
tabbedPane.addTab("Alarm", createAlarmPanel());
|
||||||
|
tabbedPane.addTab("Notes", createNotesPanel());
|
||||||
|
tabbedPane.addTab("ToDo", createTodoPanel());
|
||||||
|
|
||||||
|
// Menüleiste erstellen
|
||||||
|
JMenuBar menuBar = new JMenuBar();
|
||||||
|
JMenu settingsMenu = new JMenu("⚙");
|
||||||
|
JMenu helpMenu = new JMenu("?");
|
||||||
|
|
||||||
|
// Settings-Menü Items
|
||||||
|
JCheckBoxMenuItem alwaysOnTopItem = new JCheckBoxMenuItem("Always on Top");
|
||||||
|
alwaysOnTopItem.addActionListener(e -> frame.setAlwaysOnTop(alwaysOnTopItem.isSelected()));
|
||||||
|
settingsMenu.add(alwaysOnTopItem);
|
||||||
|
|
||||||
|
// Titel-Menüpunkt
|
||||||
|
JMenuItem titleItem = new JMenuItem("Titel ändern");
|
||||||
|
titleItem.addActionListener(e -> changeTitleDialog());
|
||||||
|
settingsMenu.add(titleItem);
|
||||||
|
|
||||||
|
// Info-Menüpunkt
|
||||||
|
JMenuItem aboutItem = new JMenuItem("About");
|
||||||
|
aboutItem.addActionListener(e -> {
|
||||||
|
JEditorPane editorPane = new JEditorPane("text/html",
|
||||||
|
"<html><div style='font-family: Arial; font-size: 10px;'>" +
|
||||||
|
"WatchTheClock v0.1<br><br>" +
|
||||||
|
"This tool is free to use and portable!<br><br>" +
|
||||||
|
"Made by Jordan Henézi<br><br>" +
|
||||||
|
"Last time updated: 08.01.2025<br><br>" +
|
||||||
|
"Website: <a href='https://henezi.de'>henezi.de</a><br>" +
|
||||||
|
"Support: watchtheclock@henezi.de<br><br>" +
|
||||||
|
"Copyright © 2025" +
|
||||||
|
"</div></html>");
|
||||||
|
|
||||||
|
editorPane.setEditable(false);
|
||||||
|
editorPane.setBackground(new JLabel().getBackground());
|
||||||
|
|
||||||
|
// Links klickbar machen
|
||||||
|
editorPane.addHyperlinkListener(event -> {
|
||||||
|
if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
|
||||||
|
try {
|
||||||
|
String url = event.getURL().toString();
|
||||||
|
if (!url.startsWith("mailto:")) {
|
||||||
|
Desktop.getDesktop().browse(event.getURL().toURI());
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
JOptionPane.showMessageDialog(frame,
|
||||||
|
editorPane,
|
||||||
|
"About WatchTheClock",
|
||||||
|
JOptionPane.INFORMATION_MESSAGE);
|
||||||
|
});
|
||||||
|
helpMenu.add(aboutItem);
|
||||||
|
|
||||||
|
menuBar.add(settingsMenu);
|
||||||
|
menuBar.add(helpMenu);
|
||||||
|
frame.setJMenuBar(menuBar);
|
||||||
|
|
||||||
|
frame.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JPanel createStopwatchPanel() {
|
||||||
|
JPanel panel = new JPanel(new BorderLayout());
|
||||||
|
|
||||||
|
// Zeitanzeige mit mehr Platz
|
||||||
|
JLabel timeLabel = new JLabel("00:00:00");
|
||||||
|
timeLabel.setFont(new Font("Arial", Font.BOLD, 72));
|
||||||
|
timeLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
||||||
|
|
||||||
|
// Extra Panel für die Zeitanzeige mit weniger Padding oben
|
||||||
|
JPanel timeLabelPanel = new JPanel(new BorderLayout());
|
||||||
|
timeLabelPanel.add(timeLabel, BorderLayout.CENTER);
|
||||||
|
timeLabelPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 20, 0)); // Reduziertes Top-Padding
|
||||||
|
panel.add(timeLabelPanel, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
// Buttons Panel
|
||||||
|
JPanel buttonPanel = new JPanel(new FlowLayout());
|
||||||
|
JButton startButton = new JButton("Start");
|
||||||
|
JButton resetButton = new JButton("Reset");
|
||||||
|
startButton.setBackground(new Color(76, 175, 80));
|
||||||
|
resetButton.setBackground(new Color(244, 67, 54));
|
||||||
|
buttonPanel.add(startButton);
|
||||||
|
buttonPanel.add(resetButton);
|
||||||
|
panel.add(buttonPanel, BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
// Timeline Panel mit angepasster Größe
|
||||||
|
JPanel timelinePanel = new JPanel();
|
||||||
|
timelinePanel.setLayout(null);
|
||||||
|
|
||||||
|
JScrollPane scrollPane = new JScrollPane(timelinePanel,
|
||||||
|
JScrollPane.VERTICAL_SCROLLBAR_NEVER,
|
||||||
|
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
|
||||||
|
scrollPane.setBorder(BorderFactory.createTitledBorder("Timeline"));
|
||||||
|
scrollPane.setPreferredSize(new Dimension(430, 85)); // Breite und Höhe angepasst
|
||||||
|
|
||||||
|
// Mausrad-Scrolling
|
||||||
|
timelinePanel.addMouseWheelListener(e -> {
|
||||||
|
JScrollBar horizontalBar = scrollPane.getHorizontalScrollBar();
|
||||||
|
int delta = e.getWheelRotation() * 50; // Scroll-Geschwindigkeit
|
||||||
|
int newValue = horizontalBar.getValue() + delta;
|
||||||
|
newValue = Math.max(0, Math.min(newValue, horizontalBar.getMaximum()));
|
||||||
|
horizontalBar.setValue(newValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fügt den MouseWheelListener auch zum ScrollPane hinzu
|
||||||
|
scrollPane.addMouseWheelListener(e -> {
|
||||||
|
JScrollBar horizontalBar = scrollPane.getHorizontalScrollBar();
|
||||||
|
int delta = e.getWheelRotation() * 50;
|
||||||
|
int newValue = horizontalBar.getValue() + delta;
|
||||||
|
newValue = Math.max(0, Math.min(newValue, horizontalBar.getMaximum()));
|
||||||
|
horizontalBar.setValue(newValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
panel.add(scrollPane, BorderLayout.NORTH);
|
||||||
|
|
||||||
|
// Stopwatch Logik
|
||||||
|
StopwatchLogic stopwatch = new StopwatchLogic(timeLabel, timelinePanel, startButton);
|
||||||
|
startButton.addActionListener(e -> stopwatch.toggleStartStop());
|
||||||
|
resetButton.addActionListener(e -> stopwatch.reset());
|
||||||
|
|
||||||
|
return panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JPanel createCountdownPanel() {
|
||||||
|
JPanel panel = new JPanel(new BorderLayout());
|
||||||
|
panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||||
|
|
||||||
|
// Zeit-Eingabe Panel
|
||||||
|
JPanel inputPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 15, 0));
|
||||||
|
|
||||||
|
// Stunden Input
|
||||||
|
JPanel hoursPanel = new JPanel(new BorderLayout());
|
||||||
|
JLabel hoursLabel = new JLabel("Hours", SwingConstants.CENTER);
|
||||||
|
JTextField hoursField = new JTextField("0", 3);
|
||||||
|
hoursField.setHorizontalAlignment(SwingConstants.CENTER);
|
||||||
|
hoursField.setFont(new Font("Arial", Font.BOLD, 24));
|
||||||
|
hoursPanel.add(hoursLabel, BorderLayout.NORTH);
|
||||||
|
hoursPanel.add(hoursField, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
// Minuten Input
|
||||||
|
JPanel minutesPanel = new JPanel(new BorderLayout());
|
||||||
|
JLabel minutesLabel = new JLabel("Minutes", SwingConstants.CENTER);
|
||||||
|
JTextField minutesField = new JTextField("0", 3);
|
||||||
|
minutesField.setHorizontalAlignment(SwingConstants.CENTER);
|
||||||
|
minutesField.setFont(new Font("Arial", Font.BOLD, 24));
|
||||||
|
minutesPanel.add(minutesLabel, BorderLayout.NORTH);
|
||||||
|
minutesPanel.add(minutesField, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
// Sekunden Input
|
||||||
|
JPanel secondsPanel = new JPanel(new BorderLayout());
|
||||||
|
JLabel secondsLabel = new JLabel("Seconds", SwingConstants.CENTER);
|
||||||
|
JTextField secondsField = new JTextField("0", 3);
|
||||||
|
secondsField.setHorizontalAlignment(SwingConstants.CENTER);
|
||||||
|
secondsField.setFont(new Font("Arial", Font.BOLD, 24));
|
||||||
|
secondsPanel.add(secondsLabel, BorderLayout.NORTH);
|
||||||
|
secondsPanel.add(secondsField, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
// Trennpunkte zwischen den Feldern
|
||||||
|
JLabel separator1 = new JLabel(":", SwingConstants.CENTER);
|
||||||
|
JLabel separator2 = new JLabel(":", SwingConstants.CENTER);
|
||||||
|
separator1.setFont(new Font("Arial", Font.BOLD, 24));
|
||||||
|
separator2.setFont(new Font("Arial", Font.BOLD, 24));
|
||||||
|
|
||||||
|
inputPanel.add(hoursPanel);
|
||||||
|
inputPanel.add(separator1);
|
||||||
|
inputPanel.add(minutesPanel);
|
||||||
|
inputPanel.add(separator2);
|
||||||
|
inputPanel.add(secondsPanel);
|
||||||
|
|
||||||
|
// Control Panel
|
||||||
|
JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10));
|
||||||
|
|
||||||
|
// Start Button
|
||||||
|
JButton startButton = new JButton("Start");
|
||||||
|
startButton.setBackground(new Color(76, 175, 80));
|
||||||
|
startButton.setPreferredSize(new Dimension(100, 35));
|
||||||
|
|
||||||
|
// Reset Button
|
||||||
|
JButton resetButton = new JButton("Reset");
|
||||||
|
resetButton.setBackground(new Color(244, 67, 54));
|
||||||
|
resetButton.setPreferredSize(new Dimension(100, 35));
|
||||||
|
|
||||||
|
// Sound Checkbox
|
||||||
|
JCheckBox soundCheckbox = new JCheckBox("Play sound");
|
||||||
|
soundCheckbox.setSelected(true);
|
||||||
|
|
||||||
|
controlPanel.add(startButton);
|
||||||
|
controlPanel.add(resetButton);
|
||||||
|
controlPanel.add(soundCheckbox);
|
||||||
|
|
||||||
|
panel.add(inputPanel, BorderLayout.CENTER);
|
||||||
|
panel.add(controlPanel, BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
// Nur Zahlen in den Textfeldern erlauben
|
||||||
|
DocumentFilter numberFilter = new DocumentFilter() {
|
||||||
|
@Override
|
||||||
|
public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
|
||||||
|
if (string.matches("\\d*")) {
|
||||||
|
super.insertString(fb, offset, string, attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
|
||||||
|
if (text.matches("\\d*")) {
|
||||||
|
super.replace(fb, offset, length, text, attrs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// FocusListener für automatische Null
|
||||||
|
FocusAdapter focusAdapter = new FocusAdapter() {
|
||||||
|
@Override
|
||||||
|
public void focusLost(FocusEvent e) {
|
||||||
|
JTextField field = (JTextField) e.getComponent();
|
||||||
|
if (field.getText().trim().isEmpty()) {
|
||||||
|
field.setText("0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Anwenden auf alle Felder
|
||||||
|
hoursField.addFocusListener(focusAdapter);
|
||||||
|
minutesField.addFocusListener(focusAdapter);
|
||||||
|
secondsField.addFocusListener(focusAdapter);
|
||||||
|
|
||||||
|
((AbstractDocument) hoursField.getDocument()).setDocumentFilter(numberFilter);
|
||||||
|
((AbstractDocument) minutesField.getDocument()).setDocumentFilter(numberFilter);
|
||||||
|
((AbstractDocument) secondsField.getDocument()).setDocumentFilter(numberFilter);
|
||||||
|
|
||||||
|
// Countdown Logik
|
||||||
|
CountdownLogic countdown = new CountdownLogic(hoursField, minutesField, secondsField,
|
||||||
|
startButton, soundCheckbox);
|
||||||
|
startButton.addActionListener(e -> countdown.toggleStartStop());
|
||||||
|
resetButton.addActionListener(e -> countdown.reset());
|
||||||
|
|
||||||
|
return panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JPanel createAlarmPanel() {
|
||||||
|
JPanel panel = new JPanel(new BorderLayout());
|
||||||
|
panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||||
|
|
||||||
|
// Zeit-Eingabe Panel
|
||||||
|
JPanel inputPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 15, 0));
|
||||||
|
|
||||||
|
// Stunden Input
|
||||||
|
JPanel hoursPanel = new JPanel(new BorderLayout());
|
||||||
|
JLabel hoursLabel = new JLabel("Hours", SwingConstants.CENTER);
|
||||||
|
JTextField hoursField = new JTextField("0", 3);
|
||||||
|
hoursField.setHorizontalAlignment(SwingConstants.CENTER);
|
||||||
|
hoursField.setFont(new Font("Arial", Font.BOLD, 24));
|
||||||
|
hoursPanel.add(hoursLabel, BorderLayout.NORTH);
|
||||||
|
hoursPanel.add(hoursField, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
// Minuten Input
|
||||||
|
JPanel minutesPanel = new JPanel(new BorderLayout());
|
||||||
|
JLabel minutesLabel = new JLabel("Minutes", SwingConstants.CENTER);
|
||||||
|
JTextField minutesField = new JTextField("0", 3);
|
||||||
|
minutesField.setHorizontalAlignment(SwingConstants.CENTER);
|
||||||
|
minutesField.setFont(new Font("Arial", Font.BOLD, 24));
|
||||||
|
minutesPanel.add(minutesLabel, BorderLayout.NORTH);
|
||||||
|
minutesPanel.add(minutesField, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
// Trennpunkte
|
||||||
|
JLabel separator = new JLabel(":", SwingConstants.CENTER);
|
||||||
|
separator.setFont(new Font("Arial", Font.BOLD, 24));
|
||||||
|
|
||||||
|
inputPanel.add(hoursPanel);
|
||||||
|
inputPanel.add(separator);
|
||||||
|
inputPanel.add(minutesPanel);
|
||||||
|
|
||||||
|
// Control Panel
|
||||||
|
JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10));
|
||||||
|
|
||||||
|
JButton activateButton = new JButton("Activate");
|
||||||
|
activateButton.setBackground(new Color(76, 175, 80));
|
||||||
|
activateButton.setPreferredSize(new Dimension(100, 35));
|
||||||
|
|
||||||
|
JCheckBox soundCheckbox = new JCheckBox("Play sound");
|
||||||
|
soundCheckbox.setSelected(true);
|
||||||
|
|
||||||
|
controlPanel.add(activateButton);
|
||||||
|
controlPanel.add(soundCheckbox);
|
||||||
|
|
||||||
|
panel.add(inputPanel, BorderLayout.CENTER);
|
||||||
|
panel.add(controlPanel, BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
// Nur Zahlen in den Textfeldern erlauben
|
||||||
|
DocumentFilter numberFilter = new DocumentFilter() {
|
||||||
|
@Override
|
||||||
|
public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
|
||||||
|
if (string.matches("\\d*")) {
|
||||||
|
super.insertString(fb, offset, string, attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
|
||||||
|
if (text.matches("\\d*")) {
|
||||||
|
super.replace(fb, offset, length, text, attrs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
((AbstractDocument) hoursField.getDocument()).setDocumentFilter(numberFilter);
|
||||||
|
((AbstractDocument) minutesField.getDocument()).setDocumentFilter(numberFilter);
|
||||||
|
|
||||||
|
// Alarm Logik
|
||||||
|
AlarmLogic alarm = new AlarmLogic(hoursField, minutesField, activateButton, soundCheckbox);
|
||||||
|
activateButton.addActionListener(e -> alarm.toggleActivation());
|
||||||
|
|
||||||
|
return panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JPanel createNotesPanel() {
|
||||||
|
JPanel panel = new JPanel(new BorderLayout());
|
||||||
|
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||||
|
|
||||||
|
// Erstellt das Textfeld
|
||||||
|
JTextArea notesArea = new JTextArea();
|
||||||
|
notesArea.setLineWrap(true);
|
||||||
|
notesArea.setWrapStyleWord(true);
|
||||||
|
notesArea.setFont(new Font("Arial", Font.PLAIN, 12));
|
||||||
|
|
||||||
|
// Fügt Scrollbalken hinzu
|
||||||
|
JScrollPane scrollPane = new JScrollPane(notesArea);
|
||||||
|
|
||||||
|
panel.add(scrollPane, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
return panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JPanel createTodoPanel() {
|
||||||
|
JPanel panel = new JPanel(new BorderLayout());
|
||||||
|
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||||
|
|
||||||
|
// ToDo Liste
|
||||||
|
DefaultListModel<JCheckBox> todoListModel = new DefaultListModel<>();
|
||||||
|
JList<JCheckBox> todoList = new JList<>(todoListModel);
|
||||||
|
todoList.setCellRenderer(new CheckboxListCellRenderer());
|
||||||
|
todoList.addMouseListener(new MouseAdapter() {
|
||||||
|
@Override
|
||||||
|
public void mouseClicked(MouseEvent e) {
|
||||||
|
int index = todoList.locationToIndex(e.getPoint());
|
||||||
|
if (index >= 0) {
|
||||||
|
JCheckBox cb = todoListModel.getElementAt(index);
|
||||||
|
cb.setSelected(!cb.isSelected());
|
||||||
|
todoList.repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Input Panel für neue ToDos
|
||||||
|
JPanel inputPanel = new JPanel(new BorderLayout());
|
||||||
|
JTextField todoInput = new JTextField();
|
||||||
|
JButton addButton = new JButton("Add");
|
||||||
|
addButton.setPreferredSize(new Dimension(60, 25));
|
||||||
|
|
||||||
|
// Optional: Tooltip hinzufügen
|
||||||
|
addButton.setToolTipText("Add new todo item");
|
||||||
|
|
||||||
|
// Button zum Hinzufügen neuer ToDos
|
||||||
|
ActionListener addTodo = e -> {
|
||||||
|
String text = todoInput.getText().trim();
|
||||||
|
if (!text.isEmpty()) {
|
||||||
|
JCheckBox newTodo = new JCheckBox(text);
|
||||||
|
todoListModel.addElement(newTodo);
|
||||||
|
todoInput.setText("");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
addButton.addActionListener(addTodo);
|
||||||
|
todoInput.addActionListener(addTodo); // Erlaubt Enter-Taste
|
||||||
|
|
||||||
|
inputPanel.add(todoInput, BorderLayout.CENTER);
|
||||||
|
inputPanel.add(addButton, BorderLayout.EAST);
|
||||||
|
|
||||||
|
// Button zum Entfernen erledigter ToDos
|
||||||
|
JButton clearButton = new JButton("Clear completed");
|
||||||
|
clearButton.addActionListener(e -> {
|
||||||
|
for (int i = todoListModel.size() - 1; i >= 0; i--) {
|
||||||
|
if (todoListModel.getElementAt(i).isSelected()) {
|
||||||
|
todoListModel.removeElementAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Layout zusammensetzen
|
||||||
|
panel.add(new JScrollPane(todoList), BorderLayout.CENTER);
|
||||||
|
panel.add(inputPanel, BorderLayout.NORTH);
|
||||||
|
panel.add(clearButton, BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
return panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class CheckboxListCellRenderer extends JCheckBox implements ListCellRenderer<JCheckBox> {
|
||||||
|
@Override
|
||||||
|
public Component getListCellRendererComponent(JList<? extends JCheckBox> list, JCheckBox value,
|
||||||
|
int index, boolean isSelected, boolean cellHasFocus) {
|
||||||
|
setSelected(value.isSelected());
|
||||||
|
setText(value.getText());
|
||||||
|
setBackground(isSelected ? list.getSelectionBackground() : list.getBackground());
|
||||||
|
setForeground(isSelected ? list.getSelectionForeground() : list.getForeground());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void changeTitleDialog() {
|
||||||
|
String newTitle = JOptionPane.showInputDialog(frame,
|
||||||
|
"Neuen Titel eingeben:",
|
||||||
|
currentTitle);
|
||||||
|
|
||||||
|
if (newTitle != null) {
|
||||||
|
currentTitle = newTitle.trim();
|
||||||
|
updateWindowTitle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void updateWindowTitle() {
|
||||||
|
if (currentTitle.isEmpty()) {
|
||||||
|
frame.setTitle(baseTitle);
|
||||||
|
} else {
|
||||||
|
frame.setTitle(baseTitle + " - " + currentTitle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,200 @@
|
|||||||
|
import javax.swing.*;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
|
||||||
|
public class StopwatchLogic {
|
||||||
|
private JLabel timeLabel;
|
||||||
|
private JPanel timelinePanel;
|
||||||
|
private JButton startButton;
|
||||||
|
private Timer timer;
|
||||||
|
private long startTime;
|
||||||
|
private long elapsedTime;
|
||||||
|
private boolean isRunning;
|
||||||
|
private List<TimeMarker> timeMarkers;
|
||||||
|
|
||||||
|
// Angepasste Konstanten für kompakteres Layout
|
||||||
|
private static final int MIN_MARKER_DISTANCE = 70;
|
||||||
|
private static final int START_X = 20;
|
||||||
|
private static final int TIMELINE_HEIGHT = 65; // Reduziert von 75
|
||||||
|
private static final int LINE_Y = 25; // Höher positioniert (war 30)
|
||||||
|
private static final int ACTION_LABEL_Y = 3; // Höher positioniert (war 5)
|
||||||
|
private static final int TIME_LABEL_Y = 40; // Höher positioniert (war 48)
|
||||||
|
|
||||||
|
public StopwatchLogic(JLabel timeLabel, JPanel timelinePanel, JButton startButton) {
|
||||||
|
this.timeLabel = timeLabel;
|
||||||
|
this.timelinePanel = timelinePanel;
|
||||||
|
this.startButton = startButton;
|
||||||
|
this.timeMarkers = new ArrayList<>();
|
||||||
|
|
||||||
|
timer = new Timer(10, e -> {
|
||||||
|
if (isRunning) {
|
||||||
|
elapsedTime = System.currentTimeMillis() - startTime;
|
||||||
|
updateDisplay();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void toggleStartStop() {
|
||||||
|
if (isRunning) {
|
||||||
|
timer.stop();
|
||||||
|
addTimeMarker("Pause");
|
||||||
|
startButton.setText("Start");
|
||||||
|
startButton.setBackground(new Color(76, 175, 80)); // Grün
|
||||||
|
} else {
|
||||||
|
if (elapsedTime == 0) {
|
||||||
|
startTime = System.currentTimeMillis();
|
||||||
|
addTimeMarker("Start");
|
||||||
|
} else {
|
||||||
|
startTime = System.currentTimeMillis() - elapsedTime;
|
||||||
|
addTimeMarker("Resume");
|
||||||
|
}
|
||||||
|
timer.start();
|
||||||
|
startButton.setText("Pause");
|
||||||
|
startButton.setBackground(new Color(255, 152, 0)); // Orange
|
||||||
|
}
|
||||||
|
isRunning = !isRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
timer.stop();
|
||||||
|
isRunning = false;
|
||||||
|
elapsedTime = 0;
|
||||||
|
timeMarkers.clear();
|
||||||
|
startButton.setText("Start");
|
||||||
|
startButton.setBackground(new Color(76, 175, 80));
|
||||||
|
updateDisplay();
|
||||||
|
updateTimeline();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateDisplay() {
|
||||||
|
long hours = (elapsedTime / 3600000);
|
||||||
|
long minutes = (elapsedTime / 60000) % 60;
|
||||||
|
long seconds = (elapsedTime / 1000) % 60;
|
||||||
|
|
||||||
|
timeLabel.setText(String.format("%02d:%02d:%02d", hours, minutes, seconds));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addTimeMarker(String action) {
|
||||||
|
TimeMarker marker = new TimeMarker(action, elapsedTime);
|
||||||
|
timeMarkers.add(marker);
|
||||||
|
updateTimeline();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTimeline() {
|
||||||
|
timelinePanel.removeAll();
|
||||||
|
|
||||||
|
int markerCount = timeMarkers.size();
|
||||||
|
int minWidth = timelinePanel.getParent().getWidth() - 40;
|
||||||
|
int requiredWidth = Math.max(minWidth, markerCount * MIN_MARKER_DISTANCE + 100);
|
||||||
|
|
||||||
|
int lastX = START_X;
|
||||||
|
|
||||||
|
for (int i = 0; i < timeMarkers.size(); i++) {
|
||||||
|
TimeMarker currentMarker = timeMarkers.get(i);
|
||||||
|
int x = START_X + (int)((currentMarker.time * (requiredWidth - 70)) / Math.max(elapsedTime, 1000));
|
||||||
|
|
||||||
|
if (x - lastX < MIN_MARKER_DISTANCE) {
|
||||||
|
x = lastX + MIN_MARKER_DISTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i % 2 == 0 && i < timeMarkers.size() - 1) {
|
||||||
|
TimeMarker nextMarker = timeMarkers.get(i + 1);
|
||||||
|
int nextX = START_X + (int)((nextMarker.time * (requiredWidth - 70)) / Math.max(elapsedTime, 1000));
|
||||||
|
nextX = Math.max(nextX, x + MIN_MARKER_DISTANCE);
|
||||||
|
|
||||||
|
// Grüner Block
|
||||||
|
JPanel timeBlock = new JPanel();
|
||||||
|
timeBlock.setBackground(new Color(76, 175, 80, 50));
|
||||||
|
timeBlock.setBounds(x, LINE_Y - 5, nextX - x, 10);
|
||||||
|
timelinePanel.add(timeBlock);
|
||||||
|
|
||||||
|
// Dauer-Label
|
||||||
|
long durationSeconds = (nextMarker.time - currentMarker.time) / 1000;
|
||||||
|
String durationText = formatDurationDetailed(durationSeconds);
|
||||||
|
JLabel durationLabel = new JLabel(durationText);
|
||||||
|
durationLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
||||||
|
durationLabel.setFont(new Font("Arial", Font.PLAIN, 10));
|
||||||
|
int labelWidth = 70;
|
||||||
|
int labelX = x + (nextX - x) / 2 - labelWidth / 2;
|
||||||
|
durationLabel.setBounds(labelX, LINE_Y + 5, labelWidth, 15);
|
||||||
|
timelinePanel.add(durationLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aktion-Label (über der Linie)
|
||||||
|
JLabel actionLabel = new JLabel(currentMarker.action);
|
||||||
|
actionLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
||||||
|
actionLabel.setFont(new Font("Arial", Font.PLAIN, 11));
|
||||||
|
actionLabel.setBounds(x - 30, ACTION_LABEL_Y, 60, 20);
|
||||||
|
timelinePanel.add(actionLabel);
|
||||||
|
|
||||||
|
// Zeitstempel-Label (unter der Linie)
|
||||||
|
JLabel timeLabel = new JLabel(currentMarker.getClockTime());
|
||||||
|
timeLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
||||||
|
timeLabel.setFont(new Font("Arial", Font.PLAIN, 11));
|
||||||
|
timeLabel.setBounds(x - 35, TIME_LABEL_Y, 70, 20);
|
||||||
|
timelinePanel.add(timeLabel);
|
||||||
|
|
||||||
|
// Vertikaler Strich
|
||||||
|
JPanel tick = new JPanel();
|
||||||
|
tick.setBackground(Color.BLACK);
|
||||||
|
tick.setBounds(x, LINE_Y - 5, 1, 10);
|
||||||
|
timelinePanel.add(tick);
|
||||||
|
|
||||||
|
lastX = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Horizontale Linie
|
||||||
|
JPanel line = new JPanel();
|
||||||
|
line.setBackground(Color.GRAY);
|
||||||
|
line.setBounds(START_X, LINE_Y, requiredWidth - 40, 1);
|
||||||
|
timelinePanel.add(line);
|
||||||
|
|
||||||
|
timelinePanel.setPreferredSize(new Dimension(requiredWidth, TIMELINE_HEIGHT));
|
||||||
|
timelinePanel.revalidate();
|
||||||
|
timelinePanel.repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Neue detaillierte Formatierungsmethode
|
||||||
|
private String formatDurationDetailed(long seconds) {
|
||||||
|
if (seconds >= 3600) {
|
||||||
|
long hours = seconds / 3600;
|
||||||
|
long minutes = (seconds % 3600) / 60;
|
||||||
|
long secs = seconds % 60;
|
||||||
|
if (minutes > 0 || secs > 0) {
|
||||||
|
return String.format("%dh %02d:%02d", hours, minutes, secs);
|
||||||
|
}
|
||||||
|
return hours + "h";
|
||||||
|
} else if (seconds >= 60) {
|
||||||
|
long minutes = seconds / 60;
|
||||||
|
long secs = seconds % 60;
|
||||||
|
if (secs > 0) {
|
||||||
|
return String.format("%d:%02dmin", minutes, secs);
|
||||||
|
}
|
||||||
|
return minutes + "min";
|
||||||
|
} else {
|
||||||
|
return seconds + "s";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TimeMarker {
|
||||||
|
private String action;
|
||||||
|
private long time;
|
||||||
|
private String clockTime;
|
||||||
|
|
||||||
|
public TimeMarker(String action, long time) {
|
||||||
|
this.action = action;
|
||||||
|
this.time = time;
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
|
||||||
|
this.clockTime = sdf.format(new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClockTime() {
|
||||||
|
return clockTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user