Skip to content
lloyddewit edited this page Oct 7, 2022 · 32 revisions

Contents

Getting Setup
Using VB.Net – your first dialog.
Adding Controls to a dialog.
Adding Code to the dialog.
Key Principles – code repetition and consistency
Testing your dialog

Getting Setup

To setup for R-Instat development, you need the following on your laptop:

  1. R (must be the latest version) which you could download from https://cran.r-project.org/
  2. RStudio which you could download from https://www.rstudio.com/products/rstudio/download/
  3. Visual Studio Community 2019 (https://visualstudio.microsoft.com/vs/) The download file is small but the installation process requires continuous internet access to the end.
  4. Once the small installer has downloaded, navigate to where it has been downloaded, and run it.
  5. You will see a similar dialog to the one below. It will be downloading necessary files for installation
Figure 1: Installation
  1. After all the files are downloaded another dialog similar to the one below will pop up. Please check .NET desktop development and at the bottom select Download then install (the highlighted ones) and click install.
Figure2: .NET Desktop Development
  1. Create a GitHub account if you don’t have one already at https://github.com/

  2. Log in to your GitHub account and create your own fork of the R-Instat project at: https://github.com/africanmathsinitiative/R-Instat by clicking the fork button on your top right and selecting your account.

  3. Create a local copy of the R-Instat project on your machine (Cloning). To Clone follow this procedure: -
    a) Open your remote repository from https://github.com/yourusername/R-Instat. You will see an interface similar to the one below.
    b) Click on the green Clone or download button on the right. A small box appears below it.
    c) Copy the URL to your repository.

Figure 3: Cloning
  1. From your start menu, open Visual Studio. You will find an interface like the one below. On the right side of the screen, click on Clone a repository. Paste the link you copied from github to Repository location. Then Click clone. This will take some times. A nother method is shown in figure 5 below. To get there, click on Continue without code.
Figure 4: Visual Studio Interface
  1. The Team Explorer should be similar to the screenshot below. Click on the Manage Connections button, the green plug-like button on the top of the team explorer window. Then Click on the Clone link and paste the URL you copied from GitHub on the yellow textbox, then click the Clone button below it. (This might take some minutes)
Figure 5: Team Explorer
  1. You will also need to download the R packages used in R-Instat.

a) open R-Instat\instat\static\InstatObject\R\RSetup.R in RStudio and run everything before the line:

load_R_Instat_packages <- function() {

b) Then run packages_not_installed() and install all these packages i.e. install.packages(packages_not_installed()).

Installing Package System.Data.SQLite

Note from Lloyd 07/10/22 TODO: This section needs updating. If you install SQLite manually, then ensure that you install version 1.0.113, not a later version.

After pulling changes from R-Instat master into your branch during testing process, something pops up that will not allow you to proceed with the process. This bug appears when you start R-Instat.See the figure below;

Figure 6: Bug produced before installing Package System.Data.SQLite

To install this package, open visual studio and then click on Tools >NuGet Package Manager>Package Manager Console as shown in the figure below;

Figure 7: Installation Process

After that now type Install-Package System.Data.SQLite as highlighted below and Enter. The screen will remain dormant for a while before the installation process begins, just give it time.

Figure 8: Install-Package System.Data.SQLite

Testing work done by other developers

Every developer is assigned programming tasks. Once they have made all required changes to the software, they carry out the following processes;

  1. They commit the changes
  2. They push the changes
  3. They open a Pull Request so that it can be merged into the master (Don’t worry about them for the moment, you will learn them as you go by)

You can view the list of open R-Instat Pull requests here - https://github.com/africanmathsinitiative/R-Instat/pulls. Each of these pull requests includes some changes to the software that need to be checked/reviewed before they are merged into the master.

To get yourself set up to do the testing

  1. Open your visual Studio 2019
  2. From your visual studio, (Assuming you downloaded and installed GitHub Extension for Visual Studio), go to View>Other Windows>Github
Figure 9: Testing
  1. You should now see a new tab – Github- on your left-hand side pane with Team Explorer and Solution Explorer.
Figure 10: Github Extension
  1. This tab now shows a list of Pull Requests that have been opened by the developers. This list corresponds to the PRs on - https://github.com/africanmathsinitiative/R-Instat/pulls.
  2. For example, if I want to test the first PR on the list, which was opened by Shadrack Kibet – I need to double click on it.
  3. The pane will load the changes made by Shadrack as shown below
Figure 11: Merging a pull request
  1. To pull the changes to your local machine, click on the link Check out to pr/5858-enabled-summary. This means that it will create a branch locally which will have these changes. If a dialog comes up saying there are changes in some files made outside of your solution, and asks to reload – Select Reload All.
  2. Now a new branch has been created in your local machine with the changes from Shadrack. You can confirm this by clicking on the Team Explorer then Branches. You will realize there is a new branch with a name similar to Shadrack’s PR title. #
Figure 12: Creating a branch
  1. Now you are all set, click on start and test the changes made.
  2. Once you are certain the changes work as required, Click on the GitHub tab again and click on the Add a review you can leave a review or a comment using the text box that appears as shown below. Three things you can do are – Comment only to just add a comment- Approve- Meaning the changes work okay and no bugs were found, Request changes- meaning the changes work but not as per the specifications, and so more changes are needed.
Figure 13: Adding a review

Using VB.Net – your first dialog.

In R-Instat, we use modal dialog boxes (Windows Forms) as a way of interacting with the user to retrieve information. Below are examples of dialog boxes in R-Instat. The main controls of our dialogs include a Selector, Receiver (Single or Multiple), and the Base Buttons. Other controls are added as needed.
The selector contains available variables (or other objects e.g. graphs) from a data frame. Receivers indicate the selected variable for use in the analysis.

Figure 14: Components of a dialog

Now, let’s look at how to create your first dialog.

  1. Open Visual Studio and load up the Instat project. From the Project menu, click Add Windows Form and give it an appropriate name from the dialog that appears. All our dialogs start with the prefix dlg. For our case, let’s call our dialog dlgSummaryTest and click Add.
Figure 15: Creating a dialog
Figure 16: Naming a dialog
  1. From the design view of the form which appears, as shown below, go to the Properties window which is on your bottom right, and change the following properties:
    a) FormBorderStyle to FixedToolWindow
    b) Maximizebox to False
    c) Minimizebox to False
    d) Text to an appropriate dialog name, in this case, I will call it “Summary Test”
    e) Start Position to CenterScreen
Figu 17: Setting the properties of a dialog

Currently, we have an empty dialog with no controls on it. Let’s look at how to add controls to the dialog.

Adding Controls to a dialog.

In our dlgSummaryTest, we will need the dialog to have simply a selector, a receiver, and the base buttons. The dialog will run a simple command: calculating the summary of an individual column, hence we need a single receiver.

To add controls on the dialog;-

  1. Scroll through the toolbox, find the required control (in our case we need ucrSelectorByDataFrameAddRemove). Drag and drop the control on the desired position on the dialog. Select the control, and on the properties window change the name property to ucrSummaryTestSelector. Do the same for the single receiver and call it ucrSummaryTestReceiver and base buttons. Our base buttons always have the name ucrBase.
  2. On top of the ucrSummaryTestReceiver, add a control from the toolbar called Label by dragging it in the same way. Change its Name property to lblSelectedColumn and the Text property to “Selected Column” (the value of text property is what the user will see on the control). Naming conventions for VB.NET controls may be found here which we mostly follow:- https://msdn.microsoft.com/en-us/library/aa263493(v=vs.60).aspx
  3. You should now have a dialog looking like this
Figure 18: A dialog with controls

Adding Code to the dialog.

Once we have the design of our dialog created, we need to add functionality to it and the controls we’ve added. We can do this by adding code to the dialog to do what we want.

For our example we need our dialog to be able to give us a summary of a single column by using the summary() function in R. So how do we do this?

To add code to a dialog, double click on the dialog or press F7 to view its code. This opens the code editor with these lines. In VB.NET we use subroutines to do “things” when events happen. The below code is a subroutine called dlgSummaryTest_Load which handles the event Load. This means that any code inside this subroutine will be executed when the dialog Summary Test loads i.e. when the Load event happens.

``Public Class dlgSummaryTest  
     `Private Sub dlgSummaryTest_Load(sender As Object, e As EventArgs) Handles MyBase.Load  
`Any code inside here will be run when the dialog loads  
   `End Sub  
 `End Class 

Below is the code for our dialog which makes the dialog functional.

Figure 19: Adding Code to Dialog

First, you need to add the code below which is the license for our open source project. Make sure to add the rest of the code as well to make the dialog functional. See explanations in the comments above the code.

'R- Instat
'Copyright (C) 2015-2017
'
'This program is free software: you can redistribute it and/or modify
'it under the terms of the GNU General Public License as published by
'the Free Software Foundation, either version 3 of the License, or
'(at your option) any later version.
'
'This program is distributed in the hope that it will be useful,
'but WITHOUT ANY WARRANTY; without even the implied warranty of
'MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
'GNU General Public License for more details.
'
'You should have received a copy of the GNU General Public License 
'along with this program.  If not, see <http://www.gnu.org/licenses/>.
Public Class dlgSummaryTest
    'We define a Boolean to know if the dialog is opening for the first time
    Private bFirstLoad As Boolean = True
    'We define a Boolean to know if the dialog is being reset
    Private bReset As Boolean = True
    'We define an object of class RFunction which is a VB.NET class defined to represent an R function 
    'that a dialog will run
    Private clsSummaryFunction As New RFunction
 
    Private Sub dlgSummaryTest_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        'On first load we initialise the dialog
        If bFirstLoad Then
            InitialiseDialog()
            bFirstLoad = False
        'If resetting, we set the defaults
        If bReset Then
            SetDefaults()
        End If
        'We always set the R code for the controls. This sub updates the values of the dialog controls so
        'that they in sync with the values in the RFunction.
        SetRCodeForControls(bReset)
        bReset = False
        'We always translate the dialog in case the language has been changed
        autoTranslate(Me)
        'We finally test and set the Ok button to be enabled or disabled.
        TestOkEnabled()
    End Sub
 
    'This sub sets initial values for the controls on the dialog
    Private Sub InitialiseDialog()
        'Sets the R parameter linked to this control.
        'In this case, the receiver will contain the variable to summarise. In the R command `summary` 
        'the parameter of the object to summarise is called `object`
        'Therefore, we set the parameter of the receiver as a New RParameter object with name `object`. 
        'The 0 is the position of the parameter in the R function, with the first parameter being 0.
        ucrSummaryTestReceiver.SetParameter(New RParameter("object", 0))
        'Sets the type of information we want from the receiver to be passed to R. The `IsRFunction` 
        'indicates that the parameter should be the column of data with name as in the receiver. The
        'alternative is `IsString` which will just pass the text displayed in the receiver.
        ucrSummaryTestReceiver.SetParameterIsRFunction()

        'Links the selector to the receiver
        ucrSummaryTestReceiver.Selector = ucrSummaryTestSelector 
        'Sets the receiver as the current receiver, ready to accept variables
        ucrSummaryTestReceiver.SetMeAsReceiver()

        'Sets the help page ID for the dialog
        'We don’t know this yet for our dialog so we comment out the line
        'ucrBaseDescribeOneVar.iHelpTopicID =

        'This sets the type of output for our function that will be displayed in the output window. 
        '2 indicates that there will be text output.
        'clsRsyntax manages the R script that the dialog will run.
        ucrBase.clsRsyntax.iCallType = 2
   End Sub

    'This sub sets the defaults for the function the dialog runs
    Private Sub SetDefaults()
        'Resets the summary function so that all previous information is cleared
        clsSummaryFunction = New RFunction        
        'Resets the selector so that the current data frame in the spreadsheet is selected by default.
        ucrSummaryTestSelector.Reset()

        'Sets the name of the R command for our function.
        clsSummaryFunction.SetRCommand("summary")
        'Adds any default parameters to our function.
        'This is adding: `maxsum = 7, na.rm = FALSE` to our function.
        clsSummaryFunction.AddParameter("maxsum", 7, iPosition:=1)
        clsSummaryFunction.AddParameter("na.rm", "FALSE", iPosition:=2)

        'Sets the main (base) R command of the R syntax, meaning that clsSummaryFunction is the 
        'main function this dialog will run.
        ucrBaseDescribeOneVar.clsRsyntax.SetBaseRFunction(clsSummaryFunction)
    End Sub

    'The links the controls on the dialog to the RFunctions the dialog will run. During the linking 
    'process, the controls will read the RFunction that it has been assigned and update its value based 
    'on the value so that the RFunctions stored in the dialog are in sync with the values the control 
    'displays on the dialog to the user.
    'In this example, we only have one control which links to a parameter in the function.
    Private Sub SetRCodeForControls(bReset As Boolean)
        ucrSummaryTestReceiver.SetRCode(clsSummaryFunction, bReset)
    End Sub

    'Enables/disables Ok depending on whether the required information is complete on the dialog.
    'In our example, if the receiver is not empty, Ok can be clicked.
    Private Sub TestOkEnabled()
        If ucrSummaryTestReceiver.IsEmpty Then
            ucrBase.OKEnabled(False)
        Else
            ucrBase.OKEnabled(True)
        End If
    End Sub

    'This handles the ClickReset event of ucrBase, which is triggered when the Reset button is clicked. 
    'Here we set the defaults, set the R code for the controls and run TestOKEnabled().
    Private Sub ucrBase_ClickReset(sender As Object, e As EventArgs) Handles ucrBase.ClickReset
        SetDefaults()
        SetRCodeForControls(True)
        TestOKEnabled()
    End Sub

    'This handles the ControlContentsChanged event of ucrSummaryTestReceiver. This event is triggered 
    'when the contents of the receiver control changes in any way. Which is why it is necessary to run 
    'TestOKEnabled() on this event.
    Private Sub Controls_ControlContentsChanged(ucrChangedControl As ucrCore) Handles ucrSummaryTestReceiver.ControlContentsChanged
        TestOKEnabled()
    End Sub
End Class

Key Principles – Code Repetition and Consistency

Where possible we do not repeat code but instead re-use code. When the same code is needed more than once, it is usually sensible for it to be in its own sub routine - e.g. setting the defaults is done when loading the first time and when clicking reset, hence it goes in its own sub called SetDefaults().

The dialog you just created contains relatively little code, considering it is doing a number of tasks, from running an R command, allowing the controls to update/be updated from the R code and passing an R command to run in R and display some output. This is because most of these tasks are in the code of the user controls. Firstly, this reduces code repetition since less code is repeated on each dialog, and secondly, it ensures the software is consistent since the user controls look and behave the same way on every dialog. Although the dialog code is short, you should understand the general system behind the controls to be able to use them properly, once you understand this, even complex dialogs become simple to create.

Most of the sub routines defined here you will find in almost every dialog. Almost all dialogs have:

a) InitialiseDialog- this sub sets initial values for the dialog and controls. This should include values that will not change on the dialog as this sub is only run the first time the dialog loads.

b) SetDefaults - This sets the defaults for the (R) functions used in the dialog. This is run when the dialog first loads and when it is reset.

c) SetRCodeForControls – This links the controls on the dialog to the RFunctions. During the linking, the controls will read its RFunction and update its value to be in sync with the R code. Once the controls are linked to the code, when the value of the control changes, it will update the RFunction it is linked to.

d) TestOkEnabled – This sub checks whether the user has set the required information for the dialog to run and if so the Ok button is enabled, otherwise it is disabled. This runs when the value of any required control changes.

e) autoTranslate(Me) – Me refers to the dialog itself and the autotranslate sub takes all the controls in Me (the dialog) and translates any display text to the chosen language.

Testing your dialog

To be able to test if your new dialog works, it needs to be accessible from R-Instat’s menu. We will add a temporary menu item to access the dialog.

  1. Open frmMain which is the main form that loads when R-Instat opens. You should see the R-Instat menu at the top of the form.

  2. Click on Describe to see the menu items and then click at the bottom of the menu to add a new item. Write “Summary test” for the new item and click enter.

  3. Double click on the new item and this should open the code for the form with a sub for the Click event of the new item already created.

  4. In this sub write dlgSummaryTest.ShowDialog(). This will show our new dialog when the menu item is clicked.

Now you can run the project by clicking Start in the Visual Studio toolbar.

Load some data and test out your new dialog to see if it works!

If it doesn’t work, go back to the example code above and compare it to your dialog code to check for differences.

If it works, then now look at the R code in the output window.

If you are familiar with R, then you will see that some of it looks like standard R code, like the summary(...) line. And some is not standard R, like the first line which includes the InstatDataObject part. This is because R-Instat stores all the data, metadata and objects used in a session in an InstatDataObject, a class we created in R to store the data in a way R-Instat can easily access. Hence, before running any standard R commands, we often have to extract the data we want from the InstatDataObject.

Notice also that the parameters maxsum and na.rm are fixed at 7 and FALSE. But what if the user wants to change these? We could have added a numeric input control for specifying maxsum and a checkbox for na.rm. This is what we did in the real dialog for summary, dlgDescribeOneVariable. If you find this in the project and you will see the extra controls on the design, and looking at the code you will see some similar code to our example above, but with more code for other options that are available on the dialog. A good exercise would now be to look at this code and try to understand everything that it does.