张世豪
4 天以前 87d7cf316e983b0398b270de03a8092412af8487
src/set/Sets.java
@@ -13,9 +13,11 @@
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Point2D;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
/**
 * 设置对话框 - 参考Shouye.java样式
@@ -45,6 +47,7 @@
    private JLabel idleTrailDurationLabel;
    private JLabel boundaryLengthVisibleLabel;
    private JLabel measurementModeEnabledLabel;
    private JLabel manualBoundaryDrawingModeLabel;
    
    private JButton mowerIdEditBtn;
    private JButton mowerSizeEditBtn;
@@ -178,6 +181,10 @@
        JPanel measurementModePanel = createMeasurementModePanel();
        measurementModeEnabledLabel = (JLabel) measurementModePanel.getClientProperty("valueLabel");
        // 手动绘制边界模式设置项
        JPanel manualBoundaryDrawingPanel = createManualBoundaryDrawingPanel();
        manualBoundaryDrawingModeLabel = (JLabel) manualBoundaryDrawingPanel.getClientProperty("valueLabel");
        JPanel feedbackPanel = createFeedbackPanel();
        
        // APP版本
@@ -195,6 +202,7 @@
        addSettingItem(panel, idleTrailPanel, true);
        addSettingItem(panel, boundaryLengthPanel, true);
        addSettingItem(panel, measurementModePanel, true);
        addSettingItem(panel, manualBoundaryDrawingPanel, true);
        addSettingItem(panel, feedbackPanel, true);
        addSettingItem(panel, appVersionPanel, false);  // 最后一项不加分割线
        
@@ -469,6 +477,157 @@
    }
    
    /**
     * 创建手动绘制边界模式设置面板
     */
    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() {
@@ -593,6 +752,16 @@
            if (renderer != null) {
                renderer.repaint();
            }
            // 通知首页更新悬浮返回按钮显示状态
            shouye.updateSettingsReturnButtonVisibility();
        }
        // 如果开启,关闭系统设置页面并返回首页
        if (newValue) {
            SwingUtilities.invokeLater(() -> {
                setVisible(false);
                dispose();
            });
        }
    }
    
@@ -662,6 +831,16 @@
            if (renderer != null) {
                renderer.setBoundaryLengthVisible(newValue);
            }
            // 通知首页更新悬浮返回按钮显示状态
            shouye.updateSettingsReturnButtonVisibility();
        }
        // 如果开启,关闭系统设置页面并返回首页
        if (newValue) {
            SwingUtilities.invokeLater(() -> {
                setVisible(false);
                dispose();
            });
        }
    }
    
@@ -821,6 +1000,19 @@
            }
        }
        
        // 更新手动绘制边界模式状态
        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 ? 
@@ -1362,6 +1554,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) {
                            // 如果无法解析,从坐标字符串计算点数
                            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);