1 /* Copyright (c) 2002-2012 The University of the West Indies
2  *
3  * Contact: robert.lancashire@uwimona.edu.jm
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Lesser General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2.1 of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Lesser General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Lesser General Public
16  *  License along with this library; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 // CHANGES to 'JSVPanel.java'
21 // University of the West Indies, Mona Campus
22 //
23 // 25-06-2007 rjl - bug in ReversePlot for non-continuous spectra fixed
24 //                - previously, one point less than npoints was displayed
25 // 25-06-2007 cw  - show/hide/close modified
26 // 10-02-2009 cw  - adjust for non zero baseline in North South plots
27 // 24-08-2010 rjl - check coord output is not Internationalised and uses decimal point not comma
28 // 31-10-2010 rjl - bug fix for drawZoomBox suggested by Tim te Beek
29 // 01-11-2010 rjl - bug fix for drawZoomBox
30 // 05-11-2010 rjl - colour the drawZoomBox area suggested by Valery Tkachenko
31 // 23-07-2011 jak - Added feature to draw the x scale, y scale, x units and y units
32 //					independently of each other. Added independent controls for the font,
33 //					title font, title bold, and integral plot color.
34 // 24-09-2011 jak - Altered drawGraph to fix bug related to reversed highlights. Added code to
35 //					draw integration ratio annotations
36 // 03-06-2012 rmh - Full overhaul; code simplification; added support for Jcamp 6 nD spectra
37 
38 package jspecview.common;
39 
40 import java.util.Hashtable;
41 import java.util.Map;
42 import java.util.Set;
43 import java.util.Map.Entry;
44 
45 import javajs.api.GenericColor;
46 
47 import org.jmol.awtjs.Event;
48 
49 import javajs.util.CU;
50 import javajs.util.Lst;
51 
52 import jspecview.api.AnnotationData;
53 import jspecview.api.JSVPanel;
54 import jspecview.api.PanelListener;
55 import jspecview.api.VisibleInterface;
56 import jspecview.common.Annotation.AType;
57 import jspecview.common.Spectrum.IRMode;
58 import jspecview.dialog.JSVDialog;
59 
60 import org.jmol.api.EventManager;
61 import org.jmol.api.GenericGraphics;
62 import org.jmol.util.Font;
63 import org.jmol.util.Logger;
64 
65 /**
66  * JSVPanel class draws a plot from the data contained a instance of a
67  * <code>Graph</code>.
68  *
69  * @author Debbie-Ann Facey
70  * @author Khari A. Bryan
71  * @author Craig A.D. Walters
72  * @author Prof Robert J. Lancashire
73  * @author Bob Hanson hansonr@stolaf.edu
74  */
75 
76 public class PanelData implements EventManager {
77 
78 	public GenericGraphics g2d, g2d0;
79 	JSViewer vwr;
80 
PanelData(JSVPanel panel, JSViewer viewer)81 	public PanelData(JSVPanel panel, JSViewer viewer) {
82 		this.vwr = viewer;
83 		this.jsvp = panel;
84 		this.g2d = this.g2d0 = viewer.g2d;
85     BLACK = g2d.getColor1(0);
86 		highlightColor = g2d.getColor4(255, 0, 0, 200);
87 		zoomBoxColor = g2d.getColor4(150, 150, 100, 130);
88 		zoomBoxColor2 = g2d.getColor4(150, 100, 100, 130);
89 	}
90 
91 	// Critical fields
92 
93 	private Lst<PanelListener> listeners = new Lst<PanelListener>();
94 
addListener(PanelListener listener)95 	public void addListener(PanelListener listener) {
96 		if (!listeners.contains(listener)) {
97 			listeners.addLast(listener);
98 		}
99 	}
100 
101 	private GraphSet currentGraphSet;
102 
getCurrentGraphSet()103 	public GraphSet getCurrentGraphSet() {
104 		return currentGraphSet;
105 	}
106 
107 	public Hashtable<ScriptToken, Object> options = new Hashtable<ScriptToken, Object>();
108 	public JSVPanel jsvp;
109 	public Lst<GraphSet> graphSets;
110 	public int currentSplitPoint;
111 	public PlotWidget thisWidget;
112 	public Coordinate coordClicked;
113 	public Coordinate[] coordsClicked;
114 
dispose()115 	public void dispose() {
116 		jsvp = null;
117 		for (int i = 0; i < graphSets.size(); i++)
118 			graphSets.get(i).dispose();
119 		graphSets = null;
120 		currentFont = null;
121 		currentGraphSet = null;
122 		coordClicked = null;
123 		coordsClicked = null;
124 		thisWidget = null;
125 		options = null;
126 		listeners = null;
127 	}
128 
129 	// plot parameters
130 
131 	public static final int defaultPrintHeight = 450, defaultPrintWidth = 280;
132 	public static final int topMargin = 40, bottomMargin = 50, leftMargin = 60,
133 			rightMargin = 50;
134 
135 	public boolean ctrlPressed;
136 	public boolean shiftPressed;
137 	public boolean drawXAxisLeftToRight;
138 	public boolean isIntegralDrag;
139 	public boolean xAxisLeftToRight = true;
140 
141 	public int scalingFactor = 1; // will be 10 for printing
142 	public int integralShiftMode;
143 	public int left = leftMargin;
144 	public int right = rightMargin;
145 
146 	public String coordStr = "";
147 	public String startupPinTip = "Click to set.";
148 	public String title;
149 
150 	int clickCount;
151 	private int nSpectra;
152 	public int thisWidth;
153 	private int thisHeight;
154 	private int startIndex, endIndex;
155 
156 	private String commonFilePath;
157 	private String viewTitle;
158 
setViewTitle(String title)159 	public void setViewTitle(String title) {
160 		viewTitle = title;
161 	}
162 
getViewTitle()163 	public String getViewTitle() {
164 		return (viewTitle == null ? getTitle() : viewTitle);
165 	}
166 
getInfo(boolean selectedOnly, String key)167 	public Map<String, Object> getInfo(boolean selectedOnly, String key) {
168 		Map<String, Object> info = new Hashtable<String, Object>();
169 		Lst<Map<String, Object>> sets = null;
170 		if (selectedOnly)
171 			return currentGraphSet.getInfo(key, getCurrentSpectrumIndex());
172 		Set<Entry<ScriptToken, Object>> entries = options.entrySet();
173 		if ("".equals(key)) {
174 			String val = "type title nSets ";
175 			for (Entry<ScriptToken, Object> entry : entries)
176 				val += entry.getKey().name() + " ";
177 			info.put("KEYS", val);
178 		} else {
179 			for (Entry<ScriptToken, Object> entry : entries)
180 				Parameters.putInfo(key, info, entry.getKey().name(), entry.getValue());
181 			Parameters.putInfo(key, info, "type", getSpectrumAt(0).getDataType());
182 			Parameters.putInfo(key, info, "title", title);
183 			Parameters.putInfo(key, info, "nSets", Integer.valueOf(graphSets.size()));
184 		}
185 			sets = new Lst<Map<String, Object>>();
186 			for (int i = graphSets.size(); --i >= 0;)
187 				sets.addLast(graphSets.get(i).getInfo(key, -1));
188 			info.put("sets", sets);
189 		return info;
190 	}
191 
setBooleans(Parameters parameters, ScriptToken st)192 	public void setBooleans(Parameters parameters, ScriptToken st) {
193 		if (st == null) {
194 			Map<ScriptToken, Boolean> booleans = parameters.getBooleans();
195 			for (Map.Entry<ScriptToken, Boolean> entry : booleans.entrySet())
196 				setBooleans(parameters, entry.getKey());
197 			return;
198 		}
199 		setBoolean(st, parameters.getBoolean(st));
200 	}
201 
202 	@SuppressWarnings("incomplete-switch")
setBoolean(ScriptToken st, boolean isTrue)203 	public void setBoolean(ScriptToken st, boolean isTrue) {
204 		setTaintedAll();
205 		if (st == ScriptToken.REVERSEPLOT) {
206 			currentGraphSet.setReversePlot(isTrue);
207 			return;
208 		}
209 		options.put(st, Boolean.valueOf(isTrue));
210 		switch (st) {
211 		case DISPLAY1D:
212 		case DISPLAY2D:
213 			doReset = true;
214 			break;
215 		}
216 	}
217 
getBoolean(ScriptToken st)218 	public boolean getBoolean(ScriptToken st) {
219 		if (st == ScriptToken.REVERSEPLOT)
220 			return currentGraphSet.reversePlot;
221 		if (options == null)
222 			return false;
223 		Object b = options.get(st);
224 		return (b != null && (b instanceof Boolean) && ((Boolean) b) == Boolean.TRUE);
225 	}
226 
227 	// //////// settable colors and fonts //////////
228 
229 	private String displayFontName;
230 	@SuppressWarnings("unused")
231 	private String titleFontName;
232 
233 	@SuppressWarnings("incomplete-switch")
setFontName(ScriptToken st, String fontName)234 	public void setFontName(ScriptToken st, String fontName) {
235 		switch (st) {
236 		case DISPLAYFONTNAME:
237 			displayFontName = fontName;
238 			break;
239 		case TITLEFONTNAME:
240 			titleFontName = fontName;
241 			break;
242 		}
243 		if (fontName != null)
244 			options.put(st, fontName);
245 	}
246 
247 	// ///////// print parameters ///////////
248 
249 	public boolean isPrinting;
250 
251 	private boolean doReset = true;
252 
253 	public String printingFontName;
254 	public String printGraphPosition = "default";
255 	public boolean titleDrawn;
256 	public boolean display1D;
257 	public boolean isLinked;
258 	public String printJobTitle;
259 
getDisplay1D()260 	public boolean getDisplay1D() {
261 		return display1D;
262 	}
263 
264 	// //// initialization - from AwtPanel
265 
266 	public Lst<Spectrum> spectra;
267 	private boolean taintedAll = true;
268 	private boolean testingJavaScript; // set TRUE to see taintedAll the way it will be in JavaScript
269 
setTaintedAll()270 	public void setTaintedAll() {
271 		taintedAll = true;
272 	}
273 
274 
initOne(Spectrum spectrum)275 	public void initOne(Spectrum spectrum) {
276 		spectra = new Lst<Spectrum>();
277 		spectra.addLast(spectrum);
278 		initMany(spectra, 0, 0);
279 	}
280 
281 	public enum LinkMode {
282 
283 		ALL, NONE, AB, ABC;
284 
getMode(String abc)285 		public static LinkMode getMode(String abc) {
286 			if (abc.equals("*"))
287 				return ALL;
288 			for (LinkMode mode : values())
289 				if (mode.name().equalsIgnoreCase(abc))
290 					return mode;
291 			return NONE;
292 		}
293 	}
294 
initMany(Lst<Spectrum> spectra, int startIndex, int endIndex)295 	public void initMany(Lst<Spectrum> spectra, int startIndex,
296 			int endIndex) {
297 		this.startIndex = startIndex;
298 		this.endIndex = endIndex;
299 		nSpectra = spectra.size();
300 		this.spectra = spectra;
301 		commonFilePath = spectra.get(0).getFilePath();
302 		for (int i = 0; i < nSpectra; i++)
303 			if (!commonFilePath.equalsIgnoreCase(spectra.get(i).getFilePath())) {
304 				commonFilePath = null;
305 				break;
306 			}
307 		setGraphSets(LinkMode.NONE);
308 	}
309 
setGraphSets(LinkMode linkMode)310 	private void setGraphSets(LinkMode linkMode) {
311 		graphSets = GraphSet.createGraphSetsAndSetLinkMode(this, jsvp, spectra,
312 				startIndex, endIndex, linkMode);
313 		currentGraphSet = graphSets.get(0);
314 		title = getSpectrum().getTitleLabel();
315 	}
316 
findMatchingPeakInfo(PeakInfo pi)317 	public PeakInfo findMatchingPeakInfo(PeakInfo pi) {
318 		PeakInfo pi2 = null;
319 		for (int i = 0; i < graphSets.size(); i++)
320 			if ((pi2 = graphSets.get(i).findMatchingPeakInfo(pi)) != null)
321 				break;
322 		return pi2;
323 	}
324 
integrateAll(ColorParameters parameters)325 	public void integrateAll(ColorParameters parameters) {
326 		for (int i = graphSets.size(); --i >= 0;)
327 			graphSets.get(i).integrate(-1, parameters);
328 	}
329 
330 	/**
331 	 * Returns the Number of Graph sets
332 	 *
333 	 * @return the Number of graph sets
334 	 */
getNumberOfGraphSets()335 	public int getNumberOfGraphSets() {
336 		return graphSets.size();
337 	}
338 
339 	/**
340 	 * Returns the title displayed on the graph
341 	 *
342 	 * @return the title displayed on the graph
343 	 */
getTitle()344 	public String getTitle() {
345 		return title;
346 	}
347 
refresh()348 	public void refresh() {
349 		doReset = true;
350 	}
351 
addAnnotation(Lst<String> tokens)352 	public void addAnnotation(Lst<String> tokens) {
353 		String title = currentGraphSet.addAnnotation(tokens, getTitle());
354 		if (title != null)
355 			this.title = title;
356 	}
357 
addPeakHighlight(PeakInfo peakInfo)358 	public void addPeakHighlight(PeakInfo peakInfo) {
359 		for (int i = 0; i < graphSets.size(); i++)
360 			graphSets.get(i).addPeakHighlight(peakInfo);
361 	}
362 
selectPeakByFileIndex(String filePath, String index, String atomKey)363 	public PeakInfo selectPeakByFileIndex(String filePath, String index, String atomKey) {
364 		PeakInfo pi = currentGraphSet.selectPeakByFileIndex(filePath, index, atomKey);
365 		if (pi == null)
366 			for (int i = graphSets.size(); --i >= 0;)
367 				if (graphSets.get(i) != currentGraphSet
368 						&& (pi = graphSets.get(i).selectPeakByFileIndex(filePath, index, atomKey)) != null)
369 					break;
370 		return pi;
371 	}
372 
setPlotColors(GenericColor[] colors)373 	public void setPlotColors(GenericColor[] colors) {
374 		for (int i = graphSets.size(); --i >= 0;)
375 			graphSets.get(i).setPlotColors(colors);
376 	}
377 
selectSpectrum(String filePath, String type, String model, boolean andCurrent)378 	public void selectSpectrum(String filePath, String type, String model,
379 			boolean andCurrent) {
380 		if (andCurrent)
381 			currentGraphSet.selectSpectrum(filePath, type, model);
382 		if ("ID".equals(type) ) {
383 			jumpToSpectrumIndex(getCurrentSpectrumIndex(), true);
384 			return;
385 		}
386 
387 		for (int i = 0; i < graphSets.size(); i++)
388 			if (graphSets.get(i) != currentGraphSet)
389 				graphSets.get(i).selectSpectrum(filePath, type, model);
390 	}
391 
hasFileLoaded(String filePath)392 	public boolean hasFileLoaded(String filePath) {
393 		for (int i = graphSets.size(); --i >= 0;)
394 			if (graphSets.get(i).hasFileLoaded(filePath))
395 				return true;
396 		return false;
397 	}
398 
399 	/**
400 	 * Clears all views in the zoom list
401 	 */
clearAllView()402 	public void clearAllView() {
403 		for (int i = graphSets.size(); --i >= 0;)
404 			graphSets.get(i).resetViewCompletely();//.clearViews();
405 	}
406 
407 	/*----------------------- JSVPanel PAINTING METHODS ---------------------*/
408 	/**
409 	 * Draws the Spectrum to the panel
410 	 *
411 	 * @param gMain
412 	 *          the main <code>Graphics</code> object
413 	 * @param gFront
414 	 *          the <code>Graphics</code> object for top-object writing
415 	 * @param gRear
416 	 * @param width
417 	 *          the width to be drawn in pixels
418 	 * @param height
419 	 *          the height to be drawn in pixels
420 	 * @param addFilePath
421 	 */
drawGraph(Object gMain, Object gFront, Object gRear, int width, int height, boolean addFilePath)422 	public synchronized void drawGraph(Object gMain, Object gFront, Object gRear,
423 			int width, int height, boolean addFilePath) {
424 		boolean withCoords;
425 		this.gMain = gMain;
426 		display1D = !isLinked && getBoolean(ScriptToken.DISPLAY1D);
427 		int top = topMargin;
428 		int bottom = bottomMargin;
429 		boolean isResized = (isPrinting || doReset || thisWidth != width || thisHeight != height);
430 		if (isResized)
431 			setTaintedAll();
432 		if (taintedAll)
433 			g2d.fillBackground(gRear, bgcolor);
434 		if (gFront != gMain) {
435 			g2d.fillBackground(gFront, null);
436 			if (gMain != gRear)
437 				g2d.fillBackground(gMain, null);
438 			g2d.setStrokeBold(gMain, false);
439 		}
440 		if (isPrinting) {
441 			top *= 3; // for three-hole punching
442 			bottom *= 3; // for file name
443 			scalingFactor = 10; // for high resolution (zooming in within PDF)
444 			withCoords = false;
445 		} else {
446 			scalingFactor = 1;
447 			withCoords = getBoolean(ScriptToken.COORDINATESON);
448 			titleOn = getBoolean(ScriptToken.TITLEON);
449 			gridOn = getBoolean(ScriptToken.GRIDON);
450 			peakTabsOn = getBoolean(ScriptToken.PEAKTABSON);
451 
452 		}
453 		boolean pointsOnly = getBoolean(ScriptToken.POINTSONLY);
454 		doReset = false;
455 		titleDrawn = false;
456 		thisWidth = width;
457 		thisHeight = height;
458 		for (int i = graphSets.size(); --i >= 0;)
459 			graphSets.get(i).drawGraphSet(gMain, gFront, gRear, width, height, left,
460 					right, top, bottom, isResized, taintedAll, pointsOnly);
461 		if (titleOn && !titleDrawn && taintedAll)
462 			drawTitle(gMain, height * scalingFactor, width * scalingFactor,
463 					getDrawTitle(isPrinting));
464 		if (withCoords && coordStr != null)
465 			drawCoordinates(gFront, top, thisWidth - right, top - 20);
466 		if (addFilePath && taintedAll) {
467 			printFilePath(gMain, left, height, commonFilePath != null ? commonFilePath
468           : graphSets.size() == 1 && currentGraphSet.getTitle(true) != null ? getSpectrum()
469               .getFilePath() : null);
470 		}
471 		if (isPrinting) {
472 			printVersion(gMain, height);
473 		}
474 		if (!testingJavaScript && (isPrinting || gMain == gFront))
475 			setTaintedAll();
476 		else
477 			taintedAll = false;
478 	}
479 
480 	/**
481 	 * @param g
482 	 * @param top
483 	 * @param x
484 	 * @param y
485 	 */
drawCoordinates(Object g, int top, int x, int y)486 	public void drawCoordinates(Object g, int top, int x, int y) {
487 		g2d.setGraphicsColor(g, coordinatesColor);
488 		Font font = setFont(g, jsvp.getWidth(), Font.FONT_STYLE_BOLD, 14,
489 				true);
490 		g2d.drawString(g, coordStr, x - font.stringWidth(coordStr), y);
491 	}
492 
setFont(Object g, int width, int style, float size, boolean isLabel)493 	public Font setFont(Object g, int width, int style, float size,
494 			boolean isLabel) {
495 		return g2d.setFont(g, getFont(g, width, style, size, isLabel));
496 	}
497 
printFilePath(Object g, int x, int y, String s)498 	public void printFilePath(Object g, int x, int y, String s) {
499 	  if (s == null)
500 	    return;
501 		x *= scalingFactor;
502 		y *= scalingFactor;
503 		if (s.indexOf("?") > 0)
504 			s = s.substring(s.indexOf("?") + 1);
505 		s = s.substring(s.lastIndexOf("/") + 1);
506 		s = s.substring(s.lastIndexOf("\\") + 1);
507 		g2d.setGraphicsColor(g, BLACK);
508 		Font font = setFont(g, 1000, Font.FONT_STYLE_PLAIN, 9, true);
509 		if (x != left * scalingFactor)
510 			x -= font.stringWidth(s);
511 		g2d.drawString(g, s, x, y - font.getHeight());
512 	}
513 
printVersion(Object g, int pageHeight)514 	public void printVersion(Object g, int pageHeight) {
515 		g2d.setGraphicsColor(g, BLACK);
516 		Font font = setFont(g, 100, Font.FONT_STYLE_PLAIN, 12, true);
517 		String s = jsvp.getApiPlatform().getDateFormat(null) + " JSpecView "
518 				+ JSVersion.VERSION_SHORT;
519 		int w = font.stringWidth(s);
520 		g2d.drawString(g, s, (thisWidth - right) * scalingFactor - w, pageHeight
521 				* scalingFactor - font.getHeight()*3);
522 	}
523 
524 	/**
525 	 * Draws Title
526 	 *
527 	 * @param g
528 	 *
529 	 * @param pageHeight
530 	 *          the height to be drawn in pixels -- after scaling
531 	 * @param pageWidth
532 	 *          the width to be drawn in pixels -- after scaling
533 	 * @param title
534 	 */
drawTitle(Object g, int pageHeight, int pageWidth, String title)535 	public void drawTitle(Object g, int pageHeight, int pageWidth, String title) {
536 		title = title.replace('\n', ' ');
537 		Font font = getFont(g, pageWidth, isPrinting
538 				|| getBoolean(ScriptToken.TITLEBOLDON) ? Font.FONT_STYLE_BOLD
539 				: Font.FONT_STYLE_PLAIN, 14, true);
540 		int nPixels = font.stringWidth(title);
541 		if (nPixels > pageWidth) {
542 			int size = (int) (14.0 * pageWidth / nPixels);
543 			if (size < 10)
544 				size = 10;
545 			font = getFont(g, pageWidth, isPrinting
546 					|| getBoolean(ScriptToken.TITLEBOLDON) ? Font.FONT_STYLE_BOLD
547 					: Font.FONT_STYLE_PLAIN, size, true);
548 		}
549 		g2d.setGraphicsColor(g, titleColor);
550 		setCurrentFont(g2d.setFont(g, font));
551 		g2d.drawString(g, title, (isPrinting ? left * scalingFactor : 5),
552 				pageHeight - (int) (font.getHeight() * (isPrinting ? 2 : 0.5)));
553 	}
554 
555 	private Font currentFont;
556 
setCurrentFont(Font font)557 	private void setCurrentFont(Font font) {
558 		currentFont = font;
559 	}
560 
getFontHeight()561 	int getFontHeight() {
562 		return currentFont.getAscent();
563 	}
564 
getStringWidth(String s)565 	int getStringWidth(String s) {
566 		return currentFont.stringWidth(s);
567 	}
568 
569 	/**
570 	 * sets bsSelected to the specified pointer from "select 3.1*1"
571 	 *
572 	 * @param iSpec
573 	 */
selectFromEntireSet(int iSpec)574 	public void selectFromEntireSet(int iSpec) {
575 		// note that iSpec is over the entire set
576 		for (int i = 0, pt = 0; i < graphSets.size(); i++) {
577 			if (iSpec == Integer.MIN_VALUE) {
578 				graphSets.get(i).setSelected(-1);
579 				continue;
580 			}
581 			Lst<Spectrum> specs = graphSets.get(i).spectra;
582 			for (int j = 0; j < specs.size(); j++, pt++)
583 				if (iSpec < 0 || iSpec == pt)
584 					graphSets.get(i).setSelected(j);
585 		}
586 	}
587 
addToList(int iSpec, Lst<Spectrum> list)588 	public void addToList(int iSpec, Lst<Spectrum> list) {
589 		for (int i = 0; i < spectra.size(); i++)
590 			if (iSpec < 0 || i == iSpec)
591 				list.addLast(spectra.get(i));
592 	}
593 
scaleSelectedBy(double f)594 	public void scaleSelectedBy(double f) {
595 		for (int i = graphSets.size(); --i >= 0;)
596 			graphSets.get(i).scaleSelectedBy(f);
597 
598 	}
599 
600 	// //// currentGraphSet methods
601 
setCurrentGraphSet(GraphSet gs, int yPixel)602 	private boolean setCurrentGraphSet(GraphSet gs, int yPixel) {
603 		// Need to check for nSplit > 1 here because this could be a
604 		// mass spec that has been selected by clicking on a GC peak.
605 		// In that case, there is no split, and we should not be changing
606 		// the selected spectrum to 0 just because the split point is 0.
607 		int splitPoint = (gs.nSplit > 1 ? gs.getSplitPoint(yPixel) : gs.getCurrentSpectrumIndex());
608 		boolean isNewSet = (currentGraphSet != gs);
609 		boolean isNewSplitPoint = (isNewSet || currentSplitPoint != splitPoint);
610 		currentGraphSet = gs;
611 		currentSplitPoint = splitPoint;
612 		if (isNewSet || gs.nSplit > 1 && isNewSplitPoint)
613 			setSpectrum(splitPoint, true);
614 		if (!isNewSet) {
615 			isNewSet = gs.checkSpectrumClickedEvent(mouseX, mouseY, clickCount);
616 			if (!isNewSet)
617 				return false;
618 			currentSplitPoint = splitPoint = gs.getCurrentSpectrumIndex();
619 			setSpectrum(splitPoint, true);
620 		}
621 
622 		// new set (so also new split point)
623 		// or nSplit > 1 and new split point
624 		// or nSplit == 1 and showAllStacked and isClick and is a spectrum click)
625 
626 		jumpToSpectrumIndex(splitPoint, isNewSet || gs.nSplit > 1 && isNewSplitPoint);
627 		return isNewSet;
628 	}
629 
jumpToSpectrum(Spectrum spec)630 	public void jumpToSpectrum(Spectrum spec) {
631 		int index = currentGraphSet.getSpectrumIndex(spec);
632 		jumpToSpectrumIndex(index, true);
633 	}
634 
jumpToSpectrumIndex(int index, boolean doSetSpec)635 	public void jumpToSpectrumIndex(int index, boolean doSetSpec) {
636 		if (index < 0 || index >= currentGraphSet.nSpectra)
637 			return;
638 		currentSplitPoint = index;
639 		if (doSetSpec)
640 			setSpectrum(currentSplitPoint, currentGraphSet.nSplit > 1);
641 		Spectrum spec = getSpectrum();
642 		notifySubSpectrumChange(spec.getSubIndex(), spec);
643 
644 	}
splitStack(boolean doSplit)645 	public void splitStack(boolean doSplit) {
646 		currentGraphSet.splitStack(doSplit);
647 	}
648 
getNumberOfSpectraInCurrentSet()649 	public int getNumberOfSpectraInCurrentSet() {
650 		return currentGraphSet.nSpectra;
651 	}
652 
getSourceID()653 	public String getSourceID() {
654 		String id = getSpectrum().sourceID;
655 		return (id == null ? getSpectrumAt(0).sourceID : id);
656 	}
657 
getStartingPointIndex(int index)658 	public int getStartingPointIndex(int index) {
659 		return currentGraphSet.viewData.getStartingPointIndex(index);
660 	}
661 
getEndingPointIndex(int index)662 	public int getEndingPointIndex(int index) {
663 		return currentGraphSet.viewData.getEndingPointIndex(index);
664 	}
665 
haveSelectedSpectrum()666 	public boolean haveSelectedSpectrum() {
667 		return currentGraphSet.haveSelectedSpectrum();
668 	}
669 
getShowAnnotation(AType type)670 	public boolean getShowAnnotation(AType type) {
671 		return currentGraphSet.getShowAnnotation(type, -1);
672 	}
673 
showAnnotation(AType type, Boolean tfToggle)674 	public void showAnnotation(AType type, Boolean tfToggle) {
675 		currentGraphSet.setShowAnnotation(type, tfToggle);
676 	}
677 
setYStackOffsetPercent(int offset)678 	public void setYStackOffsetPercent(int offset) {
679 		currentGraphSet.yStackOffsetPercent = offset;
680 	}
681 
setSpectrum(int iSpec, boolean isSplit)682 	public void setSpectrum(int iSpec, boolean isSplit) {
683 		currentGraphSet.setSpectrum(iSpec, isSplit);
684 
685 		// repaint();
686 	}
687 
getSpectrum()688 	public Spectrum getSpectrum() {
689 		return currentGraphSet.getSpectrum();
690 	}
691 
setSpecForIRMode(Spectrum spec)692 	public void setSpecForIRMode(Spectrum spec) {
693 		setTaintedAll();
694 		Spectrum spec0 = currentGraphSet.getSpectrum();
695 		currentGraphSet.setSpectrumJDX(spec);
696 		for (int i = 0; i < spectra.size(); i++)
697 			if (spectra.get(i) == spec0)
698 				spectra.set(i, spec);
699 	}
700 
isShowAllStacked()701 	public boolean isShowAllStacked() {
702 		return currentGraphSet.showAllStacked;
703 	}
704 
getCurrentSpectrumIndex()705 	public int getCurrentSpectrumIndex() {
706 		return currentGraphSet.getCurrentSpectrumIndex();
707 	}
708 
getSpectrumAt(int index)709 	public Spectrum getSpectrumAt(int index) {
710 		if (currentGraphSet == null)
711 			return null;
712 		return currentGraphSet.getSpectrumAt(index);
713 	}
714 
715 	/**
716 	 * Add information about a region of the displayed spectrum to be highlighted
717 	 * applet only right now
718 	 *
719 	 * @param gs
720 	 *
721 	 * @param x1
722 	 *          the x value of the coordinate where the highlight should start
723 	 * @param x2
724 	 *          the x value of the coordinate where the highlight should end
725 	 * @param spec
726 	 * @param r
727 	 * @param a
728 	 * @param b
729 	 * @param g
730 	 */
addHighlight(GraphSet gs, double x1, double x2, Spectrum spec, int r, int g, int b, int a)731 	public void addHighlight(GraphSet gs, double x1, double x2, Spectrum spec,
732 			int r, int g, int b, int a) {
733 		(gs == null ? currentGraphSet : gs).addHighlight(x1, x2, spec, g2d
734 				.getColor4(r, g, b, a));
735 	}
736 
737 	/**
738 	 * Remove the highlight specified by the starting and ending x value
739 	 *
740 	 * @param x1
741 	 *          the x value of the coordinate where the highlight started
742 	 * @param x2
743 	 *          the x value of the coordinate where the highlight ended
744 	 */
removeHighlight(double x1, double x2)745 	public void removeHighlight(double x1, double x2) {
746 		currentGraphSet.removeHighlight(x1, x2);
747 	}
748 
749 	/**
750 	 * Removes all highlights from the display
751 	 */
removeAllHighlights()752 	public void removeAllHighlights() {
753 		currentGraphSet.removeAllHighlights();
754 	}
755 
setZoom(double x1, double y1, double x2, double y2)756 	public void setZoom(double x1, double y1, double x2, double y2) {
757 		currentGraphSet.setZoom(x1, y1, x2, y2);
758 		doReset = true;
759 		setTaintedAll();
760 		notifyListeners(new ZoomEvent());//x1, y1, x2, y2));
761 	}
762 
763 	/**
764 	 * Resets the spectrum to it's original view
765 	 */
resetView()766 	public void resetView() {
767 		currentGraphSet.resetView();
768 	}
769 
770 	/**
771 	 * Displays the previous view zoomed
772 	 */
previousView()773 	public void previousView() {
774 		currentGraphSet.previousView();
775 	}
776 
777 	/**
778 	 * Displays the next view zoomed
779 	 */
nextView()780 	public void nextView() {
781 		currentGraphSet.nextView();
782 	}
783 
getSelectedIntegral()784 	public Integral getSelectedIntegral() {
785 		return currentGraphSet.getSelectedIntegral();
786 	}
787 
advanceSubSpectrum(int dir)788 	public void advanceSubSpectrum(int dir) {
789 		currentGraphSet.advanceSubSpectrum(dir);
790 	}
791 
setSelectedIntegral(double val)792 	public void setSelectedIntegral(double val) {
793 		currentGraphSet.setSelectedIntegral(val);
794 	}
795 
scaleYBy(double f)796 	public void scaleYBy(double f) {
797 		currentGraphSet.scaleYBy(f);
798 	}
799 
toPeak(int i)800 	public void toPeak(int i) {
801 		currentGraphSet.toPeak(i);
802 	}
803 
804 	/*------------------------- Javascript call functions ---------------------*/
805 
806 	/**
807 	 * Returns the spectrum coordinate of the point on the display that was
808 	 * clicked
809 	 *
810 	 * @return the spectrum coordinate of the point on the display that was
811 	 *         clicked
812 	 */
getClickedCoordinate()813 	public Coordinate getClickedCoordinate() {
814 		return coordClicked;
815 	}
816 
817 	/**
818 	 * click event processing
819 	 *
820 	 * @param coord
821 	 * @param actualCoord
822 	 * @return true if a coordinate was picked and fills in coord and actualCoord
823 	 */
getPickedCoordinates(Coordinate coord, Coordinate actualCoord)824 	public boolean getPickedCoordinates(Coordinate coord, Coordinate actualCoord) {
825 		return Coordinate.getPickedCoordinates(coordsClicked, coordClicked, coord,
826 				actualCoord);
827 	}
828 
829 	/**
830 	 * shifts xyCoords for a spectrum by the specified amount
831 
832 	 * @param mode
833 	 * @param xOld old position or NaN
834 	 * @param xNew NaN or new position
835 	 *
836 	 * @return true if successful
837 	 */
shiftSpectrum(int mode, double xOld, double xNew)838 	public boolean shiftSpectrum(int mode, double xOld, double xNew) {
839 		return currentGraphSet.shiftSpectrum(mode, xOld, xNew);
840 
841 	}
842 
findX(Spectrum spec, double d)843 	public void findX(Spectrum spec, double d) {
844 		currentGraphSet.setXPointer(spec, d);
845 		// repaint();
846 	}
847 
setXPointers(Spectrum spec, double x1, Spectrum spec2, double x2)848 	public void setXPointers(Spectrum spec, double x1, Spectrum spec2,
849 			double x2) {
850 		currentGraphSet.setXPointer(spec, x1);
851 		currentGraphSet.setXPointer2(spec2, x2);
852 	}
853 
854 	// called by GraphSet
855 
isCurrentGraphSet(GraphSet graphSet)856 	public boolean isCurrentGraphSet(GraphSet graphSet) {
857 		return graphSet == currentGraphSet;
858 	}
859 
repaint()860 	public void repaint() {
861 		jsvp.doRepaint(false);
862 	}
863 
setToolTipText(String s)864 	public void setToolTipText(String s) {
865 		jsvp.setToolTipText(s);
866 	}
867 
setHighlightColor(GenericColor color)868 	public void setHighlightColor(GenericColor color) {
869 		setColor(ScriptToken.HIGHLIGHTCOLOR, color);
870 	}
871 
getInput(String message, String title, String sval)872 	String getInput(String message, String title, String sval) {
873 		return jsvp.getInput(message, title, sval);
874 	}
875 
getFont(Object g, int width, int style, float size, boolean isLabel)876 	private Font getFont(Object g, int width, int style, float size,
877 			boolean isLabel) {
878 		size *= scalingFactor;
879 		if (isLabel) {
880 			if (width < 400)
881 				size = ((width * size) / 400);
882 		} else {
883 			if (width < 250)
884 				size = ((width * size) / 250);
885 		}
886 		int face = jsvp.getFontFaceID(isPrinting ? printingFontName
887 				: displayFontName);
888 		return currentFont = Font.createFont3D(face, style, size, size, jsvp.getApiPlatform(), g);
889 	}
890 
891 	// listeners to handle various events, from GraphSet or AwtPanel
892 
893 	/**
894 	 *
895 	 * @param isub
896 	 *          -1 indicates direction if no subspectra or subspectrum index if
897 	 *          subspectra
898 	 * @param spec
899 	 *          null indicates no subspectra
900 	 */
notifySubSpectrumChange(int isub, Spectrum spec)901 	public void notifySubSpectrumChange(int isub, Spectrum spec) {
902 		notifyListeners(new SubSpecChangeEvent(isub, (spec == null ? null : spec
903 				.getTitleLabel())));
904 	}
905 
906 	/**
907 	 * Notifies CoordinatePickedListeners
908 	 *
909 	 * @param p
910 	 *
911 	 */
notifyPeakPickedListeners(PeakPickEvent p)912 	public void notifyPeakPickedListeners(PeakPickEvent p) {
913 		if (p == null) {
914 			p = new PeakPickEvent(jsvp, coordClicked, getSpectrum()
915 					.getAssociatedPeakInfo(xPixelClicked, coordClicked));
916 		}
917 		// PeakInfo pi = p.getPeakInfo();
918 		// if (pi.getAtoms() == null) {
919 		// // find matching file/type/model in other panels
920 		// String filePath = pi.getFilePath();
921 		// String type = pi.getType();
922 		// String model = pi.getModel();
923 		// for (int i = 0; i < graphSets.size(); i++) {
924 		// if (graphSets.get(i) == currentGraphSet)
925 		// continue;
926 		// // just first spectrum for now -- presumed to be GC/MS
927 		// PeakInfo pi2 = graphSets.get(i).getSpectrumAt(0)
928 		// .selectPeakByFilePathTypeModel(filePath, type, model);
929 		// if (pi2 != null)
930 		// graphSets.get(i).addPeakHighlight(pi2);
931 		// }
932 		// }
933 		// problem is that you cannot have two highlights for the same model.
934 		// only problem is gc/ms, where we want to select a GC peak based on
935 		// an MS peak.
936 
937 		notifyListeners(p);
938 	}
939 
notifyListeners(Object eventObj)940 	public void notifyListeners(Object eventObj) {
941 		for (int i = 0; i < listeners.size(); i++)
942 			if (listeners.get(i) != null)
943 				listeners.get(i).panelEvent(eventObj);
944 	}
945 
946 	/*--------------the rest are all mouse and keyboard interface -----------------------*/
947 
escapeKeyPressed(boolean isDEL)948 	public void escapeKeyPressed(boolean isDEL) {
949 		currentGraphSet.escapeKeyPressed(isDEL);
950 	}
951 
952 	private enum Mouse {
953 		UP, DOWN;
954 	}
955 
956 	private Mouse mouseState;
957 	public boolean gridOn;
958 	public boolean titleOn;
959 	public boolean peakTabsOn;
960 
hasFocus()961 	public boolean hasFocus() {
962 		return jsvp.hasFocus();
963 	}
964 
isMouseUp()965 	public boolean isMouseUp() {
966 		return (mouseState == Mouse.UP);
967 	}
968 
969 	public int mouseX, mouseY;
970 
doMouseMoved(int xPixel, int yPixel)971 	public void doMouseMoved(int xPixel, int yPixel) {
972 		mouseX = xPixel;
973 		mouseY = yPixel;
974 		mouseState = Mouse.UP;
975 		clickCount = 0;
976 		GraphSet gs = GraphSet.findGraphSet(graphSets, xPixel, yPixel);
977 		if (gs == null)
978 			return;
979 //		setCurrentGraphSet(gs, yPixel, 0);
980 		gs.mouseMovedEvent(xPixel, yPixel);
981 	}
982 
doMousePressed(int xPixel, int yPixel)983 	public void doMousePressed(int xPixel, int yPixel) {
984 		mouseState = Mouse.DOWN;
985 		GraphSet gs = GraphSet.findGraphSet(graphSets, xPixel, yPixel);
986 		if (gs == null)
987 			return;
988 		setCurrentGraphSet(gs, yPixel);
989 		clickCount = (++clickCount % 3);
990 		currentGraphSet.mousePressedEvent(xPixel, yPixel, clickCount);
991 	}
992 
doMouseDragged(int xPixel, int yPixel)993 	public void doMouseDragged(int xPixel, int yPixel) {
994 		isIntegralDrag |= ctrlPressed;
995 		mouseState = Mouse.DOWN;
996 		if (GraphSet.findGraphSet(graphSets, xPixel, yPixel) != currentGraphSet)
997 			return;
998 		if (currentGraphSet.checkWidgetEvent(xPixel, yPixel, false))
999 			setTaintedAll();
1000 		currentGraphSet.mouseMovedEvent(xPixel, yPixel);
1001 	}
1002 
doMouseReleased(int xPixel, int yPixel, boolean isButton1)1003 	public void doMouseReleased(int xPixel, int yPixel, boolean isButton1) {
1004 		mouseState = Mouse.UP;
1005 		if (thisWidget == null && currentGraphSet.pendingMeasurement == null || !isButton1)
1006 			return;
1007 		currentGraphSet.mouseReleasedEvent(xPixel, yPixel);
1008 		thisWidget = null;
1009 		isIntegralDrag = false;
1010 		integralShiftMode = 0;
1011 		// repaint();
1012 	}
1013 
doMouseClicked(int xPixel, int yPixel, boolean isControlDown)1014 	public void doMouseClicked(int xPixel, int yPixel,
1015 			boolean isControlDown) {
1016 		GraphSet gs = GraphSet.findGraphSet(graphSets, xPixel, yPixel);
1017 		if (gs == null)
1018 			return;
1019 		setCurrentGraphSet(gs, yPixel);
1020 		gs.mouseClickedEvent(xPixel, yPixel, clickCount, isControlDown);
1021 		setTaintedAll();
1022 		repaint();
1023 	}
1024 
hasCurrentMeasurements(AType type)1025 	public boolean hasCurrentMeasurements(AType type) {
1026 		return currentGraphSet.hasCurrentMeasurement(type);
1027 	}
1028 
getDialog(AType type)1029 	public AnnotationData getDialog(AType type) {
1030 		return currentGraphSet.getDialog(type, -1);
1031 	}
1032 
addDialog(int iSpec, AType type, AnnotationData dialog)1033 	public void addDialog(int iSpec, AType type, AnnotationData dialog) {
1034 		currentGraphSet.addDialog(iSpec, type, dialog);
1035 	}
1036 
getPeakListing(Parameters p, Boolean tfToggle)1037 	public void getPeakListing(Parameters p, Boolean tfToggle) {
1038 		if (p != null)
1039 			currentGraphSet.getPeakListing(-1, p, true);
1040 		currentGraphSet.setPeakListing(tfToggle);
1041 	}
1042 
checkIntegral(Parameters parameters, String value)1043 	public void checkIntegral(Parameters parameters, String value) {
1044 		currentGraphSet.checkIntegralParams(parameters, value);
1045 	}
1046 
1047 	/**
1048 	 * DEPRECATED
1049 	 *
1050 	 * Sets the integration ratios that will be displayed
1051 	 *
1052 	 * @param value
1053 	 */
setIntegrationRatios(String value)1054 	public void setIntegrationRatios(String value) {
1055 		currentGraphSet.setIntegrationRatios(value);
1056 	}
1057 
getView()1058 	public ScaleData getView() {
1059 		return currentGraphSet.getCurrentView();
1060 	}
1061 
closeAllDialogsExcept(AType type)1062 	public void closeAllDialogsExcept(AType type) {
1063 		for (int i = graphSets.size(); --i >= 0;)
1064 			graphSets.get(i).closeDialogsExcept(type);
1065 	}
1066 
removeDialog(JSVDialog dialog)1067 	public void removeDialog(JSVDialog dialog) {
1068 		currentGraphSet.removeDialog(dialog);
1069 	}
1070 
normalizeIntegral()1071 	public void normalizeIntegral() {
1072 		Integral integral = getSelectedIntegral();
1073 		if (integral == null)
1074 			return;
1075 		String sValue = integral.text;
1076 		if (sValue.length() == 0)
1077 			sValue = "" + integral.getValue();
1078 		String newValue = getInput("Enter a new value for this integral",
1079 				"Normalize Integral", sValue);
1080 		try {
1081 			setSelectedIntegral(Double.parseDouble(newValue));
1082 		} catch (Exception e) {
1083 		}
1084 	}
1085 
getDrawTitle(boolean isPrinting)1086 	public String getDrawTitle(boolean isPrinting) {
1087 		String title = null;
1088 		if (isPrinting)
1089 			title = printJobTitle;
1090 		else if (nSpectra == 1) {
1091 			title = getSpectrum().getPeakTitle();
1092 		} else if (viewTitle != null) {
1093 			if (currentGraphSet.getTitle(false) != null) // check if common title
1094 				title = getSpectrum().getPeakTitle();
1095 			if (title == null)
1096 				title = viewTitle; // "View 1"
1097 		} else {
1098 			title = jsvp.getTitle().trim();
1099 		}
1100 		if (title.indexOf("\n") >= 0)
1101 			title = title.substring(0, title.indexOf("\n")).trim();
1102 		return title;
1103 	}
1104 
getPrintJobTitle(boolean isPrinting)1105 	public String getPrintJobTitle(boolean isPrinting) {
1106 		String title = null;
1107 		if (nSpectra == 1) {
1108 			title = getSpectrum().getTitle();
1109 		} else if (viewTitle != null) {
1110 			if (graphSets.size() == 1)
1111 				title = currentGraphSet.getTitle(isPrinting);
1112 			if (title == null)
1113 				title = viewTitle; // "View 1"
1114 		} else {
1115 			title = jsvp.getTitle().trim();
1116 		}
1117 		if (title.indexOf("\n") >= 0)
1118 			title = title.substring(0, title.indexOf("\n")).trim();
1119 		else if (title.startsWith("$"))
1120 			title = title.substring(1);
1121 		return title;
1122 	}
1123 
linkSpectra(LinkMode mode)1124 	public synchronized void linkSpectra(LinkMode mode) {
1125 		if (mode == LinkMode.ALL)
1126 			mode = (nSpectra == 2 ? LinkMode.AB : nSpectra == 3 ? LinkMode.ABC
1127 					: LinkMode.NONE);
1128 		if (mode != LinkMode.NONE && mode.toString().length() != nSpectra)
1129 			return;
1130 		setGraphSets(mode);
1131 	}
1132 
1133 	private boolean linking;
1134 	public int xPixelClicked;
1135 
doZoomLinked(GraphSet graphSet, double initX, double finalX, boolean addZoom, boolean checkRange, boolean is1d)1136 	public void doZoomLinked(GraphSet graphSet, double initX, double finalX,
1137 			boolean addZoom, boolean checkRange, boolean is1d) {
1138 		if (linking)
1139 			return;
1140 		linking = true;
1141 		Spectrum spec = graphSet.getSpectrumAt(0);
1142 		for (int i = graphSets.size(); --i >= 0;) {
1143 			GraphSet gs = graphSets.get(i);
1144 			if (gs != graphSet
1145 					&& Spectrum.areXScalesCompatible(spec, graphSets.get(i)
1146 							.getSpectrumAt(0), false, true))
1147 				gs.doZoom(initX, 0, finalX, 0, is1d, false, checkRange, false, addZoom);
1148 		}
1149 		linking = false;
1150 	}
1151 
clearLinkViews(GraphSet graphSet)1152 	public void clearLinkViews(GraphSet graphSet) {
1153 		if (linking)
1154 			return;
1155 		linking = true;
1156 		Spectrum spec = graphSet.getSpectrum();
1157 		for (int i = graphSets.size(); --i >= 0;) {
1158 			GraphSet gs = graphSets.get(i);
1159 			if (gs != graphSet
1160 					&& Spectrum.areXScalesCompatible(spec, graphSets.get(i)
1161 							.getSpectrum(), false, true))
1162 				gs.clearViews();
1163 		}
1164 		linking = false;
1165 	}
1166 
setlinkedXMove(GraphSet graphSet, double x, boolean isX2)1167 	public void setlinkedXMove(GraphSet graphSet, double x, boolean isX2) {
1168 		if (linking)
1169 			return;
1170 		linking = true;
1171 		Spectrum spec = graphSet.getSpectrum();
1172 		for (int i = graphSets.size(); --i >= 0;) {
1173 			GraphSet gs = graphSets.get(i);
1174 			if (gs != graphSet
1175 					&& Spectrum.areXScalesCompatible(spec, graphSets.get(i)
1176 							.getSpectrum(), false, true)) {
1177 				if (gs.imageView == null)
1178 					if (isX2) {
1179 						gs.setXPixelMovedTo(Double.MAX_VALUE, x, 0, 0);
1180 					} else {
1181 						gs.setXPixelMovedTo(x, Double.MAX_VALUE, 0, 0);
1182 					}
1183 			}
1184 		}
1185 		linking = false;
1186 	}
1187 
set2DCrossHairsLinked(GraphSet graphSet, double x, double y, boolean isLocked)1188 	public void set2DCrossHairsLinked(GraphSet graphSet, double x, double y,
1189 			boolean isLocked) {
1190 		//if (Math.abs(x - y) < 0.1)
1191 			//x = y = Double.MAX_VALUE;
1192 		for (int i = graphSets.size(); --i >= 0;) {
1193 			GraphSet gs = graphSets.get(i);
1194 			if (gs != graphSet)
1195 				gs.set2DXY(x, y, isLocked);
1196 		}
1197 	}
1198 
dialogsToFront(Spectrum spec)1199 	public void dialogsToFront(Spectrum spec) {
1200 		currentGraphSet.dialogsToFront(spec);
1201 	}
1202 
1203 	// //////// settable colors //////////
1204 
1205 	public GenericColor coordinatesColor;
1206 	public GenericColor gridColor;
1207 	public GenericColor integralPlotColor;
1208 	public GenericColor peakTabColor;
1209 	public GenericColor plotAreaColor;
1210 	public GenericColor scaleColor;
1211 	public GenericColor titleColor;
1212 	public GenericColor unitsColor;
1213 	// potentially settable;
1214 
1215 	public GenericColor highlightColor;
1216 	public GenericColor zoomBoxColor;
1217 	public GenericColor zoomBoxColor2;
1218 	public GenericColor BLACK;
1219 	public GenericColor bgcolor;
1220 
setColor(ScriptToken st, GenericColor color)1221 	public void setColor(ScriptToken st, GenericColor color) {
1222 		if (color != null)
1223 			options.put(st, CU.toRGBHexString(color));
1224 		// "return" is because these are front/back pane operations
1225 		switch (st) {
1226 		case COORDINATESCOLOR:
1227 			coordinatesColor = color;
1228 			return;
1229 		case HIGHLIGHTCOLOR:
1230 			highlightColor = color;
1231 			if (highlightColor.getOpacity255() == 255)
1232 				highlightColor.setOpacity255(150);
1233 			return;
1234 		case ZOOMBOXCOLOR:
1235 			zoomBoxColor = color;
1236 			return;
1237 		case ZOOMBOXCOLOR2:
1238 			zoomBoxColor2 = color;
1239 			return;
1240 		case BACKGROUNDCOLOR:
1241 			jsvp.setBackgroundColor(bgcolor = color);
1242 			break;
1243 		case GRIDCOLOR:
1244 			gridColor = color;
1245 			break;
1246 		case INTEGRALPLOTCOLOR:
1247 			integralPlotColor = color;
1248 			break;
1249 		case PEAKTABCOLOR:
1250 			peakTabColor = color;
1251 			break;
1252 		case PLOTCOLOR:
1253 			for (int i = graphSets.size(); --i >= 0;)
1254 				graphSets.get(i).setPlotColor0(color);
1255 			break;
1256 		case PLOTAREACOLOR:
1257 			plotAreaColor = color;
1258 			break;
1259 		case SCALECOLOR:
1260 			scaleColor = color;
1261 			break;
1262 		case TITLECOLOR:
1263 			titleColor = color;
1264 			break;
1265 		case UNITSCOLOR:
1266 			unitsColor = color;
1267 			break;
1268 		default:
1269 			Logger.warn("AwtPanel --- unrecognized color: " + st);
1270 			return;
1271 		}
1272 		taintedAll = true;
1273 	}
1274 
getColor(ScriptToken whatColor)1275 	public GenericColor getColor(ScriptToken whatColor) {
1276 		switch (whatColor) {
1277 		default:
1278 			Logger.error("awtgraphset missing color " + whatColor);
1279 			return BLACK;
1280 		case ZOOMBOXCOLOR2:
1281 			return zoomBoxColor2;
1282 		case ZOOMBOXCOLOR:
1283 			return zoomBoxColor;
1284 		case HIGHLIGHTCOLOR:
1285 			return highlightColor;
1286 		case INTEGRALPLOTCOLOR:
1287 			return integralPlotColor;
1288 		case GRIDCOLOR:
1289 			return gridColor;
1290 		case PEAKTABCOLOR:
1291 			return peakTabColor;
1292 		case PLOTAREACOLOR:
1293 			return plotAreaColor;
1294 		case SCALECOLOR:
1295 			return scaleColor;
1296 		case TITLECOLOR:
1297 			return titleColor;
1298 		case UNITSCOLOR:
1299 			return unitsColor;
1300 		}
1301 	}
1302 
getOverlayLegendData()1303 	public Object[][] getOverlayLegendData() {
1304 		int numSpectra = currentGraphSet.nSpectra;
1305 		Object[][] data = new Object[numSpectra][];
1306 		String f1 = getSpectrumAt(0).getFilePath();
1307 		String f2 = getSpectrumAt(numSpectra - 1).getFilePath();
1308 		boolean useFileName = f1 != null && f2 != null && !f1.equals(f2);
1309 
1310 		for (int index = 0; index < numSpectra; index++) {
1311 			Object[] cols = new Object[3];
1312 			Spectrum spectrum = getSpectrumAt(index);
1313 			title = spectrum.getTitle();
1314 			if (useFileName)
1315 				title = JSVFileManager.getTagName(spectrum.getFilePath()) + " - " + title;
1316 			GenericColor plotColor = getCurrentPlotColor(index);
1317 			cols[0] = new Integer(index + 1);
1318 			cols[1] = plotColor;
1319 			cols[2] = " " + title;
1320 			data[index] = cols;
1321 		}
1322 		return data;
1323 	}
1324 
1325 	@SuppressWarnings("incomplete-switch")
setColorOrFont(ColorParameters params, ScriptToken st)1326 	public void setColorOrFont(ColorParameters params, ScriptToken st) {
1327 		if (st == null) {
1328 			Map<ScriptToken, GenericColor> colors = params.elementColors;
1329 			for (Map.Entry<ScriptToken, GenericColor> entry : colors.entrySet())
1330 				setColorOrFont(params, entry.getKey());
1331 			setColorOrFont(params, ScriptToken.DISPLAYFONTNAME);
1332 			setColorOrFont(params, ScriptToken.TITLEFONTNAME);
1333 			return;
1334 		}
1335 		switch (st) {
1336 		case DISPLAYFONTNAME:
1337 			setFontName(st, params.displayFontName);
1338 			return;
1339 		case TITLEFONTNAME:
1340 			setFontName(st, params.titleFontName);
1341 			return;
1342 		}
1343 		setColor(st, params.getElementColor(st));
1344 	}
1345 
getCurrentPlotColor(int i)1346 	public GenericColor getCurrentPlotColor(int i) {
1347 		return currentGraphSet.getPlotColor(i);
1348 	}
1349 
1350 	public Hashtable<ScriptToken, Object> optionsSaved;
1351 	private Object gMain;
1352 
setPrint(PrintLayout pl, String fontName)1353 	public void setPrint(PrintLayout pl, String fontName) {
1354 		if (pl == null) {
1355 			options.putAll(optionsSaved);
1356 			optionsSaved = null;
1357 			return;
1358 		}
1359 		printJobTitle = pl.title;
1360 		// Set Graph Properties
1361 		printingFontName = fontName;
1362 		printGraphPosition = pl.position;
1363 
1364 		optionsSaved = new Hashtable<ScriptToken, Object>();
1365 		optionsSaved.putAll(options);
1366 
1367 		gridOn = pl.showGrid;
1368 		titleOn = pl.showTitle;
1369 		setBoolean(ScriptToken.XSCALEON, pl.showXScale);
1370 		setBoolean(ScriptToken.XUNITSON, pl.showXScale);
1371 		setBoolean(ScriptToken.YSCALEON, pl.showYScale);
1372 		setBoolean(ScriptToken.YUNITSON, pl.showYScale);
1373 
1374 
1375 		// TODO Auto-generated method stub
1376 
1377 	}
1378 
1379 
setDefaultPrintOptions(PrintLayout pl)1380 	public void setDefaultPrintOptions(PrintLayout pl) {
1381 		 pl.showGrid = gridOn;
1382 		 pl.showXScale = getBoolean(ScriptToken.XSCALEON);
1383 		 pl.showYScale = getBoolean(ScriptToken.YSCALEON);
1384 		 pl.showTitle = titleOn;
1385 	}
1386 
1387 
showDialog(AType type)1388 	public JSVDialog showDialog(AType type) {
1389 		AnnotationData ad = getDialog(type);
1390 		closeAllDialogsExcept(type);
1391 		if (ad != null && ad instanceof JSVDialog)
1392 			return ((JSVDialog) ad).reEnable();
1393 		int iSpec = getCurrentSpectrumIndex();
1394 		if (iSpec < 0) {
1395 			jsvp.showMessage("To enable " + type + " first select a spectrum by clicking on it.", "" + type);
1396 			return null;
1397 		}
1398 		Spectrum spec = getSpectrum();
1399 		JSVDialog dialog = vwr.getDialog(type, spec);
1400 		if (ad == null && type == AType.Measurements)
1401 			ad = new MeasurementData(AType.Measurements, spec);
1402 		if (ad != null)
1403 			dialog.setData(ad);
1404 		addDialog(iSpec, type, dialog);
1405 		dialog.reEnable();
1406 		return dialog;
1407 	}
1408 
1409 	/**
1410 	 * from jspecview.export.PDFCreator
1411 	 *
1412 	 * -- does not use iText --
1413 	 *
1414 	 *
1415 	 * @param pdfCreator
1416 	 * @param pl
1417 	 */
printPdf(GenericGraphics pdfCreator, PrintLayout pl)1418 	public void printPdf(GenericGraphics pdfCreator, PrintLayout pl) {
1419 		boolean isPortrait = !pl.layout.equals("landscape");
1420 		print(pdfCreator, (isPortrait ? pl.imageableHeight : pl.imageableWidth),
1421 				(isPortrait ? pl.imageableWidth : pl.imageableHeight),
1422 				pl.imageableX, pl.imageableY,
1423 				pl.paperHeight, pl.paperWidth, isPortrait, 0);
1424 	}
1425 
print(Object g, double height, double width, double x, double y, double paperHeight, double paperWidth, boolean isPortrait, int pi)1426 	public int print(Object g, double height, double width,
1427 			double x, double y, double paperHeight, double paperWidth,
1428 			boolean isPortrait, int pi) {
1429     g2d = g2d0;
1430     if (pi == 0) {
1431       isPrinting = true;
1432       boolean addFilePath = false;
1433       if (g instanceof GenericGraphics) {// JsPdfCreator
1434       	g2d = (GenericGraphics) g;
1435       	g = gMain;
1436       }
1437       if (printGraphPosition.equals("default")) {
1438         if (isPortrait) {
1439           height = defaultPrintHeight;
1440           width = defaultPrintWidth;
1441         } else {
1442           height = defaultPrintWidth;
1443           width = defaultPrintHeight;
1444         }
1445       } else if (printGraphPosition.equals("fit to page")) {
1446         addFilePath = true;
1447       } else { // center
1448         if (isPortrait) {
1449           height = defaultPrintHeight;
1450           width = defaultPrintWidth;
1451           x = (int) (paperWidth - width) / 2;
1452           y = (int) (paperHeight - height) / 2;
1453         } else {
1454           height = defaultPrintWidth;
1455           width = defaultPrintHeight;
1456           y = (int) (paperWidth - defaultPrintWidth) / 2;
1457           x = (int) (paperHeight - defaultPrintHeight) / 2;
1458         }
1459       }
1460       g2d.translateScale(g, x, y, 0.1);
1461       setTaintedAll();
1462       drawGraph(g, g, g, (int) width, (int) height, addFilePath);
1463       isPrinting = false;
1464       return JSViewer.PAGE_EXISTS;
1465     }
1466     isPrinting = false;
1467     return JSViewer.NO_SUCH_PAGE;
1468 	}
1469 
1470   /*--------------mouse and keyboard interface -----------------------*/
1471 
1472 	@Override
keyPressed(int code, int modifiers)1473 	public boolean keyPressed(int code, int modifiers) {
1474 		if (isPrinting)
1475 			return false;
1476 		checkKeyControl(code, true);
1477 		// should be only in panel region, though.
1478 		switch (code) {
1479 		case Event.VK_ESCAPE:
1480 		case Event.VK_DELETE:
1481 		case Event.VK_BACK_SPACE: // Mac
1482 			escapeKeyPressed(code != Event.VK_ESCAPE);
1483 			isIntegralDrag = false;
1484 			setTaintedAll();
1485 			repaint();
1486 			return true;
1487 		}
1488 		double scaleFactor = 0;
1489 		boolean doConsume = false;
1490 		if (modifiers == 0) {
1491 			switch (code) {
1492 			case Event.VK_LEFT:
1493 			case Event.VK_RIGHT:
1494 				doMouseMoved((code == Event.VK_RIGHT ? ++mouseX : --mouseX), mouseY);
1495 				repaint();
1496 				doConsume = true;
1497 				break;
1498 			case Event.VK_PAGE_UP:
1499 			case Event.VK_PAGE_DOWN:
1500 				scaleFactor = (code == Event.VK_PAGE_UP ? GraphSet.RT2
1501 						: 1 / GraphSet.RT2);
1502 				doConsume = true;
1503 				break;
1504 			case Event.VK_DOWN:
1505 			case Event.VK_UP:
1506 				int dir = (code == Event.VK_DOWN ? -1 : 1);
1507 				if (getSpectrumAt(0).getSubSpectra() == null) {
1508 					notifySubSpectrumChange(dir, null);
1509 				} else {
1510 					advanceSubSpectrum(dir);
1511 					setTaintedAll();
1512 					repaint();
1513 				}
1514 				doConsume = true;
1515 				break;
1516 			}
1517 		} else if (checkMod(code, Event.CTRL_MASK)) {
1518 			switch (code) {
1519 			case Event.VK_DOWN:
1520 			case Event.VK_UP:
1521 			case 45: // '-'
1522 			case 61: // '=/+'
1523 				scaleFactor = (code == 61 || code == Event.VK_UP ? GraphSet.RT2
1524 						: 1 / GraphSet.RT2);
1525 				doConsume = true;
1526 				break;
1527 			case Event.VK_LEFT:
1528 			case Event.VK_RIGHT:
1529 				toPeak(code == Event.VK_RIGHT ? 1 : -1);
1530 				doConsume = true;
1531 				break;
1532 			}
1533 		}
1534 		if (scaleFactor != 0) {
1535 			scaleYBy(scaleFactor);
1536 			setTaintedAll();
1537 			repaint();
1538 		}
1539 		return doConsume;
1540 	}
1541 
1542 	@Override
keyReleased(int keyCode)1543 	public void keyReleased(int keyCode) {
1544 		if (isPrinting)
1545 			return;
1546 		checkKeyControl(keyCode, false);
1547 	}
1548 
1549 	@Override
keyTyped(int ch, int mods)1550 	public boolean keyTyped(int ch, int mods) {
1551 		if (isPrinting)
1552 			return false;
1553 		switch (ch) {
1554 		case 'n':
1555 			if (mods != 0)
1556 				break;
1557 			normalizeIntegral();
1558 			return true;
1559 		case 26: // ctrl-Z
1560 			if (mods != Event.CTRL_MASK)
1561 				break;
1562 			previousView();
1563 			setTaintedAll();
1564 			repaint();
1565 			return true;
1566 		case 25: // ctrl-y
1567 			if (mods != Event.CTRL_MASK)
1568 				break;
1569 			nextView();
1570 			setTaintedAll();
1571 			repaint();
1572 			return true;
1573 		}
1574 		return false;
1575 	}
1576 
1577 	@Override
mouseAction(int mode, long time, int x, int y, int countIgnored, int buttonMods)1578 	public void mouseAction(int mode, long time, int x, int y, int countIgnored,
1579 			int buttonMods) {
1580 		if (isPrinting)
1581 			return;
1582 		switch (mode) {
1583 		case Event.PRESSED:
1584 			if (!checkMod(buttonMods, Event.MOUSE_LEFT))
1585 				return;
1586 			doMousePressed(x, y);
1587 			break;
1588 		case Event.RELEASED:
1589 			doMouseReleased(x, y, checkMod(buttonMods, Event.MOUSE_LEFT));
1590 			setTaintedAll();
1591 			repaint();
1592 			break;
1593 		case Event.DRAGGED:
1594 			doMouseDragged(x, y);
1595 			repaint();
1596 			break;
1597 		case Event.MOVED:
1598 	    jsvp.getFocusNow(false);
1599 			if ((buttonMods & Event.BUTTON_MASK) != 0) {
1600 				doMouseDragged(x, y);
1601 				repaint();
1602 				return;
1603 			}
1604 			doMouseMoved(x, y);
1605 			if (coordStr != null)
1606 				repaint();
1607 			break;
1608 		case Event.CLICKED:
1609 	    if (checkMod(buttonMods, Event.MOUSE_RIGHT)) {
1610 	    	jsvp.showMenu(x, y);
1611 	      return;
1612 	    }
1613 			ctrlPressed = false;
1614 			doMouseClicked(x, y, updateControlPressed(buttonMods));
1615 			break;
1616 		}
1617 	}
1618 
checkMod(int buttonMods, int mask)1619 	public boolean checkMod(int buttonMods, int mask) {
1620 		return ((buttonMods & mask) == mask);
1621 	}
1622 
checkKeyControl(int keyCode, boolean isPressed)1623 	public void checkKeyControl(int keyCode, boolean isPressed) {
1624 		switch (keyCode) {
1625 		case Event.VK_CONTROL:
1626 		case Event.VK_META:
1627 			ctrlPressed = isPressed;
1628 			break;
1629 		case Event.VK_SHIFT:
1630 			shiftPressed = isPressed;
1631 			break;
1632 		//default:
1633 			//ctrlPressed = updateControlPressed(keyCode);
1634 			//shiftPressed = checkMod(keyCode, Event.SHIFT_MASK);
1635 		}
1636 	}
1637 
updateControlPressed(int mods)1638 	public boolean updateControlPressed(int mods) {
1639 		// Mac does not allow Ctrl-drag. The CMD key is indicated using code 157
1640 		return (ctrlPressed |= checkMod(mods, Event.CTRL_MASK)
1641 				|| checkMod(mods, Event.MAC_COMMAND));
1642 	}
1643 
1644 	@Override
mouseEnterExit(long time, int x, int y, boolean isExit)1645 	public void mouseEnterExit(long time, int x, int y, boolean isExit) {
1646 		if (isExit) {
1647 			thisWidget = null;
1648 			isIntegralDrag = false;
1649 			integralShiftMode = 0;
1650 		} else {
1651 			try {
1652 				jsvp.getFocusNow(false);
1653 			} catch (Exception e) {
1654 				System.out.println("pd " + this + " cannot focus");
1655 			}
1656 		}
1657 	}
1658 
setSolutionColor(String what)1659 	public void setSolutionColor(String what) {
1660 		boolean isNone = (what.indexOf("none") >= 0);
1661 		boolean asFitted = (what.indexOf("false") < 0);
1662 		if (what.indexOf("all") < 0) {
1663 			int color = (isNone ? -1 : vwr.getSolutionColor(asFitted));
1664 			getSpectrum().setFillColor(color == -1 ? null : vwr.parameters.getColor1(color));
1665 		} else {
1666 			VisibleInterface vi = (VisibleInterface) JSViewer.getInterface("jspecview.common.Visible");
1667 			for (int i = graphSets.size(); --i >= 0;)
1668 				graphSets.get(i).setSolutionColor(vi, isNone, asFitted);
1669 		}
1670 
1671 		// TODO Auto-generated method stub
1672 
1673 	}
1674 
setIRMode(IRMode mode, String type)1675 	public void setIRMode(IRMode mode, String type) {
1676 		for (int i = graphSets.size(); --i >= 0;)
1677 			graphSets.get(i).setIRMode(mode, type);
1678 	}
1679 
closeSpectrum()1680 	public void closeSpectrum() {
1681 		vwr.close("views");
1682 		vwr.close(getSourceID());
1683 		vwr.execView("*", true);
1684 	}
1685 
1686 }
1687