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