From 0f83195c6abe99b0b2fbbf260230c2e16c3ba682 Mon Sep 17 00:00:00 2001 From: David McMackins II Date: Fri, 9 Sep 2016 10:13:35 -0500 Subject: Add skeleton UI --- .gitignore | 3 +- nbproject/project.properties | 4 +- src/com/delwink/icebox/Config.java | 83 ++++++++++++++ src/com/delwink/icebox/DataDir.java | 75 ++++++++++++ src/com/delwink/icebox/MainWindow.java | 176 ++++++++++++++++++++++++++++- src/com/delwink/icebox/SettingsDialog.java | 77 +++++++++++++ src/com/delwink/icebox/lang/Lang.java | 61 ++++++++++ src/com/delwink/icebox/lang/en_US.lang | 20 ++++ src/com/delwink/icebox/swing/JDialog.java | 54 +++++++++ 9 files changed, 548 insertions(+), 5 deletions(-) create mode 100644 src/com/delwink/icebox/Config.java create mode 100644 src/com/delwink/icebox/DataDir.java create mode 100644 src/com/delwink/icebox/SettingsDialog.java create mode 100644 src/com/delwink/icebox/lang/Lang.java create mode 100644 src/com/delwink/icebox/lang/en_US.lang create mode 100644 src/com/delwink/icebox/swing/JDialog.java diff --git a/.gitignore b/.gitignore index 3197301..abc3c57 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /build/ -/nbproject/private/ \ No newline at end of file +/nbproject/private/ +/dist/ \ No newline at end of file diff --git a/nbproject/project.properties b/nbproject/project.properties index f275ed2..d2510f2 100644 --- a/nbproject/project.properties +++ b/nbproject/project.properties @@ -38,8 +38,8 @@ javac.deprecation=false javac.external.vm=true javac.processorpath=\ ${javac.classpath} -javac.source=1.8 -javac.target=1.8 +javac.source=1.7 +javac.target=1.7 javac.test.classpath=\ ${javac.classpath}:\ ${build.classes.dir} diff --git a/src/com/delwink/icebox/Config.java b/src/com/delwink/icebox/Config.java new file mode 100644 index 0000000..66ae602 --- /dev/null +++ b/src/com/delwink/icebox/Config.java @@ -0,0 +1,83 @@ +/* + * IceBox - inventory management software for restaurants + * Copyright (C) 2016 Delwink, LLC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, version 3 only. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.delwink.icebox; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Static class for accessing user-specific preferences. + * @author David McMackins II + */ +public final class Config { + private static final File CONFIG_FILE = DataDir.getDataFile("icebox.properties"); + private static final Config CONFIG = new Config(); + + private final Properties PROPERTIES; + + private Config() { + PROPERTIES = new Properties(); + + PROPERTIES.setProperty("lang", "en_US"); + PROPERTIES.setProperty("mainwindow.maximized", "n"); + PROPERTIES.setProperty("mainwindow.width", "300"); + PROPERTIES.setProperty("mainwindow.height", "600"); + PROPERTIES.setProperty("setlaf", "y"); + + if (CONFIG_FILE.exists()) { + try { + PROPERTIES.load(new FileInputStream(CONFIG_FILE)); + } catch (IOException ex) { + System.err.println("Failed to load config file"); + } + } + } + + /** + * Sets a user-specific preference. + * @param key The name of the preference. + * @param value The value of the preference. + */ + public static void put(String key, String value) { + key = key.toLowerCase(); + + if (!value.equals(get(key))) { + CONFIG.PROPERTIES.setProperty(key, value); + + try { + CONFIG.PROPERTIES.store(new FileOutputStream(CONFIG_FILE), "Generated by IceBox"); + } catch (IOException ex) { + Logger.getLogger(Config.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + + /** + * Gets a user-specific preference. + * @param key The name of the preference. + * @return The value of the preference. + */ + public static String get(String key) { + return CONFIG.PROPERTIES.getProperty(key.toLowerCase()); + } +} diff --git a/src/com/delwink/icebox/DataDir.java b/src/com/delwink/icebox/DataDir.java new file mode 100644 index 0000000..acf61f4 --- /dev/null +++ b/src/com/delwink/icebox/DataDir.java @@ -0,0 +1,75 @@ +/* + * IceBox - inventory management software for restaurants + * Copyright (C) 2016 Delwink, LLC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, version 3 only. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.delwink.icebox; + +import java.io.File; +import java.io.FileNotFoundException; + +/** + * Static class which handles the IceBox data directory. + * @author David McMackins II + */ +public final class DataDir { + private static File rootDir = null; + + /** + * Gets a file in the data directory. + * @param path The relative path of the data file. + * @return The requested file. + */ + public static File getDataFile(String path) { + if (rootDir == null) { + try { + init(); + } catch (FileNotFoundException ex) { + return new File(System.getProperty("user.home"), path); + } + } + + return new File(rootDir, path); + } + + private static void init() throws FileNotFoundException { + String path = System.getProperty("user.home"); + + if (isWinblows()) + path = new File(path, "AppData\\Roaming").getAbsolutePath(); + + File f = new File(path, ".icebox"); + if (f.exists()) { + if (f.isDirectory()) { + rootDir = f; + } else { + throw new IllegalStateException("Data directory path is not a directory"); + } + } else { + try { + if (!f.mkdirs()) + throw new Exception(); + + rootDir = f; + } catch (Exception ex) { + throw new FileNotFoundException("Failed to create data directory"); + } + } + } + + private static boolean isWinblows() { + return System.getProperty("os.name").toLowerCase().startsWith("win"); + } +} diff --git a/src/com/delwink/icebox/MainWindow.java b/src/com/delwink/icebox/MainWindow.java index 18c6bd4..c1460c0 100644 --- a/src/com/delwink/icebox/MainWindow.java +++ b/src/com/delwink/icebox/MainWindow.java @@ -17,9 +17,181 @@ package com.delwink.icebox; -public class MainWindow { +import com.delwink.icebox.lang.Lang; +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.FileNotFoundException; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +/** + * The main IceBox hub window. + * @author David McMackins II + */ +public class MainWindow extends JFrame { + protected final JButton ITEMS_BUTTON, ORDERS_BUTTON, UPDATE_BUTTON; + protected final JCheckBox REORDER_ONLY; + protected final JMenu REPORT_MENU, SESSION_MENU; + protected final JMenuBar MENU_BAR; + protected final JTable INVENTORY_TABLE; + + /** + * Creates a new main IceBox window. + */ + public MainWindow() { + super(Lang.get("MainWindow.title")); + + // menus + MENU_BAR = new JMenuBar(); + setJMenuBar(MENU_BAR); + + SESSION_MENU = new JMenu(Lang.get("MainWindow.SessionMenu.name")); + MENU_BAR.add(SESSION_MENU); + + JMenuItem settings = new JMenuItem(Lang.get("Setting.dialogTitle")); + SESSION_MENU.add(settings); + settings.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + SettingsDialog sd = new SettingsDialog(MainWindow.this); + sd.setVisible(true); + } + }); + + SESSION_MENU.addSeparator(); + + JMenuItem quit = new JMenuItem(Lang.get("MainWindow.quit")); + SESSION_MENU.add(quit); + quit.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + MainWindow.this.dispatchEvent(new WindowEvent(MainWindow.this, WindowEvent.WINDOW_CLOSING)); + } + }); + + REPORT_MENU = new JMenu(Lang.get("MainWindow.ReportMenu.name")); + MENU_BAR.add(REPORT_MENU); + + JMenuItem soldVsWaste = new JMenuItem(Lang.get("Report.soldVsWaste")); + REPORT_MENU.add(soldVsWaste); + soldVsWaste.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ae) { + throw new UnsupportedOperationException("Not supported yet."); + } + }); + + // top section + REORDER_ONLY = new JCheckBox(Lang.get("MainWindow.reorderOnly")); + REORDER_ONLY.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + throw new UnsupportedOperationException("Not supported yet."); + } + }); + + JPanel optionBox = new JPanel(new FlowLayout(FlowLayout.CENTER)); + optionBox.add(REORDER_ONLY); + + // center section + INVENTORY_TABLE = new JTable(); + + JScrollPane inventoryBox = new JScrollPane(INVENTORY_TABLE); + + // bottom section + ITEMS_BUTTON = new JButton(Lang.get("MainWindow.items")); + ITEMS_BUTTON.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ae) { + throw new UnsupportedOperationException("Not supported yet."); + } + }); + + ORDERS_BUTTON = new JButton(Lang.get("MainWindow.orders")); + ORDERS_BUTTON.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ae) { + throw new UnsupportedOperationException("Not supported yet."); + } + }); + + UPDATE_BUTTON = new JButton(Lang.get("MainWindow.update")); + UPDATE_BUTTON.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ae) { + throw new UnsupportedOperationException("Not supported yet."); + } + }); + + JPanel buttonBox = new JPanel(new FlowLayout(FlowLayout.CENTER)); + buttonBox.add(ITEMS_BUTTON); + buttonBox.add(ORDERS_BUTTON); + buttonBox.add(UPDATE_BUTTON); + + // big picture + setLayout(new BorderLayout()); + add(optionBox, BorderLayout.NORTH); + add(inventoryBox, BorderLayout.CENTER); + add(buttonBox, BorderLayout.SOUTH); + + // window properties + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent we) { + if (isMaximized()) { + Config.put("mainwindow.maximized", "y"); + } else { + Config.put("mainwindow.maximized", "n"); + Config.put("mainwindow.width", String.valueOf(getWidth())); + Config.put("mainwindow.height", String.valueOf(getHeight())); + } + } + }); + + setSize(Integer.parseInt(Config.get("mainwindow.width")), + Integer.parseInt(Config.get("mainwindow.height"))); + + if (Config.get("mainwindow.maximized").equals("y")) + setMaximized(); + } + + public final void setMaximized() { + setExtendedState(getExtendedState() | MAXIMIZED_BOTH); + } + + public final boolean isMaximized() { + return (getExtendedState() & MAXIMIZED_BOTH) == MAXIMIZED_BOTH; + } public static void main(String[] args) { - // TODO: instantiate MainWindow to start application + try { + Lang.setLang(Config.get("lang") + ".lang"); + } catch (FileNotFoundException ignored) { + } + + if (Config.get("setlaf").equals("y")) { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { + System.err.println("Failed to set look and feel"); + } + } + + MainWindow mainWindow = new MainWindow(); + mainWindow.setVisible(true); } } diff --git a/src/com/delwink/icebox/SettingsDialog.java b/src/com/delwink/icebox/SettingsDialog.java new file mode 100644 index 0000000..096961e --- /dev/null +++ b/src/com/delwink/icebox/SettingsDialog.java @@ -0,0 +1,77 @@ +/* + * IceBox - inventory management software for restaurants + * Copyright (C) 2016 Delwink, LLC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, version 3 only. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.delwink.icebox; + +import com.delwink.icebox.lang.Lang; +import com.delwink.icebox.swing.JDialog; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JPanel; + +/** + * Dialog for customizing IceBox. + * @author David McMackins II + */ +public class SettingsDialog extends JDialog { + protected final JButton CANCEL_BUTTON, OK_BUTTON; + protected final JCheckBox SETLAF; + + public SettingsDialog(Frame parent) { + super(parent, Lang.get("Setting.dialogTitle")); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + + SETLAF = new JCheckBox(Lang.get("Setting.setlaf")); + SETLAF.setSelected(Config.get("setlaf").equals("y")); + JPanel setlafPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); + setlafPanel.add(SETLAF); + + CANCEL_BUTTON = new JButton(Lang.get("cancel")); + CANCEL_BUTTON.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + dispose(); + } + }); + + OK_BUTTON = new JButton(Lang.get("ok")); + OK_BUTTON.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + Config.put("setlaf", SETLAF.isSelected() ? "y" : "n"); + + dispose(); + } + }); + + JPanel buttonBox = new JPanel(new FlowLayout(FlowLayout.RIGHT)); + buttonBox.add(CANCEL_BUTTON); + buttonBox.add(OK_BUTTON); + + setLayout(new BoxLayout(this.getContentPane(), BoxLayout.Y_AXIS)); + add(setlafPanel); + add(buttonBox); + + pack(); + centorOnParent(); + } +} diff --git a/src/com/delwink/icebox/lang/Lang.java b/src/com/delwink/icebox/lang/Lang.java new file mode 100644 index 0000000..4372bb1 --- /dev/null +++ b/src/com/delwink/icebox/lang/Lang.java @@ -0,0 +1,61 @@ +/* + * IceBox - inventory management software for restaurants + * Copyright (C) 2016 Delwink, LLC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, version 3 only. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.delwink.icebox.lang; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Properties; + +/** + * Static class for getting localized GUI text. + * @author David McMackins II + */ +public final class Lang { + private static Properties lang; + + /** + * Sets the active language. + * @param path Local path to the lang file inside the lang directory. + * @throws java.io.FileNotFoundException if lang file not found. + */ + public static void setLang(String path) throws FileNotFoundException { + Properties oldLang = lang; + + try { + lang = new Properties(); + lang.load(Lang.class.getResourceAsStream(path)); + } catch (IOException | NullPointerException ex) { + lang = oldLang; + throw new FileNotFoundException("Could not find lang file " + path); + } + } + + /** + * Gets appropriate GUI text for an element. + * @param key The key for the text. + * @return The appropriate GUI text for the key, or the key itself if no + * text is found. + */ + public static String get(String key) { + try { + return lang.getProperty(key, key); + } catch (NullPointerException ex) { + return key; + } + } +} diff --git a/src/com/delwink/icebox/lang/en_US.lang b/src/com/delwink/icebox/lang/en_US.lang new file mode 100644 index 0000000..e2047b2 --- /dev/null +++ b/src/com/delwink/icebox/lang/en_US.lang @@ -0,0 +1,20 @@ +lang.name=English (United States) + +ok=OK +save=Save +cancel=Cancel + +MainWindow.help=Help +MainWindow.items=Items +MainWindow.orders=Orders +MainWindow.quit=Quit +MainWindow.reorderOnly=Needs Reorder Only +MainWindow.ReportMenu.name=Report +MainWindow.SessionMenu.name=Session +MainWindow.title=IceBox Inventory +MainWindow.update=Update + +Report.soldVsWaste=Sold vs. Waste + +Setting.dialogTitle=Settings +Setting.setlaf=Use Native Look-And-Feel \ No newline at end of file diff --git a/src/com/delwink/icebox/swing/JDialog.java b/src/com/delwink/icebox/swing/JDialog.java new file mode 100644 index 0000000..c08bd51 --- /dev/null +++ b/src/com/delwink/icebox/swing/JDialog.java @@ -0,0 +1,54 @@ +/* + * IceBox - inventory management software for restaurants + * Copyright (C) 2016 Delwink, LLC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, version 3 only. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.delwink.icebox.swing; + +import java.awt.Container; +import java.awt.Frame; + +/** + * A custom JDialog. + * @author David McMackins II + */ +public class JDialog extends javax.swing.JDialog { + /** + * Creates a new dialog. + * @param parent The parent frame of this dialog. + */ + public JDialog(Frame parent) { + super(parent); + } + + /** + * Creates a new dialog with a title. + * @param parent The parent frame of this dialog. + * @param title The title of the dialog window. + */ + public JDialog(Frame parent, String title) { + super(parent, title); + } + + /** + * Centers the dialog on its parent frame. + */ + public final void centorOnParent() { + Container parent = getParent(); + + setLocation(parent.getX() + (parent.getWidth() / 2) - (getWidth() / 2), + parent.getY() + (parent.getHeight() / 2) - (getHeight() / 2)); + } +} -- cgit v1.2.3