using System; using System.Windows.Forms; using System.Drawing; using Imsl.Chart2D; public class SampleZoom : FrameChart { private Panel panel; private AxisXY axis; private int xFirst, yFirst; private int xLast, yLast; private System.Collections.Stack stack; private MouseEventHandler mouseMoveHandler; public SampleZoom() { panel = this.Panel; Chart chart = this.Chart; axis = new AxisXY(chart); int n = 1000; double[] x = new double[n]; double[] y = new double[n]; Random ran = new Random(); for (int k = 0; k < n; k++) { x[k] = 10.0 * ran.NextDouble(); y[k] = 10.0 * ran.NextDouble(); } Data data = new Data(axis, x, y); data.DataType = Data.DATA_TYPE_MARKER; // add menu "Zoom" menu MenuItem menuZoom = new MenuItem(); menuZoom.Text = "&Zoom"; menuZoom.Shortcut = Shortcut.CtrlZ; AddMenuItem(menuZoom, "Out", Shortcut.CtrlO); AddMenuItem(menuZoom, "Restore", Shortcut.CtrlR); this.Menu.MenuItems.Add(menuZoom); // save x-axis and y-axis Window attributes on this stack. // they are used to zoom out one level. stack = new System.Collections.Stack(); // listen for mouse press events panel.MouseDown += new MouseEventHandler(Panel_MouseDown); panel.MouseUp += new MouseEventHandler(Panel_MouseUp); mouseMoveHandler = new MouseEventHandler(panel_MouseMove); } // Add a menu item private void AddMenuItem(MenuItem menuZoom, string title, Shortcut sc) { MenuItem menuItem = new MenuItem(title); menuItem.Text = title; menuItem.Shortcut = sc; menuZoom.MenuItems.Add(menuItem); menuItem.Click += new EventHandler(menuItem_Click); } // A mouse press starts the zoom // Record location of this point and listen for drag (motion) events. void Panel_MouseDown(object sender, MouseEventArgs e) { xFirst = xLast = e.X; yFirst = yLast = e.Y; panel.MouseMove += mouseMoveHandler; } // Releasing the mouse button ends the zoom // Stop listening for move events and update the Window attributes void Panel_MouseUp(object sender, MouseEventArgs e) { panel.MouseMove -= mouseMoveHandler; // ignore degenerate zooms if (xFirst == xLast || yFirst == yLast) { Refresh(); return; } // get window and convert to user coordinates double[] windowX = (double[])axis.AxisX.GetWindow(); double[] windowY = (double[])axis.AxisY.GetWindow(); // save the windows on the stack (for zoom out option) stack.Push(windowX); stack.Push(windowY); // get user coordinate of left-upper corner of the box // limit it to stay inside current window double[] boxLU = new double[2]; int x = Math.Min(xFirst, xLast); int y = Math.Min(yFirst, yLast); axis.MapDeviceToUser(x, y, boxLU); // get user coordinate of right-lower corner of the box // limit it to stay inside current window double[] boxRL = new double[2]; x = Math.Max(xFirst, xLast); y = Math.Max(yFirst, yLast); axis.MapDeviceToUser(x, y, boxRL); // set axis window to range of rubber-band box // and disable autoscale to force use of window settings axis.AutoscaleInput = ChartNode.AUTOSCALE_OFF; double xa = Math.Max(windowX[0], boxLU[0]); double xb = Math.Min(windowX[1], boxRL[0]); double ya = Math.Max(windowY[0], boxRL[1]); double yb = Math.Min(windowY[1], boxLU[1]); axis.AxisX.SetWindow(xa, xb); axis.AxisY.SetWindow(ya, yb); // force redraw of the chart Refresh(); } // Moving the mouse after a click continues the zoom. // Erase the old rubber band box and draw a new one // Also keep track of the location of this event void panel_MouseMove(object sender, MouseEventArgs e) { // erase previous rectangle Graphics g = panel.CreateGraphics(); DrawBox(g, Color.White); // draw new rectangle xLast = e.X; yLast = e.Y; DrawBox(g, Color.Red); } // Draw a box with (xFirst, yFirst) and (xLast, yLast) as its corners private void DrawBox(Graphics g, Color color) { int x = Math.Min(xFirst, xLast); int y = Math.Min(yFirst, yLast); int w = Math.Abs(xLast - xFirst); int h = Math.Abs(yLast - yFirst); g.DrawRectangle(new Pen(color), x, y, w, h); } void menuItem_Click(object sender, EventArgs e) { string cmd = ((MenuItem)sender).Text; if (cmd.Equals("Out")) { try { // zoom out by restoring window settings from the stack axis.AxisY.SetWindow((double[])stack.Pop()); axis.AxisX.SetWindow((double[])stack.Pop()); } catch (System.InvalidOperationException) { // no more levels to zoom out // restore original setting by turning on autoscale axis.AutoscaleInput = ChartNode.AUTOSCALE_DATA; } } else if (cmd.Equals("Restore")) { // restore original setting by turning on autoscale an empty stack axis.AutoscaleInput = ChartNode.AUTOSCALE_DATA; stack.Clear(); } // force redraw of the chart Refresh(); } public static void Main(string[] argv) { System.Windows.Forms.Application.Run(new SampleZoom()); } }