diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/Robots.iml b/.idea/Robots.iml
new file mode 100644
index 0000000..8df936b
--- /dev/null
+++ b/.idea/Robots.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..a55e7a1
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..8b92ee8
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..650a132
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/out/production/Robots/gui/GameVisualizer$1.class b/out/production/Robots/gui/GameVisualizer$1.class
new file mode 100644
index 0000000..4fb9850
Binary files /dev/null and b/out/production/Robots/gui/GameVisualizer$1.class differ
diff --git a/out/production/Robots/gui/GameVisualizer$2.class b/out/production/Robots/gui/GameVisualizer$2.class
new file mode 100644
index 0000000..ba3bd49
Binary files /dev/null and b/out/production/Robots/gui/GameVisualizer$2.class differ
diff --git a/out/production/Robots/gui/GameVisualizer$3.class b/out/production/Robots/gui/GameVisualizer$3.class
new file mode 100644
index 0000000..9eca837
Binary files /dev/null and b/out/production/Robots/gui/GameVisualizer$3.class differ
diff --git a/out/production/Robots/gui/GameVisualizer.class b/out/production/Robots/gui/GameVisualizer.class
new file mode 100644
index 0000000..99297d8
Binary files /dev/null and b/out/production/Robots/gui/GameVisualizer.class differ
diff --git a/out/production/Robots/gui/GameWindow.class b/out/production/Robots/gui/GameWindow.class
new file mode 100644
index 0000000..dcdd943
Binary files /dev/null and b/out/production/Robots/gui/GameWindow.class differ
diff --git a/out/production/Robots/gui/Listener.class b/out/production/Robots/gui/Listener.class
new file mode 100644
index 0000000..223493f
Binary files /dev/null and b/out/production/Robots/gui/Listener.class differ
diff --git a/out/production/Robots/gui/LogWindow.class b/out/production/Robots/gui/LogWindow.class
new file mode 100644
index 0000000..d6304ed
Binary files /dev/null and b/out/production/Robots/gui/LogWindow.class differ
diff --git a/out/production/Robots/gui/MainApplicationFrame$1.class b/out/production/Robots/gui/MainApplicationFrame$1.class
new file mode 100644
index 0000000..27fe8e2
Binary files /dev/null and b/out/production/Robots/gui/MainApplicationFrame$1.class differ
diff --git a/out/production/Robots/gui/MainApplicationFrame.class b/out/production/Robots/gui/MainApplicationFrame.class
new file mode 100644
index 0000000..b597b5d
Binary files /dev/null and b/out/production/Robots/gui/MainApplicationFrame.class differ
diff --git a/out/production/Robots/gui/RobotsProgram.class b/out/production/Robots/gui/RobotsProgram.class
new file mode 100644
index 0000000..bcac843
Binary files /dev/null and b/out/production/Robots/gui/RobotsProgram.class differ
diff --git a/out/production/Robots/log/LogChangeListener.class b/out/production/Robots/log/LogChangeListener.class
new file mode 100644
index 0000000..565fd48
Binary files /dev/null and b/out/production/Robots/log/LogChangeListener.class differ
diff --git a/out/production/Robots/log/LogEntry.class b/out/production/Robots/log/LogEntry.class
new file mode 100644
index 0000000..59e3960
Binary files /dev/null and b/out/production/Robots/log/LogEntry.class differ
diff --git a/out/production/Robots/log/LogLevel.class b/out/production/Robots/log/LogLevel.class
new file mode 100644
index 0000000..15d09c0
Binary files /dev/null and b/out/production/Robots/log/LogLevel.class differ
diff --git a/out/production/Robots/log/LogWindowSource.class b/out/production/Robots/log/LogWindowSource.class
new file mode 100644
index 0000000..4c8d31d
Binary files /dev/null and b/out/production/Robots/log/LogWindowSource.class differ
diff --git a/out/production/Robots/log/Logger.class b/out/production/Robots/log/Logger.class
new file mode 100644
index 0000000..0386159
Binary files /dev/null and b/out/production/Robots/log/Logger.class differ
diff --git a/robots/src/gui/Listener.java b/robots/src/gui/Listener.java
new file mode 100644
index 0000000..647cd84
--- /dev/null
+++ b/robots/src/gui/Listener.java
@@ -0,0 +1,8 @@
+package gui;
+
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowListener;
+
+public class Listener extends WindowAdapter {
+
+}
diff --git a/robots/src/gui/MainApplicationFrame.java b/robots/src/gui/MainApplicationFrame.java
index 62e943e..2756f06 100644
--- a/robots/src/gui/MainApplicationFrame.java
+++ b/robots/src/gui/MainApplicationFrame.java
@@ -3,6 +3,13 @@
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.beans.PropertyVetoException;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Properties;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
@@ -13,6 +20,7 @@
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
+import javax.swing.JOptionPane;
import log.Logger;
@@ -25,7 +33,23 @@
public class MainApplicationFrame extends JFrame
{
private final JDesktopPane desktopPane = new JDesktopPane();
-
+
+ private final LogWindow logWindowGlobal;
+ private final GameWindow gameWindowGlobal;
+ private static final String WINDOW_STATE_FILE = System.getProperty("user.home") + "\\window_state.properties";
+
+ private void confirmExit() {
+ int result = JOptionPane.showConfirmDialog(this,
+ "Вы действительно хотите выйти?",
+ "Подтверждение выхода",
+ JOptionPane.YES_NO_OPTION);
+ if (result == JOptionPane.YES_OPTION) {
+ saveWindowStates();
+ dispose();
+ System.exit(0);
+ }
+ }
+
public MainApplicationFrame() {
//Make the big window be indented 50 pixels from each edge
//of the screen.
@@ -39,14 +63,24 @@ public MainApplicationFrame() {
LogWindow logWindow = createLogWindow();
+ logWindowGlobal = logWindow;
addWindow(logWindow);
GameWindow gameWindow = new GameWindow();
+ gameWindowGlobal = gameWindow;
gameWindow.setSize(400, 400);
addWindow(gameWindow);
+ loadWindowStates();
+
setJMenuBar(generateMenuBar());
- setDefaultCloseOperation(EXIT_ON_CLOSE);
+ setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
+ addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosing(WindowEvent e){
+ confirmExit();
+ }
+ });
}
protected LogWindow createLogWindow()
@@ -65,15 +99,85 @@ protected void addWindow(JInternalFrame frame)
desktopPane.add(frame);
frame.setVisible(true);
}
-
+
+ private void saveWindowStates() {
+ Properties props = new Properties();
+
+ props.setProperty("frame.x", String.valueOf(getX()));
+ props.setProperty("frame.y", String.valueOf(getY()));
+ props.setProperty("frame.width", String.valueOf(getWidth()));
+ props.setProperty("frame.height", String.valueOf(getHeight()));
+ props.setProperty("frame.extendedState", String.valueOf(getExtendedState()));
+
+ saveInternalFrameState(props, logWindowGlobal, "LogWindow");
+ saveInternalFrameState(props, gameWindowGlobal, "GameWindow");
+
+ try (FileOutputStream out = new FileOutputStream(WINDOW_STATE_FILE)) {
+ props.store(out, "Window states");
+ } catch (IOException e) {
+ System.err.println("Не удалось сохранить состояние окон: " + e.getMessage());
+ }
+ }
+
+ private void saveInternalFrameState(Properties props, JInternalFrame frame, String prefix) {
+ props.setProperty(prefix + ".x", String.valueOf(frame.getX()));
+ props.setProperty(prefix + ".y", String.valueOf(frame.getY()));
+ props.setProperty(prefix + ".width", String.valueOf(frame.getWidth()));
+ props.setProperty(prefix + ".height", String.valueOf(frame.getHeight()));
+ props.setProperty(prefix + ".isIcon", String.valueOf(frame.isIcon()));
+ props.setProperty(prefix + ".isMaximum", String.valueOf(frame.isMaximum()));
+ }
+
+ private void loadWindowStates() {
+ Properties props = new Properties();
+ try (FileInputStream in = new FileInputStream(WINDOW_STATE_FILE)) {
+ props.load(in);
+ } catch (IOException e) {
+ return;
+ }
+
+ try {
+ int x = Integer.parseInt(props.getProperty("frame.x"));
+ int y = Integer.parseInt(props.getProperty("frame.y"));
+ int width = Integer.parseInt(props.getProperty("frame.width"));
+ int height = Integer.parseInt(props.getProperty("frame.height"));
+ setBounds(x, y, width, height);
+ int extendedState = Integer.parseInt(props.getProperty("frame.extendedState"));
+ setExtendedState(extendedState);
+ } catch (NumberFormatException e) {}
+
+ loadInternalFrameState(props, logWindowGlobal, "LogWindow");
+ loadInternalFrameState(props, gameWindowGlobal, "GameWindow");
+ }
+
+
+ private void loadInternalFrameState(Properties props, JInternalFrame frame, String prefix) {
+ try {
+ int x = Integer.parseInt(props.getProperty(prefix + ".x"));
+ int y = Integer.parseInt(props.getProperty(prefix + ".y"));
+ int width = Integer.parseInt(props.getProperty(prefix + ".width"));
+ int height = Integer.parseInt(props.getProperty(prefix + ".height"));
+ boolean isIcon = Boolean.parseBoolean(props.getProperty(prefix + ".isIcon"));
+ boolean isMaximum = Boolean.parseBoolean(props.getProperty(prefix + ".isMaximum"));
+
+ // Сначала устанавливаем границы, потом развёрнутость/свёрнутость
+ frame.setBounds(x, y, width, height);
+ if (isMaximum) {
+ frame.setMaximum(true);
+ } else {
+ frame.setIcon(isIcon);
+ }
+ } catch (NumberFormatException | PropertyVetoException e) {}
+ }
+
// 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,7 +186,7 @@ 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);
@@ -91,52 +195,78 @@ protected void addWindow(JInternalFrame frame)
// menuItem.setActionCommand("quit");
//// menuItem.addActionListener(this);
// menu.add(menuItem);
-//
+//
// return menuBar;
// }
-
- private JMenuBar generateMenuBar()
+
+ private void addSystemLookAndFeel(JMenu lookAndFeelMenu)
{
- JMenuBar menuBar = new JMenuBar();
-
- 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);
- }
+ }
- {
+ private void addCrossplatformLookAndFeel(JMenu lookAndFeelMenu)
+ {
JMenuItem crossplatformLookAndFeel = new JMenuItem("Универсальная схема", KeyEvent.VK_S);
crossplatformLookAndFeel.addActionListener((event) -> {
setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
this.invalidate();
});
lookAndFeelMenu.add(crossplatformLookAndFeel);
- }
+ }
+
+ private void addLogMessageItem(JMenu testMenu)
+ {
+ JMenuItem addLogMessageItem = new JMenuItem("Сообщение в лог", KeyEvent.VK_S);
+ addLogMessageItem.addActionListener((event) -> {
+ Logger.debug("Новая строка");
+ });
+ testMenu.add(addLogMessageItem);
+ }
+
+ private void addExitLookAndFeel(JMenu exitMenu)
+ {
+ JMenuItem addLogMessageItem = new JMenuItem("Завершение работы программы", KeyEvent.VK_S);
+ addLogMessageItem.addActionListener((event) -> {
+ confirmExit();
+ });
+ exitMenu.add(addLogMessageItem);
+ }
+
+ private JMenuBar generateMenuBar()
+ {
+ JMenuBar menuBar = new JMenuBar();
+
+ JMenu lookAndFeelMenu = new JMenu("Режим отображения");
+ lookAndFeelMenu.setMnemonic(KeyEvent.VK_V);
+ lookAndFeelMenu.getAccessibleContext().setAccessibleDescription(
+ "Управление режимом отображения приложения");
+
+ addSystemLookAndFeel(lookAndFeelMenu);
+
+ addCrossplatformLookAndFeel(lookAndFeelMenu);
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);
- }
+
+ addLogMessageItem(testMenu);
+
+ JMenu exitMenu = new JMenu("Выход");
+ exitMenu.setMnemonic(KeyEvent.VK_T);
+ exitMenu.getAccessibleContext().setAccessibleDescription(
+ "Меню выхода");
+
+ addExitLookAndFeel(exitMenu);
menuBar.add(lookAndFeelMenu);
menuBar.add(testMenu);
+ menuBar.add(exitMenu);
return menuBar;
}
diff --git a/robots/src/gui/RobotsProgram.java b/robots/src/gui/RobotsProgram.java
index ae0930a..a8800b1 100644
--- a/robots/src/gui/RobotsProgram.java
+++ b/robots/src/gui/RobotsProgram.java
@@ -1,6 +1,7 @@
package gui;
import java.awt.Frame;
+import java.util.Locale;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
@@ -8,6 +9,11 @@
public class RobotsProgram
{
public static void main(String[] args) {
+ UIManager.put("OptionPane.yesButtonText", "Да");
+ UIManager.put("OptionPane.noButtonText", "Нет");
+ UIManager.put("OptionPane.okButtonText", "OK");
+ UIManager.put("OptionPane.cancelButtonText", "Отмена");
+ UIManager.put("OptionPane.titleText", "Подтверждение");
try {
UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
// UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
diff --git a/robots/src/log/LogWindowSource.java b/robots/src/log/LogWindowSource.java
index ca0ce44..5e3a4ac 100644
--- a/robots/src/log/LogWindowSource.java
+++ b/robots/src/log/LogWindowSource.java
@@ -49,19 +49,16 @@ public void append(LogLevel logLevel, String strMessage)
{
LogEntry entry = new LogEntry(logLevel, strMessage);
m_messages.add(entry);
- LogChangeListener [] activeListeners = m_activeListeners;
- if (activeListeners == null)
+ if(m_messages.size() > m_iQueueLength)
+ m_messages.removeFirst();
+ if (m_activeListeners == null)
{
synchronized (m_listeners)
{
- if (m_activeListeners == null)
- {
- activeListeners = m_listeners.toArray(new LogChangeListener [0]);
- m_activeListeners = activeListeners;
- }
+ m_activeListeners = m_listeners.toArray(new LogChangeListener [0]);
}
}
- for (LogChangeListener listener : activeListeners)
+ for (LogChangeListener listener : m_activeListeners)
{
listener.onLogChanged();
}
diff --git a/robots/src/log/Logger.java b/robots/src/log/Logger.java
index b008a5d..91c71b6 100644
--- a/robots/src/log/Logger.java
+++ b/robots/src/log/Logger.java
@@ -4,7 +4,7 @@ public final class Logger
{
private static final LogWindowSource defaultLogSource;
static {
- defaultLogSource = new LogWindowSource(100);
+ defaultLogSource = new LogWindowSource(5);
}
private Logger()