View Javadoc

1   /* OpenLogViewer
2    *
3    * Copyright 2011
4    *
5    * This file is part of the OpenLogViewer project.
6    *
7    * OpenLogViewer software is free software: you can redistribute it and/or modify
8    * it under the terms of the GNU General Public License as published by
9    * the Free Software Foundation, either version 3 of the License, or
10   * (at your option) any later version.
11   *
12   * OpenLogViewer software is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Public License for more details.
16   *
17   * You should have received a copy of the GNU General Public License
18   * along with any OpenLogViewer software.  If not, see http://www.gnu.org/licenses/
19   *
20   * I ask that if you make any changes to this file you fork the code on github.com!
21   *
22   */
23  package org.diyefi.openlogviewer.propertypanel;
24  
25  import java.awt.BorderLayout;
26  import java.awt.Color;
27  import java.awt.Dimension;
28  import java.awt.FlowLayout;
29  import java.awt.event.ActionEvent;
30  import java.awt.event.ActionListener;
31  import java.awt.event.MouseEvent;
32  import java.awt.event.MouseListener;
33  import java.io.BufferedWriter;
34  import java.io.File;
35  import java.io.FileNotFoundException;
36  import java.io.FileReader;
37  import java.io.FileWriter;
38  import java.io.IOException;
39  import java.util.ArrayList;
40  import java.util.Collections;
41  import java.util.List;
42  import java.util.ResourceBundle;
43  import java.util.Scanner;
44  
45  import javax.swing.BorderFactory;
46  import javax.swing.JButton;
47  import javax.swing.JCheckBox;
48  import javax.swing.JColorChooser;
49  import javax.swing.JComboBox;
50  import javax.swing.JFrame;
51  import javax.swing.JLabel;
52  import javax.swing.JMenu;
53  import javax.swing.JMenuBar;
54  import javax.swing.JMenuItem;
55  import javax.swing.JOptionPane;
56  import javax.swing.JPanel;
57  import javax.swing.JScrollPane;
58  import javax.swing.JTextField;
59  
60  import org.apache.commons.lang3.StringUtils;
61  import org.diyefi.openlogviewer.Keys;
62  import org.diyefi.openlogviewer.OpenLogViewer;
63  import org.diyefi.openlogviewer.Text;
64  
65  public class PropertiesPane extends JFrame {
66  	private static final long serialVersionUID = 1L;
67  
68  	private final JPanel propertyView;
69  	private final ResourceBundle labels;
70  	private final String settingsDirectory;
71  
72  	private File OLVProperties;
73  	private List<SingleProperty> properties;
74  	private List<SingleProperty> removeProperties;
75  
76  	public PropertiesPane(final ResourceBundle labels, final String settingsDirectory) {
77  		super(labels.getString(Text.VIEW_MENU_ITEM_SCALE_AND_COLOR_NAME));
78  
79  		this.labels = labels;
80  		this.settingsDirectory = settingsDirectory;
81  
82  		setDefaultCloseOperation(HIDE_ON_CLOSE);
83  		setPreferredSize(new Dimension(350, 500));
84  		setSize(new Dimension(550, 500));
85  		setJMenuBar(createMenuBar());
86  
87  		final JPanel propertyPanel = new JPanel();
88  		propertyPanel.setLayout(new BorderLayout());
89  		OpenLogViewer.setupWindowKeyBindings(this);
90  
91  		propertyView = new JPanel();
92  		propertyView.setPreferredSize(new Dimension(400, 0));
93  		propertyView.setLayout(new FlowLayout(FlowLayout.LEFT));
94  
95  		final JScrollPane jsp = new JScrollPane(propertyView);
96  		propertyPanel.add(jsp, BorderLayout.CENTER);
97  		propertyPanel.add(createAcceptPanel(), BorderLayout.SOUTH);
98  		add(propertyPanel);
99  	}
100 
101 	public final void setProperties(final List<SingleProperty> p) {
102 		removeProperties = new ArrayList<SingleProperty>();
103 		properties = p;
104 		setupForLoad();
105 	}
106 
107 	private void setupForLoad() {
108 		try {
109 			final String systemDelim = File.separator;
110 			final File homeDir = new File(System.getProperty(Keys.USER_HOME));
111 
112 			if (!homeDir.exists() || !homeDir.canRead() || !homeDir.canWrite()) {
113 				System.out.println(labels.getString(Text.HOME_DIRECTORY_NOT_ACCESSIBLE));
114 
115 			} else {
116 				OLVProperties = new File(homeDir.getAbsolutePath() + systemDelim + settingsDirectory);
117 			}
118 
119 			if (!OLVProperties.exists()) {
120 				try {
121 					if (OLVProperties.mkdir()) {
122 						OLVProperties = new File(homeDir.getAbsolutePath() + systemDelim + settingsDirectory + systemDelim + "OLVProperties.olv");
123 						if (OLVProperties.createNewFile()) {
124 							loadProperties();
125 						}
126 					} else {
127 						throw new RuntimeException(labels.getString(Text.FAILED_TO_CREATE_DIRECTORY_MESSAGE));
128 					}
129 				} catch (IOException ioe) {
130 					System.out.print(ioe.getMessage());
131 				}
132 			} else {
133 				OLVProperties = new File(homeDir.getAbsolutePath() + systemDelim + settingsDirectory + systemDelim + "OLVProperties.olv");
134 				OLVProperties.createNewFile(); // Just in case the file does not exist yet. This won't overwrite an existing file.
135 				loadProperties();
136 			}
137 		} catch (Exception e) {
138 			System.out.print(e.getMessage());
139 		}
140 	}
141 
142 	private JMenuBar createMenuBar() {
143 		final JMenuBar propMenuBar = new JMenuBar();
144 		final JMenu options = new JMenu(labels.getString(Text.OPTIONS_MENU_NAME));
145 		final JMenuItem addProperty = new JMenuItem(labels.getString(Text.OPTIONS_MENU_ITEM_ADD_PROPERTY_NAME));
146 		final JMenuItem removeProperty = new JMenuItem(labels.getString(Text.OPTIONS_MENU_ITEM_REMOVE_PROPERTIES_NAME));
147 
148 		propMenuBar.add(options);
149 
150 		addProperty.addActionListener(new ActionListener() {
151 			@Override
152 			public void actionPerformed(final ActionEvent evt) {
153 				final String s = (String) JOptionPane.showInputDialog(rootPane, labels.getString(Text.ENTER_HEADER_FOR_PROPERTY));
154 				if (StringUtils.isNotBlank(s)) {
155 					final SingleProperty newprop = new SingleProperty();
156 					newprop.setHeader(s);
157 					addProperty(newprop);
158 				}
159 			}
160 		});
161 
162 		removeProperty.addActionListener(new ActionListener() {
163 
164 			@Override
165 			public void actionPerformed(final ActionEvent evt) {
166 				removePropertyPanels();
167 			}
168 		});
169 
170 		options.add(addProperty);
171 		options.add(removeProperty);
172 
173 		return propMenuBar;
174 	}
175 
176 	private JPanel createAcceptPanel() {
177 		final JPanel aPanel = new JPanel();
178 		aPanel.setPreferredSize(new Dimension(500, 32));
179 		aPanel.setLayout(new FlowLayout(FlowLayout.RIGHT, 2, 2));
180 
181 		final JButton ok = new JButton(labels.getString(Text.OK_BUTTON));
182 		final JButton cancel = new JButton(labels.getString(Text.CANCEL_BUTTON));
183 
184 		ok.addActionListener(new ActionListener() {
185 
186 			@Override
187 			public void actionPerformed(final ActionEvent e) {
188 				OpenLogViewer.getInstance().getPropertyPane().save();
189 				OpenLogViewer.getInstance().getPropertyPane().setVisible(false);
190 			}
191 		});
192 
193 		cancel.addActionListener(new ActionListener() {
194 
195 			@Override
196 			public void actionPerformed(final ActionEvent e) {
197 
198 				OpenLogViewer.getInstance().getPropertyPane().resetProperties();
199 				OpenLogViewer.getInstance().getPropertyPane().setVisible(false);
200 			}
201 		});
202 
203 		aPanel.add(cancel);
204 		aPanel.add(ok);
205 
206 		return aPanel;
207 	}
208 
209 	private void loadProperties() {
210 		try {
211 			final Scanner scan = new Scanner(new FileReader(OLVProperties));
212 
213 			while (scan.hasNext()) {
214 				final String[] propLine = scan.nextLine().split("=");
215 				final SingleProperty sp = new SingleProperty();
216 				final String[] prop = propLine[1].split(",");
217 				sp.setHeader(propLine[0]);
218 				sp.setColor(new Color(
219 						Integer.parseInt(prop[0]),
220 						Integer.parseInt(prop[1]),
221 						Integer.parseInt(prop[2])));
222 				sp.setMin(Double.parseDouble(prop[3]));
223 				sp.setMax(Double.parseDouble(prop[4]));
224 				sp.setTrackIndex(Integer.parseInt(prop[5]));
225 				sp.setActive(Boolean.parseBoolean(prop[6]));
226 				addProperty(sp);
227 			}
228 
229 			scan.close();
230 		} catch (FileNotFoundException fnf) {
231 			System.out.print(fnf.toString());
232 			throw new RuntimeException(fnf);
233 		}
234 	}
235 
236 	public final void save() {
237 		try {
238 			removeProperties.clear();
239 			updateProperties();
240 			final FileWriter fstream = new FileWriter(OLVProperties);
241 			final BufferedWriter out = new BufferedWriter(fstream);
242 
243 			for (int i = 0; i < properties.size(); i++) {
244 				out.write(properties.get(i).toString());
245 				out.newLine();
246 			}
247 
248 			out.close();
249 		} catch (IOException e) {
250 			System.err.println(labels.getString(Text.ERROR) + e.getMessage());
251 			throw new RuntimeException(labels.getString(Text.IO_ISSUE_SAVING_PROPERTY), e);
252 		}
253 	}
254 
255 	private void updateProperties() {
256 		for (int i = 0; i < propertyView.getComponentCount(); i++) {
257 			final PropertyPanel pp = (PropertyPanel) propertyView.getComponent(i);
258 			pp.updateSP();
259 		}
260 	}
261 
262 	public final void resetProperties() {
263 		for (int i = 0; i < propertyView.getComponentCount(); i++) {
264 			final PropertyPanel pp = (PropertyPanel) propertyView.getComponent(i);
265 			pp.reset();
266 		}
267 		if (!removeProperties.isEmpty()) {
268 			for (int i = 0; i < removeProperties.size(); i++) {
269 				addProperty(removeProperties.get(i));
270 			}
271 			removeProperties.clear();
272 		}
273 	}
274 
275 	private PropertyPanel exists(final SingleProperty sp) {
276 
277 		for (int i = 0; i < propertyView.getComponentCount(); i++) {
278 			final PropertyPanel pp = (PropertyPanel) propertyView.getComponent(i);
279 			if (pp.getSp().getHeader().equalsIgnoreCase(sp.getHeader())) {
280 				return pp;
281 			}
282 		}
283 		return null;
284 	}
285 
286 	public final void addProperty(final SingleProperty sp) {
287 		final PropertyPanel pp = exists(sp);
288 		if (pp == null) {
289 			properties.add(sp);
290 			Collections.sort(properties);
291 			propertyView.add(new PropertyPanel(sp), properties.indexOf(sp));
292 			propertyView.setPreferredSize(new Dimension(propertyView.getPreferredSize().width, propertyView.getPreferredSize().height + 60));
293 			propertyView.revalidate();
294 		} else {
295 			for (int i = 0; i < properties.size(); i++) {
296 				if (properties.get(i).getHeader().equalsIgnoreCase(sp.getHeader())) {
297 					properties.set(i, sp);
298 				}
299 			}
300 			pp.setSp(sp);
301 			pp.reset();
302 		}
303 	}
304 
305 	public final void addPropertyAndSave(final SingleProperty sp) {
306 		addProperty(sp);
307 		save();
308 	}
309 
310 	private void removeProperty(final SingleProperty sp) {
311 		if (properties.contains(sp)) {
312 			properties.remove(sp);
313 		}
314 	}
315 
316 	private void removePropertyPanels() {
317 		int componentIndex = 0;
318 		while (componentIndex < propertyView.getComponentCount()) {
319 			final PropertyPanel pp = (PropertyPanel) propertyView.getComponent(componentIndex);
320 			if (pp.getCheck().isSelected()) {
321 				if (!removeProperties.contains(pp.getSp())) {
322 					removeProperties.add(pp.getSp());
323 				}
324 
325 				removeProperty(pp.getSp()); // Move this to add to a queue of things to remove, in case of cancel
326 				propertyView.remove(propertyView.getComponent(componentIndex));
327 				propertyView.setPreferredSize(new Dimension(propertyView.getPreferredSize().width, propertyView.getPreferredSize().height - 60));
328 				propertyView.revalidate();
329 			} else {
330 				componentIndex++;
331 			}
332 		}
333 		propertyView.repaint();
334 	}
335 
336 	private final class PropertyPanel extends JPanel implements Comparable<PropertyPanel> {
337 		private static final long serialVersionUID = 1L;
338 		private SingleProperty sp;
339 		private final JCheckBox check;
340 		private final JPanel colorBox;
341 		private final JTextField minBox;
342 		private final JTextField maxBox;
343 		private final JTextField trackBox;
344 		private final JComboBox activeBox;
345 
346 		public PropertyPanel(final SingleProperty sp) {
347 			this.sp = sp;
348 			setLayout(new FlowLayout(FlowLayout.LEFT, 10, 2));
349 			setBorder(BorderFactory.createTitledBorder(sp.getHeader()));
350 			setPreferredSize(new Dimension(500, 50));
351 			final JLabel minLabel = new JLabel(labels.getString(Text.MIN_PROPERTY));
352 			final JLabel maxLabel = new JLabel(labels.getString(Text.MAX_PROPERTY));
353 			final JLabel colorLabel = new JLabel(labels.getString(Text.COLOR_PROPERTY));
354 			final JLabel splitLabel = new JLabel(labels.getString(Text.SPLIT_PROPERTY));
355 			final JLabel activeLabel = new JLabel(labels.getString(Text.ACTIVE_PROPERTY));
356 			trackBox = new JTextField();
357 			trackBox.setPreferredSize(new Dimension(15, 20));
358 			trackBox.setText(Integer.toString(sp.getTrackIndex()));
359 			minBox = new JTextField();
360 			minBox.setPreferredSize(new Dimension(50, 20));
361 			minBox.setText(Double.toString(sp.getMin()));
362 			maxBox = new JTextField();
363 			maxBox.setPreferredSize(new Dimension(50, 20));
364 			maxBox.setText(Double.toString(sp.getMax()));
365 			colorBox = new JPanel();
366 			colorBox.setBackground(sp.getColor());
367 			colorBox.setPreferredSize(new Dimension(30, 20));
368 			final String[] tf = {labels.getString(Text.TRUE), labels.getString(Text.FALSE)};
369 			activeBox = new JComboBox(tf);
370 
371 			if (sp.isActive()) {
372 				activeBox.setSelectedIndex(1);
373 			}
374 
375 			activeBox.setPreferredSize(new Dimension(60, 20));
376 			check = new JCheckBox();
377 
378 			colorBox.addMouseListener(new MouseListener() {
379 
380 				@Override
381 				public void mouseReleased(final MouseEvent e) {
382 					final Color newColor = JColorChooser.showDialog(
383 							OpenLogViewer.getInstance().getOptionFrame(),
384 							labels.getString(Text.CHOOSE_NEW_COLOR), colorBox.getBackground());
385 					if (newColor != null) {
386 						colorBox.setBackground(newColor);
387 					}
388 				}
389 
390 				@Override
391 				public void mouseClicked(final MouseEvent e) {
392 				}
393 
394 				@Override
395 				public void mouseEntered(final MouseEvent e) {
396 				}
397 
398 				@Override
399 				public void mouseExited(final MouseEvent e) {
400 				}
401 
402 				@Override
403 				public void mousePressed(final MouseEvent e) {
404 				}
405 			});
406 
407 			add(colorLabel);
408 			add(colorBox);
409 			add(minLabel);
410 			add(minBox);
411 			add(maxLabel);
412 			add(maxBox);
413 			add(splitLabel);
414 			add(trackBox);
415 			add(activeLabel);
416 			add(activeBox);
417 			add(check);
418 		}
419 
420 		public JCheckBox getCheck() {
421 			return check;
422 		}
423 
424 		public SingleProperty getSp() {
425 			return sp;
426 		}
427 
428 		public void setSp(final SingleProperty sp) {
429 			this.sp = sp;
430 		}
431 
432 		public void updateSP() {
433 			sp.setMin(Double.parseDouble(minBox.getText()));
434 			sp.setMax(Double.parseDouble(maxBox.getText()));
435 			sp.setColor(colorBox.getBackground());
436 			sp.setTrackIndex(Integer.parseInt(trackBox.getText()));
437 			final String active = (String) activeBox.getSelectedItem();
438 			sp.setActive(Boolean.parseBoolean(active));
439 		}
440 
441 		public void reset() {
442 			minBox.setText(Double.toString(sp.getMin()));
443 			maxBox.setText(Double.toString(sp.getMax()));
444 			colorBox.setBackground(sp.getColor());
445 			trackBox.setText(Integer.toString(sp.getTrackIndex()));
446 			activeBox.setSelectedItem(Boolean.toString(sp.isActive()));
447 		}
448 
449 		@Override
450 		public int compareTo(final PropertyPanel pp) {
451 			return this.sp.getHeader().compareToIgnoreCase(pp.getSp().getHeader());
452 		}
453 	}
454 }