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.optionpanel;
24  
25  import java.awt.Color;
26  import java.awt.Component;
27  import java.awt.Dimension;
28  import java.awt.Point;
29  import java.awt.event.ActionEvent;
30  import java.awt.event.ActionListener;
31  import java.awt.event.ContainerEvent;
32  import java.awt.event.ContainerListener;
33  import java.awt.event.MouseEvent;
34  import java.awt.event.MouseListener;
35  import java.awt.event.MouseMotionAdapter;
36  
37  import java.text.DecimalFormatSymbols;
38  import java.util.ArrayList;
39  import java.util.Iterator;
40  import java.util.List;
41  import java.util.ResourceBundle;
42  
43  import javax.swing.JFrame;
44  import javax.swing.JPanel;
45  import javax.swing.JButton;
46  import javax.swing.JLayeredPane;
47  import javax.swing.JScrollPane;
48  import javax.swing.JLabel;
49  import javax.swing.JInternalFrame;
50  import javax.swing.JTextField;
51  import javax.swing.JColorChooser;
52  import javax.swing.BorderFactory;
53  
54  import org.diyefi.openlogviewer.OpenLogViewer;
55  import org.diyefi.openlogviewer.Text;
56  import org.diyefi.openlogviewer.genericlog.GenericDataElement;
57  import org.diyefi.openlogviewer.genericlog.GenericLog;
58  import org.diyefi.openlogviewer.propertypanel.SingleProperty;
59  
60  public class OptionFrameV2 extends JFrame {
61  	private static final long serialVersionUID = 1L;
62  
63  	private static final int NUMBER_OF_COLS_OF_FREEEMS_FIELDS = 6; // Clearly a hack, but just to clarify and parameterise the existing math...
64  	private static final int HEIGHT_IN_FIELDS = 18;
65  	private static final int NUMBER_OF_ADD_BUTTONS = 1;
66  
67  	private static final int WIDTH_OF_BOXES = NUMBER_OF_COLS_OF_FREEEMS_FIELDS;
68  	private static final int HEIGHT_OF_BOXES = 2;
69  	private static final int MAX_NUMBER_OF_BOXES = WIDTH_OF_BOXES * HEIGHT_OF_BOXES;
70  
71  
72  	private static final int WTF = 4;  // Don't ask me...
73  	private static final int WTF2 = 3; // No fucking idea AT ALL...
74  
75  	private static final int COMP_HEIGHT = 20;     // every thing except panels are 20 px high; default 20
76  	private static final int COMP_WIDTH = 200;     // used for buttons and such that are in; default 200
77  	private static final int PANEL_WIDTH = 140;    // panels are 120 px wide buttons and labels are also; default 120
78  	private static final int PANEL_HEIGHT = 120;   // panels are 120 px high;default 120
79  	private static final int SCROLL_BAR_SIZE = 16; // Measured
80  
81  	// Both are wrong for scroll bars... probably need an event to handle that?
82  	private static final int WIDTH_OF_WINDOW = (NUMBER_OF_COLS_OF_FREEEMS_FIELDS * PANEL_WIDTH);
83  	private static final int HEIGHT_OF_WINDOW = ((PANEL_HEIGHT * HEIGHT_OF_BOXES) + (COMP_HEIGHT * (HEIGHT_IN_FIELDS + NUMBER_OF_ADD_BUTTONS)));
84  
85  	private static final char DS = DecimalFormatSymbols.getInstance().getDecimalSeparator();
86  	private static final String UNKNOWN_DIGIT = "-"; // String, not char, so we can append below
87  	private static final String UNKNOWN_NUMBER = UNKNOWN_DIGIT + DS + UNKNOWN_DIGIT;
88  
89  	private static final String DROP_PREFIX = "Drop";
90  
91  	private final ResourceBundle labels;
92  	private final JFrame thisRef;
93  	private final JPanel inactiveHeaders;
94  	private final ModifyGraphPane infoPanel;
95  	private JButton addDivisionButton;
96  
97  	private final JLayeredPane layeredPane;
98  	private final List<JPanel> activePanelList;
99  
100 	private final ActionListener addDivisionListener = new ActionListener() {
101 		@Override
102 		public void actionPerformed(final ActionEvent e) {
103 			addActiveHeaderPanel();
104 		}
105 	};
106 
107 	private final ActionListener remDivisionListener = new ActionListener() {
108 		@Override
109 		public void actionPerformed(final ActionEvent e) {
110 			remActiveHeaderPanel(e);
111 		}
112 	};
113 
114 	private final ContainerListener addRemoveListener = new ContainerListener() {
115 		@Override
116 		public void componentAdded(final ContainerEvent e) {
117 
118 			if (e.getChild() != null) {
119 				if (e.getChild() instanceof ActiveHeaderLabel) {
120 					((ActiveHeaderLabel) e.getChild()).setEnabled(true);
121 					((ActiveHeaderLabel) e.getChild()).setSelected(true);
122 					((ActiveHeaderLabel) e.getChild()).getGDE().setTrackIndex(activePanelList.indexOf(e.getChild().getParent()));
123 				}
124 			}
125 		}
126 
127 		@Override
128 		public void componentRemoved(final ContainerEvent e) {
129 			if (e.getChild() != null) {
130 				if (e.getChild() instanceof ActiveHeaderLabel) {
131 					((ActiveHeaderLabel) e.getChild()).setEnabled(false);
132 					((ActiveHeaderLabel) e.getChild()).setSelected(false);
133 				}
134 				for (int i = 0; i < e.getContainer().getComponentCount(); i++) {
135 					if (e.getContainer().getComponent(i) instanceof ActiveHeaderLabel) {
136 						e.getContainer().getComponent(i).setLocation(0, i * COMP_HEIGHT);
137 					}
138 				}
139 			}
140 		}
141 	};
142 
143 	public OptionFrameV2(final ResourceBundle labels) {
144 		super(OptionFrameV2.class.getSimpleName());
145 		this.labels = labels;
146 
147 		setSize(WIDTH_OF_WINDOW + WTF2, HEIGHT_OF_WINDOW + COMP_HEIGHT + SCROLL_BAR_SIZE + WTF); // why??? comp height, why??? just why???
148 		setPreferredSize(this.getSize());
149 
150 		setDefaultCloseOperation(HIDE_ON_CLOSE);
151 		thisRef = this;
152 		activePanelList = new ArrayList<JPanel>();
153 		layeredPane = new JLayeredPane();
154 		layeredPane.setPreferredSize(new Dimension(WIDTH_OF_WINDOW, HEIGHT_OF_WINDOW));
155 		OpenLogViewer.setupWindowKeyBindings(this);
156 
157 		final JScrollPane scroll = new JScrollPane(layeredPane);
158 
159 		inactiveHeaders = initHeaderPanel();
160 		layeredPane.add(inactiveHeaders);
161 		infoPanel = new ModifyGraphPane();
162 		add(infoPanel);
163 
164 		this.add(scroll);
165 		addActiveHeaderPanel();
166 	}
167 
168 	private JPanel initHeaderPanel() {
169 		final JPanel ih = new JPanel();
170 		ih.setLayout(null);
171 		ih.setName(DROP_PREFIX + "InactiveHeaderPanel");
172 		addDivisionButton = new JButton(labels.getString(Text.ADD_DIVISION_BUTTON));
173 		addDivisionButton.setBounds(0, 0, PANEL_WIDTH, COMP_HEIGHT);
174 		addDivisionButton.addActionListener(addDivisionListener);
175 		ih.add(addDivisionButton);
176 		ih.setBounds(0, 0, 1280, (COMP_HEIGHT * (HEIGHT_IN_FIELDS + NUMBER_OF_ADD_BUTTONS)));
177 		return ih;
178 	}
179 
180 	private void addActiveHeaderPanel() {
181 		if (activePanelList.size() < MAX_NUMBER_OF_BOXES) {
182 			final int row = activePanelList.size() / WIDTH_OF_BOXES;
183 			final int col = activePanelList.size() % WIDTH_OF_BOXES; // TODO this is duplicated code!!!! I found out because I got two behaviors at once...
184 			final JPanel activePanel = new JPanel();
185 			activePanelList.add(activePanel);
186 			if (OpenLogViewer.getInstance() != null) {
187 				OpenLogViewer.getInstance().getMultiGraphLayeredPane().setTrackCount(activePanelList.size());
188 			}
189 			activePanel.setLayout(null);
190 			activePanel.setName(DROP_PREFIX + " ActivePanel " + activePanelList.indexOf(activePanel));
191 			activePanel.addContainerListener(addRemoveListener);
192 
193 			activePanel.setBounds((col * PANEL_WIDTH), inactiveHeaders.getHeight() + PANEL_HEIGHT * row, PANEL_WIDTH, PANEL_HEIGHT);
194 			activePanel.setBackground(Color.DARK_GRAY);
195 			final JButton removeButton = new JButton(labels.getString(Text.REMOVE_DIVISION_BUTTON));
196 			removeButton.setToolTipText(labels.getString(Text.CLICK_TO_REMOVE_DIVISION));
197 			removeButton.setBounds(0, 0, PANEL_WIDTH, COMP_HEIGHT);
198 			removeButton.addActionListener(remDivisionListener);
199 			activePanel.add(removeButton);
200 			layeredPane.add(activePanel);
201 
202 			if (activePanelList.size() == MAX_NUMBER_OF_BOXES) {
203 				addDivisionButton.setEnabled(false);
204 			}
205 		}
206 	}
207 
208 	private void remActiveHeaderPanel(final ActionEvent e) {
209 		final JPanel panel = (JPanel) ((JButton) e.getSource()).getParent();
210 		activePanelList.remove(panel);
211 		OpenLogViewer.getInstance().getMultiGraphLayeredPane().setTrackCount(activePanelList.size());
212 
213 		for (int i = 0; i < panel.getComponentCount();) {
214 			if (panel.getComponent(i) instanceof ActiveHeaderLabel) {
215 				final ActiveHeaderLabel GCB = (ActiveHeaderLabel) panel.getComponent(i);
216 				GCB.getInactivePanel().add(GCB);
217 				GCB.setLocation(GCB.getInactiveLocation());
218 				GCB.setSelected(false);
219 				GCB.getGDE().setDisplayColor(null);
220 			} else if (panel.getComponent(i) instanceof JButton) {
221 				panel.remove(panel.getComponent(i)); // removes the button
222 			} else {
223 				i++;
224 			}
225 		}
226 
227 		panel.getParent().remove(panel);
228 		for (int i = 0; i < activePanelList.size(); i++) {
229 			final int row = i / WIDTH_OF_BOXES;
230 			final int col = i % WIDTH_OF_BOXES;
231 			activePanelList.get(i).setLocation((col * PANEL_WIDTH), inactiveHeaders.getHeight() + PANEL_HEIGHT * row);
232 		}
233 
234 		if (!addDivisionButton.isEnabled()) {
235 			addDivisionButton.setEnabled(true);
236 		}
237 
238 		// Move this to events eventually,
239 		for (int i = 0; i < activePanelList.size(); i++) {
240 			final JPanel active = activePanelList.get(i);
241 			if (active.getComponentCount() > 1) {
242 				for (int j = 0; j < active.getComponentCount(); j++) {
243 					if (active.getComponent(j) instanceof ActiveHeaderLabel) {
244 						((ActiveHeaderLabel) active.getComponent(j)).getGDE().setTrackIndex(i);
245 					}
246 				}
247 			}
248 		}
249 
250 		if (activePanelList.isEmpty()) {
251 			addActiveHeaderPanel();
252 		}
253 
254 		this.repaint();
255 	}
256 
257 	private final MouseMotionAdapter labelAdapter = new MouseMotionAdapter() {
258 
259 		@Override
260 		public void mouseDragged(final MouseEvent e) {
261 			final Component c = e.getComponent();
262 			final ActiveHeaderLabel GCB = (ActiveHeaderLabel) c;
263 			GCB.setDragging(true);
264 			final Point pointNow = layeredPane.getMousePosition();
265 			final Component parent = c.getParent();
266 			if ((e.getModifiers() == 16) && (parent != null) && (pointNow != null)) { // 4 == right mouse button
267 				if (!parent.contains(pointNow.x - parent.getX(), pointNow.y - parent.getY())) {
268 					final Component parentsParent = parent.getParent();
269 					final Component cn = parentsParent.getComponentAt(pointNow);
270 					if (cn instanceof JPanel) {
271 						final JPanel j = (JPanel) cn;
272 						if (j.getName().contains(DROP_PREFIX)) { // implement a better way to do this later
273 							j.add(c); // components cannot share parents so it is automatically removed
274 							// reset the location to where the mouse is, otherwise first pixel when moving to the new jpanel
275 							c.setLocation(
276 									// will cause a location issue reflecting where the panel was in the PREVIOUS panel
277 									pointNow.x - parent.getX() - (c.getWidth() / 2),
278 									pointNow.y - parent.getY() - (c.getHeight() / 2));
279 						}
280 					}
281 				} else {
282 					c.setLocation(c.getX() + e.getX() - (c.getWidth() / 2), c.getY() + e.getY() - (c.getHeight() / 2));
283 				}
284 				thisRef.repaint();
285 			}
286 		}
287 	};
288 
289 	private boolean place(final ActiveHeaderLabel GCB) {
290 		final int x = 0;
291 		int y = COMP_HEIGHT;
292 		while (y < GCB.getParent().getHeight()) {
293 			if (GCB.getParent().getComponentAt(x, y) == GCB.getParent() || GCB.getParent().getComponentAt(x, y) == GCB) {
294 				GCB.setLocation(x, y);
295 				return true;
296 			}
297 			y = y + COMP_HEIGHT;
298 		}
299 		return false;
300 	}
301 
302 	public final void updateFromLog(final GenericLog datalog) {
303 
304 		while (!activePanelList.isEmpty()) {
305 			activePanelList.get(0).removeAll();
306 			layeredPane.remove(activePanelList.get(0));
307 			activePanelList.remove(activePanelList.get(0)); // only did it this way incase things are out of order at any point
308 		}
309 
310 		addDivisionButton.setEnabled(true);
311 
312 		if (inactiveHeaders.getComponentCount() > 1) {
313 			inactiveHeaders.removeAll();
314 			inactiveHeaders.add(this.addDivisionButton);
315 		}
316 		this.addActiveHeaderPanel(); // will be based on highest number of divisions found when properties are applied
317 
318 		final List<ActiveHeaderLabel> tmpList = new ArrayList<ActiveHeaderLabel>();
319 		final Iterator<String> headers = datalog.keySet().iterator();
320 		ActiveHeaderLabel toBeAdded = null;
321 
322 		while (headers.hasNext()) {
323 			final String header = headers.next();
324 			final GenericDataElement GDE = datalog.get(header);
325 			toBeAdded = new ActiveHeaderLabel();
326 
327 			toBeAdded.setName(header);
328 			toBeAdded.setText(header);
329 			toBeAdded.setRef(GDE);
330 			toBeAdded.setEnabled(false); // you are unable to activate a graph in the inacivelist
331 			toBeAdded.addMouseMotionListener(labelAdapter);
332 			if (checkForProperties(GDE)) {
333 				toBeAdded.setBackground(GDE.getDisplayColor());
334 			}
335 			tmpList.add(toBeAdded);
336 		}
337 
338 		int j = 0;
339 		int leftSide = 0;
340 		for (int it = 0; it < tmpList.size(); it++) {
341 			if (COMP_HEIGHT + (COMP_HEIGHT * (j + 1)) > inactiveHeaders.getHeight()) {
342 				j = 0;
343 				leftSide += PANEL_WIDTH;
344 			}
345 
346 			tmpList.get(it).setBounds(leftSide, (COMP_HEIGHT + (COMP_HEIGHT * j)), PANEL_WIDTH, COMP_HEIGHT);
347 			inactiveHeaders.add(tmpList.get(it));
348 			j++;
349 		}
350 
351 		repaint();
352 		setDefaultCloseOperation(ICONIFIED);
353 		OpenLogViewer.getInstance().exitFullScreen();
354 		setVisible(true);
355 	}
356 
357 	private boolean checkForProperties(final GenericDataElement GDE) {
358 		for (int i = 0; i < OpenLogViewer.getInstance().getProperties().size(); i++) {
359 			if (OpenLogViewer.getInstance().getProperties().get(i).getHeader().equals(GDE.getName())) {
360 				GDE.setDisplayColor(OpenLogViewer.getInstance().getProperties().get(i).getColor());
361 				GDE.setDisplayMaxValue(OpenLogViewer.getInstance().getProperties().get(i).getMax());
362 				GDE.setDisplayMinValue(OpenLogViewer.getInstance().getProperties().get(i).getMin());
363 				GDE.setTrackIndex(OpenLogViewer.getInstance().getProperties().get(i).getTrackIndex());
364 
365 				if (OpenLogViewer.getInstance().getProperties().get(i).isActive()) {
366 					return true;
367 				}
368 			}
369 		}
370 		return false;
371 	}
372 
373 	private class ModifyGraphPane extends JInternalFrame {
374 		private static final long serialVersionUID = 1L;
375 
376 		private GenericDataElement GDE;
377 		private ActiveHeaderLabel AHL;
378 		private final JTextField minField;
379 		private final JTextField maxField;
380 		private final JButton colorButton;
381 
382 		private final ActionListener resetButtonListener = new ActionListener() {
383 			@Override
384 			public void actionPerformed(final ActionEvent e) {
385 				if (GDE != null) {
386 					GDE.reset();
387 					minField.setText(Double.toString(GDE.getDisplayMinValue()));
388 					maxField.setText(Double.toString(GDE.getDisplayMaxValue()));
389 				}
390 			}
391 		};
392 
393 		private final ActionListener applyButtonListener = new ActionListener() {
394 			@Override
395 			public void actionPerformed(final ActionEvent e) {
396 				if (GDE != null) {
397 					changeGDEValues();
398 				}
399 			}
400 		};
401 
402 		private final ActionListener saveButtonListener = new ActionListener() {
403 
404 			@Override
405 			public void actionPerformed(final ActionEvent e) {
406 				if (GDE != null) {
407 					changeGDEValues();
408 					OpenLogViewer.getInstance().getPropertyPane().addPropertyAndSave(new SingleProperty(GDE));
409 				}
410 			}
411 		};
412 
413 		private final ActionListener colorButtonListener = new ActionListener() {
414 
415 			@Override
416 			public void actionPerformed(final ActionEvent e) {
417 				final Color c = JColorChooser.showDialog(
418 						new JFrame(),
419 						labels.getString(Text.CHOOSE_BACKGROUND_COLOR),
420 						colorButton.getForeground());
421 				if (c != null) {
422 					colorButton.setForeground(c);
423 				}
424 			}
425 		};
426 
427 		public ModifyGraphPane() {
428 			final JLabel minLabel = new JLabel(labels.getString(Text.DISPLAY_MIN));
429 			minLabel.setBounds(0, 0, COMP_WIDTH / 2, COMP_HEIGHT);
430 
431 			minField = new JTextField(10);
432 			minField.setBounds(100, 0, COMP_WIDTH / 2, COMP_HEIGHT);
433 
434 			final JLabel maxLabel = new JLabel(labels.getString(Text.DISPLAY_MAX));
435 			maxLabel.setBounds(0, 20, COMP_WIDTH / 2, COMP_HEIGHT);
436 
437 			maxField = new JTextField(10);
438 			maxField.setBounds(100, 20, COMP_WIDTH / 2, COMP_HEIGHT);
439 
440 			colorButton = new JButton(labels.getString(Text.COLOR_BUTTON));
441 			colorButton.addActionListener(colorButtonListener);
442 			colorButton.setBounds(0, 40, COMP_WIDTH, COMP_HEIGHT);
443 
444 			final JButton applyButton = new JButton(labels.getString(Text.APPLY_BUTTON));
445 			applyButton.addActionListener(applyButtonListener);
446 			applyButton.setBounds(0, 60, COMP_WIDTH / 2, COMP_HEIGHT);
447 
448 			final JButton saveButton = new JButton(labels.getString(Text.SAVE_BUTTON));
449 			saveButton.addActionListener(saveButtonListener);
450 			saveButton.setBounds(100, 60, COMP_WIDTH / 2, COMP_HEIGHT);
451 
452 			final JButton resetButton = new JButton(labels.getString(Text.RESET_MIN_MAX_BUTTON));
453 			resetButton.addActionListener(resetButtonListener);
454 			resetButton.setBounds(0, 80, COMP_WIDTH, COMP_HEIGHT);
455 
456 			setLayout(null);
457 
458 			add(minLabel);
459 			add(minField);
460 			add(maxLabel);
461 			add(maxField);
462 			add(colorButton);
463 			add(applyButton);
464 			add(saveButton);
465 			add(resetButton);
466 
467 			setBounds(500, 180, 210, 133);
468 			setMaximizable(false);
469 			setDefaultCloseOperation(JInternalFrame.HIDE_ON_CLOSE);
470 			setClosable(true);
471 		}
472 
473 		public void setGDE(final GenericDataElement gde, final ActiveHeaderLabel ahl) {
474 			this.GDE = gde;
475 			this.AHL = ahl;
476 			this.setTitle(GDE.getName());
477 			minField.setText(String.valueOf(GDE.getDisplayMinValue()));
478 			maxField.setText(String.valueOf(GDE.getDisplayMaxValue()));
479 			colorButton.setForeground(GDE.getDisplayColor());
480 		}
481 
482 		private void changeGDEValues() {
483 			try {
484 				GDE.setDisplayMaxValue(Double.parseDouble(maxField.getText()));
485 			} catch (NumberFormatException e) {
486 				e.printStackTrace();
487 				throw new RuntimeException(labels.getString(Text.OPV2NFES), e); // TODO
488 			}
489 
490 			try {
491 				GDE.setDisplayMinValue(Double.parseDouble(minField.getText()));
492 			} catch (NumberFormatException e) {
493 				e.printStackTrace();
494 				throw new RuntimeException(labels.getString(Text.OPV2NFES), e); // TODO
495 			}
496 
497 			if (!GDE.getDisplayColor().equals(colorButton.getForeground())) {
498 				GDE.setDisplayColor(colorButton.getForeground());
499 				AHL.setForeground(colorButton.getForeground());
500 			}
501 		}
502 	}
503 
504 	private class ActiveHeaderLabel extends JLabel implements Comparable<Object> {
505 		private static final long serialVersionUID = 1L;
506 
507 		private GenericDataElement GDE;
508 		private Point inactiveLocation;
509 		private JPanel previousPanel;
510 		private final JPanel inactivePanel;
511 		private boolean dragging;
512 		private boolean selected;
513 		private final MouseListener selectedListener = new MouseListener() {
514 
515 			@Override
516 			public void mouseClicked(final MouseEvent e) {
517 				if (e.getModifiers() == 16) {
518 					setSelected(!selected);
519 				} else if (e.getModifiers() == 18) {
520 					infoPanel.setGDE(GDE, (ActiveHeaderLabel) e.getSource());
521 					if (!infoPanel.isVisible()) {
522 						infoPanel.setVisible(true);
523 					}
524 				}
525 			}
526 
527 			@Override
528 			public void mouseEntered(final MouseEvent e) {
529 			}
530 
531 			@Override
532 			public void mouseExited(final MouseEvent e) {
533 			}
534 
535 			@Override
536 			public void mousePressed(final MouseEvent e) {
537 				final ActiveHeaderLabel GCB = (ActiveHeaderLabel) e.getSource();
538 				GCB.setPreviousPanel((JPanel) GCB.getParent());
539 			}
540 
541 			@Override
542 			public void mouseReleased(final MouseEvent e) {
543 				final ActiveHeaderLabel GCB = (ActiveHeaderLabel) e.getSource();
544 				if (GCB.isDragging()) {
545 					if (GCB.getParent() == inactiveHeaders) { // moving back to inactive
546 						GCB.setLocation(GCB.getInactiveLocation());
547 						GCB.setSelected(false);
548 						GCB.setEnabled(false);
549 						GCB.getGDE().setDisplayColor(null);
550 					} else { // moving to
551 						if (!place(GCB)) {
552 							if (GCB.getPreviousPanel() != GCB.getParent()) { // if it moved
553 								GCB.getPreviousPanel().add(GCB);
554 								place(GCB);
555 							}
556 							if (GCB.getPreviousPanel() == GCB.getInactivePanel()) {
557 								GCB.setLocation(GCB.getInactiveLocation());
558 								GCB.setEnabled(false);
559 								GCB.setSelected(false);
560 							} else {
561 								place(GCB);
562 							}
563 							thisRef.repaint();
564 						}
565 					}
566 					GCB.setDragging(false);
567 				}
568 			}
569 		};
570 
571 		public ActiveHeaderLabel() {
572 			addMouseListener(selectedListener);
573 			setOpaque(false);
574 			inactivePanel = inactiveHeaders;
575 			dragging = false;
576 			selected = false;
577 			setBorder(BorderFactory.createEtchedBorder(Color.lightGray, Color.white));
578 		}
579 
580 		@Override
581 		public void setBounds(final int x, final int y, final int width, final int height) {
582 			super.setBounds(x, y, width, height);
583 			if (inactiveLocation == null) {
584 				inactiveLocation = new Point(x, y);
585 			}
586 		}
587 
588 		public void setRef(final GenericDataElement GDE) {
589 			this.GDE = GDE;
590 			// this line is here because if the tool tip is never set no mouse events
591 			// will ever be created for tool tips. TODO There HAS to be a better way to do this...
592 			this.setToolTipTextPreliminary();
593 		}
594 
595 		@Override
596 		public String getToolTipText(final MouseEvent e) {
597 			this.setToolTipTextFinal();
598 			return getToolTipText();
599 		}
600 
601 		public void setToolTipTextFinal() {
602 			this.setToolTipText(labels.getString(Text.FIELD_INFORMATION_PART1) + GDE.getName()
603 					+ labels.getString(Text.FIELD_INFORMATION_PART2) + GDE.getMinValue()
604 					+ labels.getString(Text.FIELD_INFORMATION_PART3) + GDE.getDisplayMinValue()
605 					+ labels.getString(Text.FIELD_INFORMATION_PART4) + GDE.getMaxValue()
606 					+ labels.getString(Text.FIELD_INFORMATION_PART5) + GDE.getDisplayMaxValue()
607 					+ labels.getString(Text.FIELD_INFORMATION_PART6));
608 		}
609 
610 		public void setToolTipTextPreliminary() {
611 			this.setToolTipText(labels.getString(Text.FIELD_INFORMATION_PART1) + GDE.getName()
612 					+ labels.getString(Text.FIELD_INFORMATION_PART2) + UNKNOWN_NUMBER
613 					+ labels.getString(Text.FIELD_INFORMATION_PART3) + UNKNOWN_NUMBER
614 					+ labels.getString(Text.FIELD_INFORMATION_PART4) + UNKNOWN_NUMBER
615 					+ labels.getString(Text.FIELD_INFORMATION_PART5) + UNKNOWN_NUMBER
616 					+ labels.getString(Text.FIELD_INFORMATION_PART6));
617 		}
618 
619 		public GenericDataElement getGDE() {
620 			return GDE;
621 		}
622 
623 		public JPanel getPreviousPanel() {
624 			return previousPanel;
625 		}
626 
627 		public void setPreviousPanel(final JPanel previousPanel) {
628 			this.previousPanel = previousPanel;
629 		}
630 
631 		public Point getInactiveLocation() {
632 			return inactiveLocation;
633 		}
634 
635 		public JPanel getInactivePanel() {
636 			return inactivePanel;
637 		}
638 
639 		public boolean isDragging() {
640 			return dragging;
641 		}
642 
643 		public void setDragging(final boolean dragging) {
644 			this.dragging = dragging;
645 		}
646 
647 		public void setSelected(final boolean selected) {
648 			if (this.isEnabled()) {
649 				this.selected = selected;
650 			} else {
651 				this.selected = false;
652 			}
653 			addRemGraph();
654 		}
655 
656 		private void addRemGraph() {
657 			if (selected) {
658 				OpenLogViewer.getInstance().getMultiGraphLayeredPane().addGraph(this.getName());
659 				this.setForeground(GDE.getDisplayColor());
660 				this.repaint();
661 			} else {
662 				OpenLogViewer.getInstance().getMultiGraphLayeredPane().removeGraph(this.getName());
663 				this.setForeground(GDE.getDisplayColor().darker().darker());
664 				this.repaint();
665 			}
666 		}
667 
668 		@Override
669 		public int compareTo(final Object o) {
670 			if (o instanceof ActiveHeaderLabel) {
671 				final ActiveHeaderLabel GCB = (ActiveHeaderLabel) o;
672 				return this.GDE.compareTo(GCB.getGDE());
673 			} else {
674 				return -1;
675 			}
676 		}
677 	}
678 }