From 238c6b44dbb36512b94586f82888893df1ceefb1 Mon Sep 17 00:00:00 2001 From: Andrew Lalis Date: Sat, 7 Nov 2020 00:11:29 +0100 Subject: [PATCH] Added starting application. --- .gitignore | 4 + pom.xml | 25 +++++ .../blockbookbinder/BlockBookBinder.java | 17 +++ .../blockbookbinder/control/ImportAction.java | 19 ++++ .../blockbookbinder/model/BookContents.java | 15 +++ .../blockbookbinder/model/BookPage.java | 14 +++ .../util/ApplicationProperties.java | 42 +++++++ .../blockbookbinder/view/MainFrame.java | 106 ++++++++++++++++++ src/main/resources/application.properties | 9 ++ .../resources/fonts/1_Minecraft-Regular.otf | Bin 0 -> 11016 bytes src/main/resources/images/book_and_quill.png | Bin 0 -> 424 bytes 11 files changed, 251 insertions(+) create mode 100644 pom.xml create mode 100644 src/main/java/nl/andrewlalis/blockbookbinder/BlockBookBinder.java create mode 100644 src/main/java/nl/andrewlalis/blockbookbinder/control/ImportAction.java create mode 100644 src/main/java/nl/andrewlalis/blockbookbinder/model/BookContents.java create mode 100644 src/main/java/nl/andrewlalis/blockbookbinder/model/BookPage.java create mode 100644 src/main/java/nl/andrewlalis/blockbookbinder/util/ApplicationProperties.java create mode 100644 src/main/java/nl/andrewlalis/blockbookbinder/view/MainFrame.java create mode 100644 src/main/resources/application.properties create mode 100644 src/main/resources/fonts/1_Minecraft-Regular.otf create mode 100644 src/main/resources/images/book_and_quill.png diff --git a/.gitignore b/.gitignore index 0e13eeb..efbf295 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,7 @@ buildNumber.properties .mvn/timing.properties # https://github.com/takari/maven-wrapper#usage-without-binary-jar .mvn/wrapper/maven-wrapper.jar + +# IntelliJ Configuration Files +.idea/ +*.iml diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..0d82aea --- /dev/null +++ b/pom.xml @@ -0,0 +1,25 @@ + + + 4.0.0 + + nl.andrewlalis + BlockBookBinder + 0.0.1 + + + 12 + 12 + + + + + + org.projectlombok + lombok + 1.18.14 + provided + + + \ No newline at end of file diff --git a/src/main/java/nl/andrewlalis/blockbookbinder/BlockBookBinder.java b/src/main/java/nl/andrewlalis/blockbookbinder/BlockBookBinder.java new file mode 100644 index 0000000..80f0b23 --- /dev/null +++ b/src/main/java/nl/andrewlalis/blockbookbinder/BlockBookBinder.java @@ -0,0 +1,17 @@ +package nl.andrewlalis.blockbookbinder; + +import nl.andrewlalis.blockbookbinder.view.MainFrame; + +import javax.swing.*; + +/** + * The main class for the application. + */ +public class BlockBookBinder { + public static void main(String[] args) { + SwingUtilities.invokeLater(() -> { + var mainFrame = new MainFrame(); + mainFrame.setupAndShow(); + }); + } +} diff --git a/src/main/java/nl/andrewlalis/blockbookbinder/control/ImportAction.java b/src/main/java/nl/andrewlalis/blockbookbinder/control/ImportAction.java new file mode 100644 index 0000000..f0c2b6e --- /dev/null +++ b/src/main/java/nl/andrewlalis/blockbookbinder/control/ImportAction.java @@ -0,0 +1,19 @@ +package nl.andrewlalis.blockbookbinder.control; + +import javax.swing.*; +import java.awt.event.ActionEvent; + +public class ImportAction extends AbstractAction { + public ImportAction(String name) { + super(name); + } + + public ImportAction(String name, Icon icon) { + super(name, icon); + } + + @Override + public void actionPerformed(ActionEvent e) { + System.out.println("Import!"); + } +} diff --git a/src/main/java/nl/andrewlalis/blockbookbinder/model/BookContents.java b/src/main/java/nl/andrewlalis/blockbookbinder/model/BookContents.java new file mode 100644 index 0000000..3ef02a6 --- /dev/null +++ b/src/main/java/nl/andrewlalis/blockbookbinder/model/BookContents.java @@ -0,0 +1,15 @@ +package nl.andrewlalis.blockbookbinder.model; + +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +public class BookContents { + @Getter + private final List pages; + + public BookContents() { + this.pages = new ArrayList<>(); + } +} diff --git a/src/main/java/nl/andrewlalis/blockbookbinder/model/BookPage.java b/src/main/java/nl/andrewlalis/blockbookbinder/model/BookPage.java new file mode 100644 index 0000000..f05f87a --- /dev/null +++ b/src/main/java/nl/andrewlalis/blockbookbinder/model/BookPage.java @@ -0,0 +1,14 @@ +package nl.andrewlalis.blockbookbinder.model; + +import lombok.Getter; +import lombok.Setter; + +public class BookPage { + @Getter + @Setter + private String content; + + public BookPage() { + this.content = ""; + } +} diff --git a/src/main/java/nl/andrewlalis/blockbookbinder/util/ApplicationProperties.java b/src/main/java/nl/andrewlalis/blockbookbinder/util/ApplicationProperties.java new file mode 100644 index 0000000..6e8dc0b --- /dev/null +++ b/src/main/java/nl/andrewlalis/blockbookbinder/util/ApplicationProperties.java @@ -0,0 +1,42 @@ +package nl.andrewlalis.blockbookbinder.util; + +import lombok.Getter; + +import java.io.IOException; +import java.util.Properties; + +/** + * Singleton class which handles the properties defined in an external + * properties file. + */ +public class ApplicationProperties { + private static ApplicationProperties instance; + @Getter + private final Properties properties; + + public static ApplicationProperties getInstance() { + if (instance == null) { + try { + instance = new ApplicationProperties(); + } catch (IOException e) { + System.err.println("Could not load properties!"); + System.exit(1); + } + } + return instance; + } + + /** + * Shortcut for getting a property. + * @param key The property's key. + * @return The value for that property. + */ + public static String getProp(String key) { + return getInstance().getProperties().getProperty(key); + } + + private ApplicationProperties() throws IOException { + this.properties = new Properties(); + this.properties.load(this.getClass().getClassLoader().getResourceAsStream("application.properties")); + } +} diff --git a/src/main/java/nl/andrewlalis/blockbookbinder/view/MainFrame.java b/src/main/java/nl/andrewlalis/blockbookbinder/view/MainFrame.java new file mode 100644 index 0000000..551ca21 --- /dev/null +++ b/src/main/java/nl/andrewlalis/blockbookbinder/view/MainFrame.java @@ -0,0 +1,106 @@ +package nl.andrewlalis.blockbookbinder.view; + +import nl.andrewlalis.blockbookbinder.control.ImportAction; +import nl.andrewlalis.blockbookbinder.util.ApplicationProperties; + +import javax.swing.*; +import javax.swing.border.EmptyBorder; +import java.awt.*; +import java.awt.datatransfer.StringSelection; +import java.net.URL; + +/** + * The main window of the application. + */ +public class MainFrame extends JFrame { + private Action importAction; + + public void setupAndShow() { + final int width = Integer.parseInt(ApplicationProperties.getProp("frame.default_width")); + final int height = Integer.parseInt(ApplicationProperties.getProp("frame.default_height")); + this.setPreferredSize(new Dimension(width, height)); + this.setTitle(ApplicationProperties.getProp("frame.title")); + this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + final URL iconUrl = this.getClass().getClassLoader().getResource("images/book_and_quill.png"); + if (iconUrl != null) { + this.setIconImage(new ImageIcon(iconUrl).getImage()); + } + + this.initActions(); + this.setContentPane(this.buildContentPane()); + this.setJMenuBar(this.buildMenuBar()); + + this.pack(); + this.setLocationRelativeTo(null); + this.setVisible(true); + } + + private void initActions() { + this.importAction = new ImportAction("Import"); + } + + private JMenuBar buildMenuBar() { + JMenuBar menuBar = new JMenuBar(); + + JMenu fileMenu = new JMenu("File"); + fileMenu.add(new JMenuItem(this.importAction)); + menuBar.add(fileMenu); + + JMenu helpMenu = new JMenu("Help"); + JMenuItem aboutItem = new JMenuItem("About"); + helpMenu.add(aboutItem); + menuBar.add(helpMenu); + + return menuBar; + } + + private Container buildContentPane() { + JPanel mainPanel = new JPanel(new BorderLayout()); + + JPanel doublePanel = new JPanel(new GridLayout(1, 2)); + mainPanel.add(doublePanel, BorderLayout.CENTER); + final Insets innerPanelInsets = new Insets(5, 5, 5, 5); + + + JPanel leftPanel = new JPanel(new BorderLayout()); + doublePanel.add(leftPanel); + leftPanel.add(new JLabel("Book Preview"), BorderLayout.NORTH); + leftPanel.setBorder(new EmptyBorder(innerPanelInsets)); + + JTextArea previewPageTextArea = new JTextArea(); + JScrollPane previewPageScrollPane = new JScrollPane(previewPageTextArea, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + leftPanel.add(previewPageScrollPane, BorderLayout.CENTER); + + JPanel previewButtonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); + previewButtonPanel.add(new JButton("<")); + previewButtonPanel.add(new JButton(">")); + leftPanel.add(previewButtonPanel, BorderLayout.SOUTH); + + + JPanel rightPanel = new JPanel(new BorderLayout()); + doublePanel.add(rightPanel); + rightPanel.add(new JLabel("Source Text"), BorderLayout.NORTH); + rightPanel.setBorder(new EmptyBorder(innerPanelInsets)); + + JTextArea mainTextArea = new JTextArea(); + JScrollPane scrollWrappedMainTextArea = new JScrollPane(mainTextArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + rightPanel.add(scrollWrappedMainTextArea, BorderLayout.CENTER); + + JPanel rightPanelButtonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); + rightPanel.add(rightPanelButtonPanel, BorderLayout.SOUTH); + rightPanelButtonPanel.add(new JButton(this.importAction)); + + + JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); + JButton exportButton = new JButton("Export to Book"); + exportButton.addActionListener(e -> { + System.out.println("Starting export."); + final String fullText = mainTextArea.getText().trim(); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(fullText.substring(0, 200)), null); + }); + bottomPanel.add(exportButton); + mainPanel.add(bottomPanel, BorderLayout.SOUTH); + + return mainPanel; + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..c28913c --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,9 @@ +# Settings for the application's GUI. +frame.title=Block Book Binder +frame.default_width=800 +frame.default_height=600 + +# Settings for Minecraft book interaction. +book.max_pages=100 +book.page_max_lines=14 +book.page_max_width=113 diff --git a/src/main/resources/fonts/1_Minecraft-Regular.otf b/src/main/resources/fonts/1_Minecraft-Regular.otf new file mode 100644 index 0000000000000000000000000000000000000000..54f08ad42ae2c7e9eb4d46c7b621544e32cfc9a2 GIT binary patch literal 11016 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/images/book_and_quill.png b/src/main/resources/images/book_and_quill.png new file mode 100644 index 0000000000000000000000000000000000000000..2e29d638b0fac5287c3c8fcaedfa684ecbb72167 GIT binary patch literal 424 zcmeAS@N?(olHy`uVBq!ia0vp^3qY8I8A$FCoGuTf3<7*YT!FNu0Q0?j_tvgmD<;5t z>eQ)HBf0I{x5p|8_)4%}yLPR?*gg(WYxwznB&tDSpUK1n6h|9XiZ z>y2Y_yc{49F{5@3hyP34yO)ZqViZ8&LH4T^+m|t4S=!hD0?}5>vx5V7D{fuNd?ghu z(hz+)c-PWJ?^YUoo?zt=%LXy$Rnpo0FWavCzjAi@`k?J0t4bkipZ>So+HkjKmf_X? zC0^Q0j3DqnbJ@F0yDHgdx_5(XquIgwD?D2(J&nK4NlR#d8F4q`*J}q5I8f5CYiXt3 z*%_}cZQ&6Bfe#E@trKN|IR5AwRu&NWW4YCU)ut;_9&C<9aDCAsnBQWLJrjpGWBw$S am&{u}RxHSy%uxmmJ_b)$KbLh*2~7Zw5~m;l literal 0 HcmV?d00001