├── .gitattributes ├── .gitignore ├── .idea ├── .gitignore ├── artifacts │ └── jar.xml ├── codeStyles │ └── codeStyleConfig.xml ├── compiler.xml ├── cssdialects.xml ├── encodings.xml ├── gradle.xml ├── jarRepositories.xml ├── libraries-with-intellij-classes.xml ├── misc.xml ├── uiDesigner.xml └── vcs.xml ├── LICENSE ├── README.md ├── base ├── .idea │ ├── .gitignore │ ├── compiler.xml │ ├── gradle.xml │ ├── jarRepositories.xml │ ├── misc.xml │ ├── uiDesigner.xml │ └── vcs.xml ├── build.gradle ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── libs │ ├── json-simple-1.1.1.jar │ ├── jsoup-1.14.2.jar │ └── rhino-1.7.13.jar ├── settings.gradle └── src │ └── main │ ├── java │ └── org │ │ └── beuwi │ │ └── msgbots │ │ ├── base │ │ ├── Dfile.java │ │ ├── FXProperty.java │ │ ├── JArray.java │ │ ├── JObject.java │ │ ├── Logger.java │ │ ├── Manager.java │ │ ├── Project.java │ │ ├── Session.java │ │ ├── annotation │ │ │ └── NotNull.java │ │ ├── file │ │ │ ├── FileListener.java │ │ │ ├── FileObserver.java │ │ │ └── FileWatcher.java │ │ ├── impl │ │ │ ├── Executor.java │ │ │ └── View.java │ │ └── type │ │ │ ├── ConfigType.java │ │ │ ├── LogType.java │ │ │ ├── ThemeType.java │ │ │ └── ToastType.java │ │ ├── compiler │ │ ├── api │ │ │ ├── Api.java │ │ │ ├── AppData.java │ │ │ ├── Bridge.java │ │ │ ├── DataBase.java │ │ │ ├── Debugger.java │ │ │ ├── Device.java │ │ │ ├── FileStream.java │ │ │ ├── GlobalLog.java │ │ │ ├── ImageDB.java │ │ │ ├── Log.java │ │ │ ├── Replier.java │ │ │ └── Utils.java │ │ └── engine │ │ │ ├── PrimitiveWrapFactory.java │ │ │ ├── ResponseParameters.java │ │ │ ├── ScriptContainer.java │ │ │ ├── ScriptEngine.java │ │ │ └── ScriptUtils.java │ │ ├── manager │ │ ├── DebugManager.java │ │ ├── FileManager.java │ │ ├── ProjectManager.java │ │ ├── ScriptManager.java │ │ └── WebManager.java │ │ ├── setting │ │ ├── GlobalSettings.java │ │ ├── ProjectSettings.java │ │ └── SharedSettings.java │ │ └── shared │ │ ├── SharedColors.java │ │ └── SharedValues.java │ └── resources │ └── default │ ├── color_map.json │ ├── global_config.json │ ├── profile_bot.png │ ├── profile_sender.png │ ├── program_data.json │ ├── script_default.js │ └── script_unified.js ├── bots └── WELCOME │ ├── bot.json │ ├── index.js │ └── log.json ├── build.gradle ├── data ├── global_config.json └── global_log.json ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── img.png ├── img_1.png ├── img_2.png ├── libs └── base.jar ├── msgbots.iml ├── readme.txt ├── settings.gradle └── src └── main ├── java ├── module-info.java └── org │ └── beuwi │ └── msgbots │ ├── Launcher.java │ ├── actions │ ├── CopyClipboardAction.java │ ├── CreateProjectAction.java │ ├── DeleteProjectAction.java │ ├── GetWebTextAction.java │ ├── OpenBrowserAction.java │ ├── OpenDesktopAction.java │ ├── RenameProjectAction.java │ ├── ShowWinMsgAction.java │ └── WriteImageFileAction.java │ ├── keyboard │ ├── KeyBinding.java │ └── KeyCategory.java │ ├── openapi │ ├── FormLoader.java │ ├── TrayIcon.java │ └── WinMessage.java │ ├── utils │ └── ResourceUtils.java │ └── view │ ├── app │ ├── MainWindow.java │ ├── actions │ │ ├── AddMainAreaTabAction.java │ │ ├── CheckAppUpdateAction.java │ │ ├── OpenDebugTabAction.java │ │ ├── OpenDialogBoxAction.java │ │ ├── OpenFileChooserAction.java │ │ ├── OpenFolderChooserAction.java │ │ ├── OpenWebViewTabAction.java │ │ ├── RefreshAllBotsAction.java │ │ ├── ReloadAllBotsAction.java │ │ ├── SaveAllEditorsAction.java │ │ ├── SaveOpenedEditorAction.java │ │ ├── ShowToastMessageAction.java │ │ ├── ToggleDebugAreaAction.java │ │ └── TriggerOpenedEditorAction.java │ ├── dialogs │ │ ├── ChooseFileDialog.java │ │ ├── CreateBotDialog.java │ │ ├── DeleteBotDialog.java │ │ ├── ImportScriptDialog.java │ │ ├── LaunchAppDialog.java │ │ ├── RenameBotDialog.java │ │ └── WelcomeToDialog.java │ ├── parts │ │ ├── DebugAreaPart.java │ │ ├── MainAreaPart.java │ │ ├── MenuBarPart.java │ │ ├── SideAreaPart.java │ │ ├── StatusBarPart.java │ │ ├── ToastViewPart.java │ │ └── ToolAreaPart.java │ ├── tabs │ │ ├── BotListTab.java │ │ ├── DebugRoomTab.java │ │ ├── DetailLogTab.java │ │ ├── GlobalConfigTab.java │ │ ├── GlobalLogTab.java │ │ └── ViewKeymapTab.java │ └── views │ │ └── MainView.java │ ├── gui │ ├── base │ │ ├── Control.java │ │ ├── Event.java │ │ └── Layout.java │ ├── control │ │ ├── BotItem.java │ │ ├── BotView.java │ │ ├── Button.java │ │ ├── ChatArea.java │ │ ├── ChatItem.java │ │ ├── ChatView.java │ │ ├── CheckBox.java │ │ ├── ComboBox.java │ │ ├── ConfigItem.java │ │ ├── ConfigView.java │ │ ├── ContextMenu.java │ │ ├── Label.java │ │ ├── ListView.java │ │ ├── LogItem.java │ │ ├── LogView.java │ │ ├── MenuBar.java │ │ ├── MenuButton.java │ │ ├── MenuItem.java │ │ ├── NaviItem.java │ │ ├── NaviView.java │ │ ├── SVGGlyph.java │ │ ├── ScrollView.java │ │ ├── Separator.java │ │ ├── Slider.java │ │ ├── SplitView.java │ │ ├── TabItem.java │ │ ├── TabView.java │ │ ├── TextArea.java │ │ ├── TextField.java │ │ ├── ToastItem.java │ │ ├── ToastView.java │ │ ├── ToggleButton.java │ │ ├── WebPage.java │ │ └── base │ │ │ ├── ButtonBase.java │ │ │ ├── CheckBoxBase.java │ │ │ ├── ComboBoxBase.java │ │ │ ├── ContextMenuBase.java │ │ │ ├── LabelBase.java │ │ │ ├── ListViewBase.java │ │ │ ├── MenuItemBase.java │ │ │ ├── SVGGlyphBase.java │ │ │ ├── ScrollViewBase.java │ │ │ ├── SeparatorBase.java │ │ │ ├── SplitViewBase.java │ │ │ ├── TabItemBase.java │ │ │ ├── TabViewBase.java │ │ │ ├── TextAreaBase.java │ │ │ ├── TextFieldBase.java │ │ │ └── ToggleButtonBase.java │ ├── dialog │ │ ├── ShowPaneDialog.java │ │ ├── ViewIconDialog.java │ │ ├── YesOrNoDialog.java │ │ └── base │ │ │ ├── DialogFrame.java │ │ │ └── DialogWrapper.java │ ├── editor │ │ ├── Editor.java │ │ ├── JFunction.java │ │ ├── Monaco.java │ │ └── Position.java │ ├── layout │ │ ├── AnchorPane.java │ │ ├── BorderPane.java │ │ ├── DebugPane.java │ │ ├── GridPane.java │ │ ├── HBox.java │ │ ├── ShadowPane.java │ │ ├── StackPane.java │ │ ├── VBox.java │ │ ├── WebPane.java │ │ └── base │ │ │ ├── AnchorPaneBase.java │ │ │ ├── BorderPaneBase.java │ │ │ ├── GridPaneBase.java │ │ │ ├── HBoxBase.java │ │ │ ├── StackPaneBase.java │ │ │ └── VBoxBase.java │ ├── skin │ │ ├── ScrollBarSkin.java │ │ └── SplitViewSkin.java │ ├── type │ │ ├── ButtonType.java │ │ ├── DialogType.java │ │ └── WindowType.java │ └── window │ │ ├── WindowBuilder.java │ │ ├── WindowEvent.java │ │ ├── WindowFrame.java │ │ ├── WindowScene.java │ │ └── WindowWrapper.java │ └── util │ ├── AllSVGIcons.java │ ├── GUIManager.java │ ├── StdActions.java │ └── ViewManager.java └── resources ├── font ├── Consola-Regular.ttf ├── D2Coding-Regular.ttf ├── JetBrainsMono-Bold.ttf ├── JetBrainsMono-Medium.ttf ├── JetBrainsMono-Regular.ttf ├── NanumGothic-Regular.ttf ├── Roboto-Regular.ttf ├── consola-bold.ttf ├── d2coding-bold.ttf ├── nanumgothic-bold.ttf ├── roboto-bold.ttf └── roboto-medium.ttf ├── form ├── dialog │ ├── create-bot-dialog.fxml │ ├── delete-bot-dialog.fxml │ ├── display-error-dialog.fxml │ ├── import-script-dialog.fxml │ ├── rename-bot-dialog.fxml │ ├── show-msg-dialog.fxml │ ├── welcome-to-dialog.fxml │ └── yes-or-no-dialog.fxml ├── frame │ ├── bot-item-frame.fxml │ ├── chat-area-frame.fxml │ ├── dialog-box-frame.fxml │ ├── log-item-frame.fxml │ ├── toast-item-frame.fxml │ └── window-box-frame.fxml ├── layout │ ├── debug-pane-layout.fxml │ └── main-view-layout.fxml ├── part │ ├── debug-area-part.fxml │ ├── main-area-part.fxml │ ├── menu-bar-part.fxml │ ├── side-area-part.fxml │ ├── status-bar-part.fxml │ ├── toast-view-part.fxml │ └── tool-area-part.fxml ├── tab │ ├── bot-list-tab.fxml │ ├── debug-room-tab.fxml │ ├── detail-log-tab.fxml │ ├── global-config-tab.fxml │ ├── global-log-tab.fxml │ └── view-kaymap-tab.fxml └── view │ └── bot-option-view.fxml ├── icon └── program.ico ├── image ├── chat.png ├── debug.png ├── error.png ├── error_big.png ├── explorer.png ├── info.png ├── info_big.png ├── log.png ├── profile.png ├── program.png ├── program_start.png ├── program_trans.png ├── reload.png ├── setting.png ├── simulation.png ├── warning.png └── warning_big.png ├── monaco ├── index.css ├── index.d.ts ├── index.html ├── index.js └── test.xml ├── theme ├── base.css ├── dark.css └── light.css └── webpage ├── html ├── about-program-page.html ├── program-start-page.html ├── release-notes-page.html ├── view-license-page.html └── welcome-guide-page.html └── style ├── base.css ├── dark.css └── light.css /.gitattributes: -------------------------------------------------------------------------------- 1 | public/src/main/resources/monaco/* linguist-vendored 2 | * linguist-vendored 3 | *.java linguist-vendored=false 4 | *.html linguist-vendored=false -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | .gradle/ 3 | lib/ -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Datasource local storage ignored files 5 | /dataSources/ 6 | /dataSources.local.xml 7 | # Editor-based HTTP Client requests 8 | /httpRequests/ 9 | -------------------------------------------------------------------------------- /.idea/artifacts/jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | $PROJECT_DIR$/out/artifacts/jar 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/cssdialects.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 16 | 17 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Messenger Bot Simulator : "Msgbots" 2 | 3 | 메신저 봇 시뮬레이터는 아직 베타버전이므로 동작 시 발생하는 버그가 많을 수 있습니다. 4 | 5 | 때문에 안정적인 동작을 보장할 수 없으며 임의로 파일 수정 시 프로그램이 동작하지 않을 수 있습니다. 6 | 7 | ## Messenger Bot Simulator 8 | ![img.png](img.png) 9 | 메신저 봇 시뮬레이터는 사용자가 메신저에서 봇을 돌리기 이전에 해당 코드를 미리 시뮬레이션 할 수 있는 프로그램입니다. 10 | 11 | 코드 편집 및 우측의 디버그 룸을 통한 시뮬레이션 기능을 통해 실제로 구동하는 것과 같은 환경을 제공합니다. 12 | 13 | 모나코 에디터를 내장함과 동시에 자동완성 기능을 포함하고 있어 강력한 생산성을 제공합니다. 14 | 15 | ![img_1.png](img_1.png) 16 | 17 | ### Version 0.7.0 18 | 19 | ![img_2.png](img_2.png) 20 | 21 | ### 업데이트 목록 22 | 업데이트 내용을 보고 싶다면 https://blog.naver.com/ttyy3388 블로그를 이용해주세요. 23 | 24 | ### API 문서 25 | https://blog.naver.com/ttyy3388/221850492456 26 | 27 | ### LICNESE 28 | Licensed under the "GPL-3.0" license. -------------------------------------------------------------------------------- /base/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /base/.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /base/.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 16 | 17 | -------------------------------------------------------------------------------- /base/.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | -------------------------------------------------------------------------------- /base/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /base/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /base/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'org.beuwi.mstbots' 6 | 7 | java { 8 | sourceCompatibility = JavaVersion.VERSION_1_8; 9 | targetCompatibility = JavaVersion.VERSION_1_8; 10 | } 11 | 12 | configurations { 13 | extraLibs 14 | } 15 | dependencies { 16 | implementation fileTree(dir: 'libs', include: ['*.jar']) 17 | // 다른 클래스에서 해당 프로젝트가 참조하는 json.simple도 접근이 가능하게 함 18 | extraLibs fileTree(dir: 'libs', include: ['*.jar']) 19 | } 20 | 21 | compileJava { 22 | options.encoding = "UTF-8" 23 | options.compilerArgs << "-Xlint:none" 24 | } 25 | 26 | jar { 27 | /* manifest { 28 | attributes('Bundle-SymbolicName': 'org.beuwi.msgbots.base') 29 | } */ 30 | from { 31 | configurations.extraLibs.collect { 32 | it.isDirectory() ? it : zipTree(it) 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /base/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /base/libs/json-simple-1.1.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/base/libs/json-simple-1.1.1.jar -------------------------------------------------------------------------------- /base/libs/jsoup-1.14.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/base/libs/jsoup-1.14.2.jar -------------------------------------------------------------------------------- /base/libs/rhino-1.7.13.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/base/libs/rhino-1.7.13.jar -------------------------------------------------------------------------------- /base/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'base' 2 | 3 | -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/base/Dfile.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.base; 2 | 3 | import org.beuwi.msgbots.manager.FileManager; 4 | import org.beuwi.msgbots.shared.SharedValues; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | 10 | // [Data File] : 특수하게 관리해야 하므로 따로 클래스 작성 11 | public class Dfile { 12 | String name; 13 | public Dfile(String name) { 14 | this.name = name; 15 | } 16 | 17 | public boolean create() { 18 | try { 19 | return toFile().createNewFile(); 20 | } 21 | catch (IOException e) { 22 | e.printStackTrace(); 23 | } 24 | return false; 25 | } 26 | 27 | // 유저가 값을 변경하면 파일이 생성되므로, 생성된 적이 없다면 기본 파일만 있음 28 | public boolean isCreated() { 29 | return toFile().exists(); 30 | } 31 | 32 | // 프로그램 밖 (유저 파일) : [Write, Read] 33 | public File toFile() { 34 | File folder = SharedValues.getFile("file.dataFolder"); 35 | return new File( folder + File.separator + name); 36 | } 37 | // 프로그램 안 (기본 파일) : [Read Only] 38 | public InputStream toResource() { 39 | return Dfile.class.getResourceAsStream("/default/" + name); 40 | } 41 | 42 | public String getData() { 43 | File file = toFile(); 44 | String result; 45 | 46 | // 유저가 파일을 변경한 적이 있다면 해당 파일이 생성 돼 있으므로 47 | if (file.exists()) { 48 | result = FileManager.read(file); 49 | } 50 | // 아니라면 기본 값을 위해 리소스 파일을 반환 51 | else { 52 | result = FileManager.read(toResource()); 53 | } 54 | 55 | return result; 56 | } 57 | 58 | // 저장의 경우 무조건 파일 생성 59 | public void setData(String data) { 60 | FileManager.write(toFile(), data); 61 | } 62 | 63 | @Override 64 | public String toString() { 65 | return name; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/base/JArray.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.base; 2 | 3 | import org.beuwi.msgbots.manager.FileManager; 4 | 5 | import org.json.simple.JSONArray; 6 | import org.json.simple.JSONObject; 7 | import org.json.simple.parser.JSONParser; 8 | 9 | import java.io.File; 10 | import java.io.InputStream; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | import java.util.stream.Collectors; 14 | 15 | public class JArray extends ArrayList { 16 | public JArray() { 17 | super(); 18 | } 19 | public JArray(File file) { 20 | this(FileManager.read(file)); 21 | } 22 | public JArray(InputStream stream) { 23 | this(FileManager.read(stream)); 24 | } 25 | public JArray(String data) { 26 | if (data == null || data.isEmpty()) { 27 | // throw new NullPointerException(); 28 | return ; 29 | } 30 | 31 | try { 32 | JSONArray array = new JSONArray(); 33 | List list = (List) new JSONParser().parse(data); 34 | 35 | // JSONObject 요소들을 자체 제작한 JObject 타입으로 변환함 36 | // 해당 방법은 비효율적이라고 생각되니 추후 메모리 문제가 생기면 변경할 예정임 37 | addAll(list.stream().map(JObject::convert).collect(Collectors.toList())); 38 | 39 | // JSONObject를 자체 제작한 JObject로 변환함 40 | // 이로써 더이상 JSONObejct를 사용할 필요가 없어지도록 함 41 | /* if (object instanceof JSONObject) 42 | // Convert to JObject 43 | JSONObject json = (JSONObject) object; 44 | JObject jobject = new JObject(); 45 | jobject.putAll(json); 46 | this.addAll((List) jobject); 47 | } */ 48 | } 49 | catch (Exception e) { 50 | e.printStackTrace(); 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/base/Logger.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.base; 2 | 3 | import org.beuwi.msgbots.base.type.LogType; 4 | 5 | // 컴파일러에서 로그를 남기기 위한 클래스 6 | public class Logger { 7 | private final Session session; 8 | protected Logger(Session session) { 9 | this.session = session; 10 | } 11 | 12 | public void info(String data) { 13 | session.log(LogType.INFO, data); 14 | } 15 | 16 | public void debug(String data) { 17 | session.log(LogType.DEBUG, data); 18 | } 19 | 20 | public void error(String data) { 21 | session.log(LogType.ERROR, data); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/base/Manager.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.base; 2 | 3 | public interface Manager { 4 | } 5 | -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/base/annotation/NotNull.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.base.annotation; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.Target; 5 | 6 | import static java.lang.annotation.ElementType.FIELD; 7 | import static java.lang.annotation.ElementType.METHOD; 8 | import static java.lang.annotation.ElementType.PARAMETER; 9 | import static java.lang.annotation.ElementType.LOCAL_VARIABLE; 10 | 11 | import static java.lang.annotation.RetentionPolicy.CLASS; 12 | 13 | @Retention(CLASS) 14 | @Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE}) 15 | public @interface NotNull {String value() default "";} -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/base/file/FileListener.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.base.file; 2 | 3 | import java.util.EventListener; 4 | 5 | public interface FileListener extends EventListener { 6 | public void changed(); 7 | // public void created(); 8 | // public void deleted(); 9 | // public void modified(); 10 | } -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/base/file/FileObserver.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.base.file; 2 | 3 | import javafx.application.Platform; 4 | 5 | import java.io.File; 6 | import java.util.HashSet; 7 | import java.util.Set; 8 | 9 | public class FileObserver extends FileWatcher { 10 | private final Set listeners = new HashSet<>(); 11 | 12 | // private final File file; 13 | 14 | public FileObserver(File file) { 15 | super(file); 16 | } 17 | 18 | /* public File getFile() { 19 | return file; 20 | } */ 21 | 22 | public void addListener(FileListener listener) { 23 | synchronized (listeners) { 24 | listeners.add(listener); 25 | } 26 | } 27 | 28 | public void removeListener(FileListener listener) { 29 | synchronized (listeners) { 30 | listeners.remove(listener); 31 | } 32 | } 33 | 34 | /* protected void fireEvent() { 35 | 36 | } */ 37 | 38 | @Override 39 | public void changed() { 40 | listeners.forEach(listener -> { 41 | Platform.runLater(listener::changed); 42 | }); 43 | } 44 | /* @Override 45 | public void deleted() { 46 | listeners.forEach(listener -> { 47 | Platform.runLater(listener::deleted); 48 | }); 49 | } 50 | @Override 51 | public void created() { 52 | listeners.forEach(listener -> { 53 | Platform.runLater(listener::created); 54 | }); 55 | } 56 | @Override 57 | public void modified() { 58 | listeners.forEach(listener -> { 59 | Platform.runLater(listener::modified); 60 | }); 61 | } */ 62 | } 63 | -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/base/impl/Executor.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.base.impl; 2 | 3 | public interface Executor { 4 | /* 5 | * 반환 값이 있는 경우에는 값을 반환하고, 6 | * 반환 값이 없다면(void) 성공 여부를 반환함 7 | */ 8 | /* public Object execute(Object object) { 9 | return null; 10 | }; */ 11 | } 12 | -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/base/impl/View.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.base.impl; 2 | 3 | public interface View { 4 | /* default void init() { 5 | return ; 6 | } // throws Exception */ 7 | 8 | // Node getRoot(); // Return Main Panel 9 | 10 | // Return Main Control 11 | /* default Node getControl() { 12 | return null; 13 | } */ 14 | 15 | // ObservableMap getNamespace(); // findById 16 | Object findById(String id); 17 | } -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/base/type/ConfigType.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.base.type; 2 | 3 | public enum ConfigType { 4 | GLOBAL("global"), PROJECT("project"), CONTROL("control"); 5 | 6 | private final String name; 7 | ConfigType(String name) { 8 | this.name = name; 9 | } 10 | 11 | @Override 12 | public String toString() { 13 | return name; 14 | } 15 | 16 | public boolean match(String data) { 17 | return name.equals(data); 18 | } 19 | 20 | public static > ConfigType convert(String value) { 21 | return ConfigType.valueOf(value.toUpperCase()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/base/type/LogType.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.base.type; 2 | 3 | public enum LogType { 4 | INFO("info"), 5 | ERROR("error"), 6 | DEBUG("debug"); 7 | 8 | private final String name; 9 | LogType(String name) { 10 | this.name = name; 11 | } 12 | @Override 13 | public String toString() { 14 | return name; 15 | } 16 | 17 | public boolean match(String data) { 18 | return name.equals(data); 19 | } 20 | 21 | public static > LogType convert(String value) { 22 | return LogType.valueOf(value.toUpperCase()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/base/type/ThemeType.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.base.type; 2 | 3 | import java.io.File; 4 | 5 | public enum ThemeType { 6 | DARK("dark"), 7 | LIGHT("light"), 8 | BLACK("black"), 9 | WHITE("white"), 10 | CUSTOM("user"); 11 | 12 | private final String name; 13 | ThemeType(String name) { 14 | this.name = name; 15 | } 16 | @Override 17 | public String toString() { 18 | return name; 19 | } 20 | 21 | public File toFile() { 22 | return null; /* switch (this) { 23 | case DARK -> SharedValues.DARK_THEME_FILE; 24 | case LIGHT -> SharedValues.LIGHT_THEME_FILE; 25 | case BLACK -> null; // SharedValues.BLACK_THEME_FILE; 26 | case WHITE -> null; // SharedValues.WHITE_THEME_FILe; 27 | case USER -> SharedValues.USER_THEME_FILE; 28 | }; */ 29 | } 30 | 31 | public static > ThemeType parse(String value) { 32 | return valueOf(value.toUpperCase()); 33 | /* // 대문자 변환 시 일치하는게 없다면 34 | ThemeType result = valueOf(value.toUpperCase()); 35 | 36 | if (result != null) { 37 | return result; 38 | } 39 | 40 | // 없다면 문자열로 변환한 거에서 비교 41 | for (ThemeType type : result.values()) { 42 | if (type.toString().equals(value)) { 43 | result = type; 44 | } 45 | } 46 | 47 | return result; */ 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/base/type/ToastType.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.base.type; 2 | 3 | public enum ToastType { 4 | INFO("info"), 5 | ERROR("error"), 6 | WARNING("warning"), 7 | TIP("tip"); 8 | 9 | private final String name; 10 | ToastType(String name) { 11 | this.name = name; 12 | } 13 | @Override 14 | public String toString() { 15 | return name; 16 | } 17 | 18 | public static > ToastType convert(String value) { 19 | return ToastType.valueOf(value.toUpperCase()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/compiler/api/AppData.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.compiler.api; 2 | 3 | import org.mozilla.javascript.ScriptableObject; 4 | import org.mozilla.javascript.annotations.JSStaticFunction; 5 | 6 | public class AppData extends ScriptableObject { 7 | @Override 8 | public String getClassName() { 9 | return "AppData"; 10 | } 11 | 12 | @JSStaticFunction 13 | public static void putBoolean(String key, Boolean bool) { 14 | return ; 15 | } 16 | 17 | @JSStaticFunction 18 | public static void putInt(String ket, int value) { 19 | return ; 20 | } 21 | 22 | @JSStaticFunction 23 | public static void putString(String key, String value) { 24 | return ; 25 | } 26 | 27 | @JSStaticFunction 28 | public static Boolean getBoolean(String ket, Boolean value) { 29 | return null; 30 | } 31 | 32 | @JSStaticFunction 33 | public static int getInt(String key, int value) { 34 | return 0; 35 | } 36 | 37 | @JSStaticFunction 38 | public static String getString(String key, String value) { 39 | return null; 40 | } 41 | 42 | @JSStaticFunction 43 | public static void remove(String key) { 44 | return ; 45 | } 46 | 47 | @JSStaticFunction 48 | public static void clear() { 49 | return ; 50 | } 51 | } -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/compiler/api/Bridge.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.compiler.api; 2 | 3 | import org.beuwi.msgbots.compiler.engine.ScriptEngine; 4 | 5 | import org.mozilla.javascript.Context; 6 | import org.mozilla.javascript.ScriptableObject; 7 | import org.mozilla.javascript.Undefined; 8 | import org.mozilla.javascript.annotations.JSStaticFunction; 9 | 10 | public class Bridge extends ScriptableObject { 11 | @Override 12 | public String getClassName() { 13 | return "Bridge"; 14 | } 15 | 16 | @JSStaticFunction 17 | public static ScriptableObject getScopeOf(String inputName) { 18 | if (Undefined.isUndefined(inputName)) { 19 | return null; 20 | } 21 | else { 22 | String scriptName = Utils.toScriptName(inputName); 23 | if (!isAllowed(scriptName)) { 24 | return null; 25 | } 26 | if (ScriptEngine.container.get(scriptName) != null) { 27 | try { 28 | return ScriptEngine.container.get(scriptName).getScope(); 29 | } 30 | catch (Throwable e) { 31 | Context.reportError(e.toString()); 32 | return null; 33 | } 34 | } 35 | } 36 | return null; 37 | } 38 | 39 | @JSStaticFunction 40 | public static Boolean isAllowed(String inputName) { 41 | return false; 42 | } 43 | } -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/compiler/api/DataBase.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.compiler.api; 2 | 3 | import org.mozilla.javascript.ScriptableObject; 4 | import org.mozilla.javascript.annotations.JSFunction; 5 | 6 | @SuppressWarnings("serial") 7 | public class DataBase extends ScriptableObject { 8 | @Override 9 | public String getClassName() { 10 | return "DataBase"; 11 | } 12 | 13 | final String name; 14 | 15 | public DataBase(ScriptableObject object, String name) { 16 | super(object, object.getPrototype()); 17 | 18 | this.name = name; 19 | } 20 | 21 | @JSFunction 22 | public String appendDataBase(String fileName, String date) { 23 | return null; 24 | } 25 | 26 | @JSFunction 27 | public String setDataBase(String fileName, String data) { 28 | return null; 29 | } 30 | 31 | @JSFunction 32 | public String getDataBase(String fileName) { 33 | return null; 34 | } 35 | 36 | @JSFunction 37 | public Boolean removeDataBase(String fileName) { 38 | return null; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/compiler/api/Debugger.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.compiler.api; 2 | 3 | import org.beuwi.msgbots.base.Manager; 4 | import org.beuwi.msgbots.base.Project; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | /* class Debugger implements Manager { 10 | protected static void replyChat(Project project, String message, boolean isBot) { 11 | OnChatListener handler = CHAT_MAP.get(project); 12 | if (handler != null) { 13 | handler.onEvent(message, isBot); 14 | } 15 | } 16 | 17 | protected static void popupToast(Project project, int type, String title, String message) { 18 | OnToastListener handler = TOAST_MAP.get(project); 19 | if (handler != null) { 20 | handler.onEvent(type, title, message); 21 | } 22 | } 23 | 24 | protected interface OnChatListener { 25 | void onEvent(String message, boolean isBot); 26 | } 27 | protected interface OnToastListener { 28 | void onEvent(int type, String title, String message); 29 | } 30 | protected interface onErrorListener { 31 | void onEvent(); 32 | } 33 | protected interface onCompileListener { 34 | void onEvent(); 35 | } 36 | 37 | protected static final Map CHAT_MAP = new HashMap<>(); 38 | protected static void setOnChatListener(Project project, OnChatListener listener) { 39 | CHAT_MAP.put(project, listener); 40 | } 41 | 42 | protected static final Map TOAST_MAP = new HashMap<>(); 43 | protected static void setOnToastListener(Project project, OnToastListener listener) { 44 | TOAST_MAP.put(project, listener); 45 | } 46 | 47 | protected static final Map ERROR_MAP = new HashMap<>(); 48 | protected void setOnErrorListener(Project project, onErrorListener listener) { 49 | ERROR_MAP.put(project, listener); 50 | } 51 | 52 | protected static final Map COMPILE_MAP = new HashMap<>(); 53 | protected void setOnCompileListener(Project project, onCompileListener listener) { 54 | COMPILE_MAP.put(project, listener); 55 | } 56 | } */ -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/compiler/api/Device.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.compiler.api; 2 | 3 | import org.mozilla.javascript.ScriptableObject; 4 | import org.mozilla.javascript.annotations.JSStaticFunction; 5 | 6 | @SuppressWarnings("serial") 7 | public class Device extends ScriptableObject { 8 | @Override 9 | public String getClassName() { 10 | return "Device"; 11 | } 12 | 13 | public Device(ScriptableObject object) { 14 | super(object, object.getPrototype()); 15 | } 16 | 17 | @JSStaticFunction 18 | public static Object getBuild() { 19 | return null; 20 | } 21 | 22 | @JSStaticFunction 23 | public static int getAndroidVersionCode() { 24 | return 28; 25 | } 26 | 27 | @JSStaticFunction 28 | public static String getAndroidVersionName() { 29 | return "9"; 30 | } 31 | 32 | @JSStaticFunction 33 | public static String getPhoneBrand() { 34 | return "samsung"; 35 | } 36 | 37 | @JSStaticFunction 38 | public static String getPhoneModel() { 39 | return "greatlteks"; 40 | } 41 | 42 | @JSStaticFunction 43 | public static Boolean isCharging() { 44 | return true; 45 | } 46 | 47 | @JSStaticFunction 48 | public static String getPlugType() { 49 | return "usb"; 50 | } 51 | 52 | @JSStaticFunction 53 | public static int getBatteryLevel() { 54 | return 100; 55 | } 56 | 57 | @JSStaticFunction 58 | public static int getBatteryHealth() { 59 | // BATTERY_HEALTH_GOOD 60 | return 3; 61 | } 62 | 63 | @JSStaticFunction 64 | public static int getBatteryTemperature() { 65 | return 1000; 66 | } 67 | 68 | @JSStaticFunction 69 | public static int getBatteryVoltage() { 70 | return 10000; 71 | } 72 | 73 | @JSStaticFunction 74 | public static int getBatteryStatus() { 75 | return 5; 76 | } 77 | 78 | @JSStaticFunction 79 | public static Object getBatteryIntent() { 80 | return null; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/compiler/api/GlobalLog.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.compiler.api; 2 | 3 | import org.beuwi.msgbots.base.Dfile; 4 | import org.beuwi.msgbots.base.Logger; 5 | import org.beuwi.msgbots.base.Session; 6 | import org.beuwi.msgbots.shared.SharedValues; 7 | 8 | import org.mozilla.javascript.ScriptableObject; 9 | import org.mozilla.javascript.annotations.JSFunction; 10 | 11 | import java.io.File; 12 | 13 | public class GlobalLog extends ScriptableObject { 14 | @Override 15 | public String getClassName() { 16 | return "GlobalLog"; 17 | } 18 | 19 | private final Session session = Session.GLOBAL; 20 | private final Logger logger = session.getLogger(); 21 | 22 | public GlobalLog(ScriptableObject object) { 23 | super(object, object.getPrototype()); 24 | } 25 | 26 | @JSFunction 27 | public void d(String data, Boolean showToast) { 28 | debug(data, showToast); 29 | } 30 | 31 | @JSFunction 32 | public void e(String data, Boolean showToast) { 33 | error(data, showToast); 34 | } 35 | 36 | @JSFunction 37 | public void i(String data, Boolean showToast) { 38 | info(data, showToast); 39 | } 40 | 41 | @JSFunction 42 | public void debug(String data, Boolean showToast) { 43 | logger.debug(data); 44 | } 45 | 46 | @JSFunction 47 | public void error(String data, Boolean showToast) { 48 | logger.error(data); 49 | } 50 | 51 | @JSFunction 52 | public void info(String data, Boolean showToast) { 53 | logger.info(data); 54 | } 55 | 56 | @JSFunction 57 | public void clear() { 58 | Dfile dfile = SharedValues.getDfile("dfile.globalLog"); 59 | // 파일이 생성 돼 있다면 60 | if (dfile.isCreated()) { 61 | dfile.setData("[]"); 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/compiler/api/ImageDB.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.compiler.api; 2 | 3 | import org.beuwi.msgbots.shared.SharedValues; 4 | 5 | import java.io.File; 6 | import java.io.FileInputStream; 7 | import java.util.Base64; 8 | 9 | public class ImageDB { 10 | public String getProfileImage() { 11 | return getProfileBase64(); 12 | } 13 | 14 | public String getProfileBase64() { 15 | try { 16 | File file = SharedValues.getFile("file.profileBot"); 17 | FileInputStream inputStream = new FileInputStream(file); 18 | byte[] bytes = new byte[(int) file.length()]; 19 | inputStream.read(bytes); 20 | return Base64.getEncoder().encodeToString(bytes); 21 | } 22 | catch (Exception e) { 23 | e.printStackTrace(); 24 | } 25 | 26 | return null; 27 | } 28 | 29 | public int getProfileHash() { 30 | return getProfileBase64().hashCode(); 31 | } 32 | 33 | public String getProfileMD5() { 34 | return null; 35 | } 36 | 37 | public String getProfileSHA() { 38 | return null; 39 | } 40 | 41 | public Object getProfileBitmap() { 42 | return null; 43 | } 44 | 45 | public String getImage() { 46 | return null; 47 | } 48 | 49 | public String toSource() { 50 | return null; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/compiler/api/Log.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.compiler.api; 2 | 3 | import org.beuwi.msgbots.base.Logger; 4 | import org.beuwi.msgbots.base.Project; 5 | import org.beuwi.msgbots.base.Session; 6 | import org.beuwi.msgbots.base.type.LogType; 7 | 8 | import org.beuwi.msgbots.manager.FileManager; 9 | import org.mozilla.javascript.ScriptableObject; 10 | import org.mozilla.javascript.annotations.JSFunction; 11 | 12 | public class Log extends ScriptableObject { 13 | @Override 14 | public String getClassName() { 15 | return "Log"; 16 | } 17 | 18 | @Override 19 | public String toString() { 20 | return getClassName(); 21 | } 22 | 23 | private final Project project; 24 | private final Session session; 25 | private final Logger logger; 26 | 27 | public Log(ScriptableObject object, Project project) { 28 | super(object, object.getPrototype()); 29 | this.project = project; 30 | this.session = project.getSession(); 31 | this.logger = session.getLogger(); 32 | } 33 | 34 | @JSFunction 35 | public void d(String data, Boolean showToast) { 36 | debug(data, showToast); 37 | } 38 | 39 | @JSFunction 40 | public void e(String data, Boolean showToast) { 41 | error(data, showToast); 42 | } 43 | 44 | @JSFunction 45 | public void i(String data, Boolean showToast) { 46 | info(data, showToast); 47 | } 48 | 49 | @JSFunction 50 | public void debug(String data, Boolean showToast) { 51 | logger.debug(data); 52 | } 53 | 54 | @JSFunction 55 | public void error(String data, Boolean showToast) { 56 | logger.error(data); 57 | } 58 | 59 | @JSFunction 60 | public void info(String data, Boolean showToast) { 61 | logger.info(data); 62 | } 63 | 64 | @JSFunction 65 | public void clear() { 66 | FileManager.write(project.getFile("log.json"), "[]"); 67 | } 68 | } -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/compiler/api/Replier.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.compiler.api; 2 | 3 | import org.beuwi.msgbots.base.Project; 4 | 5 | import org.beuwi.msgbots.base.Session; 6 | import org.beuwi.msgbots.manager.ProjectManager; 7 | import org.mozilla.javascript.annotations.JSFunction; 8 | import org.mozilla.javascript.annotations.JSStaticFunction; 9 | 10 | public class Replier { 11 | private final Session session; 12 | public Replier(Session session) { 13 | this.session = session; 14 | } 15 | 16 | @JSFunction 17 | public Boolean reply(String message) { 18 | session.chat(message, true); 19 | return true; 20 | } 21 | 22 | @JSFunction 23 | public static Boolean reply(String room, String message, Boolean hideToast) { 24 | /* 25 | // 존재하지 않는 방을 입력한 경우 전역 디버그 룸으로 전송 26 | Session session = (project != null) ? project.getSession() : Session.GLOBAL; */ 27 | // room을 프로젝트 이름으로 간주 28 | Project project = ProjectManager.findByName(room); 29 | if (project == null) { 30 | return false; 31 | } 32 | Session session = project.getSession(); 33 | session.chat(message, true); 34 | return true; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/compiler/engine/PrimitiveWrapFactory.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.compiler.engine; 2 | 3 | import org.mozilla.javascript.Context; 4 | import org.mozilla.javascript.Scriptable; 5 | import org.mozilla.javascript.WrapFactory; 6 | 7 | public class PrimitiveWrapFactory extends WrapFactory { 8 | @Override 9 | public Object wrap(Context context, Scriptable scope, Object object, Class staticType) { 10 | if (object instanceof String || object instanceof Number || object instanceof Boolean) { 11 | return object; 12 | } 13 | else if (object instanceof Character) { 14 | return new String(new char[] { ((Character) object).charValue() }); 15 | } 16 | 17 | return super.wrap(context, scope, object, staticType); 18 | } 19 | } -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/compiler/engine/ResponseParameters.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.compiler.engine; 2 | 3 | import org.beuwi.msgbots.compiler.api.ImageDB; 4 | import org.beuwi.msgbots.compiler.api.Replier; 5 | 6 | public class ResponseParameters { 7 | public String room; 8 | public String msg; 9 | public String sender; 10 | public boolean isGroupChat; 11 | public Replier replier; 12 | public ImageDB ImageDB; 13 | public String packageName; 14 | 15 | public ResponseParameters(String room, String msg, String sender, boolean isGroupChat, Replier replier, ImageDB imageDB, String packName) { 16 | this.room = room; 17 | this.msg = msg; 18 | this.sender = sender; 19 | this.isGroupChat = isGroupChat; 20 | this.replier = replier; 21 | this.ImageDB = imageDB; 22 | this.packageName = packName; 23 | } 24 | 25 | /* public String toSource() { 26 | return null; 27 | } */ 28 | } -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/compiler/engine/ScriptUtils.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.compiler.engine; 2 | 3 | import org.mozilla.javascript.ScriptableObject; 4 | import org.mozilla.javascript.annotations.JSFunction; 5 | 6 | import java.lang.reflect.Method; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | public class ScriptUtils { 11 | public static ScriptableObject convert(ScriptableObject object) { 12 | Class clazz = object.getClass(); 13 | String[] list = getJSFunctions(clazz).toArray(new String[0]); 14 | object.defineFunctionProperties(list, clazz, ScriptableObject.EMPTY); 15 | return object; 16 | } 17 | 18 | public static List getJSFunctions(Class clazz) { 19 | List list = new ArrayList<>(); 20 | for (Method method : clazz.getMethods()) { 21 | if (method.getAnnotation(JSFunction.class) != null) { 22 | list.add(method.getName()); 23 | } 24 | } 25 | return list; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/manager/DebugManager.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.manager; 2 | 3 | import org.beuwi.msgbots.base.Manager; 4 | import org.beuwi.msgbots.base.Project; 5 | import org.beuwi.msgbots.compiler.engine.ScriptEngine; 6 | 7 | // 추후 유저가 직접 엔진(ScriptEngine)을 제작하여 넣는 방식도 고려하면 좋을듯 8 | /* public class DebugManager implements Manager { 9 | private static ScriptEngine engine = null; 10 | public static void run(String message) {run(message); 11 | 12 | } 13 | public static void run(Project project, String message) { 14 | getManager().run(project, message); 15 | } 16 | 17 | public static void preInit() { 18 | getManager().preInit(); 19 | } 20 | 21 | public static void initAll(boolean isManual) { 22 | getManager().initAll(isManual); 23 | } 24 | 25 | public static boolean initScript(Project project, boolean isManual, boolean ignoreError) { 26 | return getManager().initScript(project, isManual, ignoreError); 27 | } 28 | 29 | // 엔진을 넣어야 작동하는 방식(해당 앱에서는 컴파일러를 직접 제작하지 않는다.) 30 | // 따라서 유저가 엔진 JAR을 삽입해야 작동함 31 | 32 | public static void setEngine(ScriptManager value) { 33 | manager = value; 34 | } 35 | 36 | private final static ScriptManager getManager() { 37 | if (manager == null) { 38 | throw new RuntimeException("not initialized"); 39 | } 40 | return manager; 41 | } 42 | } */ -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/manager/ProjectManager.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.manager; 2 | 3 | import javafx.collections.FXCollections; 4 | import javafx.collections.ObservableList; 5 | import org.beuwi.msgbots.base.Manager; 6 | import org.beuwi.msgbots.base.Project; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | // 모든 봇은 봇 매니저에 등록 돼 있어야 관리됨 : 즉 총괄 사무실 개념 12 | // 봇 추가는 봇 목록이 초기화 될 때만 추가됨 : [RefreshBotListAction] 참고 13 | // 프로젝트는 이름 또한 유일 키로 간주하므로 이름으로도 관리함 14 | public class ProjectManager implements Manager { 15 | private static final ObservableList list = FXCollections.observableArrayList(); 16 | 17 | public static void register(Project project) { 18 | List names = getNames(); 19 | // 이름 또한 유일 키 이므로, 이름으로 검사함 20 | if (names.contains(project.getName())) { 21 | throw new RuntimeException("project already exists in a list"); 22 | } 23 | else { 24 | list.add(project); 25 | } 26 | } 27 | 28 | public static boolean exists(String name) { 29 | return findByName(name) != null; 30 | } 31 | 32 | public static Project findByName(String name) { 33 | for (int index = 0 ; index < list.size() ; index ++) { 34 | Project project = list.get(index); 35 | if (name.equals(project.getName())) { 36 | return project; 37 | } 38 | } 39 | return null; 40 | } 41 | 42 | public static ObservableList getList() { 43 | return list; 44 | } 45 | 46 | public static List getNames() { 47 | List names = new ArrayList(); 48 | list.forEach(bot -> { 49 | names.add(bot.getName()); 50 | }); 51 | return names; 52 | } 53 | 54 | /* public static void setPower(String name, boolean power) { 55 | BotListTab.getInstance().getBotView().findById(name).setPower(power); 56 | } 57 | public static void setCompiled(String name, boolean compiled) { 58 | BotListTab.getInstance().getBotView().findById(name).setCompiled(compiled); 59 | } 60 | public static boolean getPower(String name) { 61 | return BotListTab.getInstance().getBotView().findById(name).getPower(); 62 | } 63 | public static boolean isCompiled(String name) { 64 | return BotListTab.getInstance().getBotView().findById(name).isCompiled(); 65 | } */ 66 | } 67 | -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/manager/ScriptManager.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.manager; 2 | 3 | import org.beuwi.msgbots.base.Project; 4 | import org.beuwi.msgbots.base.Manager; 5 | import org.beuwi.msgbots.compiler.api.ImageDB; 6 | import org.beuwi.msgbots.compiler.engine.ScriptEngine; 7 | import org.beuwi.msgbots.manager.ProjectManager; 8 | import org.beuwi.msgbots.setting.GlobalSettings; 9 | 10 | public class ScriptManager extends ScriptEngine implements Manager { 11 | public static void run(String message) { 12 | ScriptEngine.run( 13 | ProjectManager.getList(), 14 | message, 15 | GlobalSettings.getString("debug.roomName"), 16 | GlobalSettings.getString("debug.senderName"), 17 | GlobalSettings.getBoolean("debug.isGroupChat"), 18 | new ImageDB(), 19 | GlobalSettings.getString("debug.packageName") 20 | ); 21 | } 22 | 23 | public static void run(Project project, String message) { 24 | ScriptEngine.run( 25 | project, 26 | message, 27 | GlobalSettings.getString("debug.roomName"), 28 | GlobalSettings.getString("debug.senderName"), 29 | GlobalSettings.getBoolean("debug.isGroupChat"), 30 | new ImageDB(), 31 | GlobalSettings.getString("debug.packageName") 32 | ); 33 | } 34 | 35 | public static void preInit() { 36 | /* if (!GlobalSettings.getBoolean("program.startAutoCompile")) { 37 | return ; 38 | } */ 39 | 40 | for (Project project : ProjectManager.getList()) { 41 | if (!project.getPower()) { 42 | continue ; 43 | } 44 | ScriptEngine.initialize(project, true, false); 45 | } 46 | } 47 | 48 | public static void initAll(boolean isManual) { 49 | for (Project project : ProjectManager.getList()) { 50 | ScriptEngine.initialize(project, isManual, true); 51 | } 52 | } 53 | 54 | public static boolean initScript(Project project, boolean isManual, boolean ignoreError) { 55 | return ScriptEngine.initialize(project, isManual, ignoreError); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/manager/WebManager.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.manager; 2 | 3 | import org.beuwi.msgbots.base.Manager; 4 | 5 | import java.io.BufferedReader; 6 | import java.io.InputStreamReader; 7 | import java.net.URL; 8 | import java.net.URLConnection; 9 | 10 | public class WebManager implements Manager { 11 | public static String getText(String url) { 12 | try { 13 | URLConnection connection = new URL(url).openConnection(); 14 | 15 | connection.setRequestProperty("User-Agent", "Mozilla/5.0"); 16 | connection.setConnectTimeout(5000); 17 | connection.setUseCaches(false); 18 | 19 | BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); 20 | String text = reader.readLine(); 21 | String line = ""; 22 | 23 | while ((line = reader.readLine()) != null) { 24 | text += "\n" + line; 25 | } 26 | 27 | reader.close(); 28 | // connection.time; 29 | 30 | return text; 31 | } 32 | catch (Exception e) { 33 | e.printStackTrace(); 34 | } 35 | 36 | return null; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/setting/ProjectSettings.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.setting; 2 | 3 | import org.beuwi.msgbots.base.JObject; 4 | import org.beuwi.msgbots.manager.FileManager; 5 | import org.beuwi.msgbots.manager.ProjectManager; 6 | import org.beuwi.msgbots.base.Project; 7 | 8 | public class ProjectSettings { 9 | public static ProjectSetting get(String name) { 10 | Project project = ProjectManager.findByName(name); 11 | if (project == null) { 12 | throw new NullPointerException(); 13 | } 14 | return new ProjectSetting(project); 15 | } 16 | public static ProjectSetting get(Project project) { 17 | return new ProjectSetting(project); 18 | } 19 | 20 | public static class ProjectSetting { 21 | 22 | private final Project project; 23 | private final JObject json; 24 | 25 | private ProjectSetting(Project project) { 26 | this.project = project; 27 | this.json = project.getSetting(); 28 | } 29 | 30 | // 현재 없는 키를 입력할 경우는 생각하지 않음 31 | public T getData(String address) { 32 | return (T) json.get(address); 33 | } 34 | 35 | public int getInt(String address) { 36 | return Integer.valueOf("" + getData(address)); 37 | } 38 | 39 | public String getString(String address) { 40 | return String.valueOf("" + getData(address)); 41 | } 42 | 43 | public boolean getBoolean(String address) { 44 | return Boolean.valueOf("" + getData(address)); 45 | } 46 | 47 | public void setData(String address, T value) { 48 | // 기본 타입이 아닐 경우 49 | if (!(value instanceof String || 50 | value instanceof Double || 51 | value instanceof Boolean || 52 | value instanceof Integer || 53 | value instanceof Long)) { 54 | json.put(address, value.toString()); 55 | } 56 | else { 57 | json.put(address, value); 58 | } 59 | 60 | FileManager.write(project.getFile("bot.json"), json.toString()); 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/setting/SharedSettings.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.setting; 2 | 3 | import org.beuwi.msgbots.base.type.ConfigType; 4 | 5 | public class SharedSettings { 6 | 7 | // 아래 주석의 주소(Address)들은 이전에 쓰던 방식임 8 | // "type.head.value" > "global.program.startAutoCompile" 9 | // "type:name:option" > "project.name.ignore_api_off" 10 | 11 | public static T getData(ConfigType type, String address) { 12 | String[] data = address.split("\\."); 13 | 14 | // String type = data[0]; 15 | String name = data[0]; 16 | String option = data[1]; 17 | 18 | if (ConfigType.GLOBAL.equals(type)) { 19 | return GlobalSettings.getData(address); 20 | } 21 | if (ConfigType.PROJECT.equals(type)) { 22 | return ProjectSettings.get(name).getData(option); 23 | } 24 | 25 | throw new NullPointerException("wrong access"); 26 | } 27 | 28 | public static void setData(ConfigType type, String address, T value) { 29 | String[] data = address.split("\\."); 30 | 31 | // String type = data[0]; 32 | String name = data[0]; 33 | String option = data[1]; 34 | 35 | switch (type) { 36 | case GLOBAL: GlobalSettings.setData(address, value); break; 37 | case PROJECT: ProjectSettings.get(name).setData(option, value); break; 38 | case CONTROL: break; 39 | } 40 | } 41 | 42 | public static int getInt(ConfigType type, String address) { 43 | return Integer.valueOf("" + getData(type, address)); 44 | } 45 | 46 | public static String getString(ConfigType type, String address) { 47 | return String.valueOf("" + getData(type, address)); 48 | } 49 | 50 | public static boolean getBoolean(ConfigType type, String address) { 51 | return Boolean.valueOf("" + getData(type, address)); 52 | } 53 | } -------------------------------------------------------------------------------- /base/src/main/java/org/beuwi/msgbots/shared/SharedColors.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.shared; 2 | 3 | import javafx.scene.paint.Color; 4 | import org.beuwi.msgbots.base.Dfile; 5 | import org.beuwi.msgbots.base.JObject; 6 | import org.beuwi.msgbots.setting.GlobalSettings; 7 | 8 | public class SharedColors { 9 | private static final Dfile dfile = SharedValues.getDfile("dfile.colorMap"); 10 | private static final String theme = GlobalSettings.getString("program.colorTheme"); 11 | private static final JObject json = new JObject(dfile.toResource()); 12 | 13 | public static Color getColor(String key) { 14 | return Color.valueOf(String.valueOf(json.getMap(theme).get(key))); 15 | } 16 | 17 | /* public static Color getColor(String theme, String key) { 18 | } */ 19 | } 20 | -------------------------------------------------------------------------------- /base/src/main/resources/default/color_map.json: -------------------------------------------------------------------------------- 1 | { 2 | "base" : { 3 | }, 4 | "light" : { 5 | "icon-default": "#cccccc", 6 | "icon-hover": "#000000", 7 | "icon-focused": "#000000" 8 | }, 9 | "dark" : { 10 | "icon-default": "#8c8c8c", 11 | "icon-hover": "#ffffff", 12 | "icon-focused": "#ffffff" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /base/src/main/resources/default/global_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "mdb":{ 3 | "filePath": null, 4 | "autoConnect": false, 5 | "socketRemotePort":"9500", 6 | "socketLocalPort":"9500" 7 | }, 8 | "debug":{ 9 | "botName":"DEBUG BOT", 10 | "senderName":"DEBUG SENDER", 11 | "roomName":"DEBUG ROOM", 12 | "packageName":"com.kakao.talk", 13 | "showBotName":true, 14 | "showBotProfile":true, 15 | "showSenderName":false, 16 | "showSenderProfile":false, 17 | "showCompileError":true, 18 | "showRuntimeError":true, 19 | "showRunningTime":true, 20 | "isGroupChat":true, 21 | "htmlLoadTimeout":"10000" 22 | }, 23 | "program":{ 24 | "showStartDialog": true, 25 | "saveFolderPath": null, 26 | "version":"0.7.0", 27 | "versionCode":7, 28 | "compileAutoSave":true, 29 | "textRenderingType":"LCD", 30 | "startAutoCompile":true, 31 | "botDirPath":null, 32 | "colorTheme":"dark" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /base/src/main/resources/default/profile_bot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/base/src/main/resources/default/profile_bot.png -------------------------------------------------------------------------------- /base/src/main/resources/default/profile_sender.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/base/src/main/resources/default/profile_sender.png -------------------------------------------------------------------------------- /base/src/main/resources/default/program_data.json: -------------------------------------------------------------------------------- 1 | { 2 | "opened" : { 3 | "tab" : [] 4 | }, 5 | 6 | "selected" : { 7 | "bot" : "", 8 | "tab" : [] 9 | } 10 | } -------------------------------------------------------------------------------- /base/src/main/resources/default/script_default.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * (String) room 4 | * (String) sender 5 | * (Boolean) isGroupChat 6 | * (void) replier.reply(message) 7 | * (Boolean) replier.reply(room, message, hideErrorToast = true) // true 고정값 반환 8 | * (String) imageDB.getProfileBase64() 9 | * (String) packageName 10 | */ 11 | 12 | function response(room, msg, sender, isGroupChat, replier, imageDB, packageName) { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /base/src/main/resources/default/script_unified.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * (String) room 4 | * (String) sender 5 | * (Boolean) isGroupChat 6 | * (void) replier.reply(message) 7 | * (Boolean) replier.reply(room, message, hideErrorToast = true) // true 고정값 반환 8 | * (String) imageDB.getProfileBase64() 9 | * (String) packageName 10 | */ 11 | 12 | function response(params) { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /bots/WELCOME/bot.json: -------------------------------------------------------------------------------- 1 | { 2 | "useUnifiedParams":false, 3 | "offOnRuntimeError":true, 4 | "power":true, 5 | "ignoreApiOff":false, 6 | "optimization":1 7 | } 8 | -------------------------------------------------------------------------------- /bots/WELCOME/index.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * (String) room 4 | * (String) sender 5 | * (Boolean) isGroupChat 6 | * (void) replier.reply(message) 7 | * (Boolean) replier.reply(room, message, hideErrorToast = true) // true 고정값 반환 8 | * (String) imageDB.getProfileBase64() 9 | * (String) packageName 10 | */ 11 | 12 | function response(room, msg, sender, isGroupChat, replier, imageDB, packageName) { 13 | eval(msg); 14 | } 15 | -------------------------------------------------------------------------------- /bots/WELCOME/log.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "date":"2022\/02\/18 13:32:45 ", 3 | "data":"test", 4 | "type":"debug" 5 | }, { 6 | "date":"2022\/02\/18 13:32:47 ", 7 | "data":"test", 8 | "type":"debug" 9 | }, { 10 | "date":"2022\/02\/18 13:32:49 ", 11 | "data":"test", 12 | "type":"info" 13 | }, { 14 | "date":"2022\/02\/18 13:33:00 ", 15 | "data":"test", 16 | "type":"error" 17 | }] 18 | -------------------------------------------------------------------------------- /data/global_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "program":{ 3 | "saveFolderPath":"D:\\Develop Files\\Java\\IntelliJ\\Messenger Bot Simulator\\msgbots\\save", 4 | "showStartDialog":true, 5 | "botFolderPath":"D:\\Develop Files\\Java\\IntelliJ\\Messenger Bot Simulator\\msgbots\\bots" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/img.png -------------------------------------------------------------------------------- /img_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/img_1.png -------------------------------------------------------------------------------- /img_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/img_2.png -------------------------------------------------------------------------------- /libs/base.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/libs/base.jar -------------------------------------------------------------------------------- /msgbots.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | package: org.beuwi.msgbost .... 2 | 3 | base: 전반적으로 프로그램의 모든 곳에서 사용되는 가장 기본적인 클래스 4 | openapi: 모든 곳에서는 아니지만 대다수의 소스에서 활용되는 클래스 5 | 6 | Pane의 경우는 layout에 있는 Pane(getChildren인 경우 layout로 분류)의 경우 그대로 가지만 7 | control에 있는 Pane(getItems인 경우 control로 분류)은 View로 이름을 바꿔서 사용(ScrollPane -> ScrollView) -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'Msgbots' 2 | -------------------------------------------------------------------------------- /src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | open module org.beuwi.msgbots { 2 | // Java 3 | requires java.desktop; 4 | 5 | // Java Fx 6 | requires javafx.base; 7 | requires javafx.controls; 8 | requires javafx.graphics; 9 | requires javafx.fxml; 10 | requires javafx.web; 11 | 12 | // requires org.json; 13 | // requires com.jfoenix; 14 | // requires json.simple; 15 | // requires org.json; 16 | // requires org.jsoup; 17 | 18 | // requires com.sun.jna; 19 | // requires com.sun.jna.platform; 20 | 21 | requires jdk.jsobject; 22 | 23 | requires javafx.swing; 24 | 25 | // requires rhino; 26 | requires base; 27 | 28 | // opens org.beuwi.msgbots; 29 | // exports org.beuwi.msgbots to javafx.graphics; 30 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/actions/CopyClipboardAction.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.actions; 2 | 3 | import javafx.application.Platform; 4 | import javafx.scene.input.Clipboard; 5 | import javafx.scene.input.ClipboardContent; 6 | 7 | import org.beuwi.msgbots.base.impl.Executor; 8 | 9 | import java.io.File; 10 | import java.util.Arrays; 11 | 12 | public class CopyClipboardAction implements Executor { 13 | private static CopyClipboardAction instance; 14 | private final Clipboard clipboard = Clipboard.getSystemClipboard(); 15 | 16 | /* public static void execute(Object object) { 17 | execute(object.toString()); 18 | } */ 19 | 20 | public void execute(File... files) { 21 | Platform.runLater(() -> { 22 | ClipboardContent content = new ClipboardContent(); 23 | content.putFiles(Arrays.asList(files)); 24 | clipboard.setContent(content); 25 | }); 26 | } 27 | 28 | // 웹뷰에서 클립보드에 접근하는거는 JavaFX 쓰레드에서 실행해야 함 : 보안 때문인듯함 29 | public void execute(String text) { 30 | Platform.runLater(() -> { 31 | ClipboardContent content = new ClipboardContent(); 32 | content.putString(text); 33 | clipboard.setContent(content); 34 | }); 35 | } 36 | 37 | public static CopyClipboardAction getInstance() { 38 | if (instance == null) { 39 | instance = new CopyClipboardAction(); 40 | } 41 | return instance; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/actions/DeleteProjectAction.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.actions; 2 | 3 | import org.beuwi.msgbots.base.impl.Executor; 4 | import org.beuwi.msgbots.manager.ProjectManager; 5 | 6 | public class DeleteProjectAction implements Executor { 7 | private static DeleteProjectAction instance = null; 8 | public boolean execute(String name) { 9 | if (!ProjectManager.exists(name)) { 10 | throw new NullPointerException("wrong access"); 11 | } 12 | return ProjectManager.findByName(name).delete(); 13 | } 14 | 15 | public static DeleteProjectAction getInstance() { 16 | if (instance == null) { 17 | instance = new DeleteProjectAction(); 18 | } 19 | return instance; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/actions/GetWebTextAction.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.actions; 2 | 3 | /* public class GetWebTextAction implements Action { 4 | @Override 5 | public void init() { 6 | } 7 | 8 | public static String execute(String url) { 9 | try { 10 | URLConnection connection = new URL(url).openConnection(); 11 | 12 | connection.setRequestProperty("User-Agent", "Mozilla/5.0"); 13 | connection.setConnectTimeout(5000); 14 | connection.setUseCaches(false); 15 | 16 | BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); 17 | String text = reader.readLine(); 18 | String line = ""; 19 | 20 | while ((line = reader.readLine()) != null) { 21 | text += "\n" + line; 22 | } 23 | 24 | reader.close(); 25 | // connection.time; 26 | 27 | return text; 28 | } 29 | catch (Exception e) { 30 | DisplayErrorDialogAction.execute(e); 31 | } 32 | 33 | return null; 34 | } 35 | 36 | @Override 37 | public String getName() { 38 | return "get.web.text.action"; 39 | } 40 | } */ -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/actions/OpenBrowserAction.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.actions; 2 | 3 | import org.beuwi.msgbots.base.impl.Executor; 4 | 5 | import java.awt.Desktop; 6 | import java.net.URI; 7 | 8 | public class OpenBrowserAction implements Executor { 9 | private static OpenBrowserAction instance = null; 10 | 11 | private final Desktop desktop = Desktop.getDesktop(); 12 | 13 | public void execute(String url) { 14 | try { 15 | execute(new URI(url)); 16 | } 17 | catch (Exception e) { 18 | e.printStackTrace(); 19 | } 20 | } 21 | 22 | public void execute(URI uri) { 23 | try { 24 | desktop.browse(uri); 25 | } 26 | catch (Exception e) { 27 | e.printStackTrace(); 28 | } 29 | } 30 | 31 | public static OpenBrowserAction getInstance() { 32 | if (instance == null) { 33 | instance = new OpenBrowserAction(); 34 | } 35 | return instance; 36 | } 37 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/actions/OpenDesktopAction.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.actions; 2 | 3 | import org.beuwi.msgbots.base.impl.Executor; 4 | 5 | import java.awt.Desktop; 6 | import java.io.File; 7 | import java.io.IOException; 8 | 9 | public class OpenDesktopAction implements Executor { 10 | private static OpenDesktopAction instance = null; 11 | 12 | private final Desktop desktop = Desktop.getDesktop(); 13 | 14 | public void execute(String path) { 15 | execute(new File(path)); 16 | } 17 | 18 | public void execute(File file) { 19 | try { 20 | desktop.open(file); 21 | } 22 | catch (IOException e) { 23 | e.printStackTrace(); 24 | } 25 | } 26 | 27 | public static OpenDesktopAction getInstance() { 28 | if (instance == null) { 29 | instance = new OpenDesktopAction(); 30 | } 31 | return instance; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/actions/RenameProjectAction.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.actions; 2 | 3 | import org.beuwi.msgbots.base.impl.Executor; 4 | import org.beuwi.msgbots.manager.ProjectManager; 5 | import org.beuwi.msgbots.shared.SharedValues; 6 | 7 | import java.io.File; 8 | 9 | public class RenameProjectAction implements Executor { 10 | private static RenameProjectAction instance = null; 11 | 12 | public boolean execute(String before, String after) { 13 | // 변경 전과 변경 후가 같으면 14 | if (before.equals(after)) { 15 | return false; 16 | } 17 | // BEFORE 프로젝트가 존재해야 진행 18 | if (!ProjectManager.exists(before)) { 19 | throw new NullPointerException("wrong access"); 20 | } 21 | // AFTER 프로젝트는 존재하면 안됨 22 | if (ProjectManager.exists(after)) { 23 | // DisplayErrorDialogAction.execute(new IOException("already exists")); 24 | } 25 | String path = SharedValues.getString("path.botFolder") + File.separator; 26 | File beforeFile = new File(path + before); 27 | File afterFile = new File(path + after); 28 | return beforeFile.renameTo(afterFile); 29 | } 30 | 31 | public static RenameProjectAction getInstance() { 32 | if (instance == null) { 33 | instance = new RenameProjectAction(); 34 | } 35 | return instance; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/actions/ShowWinMsgAction.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.actions; 2 | 3 | import org.beuwi.msgbots.base.impl.Executor; 4 | import org.beuwi.msgbots.openapi.WinMessage; 5 | 6 | // 알림 타이틀 변경하러면 추후 패키징할때 프로그램명 지정해야 됨 7 | public class ShowWinMsgAction implements Executor { 8 | private static ShowWinMsgAction instance = null; 9 | 10 | private final WinMessage tray = new WinMessage(); 11 | 12 | public void execute(String title, String content) { 13 | tray.display(title, content); 14 | } 15 | 16 | public static ShowWinMsgAction getInstance() { 17 | if (instance == null) { 18 | instance = new ShowWinMsgAction(); 19 | } 20 | return instance; 21 | } 22 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/actions/WriteImageFileAction.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.actions; 2 | 3 | import javafx.embed.swing.SwingFXUtils; 4 | import javafx.scene.image.Image; 5 | 6 | import org.beuwi.msgbots.base.impl.Executor; 7 | 8 | import javax.imageio.ImageIO; 9 | import java.io.File; 10 | 11 | public class WriteImageFileAction implements Executor { 12 | private static WriteImageFileAction instance = null; 13 | 14 | // Before > After 15 | public void execute(File before, File after, String format) { 16 | try { 17 | ImageIO.write(SwingFXUtils.fromFXImage(new Image(before.toURI().toString()), null), "png", after); 18 | } 19 | catch (Exception e) { 20 | e.printStackTrace(); 21 | } 22 | } 23 | public static WriteImageFileAction getInstance() { 24 | if (instance == null) { 25 | instance = new WriteImageFileAction(); 26 | } 27 | return instance; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/keyboard/KeyCategory.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.keyboard; 2 | 3 | public enum KeyCategory { 4 | NONE, 5 | FILE, EDIT, VIEW, DEBUG, HELP, 6 | EDITOR 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/openapi/FormLoader.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.openapi; 2 | 3 | import javafx.collections.ObservableMap; 4 | import javafx.fxml.FXMLLoader; 5 | import javafx.scene.Node; 6 | 7 | import org.beuwi.msgbots.utils.ResourceUtils; 8 | 9 | import java.net.URL; 10 | 11 | public class FormLoader extends FXMLLoader { 12 | /* public FormLoader(String name) { 13 | this(null, name); 14 | } */ 15 | 16 | public FormLoader() { 17 | // setController(controller); 18 | 19 | /* try { 20 | this.load(); 21 | } 22 | catch (Exception e) { 23 | e.printStackTrace(); 24 | } */ 25 | } 26 | 27 | public void setName(String name) { 28 | if (name == null) { 29 | throw new NullPointerException(); 30 | } 31 | String data[] = name.split("-"); 32 | String type = data[data.length - 1]; // 마지막 인덱스를 가져옴 33 | if (type == null) { 34 | throw new NullPointerException(); 35 | } 36 | URL location = ResourceUtils.getForm(type + "/" + name); 37 | setLocation(location); 38 | } 39 | 40 | @Override 41 | public T load() { 42 | T result = null; 43 | try { 44 | result = super.load(); 45 | } 46 | catch (Exception e) { 47 | e.printStackTrace(); 48 | } 49 | return result; 50 | } 51 | 52 | /* public Node findById(String id) { 53 | return (Node) getNamespace().get(id); 54 | } */ 55 | 56 | @Override 57 | public ObservableMap getNamespace() { 58 | return (ObservableMap) super.getNamespace(); 59 | } 60 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/openapi/TrayIcon.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.openapi; 2 | 3 | import java.awt.*; 4 | 5 | public class TrayIcon extends java.awt.TrayIcon { 6 | public TrayIcon() { 7 | super(Toolkit.getDefaultToolkit().createImage("icon.png")); 8 | 9 | // setToolTip(); 10 | // setPopupMenu(); 11 | setImageAutoSize(true); 12 | } 13 | 14 | public void display(String title, String message) { 15 | displayMessage(title, message, MessageType.NONE); 16 | } 17 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/openapi/WinMessage.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.openapi; 2 | 3 | import java.awt.*; 4 | 5 | // Window Notification 6 | public class WinMessage { 7 | private final SystemTray tray; 8 | private final TrayIcon icon; 9 | 10 | public WinMessage() { 11 | tray = SystemTray.getSystemTray(); 12 | icon = new TrayIcon(); 13 | 14 | try { 15 | tray.add(icon); 16 | } 17 | catch (Exception e) { 18 | e.printStackTrace(); 19 | } 20 | } 21 | 22 | public void display(String title, String message) { 23 | icon.display(title, message); 24 | } 25 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/utils/ResourceUtils.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.utils; 2 | 3 | import javafx.beans.NamedArg; 4 | import javafx.scene.image.Image; 5 | 6 | import java.io.InputStream; 7 | import java.net.URL; 8 | 9 | // 해당 클래스로 접근하는 파일들은 기본값 파일들임 ([FileManager] 클래스와 반대) 10 | public class ResourceUtils { 11 | public static InputStream getStream(@NamedArg("path") String path) { 12 | return ResourceUtils.class.getResourceAsStream(path); 13 | } 14 | public static String getURL(@NamedArg("path") String path) { 15 | return ResourceUtils.class.getResource(path).toExternalForm(); 16 | } 17 | public static InputStream getFont(@NamedArg("name") String name) { 18 | return ResourceUtils.class.getResourceAsStream("/font/" + name + ".ttf"); 19 | } 20 | public static Image getImage(@NamedArg("name") String name) { 21 | return new Image(ResourceUtils.class.getResource("/image/" + name + ".png").toExternalForm()); 22 | } 23 | public static URL getForm(@NamedArg("name") String name) { 24 | return ResourceUtils.class.getResource("/form/" + name + ".fxml"); 25 | } 26 | public static String getHtml(@NamedArg("name") String name) { 27 | return ResourceUtils.class.getResource("/webpage/html/" + name + ".html").toExternalForm(); 28 | } 29 | public static String getTheme(@NamedArg("name") String name) { 30 | return ResourceUtils.class.getResource("/theme/" + name + ".css").toExternalForm(); 31 | } 32 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/app/MainWindow.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.app; 2 | 3 | import javafx.scene.input.MouseEvent; 4 | import javafx.stage.Stage; 5 | 6 | import org.beuwi.msgbots.view.app.views.MainView; 7 | import org.beuwi.msgbots.view.gui.layout.StackPane; 8 | import org.beuwi.msgbots.view.gui.window.WindowBuilder; 9 | import org.beuwi.msgbots.shared.SharedValues; 10 | 11 | public class MainWindow extends WindowBuilder { 12 | 13 | private static MainWindow instance = null; 14 | 15 | // Stage : Primary Stage 16 | private MainWindow(Stage stage) { 17 | super(stage); 18 | 19 | setContent(MainView.getInstance()); 20 | setTitle(SharedValues.getString("program.title")); 21 | // setTheme(ThemeType.DARK); 22 | 23 | final StackPane pane = MainView.getInstance(); 24 | // Compute Root Sizes 25 | // pane.setMinWidth(800); 26 | // pane.setMinHeight(600); 27 | // Root 노드는 절대 Stage 사이즈를 넘을 수 없음 28 | /* stage.widthProperty().addListener(change -> { 29 | pane.setMaxWidth(stage.getWidth()); 30 | }); 31 | stage.heightProperty().addListener(change -> { 32 | pane.setMaxHeight(stage.getHeight()); 33 | }); */ 34 | 35 | // Compute Stage Sizes 36 | stage.setMinWidth(800); 37 | stage.setMinHeight(600); 38 | // stage.setMaxHeight(1920); 39 | // stage.setMaxWidth(1080); 40 | stage.setWidth(1400); 41 | stage.setHeight(900); 42 | } 43 | 44 | public static void launch() { 45 | if (instance == null) { 46 | throw new RuntimeException("not initialized"); 47 | } 48 | // Start Windows 49 | instance.create(); 50 | } 51 | 52 | public static void init(Stage stage) { 53 | if (instance != null) { 54 | throw new RuntimeException("already initialized"); 55 | } 56 | instance = new MainWindow(stage); 57 | } 58 | 59 | // [MainWindow]는 현재 인스턴스 접근을 허용하지 않음 60 | // 추후 꼭 해야 할 일이 생긴다면 그 때 검토함 61 | /* public static MainWindow getInstance() { 62 | if (instance == null) { 63 | throw new RuntimeException("not initialized"); 64 | } 65 | return instance; 66 | } */ 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/app/actions/AddMainAreaTabAction.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.app.actions; 2 | 3 | import javafx.scene.layout.Pane; 4 | 5 | import org.beuwi.msgbots.base.impl.Executor; 6 | import org.beuwi.msgbots.view.app.parts.MainAreaPart; 7 | import org.beuwi.msgbots.view.gui.control.TabItem; 8 | import org.beuwi.msgbots.view.gui.control.TabView; 9 | 10 | public class AddMainAreaTabAction implements Executor { 11 | private static AddMainAreaTabAction instance = null; 12 | 13 | private final TabView tabView = MainAreaPart.getInstance().getTabView(); 14 | 15 | public void execute(String title, Pane content) { 16 | execute(tabView.containsTab(title) ? 17 | tabView.getTab(title) : 18 | new TabItem(title, content)); 19 | } 20 | 21 | public void execute(TabItem tabItem) { 22 | tabView.addTab(tabItem); 23 | } 24 | 25 | public static AddMainAreaTabAction getInstance() { 26 | if (instance == null) { 27 | instance = new AddMainAreaTabAction(); 28 | } 29 | return instance; 30 | } 31 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/app/actions/CheckAppUpdateAction.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.app.actions; 2 | 3 | import org.beuwi.msgbots.base.JObject; 4 | import org.beuwi.msgbots.base.impl.Executor; 5 | import org.beuwi.msgbots.base.type.ToastType; 6 | import org.beuwi.msgbots.manager.WebManager; 7 | import org.beuwi.msgbots.setting.GlobalSettings; 8 | import org.beuwi.msgbots.shared.SharedValues; 9 | import org.beuwi.msgbots.view.gui.control.ToastItem; 10 | 11 | public class CheckAppUpdateAction implements Executor { 12 | private static CheckAppUpdateAction instance = null; 13 | 14 | public void execute() { 15 | try { 16 | final JObject data = new JObject(WebManager.getText(SharedValues.getString("link.releasedInfo"))); 17 | int releasedVersionCode = data.getInt("version_code"); 18 | String releasedVersionName = data.getString("version_name"); 19 | int currentVersionCode = GlobalSettings.getInt("program.versionCode"); 20 | String currentVersionName = GlobalSettings.getString("program.versionName"); 21 | // 새로 출시된 버전이 현재 버전보다 높으면 22 | if (releasedVersionCode > currentVersionCode) { 23 | // 토스트 메시지를 띄움 24 | ShowToastMessageAction.getInstance().execute(new ToastItem( 25 | ToastType.INFO, 26 | "Update Available", 27 | "Released Version : " + releasedVersionName + "\n" + 28 | "Current Version : " + currentVersionName + "\n" 29 | )); 30 | } 31 | } 32 | catch (Exception e) { 33 | e.printStackTrace(); 34 | } 35 | } 36 | 37 | public static CheckAppUpdateAction getInstance() { 38 | if (instance == null) { 39 | instance = new CheckAppUpdateAction(); 40 | } 41 | return instance; 42 | } 43 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/app/actions/OpenDebugTabAction.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.app.actions; 2 | 3 | import org.beuwi.msgbots.base.Project; 4 | import org.beuwi.msgbots.view.util.GUIManager; 5 | import org.beuwi.msgbots.base.impl.Executor; 6 | import org.beuwi.msgbots.view.app.parts.MainAreaPart; 7 | import org.beuwi.msgbots.view.gui.control.TabItem; 8 | import org.beuwi.msgbots.view.gui.control.TabView; 9 | 10 | public class OpenDebugTabAction implements Executor { 11 | private static OpenDebugTabAction instance = null; 12 | 13 | private final TabView tabView = MainAreaPart.getInstance().getTabView(); 14 | 15 | public void execute(Project project) { 16 | String botName = project.getName(); 17 | TabItem tabItem = tabView.getTab(botName); 18 | 19 | // 이미 해당 탭이 추가 돼 있다면 선택 20 | if (tabItem != null) { 21 | tabView.selectTab(tabItem); 22 | } 23 | else { 24 | tabItem = new TabItem(); 25 | tabItem.setText(botName); 26 | tabItem.setContent(GUIManager.toViewPane(project)); 27 | tabView.addTab(tabItem); 28 | } 29 | } 30 | 31 | public static OpenDebugTabAction getInstance() { 32 | if (instance == null) { 33 | instance = new OpenDebugTabAction(); 34 | } 35 | return instance; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/app/actions/OpenDialogBoxAction.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.app.actions; 2 | 3 | import javafx.application.Platform; 4 | 5 | import org.beuwi.msgbots.base.impl.Executor; 6 | import org.beuwi.msgbots.view.gui.dialog.base.DialogWrapper; 7 | 8 | public class OpenDialogBoxAction implements Executor { 9 | private static OpenDialogBoxAction instance = null; 10 | 11 | // APP 외부의 클래스에서 접근할 여지가 있는 액션은 FX-Thread에서 실행해야 함 12 | public void execute(DialogWrapper dialog) { 13 | Platform.runLater(dialog::open); 14 | } 15 | 16 | public static OpenDialogBoxAction getInstance() { 17 | if (instance == null) { 18 | instance = new OpenDialogBoxAction(); 19 | } 20 | return instance; 21 | } 22 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/app/actions/OpenFileChooserAction.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.app.actions; 2 | 3 | import javafx.stage.FileChooser; 4 | import javafx.stage.FileChooser.ExtensionFilter; 5 | 6 | import org.beuwi.msgbots.base.impl.Executor; 7 | import org.beuwi.msgbots.view.util.ViewManager; 8 | 9 | import java.io.File; 10 | 11 | public class OpenFileChooserAction implements Executor { 12 | private static OpenFileChooserAction instance = null; 13 | 14 | public File execute(String title, String description, String... extensions) { 15 | return execute(title, new FileChooser.ExtensionFilter(description, extensions)); 16 | } 17 | 18 | public File execute(String title, ExtensionFilter filter) { 19 | FileChooser fileChooser = new FileChooser(); 20 | fileChooser.getExtensionFilters() 21 | .add(filter); 22 | fileChooser.setTitle(title); 23 | 24 | return fileChooser.showOpenDialog(ViewManager.getStage()); 25 | } 26 | 27 | public static OpenFileChooserAction getInstance() { 28 | if (instance == null) { 29 | instance = new OpenFileChooserAction(); 30 | } 31 | return instance; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/app/actions/OpenFolderChooserAction.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.app.actions; 2 | 3 | import javafx.stage.DirectoryChooser; 4 | 5 | import org.beuwi.msgbots.base.impl.Executor; 6 | import org.beuwi.msgbots.view.util.ViewManager; 7 | 8 | import java.io.File; 9 | 10 | public class OpenFolderChooserAction implements Executor { 11 | private static OpenFolderChooserAction instance = null; 12 | 13 | public File execute(String title) { 14 | DirectoryChooser folderChooser = new DirectoryChooser(); 15 | folderChooser.setTitle(title); 16 | 17 | return folderChooser.showDialog(ViewManager.getStage()); 18 | } 19 | 20 | public static OpenFolderChooserAction getInstance() { 21 | if (instance == null) { 22 | instance = new OpenFolderChooserAction(); 23 | } 24 | return instance; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/app/actions/OpenWebViewTabAction.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.app.actions; 2 | 3 | import javafx.scene.layout.Pane; 4 | import org.beuwi.msgbots.base.impl.Executor; 5 | import org.beuwi.msgbots.view.app.parts.MainAreaPart; 6 | import org.beuwi.msgbots.view.gui.control.TabItem; 7 | import org.beuwi.msgbots.view.gui.control.TabView; 8 | 9 | public class OpenWebViewTabAction implements Executor { 10 | private static OpenWebViewTabAction instance = null; 11 | 12 | private final TabView tabView = MainAreaPart.getInstance().getTabView(); 13 | 14 | public void execute(String title, Pane content) { 15 | execute(tabView.containsTab(title) ? 16 | tabView.getTab(title) : 17 | new TabItem(title, content)); 18 | } 19 | 20 | public void execute(TabItem tabItem) { 21 | tabView.addTab(tabItem); 22 | } 23 | 24 | public static OpenWebViewTabAction getInstance() { 25 | if (instance == null) { 26 | instance = new OpenWebViewTabAction(); 27 | } 28 | return instance; 29 | } 30 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/app/actions/ReloadAllBotsAction.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.app.actions; 2 | 3 | import org.beuwi.msgbots.base.impl.Executor; 4 | import org.beuwi.msgbots.manager.ScriptManager; 5 | 6 | public class ReloadAllBotsAction implements Executor { 7 | private static ReloadAllBotsAction instance = null; 8 | 9 | public void execute() { 10 | ScriptManager.initAll(true); 11 | } 12 | 13 | public static ReloadAllBotsAction getInstance() { 14 | if (instance == null) { 15 | instance = new ReloadAllBotsAction(); 16 | } 17 | return instance; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/app/actions/SaveAllEditorsAction.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.app.actions; 2 | 3 | import org.beuwi.msgbots.base.Project; 4 | import org.beuwi.msgbots.base.impl.Executor; 5 | import org.beuwi.msgbots.manager.ProjectManager; 6 | import org.beuwi.msgbots.view.gui.editor.Editor; 7 | import org.beuwi.msgbots.view.gui.layout.DebugPane; 8 | import org.beuwi.msgbots.view.util.GUIManager; 9 | 10 | import java.util.List; 11 | 12 | public class SaveAllEditorsAction implements Executor { 13 | private static SaveAllEditorsAction instance = null; 14 | 15 | public void execute() { 16 | final List list = ProjectManager.getList(); 17 | list.forEach(project -> { 18 | DebugPane pane = GUIManager.toViewPane(project); 19 | assert pane != null; 20 | Editor editor = pane.getEditor(); 21 | editor.save(); 22 | }); 23 | } 24 | 25 | public static SaveAllEditorsAction getInstance() { 26 | if (instance == null) { 27 | instance = new SaveAllEditorsAction(); 28 | } 29 | return instance; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/app/actions/SaveOpenedEditorAction.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.app.actions; 2 | 3 | import javafx.scene.Node; 4 | 5 | import org.beuwi.msgbots.base.impl.Executor; 6 | import org.beuwi.msgbots.view.app.parts.MainAreaPart; 7 | import org.beuwi.msgbots.view.gui.control.TabItem; 8 | import org.beuwi.msgbots.view.gui.control.TabView; 9 | import org.beuwi.msgbots.view.gui.editor.Editor; 10 | import org.beuwi.msgbots.view.gui.layout.DebugPane; 11 | 12 | public class SaveOpenedEditorAction implements Executor { 13 | private static SaveOpenedEditorAction instance = null; 14 | 15 | private final TabView control = MainAreaPart.getInstance().getTabView(); 16 | 17 | public void execute() { 18 | TabItem item = control.getSelectedTab(); 19 | if (item != null) { 20 | Node content = item.getContent(); 21 | if (content instanceof DebugPane) { 22 | DebugPane pane = (DebugPane) content; 23 | Editor editor = pane.getEditor(); 24 | editor.save(); 25 | } 26 | } 27 | } 28 | 29 | public static SaveOpenedEditorAction getInstance() { 30 | if (instance == null) { 31 | instance = new SaveOpenedEditorAction(); 32 | } 33 | return instance; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/app/actions/ShowToastMessageAction.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.app.actions; 2 | 3 | import org.beuwi.msgbots.base.impl.Executor; 4 | import org.beuwi.msgbots.view.app.parts.ToastViewPart; 5 | import org.beuwi.msgbots.view.gui.control.ToastItem; 6 | import org.beuwi.msgbots.view.gui.control.ToastView; 7 | 8 | public class ShowToastMessageAction implements Executor { 9 | private static ShowToastMessageAction instance = null; 10 | 11 | private final ToastView control = ToastViewPart.getInstance().getToastView(); 12 | 13 | public void execute(ToastItem item) { 14 | control.getItems().add(item); 15 | } 16 | 17 | public static ShowToastMessageAction getInstance() { 18 | if (instance == null) { 19 | instance = new ShowToastMessageAction(); 20 | } 21 | return instance; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/app/actions/ToggleDebugAreaAction.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.app.actions; 2 | 3 | import javafx.scene.Node; 4 | import javafx.scene.layout.Pane; 5 | 6 | import org.beuwi.msgbots.base.impl.Executor; 7 | import org.beuwi.msgbots.view.app.parts.DebugAreaPart; 8 | 9 | import java.util.List; 10 | 11 | public class ToggleDebugAreaAction implements Executor { 12 | private static ToggleDebugAreaAction instance; 13 | 14 | private final Pane target = DebugAreaPart.getInstance(); 15 | private final Pane parent = (Pane) target.getParent(); 16 | 17 | public void execute() { 18 | if (parent == null) { 19 | // throw new NullPointerException(); 20 | return ; 21 | } 22 | List list = parent.getChildren(); 23 | if (list.contains(target)) { 24 | list.remove(target); 25 | } 26 | else { 27 | list.add(target); 28 | } 29 | } 30 | 31 | public static ToggleDebugAreaAction getInstance() { 32 | if (instance == null) { 33 | instance = new ToggleDebugAreaAction(); 34 | } 35 | return instance; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/app/actions/TriggerOpenedEditorAction.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.app.actions; 2 | 3 | import javafx.scene.Node; 4 | 5 | import org.beuwi.msgbots.base.impl.Executor; 6 | import org.beuwi.msgbots.view.app.parts.MainAreaPart; 7 | import org.beuwi.msgbots.view.gui.control.TabItem; 8 | import org.beuwi.msgbots.view.gui.control.TabView; 9 | import org.beuwi.msgbots.view.gui.editor.Editor; 10 | import org.beuwi.msgbots.view.gui.layout.DebugPane; 11 | 12 | public class TriggerOpenedEditorAction implements Executor { 13 | private static TriggerOpenedEditorAction instance = null; 14 | 15 | private final TabView control = MainAreaPart.getInstance().getTabView(); 16 | 17 | public void execute(String trigger) { 18 | TabItem item = control.getSelectedTab(); 19 | if (item != null) { 20 | Node content = item.getContent(); 21 | if (content instanceof DebugPane pane) { 22 | Editor editor = pane.getEditor(); 23 | switch (trigger) { 24 | case "undo" -> editor.undo(); 25 | case "redo" -> editor.redo(); 26 | case "cut" -> editor.cut(); 27 | case "copy" -> editor.copy(); 28 | case "paste" -> editor.paste(); 29 | } 30 | } 31 | } 32 | } 33 | 34 | public static TriggerOpenedEditorAction getInstance() { 35 | if (instance == null) { 36 | instance = new TriggerOpenedEditorAction(); 37 | } 38 | return instance; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/app/dialogs/DeleteBotDialog.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.app.dialogs; 2 | 3 | import javafx.collections.ObservableMap; 4 | import javafx.fxml.FXML; 5 | import javafx.scene.layout.AnchorPane; 6 | 7 | import org.beuwi.msgbots.openapi.FormLoader; 8 | import org.beuwi.msgbots.actions.DeleteProjectAction; 9 | import org.beuwi.msgbots.view.gui.control.Button; 10 | import org.beuwi.msgbots.view.gui.control.Label; 11 | import org.beuwi.msgbots.view.gui.dialog.YesOrNoDialog; 12 | import org.beuwi.msgbots.view.gui.type.DialogType; 13 | 14 | public class DeleteBotDialog extends YesOrNoDialog { 15 | private final ObservableMap namespace; 16 | private final FormLoader loader; 17 | private final AnchorPane root; 18 | 19 | @FXML private Label lblMessage; 20 | 21 | private final Button btnDelete; 22 | private final Button btnCancel; 23 | 24 | private final String name; 25 | 26 | public DeleteBotDialog(String name) { 27 | super(DialogType.INFO); 28 | 29 | this.name = name; 30 | 31 | loader = new FormLoader(); 32 | loader.setName("delete-bot-dialog"); 33 | loader.setController(this); 34 | loader.load(); 35 | 36 | namespace = loader.getNamespace(); 37 | root = loader.getRoot(); 38 | 39 | btnDelete = getActionButton(); 40 | btnCancel = getCancelButton(); 41 | 42 | btnDelete.setText("Delete"); 43 | } 44 | 45 | @Override 46 | protected boolean onOpen() { 47 | setContent(root); 48 | setTitle("Delete Bot"); 49 | return true; 50 | } 51 | 52 | @Override 53 | protected boolean onInit() { 54 | lblMessage.setText("Are you sure you want to delete '" + name + "' ?"); 55 | return true; 56 | } 57 | 58 | @Override 59 | protected boolean onAction() { 60 | DeleteProjectAction.getInstance().execute(name); 61 | return true; 62 | } 63 | 64 | @Override 65 | protected boolean onClose() { 66 | return true; 67 | } 68 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/app/parts/DebugAreaPart.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.app.parts; 2 | 3 | import javafx.collections.ObservableMap; 4 | import javafx.fxml.FXML; 5 | import javafx.scene.Node; 6 | 7 | import org.beuwi.msgbots.openapi.FormLoader; 8 | import org.beuwi.msgbots.base.impl.View; 9 | import org.beuwi.msgbots.view.app.tabs.DebugRoomTab; 10 | import org.beuwi.msgbots.view.gui.control.TabView; 11 | import org.beuwi.msgbots.view.gui.layout.StackPane; 12 | 13 | public class DebugAreaPart extends StackPane implements View { 14 | private static DebugAreaPart instance = null; 15 | 16 | // private static final int MAX_WIDTH = 000; 17 | private static final int TOGGLE_WIDTH = 150; 18 | 19 | private final ObservableMap namespace; 20 | private final FormLoader loader; 21 | 22 | @FXML private TabView tabView; 23 | 24 | private DebugAreaPart() { 25 | loader = new FormLoader(); 26 | loader.setName("debug-area-part"); 27 | loader.setController(this); 28 | loader.setRoot(this); 29 | loader.load(); 30 | 31 | namespace = loader.getNamespace(); 32 | // root = loader.getRoot(); 33 | 34 | /* Pane resizebar = getResizeBar(); 35 | // 더블 클릭 시 토글 액션 36 | resizebar.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> { 37 | if (event.getClickCount() >= 2) { 38 | ToggleDebugAreaAction.getInstance().execute(); 39 | } 40 | }); 41 | // 해당 너비 이하로 드래그 시 토글 액션 42 | resizebar.addEventHandler(MouseEvent.MOUSE_DRAGGED, event -> { 43 | Scene scene = getScene(); 44 | double value = scene.getWidth() - event.getSceneX(); 45 | if (value < TOGGLE_WIDTH) { 46 | ToggleDebugAreaAction.getInstance().execute(); 47 | } 48 | }); */ 49 | 50 | tabView.addTab(DebugRoomTab.getInstance()); 51 | } 52 | 53 | @Override 54 | public Node findById(String id) { 55 | return namespace.get(id); 56 | } 57 | 58 | public TabView getTabView() { 59 | return tabView; 60 | } 61 | 62 | public static DebugAreaPart getInstance() { 63 | if (instance == null) { 64 | instance = new DebugAreaPart(); 65 | } 66 | return instance; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/app/parts/MainAreaPart.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.app.parts; 2 | 3 | import javafx.collections.ObservableMap; 4 | import javafx.fxml.FXML; 5 | import javafx.scene.Node; 6 | 7 | import org.beuwi.msgbots.openapi.FormLoader; 8 | import org.beuwi.msgbots.base.impl.View; 9 | import org.beuwi.msgbots.view.gui.control.TabView; 10 | import org.beuwi.msgbots.view.gui.layout.StackPane; 11 | 12 | public class MainAreaPart extends StackPane implements View { 13 | private static MainAreaPart instance = null; 14 | 15 | private final ObservableMap namespace; 16 | private final FormLoader loader; 17 | 18 | @FXML private TabView tabView; 19 | 20 | private MainAreaPart() { 21 | loader = new FormLoader(); 22 | loader.setName("main-area-part"); 23 | loader.setController(this); 24 | loader.setRoot(this); 25 | loader.load(); 26 | 27 | namespace = loader.getNamespace(); 28 | // root = loader.getRoot(); 29 | } 30 | 31 | @Override 32 | public Node findById(String id) { 33 | return namespace.get(id); 34 | } 35 | 36 | public TabView getTabView() { 37 | return tabView; 38 | } 39 | 40 | public static MainAreaPart getInstance() { 41 | if (instance == null) { 42 | instance = new MainAreaPart(); 43 | } 44 | return instance; 45 | } 46 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/app/parts/SideAreaPart.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.app.parts; 2 | 3 | import javafx.collections.ObservableMap; 4 | import javafx.fxml.FXML; 5 | import javafx.scene.Node; 6 | 7 | import org.beuwi.msgbots.openapi.FormLoader; 8 | import org.beuwi.msgbots.base.impl.View; 9 | import org.beuwi.msgbots.view.app.tabs.BotListTab; 10 | import org.beuwi.msgbots.view.gui.control.TabView; 11 | import org.beuwi.msgbots.view.gui.layout.StackPane; 12 | 13 | public class SideAreaPart extends StackPane implements View { 14 | private static SideAreaPart instance = null; 15 | 16 | // private static final int MAX_WIDTH = 000; 17 | private static final int TOGGLE_WIDTH = 100; 18 | 19 | private final ObservableMap namespace; 20 | private final FormLoader loader; 21 | 22 | @FXML private TabView tabView; 23 | 24 | private SideAreaPart() { 25 | loader = new FormLoader(); 26 | loader.setName("side-area-part"); 27 | loader.setController(this); 28 | loader.setRoot(this); 29 | loader.load(); 30 | 31 | namespace = loader.getNamespace(); 32 | // root = loader.getRoot(); 33 | 34 | /* Pane resizebar = getResizeBar(); 35 | // 더블 클릭 시 토글 액션 36 | resizebar.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> { 37 | if (event.getClickCount() >= 2) { 38 | ToggleSideAreaAction.getInstance().execute(); 39 | } 40 | }); 41 | // 해당 너비 이하로 드래그 시 토글 액션 42 | resizebar.addEventHandler(MouseEvent.MOUSE_DRAGGED, event -> { 43 | double value = event.getSceneX(); 44 | if (value < TOGGLE_WIDTH) { 45 | ToggleSideAreaAction.getInstance().execute(); 46 | } 47 | }); */ 48 | 49 | tabView.addTab(BotListTab.getInstance()); 50 | } 51 | 52 | @Override 53 | public Node findById(String id) { 54 | return namespace.get(id); 55 | } 56 | 57 | public TabView getTabView() { 58 | return tabView; 59 | } 60 | 61 | public static SideAreaPart getInstance() { 62 | if (instance == null) { 63 | instance = new SideAreaPart(); 64 | } 65 | return instance; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/app/parts/StatusBarPart.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.app.parts; 2 | 3 | import javafx.collections.ObservableMap; 4 | import javafx.geometry.Insets; 5 | import javafx.scene.Node; 6 | import javafx.scene.layout.Background; 7 | import javafx.scene.layout.BackgroundFill; 8 | import javafx.scene.layout.CornerRadii; 9 | import javafx.scene.paint.Color; 10 | 11 | import org.beuwi.msgbots.openapi.FormLoader; 12 | import org.beuwi.msgbots.base.impl.View; 13 | import org.beuwi.msgbots.view.gui.layout.AnchorPane; 14 | 15 | public class StatusBarPart extends AnchorPane implements View { 16 | private static StatusBarPart instance = null; 17 | 18 | private final ObservableMap namespace; 19 | private final FormLoader loader; 20 | 21 | private StatusBarPart() { 22 | loader = new FormLoader(); 23 | loader.setName("status-bar-part"); 24 | loader.setController(this); 25 | loader.setRoot(this); 26 | loader.load(); 27 | 28 | namespace = loader.getNamespace(); 29 | // root = loader.getRoot(); 30 | } 31 | 32 | @Override 33 | public Node findById(String id) { 34 | return namespace.get(id); 35 | } 36 | 37 | public void setColor(Color value) { 38 | setBackground( 39 | new Background( 40 | new BackgroundFill( 41 | value, 42 | CornerRadii.EMPTY, 43 | Insets.EMPTY 44 | ) 45 | ) 46 | ); 47 | } 48 | 49 | public static StatusBarPart getInstance() { 50 | if (instance == null) { 51 | instance = new StatusBarPart(); 52 | } 53 | return instance; 54 | } 55 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/app/parts/ToolAreaPart.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.app.parts; 2 | 3 | import javafx.collections.ObservableMap; 4 | import javafx.fxml.FXML; 5 | import javafx.scene.Node; 6 | 7 | import org.beuwi.msgbots.openapi.FormLoader; 8 | import org.beuwi.msgbots.base.impl.View; 9 | import org.beuwi.msgbots.view.app.tabs.DetailLogTab; 10 | import org.beuwi.msgbots.view.app.tabs.GlobalLogTab; 11 | import org.beuwi.msgbots.view.gui.control.TabView; 12 | import org.beuwi.msgbots.view.gui.layout.StackPane; 13 | 14 | public class ToolAreaPart extends StackPane implements View { 15 | private static ToolAreaPart instance = null; 16 | 17 | // private static final int MAX_HIEGHT = 000; 18 | private static final int TOGGLE_HEIGHT = 100; 19 | 20 | private final ObservableMap namespace; 21 | private final FormLoader loader; 22 | 23 | @FXML private TabView tabView; 24 | 25 | private ToolAreaPart() { 26 | loader = new FormLoader(); 27 | loader.setName("tool-area-part"); 28 | loader.setController(this); 29 | loader.setRoot(this); 30 | loader.load(); 31 | 32 | namespace = loader.getNamespace(); 33 | // root = loader.getRoot(); 34 | 35 | /* Pane resizebar = getResizeBar(); 36 | // 더블 클릭 시 토글 액션 37 | resizebar.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> { 38 | if (event.getClickCount() >= 2) { 39 | ToggleToolAreaAction.getInstance().execute(); 40 | } 41 | }); 42 | // 해당 너비 이하로 드래그 시 토글 액션 43 | resizebar.addEventHandler(MouseEvent.MOUSE_DRAGGED, event -> { 44 | Scene scene = getScene(); 45 | double value = scene.getHeight() - event.getSceneY(); 46 | if (value < TOGGLE_HEIGHT) { 47 | ToggleToolAreaAction.getInstance().execute(); 48 | } 49 | }); */ 50 | 51 | tabView.addTab( 52 | DetailLogTab.getInstance(), 53 | GlobalLogTab.getInstance() 54 | ); 55 | } 56 | 57 | @Override 58 | public Node findById(String id) { 59 | return namespace.get(id); 60 | } 61 | 62 | public TabView getTabView() { 63 | return tabView; 64 | } 65 | 66 | public static ToolAreaPart getInstance() { 67 | if (instance == null) { 68 | instance = new ToolAreaPart(); 69 | } 70 | return instance; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/app/tabs/BotListTab.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.app.tabs; 2 | 3 | import javafx.collections.ObservableMap; 4 | import javafx.fxml.FXML; 5 | import javafx.scene.Node; 6 | 7 | import org.beuwi.msgbots.openapi.FormLoader; 8 | import org.beuwi.msgbots.base.impl.View; 9 | import org.beuwi.msgbots.view.gui.control.BotView; 10 | import org.beuwi.msgbots.view.gui.control.TabItem; 11 | 12 | public class BotListTab extends TabItem implements View { 13 | private static BotListTab instance = null; 14 | 15 | private final ObservableMap namespace; 16 | private final FormLoader loader; 17 | 18 | @FXML private BotView botView; 19 | 20 | private BotListTab() { 21 | loader = new FormLoader(); 22 | loader.setName("bot-list-tab"); 23 | loader.setController(this); 24 | loader.setRoot(this); 25 | loader.load(); 26 | 27 | namespace = loader.getNamespace(); 28 | // root = loader.getRoot(); 29 | 30 | // 프로젝트 목록이 변경될 때마다 목록을 업데이트 함 31 | // 이러면 한 파일이 추가될 때 마다 업데이트 되므로 비효율적이라 폐기함 32 | /* ProjectManager.getList().addListener((ListChangeListener) change -> { 33 | List list = new ArrayList<>(); 34 | ProjectManager.getList().forEach(project -> { 35 | System.out.println(project); 36 | list.add(GUIManager.toListItem(project)); 37 | }); 38 | botView.getItems().setAll(list); 39 | }); */ 40 | } 41 | 42 | @Override 43 | public Node findById(String id) { 44 | return namespace.get(id); 45 | } 46 | 47 | public BotView getBotView() { 48 | return botView; 49 | } 50 | 51 | public static BotListTab getInstance() { 52 | if (instance == null) { 53 | instance = new BotListTab(); 54 | } 55 | return instance; 56 | } 57 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/app/tabs/DetailLogTab.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.app.tabs; 2 | 3 | import javafx.collections.ObservableMap; 4 | import javafx.fxml.FXML; 5 | import javafx.scene.Node; 6 | 7 | import org.beuwi.msgbots.openapi.FormLoader; 8 | import org.beuwi.msgbots.base.impl.View; 9 | import org.beuwi.msgbots.view.gui.control.LogView; 10 | import org.beuwi.msgbots.view.gui.control.TabItem; 11 | 12 | public class DetailLogTab extends TabItem implements View { 13 | private static DetailLogTab instance = null; 14 | 15 | private final ObservableMap namespace; 16 | private final FormLoader loader; 17 | 18 | @FXML 19 | private LogView control; 20 | 21 | private DetailLogTab() { 22 | loader = new FormLoader(); 23 | loader.setName("detail-log-tab"); 24 | loader.setController(this); 25 | loader.setRoot(this); 26 | loader.load(); 27 | 28 | namespace = loader.getNamespace(); 29 | // root = loader.getRoot(); 30 | } 31 | 32 | public LogView getLogView() { 33 | return control; 34 | } 35 | 36 | @Override 37 | public Node findById(String id) { 38 | return namespace.get(id); 39 | } 40 | 41 | public static DetailLogTab getInstance() { 42 | if (instance == null) { 43 | instance = new DetailLogTab(); 44 | } 45 | return instance; 46 | } 47 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/app/tabs/ViewKeymapTab.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.app.tabs; 2 | 3 | import javafx.collections.ObservableMap; 4 | import javafx.fxml.FXML; 5 | import javafx.scene.Node; 6 | import org.beuwi.msgbots.base.impl.View; 7 | import org.beuwi.msgbots.openapi.FormLoader; 8 | import org.beuwi.msgbots.view.gui.control.LogView; 9 | import org.beuwi.msgbots.view.gui.control.TabItem; 10 | 11 | public class ViewKeymapTab extends TabItem implements View { 12 | private static ViewKeymapTab instance = null; 13 | 14 | private final ObservableMap namespace; 15 | private final FormLoader loader; 16 | 17 | @FXML private LogView control; 18 | 19 | private ViewKeymapTab() { 20 | loader = new FormLoader(); 21 | loader.setName("view-keymap-tab"); 22 | loader.setController(this); 23 | loader.setRoot(this); 24 | loader.load(); 25 | 26 | namespace = loader.getNamespace(); 27 | // root = loader.getRoot(); 28 | } 29 | 30 | public LogView getLogView() { 31 | return control; 32 | } 33 | 34 | @Override 35 | public Node findById(String id) { 36 | return namespace.get(id); 37 | } 38 | 39 | public static ViewKeymapTab getInstance() { 40 | if (instance == null) { 41 | instance = new ViewKeymapTab(); 42 | } 43 | return instance; 44 | } 45 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/base/Event.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.base; 2 | 3 | import javafx.beans.value.ObservableValue; 4 | import javafx.scene.Node; 5 | import javafx.scene.layout.Pane; 6 | 7 | public enum Event { 8 | CONTROL_DISABLED, 9 | CONTROL_HOVERED, 10 | CONTROL_FOCUSED /* { 11 | @Override 12 | public String toString() { 13 | return "focused"; 14 | } 15 | }, */, 16 | WIDTH_CHANGED /* { 17 | @Override 18 | public String toString() { 19 | return "resized"; 20 | } 21 | }; */, 22 | HEIGHT_CHANGED, 23 | ID_CHANGED; 24 | 25 | public static ObservableValue toProperty(Node node, Event event) { 26 | ObservableValue property = null; 27 | 28 | switch (event) { 29 | case CONTROL_DISABLED : 30 | property = node.disabledProperty(); 31 | break; 32 | case CONTROL_FOCUSED : 33 | property = node.focusedProperty(); 34 | break; 35 | case CONTROL_HOVERED : 36 | property = node.hoverProperty(); 37 | break; 38 | case WIDTH_CHANGED : 39 | if (node instanceof Pane) { 40 | Pane pane = (Pane) node; 41 | property = pane.widthProperty(); 42 | } 43 | break; 44 | case HEIGHT_CHANGED : 45 | if (node instanceof Pane) { 46 | Pane pane = (Pane) node; 47 | property = pane.heightProperty(); 48 | } 49 | break; 50 | case ID_CHANGED : 51 | property = node.idProperty(); 52 | break; 53 | } 54 | 55 | return property; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/BotView.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control; 2 | 3 | import javafx.collections.ListChangeListener; 4 | import org.beuwi.msgbots.actions.CopyClipboardAction; 5 | import org.beuwi.msgbots.actions.OpenDesktopAction; 6 | import org.beuwi.msgbots.shared.SharedValues; 7 | import org.beuwi.msgbots.view.util.StdActions; 8 | 9 | public class BotView extends ListView { 10 | public BotView() { 11 | new ContextMenu( 12 | StdActions.CREATE_BOT.toMenuItem(), 13 | MenuItem.getSeparator(), 14 | StdActions.SHOW_IN_EXPLORER.handler(event -> { 15 | OpenDesktopAction.getInstance().execute(SharedValues.getFile("file.botFolder")); 16 | }).toMenuItem(), 17 | MenuItem.getSeparator(), 18 | StdActions.COPY_PATH.handler(event -> { 19 | CopyClipboardAction.getInstance().execute(SharedValues.getString("path.botFolder")); 20 | }).toMenuItem(), 21 | StdActions.COPY_RELATIVE_PATH.handler(event -> { 22 | CopyClipboardAction.getInstance().execute(SharedValues.getString("path.botFolder")); 23 | }).toMenuItem() 24 | ).setNode(this); 25 | 26 | getItems().addListener((ListChangeListener) change -> { 27 | while (change.next()) { 28 | for (BotItem item : change.getRemoved()) { 29 | item.setView(null); 30 | } 31 | for (BotItem item : change.getAddedSubList()) { 32 | item.setView(this); 33 | } 34 | } 35 | }); 36 | 37 | addStyleClass("bot-view"); 38 | } 39 | 40 | @Override 41 | public BotItem findById(String name) { 42 | for (BotItem item : getItems()) { 43 | if (item.getName().equals(name)) { 44 | return item; 45 | } 46 | } 47 | return null; 48 | } 49 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/Button.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control; 2 | 3 | import javafx.beans.property.BooleanProperty; 4 | import javafx.beans.property.ObjectProperty; 5 | import javafx.beans.property.SimpleBooleanProperty; 6 | import javafx.beans.property.SimpleObjectProperty; 7 | import javafx.geometry.Insets; 8 | 9 | import org.beuwi.msgbots.view.gui.control.base.ButtonBase; 10 | import org.beuwi.msgbots.view.gui.type.ButtonType; 11 | 12 | public class Button extends ButtonBase { 13 | private final ObjectProperty typeProperty = new SimpleObjectProperty(null); 14 | public final ObjectProperty typeProperty() { 15 | return typeProperty; 16 | } 17 | public void setType(ButtonType type) { 18 | typeProperty.set(type); 19 | } 20 | public ButtonType getType() { 21 | return typeProperty.get(); 22 | } 23 | 24 | private final BooleanProperty styledProperty = new SimpleBooleanProperty(false); 25 | public final BooleanProperty styledProperty() { 26 | return styledProperty; 27 | } 28 | public void setStyled(boolean styled) { 29 | styledProperty.set(styled); 30 | } 31 | public boolean isStyled() { 32 | return styledProperty.get(); 33 | } 34 | 35 | public Button() { 36 | this(null); 37 | } 38 | 39 | public Button(String text) { 40 | if (text != null) { 41 | setText(text); 42 | } 43 | 44 | addChangeListener("styled", change -> { 45 | boolean styled = isStyled(); 46 | 47 | // 기본 타입 지정 48 | setType(ButtonType.ACTION); 49 | 50 | if (styled) { 51 | setMinWidth(50); 52 | setMinHeight(20); 53 | // setPrefWidth(50); 54 | setPrefHeight(25); 55 | } 56 | 57 | setPseudoClass("styled", styled); 58 | }); 59 | 60 | addChangeListener("type", change -> { 61 | ButtonType type = getType(); 62 | setPseudoClass("action", type.equals(ButtonType.ACTION)); 63 | setPseudoClass("cancel", type.equals(ButtonType.CANCEL)); 64 | }); 65 | 66 | // 텍스트가 입력됐으면 여백 값 입력 67 | addChangeListener("text", change -> { 68 | String value = getText(); 69 | if (value != null) { 70 | setPadding(new Insets(0, 10, 0, 10)); 71 | } 72 | }); 73 | 74 | // setType(Type.CANCEL); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/ChatView.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control; 2 | 3 | import javafx.collections.ListChangeListener; 4 | import javafx.scene.control.SelectionMode; 5 | import javafx.scene.input.KeyEvent; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | public class ChatView extends ListView { 11 | public ChatView() { 12 | getItems().addListener((ListChangeListener) change -> { 13 | while (change.next()) { 14 | for (ChatItem item : change.getRemoved()) { 15 | item.setView(null); 16 | } 17 | for (ChatItem item : change.getAddedSubList()) { 18 | item.setView(this); 19 | } 20 | } 21 | }); 22 | 23 | addEventHandler(KeyEvent.KEY_PRESSED, event -> { 24 | if (event.isControlDown()) { 25 | switch (event.getCode()) { 26 | // Copy 27 | case C : 28 | final List chats = new ArrayList<>(); 29 | getSelectedItems().forEach(item -> { 30 | chats.add(item.getMessage()); 31 | }); 32 | // CopyListAction.execute(chats, "\n"); 33 | break; 34 | } 35 | } 36 | }); 37 | 38 | setAutoScroll(true); 39 | // setSelectionMode(SelectionMode.SINGLE); 40 | addStyleClass("chat-view"); 41 | } 42 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/CheckBox.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control; 2 | 3 | import org.beuwi.msgbots.view.gui.control.base.CheckBoxBase; 4 | 5 | public class CheckBox extends CheckBoxBase { 6 | /* { 7 | addStyleClass("check-box"); 8 | } */ 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/ComboBox.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control; 2 | 3 | import javafx.beans.property.ReadOnlyIntegerProperty; 4 | import javafx.beans.property.ReadOnlyObjectProperty; 5 | 6 | import org.beuwi.msgbots.view.gui.control.base.ComboBoxBase; 7 | 8 | public class ComboBox extends ComboBoxBase { 9 | public ComboBox() { 10 | setMinHeight(25); 11 | setPrefWidth(200); 12 | setPrefHeight(25); 13 | // addStyleClass("combo-box"); 14 | } 15 | 16 | public void selectNext() { 17 | getSelectionModel().selectNext(); 18 | } 19 | public void selectPrevious() { 20 | getSelectionModel().selectPrevious(); 21 | } 22 | public void selectItem(T item) { 23 | getSelectionModel().select(item); 24 | } 25 | public void setSelectedItem(T item) { 26 | getSelectionModel().select(item); 27 | } 28 | public T getSelectedItem() { 29 | return getSelectionModel().getSelectedItem(); 30 | } 31 | public int getSelectedIndex() { 32 | return getSelectionModel().getSelectedIndex(); 33 | } 34 | public ReadOnlyObjectProperty selectedItemProperty() { 35 | return getSelectionModel().selectedItemProperty(); 36 | } 37 | public ReadOnlyIntegerProperty selectedIndexProperty() { 38 | return getSelectionModel().selectedIndexProperty(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/Label.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control; 2 | 3 | import javafx.scene.image.Image; 4 | import javafx.scene.image.ImageView; 5 | 6 | import org.beuwi.msgbots.view.gui.control.base.LabelBase; 7 | 8 | public class Label extends LabelBase { 9 | 10 | { 11 | setMaxWidth(Double.MAX_VALUE); 12 | setMaxHeight(Double.MAX_VALUE); 13 | } 14 | 15 | public Label() { 16 | super(); 17 | } 18 | 19 | public Label(String text) { 20 | super(text); 21 | } 22 | 23 | public Label(Image image) { 24 | this(new ImageView(image)); 25 | } 26 | 27 | public Label(ImageView image) { 28 | this.setGraphic(image); 29 | } 30 | 31 | public void setText(Object object) { 32 | super.setText(object.toString()); 33 | } 34 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/LogItem.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control; 2 | 3 | import javafx.css.PseudoClass; 4 | import javafx.fxml.FXML; 5 | import javafx.scene.image.ImageView; 6 | 7 | import org.beuwi.msgbots.base.JObject; 8 | import org.beuwi.msgbots.base.type.LogType; 9 | import org.beuwi.msgbots.openapi.FormLoader; 10 | import org.beuwi.msgbots.view.gui.layout.HBox; 11 | import org.beuwi.msgbots.utils.ResourceUtils; 12 | import org.json.simple.JSONObject; 13 | 14 | public class LogItem extends HBox { 15 | // private static final int DEFAULT_WIDTH = 250; 16 | private static final int DEFAULT_HEIGHT = 30; 17 | 18 | @FXML private ImageView imvIcon; 19 | @FXML private Label lblDate; 20 | // @FXML private Label lblTitle; 21 | @FXML private Label lblText; 22 | 23 | private final FormLoader loader; 24 | // private final ContextMenu menu; 25 | 26 | private LogView parent; 27 | 28 | // JSONOjbect, JObejct 호환 29 | public LogItem(JSON object) { 30 | this( 31 | String.valueOf(object.get("type")), 32 | String.valueOf(object.get("date")), 33 | String.valueOf(object.get("data")) 34 | ); 35 | } 36 | 37 | public LogItem(String type, String date, String data) { 38 | this(LogType.convert(type), date, data); 39 | } 40 | 41 | public LogItem(LogType type, String date, String data) { 42 | loader = new FormLoader(); 43 | loader.setName("log-item-frame"); 44 | loader.setRoot(this); 45 | loader.setController(this); 46 | loader.load(); 47 | 48 | lblDate.setText(date); 49 | // lblDate.setWrapText(true); 50 | 51 | // lblTitle.setText(title); 52 | // lblTitle.setWrapText(true); 53 | lblText.setText(data); 54 | // lblText.setWrapText(true); 55 | 56 | String string = type.toString(); 57 | 58 | imvIcon.setImage(ResourceUtils.getImage(string)); 59 | 60 | setMinHeight(DEFAULT_HEIGHT); 61 | setPseudoClass(string, true); 62 | addStyleClass("log-item"); 63 | } 64 | 65 | public void setView(LogView parent) { 66 | this.parent = parent; 67 | } 68 | 69 | public LogView getView() { 70 | return parent; 71 | } 72 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/MenuBar.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control; 2 | 3 | import javafx.collections.ObservableList; 4 | 5 | import org.beuwi.msgbots.view.gui.layout.HBox; 6 | 7 | public class MenuBar extends HBox { 8 | public MenuBar() { 9 | setFitContent(true); 10 | setMinHeight(20); 11 | setPrefHeight(20); 12 | getStyleClass().add("menu-bar"); 13 | } 14 | 15 | // ListView처럼 동작해야 하므로 getItems로 재선언 16 | public ObservableList getItems() { 17 | return (ObservableList) getChildren(); 18 | } 19 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/MenuButton.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control; 2 | 3 | import javafx.geometry.Insets; 4 | import javafx.scene.control.MenuItem; 5 | 6 | public class MenuButton extends Button { 7 | public MenuButton() { 8 | this(null); 9 | } 10 | 11 | public MenuButton(String text) { 12 | setPadding(new Insets(0, 10, 0, 10)); 13 | setMinWidth(40); 14 | setMinHeight(20); 15 | // setPrefWidth(40); 16 | // setPrefHeight(60); 17 | 18 | if (text != null) { 19 | setText(text); 20 | } 21 | 22 | addStyleClass("menu-button"); 23 | } 24 | 25 | public void setContextMenu(ContextMenu menu) { 26 | menu.setNode(this); 27 | } 28 | 29 | public void setMenuItems(MenuItem... items) { 30 | setContextMenu(new ContextMenu(items)); 31 | } 32 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/MenuItem.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control; 2 | 3 | import javafx.beans.binding.BooleanExpression; 4 | import javafx.beans.value.ObservableValue; 5 | import javafx.event.EventHandler; 6 | import javafx.scene.control.Label; 7 | import javafx.scene.control.SeparatorMenuItem; 8 | import javafx.scene.layout.HBox; 9 | 10 | import org.beuwi.msgbots.keyboard.KeyBinding; 11 | import org.beuwi.msgbots.view.gui.control.base.MenuItemBase; 12 | 13 | public class MenuItem extends MenuItemBase { 14 | public MenuItem(String text, KeyBinding binding, EventHandler handler) { 15 | Label name = new Label(text); 16 | name.setMinWidth(150); 17 | 18 | HBox hbox = new HBox(name); 19 | 20 | setGraphic(hbox); 21 | setOnAction(handler); 22 | 23 | if (binding != null && binding.getKeyCombi() != null) { 24 | setAccelerator(binding.getKeyCombi()); 25 | } 26 | 27 | addStyleClass("menu-item"); 28 | } 29 | 30 | public MenuItem disable(boolean disable) { 31 | setDisable(disable); 32 | return this; 33 | } 34 | public MenuItem disable(ObservableValue property) { 35 | addChangeListener("parentPopup", change1 -> { 36 | ContextMenu parent = getParent(); 37 | if (parent != null) { 38 | parent.addChangeListener("showing", change2 -> { 39 | setDisable(property.getValue()); 40 | }); 41 | } 42 | }); 43 | 44 | return this; 45 | } 46 | 47 | public MenuItem enable(boolean enable) { 48 | setDisable(!enable); 49 | return this; 50 | } 51 | public MenuItem enable(ObservableValue property) { 52 | addChangeListener("parentPopup", change1 -> { 53 | ContextMenu parent = getParent(); 54 | if (parent != null) { 55 | parent.addChangeListener("showing", change2 -> { 56 | setDisable(!property.getValue()); 57 | }); 58 | } 59 | }); 60 | return this; 61 | } 62 | 63 | public ContextMenu getParent() { 64 | return (ContextMenu) getParentPopup(); 65 | } 66 | 67 | public static SeparatorMenuItem getSeparator() { 68 | return new SeparatorMenuItem(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/NaviItem.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control; 2 | 3 | import javafx.beans.property.StringProperty; 4 | import javafx.geometry.Insets; 5 | import javafx.scene.Node; 6 | import javafx.scene.layout.Pane; 7 | import javafx.scene.layout.Priority; 8 | 9 | import org.beuwi.msgbots.view.gui.control.base.TabItemBase; 10 | import org.beuwi.msgbots.view.gui.layout.HBox; 11 | 12 | public class NaviItem extends TabItemBase { 13 | // private static final int DEFAULT_ITEM_WIDTH = 150; 14 | // private static final int DEFAULT_ITEM_HEIGHT = 30; 15 | // private static final Pos DEFAULT_HEADER_ALIGNMENT = Pos.CENTER; 16 | 17 | private final HBox header = new HBox(); 18 | private final Label label = new Label(); 19 | 20 | { 21 | HBox.setHgrow(label, Priority.ALWAYS); 22 | } 23 | 24 | public NaviItem() { 25 | this(null); 26 | } 27 | public NaviItem(String title) { 28 | this(title, new Pane()); 29 | } 30 | public NaviItem(String title, Node content) { 31 | if (title != null) { 32 | setId(title); 33 | setText(title); 34 | } 35 | 36 | if (content != null) { 37 | setContent(content); 38 | } 39 | setId(title); 40 | setHeader(header); 41 | 42 | // label.setText(control.getText()); 43 | // label.setAlignment(Pos.CENTER); 44 | label.addStyleClass("text-label"); 45 | header.addStyleClass("header"); 46 | header.initChildren(label); 47 | 48 | addChangeListener("text", change -> { 49 | this.setId(getText()); 50 | label.setText(getText()); 51 | }); 52 | 53 | // 헤더 관련 옵션 54 | setPadding(new Insets(0, 10, 0, 10)); 55 | // 너비 강제 지정 56 | // setMinWidth(150); 57 | // setPrefWidth(150); 58 | // setMaxWidth(150); 59 | // 높이 강제 지정 60 | setMinHeight(30); 61 | setPrefHeight(30); 62 | setMaxHeight(30); 63 | addStyleClass("navi-item"); 64 | } 65 | 66 | public void setText(String text) { 67 | label.setText(text); 68 | } 69 | public String getText() { 70 | return label.getText(); 71 | } 72 | 73 | public StringProperty textProperty() { 74 | return label.textProperty(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/NaviView.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control; 2 | 3 | import javafx.geometry.Side; 4 | 5 | import org.beuwi.msgbots.view.gui.control.base.TabViewBase; 6 | import org.beuwi.msgbots.view.gui.layout.StackPane; 7 | 8 | public class NaviView extends TabViewBase { 9 | private final ListView header = getHeaderArea(); 10 | private final StackPane content = getContentArea(); 11 | 12 | public NaviView() { 13 | this(null); 14 | } 15 | 16 | public NaviView(NaviItem... items) { 17 | super(items); 18 | 19 | header.setMinWidth(150); 20 | header.setPrefWidth(150); 21 | header.setMaxWidth(150); 22 | 23 | setSide(Side.LEFT); 24 | // setMargin(150); 25 | setPrefWidth(500); 26 | setPrefHeight(600); 27 | addStyleClass("navi-view"); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/ScrollView.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control; 2 | 3 | import javafx.beans.property.BooleanProperty; 4 | import javafx.beans.property.SimpleBooleanProperty; 5 | import javafx.scene.Node; 6 | import javafx.scene.input.ScrollEvent; 7 | import javafx.scene.layout.Pane; 8 | 9 | import org.beuwi.msgbots.view.gui.control.base.ScrollViewBase; 10 | 11 | public class ScrollView extends ScrollViewBase { 12 | private static final double SCROLL_SPEED = 0.005; 13 | 14 | public ScrollView() { 15 | this(null); 16 | } 17 | 18 | public ScrollView(Node node) { 19 | if (node != null) { 20 | setContent(node); 21 | } 22 | 23 | addChangeListener("content", change1 -> { 24 | Node content = getContent(); 25 | if (content != null) { 26 | if (content instanceof Pane pane) { 27 | // 자동 스크롤이 켜져 있다면 제일 아래로 스크롤 되도록 28 | addChangeListener(getFXProperty(pane, "height"), change2 -> { 29 | if (isAutoScroll()) { 30 | setVvalue(1.0d); 31 | } 32 | }); 33 | } 34 | } 35 | }); 36 | 37 | addEventFilter(ScrollEvent.SCROLL, event -> { 38 | setHvalue(getHvalue() - (event.getDeltaY() * SCROLL_SPEED)); 39 | setVvalue(getVvalue() - (event.getDeltaY() * SCROLL_SPEED)); 40 | }); 41 | 42 | setFitToWidth(true); 43 | setFitToHeight(true); 44 | addStyleClass("scroll-pane"); 45 | } 46 | 47 | // 해당 프로펄티가 활성화일 때는 자동으로 마지막 아이템으로 스크롤 함. 48 | private final BooleanProperty autoScrollProperty = new SimpleBooleanProperty(); 49 | public final BooleanProperty autoScrollProperty() { 50 | return autoScrollProperty; 51 | } 52 | public void setAutoScroll(boolean value) { 53 | autoScrollProperty.set(value); 54 | } 55 | public boolean isAutoScroll() { 56 | return autoScrollProperty.get(); 57 | } 58 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/Separator.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control; 2 | 3 | import org.beuwi.msgbots.view.gui.control.base.SeparatorBase; 4 | 5 | public class Separator extends SeparatorBase { 6 | public Separator() { 7 | // addStyleClass("separator"); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/Slider.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control; 2 | 3 | import javafx.beans.property.DoubleProperty; 4 | import javafx.scene.layout.Priority; 5 | import org.beuwi.msgbots.view.gui.layout.HBox; 6 | 7 | // 우측에 값 표시를 위해 이런 방식으로 구현함 8 | public class Slider extends HBox { 9 | private final javafx.scene.control.Slider slider = new javafx.scene.control.Slider(); 10 | private final Label label = new Label(); 11 | 12 | { 13 | HBox.setHgrow(slider, Priority.ALWAYS); 14 | } 15 | 16 | public Slider() { 17 | slider.setSnapToTicks(true); 18 | slider.setMajorTickUnit(1); 19 | slider.setMinorTickCount(0); 20 | slider.setBlockIncrement(1); 21 | slider.setShowTickMarks(false); 22 | slider.setShowTickLabels(false); 23 | 24 | setSpacing(10); 25 | // setText(Math.floor(getValue())); 26 | valueProperty().addListener(change -> { 27 | // 소수점 안보이도록 28 | setValue(Math.round(getValue())); 29 | }); 30 | 31 | setValue(Math.round(getValue())); 32 | initChildren(slider, label); 33 | // addStyleClass("slider"); 34 | } 35 | 36 | public void setMin(double value) { 37 | slider.setMin(value); 38 | } 39 | public void setMax(double value) { 40 | slider.setMax(value); 41 | } 42 | public void setValue(double value) { 43 | slider.setValue(value); 44 | label.setText(value); 45 | } 46 | 47 | public double getMin() { 48 | return slider.getMin(); 49 | } 50 | public double getMax() { 51 | return slider.getMax(); 52 | } 53 | public double getValue() { 54 | return slider.getValue(); 55 | } 56 | 57 | public DoubleProperty valueProperty() { 58 | return slider.valueProperty(); 59 | } 60 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/TabView.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control; 2 | 3 | import javafx.beans.property.BooleanProperty; 4 | import javafx.beans.property.SimpleBooleanProperty; 5 | import javafx.geometry.Side; 6 | 7 | import org.beuwi.msgbots.view.gui.control.base.TabViewBase; 8 | import org.beuwi.msgbots.view.gui.layout.StackPane; 9 | 10 | public class TabView extends TabViewBase { 11 | // 원래는 헤더 높이를 강제했었으나, Border 같은 내부 길이가 길어지는 스타일 적용 시 12 | // 스크롤 바가 생기는 등 까다로운 조건이 발생해서, 그냥 헤더 넓이는 탭 헤더에 따라 알아서 적용되도록 내둠 13 | private final ListView header = getHeaderArea(); 14 | private final StackPane content = getContentArea(); 15 | 16 | public TabView() { 17 | this(null); 18 | } 19 | 20 | public TabView(TabItem... tabs) { 21 | super(tabs); 22 | 23 | header.setMinHeight(30); // 헤더 영역 높이 강제 24 | header.setMaxHeight(30); // 헤더 영역 높이 강제 25 | 26 | addChangeListener("fitHeader", change -> { 27 | header.setFitWidth(isFitHeader()); 28 | header.setFitHeight(isFitHeader()); 29 | }); 30 | 31 | setSide(Side.TOP); 32 | // setPrefWidth(500); 33 | // setPrefHeight(600); 34 | addStyleClass("tab-view"); 35 | } 36 | 37 | // 말 그대로 뷰를 토글할 수 있는 기능이고, 38 | // 두 번 같은 탭을 누르면 닫히고 다른 탭을 누르면 열림 39 | /* private final BooleanProperty togglableProperty = new SimpleBooleanProperty(); 40 | public void setTogglable(boolean value) { 41 | togglableProperty.set(value); 42 | } 43 | public boolean isTogglable() { 44 | return togglableProperty.get(); 45 | } 46 | public BooleanProperty togglableProperty() { 47 | return togglableProperty; 48 | } */ 49 | 50 | // 해당 옵션을 활성화 하면 탭 아이템의 헤더 너비가 꽉 채워짐 51 | // EX : [[Header] ] 에서 [[ Header ]] 52 | private final BooleanProperty fitHeaderProperty = new SimpleBooleanProperty(); 53 | public final BooleanProperty fitHeaderProperty() { 54 | return fitHeaderProperty; 55 | } 56 | public void setFitHeader(boolean value) { 57 | fitHeaderProperty.set(value); 58 | } 59 | public boolean isFitHeader() { 60 | return fitHeaderProperty.get(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/TextArea.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control; 2 | 3 | import org.beuwi.msgbots.view.gui.control.base.TextAreaBase; 4 | import org.beuwi.msgbots.view.util.StdActions; 5 | 6 | public class TextArea extends TextAreaBase { 7 | public TextArea() { 8 | this(null); 9 | } 10 | 11 | public TextArea(String text) { 12 | if (text != null) { 13 | setText(text); 14 | } 15 | 16 | setContextMenu(new ContextMenu( 17 | StdActions.UNDO.handler(event -> undo()).toMenuItem(), 18 | StdActions.REDO.handler(event -> redo()).toMenuItem(), 19 | MenuItem.getSeparator(), 20 | StdActions.CUT.handler(event -> cut()).toMenuItem(), 21 | StdActions.COPY.handler(event -> copy()).toMenuItem(), 22 | StdActions.PASTE.handler(event -> paste()).toMenuItem(), 23 | MenuItem.getSeparator(), 24 | StdActions.SELECT_ALL.handler(event -> selectAll()).toMenuItem() 25 | )); 26 | 27 | setPrefHeight(200); 28 | setPrefHeight(50); 29 | } 30 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/TextField.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control; 2 | 3 | import org.beuwi.msgbots.view.gui.control.base.TextFieldBase; 4 | import org.beuwi.msgbots.view.util.StdActions; 5 | 6 | public class TextField extends TextFieldBase { 7 | public TextField() { 8 | this(null); 9 | } 10 | 11 | public TextField(String text) { 12 | if (text != null) { 13 | setText(text); 14 | } 15 | 16 | setContextMenu(new ContextMenu( 17 | StdActions.UNDO.handler(event -> undo()).toMenuItem(), 18 | StdActions.REDO.handler(event -> redo()).toMenuItem(), 19 | MenuItem.getSeparator(), 20 | StdActions.CUT.handler(event -> cut()).toMenuItem(), 21 | StdActions.COPY.handler(event -> copy()).toMenuItem(), 22 | StdActions.PASTE.handler(event -> paste()).toMenuItem(), 23 | MenuItem.getSeparator(), 24 | StdActions.SELECT_ALL.handler(event -> selectAll()).toMenuItem() 25 | )); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/ToastView.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control; 2 | 3 | import javafx.beans.property.ObjectProperty; 4 | import javafx.beans.property.SimpleObjectProperty; 5 | import javafx.beans.value.ChangeListener; 6 | import javafx.collections.ListChangeListener; 7 | import javafx.collections.ObservableList; 8 | import javafx.css.PseudoClass; 9 | 10 | import org.beuwi.msgbots.view.gui.layout.VBox; 11 | 12 | // 원래는 리스트 뷰를 사용하는게 맞으나 높이 문제로 인해 "VBox" 사용 13 | public class ToastView extends VBox { 14 | 15 | public ToastView() { 16 | getItems().addListener((ListChangeListener) change -> { 17 | for (ToastItem toast : getItems()) { 18 | toast.setView(this); 19 | } 20 | 21 | // 아이템이 없으면 안보이도록 22 | // setVisible(!getChildren().isEmpty()); 23 | }); 24 | 25 | addChangeListener("selectedItem", (ChangeListener) (observable, oldItem, newItem) -> { 26 | if (oldItem != null) { 27 | oldItem.setPseudoClass("selected", false); 28 | } 29 | if (newItem != null) { 30 | newItem.setPseudoClass("selected", false); 31 | } 32 | }); 33 | 34 | // setVisible(false); 35 | // setSpacing(10); 36 | setPrefWidth(500); 37 | // setMinHeight(50); 38 | setMaxHeight(Double.MAX_VALUE); 39 | // setPrefHeight(500); 40 | 41 | addStyleClass("toast-view"); 42 | } 43 | 44 | // ListView처럼 동작해야 하므로 getItems로 재선언 45 | public ObservableList getItems() { 46 | return (ObservableList) getChildren(); 47 | } 48 | 49 | public void selectItem(ToastItem item) { 50 | setSelectedItem(item); 51 | } 52 | 53 | private final ObjectProperty selectedItemProperty = new SimpleObjectProperty(null); 54 | public ObjectProperty selectedItemProperty() { 55 | return selectedItemProperty; 56 | } 57 | public void setSelectedItem(ToastItem item) { 58 | selectedItemProperty.set(item); 59 | } 60 | public ToastItem getSelectedItem() { 61 | return selectedItemProperty.get(); 62 | } 63 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/ToggleButton.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control; 2 | 3 | import org.beuwi.msgbots.view.gui.control.base.ToggleButtonBase; 4 | 5 | public class ToggleButton extends ToggleButtonBase { 6 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/WebPage.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control; 2 | 3 | import javafx.concurrent.Worker; 4 | import javafx.scene.web.WebEngine; 5 | 6 | import org.beuwi.msgbots.view.gui.layout.WebPane; 7 | import org.beuwi.msgbots.utils.ResourceUtils; 8 | 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | 12 | // Sun 내부에 있는 "net...sun..WebPage"와 다름 13 | public class WebPage extends WebPane { 14 | // [WebPage]는 하나의 페이지(HTML)에 하나만 존재할 수 있음 15 | private static final Map created = new HashMap<>(); 16 | 17 | private final WebEngine engine; 18 | private final Worker worker; 19 | 20 | /* public Page() { 21 | this(null); 22 | } */ 23 | 24 | // Not Null 25 | private WebPage(String name) { 26 | engine = getWebEngine(); 27 | worker = getLoadWorker(); 28 | 29 | loadHtml(ResourceUtils.getHtml(name)); 30 | 31 | // JLINK 패키징 시 경로 에러가 나므로 사용 안함 32 | /* engine.setUserStyleSheetLocation( 33 | ResourceUtils.getWebStyle(theme) 34 | ); */ 35 | addStyleClass("web-page"); 36 | } 37 | 38 | public static WebPage getPage(String name) { 39 | if (!created.containsKey(name)) { 40 | created.put(name, new WebPage(name)); 41 | } 42 | return created.get(name); 43 | } 44 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/base/ButtonBase.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control.base; 2 | 3 | import javafx.beans.InvalidationListener; 4 | import javafx.beans.value.ChangeListener; 5 | import javafx.beans.value.ObservableValue; 6 | import javafx.scene.Node; 7 | 8 | import org.beuwi.msgbots.view.gui.base.Control; 9 | 10 | public class ButtonBase extends javafx.scene.control.Button implements Control { 11 | @Override public void setPseudoClass(String pseudo, boolean active) { setPseudoClass(this, pseudo, active); } 12 | 13 | @Override public

ObservableValue

getFXProperty(String name) { return getFXProperty(this, name); } 14 | 15 | @Override public void addChangeListener(String property, ChangeListener listener) { addChangeListener(getFXProperty(property), listener); } 16 | @Override public void addChangeListener(String property, InvalidationListener listener) { addChangeListener(getFXProperty(property), listener); } 17 | @Override public void removeChangeListener(String property, ChangeListener listener) { removeChangeListener(getFXProperty(property), listener); } 18 | @Override public void removeChangeListener(String property, InvalidationListener listener) { removeChangeListener(getFXProperty(property), listener); } 19 | 20 | @Override public Node findById(String id) { return findById(this, id); } 21 | 22 | @Override public void addStyleClass(String... style) { addStyleClass(this, style); } 23 | @Override public void addStyleClass(int index, String style) { addStyleClass(this, index, style); } 24 | @Override public void setStyleClass(int index, String style) { setStyleClass(this, index, style); } 25 | @Override public void initStyleClass(String... style) { initStyleClass(this, style); } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/base/CheckBoxBase.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control.base; 2 | 3 | import javafx.beans.InvalidationListener; 4 | import javafx.beans.value.ChangeListener; 5 | import javafx.beans.value.ObservableValue; 6 | import javafx.scene.Node; 7 | 8 | import org.beuwi.msgbots.view.gui.base.Control; 9 | 10 | public class CheckBoxBase extends javafx.scene.control.CheckBox implements Control { 11 | @Override public void setPseudoClass(String pseudo, boolean active) { setPseudoClass(this, pseudo, active); } 12 | 13 | @Override public

ObservableValue

getFXProperty(String name) { return getFXProperty(this, name); } 14 | 15 | @Override public void addChangeListener(String property, ChangeListener listener) { addChangeListener(getFXProperty(property), listener); } 16 | @Override public void addChangeListener(String property, InvalidationListener listener) { addChangeListener(getFXProperty(property), listener); } 17 | @Override public void removeChangeListener(String property, ChangeListener listener) { removeChangeListener(getFXProperty(property), listener); } 18 | @Override public void removeChangeListener(String property, InvalidationListener listener) { removeChangeListener(getFXProperty(property), listener); } 19 | 20 | @Override public Node findById(String id) { return findById(this, id); } 21 | 22 | @Override public void addStyleClass(String... style) { addStyleClass(this, style); } 23 | @Override public void addStyleClass(int index, String style) { addStyleClass(this, index, style); } 24 | @Override public void setStyleClass(int index, String style) { setStyleClass(this, index, style); } 25 | @Override public void initStyleClass(String... style) { initStyleClass(this, style); } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/base/ComboBoxBase.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control.base; 2 | 3 | import javafx.beans.InvalidationListener; 4 | import javafx.beans.value.ChangeListener; 5 | import javafx.beans.value.ObservableValue; 6 | import javafx.scene.Node; 7 | 8 | import org.beuwi.msgbots.view.gui.base.Control; 9 | 10 | public class ComboBoxBase extends javafx.scene.control.ComboBox implements Control { 11 | @Override public void setPseudoClass(String pseudo, boolean active) { setPseudoClass(this, pseudo, active); } 12 | 13 | @Override public

ObservableValue

getFXProperty(String name) { return getFXProperty(this, name); } 14 | 15 | @Override public void addChangeListener(String property, ChangeListener listener) { addChangeListener(getFXProperty(property), listener); } 16 | @Override public void addChangeListener(String property, InvalidationListener listener) { addChangeListener(getFXProperty(property), listener); } 17 | @Override public void removeChangeListener(String property, ChangeListener listener) { removeChangeListener(getFXProperty(property), listener); } 18 | @Override public void removeChangeListener(String property, InvalidationListener listener) { removeChangeListener(getFXProperty(property), listener); } 19 | 20 | @Override public Node findById(String id) { return findById(this, id); } 21 | 22 | @Override public void addStyleClass(String... style) { addStyleClass(this, style); } 23 | @Override public void addStyleClass(int index, String style) { addStyleClass(this, index, style); } 24 | @Override public void setStyleClass(int index, String style) { setStyleClass(this, index, style); } 25 | @Override public void initStyleClass(String... style) { initStyleClass(this, style); } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/base/LabelBase.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control.base; 2 | 3 | import javafx.beans.InvalidationListener; 4 | import javafx.beans.value.ChangeListener; 5 | import javafx.beans.value.ObservableValue; 6 | import javafx.scene.Node; 7 | 8 | import org.beuwi.msgbots.view.gui.base.Control; 9 | 10 | public class LabelBase extends javafx.scene.control.Label implements Control { 11 | @Override public void setPseudoClass(String pseudo, boolean active) { setPseudoClass(this, pseudo, active); } 12 | 13 | @Override public

ObservableValue

getFXProperty(String name) { return getFXProperty(this, name); } 14 | 15 | @Override public void addChangeListener(String property, ChangeListener listener) { addChangeListener(getFXProperty(property), listener); } 16 | @Override public void addChangeListener(String property, InvalidationListener listener) { addChangeListener(getFXProperty(property), listener); } 17 | @Override public void removeChangeListener(String property, ChangeListener listener) { removeChangeListener(getFXProperty(property), listener); } 18 | @Override public void removeChangeListener(String property, InvalidationListener listener) { removeChangeListener(getFXProperty(property), listener); } 19 | 20 | @Override public Node findById(String id) { return findById(this, id); } 21 | 22 | @Override public void addStyleClass(String... style) { addStyleClass(this, style); } 23 | @Override public void addStyleClass(int index, String style) { addStyleClass(this, index, style); } 24 | @Override public void setStyleClass(int index, String style) { setStyleClass(this, index, style); } 25 | @Override public void initStyleClass(String... style) { initStyleClass(this, style); } 26 | 27 | public LabelBase() { 28 | super(); 29 | } 30 | 31 | public LabelBase(String text) { 32 | super(text); 33 | } 34 | 35 | public LabelBase(String text, Node graphic) { 36 | super(text, graphic); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/base/MenuItemBase.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control.base; 2 | 3 | import javafx.beans.InvalidationListener; 4 | import javafx.beans.value.ChangeListener; 5 | import javafx.beans.value.ObservableValue; 6 | import javafx.scene.Node; 7 | 8 | import org.beuwi.msgbots.view.gui.base.Control; 9 | 10 | public class MenuItemBase extends javafx.scene.control.MenuItem implements Control { 11 | @Override public void setPseudoClass(String pseudo, boolean active) { setPseudoClass(this, pseudo, active); } 12 | 13 | @Override public

ObservableValue

getFXProperty(String name) { return getFXProperty(this, name); } 14 | 15 | @Override public void addChangeListener(String property, ChangeListener listener) { addChangeListener(getFXProperty(property), listener); } 16 | @Override public void addChangeListener(String property, InvalidationListener listener) { addChangeListener(getFXProperty(property), listener); } 17 | @Override public void removeChangeListener(String property, ChangeListener listener) { removeChangeListener(getFXProperty(property), listener); } 18 | @Override public void removeChangeListener(String property, InvalidationListener listener) { removeChangeListener(getFXProperty(property), listener); } 19 | 20 | @Override public Node findById(String id) { return findById(this, id); } 21 | 22 | @Override public void addStyleClass(String... style) { addStyleClass(this, style); } 23 | @Override public void addStyleClass(int index, String style) { addStyleClass(this, index, style); } 24 | @Override public void setStyleClass(int index, String style) { setStyleClass(this, index, style); } 25 | @Override public void initStyleClass(String... style) { initStyleClass(this, style); } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/base/SVGGlyphBase.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control.base; 2 | 3 | import javafx.beans.InvalidationListener; 4 | import javafx.beans.value.ChangeListener; 5 | import javafx.beans.value.ObservableValue; 6 | import javafx.scene.Node; 7 | 8 | import org.beuwi.msgbots.view.gui.base.Control; 9 | 10 | public class SVGGlyphBase extends javafx.scene.layout.Pane implements Control { 11 | @Override public void setPseudoClass(String pseudo, boolean active) { setPseudoClass(this, pseudo, active); } 12 | 13 | @Override public

ObservableValue

getFXProperty(String name) { return getFXProperty(this, name); } 14 | 15 | @Override public void addChangeListener(String property, ChangeListener listener) { addChangeListener(getFXProperty(property), listener); } 16 | @Override public void addChangeListener(String property, InvalidationListener listener) { addChangeListener(getFXProperty(property), listener); } 17 | @Override public void removeChangeListener(String property, ChangeListener listener) { removeChangeListener(getFXProperty(property), listener); } 18 | @Override public void removeChangeListener(String property, InvalidationListener listener) { removeChangeListener(getFXProperty(property), listener); } 19 | 20 | @Override public Node findById(String id) { return findById(this, id); } 21 | 22 | @Override public void addStyleClass(String... style) { addStyleClass(this, style); } 23 | @Override public void addStyleClass(int index, String style) { addStyleClass(this, index, style); } 24 | @Override public void setStyleClass(int index, String style) { setStyleClass(this, index, style); } 25 | @Override public void initStyleClass(String... style) { initStyleClass(this, style); } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/base/ScrollViewBase.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control.base; 2 | 3 | import javafx.beans.InvalidationListener; 4 | import javafx.beans.value.ChangeListener; 5 | import javafx.beans.value.ObservableValue; 6 | import javafx.scene.Node; 7 | 8 | import org.beuwi.msgbots.view.gui.base.Control; 9 | 10 | public class ScrollViewBase extends javafx.scene.control.ScrollPane implements Control { 11 | @Override public void setPseudoClass(String pseudo, boolean active) { setPseudoClass(this, pseudo, active); } 12 | 13 | @Override public

ObservableValue

getFXProperty(String name) { return getFXProperty(this, name); } 14 | 15 | @Override public void addChangeListener(String property, ChangeListener listener) { addChangeListener(getFXProperty(property), listener); } 16 | @Override public void addChangeListener(String property, InvalidationListener listener) { addChangeListener(getFXProperty(property), listener); } 17 | @Override public void removeChangeListener(String property, ChangeListener listener) { removeChangeListener(getFXProperty(property), listener); } 18 | @Override public void removeChangeListener(String property, InvalidationListener listener) { removeChangeListener(getFXProperty(property), listener); } 19 | 20 | @Override public Node findById(String id) { return findById(this, id); } 21 | 22 | @Override public void addStyleClass(String... style) { addStyleClass(this, style); } 23 | @Override public void addStyleClass(int index, String style) { addStyleClass(this, index, style); } 24 | @Override public void setStyleClass(int index, String style) { setStyleClass(this, index, style); } 25 | @Override public void initStyleClass(String... style) { initStyleClass(this, style); } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/base/SeparatorBase.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control.base; 2 | 3 | import javafx.beans.InvalidationListener; 4 | import javafx.beans.value.ChangeListener; 5 | import javafx.beans.value.ObservableValue; 6 | import javafx.scene.Node; 7 | import org.beuwi.msgbots.view.gui.base.Control; 8 | 9 | public class SeparatorBase extends javafx.scene.control.Separator implements Control { 10 | @Override public void setPseudoClass(String pseudo, boolean active) { setPseudoClass(this, pseudo, active); } 11 | 12 | @Override public

ObservableValue

getFXProperty(String name) { return getFXProperty(this, name); } 13 | 14 | @Override public void addChangeListener(String property, ChangeListener listener) { addChangeListener(getFXProperty(property), listener); } 15 | @Override public void addChangeListener(String property, InvalidationListener listener) { addChangeListener(getFXProperty(property), listener); } 16 | @Override public void removeChangeListener(String property, ChangeListener listener) { removeChangeListener(getFXProperty(property), listener); } 17 | @Override public void removeChangeListener(String property, InvalidationListener listener) { removeChangeListener(getFXProperty(property), listener); } 18 | 19 | @Override public Node findById(String id) { return findById(this, id); } 20 | 21 | @Override public void addStyleClass(String... style) { addStyleClass(this, style); } 22 | @Override public void addStyleClass(int index, String style) { addStyleClass(this, index, style); } 23 | @Override public void setStyleClass(int index, String style) { setStyleClass(this, index, style); } 24 | @Override public void initStyleClass(String... style) { initStyleClass(this, style); } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/base/SplitViewBase.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control.base; 2 | 3 | import javafx.beans.InvalidationListener; 4 | import javafx.beans.value.ChangeListener; 5 | import javafx.beans.value.ObservableValue; 6 | import javafx.scene.Node; 7 | 8 | import org.beuwi.msgbots.view.gui.base.Control; 9 | 10 | public class SplitViewBase extends javafx.scene.control.SplitPane implements Control { 11 | @Override public void setPseudoClass(String pseudo, boolean active) { setPseudoClass(this, pseudo, active); } 12 | 13 | @Override public

ObservableValue

getFXProperty(String name) { return getFXProperty(this, name); } 14 | 15 | @Override public void addChangeListener(String property, ChangeListener listener) { addChangeListener(getFXProperty(property), listener); } 16 | @Override public void addChangeListener(String property, InvalidationListener listener) { addChangeListener(getFXProperty(property), listener); } 17 | @Override public void removeChangeListener(String property, ChangeListener listener) { removeChangeListener(getFXProperty(property), listener); } 18 | @Override public void removeChangeListener(String property, InvalidationListener listener) { removeChangeListener(getFXProperty(property), listener); } 19 | 20 | @Override public Node findById(String id) { return findById(this, id); } 21 | 22 | @Override public void addStyleClass(String... style) { addStyleClass(this, style); } 23 | @Override public void addStyleClass(int index, String style) { addStyleClass(this, index, style); } 24 | @Override public void setStyleClass(int index, String style) { setStyleClass(this, index, style); } 25 | @Override public void initStyleClass(String... style) { initStyleClass(this, style); } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/base/TextAreaBase.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control.base; 2 | 3 | import javafx.beans.InvalidationListener; 4 | import javafx.beans.value.ChangeListener; 5 | import javafx.beans.value.ObservableValue; 6 | import javafx.scene.Node; 7 | 8 | import org.beuwi.msgbots.view.gui.base.Control; 9 | 10 | public class TextAreaBase extends javafx.scene.control.TextArea implements Control { 11 | @Override public void setPseudoClass(String pseudo, boolean active) { setPseudoClass(this, pseudo, active); } 12 | 13 | @Override public

ObservableValue

getFXProperty(String name) { return getFXProperty(this, name); } 14 | 15 | @Override public void addChangeListener(String property, ChangeListener listener) { addChangeListener(getFXProperty(property), listener); } 16 | @Override public void addChangeListener(String property, InvalidationListener listener) { addChangeListener(getFXProperty(property), listener); } 17 | @Override public void removeChangeListener(String property, ChangeListener listener) { removeChangeListener(getFXProperty(property), listener); } 18 | @Override public void removeChangeListener(String property, InvalidationListener listener) { removeChangeListener(getFXProperty(property), listener); } 19 | 20 | @Override public Node findById(String id) { return findById(this, id); } 21 | 22 | @Override public void addStyleClass(String... style) { addStyleClass(this, style); } 23 | @Override public void addStyleClass(int index, String style) { addStyleClass(this, index, style); } 24 | @Override public void setStyleClass(int index, String style) { setStyleClass(this, index, style); } 25 | @Override public void initStyleClass(String... style) { initStyleClass(this, style); } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/base/TextFieldBase.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control.base; 2 | 3 | import javafx.beans.InvalidationListener; 4 | import javafx.beans.value.ChangeListener; 5 | import javafx.beans.value.ObservableValue; 6 | import javafx.scene.Node; 7 | 8 | import org.beuwi.msgbots.view.gui.base.Control; 9 | 10 | public class TextFieldBase extends javafx.scene.control.TextField implements Control { 11 | @Override public void setPseudoClass(String pseudo, boolean active) { setPseudoClass(this, pseudo, active); } 12 | 13 | @Override public

ObservableValue

getFXProperty(String name) { return getFXProperty(this, name); } 14 | 15 | @Override public void addChangeListener(String property, ChangeListener listener) { addChangeListener(getFXProperty(property), listener); } 16 | @Override public void addChangeListener(String property, InvalidationListener listener) { addChangeListener(getFXProperty(property), listener); } 17 | @Override public void removeChangeListener(String property, ChangeListener listener) { removeChangeListener(getFXProperty(property), listener); } 18 | @Override public void removeChangeListener(String property, InvalidationListener listener) { removeChangeListener(getFXProperty(property), listener); } 19 | 20 | @Override public Node findById(String id) { return findById(this, id); } 21 | 22 | @Override public void addStyleClass(String... style) { addStyleClass(this, style); } 23 | @Override public void addStyleClass(int index, String style) { addStyleClass(this, index, style); } 24 | @Override public void setStyleClass(int index, String style) { setStyleClass(this, index, style); } 25 | @Override public void initStyleClass(String... style) { initStyleClass(this, style); } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/control/base/ToggleButtonBase.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.control.base; 2 | 3 | import javafx.beans.InvalidationListener; 4 | import javafx.beans.value.ChangeListener; 5 | import javafx.beans.value.ObservableValue; 6 | import javafx.scene.Node; 7 | import org.beuwi.msgbots.view.gui.base.Control; 8 | 9 | public class ToggleButtonBase extends javafx.scene.control.ToggleButton implements Control { 10 | @Override public void setPseudoClass(String pseudo, boolean active) { setPseudoClass(this, pseudo, active); } 11 | 12 | @Override public

ObservableValue

getFXProperty(String name) { return getFXProperty(this, name); } 13 | 14 | @Override public void addChangeListener(String property, ChangeListener listener) { addChangeListener(getFXProperty(property), listener); } 15 | @Override public void addChangeListener(String property, InvalidationListener listener) { addChangeListener(getFXProperty(property), listener); } 16 | @Override public void removeChangeListener(String property, ChangeListener listener) { removeChangeListener(getFXProperty(property), listener); } 17 | @Override public void removeChangeListener(String property, InvalidationListener listener) { removeChangeListener(getFXProperty(property), listener); } 18 | 19 | @Override public Node findById(String id) { return findById(this, id); } 20 | 21 | @Override public void addStyleClass(String... style) { addStyleClass(this, style); } 22 | @Override public void addStyleClass(int index, String style) { addStyleClass(this, index, style); } 23 | @Override public void setStyleClass(int index, String style) { setStyleClass(this, index, style); } 24 | @Override public void initStyleClass(String... style) { initStyleClass(this, style); } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/dialog/ShowPaneDialog.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.dialog; 2 | 3 | import org.beuwi.msgbots.view.gui.type.DialogType; 4 | import org.beuwi.msgbots.view.gui.dialog.base.DialogWrapper; 5 | 6 | public abstract class ShowPaneDialog extends DialogWrapper { 7 | // private final String title; 8 | // private final Node content; 9 | 10 | // Default : 400, 500 11 | public ShowPaneDialog() { 12 | super(DialogType.NONE); 13 | 14 | // this.title = title; 15 | // this.content = content; 16 | 17 | // root.setPrefWidth(400); 18 | // root.setPrefHeight(width); 19 | /* if (content != null) { 20 | setContent(content); 21 | } */ 22 | setMargin(0); 23 | setUseFooterBar(false); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/dialog/ViewIconDialog.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.dialog; 2 | 3 | import org.beuwi.msgbots.view.gui.dialog.base.DialogWrapper; 4 | 5 | public abstract class ViewIconDialog extends DialogWrapper { 6 | /* private final ObservableMap namespace; 7 | private final FormLoader loader; 8 | private final BorderPane root; 9 | 10 | @FXML private BorderPane brpBoxRoot; 11 | @FXML private ImageView imvBoxIcon; 12 | @FXML private StackPane stpBoxMain; 13 | 14 | public ViewIconDialog(BoxType type) { 15 | loader = new FormLoader("dialog", "yes-or-no-dialog", this); 16 | namespace = loader.getNamespace(); 17 | root = loader.getRoot(); 18 | 19 | switch (type) { 20 | case INFO : imvBoxIcon.setImage(ResourceUtils.getImage("event_big")); break; 21 | case WARNING : imvBoxIcon.setImage(ResourceUtils.getImage("warning_big")); break; 22 | case ERROR : imvBoxIcon.setImage(ResourceUtils.getImage("error_big")); break; 23 | } 24 | } 25 | 26 | @Override 27 | public void setContent(Node content) { 28 | root.setCenter(content); 29 | super.setContent(root); 30 | } 31 | 32 | @Override 33 | public Node getContent() { 34 | return root.getCenter(); 35 | } */ 36 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/dialog/base/DialogWrapper.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.dialog.base; 2 | 3 | import javafx.stage.Stage; 4 | import org.beuwi.msgbots.view.gui.type.DialogType; 5 | 6 | public abstract class DialogWrapper extends DialogFrame { 7 | public DialogWrapper() { 8 | this(DialogType.NONE); 9 | } 10 | 11 | public DialogWrapper(DialogType type) { 12 | super(type, new Stage()); 13 | } 14 | 15 | @Override 16 | protected abstract boolean onInit(); 17 | @Override 18 | protected abstract boolean onOpen(); 19 | @Override 20 | protected abstract boolean onAction(); 21 | @Override 22 | protected abstract boolean onClose(); 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/editor/JFunction.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.editor; 2 | 3 | import netscape.javascript.JSObject; 4 | 5 | import java.util.function.Function; 6 | 7 | public class JFunction implements Function { 8 | // Actual Callable 9 | private Function callable; 10 | 11 | public JFunction(Function callable) { 12 | this.callable = callable; 13 | } 14 | 15 | @Override 16 | public Object apply(JSObject args) { 17 | Integer numArgs = 0; 18 | boolean isArray = false; 19 | 20 | if (args != null) { 21 | try { 22 | numArgs = (Integer) args.getMember("length"); 23 | isArray = true; 24 | } 25 | catch (NullPointerException e) { 26 | // length not available 27 | e.printStackTrace(); 28 | } 29 | } 30 | 31 | if (isArray) { 32 | Object[] array = new Object[numArgs]; 33 | for (int i = 0; i < numArgs; i++) { 34 | array[i] = args.getSlot(i); 35 | } 36 | return callable.apply(array); 37 | } 38 | return callable.apply(new Object[] { args }); 39 | } 40 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/editor/Position.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.editor; 2 | 3 | // Cursor Position 4 | public class Position { 5 | private final int lineNumber; 6 | private final int column; 7 | 8 | public Position(int lineNumber, int column) { 9 | this.lineNumber = lineNumber; 10 | this.column = column; 11 | } 12 | 13 | public int getLineNumber() { 14 | return lineNumber; 15 | } 16 | 17 | public int getColumn() { 18 | return column; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/layout/AnchorPane.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.layout; 2 | 3 | import javafx.scene.Node; 4 | 5 | import org.beuwi.msgbots.view.gui.layout.base.AnchorPaneBase; 6 | 7 | public class AnchorPane extends AnchorPaneBase { 8 | public AnchorPane() { 9 | this(null); 10 | } 11 | 12 | public AnchorPane(Node... children) { 13 | if (children != null) { 14 | initChildren(children); 15 | } 16 | 17 | addStyleClass("anchor-pane"); 18 | } 19 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/layout/BorderPane.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.layout; 2 | 3 | import javafx.beans.NamedArg; 4 | import javafx.scene.Node; 5 | 6 | import org.beuwi.msgbots.view.gui.layout.base.BorderPaneBase; 7 | 8 | public class BorderPane extends BorderPaneBase { 9 | { 10 | getStyleClass().add("border-pane"); 11 | } 12 | 13 | public BorderPane() { 14 | super(); 15 | } 16 | 17 | public BorderPane(@NamedArg("center") Node center) { 18 | setCenter(center); 19 | } 20 | 21 | public BorderPane(@NamedArg("top") Node top, 22 | @NamedArg("right") Node right, 23 | @NamedArg("bottom") Node bottom, 24 | @NamedArg("left") Node left) { 25 | setTop(top); 26 | setRight(right); 27 | setBottom(bottom); 28 | setLeft(left); 29 | } 30 | 31 | public BorderPane(@NamedArg("top") Node top, 32 | @NamedArg("right") Node right, 33 | @NamedArg("center") Node center, 34 | @NamedArg("bottom") Node bottom, 35 | @NamedArg("left") Node left) { 36 | setTop(top); 37 | setRight(right); 38 | setCenter(center); 39 | setBottom(bottom); 40 | setLeft(left); 41 | } 42 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/layout/GridPane.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.layout; 2 | 3 | import javafx.scene.Node; 4 | import javafx.scene.layout.ColumnConstraints; 5 | import javafx.scene.layout.RowConstraints; 6 | 7 | import org.beuwi.msgbots.view.gui.layout.base.GridPaneBase; 8 | 9 | public class GridPane extends GridPaneBase { 10 | { 11 | getStyleClass().add("grid-pane"); 12 | } 13 | 14 | public GridPane() { 15 | this(0, 0); 16 | } 17 | 18 | public GridPane(int column, int row) { 19 | } 20 | 21 | public void addItem(Node item, int column, int row) { 22 | add(item, column, row); 23 | } 24 | public void addItem(Node item, int column, int row, int colspan, int rowspan) { 25 | add(item, column, row, colspan, rowspan); 26 | } 27 | 28 | public void addRow() { 29 | getRowConstraints().add(new RowConstraints()); 30 | } 31 | 32 | public void addRow(double height) { 33 | getRowConstraints().add(new RowConstraints(height)); 34 | } 35 | 36 | public void addColumn() { 37 | getColumnConstraints().add(new ColumnConstraints()); 38 | } 39 | 40 | public void addColumn(double width) { 41 | getColumnConstraints().add(new ColumnConstraints(width)); 42 | } 43 | 44 | public void initColumn(int... widths) { 45 | for (int column : widths) { 46 | if (column != 0) { 47 | addColumn(column); 48 | } 49 | else { 50 | addColumn(); 51 | } 52 | } 53 | } 54 | 55 | public void initRow(int... heights) { 56 | for (int column : heights) { 57 | if (column != 0) { 58 | addRow(column); 59 | } 60 | else { 61 | addRow(); 62 | } 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/layout/ShadowPane.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.layout; 2 | 3 | import javafx.beans.property.ObjectProperty; 4 | import javafx.beans.property.SimpleObjectProperty; 5 | import javafx.geometry.Insets; 6 | import javafx.scene.Node; 7 | 8 | // 상속을 금지함 (StyleClass 등 처리해야할 게 많아지기 때문임) 9 | public final class ShadowPane extends StackPane { 10 | 11 | // 굳이 ShadowArea 안에 ContentArea를 두는 이유는 ContentArea에 Shadow를 입히면 안 내용물에도 그림자가 생기기 때문임 12 | private final StackPane shadowArea = new StackPane(); 13 | private final StackPane contentArea = new StackPane(); 14 | 15 | public ShadowPane() { 16 | this(null); 17 | } 18 | 19 | public ShadowPane(Node content) { 20 | contentProperty().addListener(change -> { 21 | Node node = getContent(); 22 | if (node != null) { 23 | contentArea.getChildren().setAll(node); 24 | } 25 | }); 26 | 27 | if (content != null) { 28 | setContent(content); 29 | } 30 | 31 | // 창 띄울 때 흰 화면 방지 32 | setBackground(null); 33 | 34 | shadowArea.getChildren().add(contentArea); 35 | // contentArea.getStyleClass().add("root"); 36 | shadowArea.getStyleClass().add("shadow-area"); 37 | contentArea.getStyleClass().add("content-area"); 38 | 39 | setPadding(new Insets(5)); 40 | getChildren().setAll(shadowArea); 41 | getStyleClass().add("shadow-pane"); 42 | } 43 | 44 | private final ObjectProperty contentProperty = new SimpleObjectProperty(null); 45 | public final void setContent(Node content) { 46 | contentProperty.set(content); 47 | } 48 | public final Node getContent() { 49 | return contentProperty.get(); 50 | } 51 | public final ObjectProperty contentProperty() { 52 | return contentProperty; 53 | } 54 | 55 | /* public final ObservableList getChildren() { 56 | return contentArea.getChildren(); 57 | } 58 | public final ObservableList getStyleClass() { 59 | return contentArea.getStyleClass(); 60 | } */ 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/layout/StackPane.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.layout; 2 | 3 | import javafx.scene.Node; 4 | 5 | import org.beuwi.msgbots.view.gui.layout.base.StackPaneBase; 6 | 7 | public class StackPane extends StackPaneBase { 8 | public StackPane() { 9 | this(null); 10 | } 11 | public StackPane(Node... children) { 12 | if (children != null) { 13 | initChildren(children); 14 | } 15 | 16 | addStyleClass("stack-pane"); 17 | } 18 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/skin/ScrollBarSkin.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.skin; 2 | 3 | import javafx.scene.control.ScrollBar; 4 | import javafx.scene.input.ScrollEvent; 5 | 6 | public class ScrollBarSkin extends javafx.scene.control.skin.ScrollBarSkin { 7 | private static final double SCROLL_SPEED = 0.005; 8 | 9 | public ScrollBarSkin(final ScrollBar control) { 10 | super(control); 11 | 12 | control.setPrefWidth(10.0); 13 | control.addEventFilter(ScrollEvent.SCROLL, event -> { 14 | control.setValue(control.getValue() - (event.getDeltaY() * SCROLL_SPEED)); 15 | }); 16 | 17 | /* if (control.getParent() != null){ 18 | // ScrollPane, VirtualFlow 등등이 나옴 19 | Parent parent = control.getParent(); 20 | // TextArea, ListView 등등이 나옴 21 | Parent target = parent.getParent(); 22 | // 텍스트 박스 스크롤 속도 조정 23 | if (target instanceof TextArea){ 24 | TextArea textarea = (TextArea) target; 25 | ScrollBar scrollbar = (ScrollBar) textarea.lookup(".scroll-bar:vertical"); 26 | } 27 | } */ 28 | } 29 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/type/ButtonType.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.type; 2 | 3 | public enum ButtonType { 4 | ACTION, CANCEL 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/type/DialogType.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.type; 2 | 3 | public enum DialogType { 4 | NONE, INFO, ERROR, WARNING 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/type/WindowType.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.type; 2 | 3 | public enum WindowType { 4 | WINDOW, DIALOG 5 | } -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/window/WindowScene.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.window; 2 | 3 | import javafx.scene.Parent; 4 | import javafx.scene.Scene; 5 | 6 | import org.beuwi.msgbots.view.gui.layout.ShadowPane; 7 | 8 | public class WindowScene extends Scene { 9 | public WindowScene(final Parent root) { 10 | super(new ShadowPane(root)); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/gui/window/WindowWrapper.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.gui.window; 2 | 3 | import javafx.stage.Stage; 4 | import org.beuwi.msgbots.view.gui.type.WindowType; 5 | 6 | public class WindowWrapper extends WindowFrame { 7 | protected WindowWrapper(Stage stage) { 8 | this(WindowType.WINDOW, stage); 9 | } 10 | protected WindowWrapper(WindowType type, Stage stage) { 11 | super(type, stage); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/util/GUIManager.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.util; 2 | 3 | import org.beuwi.msgbots.base.Manager; 4 | import org.beuwi.msgbots.base.Project; 5 | import org.beuwi.msgbots.manager.ProjectManager; 6 | import org.beuwi.msgbots.view.gui.control.BotItem; 7 | import org.beuwi.msgbots.view.gui.layout.DebugPane; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | // GUI로 구성되어 있는 게 아닌, OpenAPI 또는 기본 클래스로만 작성되어 있다면 GUI로 변환하는 과정을 거치는 일을 하는 매니저임 13 | // 현재는 OpenAPI로 구성된 Project클래스에 대해서만 지원함 14 | // 또한, 예외 상황은 아직 고려하지 않고, 추후 문제가 야기될 시 수정하도록 함 15 | // ㄴ> 6월 23일 이후로 project.getProperty("ViewPane")이런식으로 접근함 16 | public class GUIManager implements Manager { 17 | private static final List list = new ArrayList<>(); 18 | public static List getList() { 19 | return list; 20 | } 21 | 22 | public static void register(Project project) { 23 | // 등록된 뷰가 없으면 새로 등록함 24 | if (!list.contains(project)) { 25 | // Project클래스에서는 직접적으로 뷰에 간섭하지 않도록 GUIManager클래스에서 Property지정 26 | project.setProperty("ViewPane", new DebugPane(project)); 27 | project.setProperty("ListItem", new BotItem(project)); 28 | 29 | list.add(project); 30 | } 31 | } 32 | 33 | // 인자로 받은 클래스를 뷰 패널로 변환함 (Project의 경우 디버그 패널로 변환) 34 | public static DebugPane toViewPane(Project project) { 35 | // 프로젝트 매니저에 등록 돼 있어야 함 36 | if (!ProjectManager.getList().contains(project)) { 37 | return null; 38 | } 39 | return (DebugPane) project.getProperty("ViewPane"); 40 | } 41 | 42 | 43 | // 인자로 받은 클래스를 리스트 아이템으로 변환함 (Project의 경우 봇 아이템으로 변환) 44 | public static BotItem toListItem(Project project) { 45 | return (BotItem) project.getProperty("ListItem"); 46 | } 47 | 48 | /* public TreeItem toListItem(File file) { 49 | 50 | } */ 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/beuwi/msgbots/view/util/ViewManager.java: -------------------------------------------------------------------------------- 1 | package org.beuwi.msgbots.view.util; 2 | 3 | import javafx.stage.Stage; 4 | 5 | import org.beuwi.msgbots.view.app.views.MainView; 6 | 7 | public class ViewManager { 8 | // Primary Stage 9 | // private static Application application; 10 | private static Stage stage; 11 | 12 | // 뷰와 관련된 초반 작업 진행 13 | public static void init(final Stage value) { 14 | stage = value; 15 | 16 | // Init Tab (각 파트에서 탭을 사용하므로, 가장 먼저 초기화 되어야 함) 17 | /* BotListTab.init(); 18 | DetailLogTab.init(); 19 | DebugRoomTab.init(); 20 | GlobalLogTab.init(); 21 | 22 | // Init Part 23 | MenuBarPart.init(); 24 | SideAreaPart.init(); 25 | MainAreaPart.init(); 26 | DebugAreaPart.init(); 27 | StatusBarPart.init(); 28 | ToolAreaPart.init(); */ 29 | 30 | // Init Dialog 31 | 32 | // Init Main 33 | MainView.init(); 34 | } 35 | 36 | public static Stage getStage() { 37 | return stage; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/resources/font/Consola-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/font/Consola-Regular.ttf -------------------------------------------------------------------------------- /src/main/resources/font/D2Coding-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/font/D2Coding-Regular.ttf -------------------------------------------------------------------------------- /src/main/resources/font/JetBrainsMono-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/font/JetBrainsMono-Bold.ttf -------------------------------------------------------------------------------- /src/main/resources/font/JetBrainsMono-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/font/JetBrainsMono-Medium.ttf -------------------------------------------------------------------------------- /src/main/resources/font/JetBrainsMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/font/JetBrainsMono-Regular.ttf -------------------------------------------------------------------------------- /src/main/resources/font/NanumGothic-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/font/NanumGothic-Regular.ttf -------------------------------------------------------------------------------- /src/main/resources/font/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/font/Roboto-Regular.ttf -------------------------------------------------------------------------------- /src/main/resources/font/consola-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/font/consola-bold.ttf -------------------------------------------------------------------------------- /src/main/resources/font/d2coding-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/font/d2coding-bold.ttf -------------------------------------------------------------------------------- /src/main/resources/font/nanumgothic-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/font/nanumgothic-bold.ttf -------------------------------------------------------------------------------- /src/main/resources/font/roboto-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/font/roboto-bold.ttf -------------------------------------------------------------------------------- /src/main/resources/font/roboto-medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/font/roboto-medium.ttf -------------------------------------------------------------------------------- /src/main/resources/form/dialog/create-bot-dialog.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/main/resources/form/dialog/delete-bot-dialog.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /src/main/resources/form/dialog/display-error-dialog.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 14 | 15 | 17 | 20 | 21 | 24 | 25 | -------------------------------------------------------------------------------- /src/main/resources/form/dialog/import-script-dialog.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 21 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/main/resources/form/dialog/rename-bot-dialog.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/main/resources/form/dialog/show-msg-dialog.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/main/resources/form/dialog/yes-or-no-dialog.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/main/resources/form/frame/bot-item-frame.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 26 | 33 | 39 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/main/resources/form/frame/chat-area-frame.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/main/resources/form/frame/dialog-box-frame.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 37 | -------------------------------------------------------------------------------- /src/main/resources/form/frame/log-item-frame.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/main/resources/form/frame/toast-item-frame.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 31 | 34 | 35 | 36 | 37 | 41 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /src/main/resources/form/frame/window-box-frame.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 22 | 23 | 24 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/main/resources/form/part/debug-area-part.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main/resources/form/part/main-area-part.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/main/resources/form/part/menu-bar-part.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/main/resources/form/part/side-area-part.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main/resources/form/part/status-bar-part.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | 27 | -------------------------------------------------------------------------------- /src/main/resources/form/part/toast-view-part.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 21 | 22 | 23 | 24 | 29 | 30 | 31 | 32 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/main/resources/form/part/tool-area-part.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 24 | 33 | 34 | -------------------------------------------------------------------------------- /src/main/resources/form/tab/bot-list-tab.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/main/resources/form/tab/debug-room-tab.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/main/resources/form/tab/detail-log-tab.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/main/resources/form/tab/global-log-tab.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/main/resources/form/tab/view-kaymap-tab.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/main/resources/form/view/bot-option-view.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/main/resources/icon/program.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/icon/program.ico -------------------------------------------------------------------------------- /src/main/resources/image/chat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/image/chat.png -------------------------------------------------------------------------------- /src/main/resources/image/debug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/image/debug.png -------------------------------------------------------------------------------- /src/main/resources/image/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/image/error.png -------------------------------------------------------------------------------- /src/main/resources/image/error_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/image/error_big.png -------------------------------------------------------------------------------- /src/main/resources/image/explorer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/image/explorer.png -------------------------------------------------------------------------------- /src/main/resources/image/info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/image/info.png -------------------------------------------------------------------------------- /src/main/resources/image/info_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/image/info_big.png -------------------------------------------------------------------------------- /src/main/resources/image/log.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/image/log.png -------------------------------------------------------------------------------- /src/main/resources/image/profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/image/profile.png -------------------------------------------------------------------------------- /src/main/resources/image/program.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/image/program.png -------------------------------------------------------------------------------- /src/main/resources/image/program_start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/image/program_start.png -------------------------------------------------------------------------------- /src/main/resources/image/program_trans.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/image/program_trans.png -------------------------------------------------------------------------------- /src/main/resources/image/reload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/image/reload.png -------------------------------------------------------------------------------- /src/main/resources/image/setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/image/setting.png -------------------------------------------------------------------------------- /src/main/resources/image/simulation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/image/simulation.png -------------------------------------------------------------------------------- /src/main/resources/image/warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/image/warning.png -------------------------------------------------------------------------------- /src/main/resources/image/warning_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttyy3388/msgbots/281d8bcf264599e678b0eddff0f6b65f99c1e1fa/src/main/resources/image/warning_big.png -------------------------------------------------------------------------------- /src/main/resources/monaco/index.css: -------------------------------------------------------------------------------- 1 | /* DOCUMENT CSS */ 2 | @CHARSET "UTF-8"; 3 | 4 | * { 5 | font-family: 'JetBrains Mono', 'D2Coding', monospace; 6 | /* font-family: NanumGothic, 'JetBrains Mono', monospace; */ 7 | /* font-family: Consolas, "Courier New", monospace; */ 8 | } 9 | 10 | html, body { 11 | height: 100%; 12 | margin: 0; 13 | } 14 | body { 15 | overflow-x: hidden; 16 | overflow-y: hidden; 17 | } 18 | #container { 19 | height: 100%; 20 | } 21 | 22 | /* .mtk1 { 23 | color: #7CDCFE; } */ /* TEXT COLOR */ 24 | /* .monaco-editor .lines-content.monaco-editor-background { 25 | margin-top: 4px; 26 | } */ -------------------------------------------------------------------------------- /src/main/resources/monaco/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 14 |

15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/main/resources/webpage/html/about-program-page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 20 | 21 |
22 | 23 |
24 |

Messenger Bot Simulator

25 |

Version : 0.5.0

26 |

Commit : cd2cd875e0f201ee87c9016009ea879dc57df850

27 |

Date : 2020/11/18 18:29:21

28 |
29 |
30 | 31 | -------------------------------------------------------------------------------- /src/main/resources/webpage/html/program-start-page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 20 | 21 |
22 | 23 |
24 | 25 |
26 | 27 |
28 | 29 |
30 |
31 |

Create New Bot

32 |

Import Script

33 |

Show Global Config

34 |
35 |
36 | 37 |
38 |
39 |

Ctrl + N

40 |

Ctrl + I

41 |

Ctrl + Shift + C

42 |
43 |
44 |
45 |
46 | 47 | -------------------------------------------------------------------------------- /src/main/resources/webpage/html/release-notes-page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 20 | 21 |
22 |

Version 0.5.0 Update

23 |
24 |

※ 업데이트

25 |

※ 업데이트 내용

26 |

27 |

1. 런타임 에러 시 전원 끄기 설정 적용

28 |

29 |

2. Api.Off 함수 무시 설정 추가

30 |

31 |

3. 스크립트 삭제 다이얼 로그 추가

32 |

33 |

4. 슬라이더 컴포넌트 구현

34 |

35 |

5. 봇 설정 탭 구현

36 |
37 | 38 | -------------------------------------------------------------------------------- /src/main/resources/webpage/style/base.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'D2Coding'; 3 | src: url('../../font/D2Coding-Regular.ttf'); 4 | } 5 | @font-face { 6 | font-family: 'D2Coding'; 7 | font-weight: bold; 8 | src: url('../../font/D2Coding-Bold.ttf'); 9 | } 10 | @font-face { 11 | font-family: 'NanumGothic'; 12 | src: url('../../font/NanumGothic-Regular.ttf'); 13 | } 14 | @font-face { 15 | font-family: 'NanumGothic'; 16 | font-weight: bold; 17 | src: url('../../font/NanumGothic-Bold.ttf'); 18 | } 19 | @font-face { 20 | font-family: 'Roboto'; 21 | src: url('../../font/Roboto-Regular.ttf'); 22 | } 23 | @font-face { 24 | font-family: 'Roboto'; 25 | font-weight: bold; 26 | src: url('../../font/Roboto-Bold.ttf'); 27 | } 28 | 29 | * { 30 | font-family: 'Roboto', 'NanumGothic', sans-serif; 31 | font-weight: normal; 32 | } 33 | h1 { 34 | font-weight: bold; 35 | } 36 | h2 { 37 | font-weight: normal; 38 | } 39 | h3 { 40 | font-weight: normal; 41 | } 42 | h4 { 43 | font-weight: normal; 44 | } 45 | 46 | p { 47 | line-height: normal; 48 | } 49 | 50 | a:link { 51 | text-decoration: none; 52 | } 53 | a:visited, 54 | a:active { 55 | text-decoration: none; 56 | } 57 | 58 | -------------------------------------------------------------------------------- /src/main/resources/webpage/style/dark.css: -------------------------------------------------------------------------------- 1 | /* DOCUMENT CSS */ 2 | @CHARSET "UTF-8"; 3 | 4 | /* 문자열로 적용을 시키기 때문에, 5 | html 경로 기준으로 상대경로를 작성해야 함 */ 6 | @import "../style/base.css"; 7 | 8 | * { 9 | color: #CCCCCC; 10 | } 11 | h1 { 12 | color: #FFFFFF; 13 | } 14 | body { 15 | background-color: #1E1E1E; 16 | } 17 | a:link { 18 | color: #007ACC; 19 | } 20 | a:visited, 21 | a:active { 22 | color: #007ACC; 23 | } -------------------------------------------------------------------------------- /src/main/resources/webpage/style/light.css: -------------------------------------------------------------------------------- 1 | /* DOCUMENT CSS */ 2 | @CHARSET "UTF-8"; 3 | 4 | /* 문자열로 적용을 시키기 때문에, 5 | html 경로 기준으로 상대경로를 작성해야 함 */ 6 | @import "../style/base.css"; 7 | 8 | * { 9 | color: #333333; 10 | } 11 | h1 { 12 | color: #000000; 13 | } 14 | body { 15 | background-color: #FFFFFF; 16 | } 17 | a:link { 18 | color: #007ACC; 19 | } 20 | a:visited, 21 | a:active { 22 | color: #007ACC; 23 | } --------------------------------------------------------------------------------