Friday, May 16, 2014

CPControl: Buttons

This article is a closer look at text boxes as they relate to CPView objects.  Find other CPView articles, including additional articles on CPControl objects at the our root article on the CPView topic.

Buttons!  They are a critical point to every classic application.  Today's applications swap buttons with clickable tiles, and drag-n-drop interfaces, and intuitive auto-continuation triggers, but understanding how to create a button is a great way to implement basic functionality before you define those new age interfaces.

Create a New Project

If you have followed some of the other tutorials, you should be comfortable with creating new projects.  Create a new application folder for this tutorial.  I have called my project CPButton.

Just like the previous tutorials, we will avoid creating additional object files in order to explore the basic objects.  These tutorials are short, and the objects we create are short-lived, so we will work entirely within the AppController.j file.

First Steps

First, we will create the button the same way that we have created all our view objects up to this point; later we will look at a great feature of the CPButton class which removes the guess work about dimensioning.

Add the following code to your AppController, after the definition of the contentView variable:
var button = [[CPButton alloc] initWithFrame:CGRectMake(300,300,100,50)];
[contentView addSubview:button];
When you reload your page, you will see your new button, but it does not do anything, and it has no label.  You will also notice that it appears to be two buttons, but if you click on it, you will see that it responds as a single button.  We will fix the double button problem later.

Adding a Label

Buttons often need a label in order to have meaning.  We often make use of images, but for now, we will just add a simple text label.

To do this, we will use the method: setTitle.  Add the following code:
[button setTitle:@"My Button"]
Reloading the page will show:

Actions and Targets

The button does not do anything yet.  The question is, how do we invoke a method by pushing the button?  Also, which object is the method invoked on?  How do we get a variable pointer to that object?

Every CPControl object has the function setTarget: and setAction:.  These two functions allow us to call any object and method when a trigger event happens.  For buttons, the trigger event is the click action.  For text fields, the trigger event is pressing the Enter key.  Other controls have different trigger events.

Because we are not creating any unnecessary objects in these beginner tutorials, we will create our button and set the target as the AppController itself.  The action that we define tells the code which method of the target object to invoke.

To attach our button to the AppController object, we will add the following code within our AppController:
[button setTarget:self]
[button setAction:@selector(buttonMethod:)]
The first line of code here sets the object that is going to be invoked on the action event.  Within the AppController, "self" refers to the AppController instance.

The second line of code sets the method to be called on the action event.  We have named the method "buttonMethod".  This method does not exist yet; we will have to create it.

We could have put any method name in the @selector() call we choose.  For now, remember the following:

  • In the selector definition, always remember the colon after the method name.
  • In the selector definition, always remember that this is not a string and there are no quotes around the method name.
  • The method definition, at this point, should take only one argument of a generic object type; Cappuccino's generic object type is "id".
We will add the following method to our AppController:
-(void)buttonMethod:(id)aSender
{
     //put button code here.
     alert("Button has been pushed");
}
The name of the attribute is arbitrary.  Name it whatever you like.  When a CPControl object invokes the selector, by default, it passes the object that is invoking the action.  In this case, aSender would be a link to the button that initiated the call. This means that we can reuse the same method and point multiple buttons to it if we need to. I find that I seldom need to refer to the calling object in a button call, but this is an important lesson in how CPControl objects work in general, because there will be times when you will need to know that this object points to the object that invoked it.

Now that we have given the button a method, we can reload our project and push the button to find an alert window indicating success:

Creating a Button With Text: the Easy Way

We still have the matter of the double button appearance.  We can change the CGRect object and play guessing games with the dimensions to get the perfect appearance, but the Cappuccino developers made it much easier for us.  Remove the following lines of code from your application:
var button = [[CPButton alloc] initWithFrame:CGRectMake(300,300,100,50)];
[button setTitle:@"My Button"];
In their place, add the following:
var button = [CPButton buttonWithTitle:@"My New Button, which is the Perfect Size"];
[button setFrameOrigin:CPPointMake(300,300)]; 
 We find, when we reload the page, that our button still operates, as before, but now it is perfectly wide and tall to fit the label that has been created for it:

A Word On Images

The CPButton is a CPView object just like all the CPControls that we are discussing.  This means that, like all CPView objects, that it has sub-views.  We will not do so in this tutorial, but we could use addSubview to add image objects or any other view object to the button's display.  The power in Cappuccino's UI is knowing that everything derives from CPView, and therefore, everything behaves by the same view hierarchy rules.  Every CPView object can become its own container for subviews.

CPButton class adds a new method that CPControl does not have called setImage.  Images are so frequently used on our buttons, that the developers saw fit to make this easier for us.  Whether you use the sub-view features inherited from CPControl, or the setImage method of the CPButton class, you have options to play with.

The Limitations of CPButton

We saw, when we created our CGRect that was too tall, that the button uses an image that has a fixed height, and a variable width. We can use the +buttonWithTitle:(String) method to create a button that is perfectly sized, as long as it is only one line tall. If we add line breaks to the string, we find that our button does not change its dimensions.

If, at a later time, I discover a manner to change the manner in which this image is stretched. I will update this article.

No comments:

Post a Comment