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
76 changes: 76 additions & 0 deletions robots/src/gui/AppStateManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package gui;

import java.beans.PropertyVetoException;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import log.Logger;

public class AppStateManager {
private final WindowConfigManager configManager;

public AppStateManager() {
this.configManager = new WindowConfigManager();
}

public void load() {
configManager.load();
Logger.debug("Менеджер состояний: загрузка конфигурации запущена");
}

public void save() {
configManager.save();
}

public void restoreMain(JFrame mainFrame, int defaultX, int defaultY, int defaultW, int defaultH) {
mainFrame.setBounds(
configManager.getInt("main.x", defaultX),
configManager.getInt("main.y", defaultY),
configManager.getInt("main.w", defaultW),
configManager.getInt("main.h", defaultH)
);
mainFrame.setExtendedState(configManager.getInt("main.state", JFrame.NORMAL));
}

public void restoreInternalFrame(JInternalFrame frame, String prefix, int defaultX, int defaultY, int defaultW, int defaultH) {
int w = configManager.getInt(prefix + ".w", defaultW);
int h = configManager.getInt(prefix + ".h", defaultH);
int x = configManager.getInt(prefix + ".x", defaultX);
int y = configManager.getInt(prefix + ".y", defaultY);

frame.setBounds(x, y, w, h);

try {
if (configManager.getBool(prefix + ".max", false)) {
frame.setMaximum(true);
} else if (configManager.getBool(prefix + ".icon", false)) {
frame.setIcon(true);
}
} catch (PropertyVetoException e) {
Logger.error("Не удалось восстановить состояние окна '" + prefix + "': " + e.getMessage());
}
}

public void saveMain(JFrame mainFrame) {
configManager.saveMain(
mainFrame.getX(), mainFrame.getY(),
mainFrame.getWidth(), mainFrame.getHeight(),
mainFrame.getExtendedState()
);
}

public void saveInternalFrame(JInternalFrame frame, String prefix) {
configManager.saveInternal(prefix,
frame.getX(), frame.getY(),
frame.getWidth(), frame.getHeight(),
frame.isIcon(), frame.isMaximum()
);
}

public void saveAllFrames(JDesktopPane desktopPane) {
for (JInternalFrame frame : desktopPane.getAllFrames()) {
String prefix = frame.getTitle().replaceAll("\\s+", "_").toLowerCase();
saveInternalFrame(frame, prefix);
}
}
}
9 changes: 5 additions & 4 deletions robots/src/gui/GameVisualizer.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,17 @@ private static Timer initTimer()

private volatile double m_robotPositionX = 100;
private volatile double m_robotPositionY = 100;
private volatile double m_robotDirection = 0;
private volatile double m_robotDirection = 0;

private volatile int m_targetPositionX = 150;
private volatile int m_targetPositionY = 100;

private static final double maxVelocity = 0.1;
private static final double maxAngularVelocity = 0.001;
private static final double maxVelocity = 0.1; //ЛИНЕЙНАЯ
private static final double maxAngularVelocity = 0.001;// УГЛОВАЯ

public GameVisualizer()
{

m_timer.schedule(new TimerTask()
{
@Override
Expand Down Expand Up @@ -98,7 +99,7 @@ protected void onModelUpdateEvent()
return;
}
double velocity = maxVelocity;
double angleToTarget = angleTo(m_robotPositionX, m_robotPositionY, m_targetPositionX, m_targetPositionY);
double angleToTarget = angleTo(m_robotPositionX, m_robotPositionY, m_targetPositionX, m_targetPositionY);// поворачиваем если надо налево направо
double angularVelocity = 0;
if (angleToTarget > m_robotDirection)
{
Expand Down
10 changes: 4 additions & 6 deletions robots/src/gui/LogWindow.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.TextArea;

import javax.swing.JInternalFrame;
import javax.swing.JPanel;

import log.LogChangeListener;
import log.LogEntry;
import log.LogWindowSource;
Expand All @@ -16,14 +14,14 @@ public class LogWindow extends JInternalFrame implements LogChangeListener
private LogWindowSource m_logSource;
private TextArea m_logContent;

public LogWindow(LogWindowSource logSource)
public LogWindow(LogWindowSource logSource)
{
super("Протокол работы", true, true, true, true);
m_logSource = logSource;
m_logSource.registerListener(this);
m_logContent = new TextArea("");
m_logContent.setSize(200, 500);

JPanel panel = new JPanel(new BorderLayout());
panel.add(m_logContent, BorderLayout.CENTER);
getContentPane().add(panel);
Expand All @@ -41,10 +39,10 @@ private void updateLogContent()
m_logContent.setText(content.toString());
m_logContent.invalidate();
}

@Override
public void onLogChanged()
{
EventQueue.invokeLater(this::updateLogContent);
}
}
}
194 changes: 68 additions & 126 deletions robots/src/gui/MainApplicationFrame.java
Original file line number Diff line number Diff line change
@@ -1,156 +1,98 @@
package gui;

import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;

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.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import javax.swing.*;
import log.Logger;

/**
* Что требуется сделать:
* 1. Метод создания меню перегружен функционалом и трудно читается.
* Следует разделить его на серию более простых методов (или вообще выделить отдельный класс).
*
*/
public class MainApplicationFrame extends JFrame
{
public class MainApplicationFrame extends JFrame {
private final JDesktopPane desktopPane = new JDesktopPane();

private LogWindow logWindow;
private GameWindow gameWindow;
private final AppStateManager stateManager = new AppStateManager();

private static final int DEFAULT_INSET = 50;
private static final int DEFAULT_INTERNAL_WIDTH = 600;
private static final int DEFAULT_INTERNAL_HEIGHT = 400;
private static final int DEFAULT_GAME_X = 10;
private static final int DEFAULT_GAME_Y = 10;
private static final int DEFAULT_LOG_X = 220;
private static final int DEFAULT_LOG_Y = 10;

public MainApplicationFrame() {
//Make the big window be indented 50 pixels from each edge
//of the screen.
int inset = 50;
stateManager.load();

Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setBounds(inset, inset,
screenSize.width - inset*2,
screenSize.height - inset*2);
int defW = screenSize.width - DEFAULT_INSET * 2;
int defH = screenSize.height - DEFAULT_INSET * 2;

stateManager.restoreMain(this, DEFAULT_INSET, DEFAULT_INSET, defW, defH);

setContentPane(desktopPane);

LogWindow logWindow = createLogWindow();

logWindow = createLogWindow();
stateManager.restoreInternalFrame(logWindow, "log", DEFAULT_LOG_X, DEFAULT_LOG_Y, DEFAULT_INTERNAL_WIDTH, DEFAULT_INTERNAL_HEIGHT);
addWindow(logWindow);

GameWindow gameWindow = new GameWindow();
gameWindow.setSize(400, 400);
gameWindow = new GameWindow();
stateManager.restoreInternalFrame(gameWindow, "game", DEFAULT_GAME_X, DEFAULT_GAME_Y, DEFAULT_INTERNAL_WIDTH, DEFAULT_INTERNAL_HEIGHT);
addWindow(gameWindow);

setJMenuBar(generateMenuBar());
setDefaultCloseOperation(EXIT_ON_CLOSE);

setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowClosing(java.awt.event.WindowEvent e) {
exitApplication();
}
});

Logger.debug("Главное окно инициализировано");
}

protected LogWindow createLogWindow()
{
LogWindow logWindow = new LogWindow(Logger.getDefaultLogSource());
logWindow.setLocation(10,10);
logWindow.setSize(300, 800);
setMinimumSize(logWindow.getSize());
logWindow.pack();

protected LogWindow createLogWindow() {
LogWindow lw = new LogWindow(Logger.getDefaultLogSource());
Logger.debug("Протокол работает");
return logWindow;
return lw;
}

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 exitApplication() {
stateManager.saveMain(this);
stateManager.saveAllFrames(desktopPane);
stateManager.save();

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);
Logger.debug("Конфигурация сохранена перед выходом");

UIManager.put("OptionPane.yesButtonText", "Да");
UIManager.put("OptionPane.noButtonText", "Нет");
int result = JOptionPane.showConfirmDialog(
this,
"Вы действительно хотите выйти?",
"Подтверждение выхода",
JOptionPane.YES_NO_OPTION
);
if (result == JOptionPane.YES_OPTION) {
Logger.debug("Приложение закрыто пользователем");
System.exit(0);
}
}

menuBar.add(lookAndFeelMenu);
menuBar.add(testMenu);
return menuBar;
private JMenuBar generateMenuBar() {
return new MenuBarBuilder(this).buildMenuBar();
}

private void setLookAndFeel(String className)
{
try
{

public void setLookAndFeel(String className) {
try {
UIManager.setLookAndFeel(className);
SwingUtilities.updateComponentTreeUI(this);
}
catch (ClassNotFoundException | InstantiationException
| IllegalAccessException | UnsupportedLookAndFeelException e)
{
// just ignore
Logger.debug("Тема оформления изменена: " + className);
} catch (Exception e) {
Logger.error("Не удалось установить тему оформления: " + e.getMessage());
}
}
}
}
Loading