Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 37 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,40 @@
/.metadata
/robots/.settings
/robots/bin
eclipse.bat
eclipse.bat
out/
/robots/.classpath
/robots/.project
# Translations
*.mo

# Compiled class file
*.class

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

# IDEA
.idea/
*.iml

# Maven
target/
96 changes: 96 additions & 0 deletions robots/src/config/ConfigManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package config;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import log.Logger;

/**
* Управление сохранением и загрузкой конфигурации приложения.
* Файл хранится в домашнем каталоге пользователя.
*/
public class ConfigManager {
private static final String CONFIG_FILE = System.getProperty("user.home") + File.separator + ".robot-config.properties";
private final Properties props = new Properties();

public void load() {
File file = new File(CONFIG_FILE);
if (!file.exists()) return;
try (FileInputStream fis = new FileInputStream(file)) {
props.load(fis);
} catch (IOException e) {
Logger.debug("Не удалось загрузить конфигурацию: " + e.getMessage());
}
}

public void save() {
try (FileOutputStream fos = new FileOutputStream(CONFIG_FILE)) {
props.store(fos, "Robot program configuration");
} catch (IOException e) {
Logger.debug("Не удалось сохранить конфигурацию: " + e.getMessage());
}
}

public void setMainWindowBounds(int x, int y, int width, int height, int state) {
setProperty("main.x", x);
setProperty("main.y", y);
setProperty("main.width", width);
setProperty("main.height", height);
setProperty("main.state", state);
}

public int getMainWindowX(int defaultValue) { return getIntProperty("main.x", defaultValue); }
public int getMainWindowY(int defaultValue) { return getIntProperty("main.y", defaultValue); }
public int getMainWindowWidth(int defaultValue) { return getIntProperty("main.width", defaultValue); }
public int getMainWindowHeight(int defaultValue) { return getIntProperty("main.height", defaultValue); }
public int getMainWindowState(int defaultValue) { return getIntProperty("main.state", defaultValue); }

public void setWindowBounds(String windowName, int x, int y, int width, int height, boolean icon, boolean maximized) {
setProperty(key(windowName, "x"), x);
setProperty(key(windowName, "y"), y);
setProperty(key(windowName, "width"), width);
setProperty(key(windowName, "height"), height);
setProperty(key(windowName, "icon"), icon);
setProperty(key(windowName, "maximized"), maximized);
}

public boolean hasWindow(String windowName) {
return props.containsKey(key(windowName, "x"));
}

public int getWindowX(String windowName, int defaultValue) { return getIntProperty(key(windowName, "x"), defaultValue); }
public int getWindowY(String windowName, int defaultValue) { return getIntProperty(key(windowName, "y"), defaultValue); }
public int getWindowWidth(String windowName, int defaultValue) { return getIntProperty(key(windowName, "width"), defaultValue); }
public int getWindowHeight(String windowName, int defaultValue) { return getIntProperty(key(windowName, "height"), defaultValue); }
public boolean getWindowIcon(String windowName, boolean defaultValue) { return getBooleanProperty(key(windowName, "icon"), defaultValue); }
public boolean getWindowMaximized(String windowName, boolean defaultValue) { return getBooleanProperty(key(windowName, "maximized"), defaultValue); }

private String key(String windowName, String suffix) {
return windowName + "." + suffix; // единственное место с конкатенацией (инкапсулировано)
}

private void setProperty(String key, int value) {
props.setProperty(key, Integer.toString(value));
}

private void setProperty(String key, boolean value) {
props.setProperty(key, Boolean.toString(value));
}

private int getIntProperty(String key, int defaultValue) {
String value = props.getProperty(key);
if (value == null) return defaultValue;
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
return defaultValue;
}
}

private boolean getBooleanProperty(String key, boolean defaultValue) {
String value = props.getProperty(key);
return value == null ? defaultValue : Boolean.parseBoolean(value);
}
}
219 changes: 103 additions & 116 deletions robots/src/gui/MainApplicationFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,155 +2,142 @@

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;
import javax.swing.JInternalFrame;
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;

import config.ConfigManager;
import log.Logger;

/**
* Что требуется сделать:
* 1. Метод создания меню перегружен функционалом и трудно читается.
* Следует разделить его на серию более простых методов (или вообще выделить отдельный класс).
*
*/
public class MainApplicationFrame extends JFrame
{
public class MainApplicationFrame extends JFrame {
private static final String LOG_WINDOW_TITLE = "Протокол работы";
private static final String GAME_WINDOW_TITLE = "Игровое поле";
private static final String LOG_WINDOW_NAME = "LogWindow";
private static final String GAME_WINDOW_NAME = "GameWindow";

private final JDesktopPane desktopPane = new JDesktopPane();

private final ConfigManager configManager = new ConfigManager();

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,
screenSize.width - inset*2,
screenSize.height - inset*2);
configManager.load();
loadMainWindowState();

setContentPane(desktopPane);



LogWindow logWindow = createLogWindow();
addWindow(logWindow);

GameWindow gameWindow = new GameWindow();
gameWindow.setSize(400, 400);
gameWindow.setSize(400, 400);
addWindow(gameWindow);

setJMenuBar(generateMenuBar());
setDefaultCloseOperation(EXIT_ON_CLOSE);
loadInternalWindowState(LOG_WINDOW_NAME, logWindow);
loadInternalWindowState(GAME_WINDOW_NAME, gameWindow);

setJMenuBar(new MenuBarFactory(this).createMenuBar());

addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
exitApplication();
}
});
}

public void exitApplication() {
saveAllWindowsState();
configManager.save();

int result = JOptionPane.showConfirmDialog(this,
"Вы действительно хотите выйти из приложения?",
"Подтверждение выхода",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE);
if (result == JOptionPane.YES_OPTION) {
System.exit(0);
}
}

protected LogWindow createLogWindow()
{

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();
Logger.debug("Протокол работает");
return logWindow;
}

protected void addWindow(JInternalFrame frame)
{

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);
// 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()
{
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);
}

{
JMenuItem crossplatformLookAndFeel = new JMenuItem("Универсальная схема", KeyEvent.VK_S);
crossplatformLookAndFeel.addActionListener((event) -> {
setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
this.invalidate();
});
lookAndFeelMenu.add(crossplatformLookAndFeel);
public void setLookAndFeel(String className) {
try {
UIManager.setLookAndFeel(className);
RobotsProgram.setRussianUIManagerText();
SwingUtilities.updateComponentTreeUI(this);
} catch (Exception e) {
// ignore
}
}

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);
}
private void loadMainWindowState() {
int inset = 50;
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int defaultWidth = screenSize.width - inset * 2;
int defaultHeight = screenSize.height - inset * 2;

menuBar.add(lookAndFeelMenu);
menuBar.add(testMenu);
return menuBar;
setBounds(configManager.getMainWindowX(inset),
configManager.getMainWindowY(inset),
configManager.getMainWindowWidth(defaultWidth),
configManager.getMainWindowHeight(defaultHeight));
setExtendedState(configManager.getMainWindowState(JFrame.NORMAL));
}

private void setLookAndFeel(String className)
{
try
{
UIManager.setLookAndFeel(className);
SwingUtilities.updateComponentTreeUI(this);

private void loadInternalWindowState(String windowName, JInternalFrame frame) {
if (!configManager.hasWindow(windowName)) return;

int x = configManager.getWindowX(windowName, frame.getX());
int y = configManager.getWindowY(windowName, frame.getY());
int w = configManager.getWindowWidth(windowName, frame.getWidth());
int h = configManager.getWindowHeight(windowName, frame.getHeight());
boolean icon = configManager.getWindowIcon(windowName, false);
boolean maximized = configManager.getWindowMaximized(windowName, false);

frame.setBounds(x, y, w, h);
try {
if (maximized) {
frame.setMaximum(true);
} else if (icon) {
frame.setIcon(true);
}
} catch (java.beans.PropertyVetoException e) {
Logger.debug("Не удалось восстановить состояние окна " + windowName + ": " + e.getMessage());
}
catch (ClassNotFoundException | InstantiationException
| IllegalAccessException | UnsupportedLookAndFeelException e)
{
// just ignore
}

private void saveAllWindowsState() {
configManager.setMainWindowBounds(getX(), getY(), getWidth(), getHeight(), getExtendedState());

for (JInternalFrame frame : desktopPane.getAllFrames()) {
String windowName = getWindowNameByTitle(frame.getTitle());
if (windowName != null) {
configManager.setWindowBounds(windowName,
frame.getX(), frame.getY(),
frame.getWidth(), frame.getHeight(),
frame.isIcon(), frame.isMaximum());
}
}
}

private String getWindowNameByTitle(String title) {
if (LOG_WINDOW_TITLE.equals(title)) return LOG_WINDOW_NAME;
if (GAME_WINDOW_TITLE.equals(title)) return GAME_WINDOW_NAME;
return null;
}
}
Loading