3.3. Graphical Dialer

The goal of this example is to create a simple graphical application on which the user can initiate a call on the selected speech unit to the supplied number.

3.3.1. UI mockup

salt
{
  Number:     | "      "
  Speech Unit:| ^  1  ^ | [Dial]
}

3.3.2. Plan

In order to send actions to the turret we need to connect to it first. The C# example solution has this functionality, so building upon that I propose that after a successful connection we open a new window showing the dialer.

3.3.3. Creating and designing the new window

In Visual Studio we can add a new window by selecting Project/Add Windows Form..., entering a name for it eg. GuiDialer.cs.

Now we can use the designer to create the user interface or do it from the source code. I decided to use the designer; in a 3x2 TableLayoutPanel created this nifty little interface:

../_images/dialerui.png

3.3.4. Showing the window after connection

To show the window we will need to extend the ThriftDemo class with a new member.

ThriftDemo.cs
21
22
23
24
25
  public partial class ThriftDemo : Form
  {
    private GuiDialer Dialer;

    private TurretRequestService.Client Client;

The buttonConnectToTurret_Click method handles clicking the Connect button. Creating and showing our form there should just do the trick. Since we are planning on requesting an action we should pass the Client to the GuiDialer object as well.

ThriftDemo.cs:buttonConnectToTurret_Click
143
144
145
146
147
148
149
150
151
152
153
  textBoxResponse.AppendText("Server exception: " + ex + "\n Server did not start. \n");
}
try
{
  Transport = new TSocket(textBoxIpAddr.Text, 9007);
  Transport.Open();
  Protocol = new TBinaryProtocol(new TFramedTransport(Transport));
  Client = new TurretRequestService.Client(Protocol);

  Dialer = new GuiDialer(Client);
  Dialer.Show();
GuiDialer.cs
13
14
15
16
17
18
19
20
21
  public partial class GuiDialer : Form
  {
    private TurretRequestService.Client Client;

    public GuiDialer(TurretRequestService.Client client)
    {
      Client = client;
      InitializeComponent();
    }

3.3.5. Handling dial button click

In the designer, clicking on a UI element twice automatically adds a click event handler to our class. We could do this manually as well, by adding a new method to our class and setting the Click property of the button to a System.EventHandler which calls our function.

When creating the interface the button was named dialerButton so upon double-clicking on it designer creates a dialerButton_Click method in the GuiDialer class. The speech unit selector was named suSelector and the editable textbox for the number was named numberTextBox.

Upon inspecting the API we can find a method TurretApi.TurretRequestService.makeCall which needs two parameters: the speech unit ID and the number to dial. Conveniently we have fields on the UI hopefully with just the right information and could make the call by calling the makeCall method on our client.

GuiDialer.cs
 private void dialerButton_Click(object sender, EventArgs e)
 {
   Client.makeCall((short)suSelector.Value, numberTextBox.Text);
 }

Now this is awfully optimistic so some form of failure handling would be desirable.

  • The speech unit selector is limited to the values 1-4 and (for now) we can not check for the available speech units.

  • Dialing with the number field empty is unnecessary.

  • There is also a situation of making a call from a logged out turret so we should check that as well.

Moreover in the API reference we can read:

Requests the turret to dial the given number from the specified speech unit. TurretApi.TurretApiException is thrown if speech unit id is invalid, the speech unit is busy or there is no free line to initiate a call from.

So catching those exceptions we get the following method:

GuiDialer.cs:dialerButton_Click
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
private void dialerButton_Click(object sender, EventArgs e)
{
  string number = numberTextBox.Text;
  if (number.Length == 0)
  {
    return;
  }
  if (Client.getLoginState() != TurretState.Login)
  {
    MessageBox.Show("Turret is not logged in");
    return;
  }
  try
  { 
    Client.makeCall((short)suSelector.Value, number);
  }
  catch(Exception ex)
  {
    MessageBox.Show(ex.Message);
  }
}