WWDC2003 Session 424

Transcript

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