An Introduction to TextBoxes in Quorum

In this tutorial, we will learn how to use TextBoxes in the Quorum Game Engine. TextBoxes are simple interface tools used to get text input from the user, or to output text.

For this tutorial, we will create a project with two TextBoxes, and provide Buttons that allow the user to add or transfer text from one TextBox to the other, a Button to clear the receiving TextBox, and a Button to read aloud from the receiving TextBox. To start, create a new Game Application project.

Creating TextBoxes

For this main class, we will need the libraries form TextBox, Button, and Color, giving us the following use statements:
use Libraries.Game.Game
use Libraries.Interface.Controls.TextBox
use Libraries.Interface.Controls.Button
use Libraries.Game.Graphics.Color

Since we want the TextBoxes and Buttons to be usable as soon as the game begins, all of our additional code in the main class will be in the CreateGame action.

First, we will create a TextBox and add it to the game. We will also need a Color variable, since the Initialize action for TextBoxes requires a background color. This Initialize action requires two numbers, width and height, a Color for the background, and text to fill the TextBox with. After Initializing, we need to set the TextBox’s position and add it to the game, using the SetPosition and Add functions. This gives us the following lines of code:

Color color

TextBox box1
box1:Initialize(300, 300, color:White(), "Enter text in this TextBox.")
box1:SetPosition(100, 280)
Add(box1)

Now, let’s create our second TextBox, which will be considered the recipient TextBox for this tutorial. To distinguish it from the first, we will make this TextBox gray, and will not preset text in it. Providing no text for the Initialize call will preset the TextBox to be empty. We will also place it to the right of the first TextBox. This is done with the following lines of code:

TextBox box2
box2:Initialize(300, 300, color:Gray())
box2:SetPosition(400, 280)
Add(box2)

If we build and run the project, we have the two TextBoxes and can type into either, as shown below.

This image shows the expected TextBox locations.

Additional Features

Now that we have our TextBoxes, we will create Buttons to add, transfer, clear, and read, as described at the beginning of the tutorial. First, we will create each Button’s behavior, starting by creating new Quorum classes for each. We will name these "AddBehavior.quorum," "ClearBehavior.quorum," "TransferBehavior.quorum," and "SayBehavior.quorum," respectively.

Let’s begin with the AddBehavior class, which gets text from a source TextBox and appends it to already existing text in the receiving TextBox. We will need the libraries for TextBox, Behavior, and BehaviorEvent, requiring the following use statements:

use Libraries.Interface.Controls.TextBox
use Libraries.Interface.Behaviors.Behavior
use Libraries.Interface.Events.BehaviorEvent

We will also need to create two TextBox class variables, which are undefined. Thus, we also need an action to set these TextBoxes to the same TextBoxes as those in our main class. Additionally, the AddBehavior class will inherit the Behavior class and override the Run action, giving the following template:

use Libraries.Interface.Controls.TextBox
use Libraries.Interface.Behaviors.Behavior
use Libraries.Interface.Events.BehaviorEvent

class AddBehavior is Behavior

    TextBox box1 = undefined
    TextBox box2 = undefined

    action SetTextBoxes(TextBox sourceBox, TextBox receiveBox)
        box1 = sourceBox
        box2 = receiveBox
    end

    action Run(BehaviorEvent behavior)
    end
end

First, we need to complete the Run action. To add text to a TextBox, we need to use the Insert action. To obtain text from the other TextBox, we need the GetText action. Since the GetText action returns a text object, we can use that directly as the parameter for the Insert action call, allowing us to combine both action calls onto one line. As usual, we will need to check that our TextBoxes are defined before doing so. This give us the following completed Run action:

action Run(BehaviorEvent behavior)
    if box1 not= undefined and box2 not= undefined
        box2:Insert(box1:GetText())
    end
end

Adding this to our template, the complete AddBehavior class is as follows:

use Libraries.Interface.Controls.TextBox
use Libraries.Interface.Behaviors.Behavior
use Libraries.Interface.Events.BehaviorEvent

class AddBehavior is Behavior

    TextBox box1 = undefined
    TextBox box2 = undefined

    action SetTextBoxes(TextBox sourceBox, TextBox receiveBox)
        box1 = sourceBox
        box2 = receiveBox
    end

    action Run(BehaviorEvent behavior)
        if box1 not= undefined and box2 not= undefined
            box2:Insert(box1:GetText())
        end
    end
end

Next up is the TransferBehavior class, which gets text from a source TextBox and replaces the already existing text in the receiving TextBox with it. Fortunately, this class is almost identical to the AddBehavior class, only calling the SetText action instead of the Insert action. This gives the following complete class:

use Libraries.Interface.Controls.TextBox
use Libraries.Interface.Behaviors.Behavior
use Libraries.Interface.Events.BehaviorEvent

class TransferBehavior is Behavior

    TextBox box1 = undefined
    TextBox box2 = undefined

    action SetTextBoxes(TextBox sourceBox, TextBox receiveBox)
        box1 = sourceBox
        box2 = receiveBox
    end

    action Run(BehaviorEvent behavior)
        if box1 not= undefined and box2 not= undefined
            box2:SetText(box1:GetText())
        end
    end
end

The ClearBehavior class is next, and is once again similar to the AddBehavior and TransferBehavior classes, although the ClearBehavior class only uses one TextBox. This class uses the Empty action, which clears the TextBox of any pre-existing text. The class is as follows:

use Libraries.Interface.Controls.TextBox
use Libraries.Interface.Behaviors.Behavior
use Libraries.Interface.Events.BehaviorEvent

class ClearBehavior is Behavior

    TextBox box = undefined

    action SetTextBoxes(TextBox sourceBox)
        box = sourceBox
    end

    action Run(BehaviorEvent behavior)
        if box not= undefined
            box:Empty()
        end
    end
end

Last up is the SayBehavior class, which is very similar to the ClearBehavior class, except that it uses the Speech library, which requires adding the following use statement:

use Libraries.Sound.Speech

In the Run action, we will create a Speech object and call the Say action. For the text parameter, we will use the TextBox’s GetText action again. Additionally, we will provide a second parameter, a boolean, and assign it false. This allows the user to do other actions while the text is still being read aloud.

The complete SayBehavior class is as follows:

use Libraries.Interface.Controls.TextBox
use Libraries.Interface.Behaviors.Behavior
use Libraries.Sound.Speech
use Libraries.Interface.Events.BehaviorEvent

class SayBehavior is Behavior

    TextBox box = undefined

    action SetTextBoxes(TextBox sourceBox)
        box = sourceBox
    end

    action Run(BehaviorEvent behavior)
        if box not= undefined
            Speech speech
            speech:Say(box:GetText(), false)
        end
    end
end

Now that our Behavior classes are completed, we can return to the main class and create Buttons for each, and add them to the game. Our Button declarations are as follows:

Button addButton
addButton:Initialize(150, 30, "Add Text")
addButton:SetPosition(475, 230)
Add(addButton)

Button transferButton
transferButton:Initialize(150, 30, "Transfer Text")
transferButton:SetPosition(475, 190)
Add(transferButton)

Button clearButton
clearButton:Initialize(150, 30, "Clear Text")
clearButton:SetPosition(475, 150)
Add(clearButton)

Button readButton
readButton:Initialize(150, 30, "Read Text")
readButton:SetPosition(475, 110)
Add(readButton)

Next, we need to create a variable of each Behavior class we created, and call the SetTextBoxes action on each. This can be done as follows:

AddBehavior addBehavior
addBehavior:SetTextBoxes(box1, box2)

TransferBehavior transferBehavior
transferBehavior:SetTextBoxes(box1, box2)

ClearBehavior clearBehavior
clearBehavior:SetTextBoxes(box2)

SayBehavior sayBehavior
sayBehavior:SetTextBoxes(box2)

Finally, we need to set each Button’s behavior, done through the following lines:

addButton:SetBehavior(addBehavior)
clearButton:SetBehavior(clearBehavior)
transferButton:SetBehavior(transferBehavior)
sayButton:SetBehavior(sayBehavior)

Now, when the program is run, we can add the text from the left box to the right box, replace the right box’s text with the left box’s, clear the right box, or read the right box’s text aloud.

This image shows the TextBoxes with the first four buttons.

The TextBoxSelection Class

For the final additions to our program, we will use the TextBoxSelection class. This tool keeps track of what part of the TextBox is selected, allowing us to use only a portion of the text instead of all of it, just like any standard text editor. For the purposes of this tutorial, we will simply add two more Buttons, which allow the user to add or transfer only the selected text over.

The TextBoxSelection’s main purpose is holding the start and end indices for the selection. For example, if the full TextBox holds "Hello world!" and the selection is "world," then the start index is 6 and the end index is 11.

Before we create Buttons for adding and transferring the selected text, let’s create the Behavior classes for them. We will name these "AddSelectionBehavior.quorum" and "TransferSelectionBehavior.quorum," respectively.

The AddSelectionBehavior class will need the libraries for TextBox, Behavior, BehaviorEvent, and TextBoxSelection, giving the following use statements:

use Libraries.Interface.Controls.TextBox
use Libraries.Interface.Behaviors.Behavior
use Libraries.Interface.Events.BehaviorEvent
use Libraries.Interface.Selections.TextBoxSelection

The class itself will inherit the Behavior class. It will also need two TextBox class variables, an action to set those TextBoxes, and will override the Run action, giving us the following template:

use Libraries.Interface.Controls.TextBox
use Libraries.Interface.Behaviors.Behavior
use Libraries.Interface.Events.BehaviorEvent
use Libraries.Interface.Selections.TextBoxSelection

class AddSelectionBehavior is Behavior

    TextBox box1 = undefined
    TextBox box2 = undefined

    action SetTextBoxes(TextBox sourceBox, TextBox receiveBox)
        box1 = sourceBox
        box2 = receiveBox
    end

    action Run(BehaviorEvent behavior)
    end
end

This Run action will function slightly differently than the other classes did. In it, we want to check if box1 and box2 are defined, as usual, but then we need to create a TextBoxSelection variable and set it equal to box1’s internal selection, using the TextBox’s GetSelection action. Then we will create a text variable and set it to the entire contents of box1 using the TextBox’s GetText action. With these in hand, we can make one last text variable to take out only the selection, using the text’s GetSubtext action, which accepts start and end indices. To make these indices match our selection indices, we will use the TextBoxSelection’s GetStartIndex and GetEndIndex actions. Finally, we can use this subtext variable as our parameter for the TextBox’s Insert action. This gives the following Run action:

action Run(BehaviorEvent behavior)
    if box1 not= undefined and box2 not= undefined
        TextBoxSelection selection = box1:GetSelection()
        text fullText = box1:GetText()
        text subtext = fullText:GetSubtext(selection:GetStartIndex(), selection:GetEndIndex())
        box2:Insert(subtext)
    end
end

The complete AddSelectionBehavior class is as follows:

use Libraries.Interface.Controls.TextBox
use Libraries.Interface.Behaviors.Behavior
use Libraries.Interface.Events.BehaviorEvent
use Libraries.Interface.Selections.TextBoxSelection

class AddSelectionBehavior is Behavior

    TextBox box1 = undefined
    TextBox box2 = undefined

    action SetTextBoxes(TextBox sourceBox, TextBox receiveBox)
        box1 = sourceBox
        box2 = receiveBox
    end

    action Run(BehaviorEvent behavior)
        if box1 not= undefined and box2 not= undefined
            TextBoxSelection selection = box1:GetSelection()
            text fullText = box1:GetText()
            text subtext = fullText:GetSubtext(selection:GetStartIndex(), selection:GetEndIndex())
            box2:Insert(subtext)
        end
    end
end

Now, we need to create another new class for the TransferSelectionBehavior class. This class is almost identical to AddSelectionBehavior, differing only in the class name and using the the SetText action instead of the Insert action. This gives us the following completed TransferSelectionBehavior class:

use Libraries.Interface.Controls.TextBox
use Libraries.Interface.Behaviors.Behavior
use Libraries.Interface.Events.BehaviorEvent
use Libraries.Interface.Selections.TextBoxSelection

class TransferSelectionBehavior is Behavior

    TextBox box1 = undefined
    TextBox box2 = undefined

    action SetTextBoxes(TextBox sourceBox, TextBox receiveBox)
        box1 = sourceBox
        box2 = receiveBox
    end

    action Run(BehaviorEvent behavior)
        if box1 not= undefined and box2 not= undefined
            TextBoxSelection selection = box1:GetSelection()
            text fullText = box1:GetText()
            text subtext = fullText:GetSubtext(selection:GetStartIndex(), selection:GetEndIndex())
            box2:SetText(subtext)
        end
    end
end

With our Behavior classes completed, we can now return to the main class. Adding to our CreateGame action, we merely need to create two new Buttons and give them our new Behaviors, just as we did for the previous four Buttons. Note that we also move the clearButton and sayButton to make room for the new Buttons. This adds the following code:

AddSelectionBehavior addSelectionBehavior
addSelectionBehavior:SetTextBoxes(box1, box2)

Button addSelection
addSelection:Initialize(150, 30, "Add Selection")
addSelection:SetPosition(475, 150)
clearButton:SetPosition(475, 70)
addSelection:SetBehavior(addSelectionBehavior)
Add(addSelection)

TransferSelectionBehavior transferSelectionBehavior
transferSelectionBehavior:SetTextBoxes(box1, box2)

Button transferSelection
transferSelection:Initialize(150, 30, "Transfer Selection")
transferSelection:SetPosition(475, 110)
sayButton:SetPosition(475, 30)
transferSelection:SetBehavior(transferSelectionBehavior)Add(transferSelection)

Altogether, the following is the main class in its entirety:

use Libraries.Game.Game
use Libraries.Interface.Controls.TextBox
use Libraries.Interface.Controls.Button
use Libraries.Game.Graphics.Color

class Main is Game
    action Main
        StartGame()
    end

    action CreateGame
        //We create the two TextBoxes and place them in the game
        Color color

        TextBox box1
        box1:Initialize(300, 300, color:White(), "Enter text in this TextBox.")
        box1:SetPosition(100, 280)
        Add(box1)

        TextBox box2
        box2:Initialize(300, 300, color:Gray())
        box2:SetPosition(400, 280)
        Add(box2))

        //We add the first four Buttons
        Button addButton
        addButton:Initialize(150, 30, "Add Text")
        addButton:SetPosition(475, 230)
        Add(addButton)

        Button transferButton
        transferButton:Initialize(150, 30, "Transfer Text")
        transferButton:SetPosition(475, 190)
        Add(transferButton)

        Button clearButton
        clearButton:Initialize(150, 30, "Clear Text")
        clearButton:SetPosition(475, 150)
        Add(clearButton)

        Button sayButton
        sayButton:Initialize(150, 30, "Read Text")
        sayButton:SetPosition(475, 110)
        Add(sayButton)

        //We add Behaviors to each of our Buttons
        AddBehavior addBehavior
        addBehavior:SetTextBoxes(box1, box2)

        TransferBehavior transferBehavior
        transferBehavior:SetTextBoxes(box1, box2)

        ClearBehavior clearBehavior
        clearBehavior:SetTextBoxes(box2)

        SayBehavior sayBehavior
        sayBehavior:SetTextBoxes(box2)

        //We create the Button for adding a selection of text
        AddSelectionBehavior addSelectionBehavior
        addSelectionBehavior:SetTextBoxes(box1, box2)

        Button addSelection
        addSelection:Initialize(150, 30, "Add Selection")
        addSelection:SetPosition(475, 150)
        clearButton:SetPosition(475, 70)
        addSelection:SetBehavior(addSelectionBehavior)
        Add(addSelection)

        //We create the Button for transferring a selection of text
        TransferSelectionBehavior transferSelectionBehavior
        transferSelectionBehavior:SetTextBoxes(box1, box2)

        Button transferSelection
        transferSelection:Initialize(150, 30, "Transfer Selection")
        transferSelection:SetPosition(475, 110)
        sayButton:SetPosition(475, 30)
        transferSelection:SetBehavior(transferSelectionBehavior)
        Add(transferSelection)
    end

    action Update(number seconds)
    end
end

This image shows the final expected game window.

Next Tutorial

In the next tutorial, we will discuss TabPanes, which describes how to use TabPanes.