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