From 51717ed7f1958219b827961b1076ae90ee29e26f Mon Sep 17 00:00:00 2001 From: bajdcc Date: Thu, 22 Dec 2016 00:09:29 +0800 Subject: [PATCH] ADD: Support GUI Commands: echo, dup, pipe, grep. GUI Features: - input - output - cls --- .../LALR1/grammar/runtime/RuntimeMachine.java | 17 +- .../LALR1/interpret/module/ModuleUI.java | 155 ++++++++++++++++++ .../bajdcc/LALR1/interpret/os/kern/OSIrq.java | 5 + .../interpret/os/user/routine/URShell.java | 31 ++-- src/priv/bajdcc/LALR1/ui/UIMainFrame.java | 115 +++++++++++++ src/priv/bajdcc/LALR1/ui/UIPanel.java | 42 +++++ .../bajdcc/LALR1/ui/drawing/UIFontImage.java | 41 +++++ .../bajdcc/LALR1/ui/drawing/UIGraphics.java | 95 +++++++++++ src/priv/bajdcc/LALR1/ui/drawing/UIPoint.java | 23 +++ 9 files changed, 499 insertions(+), 25 deletions(-) create mode 100644 src/priv/bajdcc/LALR1/interpret/module/ModuleUI.java create mode 100644 src/priv/bajdcc/LALR1/ui/UIMainFrame.java create mode 100644 src/priv/bajdcc/LALR1/ui/UIPanel.java create mode 100644 src/priv/bajdcc/LALR1/ui/drawing/UIFontImage.java create mode 100644 src/priv/bajdcc/LALR1/ui/drawing/UIGraphics.java create mode 100644 src/priv/bajdcc/LALR1/ui/drawing/UIPoint.java diff --git a/src/priv/bajdcc/LALR1/grammar/runtime/RuntimeMachine.java b/src/priv/bajdcc/LALR1/grammar/runtime/RuntimeMachine.java index 999bb53..cdf14e7 100755 --- a/src/priv/bajdcc/LALR1/grammar/runtime/RuntimeMachine.java +++ b/src/priv/bajdcc/LALR1/grammar/runtime/RuntimeMachine.java @@ -1,15 +1,5 @@ package priv.bajdcc.LALR1.grammar.runtime; -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Stack; - import priv.bajdcc.LALR1.grammar.Grammar; import priv.bajdcc.LALR1.grammar.runtime.RuntimeException.RuntimeError; import priv.bajdcc.LALR1.grammar.runtime.data.RuntimeArray; @@ -23,6 +13,12 @@ import priv.bajdcc.util.lexer.token.Token; import priv.bajdcc.util.lexer.token.TokenType; +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.InputStream; +import java.util.*; +import java.util.Map.Entry; + /** * 【虚拟机】运行时自动机 * @@ -51,6 +47,7 @@ public RuntimeMachine() throws Exception { ModuleList.getInstance(), ModuleString.getInstance(), ModuleProc.getInstance(), + ModuleUI.getInstance(), }; } diff --git a/src/priv/bajdcc/LALR1/interpret/module/ModuleUI.java b/src/priv/bajdcc/LALR1/interpret/module/ModuleUI.java new file mode 100644 index 0000000..161c163 --- /dev/null +++ b/src/priv/bajdcc/LALR1/interpret/module/ModuleUI.java @@ -0,0 +1,155 @@ +package priv.bajdcc.LALR1.interpret.module; + +import priv.bajdcc.LALR1.grammar.Grammar; +import priv.bajdcc.LALR1.grammar.runtime.*; +import priv.bajdcc.LALR1.ui.drawing.UIGraphics; + +import java.util.ArrayDeque; +import java.util.List; +import java.util.Queue; +import java.util.concurrent.LinkedBlockingDeque; + +/** + * 【模块】界面 + * + * @author bajdcc + */ +public class ModuleUI implements IInterpreterModule { + + private static final int INPUT_TIME = 10; + private static ModuleUI instance = new ModuleUI(); + private UIGraphics graphics; + private Queue queue = new LinkedBlockingDeque<>(1024); + private Queue queueDisplay = new ArrayDeque<>(); + private StringBuilder sb = new StringBuilder(); + + public void setGraphics(UIGraphics graphics) { + this.graphics = graphics; + } + + public void addInputChar(char c) { + queue.add(c); + } + + public static ModuleUI getInstance() { + return instance; + } + + @Override + public String getModuleName() { + return "sys.ui"; + } + + @Override + public RuntimeCodePage getCodePage() throws Exception { + String base = "import \"sys.base\";\n" + + "import \"sys.proc\";\n" + + "import \"sys.string\";\n" + + "var g_ui_print = func ~(str) {\n" + + " var ui_int = call g_create_pipe(\"int#12\");\n" + + " foreach (var c : call g_range_string(str)) {\n" + + " call g_write_pipe(ui_int, c);\n" + + " }\n" + + "};\n" + + "export \"g_ui_print\";\n" + + "var g_ui_printn = func ~(str) {\n" + + " call g_ui_print(str);\n" + + " call g_ui_println();\n" + + "};\n" + + "export \"g_ui_printn\";\n" + + "var g_ui_println = func ~() {\n" + + " call g_ui_print(g_endl);\n" + + "};\n" + + "export \"g_ui_println\";\n" + + "var g_ui_input = func ~() {\n" + + " for (;;) {\n" + + " var s = call g_ui_input_internal();\n" + + " if (!call g_is_null(s)) {\n" + + " call g_ui_println();\n" + + " return s;\n" + + " }\n" + + " var c = call g_ui_print_input();\n" + + " if (!call g_is_null(c)) {\n" + + " call g_ui_print(c);\n" + + " }\n" + + " }\n" + + "};\n" + + "export \"g_ui_input\";\n"; + + Grammar grammar = new Grammar(base); + RuntimeCodePage page = grammar.getCodePage(); + IRuntimeDebugInfo info = page.getInfo(); + buildUIMethods(info); + + return page; + } + + private void buildUIMethods(IRuntimeDebugInfo info) { + info.addExternalFunc("g_ui_print_internal", new IRuntimeDebugExec() { + @Override + public String getDoc() { + return "显示输出"; + } + + @Override + public RuntimeObjectType[] getArgsType() { + return new RuntimeObjectType[]{RuntimeObjectType.kChar}; + } + + @Override + public RuntimeObject ExternalProcCall(List args, + IRuntimeStatus status) throws Exception { + graphics.drawText((char) args.get(0).getObj()); + return null; + } + }); + info.addExternalFunc("g_ui_input_internal", new IRuntimeDebugExec() { + @Override + public String getDoc() { + return "显示输入"; + } + + @Override + public RuntimeObjectType[] getArgsType() { + return null; + } + + @Override + public RuntimeObject ExternalProcCall(List args, + IRuntimeStatus status) throws Exception { + status.getService().getProcessService().sleep(status.getPid(), INPUT_TIME); + Character c = queue.poll(); + if (c == null) { + return null; + } + if (c.equals('\n')) { + String str = sb.toString(); + sb = new StringBuilder(); + queueDisplay.clear(); + return new RuntimeObject(str); + } else { + queueDisplay.add(c); + sb.append(c); + } + return null; + } + }); + info.addExternalFunc("g_ui_print_input", new IRuntimeDebugExec() { + @Override + public String getDoc() { + return "实时显示输入"; + } + + @Override + public RuntimeObjectType[] getArgsType() { + return null; + } + + @Override + public RuntimeObject ExternalProcCall(List args, + IRuntimeStatus status) throws Exception { + return new RuntimeObject(queueDisplay.poll()); + } + }); + } +} diff --git a/src/priv/bajdcc/LALR1/interpret/os/kern/OSIrq.java b/src/priv/bajdcc/LALR1/interpret/os/kern/OSIrq.java index 8b6310b..92df561 100644 --- a/src/priv/bajdcc/LALR1/interpret/os/kern/OSIrq.java +++ b/src/priv/bajdcc/LALR1/interpret/os/kern/OSIrq.java @@ -21,6 +21,7 @@ public String getCode() { return "import \"sys.base\";\n" + "import \"sys.list\";\n" + "import \"sys.proc\";\n" + + "import \"sys.ui\";\n" + "var interrupt_num = " + INT_NUM + ";\n" + "var int_table = [];\n" + "foreach (var i : call g_range(0, interrupt_num - 1)) {\n" + @@ -74,6 +75,10 @@ public String getCode() { " }\n" + "};\n" + "call add_int_proc(10, schd_handler);\n" + + "var print_handler = func ~(ch) {\n" + + " call g_ui_print_internal(ch);\n" + + "};\n" + + "call add_int_proc(12, print_handler);\n" + ""; } } diff --git a/src/priv/bajdcc/LALR1/interpret/os/user/routine/URShell.java b/src/priv/bajdcc/LALR1/interpret/os/user/routine/URShell.java index 8c1fc4d..b580194 100644 --- a/src/priv/bajdcc/LALR1/interpret/os/user/routine/URShell.java +++ b/src/priv/bajdcc/LALR1/interpret/os/user/routine/URShell.java @@ -19,18 +19,19 @@ public String getCode() { "import \"sys.list\";\n" + "import \"sys.string\";\n" + "import \"sys.proc\";\n" + + "import \"sys.ui\";\n" + "\n" + "// PRINT WELCOME\n" + "var welcome = func [\"WELCOME\"] ~() {\n" + - " call g_println();\n" + - " call g_printn(\" ________ ________ ___ ________ ________ ________ \");\n" + - " call g_printn(\"|\\\\ __ \\\\|\\\\ __ \\\\ |\\\\ \\\\|\\\\ ___ \\\\|\\\\ ____\\\\|\\\\ ____\\\\ \");\n" + - " call g_printn(\"\\\\ \\\\ \\\\|\\\\ /\\\\ \\\\ \\\\|\\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\_|\\\\ \\\\ \\\\ \\\\___|\\\\ \\\\ \\\\___| \");\n" + - " call g_printn(\" \\\\ \\\\ __ \\\\ \\\\ __ \\\\ __ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\\\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \");\n" + - " call g_printn(\" \\\\ \\\\ \\\\|\\\\ \\\\ \\\\ \\\\ \\\\ \\\\|\\\\ \\\\\\\\_\\\\ \\\\ \\\\ \\\\_\\\\\\\\ \\\\ \\\\ \\\\____\\\\ \\\\ \\\\____ \");\n" + - " call g_printn(\" \\\\ \\\\_______\\\\ \\\\__\\\\ \\\\__\\\\ \\\\________\\\\ \\\\_______\\\\ \\\\_______\\\\ \\\\_______\\\\\");\n" + - " call g_printn(\" \\\\|_______|\\\\|__|\\\\|__|\\\\|________|\\\\|_______|\\\\|_______|\\\\|_______|\");\n" + - " call g_println();\n" + + " call g_ui_println();\n" + + " call g_ui_printn(\" ________ ________ ___ ________ ________ ________ \");\n" + + " call g_ui_printn(\"|\\\\ __ \\\\|\\\\ __ \\\\ |\\\\ \\\\|\\\\ ___ \\\\|\\\\ ____\\\\|\\\\ ____\\\\ \");\n" + + " call g_ui_printn(\"\\\\ \\\\ \\\\|\\\\ /\\\\ \\\\ \\\\|\\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\_|\\\\ \\\\ \\\\ \\\\___|\\\\ \\\\ \\\\___| \");\n" + + " call g_ui_printn(\" \\\\ \\\\ __ \\\\ \\\\ __ \\\\ __ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\\\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \");\n" + + " call g_ui_printn(\" \\\\ \\\\ \\\\|\\\\ \\\\ \\\\ \\\\ \\\\ \\\\|\\\\ \\\\\\\\_\\\\ \\\\ \\\\ \\\\_\\\\\\\\ \\\\ \\\\ \\\\____\\\\ \\\\ \\\\____ \");\n" + + " call g_ui_printn(\" \\\\ \\\\_______\\\\ \\\\__\\\\ \\\\__\\\\ \\\\________\\\\ \\\\_______\\\\ \\\\_______\\\\ \\\\_______\\\\\");\n" + + " call g_ui_printn(\" \\\\|_______|\\\\|__|\\\\|__|\\\\|________|\\\\|_______|\\\\|_______|\\\\|_______|\");\n" + + " call g_ui_println();\n" + "};\n" + "call g_join_process(call g_create_user_process(welcome));\n" + "\n" + @@ -50,7 +51,7 @@ public String getCode() { " var child = call g_load_user_x(path);\n" + " call g_start_share(\"PID#\" + child, share);\n" + " if (child+1 == 0) {\n" + - " call g_printn(\"Cannot execute '\"+path+\"'.\");\n" + + " call g_ui_printn(\"Cannot execute '\"+path+\"'.\");\n" + " var p = call g_wait_pipe(\"PIPEIN#\" + parent);\n" + " call g_sleep(50);\n" + " call g_destroy_pipe(p);\n" + @@ -85,7 +86,7 @@ public String getCode() { " var path = \"/usr/p/\" + exec;\n" + " var child = call g_load_user_x(path);\n" + " if (child+1 == 0) {\n" + - " call g_printn(\"Cannot execute '\"+path+\"'.\");\n" + + " call g_ui_printn(\"Cannot execute '\"+path+\"'.\");\n" + " return;\n" + " }\n" + " call g_start_share(\"PID#\" + child, share);\n" + @@ -96,7 +97,7 @@ public String getCode() { " call g_map_put(_args_, \"parent\", child);\n" + " call g_create_user_process_args(parse, _args_);\n" + " }\n" + - " var f = func ~(ch) -> call g_print(ch);\n" + + " var f = func ~(ch) -> call g_ui_print(ch);\n" + " var out = call g_create_pipe(\"PIPEOUT#\" + child);\n" + " call g_read_pipe(out, f);\n" + "};\n" + @@ -105,11 +106,11 @@ public String getCode() { "var get_input = func [\"INPUT\"] ~(arg) {\n" + " var this = call g_array_get(arg, 0);\n" + " var parse = call g_array_get(arg, 1);\n" + - " call g_print(\"$ \");\n" + - " var cmd = call g_stdin_read_line();\n" + + " call g_ui_print(\"$ \");\n" + + " var cmd = call g_ui_input();\n" + " let cmd = call g_string_trim(cmd);\n" + " if (call g_string_length(cmd) == 0) {\n" + - " call g_printn(\"Error: no cmd\");\n" + + " call g_ui_printn(\"Error: no cmd\");\n" + " return;\n" + " }\n" + " if (cmd == \"exit\") {\n" + diff --git a/src/priv/bajdcc/LALR1/ui/UIMainFrame.java b/src/priv/bajdcc/LALR1/ui/UIMainFrame.java new file mode 100644 index 0000000..35ef88c --- /dev/null +++ b/src/priv/bajdcc/LALR1/ui/UIMainFrame.java @@ -0,0 +1,115 @@ +package priv.bajdcc.LALR1.ui; + +import priv.bajdcc.LALR1.grammar.Grammar; +import priv.bajdcc.LALR1.grammar.runtime.RuntimeCodePage; +import priv.bajdcc.LALR1.grammar.runtime.RuntimeException; +import priv.bajdcc.LALR1.interpret.Interpreter; +import priv.bajdcc.LALR1.interpret.os.IOSCodePage; +import priv.bajdcc.LALR1.interpret.os.kern.OSEntry; +import priv.bajdcc.LALR1.interpret.os.kern.OSIrq; +import priv.bajdcc.LALR1.interpret.os.proc.OSSchd; +import priv.bajdcc.LALR1.interpret.os.user.UserMain; +import priv.bajdcc.LALR1.interpret.os.user.routine.*; +import priv.bajdcc.LALR1.syntax.handler.SyntaxException; +import priv.bajdcc.LALR1.ui.drawing.UIGraphics; +import priv.bajdcc.util.lexer.error.RegexException; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.WindowEvent; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +/** + * 【界面】窗口 + * + * @author bajdcc + */ +public class UIMainFrame extends JFrame { + private UIPanel panel; + + public UIPanel getPanel() { + return panel; + } + + public UIMainFrame() { + panel = new UIPanel(); + this.setTitle("jMiniLang OS Window"); + this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + this.setPreferredSize(new Dimension(800, 600)); + this.setContentPane(panel); + this.pack(); + this.setLocationRelativeTo(null); + this.setResizable(false); + this.setVisible(true); + } + + public static void main(String[] args) { + UIMainFrame frame = new UIMainFrame(); + frame.setTimer(); + startOS(frame.getPanel().getUIGraphics()); + frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING)); + } + + private void setTimer() { + new Timer(33, e -> { + panel.repaint(); + }).start(); + } + + private static void startOS(UIGraphics g) { + IOSCodePage pages[] = new IOSCodePage[]{ + // OS + new OSEntry(), + new OSIrq(), + new OSSchd(), + // USER + new UserMain(), + // USER ROUTINE + new URShell(), + new UREcho(), + new URPipe(), + new URDup(), + new URGrep(), + }; + + try { + String code = "import \"sys.base\";\n" + + "import \"sys.proc\";\n" + + "call g_load_sync_x(\"/kern/entry\");\n"; + + Interpreter interpreter = new Interpreter(); + + for (IOSCodePage page : pages) { + interpreter.load(page.getName(), page.getCode()); + } + + Grammar grammar = new Grammar(code); + //System.out.println(grammar.toString()); + RuntimeCodePage page = grammar.getCodePage(); + //System.out.println(page.toString()); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + RuntimeCodePage.exportFromStream(page, baos); + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + interpreter.run("@main", bais); + + } catch (RegexException e) { + System.err.println(); + System.err.println(e.getPosition() + "," + e.getMessage()); + e.printStackTrace(); + } catch (SyntaxException e) { + System.err.println(); + System.err.println(e.getPosition() + "," + e.getMessage() + " " + + e.getInfo()); + e.printStackTrace(); + } catch (RuntimeException e) { + System.err.println(); + System.err.println(e.getPosition() + ": " + e.getInfo()); + e.printStackTrace(); + } catch (Exception e) { + System.err.println(); + System.err.println(e.getMessage()); + e.printStackTrace(); + } + } +} diff --git a/src/priv/bajdcc/LALR1/ui/UIPanel.java b/src/priv/bajdcc/LALR1/ui/UIPanel.java new file mode 100644 index 0000000..8198236 --- /dev/null +++ b/src/priv/bajdcc/LALR1/ui/UIPanel.java @@ -0,0 +1,42 @@ +package priv.bajdcc.LALR1.ui; + +import priv.bajdcc.LALR1.interpret.module.ModuleUI; +import priv.bajdcc.LALR1.ui.drawing.UIGraphics; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; + +/** + * 【界面】渲染界面 + * + * @author bajdcc + */ +public class UIPanel extends JPanel { + + private UIGraphics graphics; + private JTextField input; + private ModuleUI moduleUI; + + public UIPanel() { + this.graphics = new UIGraphics(800, 600, 72, 23, 11, 25, 1); + moduleUI = ModuleUI.getInstance(); + moduleUI.setGraphics(this.graphics); + this.setFocusable(true); + this.addKeyListener(new KeyAdapter() { + public void keyTyped(KeyEvent e) { + moduleUI.addInputChar(e.getKeyChar()); + } + }); + } + + public UIGraphics getUIGraphics() { + return graphics; + } + + public void paint(Graphics g) { + //super.paint(g); + graphics.paint((Graphics2D) g); + } +} diff --git a/src/priv/bajdcc/LALR1/ui/drawing/UIFontImage.java b/src/priv/bajdcc/LALR1/ui/drawing/UIFontImage.java new file mode 100644 index 0000000..e34f21b --- /dev/null +++ b/src/priv/bajdcc/LALR1/ui/drawing/UIFontImage.java @@ -0,0 +1,41 @@ +package priv.bajdcc.LALR1.ui.drawing; + +import java.awt.*; +import java.awt.image.BufferedImage; + +/** + * 【界面】点阵文字位图 + * + * @author bajdcc + */ +public class UIFontImage { + private int width, height; + private Image[] images; + + public UIFontImage(int width, int height) { + this.width = width; + this.height = height; + this.images = new BufferedImage[256]; + for (int i = 0; i < 256; i++) { + this.images[i] = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics g = this.images[i].getGraphics(); + g.setColor(Color.white); + g.fillRect(0, 0, width, height); + if (!Character.isISOControl((char) i)) { + g.setColor(Color.black); + g.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 18)); + String str = Character.toString((char) i); + int x = width / 2 - g.getFontMetrics().stringWidth(str) / 2; + int y = height / 2 + g.getFontMetrics().getHeight() / 3; + g.drawString(str, x, y); + } + } + } + + public Image getImage(int c) { + if (c >= 0 && c <= 255) { + return this.images[c]; + } + return this.images[0]; + } +} diff --git a/src/priv/bajdcc/LALR1/ui/drawing/UIGraphics.java b/src/priv/bajdcc/LALR1/ui/drawing/UIGraphics.java new file mode 100644 index 0000000..364138d --- /dev/null +++ b/src/priv/bajdcc/LALR1/ui/drawing/UIGraphics.java @@ -0,0 +1,95 @@ +package priv.bajdcc.LALR1.ui.drawing; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.util.Queue; +import java.util.concurrent.LinkedBlockingQueue; + +/** + * 【界面】显示屏 + * + * @author bajdcc + */ +public class UIGraphics { + + private int w, h, cols, rows, width, height, zoom, size; + private char[] data; + private int ptr_x, ptr_y; + private Queue queue; + private UIFontImage fontImage; + private Image image; + + public UIGraphics(int w, int h, int cols, int rows, int width, int height, int zoom) { + this.w = w; + this.h = h; + this.cols = cols; + this.rows = rows; + this.size = cols * rows; + this.width = width * zoom; + this.height = height * zoom; + this.zoom = zoom; + this.data = new char[cols * rows]; + this.ptr_x = 0; + this.ptr_y = 0; + this.queue = new LinkedBlockingQueue<>(1024); + this.fontImage = new UIFontImage(this.width, this.height); + this.image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); + this.image.getGraphics().setColor(Color.white); + this.image.getGraphics().fillRect(0, 0, w, h); + } + + public void paint(Graphics2D g) { + for (; ; ) { + Character c = this.queue.poll(); + if (c == null) + break; + draw(g, c); + } + g.drawImage(image, 0, 0, null); + } + + private void draw(Graphics2D g, char c) { + if (c == '\n') { + if (ptr_y == rows) { + clear(g); + } else { + ptr_x = 0; + ptr_y++; + } + } else if (ptr_x == cols) { + if (ptr_y == rows) { + clear(g); + drawChar(g, c); + ptr_x++; + } else { + drawChar(g, c); + ptr_x = 0; + ptr_y++; + } + } else { + drawChar(g, c); + ptr_x++; + } + } + + private void drawChar(Graphics2D g, char c) { + this.data[ptr_y * rows + ptr_x] = c; + image.getGraphics().drawImage(fontImage.getImage(c), + ptr_x * width, ptr_y * height, null); + } + + public void clear(Graphics2D g) { + this.ptr_x = 0; + this.ptr_y = 0; + for (int i = 0; i < size; i++) { + this.data[i] = '\0'; + } + image.getGraphics().setColor(Color.white); + image.getGraphics().fillRect(0, 0, w, h); + g.drawImage(image, 0, 0, null); + } + + public void drawText(char c) { + this.queue.add(c); + } +} diff --git a/src/priv/bajdcc/LALR1/ui/drawing/UIPoint.java b/src/priv/bajdcc/LALR1/ui/drawing/UIPoint.java new file mode 100644 index 0000000..65981c7 --- /dev/null +++ b/src/priv/bajdcc/LALR1/ui/drawing/UIPoint.java @@ -0,0 +1,23 @@ +package priv.bajdcc.LALR1.ui.drawing; + +/** + * 【界面】点 + * + * @author bajdcc + */ +public class UIPoint { + public int x, y; + + public UIPoint(int x, int y) { + this.x = x; + this.y = y; + } + + @Override + public String toString() { + return "UIPoint{" + + "X=" + x + + ", Y=" + y + + '}'; + } +}