/******************************************************************************* * Copyright 2013 Geoscience Australia * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package au.gov.ga.earthsci.application.parts.exaggeration; import javax.inject.Inject; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; 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.graphics.GC; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Scale; /** * Part that allows control of the globe's vertical exaggeration. * * @author Michael de Hoog (michael.dehoog@ga.gov.au) */ public class ExaggerationPart { private final static int SCALE_HEIGHT = 22; private final static int TICK_HEIGHT = 5; private final static int SCALE_MARGIN = 14; private final static int INCREMENTS_PER_POWER = 1000; //min and max must be powers of 10: private final static double SCALE_MIN = 0.1; private final static double SCALE_MAX = 100; private final static double SCALE_LOG_MIN = Math.log10(SCALE_MIN); private final static double SCALE_LOG_MAX = Math.log10(SCALE_MAX); @Inject public void init(Composite parent) { /*Composite child = new Composite(parent, SWT.NONE); child.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_CYAN));*/ LogScale logScale = new LogScale(parent, SWT.NONE); logScale.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_CYAN)); } private class LogScale extends Composite { private final Scale scale; public LogScale(Composite parent, int style) { super(parent, style); setLayout(new GridLayout()); final Composite scaleWrapper = new Composite(this, SWT.NONE); GridData gridData = new GridData(); gridData.heightHint = SCALE_HEIGHT; gridData.grabExcessHorizontalSpace = true; gridData.horizontalAlignment = SWT.FILL; scaleWrapper.setLayoutData(gridData); scale = new Scale(scaleWrapper, SWT.HORIZONTAL); scaleWrapper.addControlListener(new ControlAdapter() { @Override public void controlResized(ControlEvent e) { scale.setSize(scale.computeSize(scaleWrapper.getSize().x, SWT.DEFAULT)); scale.setLocation(0, (scaleWrapper.getSize().y - scale.getSize().y) / 2); } }); scale.setMinimum(0); scale.setMaximum((int) Math.round(SCALE_LOG_MAX - SCALE_LOG_MIN) * INCREMENTS_PER_POWER); setValue(1); scale.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { System.out.println(getValue()); } }); LogTicks ticks = new LogTicks(this, SWT.NONE); gridData = new GridData(); gridData.grabExcessHorizontalSpace = true; gridData.horizontalAlignment = SWT.FILL; ticks.setLayoutData(gridData); } public double getValue() { if (scale.getSelection() == 0) { return 0; } double log10 = scale.getSelection() / (double) INCREMENTS_PER_POWER + SCALE_LOG_MIN; return Math.pow(10, log10); } public void setValue(double value) { if (value <= 0) { scale.setSelection(0); return; } double log10 = Math.log10(value); int selection = (int) Math.round((log10 - SCALE_LOG_MIN) * INCREMENTS_PER_POWER); scale.setSelection(selection); } } private class LogTicks extends Canvas { private int height = TICK_HEIGHT; public LogTicks(Composite parent, int style) { super(parent, style); addDisposeListener(new DisposeListener() { @Override public void widgetDisposed(DisposeEvent e) { LogTicks.this.widgetDisposed(e); } }); addPaintListener(new PaintListener() { @Override public void paintControl(PaintEvent e) { LogTicks.this.paintControl(e); } }); } protected void paintControl(PaintEvent e) { GC gc = e.gc; double value = SCALE_MIN; while (value <= SCALE_MAX) { double log10 = Math.log10(value); double percent = (log10 - SCALE_LOG_MIN) / (SCALE_LOG_MAX - SCALE_LOG_MIN); double increment = Math.pow(10, Math.floor(log10 + Double.MIN_VALUE)); long count = Math.round(value / increment); int x = (int) Math.round(percent * (getSize().x + 1 - SCALE_MARGIN * 2) + SCALE_MARGIN - 1); gc.drawLine(x, 0, x, TICK_HEIGHT); if (count == 1) { String label = Long.toString(Math.round(value)); Point labelSize = gc.textExtent(label); gc.drawString(label, x - labelSize.x / 2, TICK_HEIGHT); height = TICK_HEIGHT + labelSize.y; } value = (count + 1) * increment; } } protected void widgetDisposed(DisposeEvent e) { } @Override public Point computeSize(int wHint, int hHint, boolean changed) { return super.computeSize(wHint, height, changed); } } }