<commit_before>/*
 * This is part of Geomajas, a GIS framework, http://www.geomajas.org/.
 *
 * Copyright 2008-2014 Geosparc nv, http://www.geosparc.com/, Belgium.
 *
 * The program is available in open source according to the GNU Affero
 * General Public License. All contributions in this program are covered
 * by the Geomajas Contributors License Agreement. For full licensing
 * details, see LICENSE.txt in the project root.
 */

package org.geomajas.gwt2.client.widget.control.scalebar;

import org.geomajas.annotation.Api;
import org.geomajas.gwt2.client.event.ViewPortChangedEvent;
import org.geomajas.gwt2.client.event.ViewPortChangedHandler;
import org.geomajas.gwt2.client.map.MapPresenter;
import org.geomajas.gwt2.client.widget.AbstractMapWidget;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Style;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Widget;
import org.geomajas.annotation.Api;
import org.geomajas.gwt2.client.event.ViewPortChangedEvent;
import org.geomajas.gwt2.client.event.ViewPortChangedHandler;
import org.geomajas.gwt2.client.map.MapPresenter;
import org.geomajas.gwt2.client.widget.AbstractMapWidget;

/**
 * Map widget that shows a scale bar on the map. This widget is meant to be added to the map's widget pane (see {@link
 * MapPresenter#getWidgetPane()}).
 *
 * @author <NAME>
 * @since 2.0.0
 */
@Api(allMethods = true)
public class Scalebar extends AbstractMapWidget {

	/**
	 * Unit type to use on the scale bar.
	 *
	 * @author <NAME>
	 */
	public enum UnitType {
		/**
		 * Metric Units. Meters(m) -- Kilometers(km)
		 */
		METRIC,

		/**
		 * English Units. Yards(yd) -- Miles(mi)
		 */
		ENGLISH,

		/**
		 * English Units. Feet(ft) -- Miles(mi)
		 */
		ENGLISH_FOOT,

		/**
		 * Coordinate Reference System Units. Units(u)
		 */
		CRS
	}

	/**
	 * UI binder definition for the {@link Scalebar} widget.
	 *
	 * @author <NAME>
	 */
	interface ScalebarUiBinder extends UiBinder<Widget, Scalebar> {
	}

	private static final ScalebarUiBinder UI_BINDER = GWT.create(ScalebarUiBinder.class);

	private static final double METERS_IN_MILE = 1609.344d;

	private static final double METERS_IN_YARD = 0.9144d;

	private static final double FEET_IN_METER = 3.2808399d;

	private static final int MAX_SIZE_IN_PIXELS = 125;

	private int[] lengths = new int[] { 1, 2, 5, 10, 25, 50, 100, 250, 500, 750, 1000, 2000, 5000, 10000, 25000, 50000,
			75000, 100000, 250000, 500000, 750000, 1000000, 2000000, 5000000, 10000000 };

	// position in lengths array up to where to test for yards (larger values is for miles)
	private static final int YARD_STARTING_POINT = 11;

	private UnitType unitType = UnitType.METRIC;

	// -- for internal use, holds the last calculated best value
	private int widthInUnits;

	// -- for internal use, holds the last calculated best value
	private int widthInPixels;

	// -- for internal use, for UnitType.ENGLISH only
	private boolean widthInUnitsIsMiles;

	@UiField
	protected DivElement scaleBarElement;

	// ------------------------------------------------------------------------
	// Constructors:
	// ------------------------------------------------------------------------

	/**
	 * Create a new instance for the given map.
	 *
	 * @param mapPresenter The map presenter.
	 */
	public Scalebar(MapPresenter mapPresenter) {
		this(mapPresenter, GeomajasImpl.getClientBundleFactory().createScalebarResource());
	}

	/**
	 * Create a new instance for the given map.
	 *
	 * @param mapPresenter The map presenter.
	 * @param resource     Custom resource bundle in case you want to provide your own style for this widget.
	 */
	public Scalebar(MapPresenter mapPresenter, ScalebarResource resource) {
		super(mapPresenter);
		resource.css().ensureInjected();

		mapPresenter.getEventBus().addViewPortChangedHandler(new ViewPortChangedHandler() {

			public void onViewPortChanged(ViewPortChangedEvent event) {
				redrawScale();
			}
		});

		initWidget(UI_BINDER.createAndBindUi(this));
		redrawScale();
	}

	// ------------------------------------------------------------------------
	// Public methods:
	// ------------------------------------------------------------------------

	/**
	 * Get the unit type used in this widget.
	 *
	 * @return The unit type in which scales are displayed.
	 */
	public UnitType getUnitType() {
		return unitType;
	}

	/**
	 * Set the unit type in which scales are displayed.
	 *
	 * @param unitType The new unit type.
	 */
	public void setUnitType(UnitType unitType) {
		this.unitType = unitType;
	}

	// ------------------------------------------------------------------------
	// Private methods:
	// ------------------------------------------------------------------------

	private void redrawScale() {
		calculateBestFit(1 / mapPresenter.getViewPort().getResolution());
		scaleBarElement.setInnerText(formatUnits(widthInUnits));
		scaleBarElement.getStyle().setWidth(widthInPixels, Style.Unit.PX);
		getElement().getStyle().setWidth(widthInPixels + 10, Style.Unit.PX);
	}

	/**
	 * Find the rounded value (from the lengths array) which fits the closest into the maxSizeInPixels for the given
	 * scale.
	 *
	 * @param scale
	 * @return closest fit in units (will be miles or yards for English, m for metric, unit for CRS)
	 */
	private void calculateBestFit(double scale) {
		double unitLength = mapPresenter.getConfiguration().getUnitLength();
		int len = 0;
		long px = 0;
		if (UnitType.ENGLISH.equals(unitType)) {
			// try miles.
			for (int i = lengths.length - 1; i > -1; i--) {
				len = this.lengths[i];
				px = Math.round((len * scale / unitLength) * METERS_IN_MILE);
				if (px < MAX_SIZE_IN_PIXELS) {
					break;
				}
			}
			// try yards.
			if (px > MAX_SIZE_IN_PIXELS) {
				for (int i = YARD_STARTING_POINT; i > -1; i--) {
					len = this.lengths[i];
					px = Math.round((len * scale / unitLength) * METERS_IN_YARD);
					if (px < MAX_SIZE_IN_PIXELS) {
						break;
					}
				}
				widthInUnitsIsMiles = false;
			} else {
				widthInUnitsIsMiles = true;
			}
		} else if (UnitType.ENGLISH_FOOT.equals(unitType)) {
			// try miles.
			for (int i = lengths.length - 1; i > -1; i--) {
				len = this.lengths[i];
				px = Math.round((len * scale / unitLength) * METERS_IN_MILE);
				if (px < MAX_SIZE_IN_PIXELS) {
					break;
				}
			}
			// try feet.
			if (px > MAX_SIZE_IN_PIXELS) {
				for (int i = YARD_STARTING_POINT; i > -1; i--) {
					len = this.lengths[i];
					px = Math.round((len * scale / unitLength) / FEET_IN_METER);
					if (px < MAX_SIZE_IN_PIXELS) {
						break;
					}
				}
				widthInUnitsIsMiles = false;
			} else {
				widthInUnitsIsMiles = true;
			}
		} else {
			for (int i = lengths.length - 1; i > -1; i--) {
				len = this.lengths[i];
				px = Math.round(len * scale / unitLength);
				if (px < MAX_SIZE_IN_PIXELS) {
					break;
				}
			}
		}

		widthInUnits = len;
		widthInPixels = (int) px;
	}

	/**
	 * format to human readable string converting to unit type.
	 *
	 * @param units
	 * @return
	 */
	private String formatUnits(int units) {
		switch (unitType) {
			case ENGLISH:
				return NumberFormat.getDecimalFormat().format(units) + (widthInUnitsIsMiles ? " mi" : " yd");
			case ENGLISH_FOOT:
				return NumberFormat.getDecimalFormat().format(units) + (widthInUnitsIsMiles ? " mi" : " ft");
			case METRIC:
				if (units < 10000) {
					return NumberFormat.getDecimalFormat().format(units) + " m";
				} else {
					return NumberFormat.getDecimalFormat().format((double) units / 1000) + " km";
				}

			case CRS:
				return NumberFormat.getDecimalFormat().format(units) + " u";

			default:
				return "??";
		}
	}
}<commit_msg>PURE-236: Make sure people can influence the default styles of all Geomajas widgets.<commit_after>/*
 * This is part of Geomajas, a GIS framework, http://www.geomajas.org/.
 *
 * Copyright 2008-2014 Geosparc nv, http://www.geosparc.com/, Belgium.
 *
 * The program is available in open source according to the GNU Affero
 * General Public License. All contributions in this program are covered
 * by the Geomajas Contributors License Agreement. For full licensing
 * details, see LICENSE.txt in the project root.
 */

package org.geomajas.gwt2.client.widget.control.scalebar;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Style;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Widget;
import org.geomajas.annotation.Api;
import org.geomajas.gwt2.client.GeomajasImpl;
import org.geomajas.gwt2.client.event.ViewPortChangedEvent;
import org.geomajas.gwt2.client.event.ViewPortChangedHandler;
import org.geomajas.gwt2.client.map.MapPresenter;
import org.geomajas.gwt2.client.widget.AbstractMapWidget;

/**
 * Map widget that shows a scale bar on the map. This widget is meant to be added to the map's widget pane (see {@link
 * MapPresenter#getWidgetPane()}).
 *
 * @author <NAME>
 * @since 2.0.0
 */
@Api(allMethods = true)
public class Scalebar extends AbstractMapWidget {

	/**
	 * Unit type to use on the scale bar.
	 *
	 * @author <NAME>
	 */
	public enum UnitType {
		/**
		 * Metric Units. Meters(m) -- Kilometers(km)
		 */
		METRIC,

		/**
		 * English Units. Yards(yd) -- Miles(mi)
		 */
		ENGLISH,

		/**
		 * English Units. Feet(ft) -- Miles(mi)
		 */
		ENGLISH_FOOT,

		/**
		 * Coordinate Reference System Units. Units(u)
		 */
		CRS
	}

	/**
	 * UI binder definition for the {@link Scalebar} widget.
	 *
	 * @author <NAME>
	 */
	interface ScalebarUiBinder extends UiBinder<Widget, Scalebar> {
	}

	private static final ScalebarUiBinder UI_BINDER = GWT.create(ScalebarUiBinder.class);

	private static final double METERS_IN_MILE = 1609.344d;

	private static final double METERS_IN_YARD = 0.9144d;

	private static final double FEET_IN_METER = 3.2808399d;

	private static final int MAX_SIZE_IN_PIXELS = 125;

	private int[] lengths = new int[] { 1, 2, 5, 10, 25, 50, 100, 250, 500, 750, 1000, 2000, 5000, 10000, 25000, 50000,
			75000, 100000, 250000, 500000, 750000, 1000000, 2000000, 5000000, 10000000 };

	// position in lengths array up to where to test for yards (larger values is for miles)
	private static final int YARD_STARTING_POINT = 11;

	private UnitType unitType = UnitType.METRIC;

	// -- for internal use, holds the last calculated best value
	private int widthInUnits;

	// -- for internal use, holds the last calculated best value
	private int widthInPixels;

	// -- for internal use, for UnitType.ENGLISH only
	private boolean widthInUnitsIsMiles;

	@UiField
	protected DivElement scaleBarElement;

	// ------------------------------------------------------------------------
	// Constructors:
	// ------------------------------------------------------------------------

	/**
	 * Create a new instance for the given map.
	 *
	 * @param mapPresenter The map presenter.
	 */
	public Scalebar(MapPresenter mapPresenter) {
		this(mapPresenter, GeomajasImpl.getClientBundleFactory().createScalebarResource());
	}

	/**
	 * Create a new instance for the given map.
	 *
	 * @param mapPresenter The map presenter.
	 * @param resource     Custom resource bundle in case you want to provide your own style for this widget.
	 */
	public Scalebar(MapPresenter mapPresenter, ScalebarResource resource) {
		super(mapPresenter);
		resource.css().ensureInjected();

		mapPresenter.getEventBus().addViewPortChangedHandler(new ViewPortChangedHandler() {

			public void onViewPortChanged(ViewPortChangedEvent event) {
				redrawScale();
			}
		});

		initWidget(UI_BINDER.createAndBindUi(this));
		redrawScale();
	}

	// ------------------------------------------------------------------------
	// Public methods:
	// ------------------------------------------------------------------------

	/**
	 * Get the unit type used in this widget.
	 *
	 * @return The unit type in which scales are displayed.
	 */
	public UnitType getUnitType() {
		return unitType;
	}

	/**
	 * Set the unit type in which scales are displayed.
	 *
	 * @param unitType The new unit type.
	 */
	public void setUnitType(UnitType unitType) {
		this.unitType = unitType;
	}

	// ------------------------------------------------------------------------
	// Private methods:
	// ------------------------------------------------------------------------

	private void redrawScale() {
		calculateBestFit(1 / mapPresenter.getViewPort().getResolution());
		scaleBarElement.setInnerText(formatUnits(widthInUnits));
		scaleBarElement.getStyle().setWidth(widthInPixels, Style.Unit.PX);
		getElement().getStyle().setWidth(widthInPixels + 10, Style.Unit.PX);
	}

	/**
	 * Find the rounded value (from the lengths array) which fits the closest into the maxSizeInPixels for the given
	 * scale.
	 *
	 * @param scale
	 * @return closest fit in units (will be miles or yards for English, m for metric, unit for CRS)
	 */
	private void calculateBestFit(double scale) {
		double unitLength = mapPresenter.getConfiguration().getUnitLength();
		int len = 0;
		long px = 0;
		if (UnitType.ENGLISH.equals(unitType)) {
			// try miles.
			for (int i = lengths.length - 1; i > -1; i--) {
				len = this.lengths[i];
				px = Math.round((len * scale / unitLength) * METERS_IN_MILE);
				if (px < MAX_SIZE_IN_PIXELS) {
					break;
				}
			}
			// try yards.
			if (px > MAX_SIZE_IN_PIXELS) {
				for (int i = YARD_STARTING_POINT; i > -1; i--) {
					len = this.lengths[i];
					px = Math.round((len * scale / unitLength) * METERS_IN_YARD);
					if (px < MAX_SIZE_IN_PIXELS) {
						break;
					}
				}
				widthInUnitsIsMiles = false;
			} else {
				widthInUnitsIsMiles = true;
			}
		} else if (UnitType.ENGLISH_FOOT.equals(unitType)) {
			// try miles.
			for (int i = lengths.length - 1; i > -1; i--) {
				len = this.lengths[i];
				px = Math.round((len * scale / unitLength) * METERS_IN_MILE);
				if (px < MAX_SIZE_IN_PIXELS) {
					break;
				}
			}
			// try feet.
			if (px > MAX_SIZE_IN_PIXELS) {
				for (int i = YARD_STARTING_POINT; i > -1; i--) {
					len = this.lengths[i];
					px = Math.round((len * scale / unitLength) / FEET_IN_METER);
					if (px < MAX_SIZE_IN_PIXELS) {
						break;
					}
				}
				widthInUnitsIsMiles = false;
			} else {
				widthInUnitsIsMiles = true;
			}
		} else {
			for (int i = lengths.length - 1; i > -1; i--) {
				len = this.lengths[i];
				px = Math.round(len * scale / unitLength);
				if (px < MAX_SIZE_IN_PIXELS) {
					break;
				}
			}
		}

		widthInUnits = len;
		widthInPixels = (int) px;
	}

	/**
	 * format to human readable string converting to unit type.
	 *
	 * @param units
	 * @return
	 */
	private String formatUnits(int units) {
		switch (unitType) {
			case ENGLISH:
				return NumberFormat.getDecimalFormat().format(units) + (widthInUnitsIsMiles ? " mi" : " yd");
			case ENGLISH_FOOT:
				return NumberFormat.getDecimalFormat().format(units) + (widthInUnitsIsMiles ? " mi" : " ft");
			case METRIC:
				if (units < 10000) {
					return NumberFormat.getDecimalFormat().format(units) + " m";
				} else {
					return NumberFormat.getDecimalFormat().format((double) units / 1000) + " km";
				}

			case CRS:
				return NumberFormat.getDecimalFormat().format(units) + " u";

			default:
				return "??";
		}
	}
}
{'fraction_non_alphanumeric': 0.168566986265872, 'fraction_numerical': 0.022674267945063487, 'mean_word_length': 2.6025670945157526, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '833430', 'n_tokens_mistral': 5882, 'n_tokens_neox': 4934, 'n_words': 1310}