Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

5day-weather-forecast & 12hours-forecast #21

Merged
merged 9 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,6 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "WeatherIsland",
"request": "launch",
"mainClass": "edu.project.components.WeatherIsland",
"projectName": "weatherforecast"
},
{
"type": "java",
"name": "Main",
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/edu/project/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ private static boolean isInternetAvailable() {
socket.connect(new InetSocketAddress("8.8.8.8", 53), 1500);
return true;
} catch (Exception e) {
return true;
return false;
}
}
}
149 changes: 149 additions & 0 deletions src/main/java/edu/project/components/TimeForecast.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package edu.project.components;

import edu.project.Context;
import edu.project.api.WeatherForecast5Data;

import javax.swing.*;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

public class TimeForecast extends JPanel {
private static final DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("h a")
.withLocale(Locale.ENGLISH); // Abbreviate the hour
private static final Color PANEL_COLOR = new Color(169, 169, 169); // Light gray color
private static final int ARC_WIDTH = 20; // Adjust the arc width for rounded corners
private static final int ARC_HEIGHT = 20; // Adjust the arc height for rounded corners
private static final int SPACING = 10; // Horizontal spacing between each hour panel
private static final int INTERVAL_HOURS = 3;

private final JPanel contentPanel;
private final List<HourForecast> hourForecasts = new ArrayList<>();

public TimeForecast(Context context) {
setOpaque(false);
setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
setLayout(new BorderLayout());

JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.setOpaque(false);

JPanel titlePanel = new JPanel(new BorderLayout());
titlePanel.setOpaque(false);
titlePanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0));

JLabel titleLabel = new JLabel("5-Hour Forecast");
titleLabel.setFont(new Font("Arial", Font.BOLD, 16));
titlePanel.add(titleLabel, BorderLayout.NORTH);

JSeparator separator = new JSeparator(SwingConstants.HORIZONTAL);
separator.setForeground(Color.BLACK);
titlePanel.add(separator, BorderLayout.SOUTH);

mainPanel.add(titlePanel, BorderLayout.NORTH);

contentPanel = new JPanel();
contentPanel.setOpaque(false);
contentPanel.setLayout(new GridLayout(1, 5, SPACING, 0));
mainPanel.add(contentPanel, BorderLayout.CENTER);

add(mainPanel, BorderLayout.CENTER);

context.store.addWeatherForecast5DataListener(this::updateForecastData);
}

private void updateForecastData(WeatherForecast5Data forecastData) {
hourForecasts.clear();

List<WeatherForecast5Data.WeatherList> weatherList = forecastData.list;
int hourCount = Math.min(5, weatherList.size());
LocalDateTime currentTime = LocalDateTime.now();

for (int i = 0; i < hourCount; i++) {
LocalDateTime forecastTime = currentTime.plusHours(i * INTERVAL_HOURS);
float tempKelvin = weatherList.get(i).main.temp;
float tempCelsius = tempKelvin - 273.15f; // Convert from Kelvin to Celsius

hourForecasts.add(new HourForecast(forecastTime, tempCelsius));
}

addForecastPanels();
}

private void addForecastPanels() {
contentPanel.removeAll();

for (HourForecast forecast : hourForecasts) {
JPanel hourForecastPanel = new JPanel(new BorderLayout());
hourForecastPanel.setOpaque(false);

JPanel hourPanel = new JPanel();
hourPanel.setOpaque(false);
JLabel hourLabel = new JLabel(forecast.time.format(timeFormatter));
hourLabel.setFont(new Font(hourLabel.getFont().getName(), Font.BOLD, 14));
hourLabel.setHorizontalAlignment(SwingConstants.CENTER);
hourPanel.add(hourLabel);
hourForecastPanel.add(hourPanel, BorderLayout.NORTH);

JPanel separatorPanel = createSeparatorPanel();
hourForecastPanel.add(separatorPanel, BorderLayout.CENTER);

JPanel temperaturePanel = new JPanel();
temperaturePanel.setOpaque(false);
JLabel tempLabel = new JLabel(String.format("%.0f°", forecast.temp));
tempLabel.setFont(new Font("Arial", Font.PLAIN, 14));
tempLabel.setHorizontalAlignment(SwingConstants.CENTER);
temperaturePanel.add(tempLabel);
hourForecastPanel.add(temperaturePanel, BorderLayout.SOUTH);

contentPanel.add(hourForecastPanel);
}

revalidate();
repaint();
}

private JPanel createSeparatorPanel() {
ImageIcon icon = new ImageIcon("pic here");

JPanel separatorPanel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

int x = (getWidth() - icon.getIconWidth()) / 2;
int y = (getHeight() - icon.getIconHeight()) / 2;
icon.paintIcon(this, g2d, x, y);
}
};
separatorPanel.setPreferredSize(new Dimension(40, 40));
separatorPanel.setMaximumSize(new Dimension(40, 40));
return separatorPanel;
}

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(PANEL_COLOR);
g2d.fill(new RoundRectangle2D.Double(0, 0, getWidth(), getHeight(), ARC_WIDTH, ARC_HEIGHT));
g2d.dispose();
}

private static class HourForecast {
private final LocalDateTime time;
private final float temp;

public HourForecast(LocalDateTime time, float temp) {
this.time = time;
this.temp = temp;
}
}
}
151 changes: 151 additions & 0 deletions src/main/java/edu/project/components/WeatherForecastPanel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package edu.project.components;

import edu.project.Context;
import edu.project.api.WeatherForecast5Data;

import javax.swing.*;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

public class WeatherForecastPanel extends JPanel {
private static final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("EEE")
.withLocale(Locale.ENGLISH);
private static final Color PANEL_COLOR = new Color(169, 169, 169); // Light gray color
private static final int ARC_WIDTH = 20;
private static final int ARC_HEIGHT = 20;
private static final int SPACING = 20;

private final JPanel contentPanel;
private final List<DayForecast> dayForecasts = new ArrayList<>();

public WeatherForecastPanel(Context context) {
setOpaque(false);
setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 19));
setLayout(new BorderLayout());

JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.setOpaque(false);

JPanel titlePanel = new JPanel(new BorderLayout());
titlePanel.setOpaque(false);
titlePanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0));

JLabel titleLabel = new JLabel("5-Day Forecast");
titleLabel.setFont(new Font("Arial", Font.BOLD, 16));
titlePanel.add(titleLabel, BorderLayout.NORTH);

JSeparator separator = new JSeparator(SwingConstants.HORIZONTAL);
separator.setForeground(Color.BLACK);
titlePanel.add(separator, BorderLayout.SOUTH);

mainPanel.add(titlePanel, BorderLayout.NORTH);

contentPanel = new JPanel();
contentPanel.setOpaque(false);
contentPanel.setLayout(new GridLayout(1, 5, SPACING, 0));
mainPanel.add(contentPanel, BorderLayout.CENTER);

add(mainPanel, BorderLayout.CENTER);

context.store.addWeatherForecast5DataListener(this::updateForecastData);
}

private void updateForecastData(WeatherForecast5Data forecastData) {
dayForecasts.clear();

List<WeatherForecast5Data.WeatherList> weatherList = forecastData.list;
int dayCount = Math.min(5, weatherList.size() / 8);
LocalDate currentDate = LocalDate.now();

for (int i = 0; i < dayCount; i++) {
LocalDate forecastDate = currentDate.plusDays(i);
float sumTemp = 0;
for (int j = i * 8; j < (i + 1) * 8 && j < weatherList.size(); j++) {
sumTemp += weatherList.get(j).main.temp;
}
float averageTemp = (sumTemp / 8) - 273.15f;

dayForecasts.add(new DayForecast(forecastDate, averageTemp));
}

addForecastPanels();
}

private void addForecastPanels() {
contentPanel.removeAll();

for (DayForecast forecast : dayForecasts) {
JPanel dayForecastPanel = new JPanel(new BorderLayout());
dayForecastPanel.setOpaque(false);

JPanel dayPanel = new JPanel();
dayPanel.setOpaque(false);
JLabel dayLabel = new JLabel(forecast.date.format(dateFormatter));
dayLabel.setFont(new Font(dayLabel.getFont().getName(), Font.BOLD, 14));
dayLabel.setHorizontalAlignment(SwingConstants.CENTER);
dayPanel.add(dayLabel);
dayForecastPanel.add(dayPanel, BorderLayout.NORTH);

JPanel separatorPanel = createSeparatorPanel();
dayForecastPanel.add(separatorPanel, BorderLayout.CENTER);

JPanel temperaturePanel = new JPanel();
temperaturePanel.setOpaque(false);
JLabel tempLabel = new JLabel(String.format("%.0f°", forecast.averageTemp));
tempLabel.setFont(new Font("Arial", Font.PLAIN, 14));
tempLabel.setHorizontalAlignment(SwingConstants.CENTER);
temperaturePanel.add(tempLabel);
dayForecastPanel.add(temperaturePanel, BorderLayout.SOUTH);

contentPanel.add(dayForecastPanel);
}

revalidate();
repaint();
}

private JPanel createSeparatorPanel() {
ImageIcon icon = new ImageIcon("path/to/your/image.png");

JPanel separatorPanel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

int x = (getWidth() - icon.getIconWidth()) / 2;
int y = (getHeight() - icon.getIconHeight()) / 2;
icon.paintIcon(this, g2d, x, y);
}
};
separatorPanel.setPreferredSize(new Dimension(40, 40));
separatorPanel.setMaximumSize(new Dimension(40, 40));
return separatorPanel;
}

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(PANEL_COLOR);
g2d.fill(new RoundRectangle2D.Double(0, 0, getWidth(), getHeight(), ARC_WIDTH, ARC_HEIGHT));
g2d.dispose();
}

private static class DayForecast {
private final LocalDate date;
private final float averageTemp;

public DayForecast(LocalDate date, float averageTemp) {
this.date = date;
this.averageTemp = averageTemp;
}
}
}
23 changes: 23 additions & 0 deletions src/main/java/edu/project/components/WeatherIsland.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,29 @@ public WeatherIsland(Context context) {

add(weatherGroup);

add(Box.createVerticalStrut(8));

WeatherForecastPanel weatherForecastPanel = new WeatherForecastPanel(context);

// Maximize Width and Height
weatherForecastPanel.setMaximumSize(
new Dimension(
weatherForecastPanel.getMaximumSize().width,
weatherForecastPanel.getMaximumSize().height));

add(weatherForecastPanel);

add(Box.createVerticalStrut(8));

TimeForecast timeForecast = new TimeForecast(context);

// Maximize Width and Height
timeForecast.setMaximumSize(
new Dimension(
timeForecast.getMaximumSize().width,
timeForecast.getMaximumSize().height));

add(timeForecast);
}

@Override
Expand Down
Loading