From d825d74b260717ef6cfb564fdf54c882fe7ebb43 Mon Sep 17 00:00:00 2001 From: showman-1 Date: Fri, 6 Mar 2026 13:50:08 +0500 Subject: [PATCH 1/7] add wind "Menu" and "exit" --- robots/src/gui/MainApplicationFrame.java | 85 ++++++++++++++++++------ 1 file changed, 63 insertions(+), 22 deletions(-) diff --git a/robots/src/gui/MainApplicationFrame.java b/robots/src/gui/MainApplicationFrame.java index 62e943e..1cb03df 100644 --- a/robots/src/gui/MainApplicationFrame.java +++ b/robots/src/gui/MainApplicationFrame.java @@ -10,6 +10,7 @@ import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; +import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; @@ -18,26 +19,26 @@ /** * Что требуется сделать: - * 1. Метод создания меню перегружен функционалом и трудно читается. + * 1. Метод создания меню перегружен функционалом и трудно читается. * Следует разделить его на серию более простых методов (или вообще выделить отдельный класс). * */ public class MainApplicationFrame extends JFrame { private final JDesktopPane desktopPane = new JDesktopPane(); - + public MainApplicationFrame() { //Make the big window be indented 50 pixels from each edge //of the screen. - int inset = 50; + int inset = 50; Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); setBounds(inset, inset, - screenSize.width - inset*2, - screenSize.height - inset*2); + screenSize.width - inset*2, + screenSize.height - inset*2); setContentPane(desktopPane); - - + + LogWindow logWindow = createLogWindow(); addWindow(logWindow); @@ -46,9 +47,9 @@ public MainApplicationFrame() { addWindow(gameWindow); setJMenuBar(generateMenuBar()); - setDefaultCloseOperation(EXIT_ON_CLOSE); + setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); } - + protected LogWindow createLogWindow() { LogWindow logWindow = new LogWindow(Logger.getDefaultLogSource()); @@ -59,21 +60,21 @@ protected LogWindow createLogWindow() Logger.debug("Протокол работает"); return logWindow; } - + protected void addWindow(JInternalFrame frame) { desktopPane.add(frame); frame.setVisible(true); } - + // protected JMenuBar createMenuBar() { // JMenuBar menuBar = new JMenuBar(); -// +// // //Set up the lone menu. // JMenu menu = new JMenu("Document"); // menu.setMnemonic(KeyEvent.VK_D); // menuBar.add(menu); -// +// // //Set up the first menu item. // JMenuItem menuItem = new JMenuItem("New"); // menuItem.setMnemonic(KeyEvent.VK_N); @@ -82,28 +83,42 @@ protected void addWindow(JInternalFrame frame) // menuItem.setActionCommand("new"); //// menuItem.addActionListener(this); // menu.add(menuItem); -// +// // //Set up the second menu item. // menuItem = new JMenuItem("Quit"); // menuItem.setMnemonic(KeyEvent.VK_Q); // menuItem.setAccelerator(KeyStroke.getKeyStroke( // KeyEvent.VK_Q, ActionEvent.ALT_MASK)); // menuItem.setActionCommand("quit"); -//// menuItem.addActionListener(this); + //// menuItem.addActionListener(this); // menu.add(menuItem); -// +// // return menuBar; // } - + private JMenuBar generateMenuBar() { JMenuBar menuBar = new JMenuBar(); - + // НОВОЕ МЕНЮ "Файл" + JMenu fileMenu = new JMenu("Файл"); + fileMenu.setMnemonic(KeyEvent.VK_F); + + // Пункт "Выход" + { + JMenuItem exitMenuItem = new JMenuItem("Выход", KeyEvent.VK_X); + exitMenuItem.addActionListener((event) -> { + exitApplication(); + }); + fileMenu.add(exitMenuItem); + } + + menuBar.add(fileMenu); + JMenu lookAndFeelMenu = new JMenu("Режим отображения"); lookAndFeelMenu.setMnemonic(KeyEvent.VK_V); lookAndFeelMenu.getAccessibleContext().setAccessibleDescription( "Управление режимом отображения приложения"); - + { JMenuItem systemLookAndFeel = new JMenuItem("Системная схема", KeyEvent.VK_S); systemLookAndFeel.addActionListener((event) -> { @@ -126,7 +141,7 @@ private JMenuBar generateMenuBar() testMenu.setMnemonic(KeyEvent.VK_T); testMenu.getAccessibleContext().setAccessibleDescription( "Тестовые команды"); - + { JMenuItem addLogMessageItem = new JMenuItem("Сообщение в лог", KeyEvent.VK_S); addLogMessageItem.addActionListener((event) -> { @@ -139,7 +154,7 @@ private JMenuBar generateMenuBar() menuBar.add(testMenu); return menuBar; } - + private void setLookAndFeel(String className) { try @@ -148,9 +163,35 @@ private void setLookAndFeel(String className) SwingUtilities.updateComponentTreeUI(this); } catch (ClassNotFoundException | InstantiationException - | IllegalAccessException | UnsupportedLookAndFeelException e) + | IllegalAccessException | UnsupportedLookAndFeelException e) { // just ignore } } + /** + * НОВЫЙ МЕТОД: Обработка выхода из приложения с подтверждением + */ + private void exitApplication() + { + // Настраиваем кнопки диалога на русском языке + Object[] options = {"Да", "Нет", "Отмена"}; + + int result = JOptionPane.showOptionDialog( + this, // родительский компонент + "Вы действительно хотите выйти из приложения?", // сообщение + "Подтверждение выхода", // заголовок + JOptionPane.YES_NO_CANCEL_OPTION, // тип опций + JOptionPane.QUESTION_MESSAGE, // тип сообщения + null, // иконка (по умолчанию) + options, // массив кнопок + options[1]); // кнопка по умолчанию ("Нет") + + // Обрабатываем результат + if (result == JOptionPane.YES_OPTION) { + // Пользователь подтвердил выход + Logger.debug("Приложение завершает работу"); + System.exit(0); + } + // В остальных случаях (Нет, Отмена, закрытие диалога) просто возвращаемся + } } From 2b494874df8857859aae526e2773dba84d808194 Mon Sep 17 00:00:00 2001 From: showman-1 Date: Fri, 6 Mar 2026 13:50:56 +0500 Subject: [PATCH 2/7] add wind "Menu" and "exit" --- robots/src/gui/MainApplicationFrame.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/robots/src/gui/MainApplicationFrame.java b/robots/src/gui/MainApplicationFrame.java index 1cb03df..e962254 100644 --- a/robots/src/gui/MainApplicationFrame.java +++ b/robots/src/gui/MainApplicationFrame.java @@ -186,7 +186,7 @@ private void exitApplication() options, // массив кнопок options[1]); // кнопка по умолчанию ("Нет") - // Обрабатываем результат + // Обрабатываем результа if (result == JOptionPane.YES_OPTION) { // Пользователь подтвердил выход Logger.debug("Приложение завершает работу"); From 16961b9706969b2b7aec25d5529e64e6c1e61378 Mon Sep 17 00:00:00 2001 From: showman-1 Date: Tue, 24 Mar 2026 14:55:19 +0500 Subject: [PATCH 3/7] division into methods --- robots/src/gui/MainApplicationFrame.java | 189 ++++++++++++----------- 1 file changed, 95 insertions(+), 94 deletions(-) diff --git a/robots/src/gui/MainApplicationFrame.java b/robots/src/gui/MainApplicationFrame.java index e962254..41c99bd 100644 --- a/robots/src/gui/MainApplicationFrame.java +++ b/robots/src/gui/MainApplicationFrame.java @@ -17,19 +17,11 @@ import log.Logger; -/** - * Что требуется сделать: - * 1. Метод создания меню перегружен функционалом и трудно читается. - * Следует разделить его на серию более простых методов (или вообще выделить отдельный класс). - * - */ public class MainApplicationFrame extends JFrame { private final JDesktopPane desktopPane = new JDesktopPane(); public MainApplicationFrame() { - //Make the big window be indented 50 pixels from each edge - //of the screen. int inset = 50; Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); setBounds(inset, inset, @@ -38,7 +30,6 @@ public MainApplicationFrame() { setContentPane(desktopPane); - LogWindow logWindow = createLogWindow(); addWindow(logWindow); @@ -46,7 +37,7 @@ public MainApplicationFrame() { gameWindow.setSize(400, 400); addWindow(gameWindow); - setJMenuBar(generateMenuBar()); + setJMenuBar(createMenuBar()); setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); } @@ -67,92 +58,108 @@ protected void addWindow(JInternalFrame frame) frame.setVisible(true); } -// protected JMenuBar createMenuBar() { -// JMenuBar menuBar = new JMenuBar(); -// -// //Set up the lone menu. -// JMenu menu = new JMenu("Document"); -// menu.setMnemonic(KeyEvent.VK_D); -// menuBar.add(menu); -// -// //Set up the first menu item. -// JMenuItem menuItem = new JMenuItem("New"); -// menuItem.setMnemonic(KeyEvent.VK_N); -// menuItem.setAccelerator(KeyStroke.getKeyStroke( -// KeyEvent.VK_N, ActionEvent.ALT_MASK)); -// menuItem.setActionCommand("new"); -//// menuItem.addActionListener(this); -// menu.add(menuItem); -// -// //Set up the second menu item. -// menuItem = new JMenuItem("Quit"); -// menuItem.setMnemonic(KeyEvent.VK_Q); -// menuItem.setAccelerator(KeyStroke.getKeyStroke( -// KeyEvent.VK_Q, ActionEvent.ALT_MASK)); -// menuItem.setActionCommand("quit"); - //// menuItem.addActionListener(this); -// menu.add(menuItem); -// -// return menuBar; -// } - - private JMenuBar generateMenuBar() + /** + * Главный метод создания меню - собирает все части воедино + */ + private JMenuBar createMenuBar() { JMenuBar menuBar = new JMenuBar(); - // НОВОЕ МЕНЮ "Файл" + + menuBar.add(createFileMenu()); + menuBar.add(createLookAndFeelMenu()); + menuBar.add(createTestMenu()); + + return menuBar; + } + + /** + * Создает меню "Файл" с пунктом "Выход" + */ + private JMenu createFileMenu() + { JMenu fileMenu = new JMenu("Файл"); fileMenu.setMnemonic(KeyEvent.VK_F); + fileMenu.add(createExitMenuItem()); + return fileMenu; + } - // Пункт "Выход" - { - JMenuItem exitMenuItem = new JMenuItem("Выход", KeyEvent.VK_X); - exitMenuItem.addActionListener((event) -> { - exitApplication(); - }); - fileMenu.add(exitMenuItem); - } - - menuBar.add(fileMenu); + /** + * Создает пункт меню "Выход" + */ + private JMenuItem createExitMenuItem() + { + JMenuItem exitMenuItem = new JMenuItem("Выход", KeyEvent.VK_X); + exitMenuItem.addActionListener((event) -> exitApplication()); + return exitMenuItem; + } + /** + * Создает меню "Режим отображения" с пунктами смены темы + */ + private JMenu createLookAndFeelMenu() + { JMenu lookAndFeelMenu = new JMenu("Режим отображения"); lookAndFeelMenu.setMnemonic(KeyEvent.VK_V); lookAndFeelMenu.getAccessibleContext().setAccessibleDescription( "Управление режимом отображения приложения"); - { - JMenuItem systemLookAndFeel = new JMenuItem("Системная схема", KeyEvent.VK_S); - systemLookAndFeel.addActionListener((event) -> { - setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - this.invalidate(); - }); - lookAndFeelMenu.add(systemLookAndFeel); - } + lookAndFeelMenu.add(createSystemLookAndFeelMenuItem()); + lookAndFeelMenu.add(createCrossplatformLookAndFeelMenuItem()); - { - JMenuItem crossplatformLookAndFeel = new JMenuItem("Универсальная схема", KeyEvent.VK_S); - crossplatformLookAndFeel.addActionListener((event) -> { - setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); - this.invalidate(); - }); - lookAndFeelMenu.add(crossplatformLookAndFeel); - } + return lookAndFeelMenu; + } + /** + * Создает пункт меню "Системная схема" + */ + private JMenuItem createSystemLookAndFeelMenuItem() + { + JMenuItem systemLookAndFeel = new JMenuItem("Системная схема", KeyEvent.VK_S); + systemLookAndFeel.addActionListener((event) -> { + setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + this.invalidate(); + }); + return systemLookAndFeel; + } + + /** + * Создает пункт меню "Универсальная схема" + */ + private JMenuItem createCrossplatformLookAndFeelMenuItem() + { + JMenuItem crossplatformLookAndFeel = new JMenuItem("Универсальная схема", KeyEvent.VK_S); + crossplatformLookAndFeel.addActionListener((event) -> { + setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); + this.invalidate(); + }); + return crossplatformLookAndFeel; + } + + /** + * Создает меню "Тесты" с тестовыми командами + */ + private JMenu createTestMenu() + { JMenu testMenu = new JMenu("Тесты"); testMenu.setMnemonic(KeyEvent.VK_T); testMenu.getAccessibleContext().setAccessibleDescription( "Тестовые команды"); - { - JMenuItem addLogMessageItem = new JMenuItem("Сообщение в лог", KeyEvent.VK_S); - addLogMessageItem.addActionListener((event) -> { - Logger.debug("Новая строка"); - }); - testMenu.add(addLogMessageItem); - } + testMenu.add(createAddLogMessageMenuItem()); - menuBar.add(lookAndFeelMenu); - menuBar.add(testMenu); - return menuBar; + return testMenu; + } + + /** + * Создает пункт меню "Сообщение в лог" + */ + private JMenuItem createAddLogMessageMenuItem() + { + JMenuItem addLogMessageItem = new JMenuItem("Сообщение в лог", KeyEvent.VK_S); + addLogMessageItem.addActionListener((event) -> { + Logger.debug("Новая строка"); + }); + return addLogMessageItem; } private void setLookAndFeel(String className) @@ -168,30 +175,24 @@ private void setLookAndFeel(String className) // just ignore } } - /** - * НОВЫЙ МЕТОД: Обработка выхода из приложения с подтверждением - */ + private void exitApplication() { - // Настраиваем кнопки диалога на русском языке Object[] options = {"Да", "Нет", "Отмена"}; int result = JOptionPane.showOptionDialog( - this, // родительский компонент - "Вы действительно хотите выйти из приложения?", // сообщение - "Подтверждение выхода", // заголовок - JOptionPane.YES_NO_CANCEL_OPTION, // тип опций - JOptionPane.QUESTION_MESSAGE, // тип сообщения - null, // иконка (по умолчанию) - options, // массив кнопок - options[1]); // кнопка по умолчанию ("Нет") - - // Обрабатываем результа + this, + "Вы действительно хотите выйти из приложения?", + "Подтверждение выхода", + JOptionPane.YES_NO_CANCEL_OPTION, + JOptionPane.QUESTION_MESSAGE, + null, + options, + options[1]); + if (result == JOptionPane.YES_OPTION) { - // Пользователь подтвердил выход Logger.debug("Приложение завершает работу"); System.exit(0); } - // В остальных случаях (Нет, Отмена, закрытие диалога) просто возвращаемся } -} +} \ No newline at end of file From db799567cacc491238434437461cd3a077d1fdb9 Mon Sep 17 00:00:00 2001 From: showman-1 Date: Tue, 7 Apr 2026 13:22:18 +0500 Subject: [PATCH 4/7] save size window --- robots/src/gui/MainApplicationFrame.java | 69 +++++++++-------- robots/src/gui/WindowStateManager.java | 98 ++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 31 deletions(-) create mode 100644 robots/src/gui/WindowStateManager.java diff --git a/robots/src/gui/MainApplicationFrame.java b/robots/src/gui/MainApplicationFrame.java index 41c99bd..1e75a62 100644 --- a/robots/src/gui/MainApplicationFrame.java +++ b/robots/src/gui/MainApplicationFrame.java @@ -3,6 +3,8 @@ import java.awt.Dimension; import java.awt.Toolkit; import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; import javax.swing.JDesktopPane; import javax.swing.JFrame; @@ -20,8 +22,15 @@ public class MainApplicationFrame extends JFrame { private final JDesktopPane desktopPane = new JDesktopPane(); + private WindowStateManager stateManager; + private LogWindow logWindow; + private GameWindow gameWindow; public MainApplicationFrame() { + stateManager = new WindowStateManager(); + + stateManager.loadFromFile(); + int inset = 50; Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); setBounds(inset, inset, @@ -30,21 +39,32 @@ public MainApplicationFrame() { setContentPane(desktopPane); - LogWindow logWindow = createLogWindow(); - addWindow(logWindow); + logWindow = createLogWindow(); + gameWindow = new GameWindow(); + gameWindow.setSize(400, 400); + + stateManager.applyWindowState(logWindow, "logWindow"); + stateManager.applyWindowState(gameWindow, "gameWindow"); - GameWindow gameWindow = new GameWindow(); - gameWindow.setSize(400, 400); + addWindow(logWindow); addWindow(gameWindow); setJMenuBar(createMenuBar()); + + // Обработчик закрытия окна setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + exitApplication(); + } + }); } protected LogWindow createLogWindow() { LogWindow logWindow = new LogWindow(Logger.getDefaultLogSource()); - logWindow.setLocation(10,10); + logWindow.setLocation(10, 10); logWindow.setSize(300, 800); setMinimumSize(logWindow.getSize()); logWindow.pack(); @@ -58,23 +78,15 @@ protected void addWindow(JInternalFrame frame) frame.setVisible(true); } - /** - * Главный метод создания меню - собирает все части воедино - */ private JMenuBar createMenuBar() { JMenuBar menuBar = new JMenuBar(); - menuBar.add(createFileMenu()); menuBar.add(createLookAndFeelMenu()); menuBar.add(createTestMenu()); - return menuBar; } - /** - * Создает меню "Файл" с пунктом "Выход" - */ private JMenu createFileMenu() { JMenu fileMenu = new JMenu("Файл"); @@ -83,9 +95,6 @@ private JMenu createFileMenu() return fileMenu; } - /** - * Создает пункт меню "Выход" - */ private JMenuItem createExitMenuItem() { JMenuItem exitMenuItem = new JMenuItem("Выход", KeyEvent.VK_X); @@ -93,9 +102,6 @@ private JMenuItem createExitMenuItem() return exitMenuItem; } - /** - * Создает меню "Режим отображения" с пунктами смены темы - */ private JMenu createLookAndFeelMenu() { JMenu lookAndFeelMenu = new JMenu("Режим отображения"); @@ -109,9 +115,6 @@ private JMenu createLookAndFeelMenu() return lookAndFeelMenu; } - /** - * Создает пункт меню "Системная схема" - */ private JMenuItem createSystemLookAndFeelMenuItem() { JMenuItem systemLookAndFeel = new JMenuItem("Системная схема", KeyEvent.VK_S); @@ -122,9 +125,6 @@ private JMenuItem createSystemLookAndFeelMenuItem() return systemLookAndFeel; } - /** - * Создает пункт меню "Универсальная схема" - */ private JMenuItem createCrossplatformLookAndFeelMenuItem() { JMenuItem crossplatformLookAndFeel = new JMenuItem("Универсальная схема", KeyEvent.VK_S); @@ -135,9 +135,6 @@ private JMenuItem createCrossplatformLookAndFeelMenuItem() return crossplatformLookAndFeel; } - /** - * Создает меню "Тесты" с тестовыми командами - */ private JMenu createTestMenu() { JMenu testMenu = new JMenu("Тесты"); @@ -150,9 +147,6 @@ private JMenu createTestMenu() return testMenu; } - /** - * Создает пункт меню "Сообщение в лог" - */ private JMenuItem createAddLogMessageMenuItem() { JMenuItem addLogMessageItem = new JMenuItem("Сообщение в лог", KeyEvent.VK_S); @@ -191,8 +185,21 @@ private void exitApplication() options[1]); if (result == JOptionPane.YES_OPTION) { + saveWindowStates(); + Logger.debug("Приложение завершает работу"); System.exit(0); } } + + private void saveWindowStates() + { + if (logWindow != null) { + stateManager.saveWindowState(logWindow, "logWindow"); + } + if (gameWindow != null) { + stateManager.saveWindowState(gameWindow, "gameWindow"); + } + stateManager.saveToFile(); + } } \ No newline at end of file diff --git a/robots/src/gui/WindowStateManager.java b/robots/src/gui/WindowStateManager.java new file mode 100644 index 0000000..278b28d --- /dev/null +++ b/robots/src/gui/WindowStateManager.java @@ -0,0 +1,98 @@ +package gui; + +import java.awt.Point; +import java.io.*; +import java.util.Properties; +import javax.swing.JInternalFrame; + +public class WindowStateManager { + + private static final String CONFIG_FILE = System.getProperty("user.home") + + File.separator + + ".robot_game_config.properties"; + + private Properties properties; + + public WindowStateManager() { + properties = new Properties(); + } + + public void saveWindowState(JInternalFrame frame, String windowKey) { + try { + Point location = frame.getLocation(); + properties.setProperty(windowKey + ".x", String.valueOf(location.x)); + properties.setProperty(windowKey + ".y", String.valueOf(location.y)); + + properties.setProperty(windowKey + ".width", String.valueOf(frame.getWidth())); + properties.setProperty(windowKey + ".height", String.valueOf(frame.getHeight())); + + if (frame.isIcon()) { + properties.setProperty(windowKey + ".state", "ICONIFIED"); + } else if (frame.isMaximum()) { + properties.setProperty(windowKey + ".state", "MAXIMIZED"); + } else { + properties.setProperty(windowKey + ".state", "NORMAL"); + } + + } catch (Exception e) { + System.err.println("Ошибка сохранения состояния окна " + windowKey + ": " + e.getMessage()); + } + } + + public void saveToFile() { + try (FileOutputStream out = new FileOutputStream(CONFIG_FILE)) { + properties.store(out, "Robot Game Configuration"); + } catch (IOException e) { + System.err.println("Ошибка сохранения конфигурации: " + e.getMessage()); + } + } + + public boolean loadFromFile() { + File configFile = new File(CONFIG_FILE); + if (!configFile.exists()) { + return false; + } + + try (FileInputStream in = new FileInputStream(configFile)) { + properties.load(in); + return true; + } catch (IOException e) { + System.err.println("Ошибка загрузки конфигурации: " + e.getMessage()); + return false; + } + } + + public void applyWindowState(JInternalFrame frame, String windowKey) { + try { + String xStr = properties.getProperty(windowKey + ".x"); + String yStr = properties.getProperty(windowKey + ".y"); + if (xStr != null && yStr != null) { + frame.setLocation(Integer.parseInt(xStr), Integer.parseInt(yStr)); + } + + String widthStr = properties.getProperty(windowKey + ".width"); + String heightStr = properties.getProperty(windowKey + ".height"); + if (widthStr != null && heightStr != null) { + frame.setSize(Integer.parseInt(widthStr), Integer.parseInt(heightStr)); + } + + String state = properties.getProperty(windowKey + ".state"); + if (state != null) { + switch (state) { + case "ICONIFIED": + frame.setIcon(true); + break; + case "MAXIMIZED": + try { + frame.setMaximum(true); + } catch (Exception e) { + } + break; + } + } + + } catch (Exception e) { + System.err.println("Ошибка восстановления окна " + windowKey + ": " + e.getMessage()); + } + } +} \ No newline at end of file From ca33453247b81ddc893a79178d18e2b016f17902 Mon Sep 17 00:00:00 2001 From: showman-1 Date: Tue, 14 Apr 2026 14:34:33 +0500 Subject: [PATCH 5/7] moving reading and writing of the config to a separate class --- robots/src/gui/MainApplicationFrame.java | 2 +- robots/src/gui/WindowStateLoader.java | 65 ++++++++++++++++++ robots/src/gui/WindowStateManager.java | 87 +++--------------------- robots/src/gui/WindowStateSaver.java | 44 ++++++++++++ 4 files changed, 121 insertions(+), 77 deletions(-) create mode 100644 robots/src/gui/WindowStateLoader.java create mode 100644 robots/src/gui/WindowStateSaver.java diff --git a/robots/src/gui/MainApplicationFrame.java b/robots/src/gui/MainApplicationFrame.java index 1e75a62..c472886 100644 --- a/robots/src/gui/MainApplicationFrame.java +++ b/robots/src/gui/MainApplicationFrame.java @@ -172,7 +172,7 @@ private void setLookAndFeel(String className) private void exitApplication() { - Object[] options = {"Да", "Нет", "Отмена"}; + Object[] options = {"Да", "Нет"}; int result = JOptionPane.showOptionDialog( this, diff --git a/robots/src/gui/WindowStateLoader.java b/robots/src/gui/WindowStateLoader.java new file mode 100644 index 0000000..0862366 --- /dev/null +++ b/robots/src/gui/WindowStateLoader.java @@ -0,0 +1,65 @@ +package gui; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Properties; +import javax.swing.JInternalFrame; + +public class WindowStateLoader { + + private static final String CONFIG_FILE = System.getProperty("user.home") + + File.separator + + ".robot_game_config.properties"; + + public Properties loadFromFile() { + Properties properties = new Properties(); + File configFile = new File(CONFIG_FILE); + + if (!configFile.exists()) { + return properties; + } + + try (FileInputStream in = new FileInputStream(configFile)) { + properties.load(in); + } catch (IOException e) { + System.err.println("Ошибка загрузки конфигурации: " + e.getMessage()); + } + + return properties; + } + + public void applyWindowState(Properties properties, JInternalFrame frame, String windowKey) { + try { + String xStr = properties.getProperty(windowKey + ".x"); + String yStr = properties.getProperty(windowKey + ".y"); + if (xStr != null && yStr != null) { + frame.setLocation(Integer.parseInt(xStr), Integer.parseInt(yStr)); + } + + String widthStr = properties.getProperty(windowKey + ".width"); + String heightStr = properties.getProperty(windowKey + ".height"); + if (widthStr != null && heightStr != null) { + frame.setSize(Integer.parseInt(widthStr), Integer.parseInt(heightStr)); + } + + String state = properties.getProperty(windowKey + ".state"); + if (state != null) { + switch (state) { + case "ICONIFIED": + frame.setIcon(true); + break; + case "MAXIMIZED": + try { + frame.setMaximum(true); + } catch (Exception e) { + } + break; + } + } + + } catch (Exception e) { + System.err.println("Ошибка восстановления окна " + windowKey + ": " + e.getMessage()); + } + } +} \ No newline at end of file diff --git a/robots/src/gui/WindowStateManager.java b/robots/src/gui/WindowStateManager.java index 278b28d..2a49bf1 100644 --- a/robots/src/gui/WindowStateManager.java +++ b/robots/src/gui/WindowStateManager.java @@ -1,98 +1,33 @@ package gui; -import java.awt.Point; -import java.io.*; import java.util.Properties; import javax.swing.JInternalFrame; public class WindowStateManager { - private static final String CONFIG_FILE = System.getProperty("user.home") + - File.separator + - ".robot_game_config.properties"; - private Properties properties; + private WindowStateSaver saver; + private WindowStateLoader loader; public WindowStateManager() { - properties = new Properties(); + this.properties = new Properties(); + this.saver = new WindowStateSaver(); + this.loader = new WindowStateLoader(); } - public void saveWindowState(JInternalFrame frame, String windowKey) { - try { - Point location = frame.getLocation(); - properties.setProperty(windowKey + ".x", String.valueOf(location.x)); - properties.setProperty(windowKey + ".y", String.valueOf(location.y)); - - properties.setProperty(windowKey + ".width", String.valueOf(frame.getWidth())); - properties.setProperty(windowKey + ".height", String.valueOf(frame.getHeight())); - - if (frame.isIcon()) { - properties.setProperty(windowKey + ".state", "ICONIFIED"); - } else if (frame.isMaximum()) { - properties.setProperty(windowKey + ".state", "MAXIMIZED"); - } else { - properties.setProperty(windowKey + ".state", "NORMAL"); - } - - } catch (Exception e) { - System.err.println("Ошибка сохранения состояния окна " + windowKey + ": " + e.getMessage()); - } + public void loadFromFile() { + this.properties = loader.loadFromFile(); } public void saveToFile() { - try (FileOutputStream out = new FileOutputStream(CONFIG_FILE)) { - properties.store(out, "Robot Game Configuration"); - } catch (IOException e) { - System.err.println("Ошибка сохранения конфигурации: " + e.getMessage()); - } + saver.saveToFile(properties); } - public boolean loadFromFile() { - File configFile = new File(CONFIG_FILE); - if (!configFile.exists()) { - return false; - } - - try (FileInputStream in = new FileInputStream(configFile)) { - properties.load(in); - return true; - } catch (IOException e) { - System.err.println("Ошибка загрузки конфигурации: " + e.getMessage()); - return false; - } + public void saveWindowState(JInternalFrame frame, String windowKey) { + saver.saveWindowState(properties, frame, windowKey); } public void applyWindowState(JInternalFrame frame, String windowKey) { - try { - String xStr = properties.getProperty(windowKey + ".x"); - String yStr = properties.getProperty(windowKey + ".y"); - if (xStr != null && yStr != null) { - frame.setLocation(Integer.parseInt(xStr), Integer.parseInt(yStr)); - } - - String widthStr = properties.getProperty(windowKey + ".width"); - String heightStr = properties.getProperty(windowKey + ".height"); - if (widthStr != null && heightStr != null) { - frame.setSize(Integer.parseInt(widthStr), Integer.parseInt(heightStr)); - } - - String state = properties.getProperty(windowKey + ".state"); - if (state != null) { - switch (state) { - case "ICONIFIED": - frame.setIcon(true); - break; - case "MAXIMIZED": - try { - frame.setMaximum(true); - } catch (Exception e) { - } - break; - } - } - - } catch (Exception e) { - System.err.println("Ошибка восстановления окна " + windowKey + ": " + e.getMessage()); - } + loader.applyWindowState(properties, frame, windowKey); } } \ No newline at end of file diff --git a/robots/src/gui/WindowStateSaver.java b/robots/src/gui/WindowStateSaver.java new file mode 100644 index 0000000..5db619c --- /dev/null +++ b/robots/src/gui/WindowStateSaver.java @@ -0,0 +1,44 @@ +package gui; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Properties; +import javax.swing.JInternalFrame; + +public class WindowStateSaver { + + private static final String CONFIG_FILE = System.getProperty("user.home") + + File.separator + + ".robot_game_config.properties"; + + public void saveWindowState(Properties properties, JInternalFrame frame, String windowKey) { + try { + java.awt.Point location = frame.getLocation(); + properties.setProperty(windowKey + ".x", String.valueOf(location.x)); + properties.setProperty(windowKey + ".y", String.valueOf(location.y)); + + properties.setProperty(windowKey + ".width", String.valueOf(frame.getWidth())); + properties.setProperty(windowKey + ".height", String.valueOf(frame.getHeight())); + + if (frame.isIcon()) { + properties.setProperty(windowKey + ".state", "ICONIFIED"); + } else if (frame.isMaximum()) { + properties.setProperty(windowKey + ".state", "MAXIMIZED"); + } else { + properties.setProperty(windowKey + ".state", "NORMAL"); + } + + } catch (Exception e) { + System.err.println("Ошибка сохранения состояния окна " + windowKey + ": " + e.getMessage()); + } + } + + public void saveToFile(Properties properties) { + try (FileOutputStream out = new FileOutputStream(CONFIG_FILE)) { + properties.store(out, "Robot Game Configuration"); + } catch (IOException e) { + System.err.println("Ошибка сохранения конфигурации: " + e.getMessage()); + } + } +} \ No newline at end of file From 3e7c0b10bf9f92a5c2e73051ab53f4eb41ab821a Mon Sep 17 00:00:00 2001 From: showman-1 Date: Tue, 21 Apr 2026 19:33:42 +0500 Subject: [PATCH 6/7] change logic --- robots/src/gui/ConfigFileManager.java | 51 ++++++++++++++++ robots/src/gui/WindowStateHelper.java | 84 ++++++++++++++++++++++++++ robots/src/gui/WindowStateLoader.java | 65 -------------------- robots/src/gui/WindowStateManager.java | 32 +++++++--- robots/src/gui/WindowStateSaver.java | 44 -------------- 5 files changed, 159 insertions(+), 117 deletions(-) create mode 100644 robots/src/gui/ConfigFileManager.java create mode 100644 robots/src/gui/WindowStateHelper.java delete mode 100644 robots/src/gui/WindowStateLoader.java delete mode 100644 robots/src/gui/WindowStateSaver.java diff --git a/robots/src/gui/ConfigFileManager.java b/robots/src/gui/ConfigFileManager.java new file mode 100644 index 0000000..cb2ac87 --- /dev/null +++ b/robots/src/gui/ConfigFileManager.java @@ -0,0 +1,51 @@ +package gui; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Properties; + +/** + * Отвечает ТОЛЬКО за чтение и запись файла конфигурации. + * Ничего не знает об окнах, только работа с Properties и файлом. + */ +public class ConfigFileManager { + + private static final String CONFIG_FILE = System.getProperty("user.home") + + File.separator + + ".robot_game_config.properties"; + + /** + * Загружает настройки из файла + * @return Properties с загруженными настройками, или пустые Properties если файла нет + */ + public Properties loadFromFile() { + Properties properties = new Properties(); + File configFile = new File(CONFIG_FILE); + + if (!configFile.exists()) { + return properties; // Файла нет - возвращаем пустые настройки + } + + try (FileInputStream in = new FileInputStream(configFile)) { + properties.load(in); + } catch (IOException e) { + System.err.println("Ошибка загрузки конфигурации: " + e.getMessage()); + } + + return properties; + } + + /** + * Сохраняет настройки в файл + * @param properties настройки для сохранения + */ + public void saveToFile(Properties properties) { + try (FileOutputStream out = new FileOutputStream(CONFIG_FILE)) { + properties.store(out, "Robot Game Configuration"); + } catch (IOException e) { + System.err.println("Ошибка сохранения конфигурации: " + e.getMessage()); + } + } +} \ No newline at end of file diff --git a/robots/src/gui/WindowStateHelper.java b/robots/src/gui/WindowStateHelper.java new file mode 100644 index 0000000..dd5517e --- /dev/null +++ b/robots/src/gui/WindowStateHelper.java @@ -0,0 +1,84 @@ +package gui; + +import java.util.Properties; +import javax.swing.JInternalFrame; + +/** + * Отвечает ТОЛЬКО за сохранение и восстановление состояния окон в Properties. + * Ничего не знает о файлах, только преобразует окно в Properties и обратно. + */ +public class WindowStateHelper { + + /** + * Сохраняет состояние одного окна в Properties + * @param properties куда сохранять + * @param frame окно, состояние которого сохраняем + * @param windowKey идентификатор окна ("logWindow", "gameWindow" и т.д.) + */ + public void saveWindowState(Properties properties, JInternalFrame frame, String windowKey) { + try { + java.awt.Point location = frame.getLocation(); + properties.setProperty(windowKey + ".x", String.valueOf(location.x)); + properties.setProperty(windowKey + ".y", String.valueOf(location.y)); + + properties.setProperty(windowKey + ".width", String.valueOf(frame.getWidth())); + properties.setProperty(windowKey + ".height", String.valueOf(frame.getHeight())); + + if (frame.isIcon()) { + properties.setProperty(windowKey + ".state", "ICONIFIED"); + } else if (frame.isMaximum()) { + properties.setProperty(windowKey + ".state", "MAXIMIZED"); + } else { + properties.setProperty(windowKey + ".state", "NORMAL"); + } + + } catch (Exception e) { + System.err.println("Ошибка сохранения состояния окна " + windowKey + ": " + e.getMessage()); + } + } + + /** + * Восстанавливает состояние окна из Properties + * @param properties откуда восстанавливать + * @param frame окно, которому применяем настройки + * @param windowKey идентификатор окна + */ + public void applyWindowState(Properties properties, JInternalFrame frame, String windowKey) { + try { + // Восстанавливаем позицию + String xStr = properties.getProperty(windowKey + ".x"); + String yStr = properties.getProperty(windowKey + ".y"); + if (xStr != null && yStr != null) { + frame.setLocation(Integer.parseInt(xStr), Integer.parseInt(yStr)); + } + + // Восстанавливаем размеры + String widthStr = properties.getProperty(windowKey + ".width"); + String heightStr = properties.getProperty(windowKey + ".height"); + if (widthStr != null && heightStr != null) { + frame.setSize(Integer.parseInt(widthStr), Integer.parseInt(heightStr)); + } + + // Восстанавливаем состояние + String state = properties.getProperty(windowKey + ".state"); + if (state != null) { + switch (state) { + case "ICONIFIED": + frame.setIcon(true); + break; + case "MAXIMIZED": + try { + frame.setMaximum(true); + } catch (Exception e) { + // Некоторые LookAndFeel могут не поддерживать maximize + } + break; + // case "NORMAL" - ничего не делаем, это состояние по умолчанию + } + } + + } catch (Exception e) { + System.err.println("Ошибка восстановления окна " + windowKey + ": " + e.getMessage()); + } + } +} \ No newline at end of file diff --git a/robots/src/gui/WindowStateLoader.java b/robots/src/gui/WindowStateLoader.java deleted file mode 100644 index 0862366..0000000 --- a/robots/src/gui/WindowStateLoader.java +++ /dev/null @@ -1,65 +0,0 @@ -package gui; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.Properties; -import javax.swing.JInternalFrame; - -public class WindowStateLoader { - - private static final String CONFIG_FILE = System.getProperty("user.home") + - File.separator + - ".robot_game_config.properties"; - - public Properties loadFromFile() { - Properties properties = new Properties(); - File configFile = new File(CONFIG_FILE); - - if (!configFile.exists()) { - return properties; - } - - try (FileInputStream in = new FileInputStream(configFile)) { - properties.load(in); - } catch (IOException e) { - System.err.println("Ошибка загрузки конфигурации: " + e.getMessage()); - } - - return properties; - } - - public void applyWindowState(Properties properties, JInternalFrame frame, String windowKey) { - try { - String xStr = properties.getProperty(windowKey + ".x"); - String yStr = properties.getProperty(windowKey + ".y"); - if (xStr != null && yStr != null) { - frame.setLocation(Integer.parseInt(xStr), Integer.parseInt(yStr)); - } - - String widthStr = properties.getProperty(windowKey + ".width"); - String heightStr = properties.getProperty(windowKey + ".height"); - if (widthStr != null && heightStr != null) { - frame.setSize(Integer.parseInt(widthStr), Integer.parseInt(heightStr)); - } - - String state = properties.getProperty(windowKey + ".state"); - if (state != null) { - switch (state) { - case "ICONIFIED": - frame.setIcon(true); - break; - case "MAXIMIZED": - try { - frame.setMaximum(true); - } catch (Exception e) { - } - break; - } - } - - } catch (Exception e) { - System.err.println("Ошибка восстановления окна " + windowKey + ": " + e.getMessage()); - } - } -} \ No newline at end of file diff --git a/robots/src/gui/WindowStateManager.java b/robots/src/gui/WindowStateManager.java index 2a49bf1..d350595 100644 --- a/robots/src/gui/WindowStateManager.java +++ b/robots/src/gui/WindowStateManager.java @@ -3,31 +3,47 @@ import java.util.Properties; import javax.swing.JInternalFrame; +/** + * Управляет сохранением и восстановлением состояния окон. + * Использует ConfigFileManager для работы с файлом и WindowStateHelper для работы с окнами. + */ public class WindowStateManager { private Properties properties; - private WindowStateSaver saver; - private WindowStateLoader loader; + private ConfigFileManager fileManager; + private WindowStateHelper windowHelper; public WindowStateManager() { this.properties = new Properties(); - this.saver = new WindowStateSaver(); - this.loader = new WindowStateLoader(); + this.fileManager = new ConfigFileManager(); + this.windowHelper = new WindowStateHelper(); } + /** + * Загружает настройки из файла + */ public void loadFromFile() { - this.properties = loader.loadFromFile(); + this.properties = fileManager.loadFromFile(); } + /** + * Сохраняет настройки в файл + */ public void saveToFile() { - saver.saveToFile(properties); + fileManager.saveToFile(properties); } + /** + * Сохраняет состояние одного окна + */ public void saveWindowState(JInternalFrame frame, String windowKey) { - saver.saveWindowState(properties, frame, windowKey); + windowHelper.saveWindowState(properties, frame, windowKey); } + /** + * Восстанавливает состояние окна + */ public void applyWindowState(JInternalFrame frame, String windowKey) { - loader.applyWindowState(properties, frame, windowKey); + windowHelper.applyWindowState(properties, frame, windowKey); } } \ No newline at end of file diff --git a/robots/src/gui/WindowStateSaver.java b/robots/src/gui/WindowStateSaver.java deleted file mode 100644 index 5db619c..0000000 --- a/robots/src/gui/WindowStateSaver.java +++ /dev/null @@ -1,44 +0,0 @@ -package gui; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.Properties; -import javax.swing.JInternalFrame; - -public class WindowStateSaver { - - private static final String CONFIG_FILE = System.getProperty("user.home") + - File.separator + - ".robot_game_config.properties"; - - public void saveWindowState(Properties properties, JInternalFrame frame, String windowKey) { - try { - java.awt.Point location = frame.getLocation(); - properties.setProperty(windowKey + ".x", String.valueOf(location.x)); - properties.setProperty(windowKey + ".y", String.valueOf(location.y)); - - properties.setProperty(windowKey + ".width", String.valueOf(frame.getWidth())); - properties.setProperty(windowKey + ".height", String.valueOf(frame.getHeight())); - - if (frame.isIcon()) { - properties.setProperty(windowKey + ".state", "ICONIFIED"); - } else if (frame.isMaximum()) { - properties.setProperty(windowKey + ".state", "MAXIMIZED"); - } else { - properties.setProperty(windowKey + ".state", "NORMAL"); - } - - } catch (Exception e) { - System.err.println("Ошибка сохранения состояния окна " + windowKey + ": " + e.getMessage()); - } - } - - public void saveToFile(Properties properties) { - try (FileOutputStream out = new FileOutputStream(CONFIG_FILE)) { - properties.store(out, "Robot Game Configuration"); - } catch (IOException e) { - System.err.println("Ошибка сохранения конфигурации: " + e.getMessage()); - } - } -} \ No newline at end of file From 71143730440cdf63bce776e47d4f3302da2c5921 Mon Sep 17 00:00:00 2001 From: showman-1 Date: Tue, 21 Apr 2026 19:40:13 +0500 Subject: [PATCH 7/7] change logic --- robots/src/gui/ConfigFileManager.java | 15 +++------------ robots/src/gui/WindowStateHelper.java | 24 +++--------------------- robots/src/gui/WindowStateManager.java | 20 ++++---------------- 3 files changed, 10 insertions(+), 49 deletions(-) diff --git a/robots/src/gui/ConfigFileManager.java b/robots/src/gui/ConfigFileManager.java index cb2ac87..3c162d7 100644 --- a/robots/src/gui/ConfigFileManager.java +++ b/robots/src/gui/ConfigFileManager.java @@ -6,20 +6,14 @@ import java.io.IOException; import java.util.Properties; -/** - * Отвечает ТОЛЬКО за чтение и запись файла конфигурации. - * Ничего не знает об окнах, только работа с Properties и файлом. - */ + public class ConfigFileManager { private static final String CONFIG_FILE = System.getProperty("user.home") + File.separator + ".robot_game_config.properties"; - /** - * Загружает настройки из файла - * @return Properties с загруженными настройками, или пустые Properties если файла нет - */ + public Properties loadFromFile() { Properties properties = new Properties(); File configFile = new File(CONFIG_FILE); @@ -37,10 +31,7 @@ public Properties loadFromFile() { return properties; } - /** - * Сохраняет настройки в файл - * @param properties настройки для сохранения - */ + public void saveToFile(Properties properties) { try (FileOutputStream out = new FileOutputStream(CONFIG_FILE)) { properties.store(out, "Robot Game Configuration"); diff --git a/robots/src/gui/WindowStateHelper.java b/robots/src/gui/WindowStateHelper.java index dd5517e..fa5aa01 100644 --- a/robots/src/gui/WindowStateHelper.java +++ b/robots/src/gui/WindowStateHelper.java @@ -3,18 +3,10 @@ import java.util.Properties; import javax.swing.JInternalFrame; -/** - * Отвечает ТОЛЬКО за сохранение и восстановление состояния окон в Properties. - * Ничего не знает о файлах, только преобразует окно в Properties и обратно. - */ + public class WindowStateHelper { - /** - * Сохраняет состояние одного окна в Properties - * @param properties куда сохранять - * @param frame окно, состояние которого сохраняем - * @param windowKey идентификатор окна ("logWindow", "gameWindow" и т.д.) - */ + public void saveWindowState(Properties properties, JInternalFrame frame, String windowKey) { try { java.awt.Point location = frame.getLocation(); @@ -37,29 +29,21 @@ public void saveWindowState(Properties properties, JInternalFrame frame, String } } - /** - * Восстанавливает состояние окна из Properties - * @param properties откуда восстанавливать - * @param frame окно, которому применяем настройки - * @param windowKey идентификатор окна - */ + public void applyWindowState(Properties properties, JInternalFrame frame, String windowKey) { try { - // Восстанавливаем позицию String xStr = properties.getProperty(windowKey + ".x"); String yStr = properties.getProperty(windowKey + ".y"); if (xStr != null && yStr != null) { frame.setLocation(Integer.parseInt(xStr), Integer.parseInt(yStr)); } - // Восстанавливаем размеры String widthStr = properties.getProperty(windowKey + ".width"); String heightStr = properties.getProperty(windowKey + ".height"); if (widthStr != null && heightStr != null) { frame.setSize(Integer.parseInt(widthStr), Integer.parseInt(heightStr)); } - // Восстанавливаем состояние String state = properties.getProperty(windowKey + ".state"); if (state != null) { switch (state) { @@ -70,10 +54,8 @@ public void applyWindowState(Properties properties, JInternalFrame frame, String try { frame.setMaximum(true); } catch (Exception e) { - // Некоторые LookAndFeel могут не поддерживать maximize } break; - // case "NORMAL" - ничего не делаем, это состояние по умолчанию } } diff --git a/robots/src/gui/WindowStateManager.java b/robots/src/gui/WindowStateManager.java index d350595..fe78eb1 100644 --- a/robots/src/gui/WindowStateManager.java +++ b/robots/src/gui/WindowStateManager.java @@ -3,10 +3,6 @@ import java.util.Properties; import javax.swing.JInternalFrame; -/** - * Управляет сохранением и восстановлением состояния окон. - * Использует ConfigFileManager для работы с файлом и WindowStateHelper для работы с окнами. - */ public class WindowStateManager { private Properties properties; @@ -19,30 +15,22 @@ public WindowStateManager() { this.windowHelper = new WindowStateHelper(); } - /** - * Загружает настройки из файла - */ + public void loadFromFile() { this.properties = fileManager.loadFromFile(); } - /** - * Сохраняет настройки в файл - */ + public void saveToFile() { fileManager.saveToFile(properties); } - /** - * Сохраняет состояние одного окна - */ + public void saveWindowState(JInternalFrame frame, String windowKey) { windowHelper.saveWindowState(properties, frame, windowKey); } - /** - * Восстанавливает состояние окна - */ + public void applyWindowState(JInternalFrame frame, String windowKey) { windowHelper.applyWindowState(properties, frame, windowKey); }