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@540: import com.smartgwt.client.types.Positioning; ingo@540: import com.smartgwt.client.types.SelectionType; ingo@540: import com.smartgwt.client.widgets.Button; 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@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@540: extends Button ingo@540: implements MouseDownHandler, MouseUpHandler, MouseMoveHandler, HasZoomHandlers 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@540: public ZoomboxControl(ChartOutputTab chartTab) { ingo@540: super("Zoombox"); ingo@540: ingo@540: this.handlers = new ArrayList(); ingo@540: this.chartTab = chartTab; ingo@540: this.start = new int[2]; ingo@540: this.end = new int[2]; ingo@540: this.zoombox = new Canvas(); ingo@540: ingo@540: initZoombox(); ingo@540: ingo@540: setActionType(SelectionType.CHECKBOX); ingo@540: setSelected(false); ingo@540: ingo@540: chartTab.getChartPanel().addMouseDownHandler(this); ingo@540: chartTab.getChartPanel().addMouseMoveHandler(this); ingo@540: chartTab.getChartPanel().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@540: zoombox.setPosition(Positioning.ABSOLUTE); ingo@541: zoombox.setBorder("2px solid black"); ingo@540: zoombox.setOpacity(50); ingo@540: zoombox.setWidth(0); ingo@540: zoombox.setHeight(0); 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@540: start[0] = getRelativeX(event.getX()); ingo@540: start[1] = getRelativeY(event.getY()); ingo@540: ingo@540: end[0] = start[0]; ingo@540: end[1] = start[1]; ingo@540: ingo@540: chartTab.getChartPanel().addChild(zoombox); ingo@540: ingo@540: positionZoombox(); 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@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@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@540: clearZoombox(); ingo@540: ingo@540: chartTab.getChartPanel().removeChild(zoombox); ingo@540: } ingo@540: ingo@540: ingo@540: /** 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@540: zoombox.setLeft(0); ingo@540: zoombox.setTop(0); ingo@540: zoombox.setWidth(0); ingo@540: zoombox.setHeight(0); 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 :