diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 19c25a3..bbf545a 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -7,6 +7,7 @@ + diff --git a/pom.xml b/pom.xml index ee2953a..621ac24 100644 --- a/pom.xml +++ b/pom.xml @@ -43,6 +43,12 @@ 5.8.26 + + org.xerial + sqlite-jdbc + 3.14.2.1 + + com.melloware diff --git a/src/main/java/xyz/wbsite/jmacro/JMacro.java b/src/main/java/xyz/wbsite/jmacro/JMacro.java index 625f5b7..6e95d7c 100644 --- a/src/main/java/xyz/wbsite/jmacro/JMacro.java +++ b/src/main/java/xyz/wbsite/jmacro/JMacro.java @@ -11,6 +11,7 @@ import xyz.wbsite.jmacro.util.*; import java.awt.*; import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; import java.io.File; import java.util.ArrayList; @@ -300,6 +301,26 @@ public abstract class JMacro { robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); } + /** + * 执行复制命令 + */ + public void sendCopyCommand() { + robot.keyPress(KeyEvent.VK_CONTROL); + robot.keyPress(KeyEvent.VK_C); + robot.keyRelease(KeyEvent.VK_C); + robot.keyRelease(KeyEvent.VK_CONTROL); + } + + /** + * 执行粘贴命令 + */ + public void sendPasteCommand() { + robot.keyPress(KeyEvent.VK_CONTROL); + robot.keyPress(KeyEvent.VK_V); + robot.keyRelease(KeyEvent.VK_V); + robot.keyRelease(KeyEvent.VK_CONTROL); + } + /** * 捕获指定区域屏幕 */ diff --git a/src/main/java/xyz/wbsite/jmacro/JMainController.java b/src/main/java/xyz/wbsite/jmacro/JMainController.java index e7aecbb..82283db 100644 --- a/src/main/java/xyz/wbsite/jmacro/JMainController.java +++ b/src/main/java/xyz/wbsite/jmacro/JMainController.java @@ -1,5 +1,12 @@ package xyz.wbsite.jmacro; +import cn.hutool.core.collection.BoundedPriorityQueue; +import cn.hutool.core.util.StrUtil; +import javafx.fxml.FXML; +import javafx.scene.control.Button; +import javafx.scene.control.TextArea; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; import xyz.wbsite.jmacro.base.Legend; import xyz.wbsite.jmacro.base.ViewRect; import xyz.wbsite.jmacro.tool.Measure; @@ -7,10 +14,6 @@ import xyz.wbsite.jmacro.tool.PickLegend; import xyz.wbsite.jmacro.tool.PickPoint; import xyz.wbsite.jmacro.tool.PickRect; import xyz.wbsite.jmacro.util.DialogUtil; -import javafx.fxml.FXML; -import javafx.scene.control.Button; -import javafx.scene.image.Image; -import javafx.scene.image.ImageView; import java.awt.*; import java.util.concurrent.Semaphore; @@ -32,6 +35,11 @@ public class JMainController { private Button capture; @FXML private ImageView preview; + @FXML + private TextArea console; + + private final int MAX_LENGTH = 100; + private final BoundedPriorityQueue logs = new BoundedPriorityQueue<>(MAX_LENGTH); private Semaphore semaphore = new Semaphore(1); @@ -127,7 +135,7 @@ public class JMainController { /** * 预览 * - * @param image + * @param image 图片 */ public void preview(Image image) { try { @@ -143,4 +151,20 @@ public class JMainController { throw new RuntimeException(e); } } + + /** + * 日志窗口 + * + * @param log 格式化 + * @param args 参数 + */ + public synchronized void println(String log, Object... args) { + String format = StrUtil.format(log, args) + "\n"; + if (logs.size() >= MAX_LENGTH) { + String poll = logs.poll(); + console.deleteText(0, poll.length()); + } + logs.add(format); + console.appendText(format); + } } diff --git a/src/main/java/xyz/wbsite/jmacro/db/Client.java b/src/main/java/xyz/wbsite/jmacro/db/Client.java new file mode 100644 index 0000000..8f4ef54 --- /dev/null +++ b/src/main/java/xyz/wbsite/jmacro/db/Client.java @@ -0,0 +1,151 @@ +package xyz.wbsite.jmacro.db; + +import java.io.File; +import java.sql.Connection; +import java.sql.Date; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Time; +import java.sql.Types; + +/** + * xyz.wbsite.wsqlite.Client + * + * @author wangbing + */ +public class Client { + + Connection connection; + ResultSet resultSet; + String dbFilePath; + + /** + * 构造函数 + * + * @param dbFile 文件 + * @throws ClassNotFoundException + * @throws SQLException + */ + public Client(File dbFile) throws ClassNotFoundException, SQLException { + this.dbFilePath = dbFile.getAbsolutePath(); + if (!dbFile.exists()) { + connection = getConnection(); + } + } + + /** + * 执行sql语句 + * + * @param sql + * @throws SQLException + * @throws ClassNotFoundException + */ + public void execute(String sql) throws SQLException, ClassNotFoundException { + try { + executeUpdate(sql); + } finally { + destroyed(); + } + } + + /** + * 执行sql查询语句 + * + * @param sql + * @throws SQLException + * @throws ClassNotFoundException + */ + public ResultSet executeQuery(String sql, Object... args) throws SQLException, ClassNotFoundException { + PreparedStatement preparedStatement = getConnection().prepareStatement(sql); + setArg(preparedStatement, args); + return preparedStatement.executeQuery(); + } + + /** + * 执行sql语句 + * + * @param sql + * @throws SQLException + * @throws ClassNotFoundException + */ + public int executeUpdate(String sql, Object... args) throws SQLException, ClassNotFoundException { + try { + PreparedStatement preparedStatement = getConnection().prepareStatement(sql); + setArg(preparedStatement, args); + return preparedStatement.executeUpdate(); + } finally { + destroyed(); + } + } + + private void setArg(PreparedStatement ps, Object... args) throws SQLException { + for (int i = 0; i < args.length; i++) { + Object arg = args[i]; + + if (arg == null) { + ps.setNull(i + 1, Types.NULL); + } else if (arg instanceof String) { + ps.setString(i + 1, (String) arg); + } else if (arg instanceof Date) { + ps.setDate(i + 1, (Date) arg); + } else if (arg instanceof Time) { + ps.setTime(i + 1, (Time) arg); + } else if (arg instanceof java.util.Date) { + ps.setLong(i + 1, ((java.util.Date) arg).getTime()); + } else if (arg instanceof Boolean) { + ps.setBoolean(i + 1, (Boolean) arg); + } else if (arg instanceof Byte) { + ps.setByte(i + 1, (Byte) arg); + } else if (arg instanceof Short) { + ps.setShort(i + 1, (Short) arg); + } else if (arg instanceof Integer) { + ps.setInt(i + 1, (int) arg); + } else if (arg instanceof Long) { + ps.setLong(i + 1, (long) arg); + } else if (arg instanceof Float) { + ps.setFloat(i + 1, (float) arg); + } else if (arg instanceof Double) { + ps.setDouble(i + 1, (double) arg); + } else if (arg instanceof byte[]) { + ps.setBytes(i + 1, (byte[]) arg); + } + } + } + + /** + * 获取数据库连接 + * + * @return 数据库连接 + * @throws ClassNotFoundException + * @throws SQLException + */ + Connection getConnection() throws ClassNotFoundException, SQLException { + if (null == connection) { + Class.forName("org.sqlite.JDBC"); + connection = DriverManager.getConnection("jdbc:sqlite:" + dbFilePath); + } + return connection; + } + + /** + * 数据库资源关闭和释放 + */ + public void destroyed() { + try { + if (null != resultSet) { + resultSet.close(); + resultSet = null; + } + + if (null != connection) { + connection.close(); + connection = null; + } + + } catch (SQLException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/main/java/xyz/wbsite/jmacro/db/ObjectClient.java b/src/main/java/xyz/wbsite/jmacro/db/ObjectClient.java new file mode 100644 index 0000000..9c55b20 --- /dev/null +++ b/src/main/java/xyz/wbsite/jmacro/db/ObjectClient.java @@ -0,0 +1,323 @@ +package xyz.wbsite.jmacro.db; + + +import xyz.wbsite.jmacro.db.anonation.TableField; + +import java.io.File; +import java.lang.reflect.Field; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * xyz.wbsite.wsqlite.Client + * + * @author wangbing + */ +public class ObjectClient extends Client { + + private Map classMap = new HashMap<>(); + + /** + * 构造函数 + * + * @param dbFile 文件 + * @param classList 注册对象 + * @throws ClassNotFoundException + * @throws SQLException + */ + public ObjectClient(File dbFile, List classList) throws ClassNotFoundException, SQLException { + super(dbFile); + for (Class aClass : classList) { + classMap.put(aClass.getName(), aClass); + } + for (String key : classMap.keySet()) { + Class object = classMap.get(key); + StringBuffer sql = new StringBuffer(); + String name = object.getSimpleName(); + + sql.append("CREATE TABLE IF NOT EXISTS "); + sql.append(name); + sql.append(" ("); + + Field[] fields = object.getDeclaredFields(); + for (Field f : fields) { + if (f.isAnnotationPresent(TableField.class)) { + TableField bind = f.getAnnotation(TableField.class); + int length = bind.value(); + + if (f.getType() == String.class) { + sql.append(f.getName().toUpperCase()); + sql.append(" VARCHAR(" + length + "),"); + } else if (f.getType() == Boolean.class || f.getType() == boolean.class) { + sql.append(f.getName().toUpperCase()); + sql.append(" BOOLEAN,"); + } else if (f.getType() == Byte.class || f.getType() == byte.class || + f.getType() == Short.class || f.getType() == short.class || + f.getType() == Character.class || f.getType() == char.class || + f.getType() == Integer.class || f.getType() == int.class || + f.getType() == Long.class || f.getType() == long.class) { + sql.append(f.getName().toUpperCase()); + sql.append(" INTEGER,"); + } else if (f.getType() == Float.class || f.getType() == float.class || + f.getType() == Double.class || f.getType() == double.class) { + sql.append(f.getName().toUpperCase()); + sql.append(" REAL,"); + } else if (f.getType() == Byte[].class || f.getType() == byte[].class) { + sql.append(f.getName().toUpperCase()); + sql.append(" BLOB,"); + } else if (f.getType() == Date.class) { + sql.append(f.getName().toUpperCase()); + sql.append(" TIMESTAMP,"); + } + } + } + + sql.replace(sql.length() - 1, sql.length(), ""); + sql.append(")"); + System.out.println("SQL ==> " + sql.toString()); + execute(sql.toString()); + } + } + + public int insert(Class poClass, T po) throws SQLException, ClassNotFoundException { + try { + Class aClass = classMap.get(poClass.getName()); + if (aClass == null) { + System.err.println(poClass.getName() + " not found."); + } else { + StringBuffer sql = new StringBuffer(); + sql.append("INSERT INTO "); + sql.append(aClass.getSimpleName()); + sql.append("("); + + //获取字段列表 + List fs = getFields(poClass); + + StringBuffer fieldsSql = new StringBuffer(); + StringBuffer valueSql = new StringBuffer(); + Object[] values = new Object[fs.size()]; + + for (int i = 0; i < fs.size(); i++) { + Field f = fs.get(i); + f.setAccessible(true); + fieldsSql.append(f.getName().toUpperCase()); + valueSql.append("?"); + values[i] = f.get(po); + if (i != fs.size() - 1) { + fieldsSql.append(","); + valueSql.append(","); + } + } + + sql.append(fieldsSql); + sql.append(") VALUES ("); + sql.append(valueSql); + sql.append(")"); + System.out.println("SQL ==> " + sql.toString()); + return executeUpdate(sql.toString(), values); + } + } catch (IllegalAccessException e) { + e.printStackTrace(); + } finally { + destroyed(); + } + return 0; + } + + public int delete(Class poClass, Where where) throws SQLException, ClassNotFoundException { + try { + Class aClass = classMap.get(poClass.getName()); + if (aClass == null) { + System.err.println(poClass.getName() + " not found."); + } else { + StringBuffer sql = new StringBuffer(); + sql.append("DELETE FROM "); + sql.append(aClass.getSimpleName()); + sql.append(where.getSql()); + System.out.println("SQL ==> " + sql.toString()); + return executeUpdate(sql.toString(), where.getArgs()); + } + } finally { + destroyed(); + } + return 0; + } + + public int update(Class poClass, T po, Where where) throws SQLException, ClassNotFoundException { + try { + Class aClass = classMap.get(poClass.getName()); + if (aClass == null) { + System.err.println(poClass.getName() + " not found."); + } else { + //获取字段列表 + List fs = getFields(poClass); + + StringBuffer sql = new StringBuffer(); + Object[] values = new Object[fs.size()]; + sql.append("UPDATE "); + sql.append(aClass.getSimpleName()); + sql.append(" SET "); + + for (int i = 0; i < fs.size(); i++) { + Field f = fs.get(i); + f.setAccessible(true); + sql.append(f.getName()); + sql.append(" = ?"); + values[i] = f.get(po); + if (i != fs.size() - 1) { + sql.append(","); + } + } + + // 条件 + sql.append(where.getSql()); + + System.out.println("SQL ==> " + sql.toString()); + return executeUpdate(sql.toString(), concat(values, where.getArgs())); + } + } catch (IllegalAccessException e) { + e.printStackTrace(); + } finally { + destroyed(); + } + return 0; + } + + public List select(Class poClass, Where where, int pageNumber, int pageSize) throws SQLException, ClassNotFoundException { + ArrayList list = new ArrayList<>(); + try { + Class aClass = classMap.get(poClass.getName()); + if (aClass == null) { + System.err.println(poClass.getName() + " not found."); + } else { + StringBuffer sql = new StringBuffer(); + sql.append("SELECT "); + + //获取字段列表 + List fs = getFields(poClass); + + for (int i = 0; i < fs.size(); i++) { + Field f = fs.get(i); + sql.append(f.getName().toUpperCase()); + if (i != fs.size() - 1) { + sql.append(","); + } + } + + sql.append(" FROM "); + sql.append(aClass.getSimpleName()); + + // 条件 + sql.append(where.getSql()); + + //分页参数 + if (pageSize > 0) { + sql.append(" LIMIT " + (pageNumber - 1) + "," + pageSize); + } + + System.out.println("SQL ==> " + sql.toString()); + list.addAll(executeQuery(poClass, sql.toString(), where.getArgs())); + } + } finally { + destroyed(); + } + return list; + } + + /** + * 执行select查询,返回结果列表 + * + * @param sql sql select 语句 + * @param poClass 结果集的行数据处理类对象 + * @return + * @throws SQLException + * @throws ClassNotFoundException + */ + public List executeQuery(Class poClass, String sql, Object... args) throws SQLException, ClassNotFoundException { + List rsList = new ArrayList(); + try { + resultSet = executeQuery(sql, args); + + //获取字段列表 + List fs = getFields(poClass); + + while (resultSet.next()) { + try { + T o = poClass.newInstance(); + for (int i = 0; i < fs.size(); i++) { + Field f = fs.get(i); + f.setAccessible(true); + + if (f.getType() == String.class) { + String v = resultSet.getString(f.getName()); + f.set(o, v); + } else if (f.getType() == Boolean.class || f.getType() == boolean.class) { + boolean v = resultSet.getBoolean(f.getName()); + f.set(o, v); + } else if (f.getType() == Byte.class || f.getType() == byte.class) { + byte v = resultSet.getByte(f.getName()); + f.set(o, v); + } else if (f.getType() == Short.class || f.getType() == short.class) { + short v = resultSet.getShort(f.getName()); + f.set(o, v); + } else if (f.getType() == Character.class || f.getType() == char.class) { + short v = resultSet.getShort(f.getName()); + f.set(o, (char) v); + } else if (f.getType() == Integer.class || f.getType() == int.class) { + int v = resultSet.getInt(f.getName()); + f.set(o, v); + } else if (f.getType() == Long.class || f.getType() == long.class) { + long v = resultSet.getLong(f.getName()); + f.set(o, v); + } else if (f.getType() == Float.class || f.getType() == float.class) { + float v = resultSet.getFloat(f.getName()); + f.set(o, v); + } else if (f.getType() == Double.class || f.getType() == double.class) { + double v = resultSet.getDouble(f.getName()); + f.set(o, v); + } else if (f.getType() == Byte[].class || f.getType() == byte[].class) { + byte[] v = resultSet.getBytes(f.getName()); + f.set(o, v); + } else if (f.getType() == Date.class) { + Date v = resultSet.getDate(f.getName()); + f.set(o, v); + } else { + String v = resultSet.getString(f.getName()); + f.set(o, v); + } + } + rsList.add(o); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + } finally { + destroyed(); + } + return rsList; + } + + private List getFields(Class aClass) { + List fs = new ArrayList<>(); + for (Field f : aClass.getDeclaredFields()) { + if (f.isAnnotationPresent(TableField.class)) { + fs.add(f); + } + } + return fs; + } + + private T[] concat(T[] arr1, T[] arr2) { + List temp = new ArrayList<>(); + temp.addAll(Arrays.asList(arr1)); + temp.addAll(Arrays.asList(arr2)); + return (T[]) temp.toArray(); + } +} \ No newline at end of file diff --git a/src/main/java/xyz/wbsite/jmacro/db/Where.java b/src/main/java/xyz/wbsite/jmacro/db/Where.java new file mode 100644 index 0000000..13f66f9 --- /dev/null +++ b/src/main/java/xyz/wbsite/jmacro/db/Where.java @@ -0,0 +1,94 @@ +package xyz.wbsite.jmacro.db; + +import java.util.ArrayList; +import java.util.List; + +public class Where { + private String sql; + private Object[] args; + + private Where() { + } + + public String getSql() { + return sql; + } + + public void setSql(String sql) { + this.sql = sql; + } + + public Object[] getArgs() { + return args; + } + + public void setArgs(Object[] args) { + this.args = args; + } + + public Where(String sql, Object[] args) { + this.sql = sql; + this.args = args; + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private StringBuilder sb = new StringBuilder(); + private List argsList = new ArrayList<>(); + + public Builder eq(String name, Object value) { + return eq(true, name, value); + } + + public Builder like(String name, Object value) { + return like(true, name, value); + } + + public Builder isNull(String name, Object value) { + return isNull(true, name, value); + } + + public Builder isNotNull(String name, Object value) { + return isNotNull(true, name, value); + } + + public Builder eq(boolean condition, String name, Object value) { + if (condition) { + sb.append(sb.length() > 0 ? " and " : " where ").append(name).append(" = ? "); + argsList.add(value); + } + return this; + } + + public Builder like(boolean condition, String name, Object value) { + if (condition) { + sb.append(sb.length() > 0 ? " and " : " where ").append(name).append("like ?"); + argsList.add(value); + } + return this; + } + + public Builder isNull(boolean condition, String name, Object value) { + if (condition) { + sb.append(sb.length() > 0 ? " and " : " where ").append(name).append("is null"); + argsList.add(value); + } + return this; + } + + public Builder isNotNull(boolean condition, String name, Object value) { + if (condition) { + sb.append(sb.length() > 0 ? " and " : " where ").append(name).append("is not null"); + argsList.add(value); + } + return this; + } + + public Where build() { + return new Where(sb.toString(), argsList.toArray()); + } + } +} diff --git a/src/main/java/xyz/wbsite/jmacro/db/anonation/TableField.java b/src/main/java/xyz/wbsite/jmacro/db/anonation/TableField.java new file mode 100644 index 0000000..f78299e --- /dev/null +++ b/src/main/java/xyz/wbsite/jmacro/db/anonation/TableField.java @@ -0,0 +1,13 @@ +package xyz.wbsite.jmacro.db.anonation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface TableField { + + int value() default 20; +} diff --git a/src/main/java/xyz/wbsite/jmacro/db/entity/Example.java b/src/main/java/xyz/wbsite/jmacro/db/entity/Example.java new file mode 100644 index 0000000..4bd2d9b --- /dev/null +++ b/src/main/java/xyz/wbsite/jmacro/db/entity/Example.java @@ -0,0 +1,110 @@ +package xyz.wbsite.jmacro.db.entity; + + +import xyz.wbsite.jmacro.db.anonation.TableField; + +import java.util.Date; + +public class Example { + + @TableField(40) + private String s; + @TableField + private boolean b; + @TableField + private byte[] bs; + @TableField + private byte b1; + @TableField + private short s1; + @TableField + private int age; + @TableField + private long id; + @TableField + private float f1; + @TableField + private double d1; + @TableField + private Date date; + + public String getS() { + return s; + } + + public void setS(String s) { + this.s = s; + } + + public boolean isB() { + return b; + } + + public void setB(boolean b) { + this.b = b; + } + + public byte[] getBs() { + return bs; + } + + public void setBs(byte[] bs) { + this.bs = bs; + } + + public byte getB1() { + return b1; + } + + public void setB1(byte b1) { + this.b1 = b1; + } + + public short getS1() { + return s1; + } + + public void setS1(short s1) { + this.s1 = s1; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public float getF1() { + return f1; + } + + public void setF1(float f1) { + this.f1 = f1; + } + + public double getD1() { + return d1; + } + + public void setD1(double d1) { + this.d1 = d1; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } +} diff --git a/src/main/java/xyz/wbsite/jmacro/util/Logger.java b/src/main/java/xyz/wbsite/jmacro/util/Logger.java index 3bc7b61..fb3ea83 100644 --- a/src/main/java/xyz/wbsite/jmacro/util/Logger.java +++ b/src/main/java/xyz/wbsite/jmacro/util/Logger.java @@ -5,6 +5,7 @@ import cn.hutool.core.date.DateUtil; import cn.hutool.core.lang.caller.CallerUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.log.level.Level; +import xyz.wbsite.jmacro.JMainApplication; import xyz.wbsite.jmacro.ex.MacroErrorException; /** @@ -16,7 +17,6 @@ import xyz.wbsite.jmacro.ex.MacroErrorException; */ public class Logger { - public static void info(String format, Object... arg) { DateTime date = DateUtil.date(); String level = Level.INFO.toString(); @@ -26,19 +26,23 @@ public class Logger { StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); // 通常堆栈追踪数组的第三个元素是logMessage方法的调用者 int lineNumber = stackTrace[2].getLineNumber(); - System.out.println(StrUtil.format("[{}] [{}] {} [{}:{}]", date, level, log, name, lineNumber)); + JMainApplication.mainController.println("[{}] [{}] {} [{}:{}]", date, level, log, name, lineNumber); } public static void error(String format, Object... arg) { + // 获取当前时间 DateTime date = DateUtil.date(); + // 获取日志级别 String level = Level.ERROR.toString(); + // 格式化日志信息 String log = StrUtil.format(format, arg); + // 获取调用者类名 String name = CallerUtil.getCallerCaller().getSimpleName(); // 获取当前线程的堆栈追踪 StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); // 通常堆栈追踪数组的第三个元素是logMessage方法的调用者 int lineNumber = stackTrace[2].getLineNumber(); - System.out.println(StrUtil.format("[{}] [{}] {} [{}:{}]", date, level, log, name, lineNumber)); - throw new MacroErrorException(StrUtil.format(format, arg)); + // 打印日志信息 + JMainApplication.mainController.println("[{}] [{}] {} [{}:{}]", date, level, log, name, lineNumber); } } diff --git a/src/main/resources/main.css b/src/main/resources/main.css new file mode 100644 index 0000000..e31b742 --- /dev/null +++ b/src/main/resources/main.css @@ -0,0 +1,12 @@ +/* styles.css */ +.text-area, +.text-area:focused, +.text-area:unfocused, +.text-area:disabled { + -fx-control-inner-background: transparent; + -fx-background-color: transparent; +} + +.text-area .content { + -fx-background-color: transparent; +} \ No newline at end of file diff --git a/src/main/resources/main.fxml b/src/main/resources/main.fxml index 3258cbd..2851f04 100644 --- a/src/main/resources/main.fxml +++ b/src/main/resources/main.fxml @@ -5,7 +5,7 @@ - + @@ -81,6 +81,13 @@ +