ingo@540: package de.intevation.flys.client.client.ui.chart;
ingo@540:
ingo@540: import java.util.ArrayList;
ingo@540: import java.util.List;
ingo@540:
ingo@543: import com.google.gwt.core.client.GWT;
ingo@543:
ingo@540: import com.smartgwt.client.types.Positioning;
ingo@540: import com.smartgwt.client.types.SelectionType;
ingo@543: import com.smartgwt.client.widgets.ImgButton;
ingo@540: import com.smartgwt.client.widgets.Canvas;
ingo@540: import com.smartgwt.client.widgets.events.MouseDownEvent;
ingo@540: import com.smartgwt.client.widgets.events.MouseDownHandler;
ingo@540: import com.smartgwt.client.widgets.events.MouseMoveEvent;
ingo@540: import com.smartgwt.client.widgets.events.MouseMoveHandler;
ingo@546: import com.smartgwt.client.widgets.events.MouseOutEvent;
ingo@546: import com.smartgwt.client.widgets.events.MouseOutHandler;
ingo@540: import com.smartgwt.client.widgets.events.MouseUpEvent;
ingo@540: import com.smartgwt.client.widgets.events.MouseUpHandler;
ingo@540:
ingo@540: import de.intevation.flys.client.client.event.HasZoomHandlers;
ingo@540: import de.intevation.flys.client.client.event.ZoomEvent;
ingo@540: import de.intevation.flys.client.client.event.ZoomHandler;
ingo@540:
ingo@540:
ingo@540: /**
ingo@540: * This control observes that panel retrieved by ChartOutputTab.getChartPanel().
ingo@540: * If activated, a zoombox is drawn. One of the two edges is the position of the
ingo@540: * mouse down event on the observed panel. The other edge is specified by the
ingo@540: * current mouse position. If the mouse up event occurs, start and end point
ingo@540: * relative to the left and upper border of the observed panel is determined and
ingo@540: * a ZoomEvent is fired.
ingo@540: *
ingo@540: * @author Ingo Weinzierl
ingo@540: */
ingo@540: public class ZoomboxControl
ingo@543: extends ImgButton
ingo@546: implements MouseDownHandler, MouseUpHandler, MouseMoveHandler, HasZoomHandlers,
ingo@546: MouseOutHandler
ingo@540: {
ingo@540: protected List handlers;
ingo@540:
ingo@540: protected ChartOutputTab chartTab;
ingo@540:
ingo@540: protected Canvas zoombox;
ingo@540:
ingo@540: protected int[] start;
ingo@540: protected int[] end;
ingo@540:
ingo@540:
ingo@543: public ZoomboxControl(ChartOutputTab chartTab, String imageUrl) {
ingo@543: super();
ingo@540:
ingo@540: this.handlers = new ArrayList();
ingo@540: this.chartTab = chartTab;
ingo@779: this.start = new int[] { -1, -1 };
ingo@540: this.end = new int[2];
ingo@540: this.zoombox = new Canvas();
ingo@540:
ingo@540: initZoombox();
ingo@540:
ingo@543: String baseUrl = GWT.getHostPageBaseURL();
ingo@543: setSrc(baseUrl + imageUrl);
ingo@540: setActionType(SelectionType.CHECKBOX);
ingo@543: setSize(20);
ingo@543: setShowRollOver(false);
ingo@540: setSelected(false);
ingo@540:
ingo@779: Canvas chart = chartTab.getChartPanel();
ingo@779: chart.addMouseDownHandler(this);
ingo@779: chart.addMouseOutHandler(this);
ingo@779: chart.addMouseMoveHandler(this);
ingo@779: chart.addMouseUpHandler(this);
ingo@540: }
ingo@540:
ingo@540:
ingo@540: /**
ingo@540: * Initializes the zoombox that is displayed over the observed area. The
ingo@540: * zoombox has an opaque background. Its height/width and x/y values are
ingo@540: * determined by the start point (mouse down) and the current mouse
ingo@540: * position.
ingo@540: */
ingo@540: protected void initZoombox() {
ingo@779: Canvas chart = chartTab.getChartPanel();
ingo@779: chart.addChild(zoombox);
ingo@779:
ingo@540: zoombox.setPosition(Positioning.ABSOLUTE);
ingo@541: zoombox.setBorder("2px solid black");
ingo@540: zoombox.setOpacity(50);
ingo@779: zoombox.setWidth(1);
ingo@779: zoombox.setHeight(1);
ingo@779: zoombox.setLeft(-10000);
ingo@779: zoombox.setTop(-10000);
ingo@540: }
ingo@540:
ingo@540:
ingo@540: /**
ingo@540: * Registers a new ZoomHandler that wants to listen to ZoomEvents.
ingo@540: *
ingo@540: * @param handler A new ZoomHandler.
ingo@540: */
ingo@540: public void addZoomHandler(ZoomHandler handler) {
ingo@540: if (handler != null) {
ingo@540: handlers.add(handler);
ingo@540: }
ingo@540: }
ingo@540:
ingo@540:
ingo@540: /**
ingo@540: * A mouse down event on the specified area will set the start point for the
ingo@540: * zoombox.
ingo@540: *
ingo@540: * @param event The mouse down event which contains the xy coordinates of
ingo@540: * the observed area.
ingo@540: */
ingo@540: public void onMouseDown(MouseDownEvent event) {
ingo@540: if (!isSelected()) {
ingo@540: return;
ingo@540: }
ingo@540:
ingo@779: start[0] = getRelativeX(event.getX()) - 1;
ingo@779: start[1] = getRelativeY(event.getY()) + 1;
ingo@540:
ingo@540: end[0] = start[0];
ingo@540: end[1] = start[1];
ingo@540: }
ingo@540:
ingo@540:
ingo@540: /**
ingo@540: * A mouse move event on the specified area will set the end point for the
ingo@540: * zoombox. If the end point differs from the start point, an opaque box is
ingo@540: * displayed.
ingo@540: *
ingo@540: * @param event The mouse move event which contains the xy coordinates of
ingo@540: * the observed area.
ingo@540: */
ingo@540: public void onMouseMove(MouseMoveEvent event) {
ingo@779: if (!isSelected() || !isZooming()) {
ingo@540: return;
ingo@540: }
ingo@540:
ingo@779: int x = getRelativeX(event.getX());
ingo@779: int y = getRelativeY(event.getY());
ingo@779:
ingo@779: end[0] = x > start[0] ? x-1 : x+1;
ingo@779: end[1] = y > start[1] ? y-1 : y+1;
ingo@540:
ingo@540: positionZoombox();
ingo@540: }
ingo@540:
ingo@540:
ingo@540: /**
ingo@540: * The mouse up event finalizes the zoom operation. It sets the end point
ingo@540: * for this operation, clears the zoombox and fires a ZoomEvent.
ingo@540: *
ingo@540: * @param event The mouse up event which contains the xy coordinates of the
ingo@540: * observed area.
ingo@540: */
ingo@540: public void onMouseUp(MouseUpEvent event) {
ingo@540: if (!isSelected()) {
ingo@540: return;
ingo@540: }
ingo@540:
ingo@540: end[0] = getRelativeX(event.getX());
ingo@540: end[1] = getRelativeY(event.getY());
ingo@540:
ingo@541: fireZoomEvent();
ingo@541:
ingo@779: reset();
ingo@546: }
ingo@540:
ingo@546:
ingo@546: /**
ingo@546: * The mouse out event is used to cancel an active zoom operation.
ingo@546: *
ingo@546: * @param event The mouse out event.
ingo@546: */
ingo@546: public void onMouseOut(MouseOutEvent event) {
ingo@546: if (!isSelected() || !isMouseOut(event.getX(), event.getY())) {
ingo@546: return;
ingo@546: }
ingo@546:
ingo@779: reset();
ingo@546: }
ingo@546:
ingo@546:
ingo@546: /**
ingo@546: * Returns the chart panel.
ingo@546: *
ingo@546: * @return the chart panel.
ingo@546: */
ingo@546: protected Canvas getChartPanel() {
ingo@546: return chartTab.getChartPanel();
ingo@546: }
ingo@546:
ingo@546:
ingo@546: /**
ingo@546: * This method is required to check manually if the mouse pointer really
ingo@546: * moves out the chart area. The MouseOutEvent is also fired if the mouse
ingo@546: * goes down which doesn't seem to be correct. So, we gonna check this
ingo@546: * manually.
ingo@546: *
ingo@546: * @param x The x coordinate.
ingo@546: * @param y The y coordinate.
ingo@546: *
ingo@546: * @return true, if the mouse is really out of the chart area, otherwise
ingo@546: * false.
ingo@546: */
ingo@546: protected boolean isMouseOut(int x, int y) {
ingo@546: Canvas chart = getChartPanel();
ingo@546:
ingo@546: int left = chart.getPageLeft();
ingo@546: int right = chart.getPageRight();
ingo@546: int top = chart.getPageTop();
ingo@546: int bottom = chart.getPageBottom();
ingo@546:
ingo@546: if (x <= left || x >= right || y <= top || y >= bottom) {
ingo@546: return true;
ingo@546: }
ingo@546:
ingo@546: return false;
ingo@540: }
ingo@540:
ingo@540:
ingo@540: /**
ingo@779: * Returns true, if a zoom action is in process.
ingo@779: *
ingo@779: * @return true, if a zoom action is in process.
ingo@779: */
ingo@779: public boolean isZooming() {
ingo@779: return start[0] > 0 && start[1] > 0;
ingo@779: }
ingo@779:
ingo@779:
ingo@779: /**
ingo@540: * Returns the X coordinate relative to the left border.
ingo@540: *
ingo@540: * @param x The X coordinate relative to the window.
ingo@540: *
ingo@540: * @return the X coordinate relative to the left border.
ingo@540: */
ingo@540: protected int getRelativeX(int x) {
ingo@540: return x - chartTab.getChartPanel().getPageLeft();
ingo@540: }
ingo@540:
ingo@540:
ingo@540: /**
ingo@540: * Returns the Y coordinate relative to the top border.
ingo@540: *
ingo@540: * @param y The Y coordinate relative to the window.
ingo@540: *
ingo@540: * @return the Y coordinate relative to the top border.
ingo@540: */
ingo@540: protected int getRelativeY(int y) {
ingo@540: return y - chartTab.getChartPanel().getPageTop();
ingo@540: }
ingo@540:
ingo@540:
ingo@540: /**
ingo@540: * Returns min and max x/y values based on the stored values in start
ingo@540: * and end.
ingo@540: *
ingo@540: * @return an int[] as follows: [xmin, ymin, xmax, ymax].
ingo@540: */
ingo@540: protected int[] orderPositions() {
ingo@540: int xmin = start[0] < end[0] ? start[0] : end[0];
ingo@540: int ymin = start[1] < end[1] ? start[1] : end[1];
ingo@540:
ingo@540: int xmax = start[0] >= end[0] ? start[0] : end[0];
ingo@540: int ymax = start[1] >= end[1] ? start[1] : end[1];
ingo@540:
ingo@540: return new int[] { xmin, ymin, xmax, ymax };
ingo@540: }
ingo@540:
ingo@540:
ingo@540: /**
ingo@540: * Sets the width, height, x and y values of the zoombox.
ingo@540: */
ingo@540: protected void positionZoombox() {
ingo@540: int[] values = orderPositions();
ingo@540:
ingo@540: zoombox.setLeft(values[0]);
ingo@540: zoombox.setTop(values[1]);
ingo@540: zoombox.setWidth(values[2] - values[0]);
ingo@540: zoombox.setHeight(values[3] - values[1]);
ingo@540: }
ingo@540:
ingo@540:
ingo@540: /**
ingo@540: * Clears the zoombox (set position and size to null).
ingo@540: */
ingo@540: protected void clearZoombox() {
ingo@779: zoombox.setLeft(-10000);
ingo@779: zoombox.setTop(-10000);
ingo@779: zoombox.setWidth(1);
ingo@779: zoombox.setHeight(1);
ingo@779: }
ingo@546:
ingo@779:
ingo@779: /**
ingo@779: * Resets the zoom control (start point and zoombox).
ingo@779: */
ingo@779: protected void reset() {
ingo@779: start[0] = -1;
ingo@779: start[1] = -1;
ingo@779:
ingo@779: clearZoombox();
ingo@540: }
ingo@540:
ingo@540:
ingo@540: /**
ingo@540: * Fires a ZoomEvent to all registered listeners.
ingo@540: */
ingo@540: protected void fireZoomEvent() {
ingo@540: int[] pos = orderPositions();
ingo@540:
ingo@540: ZoomEvent event = new ZoomEvent(pos[0], pos[1], pos[2], pos[3]);
ingo@540:
ingo@540: for (ZoomHandler handler: handlers) {
ingo@540: handler.onZoom(event);
ingo@540: }
ingo@540: }
ingo@540: }
ingo@540: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :