package jp.hasc.hasctool.ui.views;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.NavigableSet;
import java.util.TreeSet;
import java.util.concurrent.TimeUnit;

import jp.hasc.hasctool.core.data.DefaultVectorSignalComparator;
import jp.hasc.hasctool.core.data.LabelSignalMessage;
import jp.hasc.hasctool.core.data.NullSignalMessage;
import jp.hasc.hasctool.core.data.ObjectSignalMessage;
import jp.hasc.hasctool.core.data.SignalMessage;
import jp.hasc.hasctool.core.data.VectorSignalMessage;
import jp.hasc.hasctool.core.data.VectorSignalMessages;
import jp.hasc.hasctool.core.messaging.MessageProcessor;
import jp.hasc.hasctool.core.runtime.FileStreamProvider;
import jp.hasc.hasctool.core.util.CoreUtil;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.MouseWheelListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;

/**
 * CoordinateViewのWidget
 * @author hodaka
 */
public class CoordinateViewWidget extends Composite {
	
	private final class CopyLinkSelectionListener implements SelectionListener {
		@Override
		public void widgetSelected(SelectionEvent e) {
			String text=e.text;
			LOG.debug("toClipboard: "+text);
			CoreUtil.copyToClipboard(getShell().getDisplay(), text);          
		}

		@Override
		public void widgetDefaultSelected(SelectionEvent e) {
		}
	}  

	/** logger for this class */
	private final static org.apache.commons.logging.Log LOG = org.apache.commons.logging.LogFactory
	.getLog(CoordinateViewWidget.class);

	private static final int REFRESH_DELAY_MS = 1000 / 30;

	private Canvas canvas_;
//	private Slider slider_;
//	private long sliderUnitTime_;
	private Label topLabel_;
	private Link timeLabel_;
	private ToolBar toolBar_;
	

	private boolean showScale_=true;
	
	private String imagePath_;
	private Image img_;
	private int imgH, imgW;
	

	private FileStreamProvider fsp;

	public CoordinateViewWidget(Composite parent, int style) {
		super(parent,style);
		this.setLayout(new FormLayout());

		toolBar_ = new ToolBar(this, SWT.VERTICAL);
		{
			FormData fd = new FormData();
			fd.top=new FormAttachment(0, 1);
			fd.right=new FormAttachment(100, -1);
			fd.bottom=new FormAttachment(100, -1);
			toolBar_.setLayoutData(fd);
		}

		{
			ToolItem ti=new ToolItem(toolBar_, SWT.NONE);
			ti.setText("+");
			ti.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					upScale();
				}
			});
		}
		{
			ToolItem ti=new ToolItem(toolBar_, SWT.NONE);
			ti.setText("-");
			ti.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					downScale();
				}
			});
		}

		{
			ToolItem ti=new ToolItem(toolBar_, SWT.NONE);
			ti.setText("[*]");
			ti.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					initializeScale();
				}

			});
		}
		
		//
		topLabel_ = new Label(this, SWT.WRAP);
		{
			FormData fd = new FormData();
			fd.top=new FormAttachment(0, 1);
			fd.left=new FormAttachment(0, 1);
			fd.right=new FormAttachment(70, -1);
			topLabel_.setLayoutData(fd);
			/*
			String sid = getViewSite().getSecondaryId();
			topLabel_.setText(sid!=null?sid:"");
			 */
		}

		timeLabel_ = new Link(this, SWT.WRAP);
		{
			FormData fd = new FormData();
			fd.top=new FormAttachment(0, 1);
			fd.left=new FormAttachment(topLabel_, 1);
			fd.right=new FormAttachment(toolBar_, -1);
			timeLabel_.setText("time:");
			timeLabel_.setLayoutData(fd);
			timeLabel_.addSelectionListener(new CopyLinkSelectionListener());
		}
		
		


		/*
		valueLabel_ = new Link(this, SWT.WRAP);
		{
			FormData fd = new FormData();
			fd.top=new FormAttachment(0, 1);
			fd.left=new FormAttachment(timeLabel_, 1);
			fd.right=new FormAttachment(100, -1);
			valueLabel_.setText("<a>value</a>");
			valueLabel_.setLayoutData(fd);
			valueLabel_.addSelectionListener(new CopyLinkSelectionListener());
		}
		 */


		canvas_ = new Canvas(this, SWT.BORDER | SWT.DOUBLE_BUFFERED);
		{
			FormData fd = new FormData();
			fd.top=new FormAttachment(topLabel_, 1);
			fd.left=new FormAttachment(0, 1);
			fd.bottom=new FormAttachment(100, -1);
			fd.right=new FormAttachment(toolBar_, -1);
			canvas_.setLayoutData(fd);
			canvas_.addPaintListener(new PaintListener() {
				@Override
				public void paintControl(PaintEvent e) {
					onCanvasPaint(e);
				}
			});
			

			// time picker
//			canvas_.addMouseListener(new MouseListener() {
//				int downX_,downY_; 
//
//				@Override
//				public void mouseUp(MouseEvent e) {
//					if (e.button==1) {
//						if (Math.abs(downX_-e.x)>2 || Math.abs(downY_-e.y)>2) {
//							// range
////							timeMarkerEnd_=getTimeAtCanvasX(e.x,getCanvasWidth());
////							if (timeMarkerEnd_<timeMarkerBegin_) {
////								// swap
////								Long tmp=timeMarkerBegin_; timeMarkerBegin_=timeMarkerEnd_; timeMarkerEnd_=tmp;
////							}
//							
//						
////							updateTimeLabel();
//							requestRedraw();
//						}
//					}
//				}
//
//				@Override
//				public void mouseDown(MouseEvent e) {
//					if (e.button==1) {
//						downX_=e.x;
//						downY_=e.y;
////						timeMarkerBegin_=getTimeAtCanvasX(downX_,getCanvasWidth());
//						// point
//						timeMarkerEnd_=null;
//						
////						updateTimeLabel();
//						requestRedraw();
//					}else{
//						timeMarkerBegin_=timeMarkerEnd_=null;
////						updateTimeLabel();
//						requestRedraw();
//					}
//				}
//
//				@Override
//				public void mouseDoubleClick(MouseEvent e) {
//				}
//			});
			
			canvas_.addMouseMoveListener(new MouseMoveListener() {
				int preX = -1;
				int preY = -1;
				@Override
				public void mouseMove(MouseEvent e) {
					if (e.stateMask == SWT.BUTTON1) {
						if (preX > 0) {;
							setWidthMin(getWidthMin() - (double)(e.x - preX)/viewSize_);
							setHeightMin(getHeightMin() - (double)(e.y - preY)/viewSize_);
							requestRedraw();
						}
						preX = e.x;
						preY = e.y;
					} else {
						preX = -1;
						preY = -1;
					}
					
				}
			});
			
			canvas_.addMouseWheelListener(new MouseWheelListener() {			
				@Override
				public void mouseScrolled(MouseEvent e) {
					System.out.println("scrolled");
					if (e.count > 0) upScale();
					else downScale();
				}
			});
		}
		
			




		//
		clearData(DATA_BITS_ALL);
	}

//	protected void updateLabel() {
//		if (timeMarkerEnd_!=null && timeMarkerBegin_!=null) {
//			timeLabel_.setText("time:<a>"+
//					((viewTimeOffset_!=0)?"r ":"")+
//					timeToSecond(timeMarkerBegin_-viewTimeOffset_)+","+timeToSecond(timeMarkerEnd_-viewTimeOffset_)+"</a>");
//		}else if (timeMarkerBegin_!=null) {
//			timeLabel_.setText("time:<a>"+
//					((viewTimeOffset_!=0)?"r ":"")+
//					timeToSecond(timeMarkerBegin_-viewTimeOffset_)+"</a>");
//		}else{
//			timeLabel_.setText("time:");
//		}
//	}

	public static double timeToSecond(Long time) {
		return SignalMessage.TIME_UNIT.toMillis(time)/1000.0;
	}

	private Long timeMarkerBegin_=null, timeMarkerEnd_=null;
	private int signalDataCapacity_ = -1; // -1なら無制限
	private NavigableSet<VectorSignalMessage> coData_=new TreeSet<VectorSignalMessage>(new DefaultVectorSignalComparator());
	private NavigableSet<LabelSignalMessage> labelData_=new TreeSet<LabelSignalMessage>();
	private double viewSize_ = 1.0;
	private double heightMin_= 100;
	private double widthMin_= 0;

	private Color[] waveColores_=new Color[]{new Color(null,0,0,255), new Color(null,255,0,0),
			new Color(null,0,255,0), new Color(null,0,255,255), new Color(null,255,0,255)};
	
	public static class AlphaColor {
		private int alpha_;
		private Color color_;
		public AlphaColor(int a,int r,int g,int b) {
			alpha_=a;
			color_=new Color(null,r,g,b);
		}
		public int getAlpha() {
			return alpha_;
		}
		public Color getColor() {
			return color_;
		}
		
		/**
		 * 半透明の色（this）を、背景色backgroundと合成して、不透明化した色を返します
		 */
		public Color getOpaqueColor(Color background) {
			Color ret;
			int a=alpha_;
			if (a==255) {
				ret = color_;
			}else{
				int r=color_.getRed();
				int g=color_.getGreen();
				int b=color_.getBlue();
				int r0=background.getRed();
				int g0=background.getGreen();
				int b0=background.getBlue();
				ret = new Color(null,r0*(255-a)/255+r*a/255,g0*(255-a)/255+g*a/255,b0*(255-a)/255+b*a/255);
			}
			return ret;
		}
	}
	
	public static final AlphaColor ALPHA_COLOR_WHITE = new AlphaColor(255,255,255,255);
	private static final AlphaColor ALPHA_COLOR_TIME_MARKER = new AlphaColor(180,170,170,170);
	
	/* 不透明のカラーセット
	private AlphaColor[] labelColors_=new AlphaColor[]{
			new AlphaColor(255,255,255,128), new AlphaColor(255,200,255,255), new AlphaColor(255,255,200,255),
			new AlphaColor(255,255,200,128), new AlphaColor(255,200,200,255), new AlphaColor(255,200,255,128), 
			new AlphaColor(255,64,255,255), new AlphaColor(255,255,64,255) };
	*/
	

	private int getCanvasWidth() {
		return canvas_.getSize().x-canvas_.getBorderWidth()*2;
	}
	private int getCanvasHeight() {
		return canvas_.getSize().y-canvas_.getBorderWidth()*2;
	}
	
	private void setBackgroundAlphaColor(GC gc, AlphaColor ac) {
		gc.setBackground(ac.getColor());
		gc.setAlpha(ac.getAlpha());
	}

	public static final Color COLOR_BLACK=new Color(null,0,0,0);
	
	/** draw view */
	private void onCanvasPaint(PaintEvent e) {
		requestedRedraw_=false;
		//
		GC gc = e.gc;
		int cw=getCanvasWidth(), ch=getCanvasHeight();
		

		// bg
		setBackgroundAlphaColor(gc, ALPHA_COLOR_WHITE);
		gc.fillRectangle(0,0,cw,ch);
		if (img_ != null) {
			gc.drawImage(img_, 0, 0, imgW, imgH, -(int)(getWidthMin()*getViewSize()), -(int)(getHeightMin()*getViewSize()), (int)(imgW * viewSize_), (int)(imgH * viewSize_));
		}




		// timeMarker BG
		setBackgroundAlphaColor(gc, ALPHA_COLOR_TIME_MARKER);
		gc.setAlpha(180);
		if (timeMarkerBegin_!=null && timeMarkerEnd_!=null) {
			int x0=getX(timeMarkerBegin_);
			int x1=getX(timeMarkerEnd_);
			gc.fillRectangle(x0, 0, x1-x0, ch);
		}
		setBackgroundAlphaColor(gc, ALPHA_COLOR_WHITE);
		

		// lines
		do {
			synchronized(coData_) {
				if (coData_.isEmpty()) {
					break;
				}
				//
//				VectorSignalMessage first= coData_.first();
//				VectorSignalMessage last =coData_.last();
				//
//				int maxVectorSize=2;
//				for(int idx=0;idx<maxVectorSize;++idx) {
					SignalMessage prevElem=null;
					int prevX=0,prevY=0;
					Color color = waveColores_[0%waveColores_.length];
					gc.setForeground(color);
					gc.setBackground(color);
					for(VectorSignalMessage elem: coData_) {
//						int vsize = elem.getVectorSize();
//						if (vsize<=idx) continue;
//						if (maxVectorSize<vsize) maxVectorSize=vsize;
						//
						int x=getX(elem.getVectorElement(0));
						int y=getY(elem.getVectorElement(1));
//						System.out.println("(" + x + ", " + y + ")");
//						System.out.println(elem.getVectorElement(0)+","+elem.getVectorElement(1));
						if (prevElem!=null) {
							gc.drawLine(prevX, prevY, x, y);
						}
//						if((prevX < x-2 || prevX > x+2) && (prevY < y-2 || prevY > y+2) ){ // if there is a distance between dot, then draw.
							gc.fillRectangle(x-1, y-1, 3,3); // stop draw box
//						}
						prevElem=elem;
						prevX=x; prevY=y;
					}
//				}
			}
		}while(false);



		// label edges
//		if (labels!=null){
//			gc.setForeground(COLOR_BLACK);
//			HashMap<LabelInfo,LabelSignalMessage> beginSigs=new HashMap<LabelInfo, LabelSignalMessage>();
//			for(LabelSignalMessage lblSig:labels) {
//				switch(lblSig.getType()) {
//				case BEGIN:
//					beginSigs.put(lblSig.getLabelInfo(), lblSig);
//					break;
//				case END:
//					LabelSignalMessage beginSig = beginSigs.get(lblSig.getLabelInfo());
//					drawLabelEdge(gc, cw, ch, lblSig, beginSig, lblSig);
//					break;
//				}
//			}
//			for(LabelSignalMessage beginSig : beginSigs.values()) {
//				drawLabelEdge(gc, cw, ch, beginSig, beginSig, null);
//			}
//			beginSigs.clear();
//		}
		setBackgroundAlphaColor(gc, ALPHA_COLOR_WHITE);


	}

//	private void drawLabelEdge(GC gc, int cw, int ch,
//			LabelSignalMessage lblSig, LabelSignalMessage beginSig, LabelSignalMessage endSig) {
//		gc.setForeground(COLOR_BLACK);
//		//
//		AlphaColor labelColor=getLabelBgColor(lblSig.getLabelInfo());
//		// 白と半透明のラベル色を合成した色を、不透明色で塗る
//		boolean transparent=false;
//		gc.setAlpha(255);
//		gc.setBackground(labelColor.getOpaqueColor(ALPHA_COLOR_WHITE.getColor()));
//		//
//		String lblStr=lblSig.getLabelInfo().getLabel();
//		int h=gc.getFontMetrics().getHeight()+4;
//		
//		if (beginSig!=null && endSig!=null && beginSig.getTime()==endSig.getTime()) {
//			// 同時刻
//			int x1=getLocX(beginSig.getTime(), cw);
//			gc.setForeground(COLOR_BLACK);
//			//gc.fillRectangle(x1-3, 0, 7, ch);
//			gc.drawLine(x1, 0, x1, ch);
//			gc.drawText(lblStr, x1+2+3, ch-h+2, transparent);
//		}else{
//			// 別時刻
//			gc.setForeground(COLOR_BLACK);
//			if (beginSig!=null) {
//				int x1=getLocX(beginSig.getTime(), cw);
//				gc.drawLine(x1, 0, x1, ch);
//				gc.drawText(lblStr, x1+2, ch-h+2, transparent);
//			}
//			if (endSig!=null) {
//				int x1=getLocX(endSig.getTime(), cw);
//				gc.drawLine(x1, 0, x1, ch);
//				int w=gc.stringExtent(lblStr).x;
//				gc.drawText(lblStr, x1-2-w, ch-h+2, transparent);
//			}
//		}
//	}

//	private AlphaColor getLabelBgColor(LabelInfo labelInfo) {
//		String lblstr = labelInfo.getLabel();
//		AlphaColor c=labelColorMap_.get(lblstr);
//		if (c!=null) return c;
//		c=getNextLabelColor();
//		labelColorMap_.put(lblstr, c);
//		return c;
//	}


	public static String getTimeString(long t) {
		return (TimeUnit.MILLISECONDS.convert(t, SignalMessage.TIME_UNIT)/1000.f)+"s";
	}

//	private long getTimeAtCanvasX(int x, int canvasWidth) {
//		int w=canvasWidth-3;
//		return (x-1-w)*viewTimeWidth_/w + viewTimeMax_;
//	}

	private int getX(double d) {
		return 1+(int)((d-widthMin_)*getViewSize());
	}

	private int getY(double d) {
		return 1+(int)((d-heightMin_)*getViewSize());
	}
	

	/*
	@Override
	public void setFocus() {
	}
	 */

	private boolean requestedUpdateTimeRangeAndRedraw=false;

	/** should be called from SWT thread */
	private void doRequestedUpdateTimeRange() {
		synchronized(coData_) {
			if (!coData_.isEmpty()) {

				// trim waveData within capacity
				if (signalDataCapacity_>=0) {
					int trimmingNum=coData_.size()-signalDataCapacity_;
					if (trimmingNum>0) {
						for(Iterator<VectorSignalMessage> it=coData_.iterator(); it.hasNext() && trimmingNum>0; --trimmingNum) {
							it.next();
							it.remove();
						}
					}
				}

				// range
//				initializeScale();
			}
		}
//		synchronized (labelData_) {
//			if (!labelData_.isEmpty()) {
//				// todo: trim LabelData？
//
//				// 表示範囲を、ラベルの範囲に拡張
//				long labelTimeMin=labelData_.first().getTime();
//				long labelTimeMax=labelData_.last().getTime();
//				if (empty || coDataTimeMin_>labelTimeMin) coDataTimeMin_=labelTimeMin;
//				if (empty || waveDataTimeMax_<labelTimeMax) waveDataTimeMax_=labelTimeMax;
//				empty=false;
//			}
//		}
//		if (empty) {
//			coDataTimeMin_=0;
//			waveDataTimeMax_=0;
//		}

		// auto scroll
//		if (followSlider_) {
//			viewTimeMax_=waveDataTimeMax_;
//		}

		// update slider
//		if (!slider_.isDisposed()) {
//			slider_.setMaximum((int)((waveDataTimeMax_-coDataTimeMin_)/sliderUnitTime_));
//			slider_.setThumb((int)(viewTimeWidth_/sliderUnitTime_));
//		}
//		setViewTimeMax(viewTimeMax_);
	}

	public void preventUpdates(boolean b) {
		if (b) {
			requestedUpdateTimeRangeAndRedraw=true;
			requestedRedraw_=true;
		}else{
			requestedUpdateTimeRangeAndRedraw=false;
			doRequestedUpdateTimeRange();
			doRedraw();
		}
	}

	public void requestUpdateTimeRangeAndRedraw() {
		if (requestedUpdateTimeRangeAndRedraw) return;
		requestedUpdateTimeRangeAndRedraw=true;
		requestedRedraw_=true;
		asyncTimerExec(REFRESH_DELAY_MS, new Runnable() {
			@Override
			public void run() {
				requestedUpdateTimeRangeAndRedraw=false;
				doRequestedUpdateTimeRange();
				doRedraw();
			}
		});
	}

	/** should be called from SWT thread */
	private void doRedraw() {
		if (!canvas_.isDisposed()) canvas_.redraw();
	}

	private boolean requestedRedraw_=false;


	public void requestRedraw() {
		if (requestedRedraw_) return;
		requestedRedraw_=true;
		asyncTimerExec(REFRESH_DELAY_MS, new Runnable() {
			@Override
			public void run() {
				doRedraw();
			}
		});
	}

	private void asyncTimerExec(final int milliseconds, final Runnable runnable) {
		getDisplay().asyncExec(new Runnable() {
			@Override
			public void run() {
				getDisplay().timerExec(milliseconds, runnable);
			}
		});
	}

	private MessageProcessor inputPort_=new MessageProcessor() {
		@Override
		public void processMessage(Object message) {
			if (message instanceof VectorSignalMessage) {
				VectorSignalMessage vecMsg=(VectorSignalMessage)message;
				processVectorSignalMessage(vecMsg);
			}else if (message instanceof ObjectSignalMessage) {
				ObjectSignalMessage osm=(ObjectSignalMessage)message;
				SignalMessage[] sigs = (SignalMessage[]) osm.getValue();
				if (sigs.length==2 && sigs[0] instanceof VectorSignalMessage && sigs[1] instanceof ObjectSignalMessage) {
					// (VectorSignalMessage, LabelSignalMessage[]) の複合メッセージ
					VectorSignalMessage vecMsg=(VectorSignalMessage)sigs[0];
					processVectorSignalMessage(vecMsg);
					//
					ObjectSignalMessage labelMsgs=(ObjectSignalMessage) sigs[1];
					SignalMessage[] lbls=(SignalMessage[]) labelMsgs.getValue();
					for(SignalMessage lbl:lbls) {
						if (lbl instanceof LabelSignalMessage) {
							processLabelMessage((LabelSignalMessage)lbl);
						}else if (lbl instanceof NullSignalMessage) {
							// NOP
						}else{
							LOG.warn("Unknown signal:"+lbl);
						}
					}
				}

			}else if (message==SignalMessage.BEGIN) {
				clearData(clearingDataWhenBeginMessage_);
			}else if (message==SignalMessage.END) {
				LOG.debug("got END message.");
			}else if (message instanceof String) {
				//LOG.debug("string message: "+message);
				String s=(String) message;
				if (s.startsWith(HEADER_PREFIX_IMAGE)) {
					processCoordinatesHeader(s.substring(HEADER_PREFIX_IMAGE.length()));
				}
			}
		}
		
		/**
		 * coordinateファイルの、"#targetImg:"の行を処理します
		 */
		private void processCoordinatesHeader(String param) {
			//
			imagePath_ = param.trim();
			img_ = new Image(getDisplay(), fsp.openInputStream(imagePath_));
//			img_ = new Image(getDisplay(), imagePath_);	
			imgH  = img_.getBounds().height;
			imgW = img_.getBounds().width;

		}
		
		private void processLabelMessage(LabelSignalMessage lbl) {
			//LOG.debug("WaveView: labelSig "+lbl);
			synchronized(labelData_) {
				labelData_.add(lbl);
				requestUpdateTimeRangeAndRedraw();
				//requestRedraw();
			}
		}

		private void processVectorSignalMessage(VectorSignalMessage we) {
			synchronized(coData_) {
				coData_.add(we);
				requestUpdateTimeRangeAndRedraw();
				//requestRedraw();
			}
		}
	};
	
	public static final String HEADER_PREFIX_IMAGE = "#targetImg:";

	void setVectorData(Collection<VectorSignalMessage> waveData) {
		synchronized(coData_) {
			coData_.clear();
			coData_.addAll(waveData);
			requestUpdateTimeRangeAndRedraw();
		}
	}

	void setLabelData(Collection<LabelSignalMessage> labelData) {
		synchronized(labelData_) {
			labelData_.clear();
			labelData_.addAll(labelData);
			requestUpdateTimeRangeAndRedraw();
		}
	}

	public MessageProcessor getInputPort() { return inputPort_; }

	public static final int DATA_BIT_LABEL=2;
	public static final int DATA_BIT_WAVE=1;
	public static final int DATA_BITS_ALL=DATA_BIT_LABEL|DATA_BIT_WAVE;

	private int clearingDataWhenBeginMessage_=DATA_BITS_ALL;

	public void clearData(int dataToClear) {
		if ((dataToClear&DATA_BIT_LABEL)!=0) {
			synchronized (labelData_) {
				labelData_.clear();
			}
		}
		if ((dataToClear&DATA_BIT_WAVE)!=0) {
			synchronized(coData_) {
				coData_.clear();
				//viewTimeMax_=0;
				requestUpdateTimeRangeAndRedraw();
			}
		}
	}


	/*
	private void onInit(IViewSite site) {
	}

	@Override
	public void init(IViewSite site, IMemento memento) throws PartInitException {
		super.init(site, memento);
		onInit(site);
	}

	@Override
	public void init(IViewSite site) throws PartInitException {
		super.init(site);
		onInit(site);
	}
	 */

	public void upScale() {
		setHeightMin(getHeightMin() + (double)getCanvasHeight()*0.25/getViewSize());
		setWidthMin(getWidthMin() + (double)getCanvasWidth()*0.25/getViewSize());
		setViewSize(getViewSize()*2);
		requestRedraw();
	}
	
	public void downScale() {
		setViewSize(getViewSize()/2);
		setHeightMin(getHeightMin() - (double)getCanvasHeight()*0.25/getViewSize());
		setWidthMin(getWidthMin() - (double)getCanvasWidth()*0.25/getViewSize());
		requestRedraw();
	}
	
	public void initializeScale() {
		double magH = (double)getCanvasHeight() / (double)imgH;
		double magW = (double)getCanvasWidth() / (double)imgW;
		
		if (magH < magW) {
			setViewSize(magH);
			setWidthMin(((double)imgW - (double)getCanvasWidth()/magH)/2);
			setHeightMin(0.0);

		} else {
			setViewSize(magW);
			setWidthMin(0.0);
			setHeightMin(((double)imgH - (double)getCanvasHeight()/magW)/2);
		}
		
		requestRedraw();
	}
	
	public int getSignalDataCapacity() {
		return signalDataCapacity_;
	}

	public void setSignalDataCapacity(int signalDataCapacity) {
		signalDataCapacity_ = signalDataCapacity;
	}
	
	public double getViewSize() {
		return viewSize_;
	}
	
	public void setViewSize(double viewSize) {
		viewSize_ = viewSize;
	}

	public double getHeightMin() {
		return heightMin_;
	}

	public void setHeightMin(double heightMin) {
		heightMin_ = heightMin;
	}

	public double getWidthMin() {
		return widthMin_;
	}

	public void setWidthMin(double widthMin) {
		widthMin_ = widthMin;
	}
	
	public boolean isShowScale() {
		return showScale_;
	}

	public void setShowScale(boolean showGraduations) {
		showScale_ = showGraduations;
	}

	public void setTitleName(String s) {
		topLabel_.setText(s);
	}


	public ToolBar getToolBar() {
		return toolBar_;
	}


	public void setFileStreamProvider(FileStreamProvider f) {
		fsp = f;
	}

	public int getClearingDataWhenBeginMessage() {
		return clearingDataWhenBeginMessage_;
	}

	public void setClearingDataWhenBeginMessage(int clearDataWhenBeginMessage) {
		clearingDataWhenBeginMessage_ = clearDataWhenBeginMessage;
	}

}
