From 48ee74129bb09a817a0bbbabe860c4007b74c66b Mon Sep 17 00:00:00 2001
From: 826220679@qq.com <826220679@qq.com>
Date: 星期日, 21 十二月 2025 12:37:44 +0800
Subject: [PATCH] 新增了往返路径

---
 src/set/Sets.java |  808 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 803 insertions(+), 5 deletions(-)

diff --git a/src/set/Sets.java b/src/set/Sets.java
index b81eac5..ab09098 100644
--- a/src/set/Sets.java
+++ b/src/set/Sets.java
@@ -1,21 +1,22 @@
 package set;
 
 import baseStation.BaseStation;
-
+import gecaoji.Device;
+import gecaoji.MowerSafetyDistanceCalculator;
+import publicway.buttonset;
 import zhuye.MapRenderer;
 import zhuye.Shouye;
-import zhuye.buttonset;
-import set.Setsys;
-
+import zhuye.celiangmoshi;
 import javax.swing.*;
 import javax.swing.filechooser.FileNameExtensionFilter;
 
 import java.awt.*;
 import java.awt.event.*;
-import java.awt.geom.RoundRectangle2D;
+import java.awt.geom.Point2D;
 import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
 
 /**
  * 璁剧疆瀵硅瘽妗� - 鍙傝�僑houye.java鏍峰紡
@@ -34,6 +35,8 @@
     
     // 璁剧疆椤圭粍浠�
     private JLabel mowerIdLabel;
+    private JLabel mowerSizeLabel;
+    private JLabel mowingSafetyDistanceLabel;
     private JLabel baseStationIdLabel;
     private JLabel handheldMarkerLabel;
     private JLabel simCardNumberLabel;
@@ -42,8 +45,12 @@
     private JLabel appVersionLabel;
     private JLabel idleTrailDurationLabel;
     private JLabel boundaryLengthVisibleLabel;
+    private JLabel measurementModeEnabledLabel;
+    private JLabel manualBoundaryDrawingModeLabel;
     
     private JButton mowerIdEditBtn;
+    private JButton mowerSizeEditBtn;
+    private JButton mowingSafetyDistanceEditBtn;
     private JButton baseStationIdEditBtn;
     private JButton handheldEditBtn;
     private JButton checkUpdateBtn;
@@ -124,6 +131,18 @@
         mowerIdLabel = (JLabel) mowerIdPanel.getClientProperty("valueLabel");
         mowerIdEditBtn = (JButton) mowerIdPanel.getClientProperty("editButton");
 
+        // 鍓茶崏鏈洪暱瀹�
+        JPanel mowerSizePanel = createSettingItemPanel("鍓茶崏鏈洪暱瀹�",
+            formatMowerSize(), true);
+        mowerSizeLabel = (JLabel) mowerSizePanel.getClientProperty("valueLabel");
+        mowerSizeEditBtn = (JButton) mowerSizePanel.getClientProperty("editButton");
+
+        // 鍓茶崏瀹夊叏璺濈
+        JPanel mowingSafetyDistancePanel = createSettingItemPanel("鍓茶崏瀹夊叏璺濈",
+            formatMowingSafetyDistance(), true);
+        mowingSafetyDistanceLabel = (JLabel) mowingSafetyDistancePanel.getClientProperty("valueLabel");
+        mowingSafetyDistanceEditBtn = (JButton) mowingSafetyDistancePanel.getClientProperty("editButton");
+
         JPanel baseStationIdPanel = createSettingItemPanel("宸垎鍩哄噯绔欑紪鍙�",
             resolveBaseStationId(), true);
         baseStationIdLabel = (JLabel) baseStationIdPanel.getClientProperty("valueLabel");
@@ -156,6 +175,14 @@
         // 鏄剧ず杈圭晫璺濈璁剧疆椤�
         JPanel boundaryLengthPanel = createBoundaryLengthPanel();
         boundaryLengthVisibleLabel = (JLabel) boundaryLengthPanel.getClientProperty("valueLabel");
+        
+        // 寮�鍚祴閲忔ā寮忚缃」
+        JPanel measurementModePanel = createMeasurementModePanel();
+        measurementModeEnabledLabel = (JLabel) measurementModePanel.getClientProperty("valueLabel");
+        
+        // 鎵嬪姩缁樺埗杈圭晫妯″紡璁剧疆椤�
+        JPanel manualBoundaryDrawingPanel = createManualBoundaryDrawingPanel();
+        manualBoundaryDrawingModeLabel = (JLabel) manualBoundaryDrawingPanel.getClientProperty("valueLabel");
 
         JPanel feedbackPanel = createFeedbackPanel();
         
@@ -164,6 +191,8 @@
         
         // 娣诲姞璁剧疆椤癸紝浣跨敤鍒嗗壊绾垮垎闅�
         addSettingItem(panel, mowerIdPanel, true);
+        addSettingItem(panel, mowerSizePanel, true);
+        addSettingItem(panel, mowingSafetyDistancePanel, true);
         addSettingItem(panel, baseStationIdPanel, true);
         addSettingItem(panel, handheldPanel, true);
         addSettingItem(panel, simCardPanel, true);
@@ -171,6 +200,8 @@
         addSettingItem(panel, firmwarePanel, true);
         addSettingItem(panel, idleTrailPanel, true);
         addSettingItem(panel, boundaryLengthPanel, true);
+        addSettingItem(panel, measurementModePanel, true);
+        addSettingItem(panel, manualBoundaryDrawingPanel, true);
         addSettingItem(panel, feedbackPanel, true);
         addSettingItem(panel, appVersionPanel, false);  // 鏈�鍚庝竴椤逛笉鍔犲垎鍓茬嚎
         
@@ -201,6 +232,67 @@
         return seconds + "绉�";
     }
 
+    /**
+     * 灏嗗瓧绗︿覆鍊艰浆鎹负绫筹紙鍏煎鏃ф暟鎹紝濡傛灉鍊煎ぇ浜�100璁や负鏄帢绫筹紝闇�瑕侀櫎浠�100锛�
+     */
+    private double convertToMeters(String value) {
+        if (value == null || value.trim().isEmpty() || "-1".equals(value.trim())) {
+            return -1;
+        }
+        try {
+            double val = Double.parseDouble(value.trim());
+            // 濡傛灉鍊煎ぇ浜�100锛岃涓烘槸鍘樼背锛岄渶瑕佽浆鎹负绫�
+            if (val > 100) {
+                return val / 100.0;
+            }
+            return val;
+        } catch (NumberFormatException e) {
+            return -1;
+        }
+    }
+
+    /**
+     * 鏍煎紡鍖栨暟鍊间负绫筹紝淇濈暀2浣嶅皬鏁�
+     */
+    private String formatMeters(double value) {
+        if (value < 0) {
+            return "鏈缃�";
+        }
+        return String.format("%.2f", value) + "m";
+    }
+
+    private String formatMowerSize() {
+        Device device = Device.getActiveDevice();
+        if (device == null) {
+            return "鏈缃�";
+        }
+        String width = device.getMowerWidth();
+        String length = device.getMowerLength();
+        double widthMeters = convertToMeters(width);
+        double lengthMeters = convertToMeters(length);
+        
+        if (widthMeters < 0 && lengthMeters < 0) {
+            return "鏈缃�";
+        }
+        
+        String widthStr = widthMeters >= 0 ? formatMeters(widthMeters) : "鏈缃�";
+        String lengthStr = lengthMeters >= 0 ? formatMeters(lengthMeters) : "鏈缃�";
+        return lengthStr + " 脳 " + widthStr;
+    }
+
+    private String formatMowingSafetyDistance() {
+        Device device = Device.getActiveDevice();
+        if (device == null) {
+            return "鏈缃�";
+        }
+        String distance = device.getMowingSafetyDistance();
+        double distanceMeters = convertToMeters(distance);
+        if (distanceMeters < 0) {
+            return "鏈缃�";
+        }
+        return formatMeters(distanceMeters);
+    }
+
     
     private JPanel createSettingItemPanel(String title, String value, boolean editable) {
         JPanel panel = new JPanel(new GridBagLayout());
@@ -384,6 +476,295 @@
     }
     
     /**
+     * 鍒涘缓鎵嬪姩缁樺埗杈圭晫妯″紡璁剧疆闈㈡澘
+     */
+    private JPanel createManualBoundaryDrawingPanel() {
+        JPanel panel = new JPanel(new GridBagLayout());
+        panel.setOpaque(false);  // 閫忔槑鑳屾櫙
+        panel.setAlignmentX(Component.LEFT_ALIGNMENT);
+        panel.setMaximumSize(new Dimension(Integer.MAX_VALUE, ROW_HEIGHT));
+        panel.setPreferredSize(new Dimension(Integer.MAX_VALUE, ROW_HEIGHT));
+        panel.setMinimumSize(new Dimension(0, ROW_HEIGHT));
+        panel.setBorder(BorderFactory.createEmptyBorder(ITEM_PADDING, ITEM_PADDING, ITEM_PADDING, ITEM_PADDING));
+
+        GridBagConstraints gbc = new GridBagConstraints();
+
+        JLabel titleLabel = new JLabel("鎵嬪姩缁樺埗杈圭晫妯″紡");
+        titleLabel.setFont(new Font("寰蒋闆呴粦", Font.BOLD, 14));
+        titleLabel.setForeground(Color.BLACK);
+        titleLabel.setHorizontalAlignment(SwingConstants.RIGHT);
+        titleLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
+        // 娣诲姞鐐瑰嚮浜嬩欢锛屾樉绀哄潗鏍囧璇濇
+        titleLabel.addMouseListener(new MouseAdapter() {
+            @Override
+            public void mouseClicked(MouseEvent e) {
+                showManualBoundaryCoordinatesDialog();
+            }
+            
+            @Override
+            public void mouseEntered(MouseEvent e) {
+                titleLabel.setForeground(THEME_COLOR);
+            }
+            
+            @Override
+            public void mouseExited(MouseEvent e) {
+                titleLabel.setForeground(Color.BLACK);
+            }
+        });
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+        gbc.weightx = 0;
+        gbc.anchor = GridBagConstraints.EAST;
+        gbc.insets = new Insets(0, 0, 0, 12);
+        panel.add(titleLabel, gbc);
+
+        manualBoundaryDrawingModeLabel = new JLabel(setData.isManualBoundaryDrawingMode() ? "宸插紑鍚�" : "宸插叧闂�");
+        manualBoundaryDrawingModeLabel.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 14));
+        manualBoundaryDrawingModeLabel.setForeground(Color.DARK_GRAY);
+        gbc = new GridBagConstraints();
+        gbc.gridx = 1;
+        gbc.gridy = 0;
+        gbc.weightx = 1.0;
+        gbc.anchor = GridBagConstraints.EAST;
+        panel.add(manualBoundaryDrawingModeLabel, gbc);
+
+        panel.putClientProperty("valueLabel", manualBoundaryDrawingModeLabel);
+
+        // 鍒涘缓鍒囨崲鎸夐挳锛堜娇鐢ㄥ浘鏍囷級
+        JButton toggleBtn = createManualBoundaryDrawingToggleButton();
+        gbc = new GridBagConstraints();
+        gbc.gridx = 2;
+        gbc.gridy = 0;
+        gbc.weightx = 0;
+        gbc.anchor = GridBagConstraints.EAST;
+        panel.add(toggleBtn, gbc);
+        panel.putClientProperty("toggleButton", toggleBtn);
+
+        return panel;
+    }
+    
+    /**
+     * 鍒涘缓鎵嬪姩缁樺埗杈圭晫妯″紡鍒囨崲鎸夐挳
+     */
+    private JButton createManualBoundaryDrawingToggleButton() {
+        JButton button = new JButton();
+        button.setContentAreaFilled(false);
+        button.setBorder(null);
+        button.setFocusPainted(false);
+        button.setCursor(new Cursor(Cursor.HAND_CURSOR));
+        button.setPreferredSize(new Dimension(32, 32));
+        button.setMinimumSize(new Dimension(32, 32));
+        button.setMaximumSize(new Dimension(32, 32));
+        
+        updateManualBoundaryDrawingToggleButton(button);
+        
+        button.addActionListener(e -> toggleManualBoundaryDrawingMode(button));
+        
+        return button;
+    }
+    
+    /**
+     * 鏇存柊鎵嬪姩缁樺埗杈圭晫妯″紡鍒囨崲鎸夐挳鍥炬爣
+     */
+    private void updateManualBoundaryDrawingToggleButton(JButton button) {
+        boolean isEnabled = setData.isManualBoundaryDrawingMode();
+        try {
+            String iconPath = isEnabled ? "image/open.png" : "image/close.png";
+            ImageIcon icon = new ImageIcon(iconPath);
+            if (icon.getIconWidth() > 0) {
+                Image scaledImage = icon.getImage().getScaledInstance(32, 32, Image.SCALE_SMOOTH);
+                button.setIcon(new ImageIcon(scaledImage));
+                button.setText(null);
+            } else {
+                button.setIcon(null);
+                button.setText(isEnabled ? "寮�" : "鍏�");
+            }
+        } catch (Exception e) {
+            button.setIcon(null);
+            button.setText(isEnabled ? "寮�" : "鍏�");
+            System.err.println("鏃犳硶鍔犺浇鎵嬪姩缁樺埗杈圭晫妯″紡鍥炬爣: " + e.getMessage());
+        }
+    }
+    
+    /**
+     * 鍒囨崲鎵嬪姩缁樺埗杈圭晫妯″紡鐘舵��
+     */
+    private void toggleManualBoundaryDrawingMode(JButton button) {
+        boolean newValue = !setData.isManualBoundaryDrawingMode();
+        setData.setManualBoundaryDrawingMode(newValue);
+        
+        // 淇濆瓨鍒伴厤缃枃浠�
+        setData.updateProperty("manualBoundaryDrawingMode", String.valueOf(newValue));
+        
+        // 鏇存柊UI
+        if (manualBoundaryDrawingModeLabel != null) {
+            manualBoundaryDrawingModeLabel.setText(newValue ? "宸插紑鍚�" : "宸插叧闂�");
+        }
+        updateManualBoundaryDrawingToggleButton(button);
+        
+        // 閫氱煡MapRenderer鏇存柊鎵嬪姩缁樺埗杈圭晫妯″紡鐘舵��
+        Shouye shouye = Shouye.getInstance();
+        if (shouye != null) {
+            MapRenderer renderer = shouye.getMapRenderer();
+            if (renderer != null) {
+                renderer.setManualBoundaryDrawingMode(newValue);
+                if (!newValue) {
+                    // 濡傛灉鍏抽棴妯″紡锛屾竻绌哄凡缁樺埗鐨勭偣
+                    renderer.clearManualBoundaryPoints();
+                }
+            }
+            // 閫氱煡棣栭〉鏇存柊鎮诞杩斿洖鎸夐挳鏄剧ず鐘舵��
+            shouye.updateSettingsReturnButtonVisibility();
+        }
+        
+        // 濡傛灉寮�鍚紝鍏抽棴绯荤粺璁剧疆椤甸潰骞惰繑鍥為椤�
+        if (newValue) {
+            SwingUtilities.invokeLater(() -> {
+                setVisible(false);
+                dispose();
+            });
+        }
+    }
+    
+    /**
+     * 鍒涘缓寮�鍚祴閲忔ā寮忚缃潰鏉�
+     */
+    private JPanel createMeasurementModePanel() {
+        JPanel panel = new JPanel(new GridBagLayout());
+        panel.setOpaque(false);  // 閫忔槑鑳屾櫙
+        panel.setAlignmentX(Component.LEFT_ALIGNMENT);
+        panel.setMaximumSize(new Dimension(Integer.MAX_VALUE, ROW_HEIGHT));
+        panel.setPreferredSize(new Dimension(Integer.MAX_VALUE, ROW_HEIGHT));
+        panel.setMinimumSize(new Dimension(0, ROW_HEIGHT));
+        panel.setBorder(BorderFactory.createEmptyBorder(ITEM_PADDING, ITEM_PADDING, ITEM_PADDING, ITEM_PADDING));
+
+        GridBagConstraints gbc = new GridBagConstraints();
+
+        JLabel titleLabel = new JLabel("寮�鍚祴閲忔ā寮�");
+        titleLabel.setFont(new Font("寰蒋闆呴粦", Font.BOLD, 14));
+        titleLabel.setForeground(Color.BLACK);
+        titleLabel.setHorizontalAlignment(SwingConstants.RIGHT);
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+        gbc.weightx = 0;
+        gbc.anchor = GridBagConstraints.EAST;
+        gbc.insets = new Insets(0, 0, 0, 12);
+        panel.add(titleLabel, gbc);
+
+        measurementModeEnabledLabel = new JLabel(setData.isMeasurementModeEnabled() ? "宸插紑鍚�" : "宸插叧闂�");
+        measurementModeEnabledLabel.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 14));
+        measurementModeEnabledLabel.setForeground(Color.DARK_GRAY);
+        gbc = new GridBagConstraints();
+        gbc.gridx = 1;
+        gbc.gridy = 0;
+        gbc.weightx = 1.0;
+        gbc.anchor = GridBagConstraints.EAST;
+        panel.add(measurementModeEnabledLabel, gbc);
+
+        panel.putClientProperty("valueLabel", measurementModeEnabledLabel);
+
+        // 鍒涘缓鍒囨崲鎸夐挳锛堜娇鐢ㄥ浘鏍囷級
+        JButton toggleBtn = createMeasurementModeToggleButton();
+        gbc = new GridBagConstraints();
+        gbc.gridx = 2;
+        gbc.gridy = 0;
+        gbc.weightx = 0;
+        gbc.anchor = GridBagConstraints.EAST;
+        panel.add(toggleBtn, gbc);
+        panel.putClientProperty("toggleButton", toggleBtn);
+
+        return panel;
+    }
+    
+    /**
+     * 鍒涘缓娴嬮噺妯″紡鍒囨崲鎸夐挳
+     */
+    private JButton createMeasurementModeToggleButton() {
+        JButton button = new JButton();
+        button.setContentAreaFilled(false);
+        button.setBorder(null);
+        button.setFocusPainted(false);
+        button.setCursor(new Cursor(Cursor.HAND_CURSOR));
+        button.setPreferredSize(new Dimension(32, 32));
+        button.setMinimumSize(new Dimension(32, 32));
+        button.setMaximumSize(new Dimension(32, 32));
+        
+        updateMeasurementModeToggleButton(button);
+        
+        button.addActionListener(e -> toggleMeasurementMode(button));
+        
+        return button;
+    }
+    
+    /**
+     * 鏇存柊娴嬮噺妯″紡鍒囨崲鎸夐挳鍥炬爣
+     */
+    private void updateMeasurementModeToggleButton(JButton button) {
+        boolean isEnabled = setData.isMeasurementModeEnabled();
+        try {
+            String iconPath = isEnabled ? "image/open.png" : "image/close.png";
+            ImageIcon icon = new ImageIcon(iconPath);
+            if (icon.getIconWidth() > 0) {
+                Image scaledImage = icon.getImage().getScaledInstance(32, 32, Image.SCALE_SMOOTH);
+                button.setIcon(new ImageIcon(scaledImage));
+                button.setText(null);
+            } else {
+                button.setIcon(null);
+                button.setText(isEnabled ? "寮�" : "鍏�");
+            }
+        } catch (Exception e) {
+            button.setIcon(null);
+            button.setText(isEnabled ? "寮�" : "鍏�");
+            System.err.println("鏃犳硶鍔犺浇娴嬮噺妯″紡鍥炬爣: " + e.getMessage());
+        }
+    }
+    
+    /**
+     * 鍒囨崲娴嬮噺妯″紡鐘舵��
+     */
+    private void toggleMeasurementMode(JButton button) {
+        boolean newValue = !setData.isMeasurementModeEnabled();
+        setData.setMeasurementModeEnabled(newValue);
+        
+        // 淇濆瓨鍒伴厤缃枃浠�
+        setData.updateProperty("measurementModeEnabled", String.valueOf(newValue));
+        
+        // 鏇存柊UI
+        if (measurementModeEnabledLabel != null) {
+            measurementModeEnabledLabel.setText(newValue ? "宸插紑鍚�" : "宸插叧闂�");
+        }
+        updateMeasurementModeToggleButton(button);
+        
+        // 閫氱煡MapRenderer鏇存柊
+        Shouye shouye = Shouye.getInstance();
+        if (shouye != null) {
+            MapRenderer renderer = shouye.getMapRenderer();
+            if (renderer != null) {
+                renderer.setMeasurementMode(newValue);
+            }
+            if (newValue) {
+                celiangmoshi.start();
+            } else {
+                celiangmoshi.stop();
+            }
+            // 鍒锋柊鍦板浘鏄剧ず锛堥�氳繃MapRenderer瑙﹀彂閲嶇粯锛�
+            if (renderer != null) {
+                renderer.repaint();
+            }
+            // 閫氱煡棣栭〉鏇存柊鎮诞杩斿洖鎸夐挳鏄剧ず鐘舵��
+            shouye.updateSettingsReturnButtonVisibility();
+        }
+        
+        // 濡傛灉寮�鍚紝鍏抽棴绯荤粺璁剧疆椤甸潰骞惰繑鍥為椤�
+        if (newValue) {
+            SwingUtilities.invokeLater(() -> {
+                setVisible(false);
+                dispose();
+            });
+        }
+    }
+    
+    /**
      * 鍒涘缓杈圭晫璺濈鏄剧ず鍒囨崲鎸夐挳
      */
     private JButton createBoundaryLengthToggleButton() {
@@ -449,6 +830,16 @@
             if (renderer != null) {
                 renderer.setBoundaryLengthVisible(newValue);
             }
+            // 閫氱煡棣栭〉鏇存柊鎮诞杩斿洖鎸夐挳鏄剧ず鐘舵��
+            shouye.updateSettingsReturnButtonVisibility();
+        }
+        
+        // 濡傛灉寮�鍚紝鍏抽棴绯荤粺璁剧疆椤甸潰骞惰繑鍥為椤�
+        if (newValue) {
+            SwingUtilities.invokeLater(() -> {
+                setVisible(false);
+                dispose();
+            });
         }
     }
     
@@ -488,6 +879,11 @@
         // 浠嶴etsys绫诲姞杞芥暟鎹�
         setData.initializeFromProperties();
         baseStation.load();
+        // 浠巇evice.properties鍔犺浇璁惧鏁版嵁
+        Device device = Device.getActiveDevice();
+        if (device != null) {
+            device.initFromProperties();
+        }
         updateDisplay();
         // 鍔犺浇骞跺簲鐢ㄤ笂娆′繚瀛樼殑瑙嗗浘涓績鍧愭爣
         loadViewCenterFromProperties();
@@ -539,6 +935,16 @@
             mowerIdLabel.setText(setData.getMowerId() != null ? setData.getMowerId() : "鏈缃�");
         }
 
+        // 鏇存柊鍓茶崏鏈洪暱瀹芥樉绀�
+        if (mowerSizeLabel != null) {
+            mowerSizeLabel.setText(formatMowerSize());
+        }
+
+        // 鏇存柊鍓茶崏瀹夊叏璺濈鏄剧ず
+        if (mowingSafetyDistanceLabel != null) {
+            mowingSafetyDistanceLabel.setText(formatMowingSafetyDistance());
+        }
+
         if (baseStationIdLabel != null) {
             baseStationIdLabel.setText(resolveBaseStationId());
         }
@@ -580,6 +986,32 @@
             }
         }
         
+        // 鏇存柊娴嬮噺妯″紡鐘舵��
+        if (measurementModeEnabledLabel != null) {
+            measurementModeEnabledLabel.setText(setData.isMeasurementModeEnabled() ? "宸插紑鍚�" : "宸插叧闂�");
+        }
+        // 鏇存柊娴嬮噺妯″紡鍒囨崲鎸夐挳鍥炬爣
+        JPanel measurementModePanel = (JPanel) measurementModeEnabledLabel.getParent();
+        if (measurementModePanel != null) {
+            JButton toggleBtn = (JButton) measurementModePanel.getClientProperty("toggleButton");
+            if (toggleBtn != null) {
+                updateMeasurementModeToggleButton(toggleBtn);
+            }
+        }
+        
+        // 鏇存柊鎵嬪姩缁樺埗杈圭晫妯″紡鐘舵��
+        if (manualBoundaryDrawingModeLabel != null) {
+            manualBoundaryDrawingModeLabel.setText(setData.isManualBoundaryDrawingMode() ? "宸插紑鍚�" : "宸插叧闂�");
+        }
+        // 鏇存柊鎵嬪姩缁樺埗杈圭晫妯″紡鍒囨崲鎸夐挳鍥炬爣
+        JPanel manualBoundaryDrawingPanel = (JPanel) manualBoundaryDrawingModeLabel.getParent();
+        if (manualBoundaryDrawingPanel != null) {
+            JButton toggleBtn = (JButton) manualBoundaryDrawingPanel.getClientProperty("toggleButton");
+            if (toggleBtn != null) {
+                updateManualBoundaryDrawingToggleButton(toggleBtn);
+            }
+        }
+        
         // 鏇存柊APP鐗堟湰鏄剧ず
         if (appVersionLabel != null) {
             appVersionLabel.setText(setData.getAppVersion() != null ? 
@@ -623,6 +1055,16 @@
             mowerIdEditBtn.addActionListener(e -> editMowerId());
         }
 
+        // 鍓茶崏鏈洪暱瀹界紪杈戞寜閽簨浠�
+        if (mowerSizeEditBtn != null) {
+            mowerSizeEditBtn.addActionListener(e -> editMowerSize());
+        }
+
+        // 鍓茶崏瀹夊叏璺濈缂栬緫鎸夐挳浜嬩欢
+        if (mowingSafetyDistanceEditBtn != null) {
+            mowingSafetyDistanceEditBtn.addActionListener(e -> editMowingSafetyDistance());
+        }
+
         if (baseStationIdEditBtn != null) {
             baseStationIdEditBtn.addActionListener(e -> editBaseStationId());
         }
@@ -671,6 +1113,181 @@
         }
     }
 
+    private void editMowerSize() {
+        Device device = Device.getActiveDevice();
+        if (device == null) {
+            JOptionPane.showMessageDialog(this, "璁惧鏈垵濮嬪寲", "閿欒", JOptionPane.ERROR_MESSAGE);
+            return;
+        }
+
+        // 鑾峰彇褰撳墠鍊煎苟杞崲涓虹背锛堝吋瀹规棫鏁版嵁锛�
+        double currentLengthMeters = convertToMeters(device.getMowerLength());
+        double currentWidthMeters = convertToMeters(device.getMowerWidth());
+        
+        String currentLengthStr = currentLengthMeters >= 0 ? String.format("%.2f", currentLengthMeters) : "";
+        String currentWidthStr = currentWidthMeters >= 0 ? String.format("%.2f", currentWidthMeters) : "";
+
+        // 鍒涘缓杈撳叆瀵硅瘽妗�
+        JPanel inputPanel = new JPanel(new GridLayout(2, 2, 5, 5));
+        inputPanel.add(new JLabel("闀垮害(m):"));
+        JTextField lengthField = new JTextField(currentLengthStr);
+        inputPanel.add(lengthField);
+        inputPanel.add(new JLabel("瀹藉害(m):"));
+        JTextField widthField = new JTextField(currentWidthStr);
+        inputPanel.add(widthField);
+
+        int result = JOptionPane.showConfirmDialog(this,
+            inputPanel,
+            "淇敼鍓茶崏鏈洪暱瀹�",
+            JOptionPane.OK_CANCEL_OPTION,
+            JOptionPane.QUESTION_MESSAGE);
+
+        if (result == JOptionPane.OK_OPTION) {
+            String newLength = lengthField.getText().trim();
+            String newWidth = widthField.getText().trim();
+
+            // 楠岃瘉杈撳叆
+            if (newLength.isEmpty() && newWidth.isEmpty()) {
+                JOptionPane.showMessageDialog(this, "闀垮害鍜屽搴︿笉鑳藉悓鏃朵负绌�", "鎻愮ず", JOptionPane.WARNING_MESSAGE);
+                return;
+            }
+
+            double lengthValue = -1;
+            double widthValue = -1;
+
+            if (!newLength.isEmpty()) {
+                try {
+                    lengthValue = Double.parseDouble(newLength);
+                    if (lengthValue < 0) {
+                        JOptionPane.showMessageDialog(this, "闀垮害蹇呴』澶т簬绛変簬0", "鎻愮ず", JOptionPane.WARNING_MESSAGE);
+                        return;
+                    }
+                } catch (NumberFormatException e) {
+                    JOptionPane.showMessageDialog(this, "闀垮害蹇呴』鏄湁鏁堢殑鏁板瓧", "鎻愮ず", JOptionPane.WARNING_MESSAGE);
+                    return;
+                }
+            }
+
+            if (!newWidth.isEmpty()) {
+                try {
+                    widthValue = Double.parseDouble(newWidth);
+                    if (widthValue < 0) {
+                        JOptionPane.showMessageDialog(this, "瀹藉害蹇呴』澶т簬绛変簬0", "鎻愮ず", JOptionPane.WARNING_MESSAGE);
+                        return;
+                    }
+                } catch (NumberFormatException e) {
+                    JOptionPane.showMessageDialog(this, "瀹藉害蹇呴』鏄湁鏁堢殑鏁板瓧", "鎻愮ず", JOptionPane.WARNING_MESSAGE);
+                    return;
+                }
+            }
+
+            // 鏇存柊璁惧灞炴�э紙淇濆瓨涓虹背锛屼繚鐣�2浣嶅皬鏁帮級
+            if (lengthValue >= 0) {
+                String lengthStr = String.format("%.2f", lengthValue);
+                device.setMowerLength(lengthStr);
+                device.updateField("mowerLength", lengthStr);
+            } else {
+                device.setMowerLength("-1");
+                device.updateField("mowerLength", "-1");
+            }
+
+            if (widthValue >= 0) {
+                String widthStr = String.format("%.2f", widthValue);
+                device.setMowerWidth(widthStr);
+                device.updateField("mowerWidth", widthStr);
+            } else {
+                device.setMowerWidth("-1");
+                device.updateField("mowerWidth", "-1");
+            }
+
+            // 濡傛灉闀垮害鍜屽搴﹂兘鏈夋晥锛岃嚜鍔ㄨ绠楀畨鍏ㄨ窛绂�
+            if (lengthValue > 0 && widthValue > 0) {
+                try {
+                    double safetyDistance = MowerSafetyDistanceCalculator.calculateSafetyDistance(lengthValue, widthValue);
+                    String safetyDistanceStr = String.format("%.2f", safetyDistance);
+                    device.setMowingSafetyDistance(safetyDistanceStr);
+                    device.updateField("mowingSafetyDistance", safetyDistanceStr);
+                    
+                    // 鏇存柊瀹夊叏璺濈鏄剧ず
+                    if (mowingSafetyDistanceLabel != null) {
+                        mowingSafetyDistanceLabel.setText(formatMowingSafetyDistance());
+                    }
+                } catch (IllegalArgumentException e) {
+                    // 濡傛灉璁$畻澶辫触锛屼笉鏇存柊瀹夊叏璺濈
+                    System.err.println("璁$畻瀹夊叏璺濈澶辫触: " + e.getMessage());
+                }
+            }
+
+            // 淇濆瓨鍒癲evice.properties
+            device.saveToProperties();
+
+            // 鏇存柊鏄剧ず
+            if (mowerSizeLabel != null) {
+                mowerSizeLabel.setText(formatMowerSize());
+            }
+            JOptionPane.showMessageDialog(this, "鍓茶崏鏈洪暱瀹芥洿鏂版垚鍔�" + 
+                (lengthValue > 0 && widthValue > 0 ? "锛屽畨鍏ㄨ窛绂诲凡鑷姩璁$畻" : ""), 
+                "鎴愬姛", JOptionPane.INFORMATION_MESSAGE);
+        }
+    }
+
+    private void editMowingSafetyDistance() {
+        Device device = Device.getActiveDevice();
+        if (device == null) {
+            JOptionPane.showMessageDialog(this, "璁惧鏈垵濮嬪寲", "閿欒", JOptionPane.ERROR_MESSAGE);
+            return;
+        }
+
+        // 鑾峰彇褰撳墠鍊煎苟杞崲涓虹背锛堝吋瀹规棫鏁版嵁锛�
+        double currentDistanceMeters = convertToMeters(device.getMowingSafetyDistance());
+        String currentValueStr = currentDistanceMeters >= 0 ? String.format("%.2f", currentDistanceMeters) : "";
+
+        String newValue = (String) JOptionPane.showInputDialog(this,
+            "璇疯緭鍏ュ壊鑽夊畨鍏ㄨ窛绂�(鍗曚綅:m):",
+            "淇敼鍓茶崏瀹夊叏璺濈",
+            JOptionPane.QUESTION_MESSAGE,
+            null,
+            null,
+            currentValueStr);
+
+        if (newValue == null) {
+            return; // 鐢ㄦ埛鍙栨秷
+        }
+
+        newValue = newValue.trim();
+        if (newValue.isEmpty()) {
+            JOptionPane.showMessageDialog(this, "鍓茶崏瀹夊叏璺濈涓嶈兘涓虹┖", "鎻愮ず", JOptionPane.WARNING_MESSAGE);
+            return;
+        }
+
+        // 楠岃瘉杈撳叆
+        double distanceValue;
+        try {
+            distanceValue = Double.parseDouble(newValue);
+            if (distanceValue < 0) {
+                JOptionPane.showMessageDialog(this, "鍓茶崏瀹夊叏璺濈蹇呴』澶т簬绛変簬0", "鎻愮ず", JOptionPane.WARNING_MESSAGE);
+                return;
+            }
+        } catch (NumberFormatException e) {
+            JOptionPane.showMessageDialog(this, "鍓茶崏瀹夊叏璺濈蹇呴』鏄湁鏁堢殑鏁板瓧", "鎻愮ず", JOptionPane.WARNING_MESSAGE);
+            return;
+        }
+
+        // 鏇存柊璁惧灞炴�э紙淇濆瓨涓虹背锛屼繚鐣�2浣嶅皬鏁帮級
+        String distanceStr = String.format("%.2f", distanceValue);
+        device.setMowingSafetyDistance(distanceStr);
+        device.updateField("mowingSafetyDistance", distanceStr);
+
+        // 淇濆瓨鍒癲evice.properties
+        device.saveToProperties();
+
+        // 鏇存柊鏄剧ず
+        if (mowingSafetyDistanceLabel != null) {
+            mowingSafetyDistanceLabel.setText(formatMowingSafetyDistance());
+        }
+        JOptionPane.showMessageDialog(this, "鍓茶崏瀹夊叏璺濈鏇存柊鎴愬姛", "鎴愬姛", JOptionPane.INFORMATION_MESSAGE);
+    }
+
     private void editHandheldMarkerId() {
         String currentValue = setData.getHandheldMarkerId() != null ? setData.getHandheldMarkerId() : "";
         String newValue = (String) JOptionPane.showInputDialog(this,
@@ -936,6 +1553,187 @@
         }
     }
     
+    /**
+     * 鏄剧ず鎵嬪姩缁樺埗杈圭晫鍧愭爣瀵硅瘽妗�
+     */
+    private void showManualBoundaryCoordinatesDialog() {
+        // 浠� shoudongbianjie.properties 鏂囦欢璇诲彇鍧愭爣
+        String coordinates = null;
+        int pointCount = 0;
+        
+        try {
+            java.util.Properties props = new java.util.Properties();
+            java.io.File file = new java.io.File("shoudongbianjie.properties");
+            
+            if (file.exists()) {
+                try (java.io.FileInputStream input = new java.io.FileInputStream(file)) {
+                    props.load(input);
+                    coordinates = props.getProperty("boundaryCoordinates");
+                    String pointCountStr = props.getProperty("pointCount");
+                    if (pointCountStr != null && !pointCountStr.trim().isEmpty()) {
+                        try {
+                            pointCount = Integer.parseInt(pointCountStr.trim());
+                        } catch (NumberFormatException e) {
+                            // 濡傛灉鏃犳硶瑙f瀽锛屼粠鍧愭爣瀛楃涓茶绠楃偣鏁�
+                            if (coordinates != null && !coordinates.trim().isEmpty()) {
+                                pointCount = coordinates.split(";").length;
+                            }
+                        }
+                    } else if (coordinates != null && !coordinates.trim().isEmpty()) {
+                        // 濡傛灉娌℃湁鐐规暟閲忥紝浠庡潗鏍囧瓧绗︿覆璁$畻
+                        pointCount = coordinates.split(";").length;
+                    }
+                }
+            }
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            JOptionPane.showMessageDialog(this, 
+                "璇诲彇鍧愭爣鏂囦欢澶辫触: " + ex.getMessage(), 
+                "閿欒", 
+                JOptionPane.ERROR_MESSAGE);
+            return;
+        }
+        
+        // 濡傛灉娌℃湁鍧愭爣鏁版嵁锛屾樉绀烘彁绀�
+        if (coordinates == null || coordinates.trim().isEmpty()) {
+            JOptionPane.showMessageDialog(this, 
+                "褰撳墠娌℃湁淇濆瓨鐨勮竟鐣屽潗鏍�", 
+                "鎻愮ず", 
+                JOptionPane.INFORMATION_MESSAGE);
+            return;
+        }
+        
+        // 鍒涘缓瀵硅瘽妗� - 瀹藉害鍜岀郴缁熻缃〉闈竴鏍凤紙400锛�
+        JDialog dialog = new JDialog(this, "鎵嬪姩缁樺埗杈圭晫鍧愭爣", true);
+        dialog.setLayout(new BorderLayout(0, 12));
+        dialog.setResizable(true);
+        dialog.setPreferredSize(new Dimension(400, 400));
+        dialog.setSize(new Dimension(400, 400));
+        dialog.setMinimumSize(new Dimension(400, 300));
+        
+        JPanel content = new JPanel();
+        content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS));
+        content.setBorder(BorderFactory.createEmptyBorder(20, 24, 20, 24));
+        dialog.add(content, BorderLayout.CENTER);
+        
+        // 鏍囬
+        String titleText = pointCount > 0 
+            ? "鍧愭爣鐐瑰垪琛紙鍏� " + pointCount + " 涓偣锛夛細"
+            : "鍧愭爣鐐瑰垪琛細";
+        JLabel titleLabel = new JLabel(titleText);
+        titleLabel.setFont(new Font("寰蒋闆呴粦", Font.BOLD, 14));
+        titleLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
+        content.add(titleLabel);
+        
+        content.add(Box.createRigidArea(new Dimension(0, 10)));
+        
+        // 鍧愭爣鏂囨湰鍖哄煙
+        JTextArea coordinatesArea = new JTextArea(coordinates);
+        coordinatesArea.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 12));
+        coordinatesArea.setLineWrap(true);
+        coordinatesArea.setWrapStyleWord(false);
+        coordinatesArea.setEditable(false);
+        coordinatesArea.setBackground(Color.WHITE);
+        JScrollPane scrollPane = new JScrollPane(coordinatesArea);
+        scrollPane.setAlignmentX(Component.LEFT_ALIGNMENT);
+        scrollPane.setPreferredSize(new Dimension(0, 200));
+        content.add(scrollPane);
+        
+        content.add(Box.createRigidArea(new Dimension(0, 16)));
+        
+        // 鎸夐挳闈㈡澘
+        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 10, 0));
+        buttonPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
+        
+        // 鍒涘缓澶嶅埗鎸夐挳锛屼娇鐢ㄥ浘鏍�
+        JButton copyButton = new JButton();
+        try {
+            ImageIcon copyIcon = new ImageIcon("image/fuzhi.png");
+            if (copyIcon.getIconWidth() > 0) {
+                // 璋冩暣鍥炬爣澶у皬
+                Image scaledImage = copyIcon.getImage().getScaledInstance(32, 32, Image.SCALE_SMOOTH);
+                copyButton.setIcon(new ImageIcon(scaledImage));
+            } else {
+                copyButton.setText("澶嶅埗鍧愭爣");
+            }
+        } catch (Exception ex) {
+            copyButton.setText("澶嶅埗鍧愭爣");
+            System.err.println("鏃犳硶鍔犺浇澶嶅埗鍥炬爣: " + ex.getMessage());
+        }
+        copyButton.setContentAreaFilled(false);
+        copyButton.setBorder(null);
+        copyButton.setFocusPainted(false);
+        copyButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
+        copyButton.setToolTipText("澶嶅埗鍧愭爣");
+        
+        // 鍔犺浇鎴愬姛鍥炬爣
+        ImageIcon successIcon = null;
+        try {
+            ImageIcon originalSuccessIcon = new ImageIcon("image/fuzhisucc.png");
+            if (originalSuccessIcon.getIconWidth() > 0) {
+                Image scaledSuccessImage = originalSuccessIcon.getImage().getScaledInstance(32, 32, Image.SCALE_SMOOTH);
+                successIcon = new ImageIcon(scaledSuccessImage);
+            }
+        } catch (Exception ex) {
+            System.err.println("鏃犳硶鍔犺浇鎴愬姛鍥炬爣: " + ex.getMessage());
+        }
+        
+        final ImageIcon finalSuccessIcon = successIcon;
+        final ImageIcon originalCopyIcon = (ImageIcon) copyButton.getIcon();
+        
+        copyButton.addActionListener(e -> {
+            String text = coordinatesArea.getText();
+            if (text != null && !text.trim().isEmpty()) {
+                java.awt.Toolkit.getDefaultToolkit().getSystemClipboard().setContents(
+                    new java.awt.datatransfer.StringSelection(text), null);
+                
+                // 鍒囨崲涓烘垚鍔熷浘鏍�
+                if (finalSuccessIcon != null) {
+                    copyButton.setIcon(finalSuccessIcon);
+                }
+                
+                // 2绉掑悗鎭㈠涓哄師濮嬪浘鏍�
+                Timer restoreTimer = new Timer(2000, evt -> {
+                    if (originalCopyIcon != null) {
+                        copyButton.setIcon(originalCopyIcon);
+                    }
+                });
+                restoreTimer.setRepeats(false);
+                restoreTimer.start();
+            }
+        });
+        
+        // 鍒涘缓鍏抽棴鎸夐挳锛屼娇鐢ㄥ浘鏍�
+        JButton closeButton = new JButton();
+        try {
+            ImageIcon closeIcon = new ImageIcon("image/closepage.png");
+            if (closeIcon.getIconWidth() > 0) {
+                // 璋冩暣鍥炬爣澶у皬
+                Image scaledImage = closeIcon.getImage().getScaledInstance(32, 32, Image.SCALE_SMOOTH);
+                closeButton.setIcon(new ImageIcon(scaledImage));
+            } else {
+                closeButton.setText("鍏抽棴");
+            }
+        } catch (Exception ex) {
+            closeButton.setText("鍏抽棴");
+            System.err.println("鏃犳硶鍔犺浇鍏抽棴鍥炬爣: " + ex.getMessage());
+        }
+        closeButton.setContentAreaFilled(false);
+        closeButton.setBorder(null);
+        closeButton.setFocusPainted(false);
+        closeButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
+        closeButton.setToolTipText("鍏抽棴");
+        closeButton.addActionListener(e -> dialog.dispose());
+        
+        buttonPanel.add(copyButton);
+        buttonPanel.add(closeButton);
+        content.add(buttonPanel);
+        
+        dialog.pack();
+        dialog.setLocationRelativeTo(this);
+        dialog.setVisible(true);
+    }
+    
     private void checkForUpdates() {
         // 妯℃嫙妫�鏌ユ洿鏂拌繃绋�
         checkUpdateBtn.setEnabled(false);

--
Gitblit v1.10.0