Build the State Change Events13:31 with Craig Dennis
Our application has several states that it enters into. Let's figure out how to handle them and let users of our application know what state they are in.
One of the things that's important to gather up at this beginning phase 0:00 is to determine what makes the state of our application change. 0:03 So there's a couple of things from the mockup that change the state. 0:07 Now obviously, there are buttons, right? 0:10 Play, Pause and Resume. 0:12 Now clicking Start will begin a new attempt and 0:14 change the color of the screen and start the timer. 0:17 Let's take a look at the board, and see if we can't see anything else. 0:20 Okay, so let's pick up the story here. 0:24 As a user, I should always know what state I am in, focus, break or 0:26 pause, so that I'm not distracted. 0:29 So, let's pull that over into the doing column and 0:31 let's talk about that a little bit. 0:34 So that was where we wanted to just change the color of the screen, right, 0:35 so the way that we solved that with a mock ups was the screen color changes, right? 0:40 Focus is one color, break is another color and when it's paused, 0:44 the pause button shows up. 0:48 In addition to changing the color of the screen, 0:51 we also wanted to set the title of the page of what's happening. 0:52 Let's go set that up in our controller. 0:55 So, in addition to changing the color of the screen, 0:58 we also wanted to set that title, remember it's at focus time or break time. 1:00 So, we need to set up our controller. 1:04 Cuz we don't have one currently. 1:06 So let's go to this home.fxml. 1:07 I used home as the name there for like the home screen. 1:10 Make sense, 1:14 because we don't have any other screens here so this was the home, the main one. 1:14 All right so one quick way to set up the controller is you can just define it. 1:19 Doesn't have to exist yet. 1:24 Com.teamtreehouse.pomodoro. 1:25 Even a package, right? 1:28 Controllers, let's drop it in a controllers package. 1:31 And let's call it home. 1:33 And if I come over here it's gonna say create the class. 1:36 Yeah, that's what we want. 1:39 Cool. 1:41 And now we have, under our controller package we have home. 1:41 Awesome. 1:45 So, we know that we want to know what the current attempt is that's 1:46 happening, right? 1:50 So let's go ahead and let's make that a private variable. 1:51 It's gonna ask and yep, that's what we mean, okay. 1:59 First things first. 2:05 Let's set up a method that starts a new attempt. 2:06 We'll use this for all of our attempt kinds. 2:09 So it should take an attempt kind. 2:11 Right. So let's keep it private. 2:13 Nobody needs to know about it yet. 2:15 Nobody on the outside, that is. 2:18 We can use this internally all we want. 2:20 So we'll say prepareAttempt and it takes an AttemptKind, We'll just call it kind. 2:21 Okay, and let's go ahead and we'll build a brand new attempt for 2:32 each time this method gets called. 2:35 So we're gonna set our CurrentAttempt = new Attempt and it takes a kind. 2:37 And we don't yet have what that message is, so let's leave it blank for now. 2:45 A common approach to handling design changes is to add and remove a CSS class. 2:49 Now we can do that here, right? 2:55 Let's add a class for the kind. 2:56 Then we can put whatever styles we want in that class definition. 2:59 Right? Does that make sense? 3:02 So, let's do that. 3:03 But first, let's make sure that we have a handle on the root node, 3:06 which is what we want. 3:10 Let's look at what's over there. 3:11 So, here, fx:id="container". 3:12 So, remember, in your controller, there is that FXML annotation. 3:14 And, we want to bring in a private VBox and its name is container. 3:22 Perfect, awesome. 3:29 If you click this, over here, it flips to right where the thing is. 3:33 It's kind of handy. 3:36 It flips back. 3:37 Does not. 3:39 Okay, and now let's make our method, column method that we haven't yet created. 3:41 We'll call it add attempt style, that makes sense right? 3:46 That's what we're going to do, we're going to have the style of what this attempt is, 3:50 so we'll say addAttemptStyle and let's have that take a kind. 3:52 Okay so, a method doesn't exist yet. 3:59 Let's go ahead, and 4:02 let's use this intention action to create the method for us. 4:02 Okay? 4:05 Awesome. 4:07 All right, so we have a handle on our container, 4:10 and containers have things that are called get style class. 4:16 Now, that sounds like that returns one, but 4:20 actually what happens is it returns a list. 4:24 It's a little weird of language, maybe get style classes would have been better, 4:25 but it is what it is. 4:30 It's called StyleClass on the other side, right. 4:31 It's not StyleClasses even though there could be multiple ones. 4:33 So, it returns a list, and because it's a list, we can just add to it, right. 4:36 So we're going to .add and let's push in the name of the kind. 4:42 And we already have the name, right? 4:48 That was the word in all caps that we wrote out before. 4:51 But let's make the class a little bit quieter, right? 4:54 So, we'll say kind. 4:56 If you do toString, it will use that name that we gave it. 4:57 And then, we'll do toLowerCase. 5:02 Now I remember in the notes from what 5:06 Susan gave me when I transferred something over, I actually already made this for us. 5:09 So let's take a look in the CSS that we're using here. 5:13 And if we scroll down here into the state based selectors. 5:16 Down here, so look, here's focus, that was the name of the focus. 5:21 And what's gonna happen is it's gonna change the background color to this. 5:24 And break will change the background color to that, whatever that is. 5:28 Oh look, it's a bug. 5:31 I'll fix that. 5:32 Okay, so let's think this through. 5:34 Let's walk back through this. 5:36 So it's gonna come in, we're gonna call prepareAttempt, and 5:37 it's gonna set the CurrentAttempt to a new one, which is totally cool. 5:40 And it's gonna add an AttemptStyle. 5:42 So let's say that we pushed in one that was focus. 5:43 It's gonna come through, it will add focus and 5:46 let's say that we push one in that's break. 5:49 Oh, it's gonna add two. 5:51 We don't want that, we don't want it to say focus and break. 5:53 Cuz then what's gonna happen? 5:55 Both of those classes are gonna be there and both of those are gonna apply, and 5:56 the last one defined will apply. 6:00 So it will always be that color break. 6:01 We don't wanna do that. 6:03 So, we wanna remove them too, right? 6:04 So let's do that. 6:06 You can, let's make something for exactly what we're trying to do. 6:08 We gonna say private and then it'll be a void, let's make a clearAttemptStyles. 6:12 What we can do here is we can loop through everything that's in that enum, and 6:17 just remove it, just pop it off. 6:21 Right. So for AttemptKind kind, and 6:23 if you say on an enum attempt kind dot values, 6:27 it will loop through each one of the values that are in the enum. 6:31 Now again, that's a list. 6:38 So get style class is a list, and lists have a thing 6:40 that's handy called remove, which it will pop the object off, should it exist. 6:46 It won't give you an error if it doesn't, 6:50 so let's just loop through all of them and pop off what's on there. 6:52 Probably a little cleaner way to do this, but it'll work for 6:58 now and because we've put it in our own method we can fix this however we want. 7:02 As long as it does that. 7:07 As long as it clears the attempt styles we can change this however we want, right? 7:08 So I'm gonna put that right at the top of the prepare attempt, right? 7:12 Let's start with a clean slate. 7:15 So we'll say clear attempt styles. 7:16 And then we'll add the attempt style. 7:19 Okay, and so the next thing that we wanna do, is we wanna 7:21 set the text label with the name of the kind of attempt that's going on. 7:23 So let's get a handle to the title in our controller. 7:28 So, what was that? 7:31 That was title, so let's get a handle over here. 7:32 We'll say @FXML private it was 7:34 label and it's called title. 7:39 And we want gamma Java FX version of that. 7:46 You can have this on the same line or below. 7:51 Sometimes it auto corrects to that. 7:55 So I like to at least have it in the same style, whatever that's going on the file, 7:56 keep it the same way. 7:59 It's really up to your team on a style decision for that sort of thing. 7:59 And this prepare attempt, we could set the title, right. 8:05 We could do this title.setText and we could just set it to the kind, and 8:08 we could get the two string version of that. 8:12 But that's not really what we want, right. 8:15 Like what if we changed the word from being focused? 8:18 And it's in all caps, too. 8:20 We don't want to have to play around with stuff. 8:22 So we want a display name. 8:23 And why don't we just set that as a constant as part of the enum. 8:26 Let's do that, so 8:30 we'll say get DisplayName, that sounds like a good function, right? 8:30 We're wanna say, how do we display this? 8:35 So we'll save that and I am going to click here. 8:38 Let's use the intention action and we'll create a method, getDisplayName. 8:42 There we go. 8:49 And let's do a private 8:49 String m DisplayName. 8:54 Didn't work out exactly the way that I wanted it to. 9:00 [LAUGH] And we'll pop it in the constructor here, too. 9:01 So, let's do displayName and 9:05 we'll say mDisplayName = displayName and 9:10 of course that's a string. 9:17 Okay so now these are complaining obviously, and so 9:23 we want this to be called Focus time, and we want this to be called Break time. 9:25 Now of course, if that changes, if the way that these words change, 9:31 what's nice is this focus could, we could have something totally, 9:34 concentration time over here, right. 9:40 But we could still call it focus in our code, whenever we use focus and 9:42 then this could kind of change. 9:45 So that helps keep things dynamic. 9:46 I'm really liking this enum usage. 9:49 I mean, imagine if we had to go through a big if else switch here. 9:50 Since everything else is already defined, we can just use it, right. 9:54 So we're using this kind.getDisplayName, perfect. 9:57 All right, I'm ready to see if this is working. 10:00 But how do we do that? 10:03 One trick that I like to use is I like to drop in, right at the top here, 10:05 let's just add a Button. 10:09 And this works really well in 10:12 things where you don't have much control of when input comes in. 10:15 Because this program will just run and it will be sitting there. 10:19 So let's give this an ID, and I like to use all caps so I don't forget about it. 10:21 And we'll say onAction DEBUG, all right? 10:27 And, of course, debug doesn't exist cuz we just made that up. 10:33 So we will create a method over here. 10:38 Void DEBUG, and we'll just make it do something silly. 10:41 All right, so now if we kick off things in debugger mode 10:48 Something is wrong. 10:59 Oh, I forgot to close the tag. 11:01 That's what it's angry about. 11:02 So let's try that again, let's run in debug mode. 11:05 Okay, so there is a button there that I forgot to label Debug. 11:11 Let's do that really quick. 11:16 So you can. 11:19 See that. 11:23 And I will close main there. 11:24 Let's do that again. 11:28 Let's run DEBUG. 11:29 There we go, there's the DEBUG button. 11:33 Got some weird styling that it's inherited, but that's all right. 11:35 And if I click it and say hi mom, we don't necessarily want that. 11:38 We want to put a break point on where it says hi mom, right? 11:43 So now, if we do debug. 11:49 There's our app. 11:52 When we click it, we're going to pause. 11:53 And now we can use that trick that we learned before with 11:57 this Evaluate Expression. 11:59 And I can say prepareAttempt(AttemptKind), and we'll do FOCUS first, 12:03 (AttemptKind.FOCUS). 12:06 What that should do, is it should. 12:08 So it returned void, but it should have, as we continue our app. 12:17 Now if we look at our app, it should be, There we go. 12:23 So it says Focus time, and it's changed its color. 12:27 Awesome. Let's make sure that it also works for 12:31 Break time. 12:33 So, here we are, broken again. 12:35 And we'll say run, Evaluate Expression, 12:36 prepare attempt, we'll do attempt kind, break. 12:41 Evaluate. 12:48 And we close that. 12:53 And we can continue running. 12:54 Now, if we look at our app. 12:57 There we go, Break time blue. 12:59 Beautiful, it's working. 13:01 Great, we got most of our states all set up. 13:03 But I left an important one out. 13:07 We need to start the timer with the appropriate time. 13:09 I wanted to explore another way to do things. 13:12 We just saw how to essentially bring the reference of the node into the controller 13:15 from the FXML. 13:20 But I wanna show you things the other way. 13:22 The FXML can actually bind to a property on the controller. 13:24 Let's explore the binding way of doing things right after this break. 13:28
You need to sign up for Treehouse in order to download course files.Sign up