initial commit
[instantlauncher.git] / src / main / java / eu / svjatoslav / instantlauncher / menu / Menu.java
1 package eu.svjatoslav.instantlauncher.menu;
2
3 import java.awt.Color;
4 import java.awt.Dimension;
5 import java.awt.event.MouseEvent;
6 import java.awt.event.MouseListener;
7 import java.io.File;
8 import java.util.Arrays;
9 import java.util.Comparator;
10 import java.util.HashSet;
11 import java.util.Set;
12
13 import javax.swing.Box;
14 import javax.swing.BoxLayout;
15 import javax.swing.JButton;
16 import javax.swing.JPanel;
17 import javax.swing.SwingConstants;
18 import javax.swing.border.EmptyBorder;
19
20 import eu.svjatoslav.commons.gui.dialog.ExceptionDialog;
21 import eu.svjatoslav.instantlauncher.Utils;
22
23 public class Menu {
24
25     public static final Color BUTTON_BG_DIRECTORY = new Color(0, 0, 60);
26     public static final Color BUTTON_BG_DIRECTORY_SELECTED = new Color(0, 0, 100);
27
28     public static final Color BUTTON_BG_LINK = new Color(60, 60, 0);
29     public static final Color BUTTON_BG_LINK_SELECTED = new Color(100, 100, 0);
30
31     public static final Color BUTTON_BG_EXECUTABLE_FILE = new Color(60, 0, 0);
32     public static final Color BUTTON_BG_EXECUTABLE_FILE_SELECTED = new Color(100, 0, 0);
33
34     public static final Color BUTTON_BG_NONEXECUTABLE_FILE = new Color(0, 60, 0);
35     public static final Color BUTTON_BG_NONEXECUTABLE_FILE_SELECTED = new Color(0, 100, 0);
36
37     public static final Dimension SIZE_BUTTON = new Dimension(200, 30);
38     public static final Dimension SIZE_MENU_PANEL = new Dimension(210, 900);
39
40     private JPanel menuPanel;
41
42     public JButton selectedButton;
43     public File selectedFile;
44
45     private final Set<MenuListener> menuListeners = new HashSet<MenuListener>();
46
47     public Menu(final File directory) {
48         buildContentPanel(directory);
49     };
50
51     /**
52      * <pre>
53      * Assign specific colors to:
54      *    Directory
55      *    Executable file
56      *    Non executable file
57      * </pre>
58      */
59     public static Color getFileColor(final File file, final boolean selected) {
60         if (file.isDirectory()) {
61             if (selected) {
62                 return BUTTON_BG_DIRECTORY_SELECTED;
63             } else {
64                 return BUTTON_BG_DIRECTORY;
65             }
66         }
67
68         if (file.isFile()) {
69             if (file.canExecute()) {
70                 if (selected) {
71                     return BUTTON_BG_EXECUTABLE_FILE_SELECTED;
72                 } else {
73                     return BUTTON_BG_EXECUTABLE_FILE;
74                 }
75             } else {
76                 if (selected) {
77                     return BUTTON_BG_NONEXECUTABLE_FILE_SELECTED;
78                 } else {
79                     return BUTTON_BG_NONEXECUTABLE_FILE;
80                 }
81             }
82         }
83
84         if (selected) {
85             return BUTTON_BG_LINK_SELECTED;
86         } else {
87             return BUTTON_BG_LINK;
88         }
89     }
90
91     public void addMenuListener(final MenuListener menuListener) {
92         menuListeners.add(menuListener);
93     }
94
95     public JButton buildButton(final File file) {
96         JButton button;
97         if (file.isDirectory()) {
98             button = new JButton("[ " + file.getName() + " ]");
99         } else {
100             button = new JButton(file.getName());
101         }
102
103         button.setBackground(getFileColor(file, false));
104         button.setForeground(new Color(255, 255, 255));
105
106         button.setBorder(new EmptyBorder(5, 10, 5, 10));
107
108         final Menu.ButtonMouseListener mouseListener = new ButtonMouseListener(button, this, file);
109         button.addMouseListener(mouseListener);
110
111         button.setHorizontalTextPosition(SwingConstants.CENTER);
112
113         // set button size
114         Utils.setComponentSize(button, SIZE_BUTTON);
115
116         return button;
117     }
118
119     private void buildContentPanel(final File directory) {
120         menuPanel = new JPanel();
121
122         Utils.setComponentSize(menuPanel, SIZE_MENU_PANEL);
123
124         final BoxLayout layout = new BoxLayout(menuPanel, BoxLayout.Y_AXIS);
125         menuPanel.setLayout(layout);
126         menuPanel.setBackground(Color.BLACK);
127
128         final File[] listFiles = directory.listFiles();
129
130         // Sort files by name
131         Arrays.sort(listFiles, new Comparator<File>() {
132             @Override
133             public int compare(final File f1, final File f2) {
134
135                 // directories come before files
136                 if (f1.isFile() && f2.isDirectory()) {
137                     return 1;
138                 }
139                 if (f2.isFile() && f1.isDirectory()) {
140                     return -1;
141                 }
142
143                 // order by file name
144                 return f1.getName().toUpperCase().compareTo(f2.getName().toUpperCase());
145             }
146         });
147
148         // add files to the panel
149         for (final File file : listFiles) {
150             // ignore hidden files
151             if (!file.getName().startsWith(".")) {
152                 menuPanel.add(Box.createVerticalStrut(10));
153                 menuPanel.add(buildButton(file));
154             }
155         }
156     }
157
158     public JPanel getMenuPanel() {
159         return menuPanel;
160     }
161
162     public JButton getSelectedButton() {
163         return selectedButton;
164     }
165
166     public File getSelectedFile() {
167         return selectedFile;
168     }
169
170     public void notifyAlternativeEventListeners(final File chosenFile) {
171         for (final MenuListener menuListener : menuListeners) {
172             menuListener.menuItemSelectedAlternative(this, chosenFile);
173         }
174     }
175
176     public void notifyEventListeners(final File chosenFile) {
177         for (final MenuListener menuListener : menuListeners) {
178             menuListener.menuItemSelected(this, chosenFile);
179         }
180     }
181
182     public void setSelected(final JButton selectedButton, final File selectedFile) {
183         this.selectedButton = selectedButton;
184         this.selectedFile = selectedFile;
185     }
186
187     public static class ButtonMouseListener implements MouseListener {
188
189         JButton parentButton;
190         Menu parentMenu;
191         File file;
192
193         public ButtonMouseListener(final JButton button, final Menu parentMenu, final File file) {
194             parentButton = button;
195             this.parentMenu = parentMenu;
196             this.file = file;
197         }
198
199         @Override
200         public void mouseClicked(final MouseEvent e) {
201             try {
202
203                 if (e.getButton() == 1) {
204                     parentMenu.notifyEventListeners(file);
205                 }
206                 if (e.getButton() == 3) {
207                     parentMenu.notifyAlternativeEventListeners(file);
208                 }
209             } catch (final Exception ex) {
210                 ExceptionDialog.showException(ex);
211             }
212         }
213
214         @Override
215         public void mouseEntered(final MouseEvent e) {
216             try {
217                 if (parentButton != parentMenu.getSelectedButton()) {
218
219                     if (parentMenu.getSelectedButton() != null) {
220                         parentMenu.getSelectedButton().setBackground(getFileColor(parentMenu.getSelectedFile(), false));
221                     }
222
223                     parentMenu.setSelected(parentButton, file);
224                     parentButton.setBackground(getFileColor(file, true));
225
226                     if (file.isDirectory()) {
227                         parentMenu.notifyEventListeners(file);
228                     }
229                 }
230             } catch (final Exception ex) {
231                 ExceptionDialog.showException(ex);
232             }
233         }
234
235         @Override
236         public void mouseExited(final MouseEvent e) {
237         }
238
239         @Override
240         public void mousePressed(final MouseEvent e) {
241         }
242
243         @Override
244         public void mouseReleased(final MouseEvent e) {
245         }
246
247     }
248
249 }