WWDC2003 Session 424
Transcript
Kind: captions Language: en again my name is Chuck so I am a works engineer and today we're going to talk to you about my name is my you know we're going to talk to you about some cool tips and tricks sort of think of this as the roared for sticking around so late on a Friday evening and what we're going to do is we're going to talk about some things that you could do which would you know put cool features in the applications and mimic some of the things that you've seen our own applications doing and these topics will range from beginner level topics that will be easy 40 and understand to some more advanced topics and don't worry there's gonna be lots of code and demos but all the source code will be available online for download I don't know if it's there right now which should be there sometime today okay so the way we're going to run things today is you guys get to ask the questions and we're going to answer them and fortunately Jason gave me lift the questions right before I came up on stage couple months ago and I punched in all the slides and all the demos so that we can just flow through nice and smoothly without any habit to go out to the crowd so the first question you guys had for us was well I've seen I chat safari address book all these applications with these cool rollover effects so just to explain with the rollover effective we've got the mouse moving back and forth and you see it represents that I have some clickable area okay so the idea for doing a rollover is really quite simple what we're going to do is track the mouse we're going to need to know when it enters in exits the region and once it does that we're going to set up some state that lets us know that either we want to draw a rollover or we're done drawing the rollover okay so how do we track the mouse well you could imagine that we continually monitor where the mouse is position is at every instant every time it moved that seems a little well a little unnecessary and very inefficient so all we really need to do in most situations is know when the mouse enters an area and when it exits an area if we had to we really could track the mouse at every instant of your location but we don't need to for this let's just be nice and efficient about it we're going to use ennis views API to add a tracking rectangle and when we do this one of the parameters we can specify is the owner and the owner gets notified with mouse entered and mouse exited whenever the mouse enters a region and when it exits the region okay so once it enters a region we want to set up our drawing states that we know we want to draw a rollover and we're going to use and it's desi a path to help us draw the rollover when we have our state set and what we're going to do is use this API to append well there's supposed to be a little image that it shows what we're doing but there we go we're going to append to caps at the end to half circular arts and when we're done we're going to use its API to close the path close up nicely when we draw it we're going to use this API to fill and we're going to draw a filled region created using this fuzzy a path so if we could go to demo one please ok so I'm going to start out first by showing you what we get when we run the application and see we have some other fans out there when we move over a region we get a nice little highlight effect that's busy a path ok so let's see how we did that we start by bringing up our nib to see how things are configured and we have a number of text fields in here and the important thing about these text fields that I wanted to point out is that it's called a rollover text field and if we look at the classes we see that roll over text field is a subclass of edit text field alright so we look at the code in roll over text field we have two instance variables one is they roll over path so whenever we enter region we're going to set up a rollover pass and we have a rollover path that's our cue that we want to draw a roll over and we have this rollover tracking rekt tag this is a value that's returned from the ad tracking rec api and it's what we're going to use to reference that track of rectangles we need to remove it or change this position so bring up the implementation file and we start out we have a number of routines which are just utility nicety routines that going to use when we manage our tracking rectangle we've got something to clear the current tracking rectangle and then we've got one to reset the current track rectangle and you know the first thing it does is clear the track and rectangle and then put it at a new position and we only do this when we're not live resized there's no point doing it during why every size because the mouse is over the girl box is not any it's not over your control so we're going to do that at the end of library size and be a little more performance intensive okay and then we've got a number of places where we insert calls to these routines which will either clear the track and rectangle or reset it at the appropriate time so for instance if the frame origin of our view moves well that's a good time to reset the track and rectangle when our frame size changes will do it also if we for some reason get moved into a new window well clear the track and rectangle information for the old window we're about to move into a new one and finally when we move into new window well let's set up a track rectangle in that new window and again we skipped setting any tracking rectangle information any any actual setting up any tracking rectangle during library sides so when live resize is over let's set it up then okay so that should be all the points that we need to catch and now that we have a tract as the owner we're going to get a call back when the mouse enters when the mouse enters we will create a busy a path and we're going to append one-half archon I guess the left side first not sure and yet some website first and then we're going to attend another half park on the right size and finally close the pack and we get just that diagram that I had showed you and since you know does the a pass and tell us what it balances well that's just dirty the bounds of the Bezier path that's what really needs to be updated and finally when mouse exits we're going to say that we need to read explain that bounds again and we're going to get rid of the beds a pack and finally to draw the beds a path if we have a rollover path we want to drive and we're going to set the color that we're going to fill the beds a path with a nice gray color and let's go ahead and change the text color to white that it can be more easily seen on top of the rollover effect and then we're just going to let NS text field do its thing it knows how to draw the text so we draw the rollover in the background and then we let it draw the text on top and that's it so if we could go back to slide please ok so we've answered the first question now the second question that I've heard was that you've seen this cool little raised editing effect in address book when there's a selected area it looks like it's you know in an editor which has this nice shadow around it how can I do that well the idea is actually really pretty simple once you have a key bit of insight on how to do it and what we're going to do is track the text selection and draw this raises editor around where the selection is and the key bit of insight is that well first of all we have this new class called n a shadow and Panther that we're going to take advantage of and the second bit is what we're going to do is create an image which has a hole punched out of the middle the middle and a shadow around the outside and because there's a hole punched in the middle we can just have n a text view do its normal drawing and then we draw the image over top of the text and because there's a hole in the middle you could see the text through it so this is actually just going to be a subclass aventis text view ok so i mentioned n its shadow is a new class in panther it has API which allows you to configure the shadow configure things about it like the offset and the blur radius and it has API which lets you set it as something that's used as a current drawing style just like you can use an NS color or Dennis font and tell it to set as part of the current drawing style you can do the same you can use it similar with well you can use it exactly like those things within a shadow and I have an example at the bottom that shows where we save the graphics context because we're going to set a shadow as the current drawing style and then when we still pass that path wound up having a shadow around it and since we don't want shadow drawing to apply to anything else other than just the drawing of that path we restore the graphic state when we're done so that it the shadow no longer applies so if we go back to the demos please demo on alright let's run this and see what we're going to get so this is a mock-up of something that you might see in address book and it behaves much like address book when I click I get a raise editor by type the Rays editor follows the selection and pretty much everything works so like I expect and just for fun we know how to do rollovers now so let's throw those then okay and we'll take a quick look at the nib again and see that well we just have one partial class there and it's called raised editing text you and it's a subclass of NS text view and we'll go to the code and we have here for classes which which are all part of the implementation of this raised text view we're going to focus on one of those in particular right now but again like I said you can download the code and look what the rest of it does but I'll just give a quick overview we have one file which has a category that defines all the methods dealing with handling the text selection and making text selection in that example work just like you'd expect it to work if it was address book and then we have a small file that does handle the rollover effect and then a file which deals with text attributes and make those easier to use in the rest of our code and if you want to find out more about what text attributes are tix a text view and it's text storage deal in attributed text and give you the ability to attach attributes to certain ranges of text and that's sort of what that class deals with I'd suggest going to Doug Davidson stock at five o'clock today if you want to find out more about that and finally we get to the part that deals with drawing that raised shadow look and we start out we have an hour awake from that we do a little you I set up so it fills the textview with some dummy information and then we have a routine called shadow image around pap it takes a veggie a path which specifies the boundary of where we want the shadow to be and what we're going to do is give them that busy a path figure out how big the image should be the image is going to need to be a little bit bigger than the beds da Paz found because it needs some offsets left to right top and bottom to accommodate for the shadow so what we do is we create an image and we're going to we're going to do something special were going to cash it separately because we know we resize in this image a lot we don't want to be cached in the same catch window as all the other ones I'd suggest reading up on the documentation the web to find out more about why we might do this in what it means we set the image to be flipped because well we're dealing with drawing text and typically flipping the coordinates makes that easier so what this means is the origin will be at the top left and said the bottom bottom left and finally we locked focus on the image and what that does is tell the image called the drawing system that our current drawing context is that image all the drawings going to go into that image we do a little translations that we draw the right spots and finally we're if we're the first responder we want to have the raised look and what we're going to do is save the way the graphic states so that shadows only apply to what we're about to do we create a shadow and give it some parameters and finally we set the shadow and set a color so that when we fill the path we actually feel something and it'll turn off that it doesn't matter what color we we set that path to because we're about to erase it in a little bit and you'll see what I'm talking about there so we set the shadow and then we fill with the path so we fill in a in a region in a rectangular region and outside of that reason that we filled in it's going to get some shadow and finally we're done drawing with shadows let's restore the graphic state and now let's knock a hole law of the mill because we're going to need to be able to see through that image to the text that's behind it and what we do is we clip to the past so we make sure that only drawing goes into that area inside of the path that we originally path path we set the color to be clear color and then we fill the entire bounds setting it to clear color basically knocks a full oz mill so it doesn't matter what we set that color to be before that white color because we've knocked a hole in the middle and finally we set sort of a nice light gray color and draw a border around where the shadow is just to make it stand out a little bit better all right and then we return the image and finally we have a routine which draws the raised editor what it's going to do is find out where the currently edited ranges and if there's a currently edited selection and text view deals and glyphs not characters again I would go to Doug Davidson stocks going to find out more about glyphs and characters and things like that if we have an area that we want to draw the Rays editor in what we're going to do is talk to the layout manager and find out where those glyphs live so we get a rectangle back and then we're going to inset well actually we're going to outset it I'll set that rectangle just a little bit so there's some separation between the selection and where the Rays editor in the shadows start and given that we're going to create a bevy a path with the rectangle that contains the edited glyph and pass that off to our helper routine to create a shadow image we get the shadow image back and we composite it to the screen and finally all we did was over I'd draw rect in ennis textview we let textview do its thing because it knows what to do and knows how to draw text us and afterwards well which are roll over if we have one and rollers are cool and then we draw the raised editor and that's it because you know we draw that image and it's a you're able to see through the image into the text behind it okay if we go back to the slides please so that ends my portion of the talk I'm going to invite up on stage our next speaker who is going to bring back an old friend that some of you might have mentioned that if you've been to WC lasco peers she's going to enhance dot view and try and make it the best app ever Tina thank you very much Chuck once again my name is Tina flung and I work with Chuck on the cocoa frameworks so many of you are probably familiar with two of our absalon systems mail and I chat and you may be thinking wow how do they do so many great things with the dock icons for instance you'll notice here that mail put the number of unread messages you have on the upper right side of the icon and when you minimize one of your ichat buddy windows chat windows you have a big picture of your buddies icon and there rather than a mini version of the entire window well there's two things going on here the first is male uses something called doc icon bet and for ichat they actually do something called your they sent the docs mini windows and so we want to make dot view the best staff ever so notice here that dot view traditionally has just an icon that's this big red dot and for the mini window it just miniaturizes the window of the entire dot view so notice here that we're going to have a colored badge on the dot view icon to represent what color your current dot is and we're also going to change the mini window to just be a version of the colored dot that's in your window so first let's talk about doc icon badging it's pretty simple the first thing you want to do is you want to grab the original icon of your dog now the application so to do this you're an Afghan is fun doll to give you the applications main bundle and get the path for the application from that bundle once you have the application in go to NS workspace and get the applications icon for the dock for vaping icon then you want to apply that badge to the image then you want to set that new image to be a new dock icon and there's one last thing you have to reset the icon back to its original icon before at termination and the reason being is you know that you can imagine a case where an app might want to leave that change modified icon add application but in this case we don't so we're going to register for the app and its application will terminate notification and set the icon back before we terminate so can I switch to demo so first the code here that we're going to change is pretty simple and the main thought view we have this method that updates application badge and what you'll see here is the first thing we do is grab the unmodified applications image and we do a bunch of computation to determine where we want to draw that new badge so here it is we draw the original image we add the badge which in this case is just a rectangle and the color of the dot then we call this NS application method set application icon image to set the image to be the new image with the badge applied and that's basically it except for in order to have the icon reset to its original state when application terminates we want to register for the app will terminate notification and here it is when we terminate we grab the original application icon and reset that to be your application your applications icon and here we're going to run it for you so here's thought view and malls glory and you can resize it and notice here you have just a red dot I'll make this bigger for you so here we just have the main dot but now we have this color dad so if we change the color of the dot you'll notice here that says now I had to fly to it that's it may go back slide please so now let's talk about that how we do the dark mini window so the first thing is we want to actually compute the image for the mini window lazily so in order to do this we're going to first register for the NS window did miniaturize notification and when we get that notification that's when we're going to compute the image for the mini window but you don't want them receiving these notifications for all the windows in your app so in order to make sure that we only have the main window receive these notifications we're going to look at two NS view delegate methods and so when you happy when you receive the NSU did move to window delegate methods you know that you are now the main window and at this point you will register for the did miniature identification when you receive the NSU view will move to window delegate method that means you're about to switch out of your window and that's no longer going to be your main window and at this point you want to unregister for the NS window did miniaturize notification so once you get this notification you're going to want to create the new mini window image and then set that to be the NS window your windows mini window and to do this use NS windows set mini window image method so can i switch back to demo please so first we'll take a look at the code so again we first take a look at the view did move to window delegate method and when we seed this we're going to register for the NS window did miniaturize notification when you're about to move out of the window then you're going to remove yourself from that notification and here's where the main crux of the mini window occurs once we receive that notification prepare mini window gets called and first we want to compute that new image so we're in create the image and draws the dot with the proper color set and that's going to be a new mini window image and then here it is you take this main window and you set the mini window image to be the newly computed image and just for fun we're going to actually have it tell you the radius for the title so we're going to see that run here so here we go when you change the size and the color of your dot and then we're going to miniaturize it notice here now we just have the dot is a mini window and it tells you that the radius here is 86.6 back to size please and so you may not think wow we have dot view with all this great stuff like this great descriptive dock icons but what I really want is rather than have the slider and the color well at the bottom of your dog new window wouldn't it be great if it had an animating inspector like finders most of you have probably seen this in finder and you know it's pretty neat you have these exclusive triangles so you have like the main information when you click on the disclosure triangle more detailed information occurs so how do you do that well it's pretty simple you have your three main views that are your general views of your inspector and then each one of these views will have an associated detailed view to go along with it the main difficulty here is that you want to temporarily adjust the resizing behavior of each of the views during the window animation and then animate the window so let's take a look at that resizing behavior most of you are probably used to doing this in interface builder what you have here is you set a string that indicates which part of your window overview is variable so in this case if you set the string of the top part of your view that means you're going to be pinned to the bottom of your window and most of you who are you know familiar with interface builder are probably used to doing this we're going to show you how you can do the same behavior programmatically so we have this method on NS view called set auto resizing mask and here rather than have the springs indicate the variable parts of your view we're going to have the mask indicate the same part and so here you'll notice you have the NS max why margin the min why margin and the height sizeable mask and so once again if you want your view to be pinned to the bottom you would set your auto resizing mask to be an ass max wide margin so for your inspector what you're going to want to do is for each view above your expanding view you're going to want to set the min y margin I jawless resizing mask for everything below that expanding view you're going to want to set the max y margin and for the expanding view itself you'll want to make the height sizable and once again remember if you want your window to be resizable make sure that you set them back to the original states or all funny things would happen to me when you try to resize the window so let's go back to demo so first we're going to take a look at the code and so all the main code here occurs during this toggle detailed visible and this is going to occur every time you hit that disclosure triangle so the first thing that we do is we use this new set in a API available in NS view that's new to Panther and basically if you're now telling your view to be visible you want to make sure you set you you make that be visible before you animate so that you're not animating into nothing then you're going to want to order all your disclosure views to the proper y coordinate and have some code that does that and shears like all the residing code we're talking about so for everything above and below the expanding views you can want to set the auto resizing mass to the proper mask as we talked about in slides and for the view that's actually expanding we're going to set the other side mass to NSU height sizable and finally you're going to resize the window using the animation API so we have a set frame display and to animate to be yes and once again if your view is no longer if you're now hiding your closing up the disclosure triangle you're going to want to set the detailed view to be hidden so that it's picking out the keyboard loop and a bunch of other things so let's take a look at that so now we have this great inspector for doc you and so we have a bunch of things you can do again you can change the size of your dot to color every dot and have a bunch of great new features that surprises you require no code to implement and that's it and notice here that the disclosure triangles animate and everything stays in place next slide please and so that's thought to you for you new and improved so to teach you some great trick they can do it at OpenGL view I'll out now like to introduce mr. NSU himself Troy Stevens [Applause] thank you very much Tina for that dub you just gets more and more powerful every year I mean I think we're revolutionising dot management am i right so Chuck so my topic today the slide says it all how can you take an opengl view that you're doing some rendering into and go fullscreen with it you've seen this in games games take over the entire screen keynote does this to show your presentation it's doing it right now this is here it is here's our demo fullscreen opengl so how can you do this well there of course a number of different ways to connect between the platform independent industry standard opengl api and different windowing systems and even on mac OS 10 i think one of the reasons it's the best as we give you so many ways to connect we have blood we have a GL which existed on mac OS 9 and is generally used by carbon apps we have cgl which supports a GL and then and then we have the NS OpenGL layer in app kit of course so in this case we're going to focus on how you would do this if you're using the NS OpenGL classes and it's OpenGL view and ass OpenGL context and s OpenGL pixel format to handle your OpenGL windowing in your cocoa out so we're going to do things a little differently for this demo we're going to go to the demo first and take a look just so we have a mental picture in mind of what it is we're trying to accomplish then we'll go to slides and we'll take a look at what some of the concepts are that are involved in doing this and then I promise we'll go back to the code will take a look at the code and how you actually do this so if we could go to demo one please so here we've got an opengl view in a window does some simple GL rendering we've got a three dimensional sphere here with a texture map on it and you'll notice there are some various it supports mouse input we can grab with the mouse and if we move the mouse vertically we can rotate the sphere we can move the mouse horizontally and change the direction the Sun is coming from there's some animation it's rotating there's also keyboard support if I hit the W key you'll have to take my word on this I am hitting W key and it's toggling wireframe rendering mode you can resize this so if we want to go to full screen with this say and take over the entire screen fill the entire screen area we just grab this thing down here and there you go whoa but seriously folks do you want it you want to be able to what we're really talking about here is I want to make this clear not just filling the entire screen with your OpenGL view you really want to take over the hardware you want to take control of that display so that you can do various other things that can help to improve your rendering performance you want to lock to your screen refresh so we've got a little method that's wired up to this button and if we do that now we're in full screen mode we've still got a mouse pointer we could have hidden that if we wanted to and you'll notice you still have Mouse response here and keyboard response and you can hit escape you of course always want to give your users a way out right because we're in full screen mode there's no quit menu item here or anything so hit escape and we're back to non full screen mode and we can hang on this all we want and go back and force them it's a pretty smooth transition I'm not trying to do anything sophisticated like a gamma fade here but it just works tried to keep the codes fairly simple so this is as I said more than just taking a view and going fullscreen with it then filling the screen what we're actually doing is we're rendering to a context we have what's called a full screen opengl context and there's actually no no view involved when we go to full screen mode so this is going take a little refactoring of our coats and we architecting of our app to really fully support this right and if we could go back to slides please well go over that so what are some of the prerequisites this is the somewhat advanced technique so we got a bunch of stuff to go through but remember the the sample code i believe is available now online so you can download it after this talk and study it to your heart's content and it'll give you a good baseline to start with if you're trying to implement this technique yourself you can start with something that works so one of the things that we need to do with NS OpenGL is start by creating a separate NS OpenGL context there's one that's implicitly created for you or you may be explicitly creating it in your NS OpenGL view so we want a separate context to render to when we go to full screen mode we want to give it the same more or less pixel format attributes that we gave to our non windowed context for example let's say we have some common attributes that we're using we want 24 bits of color buffer we want a 16 bit depth buffer we want a double buffered context so we can page flip and we want to specify that we'd like to have a hardware accelerated rendering context because we know we've got some great hardware we can lender with so when we create our full screen opengl context we want to use those attributes and we want to also specify the full screen pixel format attribute that's pretty straightforward we also want to specify a screen mask remember you could be running on a multi monitor system if you need to specify which screen it is that you want to take over and go into full screen mode with and the mask itself for example if you were on the main display you could simply pass this simple expression here so you do display ID to OpenGL display mask there's a mask macro for that if you look in CG direct display H you will find I believe this API so let's just say we're going to the main display we specify that for the mask we also need to do something special in the non full screen context since we know that we want to go full screen with that this one's a little obscure but by specifying the no recovery attribute in the non full screen context what we're doing is worth telling NS OpenGL that want a context that cannot fall back to a software renderer if we want our non full screen context to be compatible with our full screen context for purposes of texture sharing and sharing display lists' and other such OpenGL objects we need them too we need cgl to consider them compatible to do that we have to to make our non full screen context hardware only and that we do that using the no recovery attribute so another thing that we need to do is we're going to sort of change the model of our application normally you let app kit do the driving up kit runs your run loop app kit hands you events it tells you when to draw rect in your view tells you when you got a key down and that sort of thing but when we're in full screen mode we're really taking over the system we're going to drive everything we're going to be in our own loop for the whole time that we're in full screen mode until we exit driving the event loop and processing our own events so in order to facilitate this what we're going to do is factor code out of our NS OpenGL view subclass and move it into some other common object so that we can reference it both when we're in full screen mode and we're in when we're in windowed mode we're going to take all the OpenGL initialization and drawing that we normally do in our draw rect call and move that into another object and also our input event handling we want to be able to handle the same keyboard mouse events whether we're in full screen or non full screen so to help illustrate exactly what we're doing here we've got our OpenGL view to start with and normally it's got a draw rect method it's got a reshaped method that gets called whenever the view is resized and needs to adjust this GL viewport and so on and we also get mouse down and key down events so the first thing we're going to do is we're going to take the rendering and updating for changes in size move those into a scene object this is just an NS object this is your sort of data model object so we're going to move all the rendering out into a separate scene object that we define so that OpenGL view just calls the scene to do that and then we're going to have a controller object that handles all of the keyboard events and we're just going to have OpenGL view forward all these sort of requests delegate effectively to these different objects and then main controller has a go fullscreen method we're going to look at that one in detail that's going to be the focus of what's unique about this demo and that is the method as i said we stay in that method for the entire time that we are in full screen mode it takes over control and only when we exit full screen modes that relinquish control that invocation is live for the whole time we're in full screen mode and that's exactly what's wired up to that button that I click to go full screen so if you'll notice here we have a scene object this is this is our model so we have here everybody with me Model View controller it's Friday okay since I'm not planning on quitting my day job look at some API just a quick overview of some of the API I know this is a lot of stuff but users from the API that we will find particularly useful in implementing this one thing we want to be able to do is capture to the display talk to courts and say hey we want to own this display so that we can control it one of the other things that you may want to do is actually change screen resolution maybe you want to run an 800 x 600 or an even higher res than the user is running in we don't do that for simplicity in this demo but it's fairly easy to go ahead and do that once you've taken control of the display you can query courts and ask it what are the different modes this display supports and do that of course we're going to be able to be creating an NS OpenGL context the standard initializer for that and it with format share context notice the share context that's what's going to enable us to share texture objects with our in fact the earth texture is uploaded only once to OpenGL and when we go to full screen mode we just since we're specifying the non full screen context of the share context we just automatically get it we don't have to send it up there again set full screen of course a method on ms OpenGL context that's the main method used to go into full screen mode when you're ready and then we make we want to use make current context to make that context current so we can start drawing into it another thing you're going to want to do is potentially sink to the refresh rate so that you can what this does is it avoids tearing artifacts it's basically telling GL that you want this context to swap front and back buffers since we're double buffered in sync with the vertical retrace on your monitor this matters even on an LCD panel even LCD panels people are surprised to discover have a concept of retrace we also are going to need in full screen modes who flush our our buffer each time we're done drawing a frame will do that explicitly so that's where we swap the back buffer to the front buffer and then when we act want to exit full screen mode we clear the current context we send a clear drawable message to the context and that's how we get out of it and we can let go the full screen context can be done with it so if we could go back to the demo machine look at the source code that implements this and we have a few different classes here as promised we have a controller class our controller has a connection to the model and this is our full screen context here is just an OpenGL context like any other we've got a connection out to our view so and then the OpenGL view has a connection to the scene object that knows how to render the scene so it can delegate out to the scene to draw itself and it has a connection to the controller so it can send all the input events to the controller so let's look at the real interesting part going fullscreen that's in main controller it's really easy to see ok good so we'll go right down here to the go fullscreen method this is what's wired up to that button this is where we go first when we're entering full screen mode we have first of all we create our list of pixel format attributes you notice we have the common attributes here these are the same you'll see if you look at the source code as are specified for the non fullscreen context in addition we've got the display masks we've got the full screen after being specified here i should say they're the same common attributes with the exception of the no recovery attribute that's in turn on full screen context only so just that this is a lot of staff feel you can look at this at your leisure but just to quickly go through it we create the pixel format with those attributes and just for debugging and printing out here the renderer ID which identifies uniquely what card you're running on and you can see in the console output when we run the app that we can do that for Diagnostics we see that we end up seeing that both the full screen and non full screen contexts have the same render ID they're talking to the same hardware and that's the whole point of the no recovery attribute we create our full screen contacts we're done with the pixel format we temporarily spout the animation timer because instead of having a timer call us back every time we want to switch frames what we do is we drive the animation are we just checked the time interval each time we go through the loop we're in this loop of checking for input doing updating the simulation which in this case is just very quickly advancing the globe to the next frame and then rendering and we just keep doing that over and over again so we capture the display here here I've just done capture all displays but you can be more specific than that you would want to do that on a multi monitor system but capture all displays is fairly simple and universal now we tell the context to set full screen we make it current here's where we set the flop interval this is a case in which we have to drop down to see GL API to do that we're saving the old swap interval as a courtesy so we can set it back again before we after we exit full screen mode we set the scene tell the scene to set up for a new new display size and then we enter our loop and the loop is fairly simple in structure we're checking for in-processing input events with the first thing we do each time through the loop notice what we're doing with the mouse down event we're sending it to self the controller handles these events and the view likewise forwards mouth down events to the controller same thing for mouse up mouse drag we don't actually use votes but they're in their key down so we check for input we check the time interval for this frame and we advance our animation by the by the time Delta and then we render the scene and as I said we flush buffer when we're in full screen mode this is telling GL to do the page flip bring the back buffer forward and now we're going to start over and draw the next frame I'm a new back buffer and we're using an auto release pool here so that each time through the loop any objects that are created since again we're not app catism driving things anymore we don't have a clean up auto released objects for us so there's a common technique you create not a release pool and you release it at the end of the loop and everything gets cleaned up for you then there's a little trick in here you'll see to sort of clear the frame buffer clear a couple of pages before we switch back out a full screen mode this avoids just kind of an ugly flash of garbage when you go out to back to full screen back to non full screen we're setting the swap interval back to be a good citizen we're clearing the current context clearing the drawable we're releasing all displays and just telling our window to OpenGL view we need display and that's it so you see we have a key down method in the controller that actually handles the response for any key that might be pressed mouse down is implemented in main controller to do the work that is done when the mouse is clicked and then dragged to rotate the globe and so on so if we look at very quickly at the view object we've got very little left in the view object here it creates the pixel format its own pixel format again with the no recovery attribute and it's an it with frame method but everything else draw rec delegates out to the scene reshape delegates out to the scene you get the idea by now that we're just forwarding all those input objects to the scene all those input events to the controller object and all of the requests surrender to the scene so we've refactored our code as is said to better facilitate going fullscreen so I know it's a lot of stuff the source code i believe is online now if you log into your ADC account and with that I'd like to go back to slides and put you in a very capable hands of mr. Doug Davidson owner of the incredibly powerful insanely great tech system in cocoa he's going to show you some very cool stuff thank [Applause] Thank You Troy I'm no Davidson and I'm here to answer the next question so let's be a question please alright the question is I chat puts these beautiful bubbles around its text how could you do something like that good questions will think now if you want to know more about the theoretical underpinnings to this sort of thing you've come to my talk later on this afternoon five o'clock on Coco tech system but this is tips and tricks so we're just going to jump right in and do it and what we're going to do is draw one of these bubbles around each paragraph of the text so there are a few things we have to keep in mind now the cocoa text system automatically make sure that the text will be redrawn whenever it changes but these bubbles are going to be a little bit bigger than the text so we're going to need to make sure ourselves that they get redrawn too now we're going to be drawing these bubbles above the background and below the glyphs and the text itself so the way we're going to do that is should be fairly obvious we're going to subclass and it's text you to add some additional drawing to it and we're going to want to draw one bubble around each paragraph of the text so the main thing we need to know in order to do that is where the paragraphs are located location and size for each paragraph and the general answer to any question in that sort in the text system is ask the layout manager NS layout manager knows all so we're going to ask the layout manager to find out the information and will tell us where the paragraphs are located so we can draw the bubbles around them so some api's we're going to need all views have a method set needs display in wreck but NS text view has an additional somewhat more specific methods that needs display and rec to avoid additional layout and so we need to know that because we're going to be overriding that it gets cold quite a bit from the text system when text changes and things need to be redeployed and and as text view has another method new for Panther called draw view background in wrecked and what this does this is the method that text few users to actually draw the background for the view and so we're going to be overriding that so we can do our drawing above the background below the text and then we're going to need some NS layout manager methods first of all it generically local code systems you always need to use the layout manager to convert between ranges of characters and the text and ranges of glyphs that are displayed on the screen so we'll need those methods and we'll need some more layout manager methods to go from a reckless being drawn to the glyphs in that range and to determine where the lines of text are in the text view and we also have a new method in Panther on NS string called paragraph range for range there has always been a method line range for range but in fans are we distinguish between line ranges and paragraph ranges and we really want here is the range of paragraph in the text so we're going to use that method to determine what the ranges of paragraphs are in the characters of the text so let's take a look at some code if we can come over to demo one hmm here's our subclass of NS text view and so the first method i want to point out is our override of setting these display and rec to avoid additional layout and so as i said we need to make sure that these bubbles which are a little bit bigger than the paragraphs in clothes are going to get redrawn when the paragraph changes and the quick and dirty way to do that here is to simply expand the wrecked that is being dirtied by the amount the widths and Heights at the bubble over lapses for the text we could probably be a little more bit more precise here if we did a little bit more work but this works fine and then the next method i want to point out is a draw view background in wreck which we are overriding in an S text view so the first thing we do is call the super method which actually draw at the background is we want to draw the background first for the bubble and then we're going to figure out where each paragraph is in the wreck that we're done being asked to draw so we can draw a bubble around it so one thing we always have to do and working with the layout manager the layout manager works in text container coordinates not in view court that's so we have to do a translation to get into container coordinates then we ask the layout manager to determine what the range of glyphs is that we need to deal with to cover the wreck that we're being asked to redraw and we'll convert that to a charger range so we can examine this corresponding text this is the text that we need to determine the ranges of paragraph and we'll go through that text paragraph by paragraph iterating through each and so for we determine the range of a given paragraph by using the industry method paragraph range for range so we'll loop through it paragraph by paragraph and for each paragraph will have the range of characters in that paragraph then we're going to go back to the layout manager to determine where that paragraph is located so we'll get a glyph range corresponding to that paragraph range from the layout manager and then we're going to go to the lab manager to determine where the lines in that paragraph are in the text container in the text view and so this is a very common idiom when dealing with the layout masher to iterate through by lines and we call the line fragment use direct for Clifton index method the layout manager and what that does is it returns what we're asking for which is the used wrecked for a particular line and we want that because we need to that's part of the paragraph and it also returns by reference the range of lift in that line so that will help us iterate through by lines we're going to skip after we're done with this to the beginning of the next the next clip after this line and then we take that youth wrecked and you need it in to the wrecks that we're determining for the paragraph that tells us where the paragraph lives but again all the coordinates that the layout matter uses our container coordinates so in order to get it back to view coordinates we take our paragraph correct and we we undo that same translation and then we call a method that we have that draw actually draws the bubble and actually drawing the bubble is pretty simple I don't want to go too into it too much detail but we have some nice images and we draw an image on one side and image on the other side and we fill the middle with a pattern image so now we put it all together let's run it and see how it works there we go thank you now if we could go back to the slide I'd like to bring up Chuck again to wrap things up thank you Doug all right thanks ugh so I hope you guys have had some fun with this session that was sort of the intent of it have some fun show you guys how to do some cool features and I think you know I had a lot of fun fact the most fun of these the afternoon is seeing Troy staying up here I hope you all enjoyed that as much as I did so let's do the ramp up and well there's not much left ok so you all know by now you're getting dvds and so on so take a look at those when you get a chance what i want to point out is a talk that set five o'clock i hope some of you can stick around for that you're going to see Doug talkies more about the text system and find out you know how powerful it really really is very very cool stuff and the other thing I want to point out is who to contact you probably all know this by now John Glenn Z I guess is your main contact and well we've all seen before I'm going to skip ahead and show you that there's some more information and what I want to point out really here is the demo code now the demo code if it's not available right now it should be up there very soon so each of the demos that you saw on stage will be available for you to download and look at at your leisure