WWDC2004 Session 433
Transcript
Kind: captions Language: en good morning everyone welcome to session for 33 please welcome software engineer David McLeod good morning thank you for coming out I'm glad to see there's people here interested in making custom H I've use that means you're getting our message that H I've you is the way to go forward and you're ready to do it with us your applications all provide your specialty you make them special why should you make them special by doing whatever things you do on the inside that we don't we don't do and you present that special specialty through your user interface so almost everyone here has some kind of custom user interface whether you're drawing directly into a window or you're using a custom control you're using some other view system like power plant for example I am trying to find a nice way of saying that so people are going to be moving to a chive use and you might have some custom content already as you go forward you're going to need to have a chive you we're going to H I view as the technology we're going to use to move forward as we do things like resolution independence as we add new features to the toolbox and you need to be there with us to move forward basically today I'm going to go over how to make a custom each of you it's going to be a primer on how to make a chive use so we're gonna learn how to subclass on each I object how to create a custom a chive you and just how to implement the basic behaviors that make of you first I'm going to give you a little bit of background a chive use well the whole a chai toolbox on the inside is object oriented and a chive user a subclass of the main main object H I object all of the API is associated with HIV UNH I objects are object oriented they use C interfaces and carbon events to do to do the communication where the h I views or H I objects are the classes and the carbon events are the methods or messages and with those with those messages we put in carbon event parameters and that's how you pass parameters to and from your sub classes so here it is H I object is really our base class everything's based off an H I object and like I said there's some meth edges that are associated with with with the class there's also some properties from that base class we have subclasses H I've used Windows menus there's a few other ones i don't have up there like toolbars etc but that's just to show that you know a chai objects are the base class that we use to inherit from to produce different objects within the toolbox we're going to focus in on h-i views so H I views are the subclasses H I've use like I said with all of our with all of our classes messages are the carbon events and there's a few properties associated with the subclass we use H I've you to subclass to make our are all of the views that you associate with the system so like pop up buttons radio buttons checkboxes all of that and this is where you would subclass to make your custom H I've you notably you can also subclass an existing a subclass of an H I've you so in this example I would subclass a push button and just override some some of the extra behaviors make my own custom kind of push button that inherits from the existing push button well I'm just going to focus on subclassing H I've you directly so a custom H I've you is a subclass of H I object where you handle a few messages associated with construction and it's also a subclass of a chive you where you handle a few messages that actually produce the behaviors of your H I've you and that's all that makes up a custom H I've you understand these concepts is sort of key and understanding how to subclass and make your own custom H I've you so next I'm going to get into just how to go about doing that subclassing first thing you're going to need to do is register your sub class and that means handling those events that are messages for the H I object associated with doing construction doing destruction one went to finish with the object and doing initialization after that you're ready to instantiate that's all there is to it so here's an example of how to register your sub class using H I register hhi object register register subclass API the first parameter that's really important is the class ID of your custom of your sub class and that's a reverse domain string that we that you send to a chai two blocks to tell it to tell it how to identify your sub class and throughout the process that is how you identify your sub class 2 H I toolbox that's how you we you know we know what we're talking about next you want to tell at the base class ID from which you're going to be sub classing in today's examples where I'm so glassing in a chive you I'll be passing in the the base class ID of HIV you can also use this to subclass what's you know the pop-up buttons class ID or directly from h-i object node will see nobly if your sub classing directly from an H I object you can leave this blank because that's the base base sub + and the last one I'm going to draw attention to is the construct proc this is the event handler that's going to be handling the events the construction events the k event H I object construct destruct and initialize events here's an example in code of using it so it's just like any other carbon event handler that you've used before you set up a list of carbon events that you're interested in it's just a set of class event pairs in this case I'm interested in the key event class H I object class of events and i'm interested in Kate event H I object construct initialize and destruct next you call a chai object register subclass and this is where the reverse domain name my class ID identifier comes into play it I dent off' eyes uniquely my subclass by this ID and you can see here in this example that I'm subclassing from a chive you using the public key HIV class ID and I specify which handler is going to be receiving these three events that I'm interested in it's going to receive them and handle them dispatch them out appropriately so here's an example of the the meat of what that kind of that event handler would look like I handle those those three events that i've registered for when i get the construct event i do something to handle construction similarly with the initialization and destruction i do something to handle those so i want to get into exactly what you would do in those three cases where you're handling those events first construction it's very notable it is called direct it's called directly by the instantiation mechanism of H I object it's not from an event handler stack and this is really important because under normal circumstances with carbon event handlers you can call next to van time to learn and let some of the default behavior happening but there's no event handler stack in place so you just can't do that really bad things will happen when you get the construction event that's the time when your sub class does its allocation or instantiates maybe a c++ class any of the allocation that's going to occur happens here it's not time to do initialization yet because things might not be set up sufficiently you do that later on and the really i think this is the only tricky concept in the hole in the whole subclassing mechanism the event the key event / am H I object instance parameter during the construction handling on the way in what you get is a base H I object rest that's what's been constructed so far by the H I object subclassing mechanism that's the object ref that you're going to have for the rest of the life of the instantiation of your subclass what you do generally is store that in some of the data that you've allocated just recently in this construct handler so on the way in its that H I object graph on the way out you want to set the parameter to whatever the instance data is that you've allocated and that's important because from now on whenever whenever your sub class is called that instance data is going to be passed in as the user data to your event handler and that's how you can get the reference to what your instances in your sub class so here's an example of handling a cave event H I object construction event just a little reminder don't call a next event handler bad stuff bad stuff going to happen I do some allocation I have a little data structure it's not really important what's in it i call it my view data the only important thing to note is that i have a spot in there to remember my h i object rest that I get right on the way in from construction I get that H I objects ref from k event parameter instance and I I store it in my allocation space the space that I've allocated oops and on the way out you can see that I've stored that allocated instance data back in and overwritten the K event prime H I object instance from now on whenever my van hello gets called I'm going to get that instance data and I can use it to implement my sub class doesn't really I like to talk about destruction first but just kind of reordered of it the destruction is going to happen way at the end so before the destruction happens you're going to do initialization initial when you get in k event H I objects initialize event that means the construction have some successfully allocations okay everything's ready to go it's time to set things up when the initialization event comes to you all of the initialization parameters are set as carbon event parameters in the incoming event so you can just extract those if there are any and do whatever you want with some store them into your instance data or set up things or do whatever you want this phase is optional not not everybody's going to have a instance initialization but actually I think it'd be pretty common you don't have to do it nothing bad will happen I think I forgot to mention in the with a construction event it's absolutely required if you don't do it no construction is going to happen and the rest of presentations not going to happen so it definitely have to handle construction so here's an example of handling the initialization event first of all you want to call next to van hendra that's important because it gives your super classes a chance to initialize if you're familiar with C++ that's just like passing on the your constructor up to the other superclass constructor so you got to give your superclass a chance to initialize itself as well you check the return value from call next event handler and make sure that your superclass initialized successfully because if it didn't you certainly aren't really going to need to and then it's time to handle your own initialization like I said you just use the incoming event you extract parameters from it using get event parameter and do whatever you want with them and this is also time when you can modify the initialization event and set things like your future bits and that sort of thing example of it here lastly after everything is done and everything's being torn down you'll get a destruction event again this is not being called from the normal event stack so don't call next event handler even if we did do that and we allowed allowed you to tell your parents to destruct themselves before you did that would be a very bad thing it's like calling delete in delete parent in your C++ destruct method it's bad idea this is not optional you have to handle your destruction to get rid of any allocated data if you don't handle this event destruction will fail and when you do destruction that's your that's your time to deallocate anything you allocated during the construction phase if you allocated some memory or if you instantiate it a C++ subclass it's time for you to either free the memory or delete the subclass the C++ with us again emphasizing don't call next event handler I say it Lots in here it's going to be in the sample code that you see it's going to be in kurt's demo you just don't want to do it's also in the header docks just don't call next event handler when you're doing construction and destruction and as you can see this is just my time to clean up my allocated data one important note one important note here is that you will get a destructive ant if initialization was unsuccessful so you have to be able to handle a destroying a partially initialized or an uninitialized subclass so if if construction went ok but initialization didn't you'll still get a destructive nth so you have that opportunity to deallocate that's pretty much it so that you after you after you install that event handler you're ready to instantiate you have to register the subclass using that API mentioned previously and to do that you create an initialization event so to actually instantiate you create it create initialization event stuff any parameters in that you want to end up being passed to your subclass instantiation and then call h I object create using that initialization event that you just created there's an example of that I create an event it's a cave in class H I object given H object initialize event real standard way of making an agreement I made a made up of fake value here to stuff into the event as a parameter that the initialization event as a parameter is just a float I push in there and I call h I object.create and you'll note here that H I object.create takes the reverse domain class ID that I registered my class with that's how you tell toolbox hey that's the thing I registered that's how that's how I want you to instantiate right now so that's how you get your sub class into instance to be the one you want I'd show you a demo there's not much a demo yet you've just made an instance doesn't do anything it's it's not that's just how to make that's just how to make a subclass of an H I object it's not in anything it doesn't draw it doesn't have any behavior anything like that so i'm going to show you anything to give you something to show you probably want to implement the simple view behavior simple view behaviors are drawing fit testing clicking keyboard keyboard handling and definitely accessibility these are the simple basic behaviors that you're going to want in almost every h I've you and really they just all map on to either directly onto a carbon event or onto a class of carbon events really straightforward so let's say you wanted to add some drawing to your HIV subclass you want to handle the key event controlled draw event really important concept with a chive you drawing is getting this event that's the only place you ever draw you don't draw willy-nilly you invalidate your your your views and then when the appropriate time comes the view system will ask you to draw and that's how we achieve the compositing and the efficient drawing so like I said up here validation is your friend you want to invalidate and then let the let the toolbox tell you when it good time to draw is when you get the draw event inside the event there's a CG text rest so you can extract that it's a parameter of the event and the nice thing about the CG context ref it's all set up for you it's all clipped its trans transform properly it might be scaled if you're if we're in the future sometime and we're doing resolution independence you don't have to worry about anything like the order and the and you definitely don't have to erase behind which did with quick draw because paintings all happening in a nice composited stack this this concept also gives you a context that is Oh top left sorry what's left for me up here it's all top left you might not be used to that if you've been making your own context in an event handler so far with like a user pain or or that kind of thing so the context is already top left for you and then you just go ahead and do whatever kind of drawing you want in there with reports and get your cool rendering effect adding adding a drop in handlers very easy you just extend the this is a class event list that I had before I'm just expanded it by putting a cave in class control key event control draw event on to it and I register it register the handler the same as I did before and then you change your handler so that it handles the cave in class control cave and control draw and then you do your drawing there here's the meat of what a draw handler would look like so basically extract the CG context ref out of the event using good event parameter I have the reference to my H I've you that gets passed every time the event handlers skulls I use that to get my view ref and I get the bounds of it and I just do some drawing it's simple drawing here does a translucent red rectangle I think that's it you know you have a nice simple h I've you that draws a rectangle you wouldn't actually see it though I stuck this in here this is an important step if you were to just instantiate now you wouldn't see anything because that a chive you is is it has no parent it's just off in ether somewhere you need to add it to a window or at it as a sub view of a view in a window so you want to either add it as icon to the content view of a window or some kind of parent view and you also need to make it visible it's made initially invisible for efficiency if you if you create it and then after you create it you want to set a bunch of things you don't want something to happen to it and make it redraw over and over while you're setting it up so it's created initially invisible you set it up and you'll set the control value or whatever you're going to do on it and then you make it visible and only ask you make visible are you going to see it this is really one of the big hurdles that people hit when they first make an HIV is like I made it it's not showing up where is it you have to take these steps they're very important it's very common that they're forgotten it's one of the questions we answer or you guys help us answer on the carbon dev list Austin so I'd like to ask her to come up and just go through some of the things I showed to instantiate a simple HIV subclass Kurt thank you David don't forget switch to the demo machine please so basically what we're going to look at here is just the HIV you test application now this is just a sample code it's available and develop our examples carbon but I want to walk through just making a very simple a subclass of a chive you that does just a simple drawing so let's go about looking how we do this we're going to define a chai teste register and during application initialization that out if this function will be called because we need to register this subclass with the H I object sub housing system and then we need to specify that we're going to handle these H I object specific events so construct initialize indie struck now as David mentioned construct and destruct are required if you don't specify these registration will actually fail and then H I object initialization is optional but as they would also mentioned that's probably where you'll handle most of your initialization so as so you can see how the h I object specific events and the control which are the view of specific events are kind of glob together this is all in the event lists that we're going to pass into the H I object register subclass API and for now we're just going to be looking at the K even control draw event next we register the subclass and as David mentioned we pass in our class ID which we defined which we define it's in the header file because in the header file other than publicly available to the rest of the application okay and then we say that it's going to be a subclass of the standard khi view class ID we give it its construct proc this is going to be our event handler so we're basically telling the event system that these are the events that were interested in with this event list and when one of these events happens to call our callback which is give you handler and basically this this whole section is in a one-shot section and what we're doing there is we define a static class ref and so if you call this particular function it's the application were to call this particular function more than once the registration what's happened multiple times so basically just turn that one shot then when after its registered and the application wants to instantiate a instance of this class our handler is then called basically as David mentioned we need to handle the construct and destructive nth and as you know don't call call next event handler here and then we'll also be handling initialized as well so and when the instance is to be constructed oh and I should also mention that we're going to be handled the handling the draw so after the it's the instance is constructed and then embedded into a view hierarchy will also get this draw event as well and since we're doing this as a see interface based method of doing this first all of the data is going to be allocated in the construct event and then we'll just operate on that data as well later on and here and this is where it is so when we construct the instant we go ahead and Malik our data now as David mentioned doesn't really matter for the purposes of this example what that data is other than that we're going to be grabbing the H I object instance and stuffing it into our data and then finally before returning we stuff a void pointer argument into the event and this is how will reference or grab our data out of out of the events as our draw and tracking and other types of event handlers are called after construction his successfully happen will get called to initialize and so in our event handler will get the K event H I object initialize event which we then call this function for and whoever's called us has set up some parameters in in the event and so where you grab those parameters out and we stuff them into our data store and basically for this example we're just going to be drawing a rectangle and we want to know the RGB value so somebody stuffed RGB values into the event we're grabbing them out here and stuffing them into our instance data and then after we use this this instance is going to be drawing these users going to be tracking all the stuff is going to happen when we need to tear it down we hit eh I object destructive event and in that case we just call our function to destruct it and we just free our data store for this particular object once this correctly instantiated you can embed it into your view hierarchy and would make it visible and at that point the draw method is going to get or the draw message is going to get sent to your instance and so here we're just very we're doing some very simple operation we're going to set up to draw a particular rectangle and this is all basically designed to have different colors whether it's selected or whether we're tracking or anything it's that particular point then we just draw that rectangle so let's actually see this in action very simple I mean so what we did in our main function was we just we registered this subclass we created a construct event and then sent in and called H I object.create instantiated object we embedded that into this window and it's the sub coffee system till the straw and that's where we draw with the context that it's given us that's basically it for this particular example Thank You Curt we can reach back to the slides well that's just a simple h I've you all of our examples today are simply not we could have written some demo to do some fancy stuff that all the focus would have been on how we did the fancy drawing how we did the fancy tracking what we chose to do instead is use the simple test h I've you stuff that's available at sample code right now you probably even have it on your machine if you have a machine here and developer examples something something if you search for H I test you'll find it so Kurt went through that but handling events like that and registering them you're doing the same thing over and over it's just you know we put some events in a list and then you go to you got to handle the event and dispatch it and take the parameters out and you're just going to be doing the same things over and over especially for event for H object subclassing all those events are always the same you're always going to doing the very same thing so it's just a boilerplate and that's kind of boring gonna be like I said doing the same things over and over we don't do that on the inside of a chai toolbox we actually have a C++ framework because this this is no fun and that's why we made a chai framework so H I framework is a lightweight C++ framework for just for doing the sub classing of a chai object and making custom h I've use and it's really just a subset of what we use internally to make our own custom eh I've used like well they're not custom for you as their system HIV is like the push button for example we use a very similar framework internally T object wraps thi object class something notable about that is T object doesn't exist in the public a chai framework we're going to be rubbing that next week and it's just something we added in and I'll show you why in a minute tvt view wraps a chive you very straightforward and there's a couple of convenience event convenience wrappers one for extracting and setting parameters in a carbon event and another one for manipulating rectangles that's my favorite I don't like doing all that finding the center in the top and the bottom of rectangles and all that and basically all you have to do is override a few methods few base methods and you will be able to subclass very quickly so there's a register class method which I'll show there's a static construct method what you have to make and that's so that you can specifically make your subclass instantiation statically and you also opt override get kind it's a pure virtual method so that we can identify what kind it is and then after that you only have to handle what is interesting to you you don't have to worry about the carpet events you just go over I'd certain methods like a draw method or some kind of accessibility method or keyboard handling or whatever so here's an example of overriding key object registered glass you can see here this only happens once so there's a static that's stored this is a this is a static route this is a static it so that you don't reregister it over and over and over you only need to register with it once again you see that reverse domain name class ID that I talked about before and yet you have to specify what the static construct method is for your sub class in this case it's just a it's almost always going to be called construct and it's a static method in in your C++ subclass here's an example of overriding a draw the draw event handler you can see that there's a couple of parameters coming in those benek conveniently extracted from you from the carbon events here you get the nicely clipped transformed cg context this is exact same drawing as happened in my previous sample code I put up here there's a bounds access ER because I have a I clearly have a reference to my tea view instance I just get its bounds and I draw it so Kurt's going to come back back up and he's going to show you that same class reimplemented using HRM work Kurt thank you so basically yeah we're just going to reimplement this using the H I frame our group which is so much easier I mean you probably saw some of the demos that we did in our sessions yesterday and we always use a chai framework for just because we it's quick right so here we define our class ID which is this is the idea that that indicates or it identifies our class to the H I object subclassing system then we also implement the get kind as you mentioned it's a pure pure virtual methods that we have to override in that so the system can identify what kind of instance you are then register class now if you remember when we called H I object register subclass there was this huge function we had to add the whole parameter list and then we called H I object register subclass this is just the same same concept but much simpler like I mentioned we had the one shot this is now all it is we specify the class ID which we defined at the top of this file and then we specify a construct proc now this is important because when the application needs to instantiate your object it needs to call something to do that instantiation and that's this construct proc which will get called so when someone calls H I object construct or create using your class ID and it needs to instantiate your object this this handler is going to get called and this is a class method so it's kind on your method so you need to create an instance of your class and this is really important this is where you actually instantiate your object by calling new on your view after that once you embed it into your view hierarchy and make it visible your draw method is called this is the same thing that we did in the previous example using C but we don't have to do all the extraction from the carbon of it earth yeah from the carbon event in order to get the context and the region that we should be drawn into it's all passed into us and then we go ahead and we do our switching and we can change the color based on active state or whatever at that particular time and as David mentioned drawing whether regardless of whether you're doing it in a chai framework C++ or NC should only be done in your draw handler and if you need to force drawing in some other places like you're tracking the control you wouldn't draw those particular points you would invalidate so the next time through the event system where it's going to draw that's it will call this function to do all your drawing so only draw here that's it so if we want to go ahead and run that we can see that this is our old sea bass one and this is our C++ label on using a chai framework it was a lot less code really easy setup and boom it's there I'd say thank you courage so hopefully that shows some of the simplicity of a chai framework I really highly recommend using it even if you make one first and see and then try one using the H I frame work afterwards it will really help you understand the concepts and once you understand the concepts you'll just you'll just love them and you really want to use them let's go over a bit more of the basic behavior that's available to override like click handling click handling has a few events associated with it first you want to hit test that determines if a point is within a part or within your whole view depends how many parts or maybe if you only have one part might be your whole view this is not time to handle click you get asked for hit testing just to see if a point is within your view could be used for other things it's not time to do any click handling it one really important and a nice point about doing cave and control hit test if you can't contrast it to doing hit testing with say a control definition is that the hit testing can have multiple parts this just doesn't just say I'm hit or not hit and that means that the the default tracking can track individual parts of your control easily your custom each of you easily and it was a little harder to do with a control definite custom control definition you can still do custom tracking if you want you just handle the cave in control track event and do your custom tracking there and validate to do redrawing whatever you want another important part of doing click handling is if if the value changes of the highlight changes you probably want to handle that you'll get a message that says that they have changed you will probably want to invalidate so that you appear different when you're being clicked or when you're being tracked or if your highlight changes and eventually when someone does do a mouse up then they do click on your view you'll get a cave and control hit event that means you've been clicked then it's time to handle Shh I framework click handling all it does is take those carbon events take out a few carbon event parameters and to do the cliq handling all you have to do then is override a few minutes if you're interested in overriding the hit testing you do the hit testing tracking is available and do the highlight change to value change overriding to do whatever you want when those change as well as control hit here's an example of overriding a hit test in t view tried to make a little more interesting code snippet this one here it goes in it it gets the bounds of my view divided into four and it tells you which one of the four quadrants gets clicked and returns that part everything else is handled by a chai framework it puts the park back into it does a set of in parameter and it goes back into the view system just fine here's an example of overriding control hit you know what do you do when someone clicks on your control if it's a simple control generally you'll just want to set your value to whatever the incoming part was say I had that four quadrant view I just mentioned well my value be maybe one two three four depending on which quadrant was hit interestingly here you always want to return event not handle there and that's so that you can let the event hit the the rest of the system handle the event and that does things like sending out the command ID so if you have a command ID associated with your view or someone else some other client of your custom view is using it and associates a command ID for it and want is expecting to receive it you have to return the event not handle there so that the system knows that it's got to keep on keep on processing it and do that for you you can also override the change handler so generally very simple you know if your value changes you want to invalidate so that you draw a later to reflect how your values changed similarly with the highlight change you want to invalidate so you know later on when it's the appropriate time to draw you can draw highlight differently and that's really quite common so there's actually a couple of auto and validation convenience bit so you can set on a view in a chai framework to tell it that you automatically want to invalidate when the value changes or when the highlight changes similarly there's also a few bits for automatic and validation when you in activate when your activation changes enable state changes or someone changes your title next kind of basic behavior keyboard handling someone starts typing this is all done through the Caye event class text input class of carbon events and most specifically is the key event text input unicode for key event you will get a unicode value that indicates which key has been pressed previously you might have been doing some Rob in handling and doing a key down or rocky down or whatever I don't even remember anymore where this is what i use to use that an H I framework you just got override the text input method one important note here is that you probably want to deal with special key so if someone presses command period you don't you might want to pass that off so cancel happens properly or someone presses enter a return you might want to you know pass it off so that the default button gets handled properly here's an example of overriding text input it's it's quite simple it's a little bit different than the other ones because you're actually getting a whole class of events here so you have to extract you have to extract the event kind out of the incoming event make sure make sure it's a key event texting put Unicode for key event you extract that's coming in so that you can act on it and then you just get the parameter out of it this example here looks a little bit different than get event parameter because it's using the T carbon event convenience functions so you get the K event / am text input send texts out of the event and then you do whatever with it and remembering to handle those special keys if you need to a last basic the last basic behavior you want that your control to have your custom view to have is to be accessible it allows an external application like both voiceover to control your app and it really is as important as the other ways of manipulating your view because someone that can't use a mouse or can't use a keyboard this is the way they're going to be using your application through this accessibility layer solemn implemented like carbon events just like everything else and there there are a few events and they look a little daunting at first because guy likes to write really long event names but other than that it's just setting a few attributes like what the role isn't that sort of thing and it's just generally describing your view so that it can be presented to a user that's not using a keyboard or not being able to visually perceive it a guy covered this yesterday morning and an excellent session that hopefully you can review somehow through the I don't know how you guys get to the sessions after they've already run I think there's DVDs or whatever coming I saw a video camera onion so if you can get up that content it's really really good and it's really quite key to have the basic behavior being an accessible view so like I said there's a class of events Kevin class accessibility cave and accessible get child a point get all attributes me get me a few attributes those are all just describing what your view is and it's just really taking some CF types and pushing them into a CF dictionary to see if array and a van accessible perform named action that's how the external application can tell your view to do its thing all of those map directly on they look it's just like a one-to-one mapping directly on to some methods that we have in T object the names are very similar you'll be able to find them easily this is where earlier on I mentioned that we added T object to a chai framework and the reason we added a tea object class is because the accessibility doesn't just apply to a chive use it applies more generally to a 2h I objects so we put them in T object because accessibility applies to windows and menus and toolbars and whatever other subclasses of a chai object and that that's the layer that we have to provide it so here's an example of overriding one of the accessibility methods get accessible attribute names there's a lot of dependency on your parent you're super super class you know whatever whatever you subclass you're a chive you from so we pass in a few more parameters so that you can allow your you can allow your parent a chance to fill in some of the accessibility information for you now what you do is you call next event handler to let your parent event fill in as much as it can after that comes back successfully that's your your turn to fill in some parameters to describe you know the value attribute or the role attribute this is the time that your your view gets to describe itself and overall that's the basic custom each eye view you just have those five basic behaviors some of them you know you might not have Mouse handling you might just be displaying a bar graph or something I you might not have keyboard handling so there's no text input but you're probably going to have drawings and I'd highly recommend having but you probably want to add a few more things to it just to make it fancy before I get into that I just like to go over some key areas so that you can make a good custom each of you I'm going to cover a opaque region what that means as far as driving performance goes as well as doing some limited drawing opaque region I'll show in a minute lets you describe what parts of your view or completely opaque and limited drawing lots of you system tell you to only draw parts of your view so you don't have to draw as much maybe not do as many calculations and in so doing be a little bit more efficient and actually there's a feature bit khi view does not draw if your view is just some kind of containment view and it doesn't draw at all if we have this bit we can be ultimately efficient as far as drawing goes and just never ever tell you the draw so the ax pake region that's your chance to describe to the view subsystem and tell it which part of you is completely opaque that means you can't see any of the pixels behind you and since you can't since none of the pixels behind you can be seen we shouldn't bother drawing them so that lets everything behind you be more efficient let everything be more efficient I'll let your whole application be more efficient it could be some sub part of your H I've you in that example I mentioned earlier where I had some quadrants with one two three four maybe the highlight change from quadrant 2 2 quadrant 3 and I just have to redraw quadrant 2 in Quadrant 3 because 1 and 4 is still the same could be your whole view like in that square we're drawing or if you're drawing a bar graph or something and the performance gain like I said is that nobody behind you has to draw if you're obscuring them nothing none of the obscured content has to draw and I think I mixed in something when i said the the quadrants there also cover that in a second with a limited drawing sorry so handling to feedback about what your opaque region is you get the key event control get region event and I can do the compare and contrast you just override the get region method nhi framework and and watch for the request for the opaque part all I have to do is report that region that's fully opaque there's an example of doing it you see the incoming parts already been extracted out for you by H I've you and you look for the opaque meta part in this case it's just a full rectangle of the whole view that means anything that's behind the view doesn't have to be have to be drawn anything that doesn't have to draw makes your view it makes your application more efficient limited drawing cave and control draw on the way and has a parameter which is a region that describes which is the dirty area that needs to be redrawn you don't have to redraw everything you just have to draw that dirty area now is when my quadrant example applies if the highlight changes from one quadrant to another you don't have to draw all of them just the two that changed so you just extract out the region using the cave event / M region handle and you just limit your drawing to that nice thing is TV draw already those have for you it takes it takes that limit region out and it passes it in so here's an example of using the incoming limit region I tried to write some sample code but you run out of space pretty fast when the font is that big so basically you would just cycle through your parts check to see if that limit region intersects the parts and you only draw the ones that intersect in that quadrant example I would just go through them and check important caveat here is that if all the machinery of checking to see if dinners this intersects and that intersects takes too long you might just want to draw entirely and not do this it might be more efficient just to draw everything and the clip will take care of it and not worry about doing this machinery next thing you'll probably want to do is add some kind of animation everybody wants animation in their views they always look nice that way because everybody loves pulsing push buttons right mm-hmm so the way you do that you don't you know install any sort of idol loops or doing anything like that all you have to do is install a carbon event a timer they called a timer function in your view subclass and does invalidation of some sort to tell your view when it's appropriate time to draw draw and that newly animated state it's important to remember to remove that timer when you destroy your view because it'll be a timer in place that's maybe you got a reference to your view and if it destroys it the timer doesn't stop firing and it'll try and reference of you that's destroyed so you want to keep track of that that carbon event timer and when your view goes gets destroyed you want to you want to remove that event timer and just to be efficient you don't ever want to animate when your view is invisible what's the point here's a full animation sample well most of it now you can see here that the install of an event loop timer during the initialization phase of my H I've you estancia shun I'm installed an event loop timer that draws 30 times a second you don't want to draw to why you don't want to do this too often this if the users not going to be able to perceive it and that that event loop timer I tell it what the static callback is and that's my van handler and also pass an instant so it can identify which of the view subclass instantiations is actually being animated later on when the when the event handler gets called it's going to be past that instance so that it knows so here's the this is this does the this does the actual animation that's a static timer static call like it's called this is a static entry point into your class so you have to extract your instantiation and then access it so that's what the casting of my view does there with the user data and then you do whatever changed in your animation you know you advanced one frame or you move something in your in your implementation however you're you're doing your animation and then you invalidate the view so that that just called an API underneath an HR a mark called a chive you set needs display and let's view system know that at the appropriate time in the event loop cycle when it's time to draw that view need to be redrawn it's also very easy to add any other additional behaviors that you want like drag and drop it's just overriding some carbon events and there's those facilities for using that in a chai framework focus handling scroll to hear other parts and bounds sighs reporting besides constraints sizing trains are what you use to describe what your the size of your view is when you're using it in a toolbar all of that I just matter of having some carbon events returning the appropriate parameters and they're all wrapped up in a chai framework and you can just override the appropriate method to get these additional behaviors lastly you probably want to instantiate from a nib one of these custom each I views you don't want to make it programmatically every time it's really easy to do that the only important part is that you have to register your view before you actually do the instantiation of your nib so you just use a the H I've you widget in I be in the widget panel it's a orange box as a chive you in it drag it into your window and you bring up the info panel and the attributes pain of that I just set the class ID to that string that we've been using over and over when we registered our HIV so class that's a unique identifier that tells a chai 20 blocks which subclass to instantiate and just go set that in there and when the nib is loaded all the construction routines are called and it's just like your creative programmatically the really important they're a really important part there is that you must register before you instantiate or else nothing's going to happen it's not a recognizable subclass to H I tool box until you register so I've shown you custom eh I views are really easy to implement it's just you know some H I object subclassing and it all uses carbon events which are familiar with just install carbon event handlers and if you use a chai framework it makes it very simple I can pop out a custom view really really fast making the sample code or making any custom pieces for myself much easier than doing really really custom UI and drawing into the window or it's even easier than doing a custom control definition it's extremely easy to make a subclass using a chai framework an HIV subclassing so what I recommend you do is go make a custom each eye view right now go download the H I frame work sample code and just make one independently of your application make something fun for yourself just so you could get a feel for it you might want to go through H I test you sample code so you can compare the capi to the C++ ones but I guarantee you won't want to do that boilerplate stuff over and over and over if you don't have to you could just override a few methods I want to see that you're going to see how easy it is to take different pieces of your applications you I make it them into custom h I've use and make your whole application use a chive you and compositing and do all the new whispering suit features that you'd need to do to come with us into the future bring application to the future and not get left behind I heard one comment yesterday someone said well I'm not going to use a chive you because Apple comes up with these new technologies and I get I get worried about it and I'm going to wait it's time to stop waiting we introduced we introduced this so you can do it in Jaguar in Panther all of our views rhi like you're using HIV already every every single system UI widget is an H I've you already everything is a chive you that even though closed box is in the windows that is it's not like we're saying we're going to do it we've done it and you have to come with us and it's time to come now by making a custom each of you a little bit more information you can hit the documents in the reference library is upgrading to the Mac os10 tool H I toolbox we've got some great information there to bring you forward with us introduced introducing a chive you goes into detail some of the concepts that went over today technote 2074 is really good if you're used to the control manager and you want to get used to some of these new HIV you ap is that we have and I definitely recommend going over the HIV sample code that's available out there go over H I framework check out some of the sample subclasses that the engineers have written and that are available to you and it'll really enlighten you is about about what you need to do next you can send za via email directly if you want to there's an email address I don't know why I have this