diff --git a/src/main/java/edu/project/Store.java b/src/main/java/edu/project/Store.java index 6335f8b..87b9fef 100644 --- a/src/main/java/edu/project/Store.java +++ b/src/main/java/edu/project/Store.java @@ -85,4 +85,29 @@ public void setWeatherForecast5Data(WeatherForecast5Data data) { public void addWeatherForecast5DataListener(Consumer listener) { weatherForecast5DataListeners.add(listener); } + + /* Zoom */ + + public void zoomIn() { + SwingUtilities.invokeLater(() -> { + zoomInListeners.forEach(listener -> listener.run()); + }); + } + + public void zoomOut() { + SwingUtilities.invokeLater(() -> { + zoomOutListeners.forEach(listener -> listener.run()); + }); + } + + private ArrayList zoomInListeners = new ArrayList<>(); + private ArrayList zoomOutListeners = new ArrayList<>(); + + public void addZoomInListener(Runnable listener) { + zoomInListeners.add(listener); + } + + public void addZoomOutListener(Runnable listener) { + zoomOutListeners.add(listener); + } } diff --git a/src/main/java/edu/project/components/App.java b/src/main/java/edu/project/components/App.java index 95ee27c..08495c0 100644 --- a/src/main/java/edu/project/components/App.java +++ b/src/main/java/edu/project/components/App.java @@ -55,5 +55,29 @@ public void mouseClicked(MouseEvent e) { Config.WINDOW_INIT_PADDING, (int) (Config.WINDOW_INIT_WIDTH * 0.4), Config.WINDOW_INIT_HEIGHT - Config.WINDOW_INIT_PADDING * 2); + + ZoomButtonGroup zoomButtonGroup = new ZoomButtonGroup(context); + + // Disable click-throughts to the overlapped map + zoomButtonGroup.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + e.consume(); + } + }); + + layers.add(zoomButtonGroup); + layers.setLayer(zoomButtonGroup, JLayeredPane.MODAL_LAYER + 1); + layers.addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent e) { + super.componentResized(e); + zoomButtonGroup.setBounds( + layers.getWidth() - 50 - 16, + layers.getHeight() - 100 - 16, + 50, + 100); + } + }); } } diff --git a/src/main/java/edu/project/components/GeoMap.java b/src/main/java/edu/project/components/GeoMap.java index e2bf9e8..a3e6e55 100644 --- a/src/main/java/edu/project/components/GeoMap.java +++ b/src/main/java/edu/project/components/GeoMap.java @@ -3,7 +3,7 @@ import java.awt.Point; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import java.awt.event.MouseWheelListener; +import java.awt.event.MouseWheelEvent; import java.io.IOException; import java.util.HashSet; @@ -29,9 +29,34 @@ public GeoMap(Context context) { addMouseListener(mouseInputListener); addMouseMotionListener(mouseInputListener); - // Add Zoom Interaction - MouseWheelListener mouseWheelListener = new ZoomMouseWheelListenerCursor(this); - addMouseWheelListener(mouseWheelListener); + // Add Zoom Interaction with a zoom-out limiter + addMouseWheelListener(new ZoomMouseWheelListenerCursor(this) { + @Override + public void mouseWheelMoved(MouseWheelEvent evt) { + if (evt.getWheelRotation() > 0 && !canZoomOut()) + return; + super.mouseWheelMoved(evt); + } + }); + + // Listen Zoom requests from store + context.store.addZoomInListener(() -> { + setZoom(getZoom() - 1); + }); + context.store.addZoomOutListener(() -> { + if (!canZoomOut()) + return; + setZoom(getZoom() + 1); + }); + + // Add Focus on click + addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + requestFocus(); + super.mouseClicked(e); + } + }); WaypointPainter waypointPainter = new WaypointPainter<>(); HashSet waypoints = new HashSet<>(); @@ -66,4 +91,11 @@ public void mouseClicked(MouseEvent event) { setCenterPosition(context.store.getLocation()); setZoom(Config.MAP_INIT_ZOOM); } + + private boolean canZoomOut() { + int zoom = getZoom(); + int maxZoom = getTileFactory().getInfo().getMaximumZoomLevel(); + int invertedZoom = maxZoom - zoom; + return (invertedZoom >= 4); + } } diff --git a/src/main/java/edu/project/components/TimeForecast.java b/src/main/java/edu/project/components/TimeForecast.java index 6cda6fe..29a88ac 100644 --- a/src/main/java/edu/project/components/TimeForecast.java +++ b/src/main/java/edu/project/components/TimeForecast.java @@ -21,22 +21,22 @@ 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(224, 224, 224); // 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 static final DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("h a") + .withLocale(Locale.ENGLISH); // Abbreviate the hour + private static final Color PANEL_COLOR = new Color(224, 224, 224); // 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 hourForecasts = new ArrayList<>(); - public TimeForecast(Context context) { - putClientProperty(FlatClientProperties.STYLE, - "border: 16,16,16,16,shade(@background,10%),,16"); - setOpaque(false); - setLayout(new BorderLayout()); + public TimeForecast(Context context) { + putClientProperty(FlatClientProperties.STYLE, + "border: 16,16,16,16,shade(@background,10%),,16"); + setOpaque(false); + setLayout(new BorderLayout()); JPanel mainPanel = new JPanel(new BorderLayout()); mainPanel.setOpaque(false); @@ -45,14 +45,14 @@ public TimeForecast(Context context) { titlePanel.setOpaque(false); titlePanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0)); - JLabel titleLabel = new JLabel("5-Hour Forecast"); + JLabel titleLabel = new JLabel("12-Hour Forecast"); titleLabel.setFont(new Font("Arial", Font.BOLD, 16)); titlePanel.add(titleLabel, BorderLayout.NORTH); JSeparator separator = new JSeparator(SwingConstants.HORIZONTAL); - separator.setForeground(Color.GRAY); + separator.setForeground(new Color(0, 0, 0, 0.2f)); + separator.setPreferredSize(new Dimension(separator.getPreferredSize().width, 2)); titlePanel.add(separator, BorderLayout.SOUTH); - mainPanel.add(titlePanel, BorderLayout.NORTH); contentPanel = new JPanel(); contentPanel.setOpaque(false); diff --git a/src/main/java/edu/project/components/WeatherForecastPanel.java b/src/main/java/edu/project/components/WeatherForecastPanel.java index 048ff18..410792c 100644 --- a/src/main/java/edu/project/components/WeatherForecastPanel.java +++ b/src/main/java/edu/project/components/WeatherForecastPanel.java @@ -42,7 +42,11 @@ public WeatherForecastPanel(Context context) { titleLabel.setFont(new Font("Arial", Font.BOLD, 16)); titlePanel.add(titleLabel); - // Add the title panel to the main panel + JSeparator separator = new JSeparator(SwingConstants.HORIZONTAL); + separator.setForeground(new Color(0, 0, 0, 0.2f)); + separator.setPreferredSize(new Dimension(separator.getPreferredSize().width, 2)); + titlePanel.add(separator, BorderLayout.SOUTH); + mainPanel.add(titlePanel, BorderLayout.NORTH); // Create the content panel diff --git a/src/main/java/edu/project/components/ZoomButtonGroup.java b/src/main/java/edu/project/components/ZoomButtonGroup.java new file mode 100644 index 0000000..15c589c --- /dev/null +++ b/src/main/java/edu/project/components/ZoomButtonGroup.java @@ -0,0 +1,33 @@ +package edu.project.components; + +import java.awt.Color; +import java.awt.Font; +import java.awt.GridLayout; + +import javax.swing.JButton; +import javax.swing.JPanel; + +import edu.project.Context; + +public class ZoomButtonGroup extends JPanel { + public ZoomButtonGroup(Context context) { + setOpaque(false); + setLayout(new GridLayout(2, 1)); + + JButton zoomInButton = new JButton("+"); + zoomInButton.setFont(new Font("Arial", Font.PLAIN, 32)); + zoomInButton.setForeground(Color.GRAY); + add(zoomInButton); + zoomInButton.addActionListener(e -> { + context.store.zoomIn(); + }); + + JButton zoomOutButton = new JButton("-"); + zoomOutButton.setForeground(Color.GRAY); + zoomOutButton.setFont(new Font("Arial", Font.PLAIN, 32)); + add(zoomOutButton); + zoomOutButton.addActionListener(e -> { + context.store.zoomOut(); + }); + } +}