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