Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

WaveForm WebGraph Interaction

Solved!
Go to solution

My goal is to create a WaveForm graph with the following criteria.

  1. Click/double-click on graph to draw cursor at the nearest point.
  2. Draw a box to zoom in.
  3. Provide some way to zoom back out.

With the code below, I can double-click to draw cursor at the nearest point and draw a box to zoom in.  However, I can't figure out how to zoom out.

 

What am I doing wrong?

 

(Measurement Studio 8.5 & Visual Studio 2008)

 

 

Imports NationalInstruments
Imports NationalInstruments.UI
Imports System.Drawing

Partial Public Class PlotData
Inherits System.Web.UI.Page

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then 'generate initial random waveform
myGraph.PlotY(GenerateData(1000))
End If
End Sub

Protected Sub myGraph_PlotAreaClick(ByVal sender As Object, ByVal e As NationalInstruments.UI.ClickEventArgs) Handles myGraph.PlotAreaClick
Dim plotX As Double, plotY As Double

InverseMap(myGraph, e.X, e.Y, plotX, plotY)
myGraph.Cursors(0).MoveCursor(plotX, plotY)

'Show click and plot coordinates
cursor_lbl.Text = "X: " & e.X & " Y: " & e.Y & " pX: " & plotX & " pY: " & plotY
End Sub

Private Shared Function GenerateData(ByVal dataLength As Integer) As Double()

Dim data(dataLength) As Double
Dim rnd As New Random()

For i As Integer = 0 To dataLength - 1
data(i) = rnd.NextDouble() * Math.Sin((i / 3.15))
Next

Return data
End Function

Private Shared Sub InverseMap(ByVal graph As NationalInstruments.UI.WebForms.WaveformGraph, ByVal xClick As Integer, ByVal yClick As Integer, ByRef xPlot As Double, ByRef yPlot As Double)
Dim xMin As Double, xMax As Double
Dim yMin As Double, yMax As Double
Dim plotLeft As Double, plotRight As Double
Dim plotTop As Double, plotBottom As Double

xMin = graph.XAxes(0).Range.Minimum
xMax = graph.XAxes(0).Range.Maximum
yMin = graph.YAxes(0).Range.Minimum
yMax = graph.YAxes(0).Range.Maximum

With graph.PlotAreaBounds
plotLeft = .Left
plotRight = .Right
plotTop = .Top
plotBottom = .Bottom
End With

xPlot = ((xMax - xMin) * ((xClick - plotLeft) / (plotRight - plotLeft))) + xMin
yPlot = ((yMax - yMin) * ((plotBottom - yClick) / (plotBottom - plotTop))) + yMin

End Sub
End Class

 

<ni:WaveformGraph runat="server" ID="myGraph" Width="1000px" Height="500px"
InteractionMode="ZoomX, ZoomY, PlotAreaClick">
<XAxes><ni:XAxis Mode="Fixed" Range="400, 600"/></XAxes>
<YAxes><ni:YAxis/></YAxes>

<Cursors><ni:XYCursor Plot="Plots[0]" /></Cursors>

<Plots><ni:WaveformPlot /></Plots>

</ni:WaveformGraph>

 

 

 

 

0 Kudos
Message 1 of 3
(3,858 Views)
Solution
Accepted by topic author CodeSDz

Hi Steven,

 

The solution I can think of is to use a special key (say Control key) along with a mouse click to zoom out. This will need quite a bit of work on your part.

 

The plot are click event does not provide info about if there was a key press. In order to do this, you will need to manually pass some information from client side to the server side that you had pressed the control key while you clicked. This can be done using a HTML hidden field.

 

How to pass the control key pressed info from client to server?

1) Add a hidden field (say with id and name attributes set to 'ControlKeyPressed') inside the form that is rendered by default in the .aspx file.

2) At the end of the form, Register the key down and key up events on the document.

3) In the javascript event handlers, when the control key is pressed, set the hidden field's value as 'Y', in all other cases, the hidden field's value will be set to 'N'.

 

 

The .aspx code would look something like,

 

 


<form id="form1" runat="server">

 

 

<!-- IMPORTANT: The hidden field that you would need to pass data to server -->

<input type ="hidden" id="ControlKeyPressed" name="ControlKeyPressed" value="" />

 

 

<div>
<ni:WaveformGraph ID="WaveformGraph1" runat="server"
InteractionMode="ZoomX, ZoomY, PlotAreaClick"
onplotareaclick="WaveformGraph1_PlotAreaClick">
<XAxes>
<ni:XAxis>
</ni:XAxis>
</XAxes>
<Plots>
<ni:WaveformPlot XAxis="XAxes[0]" YAxis="YAxes[0]" />
</Plots>
<YAxes>
<ni:YAxis>
</ni:YAxis>
</YAxes>
</ni:WaveformGraph>
</div>
</form>

 

 

<!-- Javascript -->

 

<script type="text/javascript">

 

function myKeyDownHandler(e) {
if (!e) e = event;

var x = document.getElementById("ControlKeyPressed");
if (e.keyCode == 17) { // check code for contro key.

// If key pressed is control, then set the hidden fields value to 'Y'.

x.value = "Y";
}
else {
x.value = "N";
}
}

function myKeyUpHandler(e) {
if (!e) e = event;

var x = document.getElementById("ControlKeyPressed");
if (e.keyCode == 17) {

// Here the control is is released, so change back the hidden field's value to 'N'.

x.value = "N";
}
}

function init() {

  // Attach the events.

if (document.attachEvent) {
document.attachEvent("onkeydown", myKeyDownHandler);
document.attachEvent("onkeypress", myKeyDownHandler);
document.attachEvent("onkeyup", myKeyUpHandler);
}
}

 

// IMPORTANT: Dont forget to call the init() function once when the document is loaded.

init();

 

 

</script>

 

Now, when there is a PlotAreaClick event fired on the server (here server meaning the C#/VB code), the server maintains the parameters that the client had sent. You can access parameters as follows,

 

 

string str = Context.Request.Params["ControlKeyPressed"] as string;

 

Now, your PlotAreaClick event handler would look something like,

 

protected void WaveformGraph1_PlotAreaClick(object sender, ClickEventArgs e)
{
if (IsPlotAreaClick())
{
//--------------------------------------------------------------------------------------
// Important Note:
// You will have to maintain a stack to remember the ranges of x/y axes before you set the new ranges.
// Keep the stack in a session variable or an application varaible or make the stack a static variable.
// First, Push the current x/y ranges to the stack.
//--------------------------------------------------------------------------------------

//Then, perform the tasks that you intend to do.
//Set the calculated new range to x/y axes.

WaveformGraph1.XAxes[0].Range = new Range(0, 1); // This is your calculated new range.
WaveformGraph1.YAxes[0].Range = new Range(0, 1); // This is your calculated new range.
}
else
{
//Pop the item from stack and assign the range to x/y axes.

WaveformGraph1.XAxes[0].Range = new Range(0, 10); // here you should use the value popped from stack.
WaveformGraph1.YAxes[0].Range = new Range(0, 10); // here you should use the value popped from stack.
}
}

private bool IsPlotAreaClick()
{
string str = Context.Request.Params["ControlKeyPressed"] as string;

// If the parameter value is 'Y' then that means the action was a zoom back out, not a plot area click.

if (str == "Y")
return false;
else return true;
}

 

Hope this helps.

 

Message Edited by vcp on 05-21-2010 09:33 AM
Message 2 of 3
(3,839 Views)

Wow.  In the meantime, I just added a form button which calls myGraph.ResetZoomPan().  For simplicity, I'll probably just stick with that.

 

Also, do you happen to know why a double-click (instead of a single click) is required to trigger the PlotAreaClick event?

0 Kudos
Message 3 of 3
(3,831 Views)