Developing Graphical User Interfaces with JUCE, Julian Storer, JUCE Summit 2015

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
we're going to rattle through a great speed and great debt lots and lots of aspects of the juice Gary the glasses and the graphics classes so for the first half of the workshop this is what we're going to cover and I'm going to whiz through these we probably have about four minutes on each of these topics so I'm going to blast that information at you but we do want this to be kind of a little bit little bit two-way so if you have particular questions that come up that you think's you've been wondering about things that I'm going to cover here then do shout out and we'll go into some detail but I do want to cover as broader a range of topics as we possibly can so after after after a break we're going to go in the go into more detail looking at the actual rendering rather than the GUI framework so so yeah first off we're going to look at the components the actual widget side level stuff and second half we're going to look at actually rendering that stuff to the screen and all the way long I'm going to go through some examples and and do some code and I'm going to try and for each of these come up with some little tricks and tips that you guys might find useful that a lot of people even even people I work with on the team sort of sort of surprised by these little hidden hidden secrets in that so let's get let's get started so first of all we're going talk about the component class or it could class itself this is the basis for all of the the juice GUI GUI components and it's a big one so this one this is one of those big old classes it kind of has to be but actually what's what's inside the class is pretty it's pretty minimal let me just get this on the screen this is the dista api reference for the component class hundreds of methods and let's I'll talk through this and we'll I'll do some of the other examples with maybe set a bigger font so the basis of component you have a hierarchy of components we have parents with shop with child components inside the child components are clipped to the area of a parent and they'll generally laid out by the parents parent will have a resized method which you ever ride I mean I'm sure half there it actually can we have a show of hands who's actually written some juice GUI classes yeah pretty much all of you few few of you haven't most the disk repo is pretty much like any other frameworks the Java component class or the cute or whatever other kind of frame we all have the same kind of stricter which is a component or widgets or a view and that has sub views within it the juice component classes is that generally the important methods are resource method that you override and a paint method where you draw the thing the in terms of ownership is quite important to note that the component doesn't own any of its child any of the children you put inside it so you have to manage that stuff yourself generally you do that by having member variables within the cone which I was going to show you but it's kind of blurred um let me let me try again that's some so example component this is actually really the producer but doesn't have to be paint method draw something this is a hello world so we're drawing that I've come into the other set out for the moment I'm not going to go into detail over this most of you know this and those of you don't but probably use something similar talk about clipping and repainting of these things what happens when you when you have a child component with a chunk of power only the the bits of the child that actually within the bounds of the parent get get repainted so you can use this as a view we have laser as a sort of scrolling view we have a viewport class which does that so that initially let you scroll things around inside a parent or you can just use it as a way of collecting together a group of component moving them around when you call repaint on on the component this is always asynchronous and it's amazing how many beginner beginner questions we still get where people I expect to be able to say to actually dynamic before something to be repainted as soon as they want to soon something changes so that we they'll have a component which draws something in its and a value or some sort of shape they'll want to change the shape and they'll expect that expect cool something and make it repaint right away but what happens in juice and other frameworks is when you call a repaint method which it basically invalidates parts of of the component and a bit later on on the message thread it'll come around and it'll it'll repaint everything that's been invalidated recently and you generally the OS will do that at a higher frame rate as it as it can as you can get away with opacity is quite an important thing to think about when you're when you're creating your component layouts if you make a component opaque then it's going to be it's not going to have to draw the things behind it so if you're if you're doing some pretty complex GUI within the larger window and this bit of goo is updating very very fast or very frequently and you've got stuff behind it if you can make the sub the child fake then you generally should because then when you call repaint on child it wouldn't have to filter that call back it up to the parents and the parents will just never never actually have to have that pavement that's called what's I'd like to show you it in terms of laying out the children there's a little little trick I want to walk walk everyone through which is quite we have fun with around the office because it's um it's one of these mice one of these things that when I show it to people they sort of it's it becomes obvious and I hope you're going to be able to read this was trying to see some live coding here ah I'm just going to mirror my display so I can so I can actually read it too okay so here's a hello world component I'm running this in producer just so we can see things updating when I change it this is our hello world down here and here's the code that lays it out I'm going to add a handful of herbs a handful of child proponents to this it's like we just going to add some text buttons and what we should see is that when it compiles power okay we've got so here we've got I've added some text button text buttons as member as member variables I've either been in the constructor to the parent and in the resize method I know Nancy laid the lady's things out so what everyone sit naïvely does when they start this kind of programming is though your Stu button ones that set bounds 100 comma 100 you'll use for integers your lay things out with absolute coordinates that kind of thing and then then you need a more complicated layout so you end up coming with big expressions to say oh this component goes at the X of this one minus the half of the width of this one but a much more elegant way that you'll see used throughout the the juice Coast code base now if you search through for some of our resource methods is to start with a rectangle and then chop the rectangle down and it's one of these things that once you want to sit down you get our I get that and you end up with much cleaner more readable code so if I want to lay out these three buttons so the top one fills at the top half of the of the parent and then put the other two below it spread out then what we can do is start with a rectangle are just here I have John makes it even bigger most why I can remember how my font size is set let's make it bigger so we start with a rectangle which is the parent bound and then we'll chop bits off it so for our top button let's let's actually call this method removed from top which actually moves a chunk of pixels from the at the bounds that we started with which is the whole the whole thing so it's remove 100 pixels which modifies actually mute mutates the original variable our R and returns the bit it's chopped off so then what we'll see is we've got our but little top and that's left the original rectangle cut down a bit and we can take more more chunks out of that so we can take a bite out of its left-hand side and then that will give us that bit there and then for the third button let's just use whatever is remaining which is which is now R and then that will look like that so as we as we resize this you can see it's we've got a fixed size off the top and pixels off the left and this is actually a lot more readable reads as what you're trying to do so give you some pretty interesting and complex layouts with good that with that technique another another trick might be that say say we wanted to do it the other way around and we wanted to say take a chunk off the top and put the two buttons in there and then use whatever's remaining for our for the rest of it we'd say this all would take junk off the top and we might call it top section and then we take chunks off our load temporary variable top section you might take it take junk of its left and then that's our next button to the remains of the top section and then whatever's left goes becomes the other one and you soon see the result should be if I can find the window and I would say we take a top section by chopping it off the whole thing then we sub sub chop out bits of that and then whatever is left becomes the next one and by kind of stacking up building up shopping and having subsections and chopping bits houses and this is a pretty pretty clean way of expressing what you're trying to do it's also quite handy if you want to indent these so if I wanted all these buttons to be slightly indented then I would just say indented by say 10 and I sorry not indented reduce and my own variable names my method names so let's just release all of these after they've been created and then you can see them all popping in gray on gray on a bad projector okay so some worry about how you actually get events in and out there are several ways to get events from a component the event the kind of events you want are mount events key events and and if types of event that you generate yourself so most of usually you'll stop wanting some Mouse events so for that you can either overload the set of mouse mouse down mouse drag ourself operators or you can attach a mouse listener which gets the same callbacks but you can actually listen to any component let me quickly show some example of that let's have a mass tournament always but override on the end it'll save your life one day so on a mouse down let let's set a flag so let's call it clicked so when we get clicked we will set clicked true and let's repaint so that way synchronously then cause repaint and then in or paint method we could then say let's paint ourselves with if we've been clicked then let's have a huge font otherwise we'll have a normal fun so now if you look at this this class I click on the background suddenly becomes huge we instantiate that overrunning Mouse down is and massive answer is a great thing to do if you building a really custom component but you've got to be careful of using these when you're using other components so if you took your site a button and inherits from a button so you have a subclass of that and you shouldn't really go and overloading any of these functions because you're bound to break something because those base classes are going to use these these callbacks themselves to actually do important things so if you're really really confident you can override it but make sure you call the superclass from inside your method a cleaner way of doing it is to add a mouse listener to something else because then it's you know you get the events as well as that component being able to handle them when you get mass event another thing you'll find yourself hosted at some point will be to filter them out so you may want to have a component that's a funny shape if you want to make sure that shape in gets clicked when people click within it then you're going to need a hit test so that's quite easily done with a method that takes election the why if I race it today I would make it take a point but this is old old code and so for this example opponent let me just make it return let's say it only gets clicked on if you click on the left hand side of it so that would be if the X is less than half of its size so go back to that but and so now if I click on the right nothing happens if I click on the left we get that huge hello world quite often you also find you want to write components that don't get click this all but just overlay so you might find yourself building something that's just adding a transparency layer or which contains other components that are moving around over something else you want and you want the things behind it to be clickable so you need to do that with a hit test that returns false or returns some checks whether it's child components or under in the way and returns true if you hit on one of those or you can just call a component method which is set intercepts and mouse clicks so let me let me make this component over intercept nothing actually handle nothing at all so this makes this component now entirely unclick Abul including the children so I can't even click on these buttons we also now have as induce before we have mouse forced touch so when you get your mouse event in here I don't have a forced touch device but the mouse event class now has a pressure a pressure parameter and that'll also pick up pressure from Windows tablet pens as well if you need a mouse wheel that's that's the same same kind of thing you get a mouse wheel callback and the set of callbacks Mouse down mouse up these are all so that's a question no question questions are welcomed Suzy feel free to interrupt because we want these but yeah but we do want these workshop speak to be pretty pretty interactive so if you guys have I mean the rest of the day is going to be talks this is more like an opportunity for you guys to say hey you're talking about something that I have a problem with or I'm interested in so do shout out and we'll we'll go off at tangents yeah question yeah that's and question the question is can you allow messages to go to components behind something else but get messages to both of them yes it's it's one of the things that it's actually one things I was gonna mention is a common mistake which is a lot of people will naively try and do that by overriding there they'll override the mouse down or Mouse out in the in the object this at the front and then they'll call Mouse down or Mouse up of their parents so they'll write something like get parent component arrow Mouse down which will kind of work but you will always end up with some little edge case where the parent doesn't get its Mouse down up drag ENTER leave events in the right order because all of these events go through when they delivered correctly by the operating system they go through a class called the mouse input source and this basically makes sure that whatever sequence of it clicks and up downs and moves come in they end up with it you end up with your component getting a sensible sequence so you're not going to ever get a mouse down and then a mouse exit without their being in the mouse up in the middle whereas if you start calling directly Mouse up the mouse at enter and leave callbacks then you could end up telling giving a component at a strange sequence and they get into a strange state and you have bugs that like but to go out to the question yeah you can attach a mouse listener to the one in front so the one behind would get its own mouse clicks but also most pics from the the component in front which would probably do what what you're trying to achieve that or you can just make the one in front ignore mouse clicks if that works better and then deal with deal with whatever that should do when they arrive at the back so it depends on what you're doing really there's lots of lots of ways you can type all that so yeah don't leak them don't work yeah if you if you call if you yeah the question is if you if you have a text button and call that insert mouse clicks false on it then yeah it won't work it can't get any event the events will go through to whatever was behind it yeah and one other point I want to make on there is if you need the global mail system we the desktop class is a place to look so it has there's a global Mouse listener callback class and you can attach one of those to the desktop and it will call you whenever anything happens anywhere which is kind of useful if you want to do things like detect when the the user has moved the mouse to wake up or that kind of thing yeah mm-hmm if you have a question if you look if you have a list box in a viewport and you scroll inside the list box in the viewport at least on Windows you get like a double scroll right because I think it's because you like destroy one of the mouse wheel events keep one of them because of some scrolling issue on Windows I don't know why but okay the way it's supposed to work there is that the mouse wheel event will go to the child component which will be the spot and if it wants it it uses it but I think if it if you get to the end it then passes I can't rehearse but the idea is it would pass it up if it if it doesn't use it but maybe there's maybe there's something not working that I think it's not kind of for maybe each case maybe I'm having some trouble with that you're not plugging okay we'd have to I just have a look at that in its the idea is it would pass it on if it doesn't want it so if you if you scrolled and it can go any further it should pass it on yeah but it's gross both of them right with one scroll okay maybe once attached as a listener I it's it's it it's very specific I'd have to have a look at so keep keyboard short key board events and shortcuts work in a slightly different way they you have with those you have a focus component and there's always a foot one focus component per window and there's only one focus window and when a key event comes in then it will be sent to the to the focus component if there is one and if that doesn't want it it passes on to its parents and the unlike the mouse mouse events the key event the key callbacks have they return a boolean to say whether it actually wanted the event or not so they can kind of turn it down but you can also attach key listeners so quite often you want something like a situation where you want everything that's every key that's pressed to go to one particular callback because you're looking for some strange application wide shortcut key so to do that you generally attach your key listener to the to the very top parent and that would get called when nothing else wants it but you may still want because you may still want that key to be used if it's saying if you have a focus text editor you might want that to get the key but if that doesn't want it then you want to make sure that you get everything else that's not used so you can look for your special key we actually there's also induced we have a quite large set of classes around the application command where we have application command manager and application command target which let you set up sets of commands which you attach to particular targets now this is a huge topic I'm not I don't have time to actually I can spend an hour just talking about how this works because you have to register command and then the commands can't describe themselves and then you have menus and buttons that can give them a command ID and they figure out from that what they should have in as text and it's a complicate our --get I've complicated them thing too to implement if you want to actually see how that's done the the introducer is a good example for that because that has lots of that uses this for all of its shortcut handling so it's probably easiest if if you need that kind of applicate application type shortcut behavior to look at what that doesn't and to copier gotta have my notes on the screen now it's working on one screen now so yeah I learnt about custom commands or custom looking feels in our little hello world here I'm just painting and this is this is kind of the easy way to get started with doing a custom component you just override it you do paint easy the other way to do to customize things is with the look and feel class now the look and feel is a huge class with many many methods that draw different types of components so there'll be classes to draw a button to draw a slider to draw all the bits of a slider draw every kind of pre-made widget and if you look inside something like a text button paint it will just call it it'll find the current look and feel and it will call a method on there to draw itself and that means it globally or for a particular window or for a particular component hierarchy you can replace all of the drawing with a customized look and feel that behaves in whatever way you want so that every button in your app uses the same paint method you don't have to oh and even if they've overridden special special other things in their button in particular button classes those still call your look and feel there are hundreds and hundreds of methods in there that you but generally when I when I tend to do custom look and feels you'll end up implementing maybe ten or fifteen methods to do just the bits you're interested in which may involve drawing some backgrounds drawing some buttons drinks of sliders and there's some examples of that in the juice demo which shall fire up so here we've got some some hard to see blood components which which have some custom look and feels and we can just swap through them and it it means you can do very very different behaviors very different looks without having to worry too much about actually handling the the input methods differently whether you choose to do a look and feel or whether you choose to do some custom components it kind of depends on what you're doing so it's if you need to customize buttons and look the look of things which are in say dialogues internal dialogues like if you need to customize the a lot of you will probably be doing audio stuff so you'll want an audio device selector component which has dropdowns and lists of buttons to turn on audio devices and combo boxes and things you to customize that it's very very difficult to actually write custom versions of all that and build it yourself so you just write look and feel and attach it to the component that just gives you and you can make it look however you like it's sort of a pro tip about how you structure your components like quite often I see beginner code where people will start with a big custom component and they'll draw some things in it so you'll see this often with a lot of people imagine you're writing a step sequencer and you draw a grid and you've got a paint method it draws a grid and then you fill in you have an array of where the jump beats are so you stop drawing blobs in your grid and then you say well okay we need to click on these on these on these blobs so you have a mouse mouse down callback and you say Oh which blob as the person clicked in so you then turn things on and off and when that happens you need to repaint so you call repaint when they turn the blob on and off and you very quickly you end up with this huge component that has a whole user interface within it but it's all being done in a repaint in the paint statement and then you start hitting performance problems because you can't repaint the whole thing each time that something small changes so then you repaint bits of it and it's important to know when the point is to say okay stop break it down into sub components this grid should be not a grid of things that I paint this should be a grid of child components and each one of those needs to know about what it's trying to do and then you have to balance that against performance sometimes because there's a small but but nonzero overhead of having a bunch of components so if you have thousands of items on the screen scrolling around then you might you might not want to make them components but there are tricks and tips you can use to really keep that overhead down so you can still break down your user interface into a good granularity of things that think self-contained objects that that do a particular task without that the responsibility for that behavior leaking out into a bigger class and still get some good performance I'll talk more in the second half of this about actual graphics performance and how to how to speed these things up and keep the overhead down especially when you have a component paint method so actually painting for set painting using clips is a good pro tip for that one let me show you I could do a live example of that if I have let me quickly creates in this example a child component which I'll call a blob and in my blog I'm against the other thing but paint um I'm going to fill it with a color always sleepover ride you take nothing else away from this this conference it's it's important so we'll fill that with red and I'll add a blob and I'll add the blob to my user interface and we'll put it that's it I'm just going to type some numbers in here rather than trying to be more elegant so I'll just put it at an obvious place so there's our red blob now whenever that red blob gets repainted what will happen is the first of all the background component the parent component will get its paint method call then it's time to draw the sub components for each one of these the graphics context object that you're painting into will have to be clipped down so before the the red blob paint method gets called the graphics object that it takes will have to have its state messed around with now if you have one objects on one component screen you'll never notice the overhead of this but in bigger apps like in when we're working on traction you have a whole screen full of tracks and clips components scrolling around doing very lots and lots of deeply embedded hierarchies the overhead of just clipping the graphics letting that thing draw itself and unclipping it starts to add up so we added this set painting as unclipped flag now what I'm going to do here is I'm going to call it on blob you'd normally do this in the constructor so I'll give a little constructor here for blob and in there I'm going to call set painting is unclipped and this is going to ruin our user interface it's not going to work anymore because now the whole thing is red what this means it's kind of a pro flag you can call it says like I know what I'm doing my pen retain trust me I'm not going to draw outside the bounds if you do you're going to get all sorts of nasty artifact painting painting going on because it's not going to bother clipping this thing before you actually your paint method gets called so if we're going to be a good citizen and do this correctly what we then need to do is set color and only fill within our bounce so it's quite easy to do I can just do a full rect of our local bounds and it's a bit more typing but actually it has the same effect and if you have a thousand of these being painted it's pretty much like calling Phil Rex a thousand times rather than a thousand times of clipping or graphics context letting some something figure out how big the screen is trying to do that drawing only the clip bit of it then on clipping and these graphics come to us a pretty heavyweight things they've got a lot of state inside them so this this actually can be the difference between an app that works smoothly and doesn't work at all yes yeah what's the difference between you get local about it get about question is what's the difference between get local bounds and get bounds get local bounds returns the bounds of the component relative to itself so it'll always have a zero zero position get bounds returns the position of the component within its parent so for for example here of the of the Red Square if you call if you call get local bounds on this it will return naught naught comma 100 100 or if we call get bounds on it it'll be 50 50 100 100 because it's at 50 in its parent so when you're within a resized method or a paint method you're generally going to be cool and get local bounds because you're not interested in where you are globally you're only interested in what's going on within your little wind over your own coordinate space sorry zero zero is actually 50/50 from the plug-in screen yeah right yes absolutely and I'll show you if I if within our blob which is the child component if I then I'll paint it red but then I'll draw a blob it inside it I'll draw a a blue blob and I'm going to draw this blob at ten come at ten ten ten that'll do so it's ten ten within within the blob itself the red thing and your series in the corner so as the as the red thing moves around which I can which actually I can probably do in an impressive way using the producer here oh is this going to work yay okay so so so as we change the position of the child component the blue blob which is really not very easy to see here but that's obviously all relative to the thing you're drawing and so when you're when you're inside your paint method or when you're inside your resize method you don't have to worry about where you are on the screen you don't have to worry about how you're transformed or anything like that fixes like pre translated everything everything is just done for you so you just work within your your little space and the only thing in this case because I've turned the clipping off I have to worry about not doing outside my space but the coordinates are all the same you also talked a bit now about other ways you can mess around with that coordinate space because we can add an affine transform to these things that could be used to rotate and do crazy things to your component and again that all happens to the coordinates space before you get to paint into it so if I want to rotate this red blob a bit then I can add another find transform which I'll do to the to the blob I'm going to set transform a rotation of a bit think that it's a compile yep so there's our rotated blob but the blue blob with it the blue bit within it is still everything's still relative to that and even if I scale and squash it around everything just moves as if as if you're taking the image of what you've drawn and you're pulling that image around which might actually be what's going on behind sings and transforms transforms are great for doing things like rotations and scaling of a component it always messes with my head when I try to use them for positioning because a component has a bounce so it has a position within its parent a rectangle where it lives within the parent and then you apply enough own transform that as well and it's kind of it's really hard to to picture mentally the combination of those two things so if you're scaling everything right down then does the rectangle the bounds works and will change and get scaled down or does that happen afterwards it's it's easier not to just keep everything flat and maybe right if you really need a rotation then do that and I'd love to explain an easy way to to actually do do that but it's it it's one of these things I generally when I do it I generally add the affine transform to see what happens and move it around and until it looks right but it can be really useful technique if you need to rotate things and show things yeah different different scales like we actually use our find transforms when you're running on when we have to rescale displays so on Windows and Linux where the where the operating system doesn't do the rescaling for you on high DPI displays then all the components are getting rendered with our fine transforms but they build up so you can take so questions yeah everything be everything will be all the mouse input and any any other numbers that go in as a component are translated in and out so when you're actually working within the component itself then you don't have to worry about where these things came from which origin is it rotated around its the let me get this right it's it's the parent origin so the bounds itself will be translated so if you have a component that's translated by OC edge scaled by 1/2 then as you said its bounds those numbers will be halved so it's one of these things is really hard even to pick even to draw a picture of but so it's kind of I tend to stick to six keeping things flat until you really need to and then when you do a good tip is to is to once you start using fi transforms you use it to actually position the thing as well as scale it will rotate it so you leave your the bounds of your component at zero and then just use that find transfer to move it around so use the F own transform to scale rotate and do everything in one go because then you can just it's just about manageable to get your head around this stuff and that's only 2d I don't know how 3d would would be but yeah the affine transforms build up as well so if you have a transform component and you put another one within that and they both have a transform then everything obviously yeah yes gets transferred all without so so the one inside this doubly transformed but the mouse yeah the Mouse events all come in out as you'd expect so in fact you can illustrate this here work if I am if it if in the case of this component if I didn't that's why so in my answer component here which I'll get on screen I'm adding the blob and I'm transforming the blob if I just look at blob on its own which they can do here I can just pull out there the blob as it as a separate window when you went as far as the blobs concerned that's it's flat but it's only when the parent decides to add it and then transform it that that becomes that instance becomes a transform transformed instance so we're doing well for time we're going to have a break in about 10 minutes 10 to 15 minutes and so at the end of it there are topics that people have that you want me to go into in more detail or things you don't think you don't get all I haven't covered properly anything component related really look and feel should we do some some more talking about that okay let me let me get up the look and feel class looking for your lives in juice GUI basics and the base class ignore those the base class is very ugly because what it is is it's a conglomeration of all of the different look and feel abstract classes for all the different things it has to be able to affect now okay I wrote this in 2003 if I raise it today I probably do this slightly differently but this is the way it and it works pretty well because it means that you write one class which implements your entire user interface look and then you can just use that everywhere but what it's actually doing here is it's saying in each of these looking for your methods types are if you go and look at one of these info saya it's all tick window it there'll be an abstract class here which has a virtual method which draws a tilted window and then somewhere further down in here there will be an implementation of that not in the base class but in the one of the actual implementations of this so we have we've got three at the moment we want to do some new ones this year I want to do some new snazzy-looking feels but at the moment we've got v1 v2 and v3 and like Italy too so if we wanted to look at our tooltip window that's not in that and v1 or p3 it's in one of these okay hidden somewhere in here there's a draw there'll be a draw method for whatever you can think of so here we've got some draw some stuff to a scrollbar and all these methods get it they don't need to really know much about what they're doing they're just told hey draw me a scrollbar here's a graphics context and it will draw a scrollbar if we look in an implementation of one of those they're generally pretty pretty gnarly things so this is something cause an old-fashioned scrollbar button from our v1 look and feel and it's just adding some triangles sync some colors and it doesn't really need to know anything about what the components it's drawing it's just interested in painting it what you can do when you're doing a custom liquor feel is you generally start with a look and feel v1 or v2 or v3 and then you'd override some of the methods yourself so if you're only interested in buttons you just override something that draws a button so it'd be a draw button in here somewhere draw button background and this is just drawing like an and all this is v1 so this would be like it when there's old mac style was ng buttons being my owns a nice flat 2d button and so you just implement that and then you'd set you create an instance of your look and feel object and you globally set that and then it would just be picked up and used by everything when when the component needs to look and feel object to use to draw itself the component class itself has it get like a feel method and that will if you set one for that particular component it'll return it otherwise it'll ask its parent hey what's your look and feel if that doesn't have one it'll pass that up until it finds one and if it doesn't find one it'll ease the global one so you can have a window with one look and feel but a little subsection of it that has some model can feel it's it's quite straightforward when you get when you get going and you only have to implement a bit you're interested in that answer your question with looking feel I think I'd probably break it down because when I started there wasn't a lot of wasn't a lot of types of widgets so it I put in one class but actually what I should have done is had a look and feel is a collection of other types actually no better answer than that if I think they are Duke with lambda and you just set lambdas for all the looking fields which would be quite neat any other some of the would widgets might do that I can't think of any of it do because most of them don't need a custom hit test the thing about looking field is it can only add functionality to a component if if that if the widget itself wants that if you see it you can't you can't use a looking for to force a button to have a different hit test but unless the button itself has a hit test method but calls are looking for answers hey I'm going to pass the responsibility for this on to the look and feel it's used it's quite a passive thing it's used by components when they need to do something if you needed a button that had a particular looking for and a hit test you probably have to implement your own button subclass but some of the other types of widget might that's what I can't remember but some of them might neither hit test so they'll they'll they'll have a function in the look and feel which is a hit test callback and then you can implement that if you need to if you need to do it but um yeah doesn't ring any bells I don't think there are any that need bad oh yeah that's a good one yeah yes yes fine color that's that's a good one to explain because that's that's a little little bit complicated um when you need colors say we have a text button and text button has a color now we have a look and feel to draw that but you also want that to be customizable so you might wants a whole bunch of buttons on the screen and you want to set the look and feel for everything but you actually want that button there to be read so for that kind of purpose we have we store all the colors in in a propertyless so we have name IDs for colors and then a way of looking up what color you should be using it in a particular context for a particular color ID so one of those IDs will be a text button color which will probably be I'll find an example in here so here we go so the look and feel itself has a base cluster look feel has a list of colors and so an idea in the color a component every component can have a list of colors ID in color like just a map basically when something needs to draw say you when your text button needs to draw itself and you know what color it's going to use it first of all asks the the components itself sees if you've set explicitly a color within that component that overrides anything else and it does that by calling find color which is a component method if the find color find finds that you haven't actually said anything explicitly for that like vote then the last the look and feel hey you know get me the color for this and looking for yours do have a set of default colors it'll also pass it up the parent hierarchy so you can set so if you have a win window with lots of buttons in and you want them all to be red you can set a color at the higher level to override that color ideas red so there's a whole chain of lookups it'll go through when it's trying to it's trying to figure out what color to use so yeah question yeah my question will be we have those of components the other custom 11 cars mm-hmm would be very brilliant is that I would the introducer juicer for you 11 school they can define a balance and give them IDs mm-hmm so whenever I use those colors right and if we want to change all my 100 components to have a different color I only change that ID instead of having to go to all those who want this color this color right now it's impossible to use my own ID for typical let's say I make my own color and our sample s IDs right instead of when I you get the code if she said it for specific billion set a specific color this is hex hex value right I don't want to be a hex Telangana we might be five or so whenever I change if I met my application I decide I want this color to be this color then it's all I think just done right now is I get all these hard coding hex values and also to work with okay Oh hard to explain yeah maybe maybe you need to show me that one if you have this little pearl at one day - did you make your own colors but whenever you set them they will set in or xl1 my arms so that is the basically top you have colors right there which is just yep that that's that's so that's a comment I come on wait to to have custom colors for custom components not for not for the built-in ones but for custom ones you would tend to have like a namespace or a class that has a bunch of named colors within them and it's easy to read that way what you're asking is more like make my GUI in yeah yeah so he's talking about the introduces like GUI editor yeah yeah I can't switch do you yeah because all the colors are hard code what I want to do is that if I make my my component shoes I can say this is it this is the polarity I made yeah I think I think what you're hating do really really business is tons of time because now you make your core which is over right loop of you yeah I I think what you're hitting there is a you're coming up against stuff that the introduces GUI editor we sort of never meant to do so but we could boot but you know we could it it could be extended you know that yeah you can make you yeah yeah but yeah I mean there any number of its when they're bit not did that three months this this these workshops they can be feature requests they can be maybe maybe not bug reports but you know but this is it we want this needs to be kind of open so yeah feel free to you know tell me what you're after what's not working for you and then yeah for the rest of the day will be lecturing at you about what what you should do this is more your opportunity to to be a bit more interactive so yeah fine color it's quite a complicated process that goes through but it does give you lots of places where you can substitute colors yourself I mean maybe for what you're trying to do you could have a look and when you create the when you actually create your objects you could set have something sets all color IDs yeah I mean I know in the second working yeah so disgusting code below your generator yeah it sets the college for all those buttons yeah if you use your own be fine excuse well sure yeah what I get now is very okay just happy comma classes I have a pollen replace function replace this hex value with this one for whenever you have counter a color with this value replace it with this yeah it's sort of trouble sometimes it's constantly switching okay but I just yeah we always find a way of constantly having your own defines yeah okay second board so we're aiming for 1010 it sounds like you next door they're having the break now so any quick quick questions for a couple minutes before because next after break will I want to get more into rendering engines actually drawing shapes and how all that stuff works behind the scenes right so yeah yeah yes sir I'm not sure if it's a quick question 0 adviced way to when creating custom components like you said like a row of buttons or knobs and stuff like that and they need to propagate their events to to the to the parent component for instance is there a advised way to do that or illustrated way it depends on tell you what you're using for I mean if and what kind of events you you want to pass it pass I mean it'd be very easy for them to just get run through them and Mouse listeners to each one and have all those Masterson's calling the same place because then when you get masters in the callback you can tell what component by look at the event you can see where it came from so if you have a thousand components and they all call the same function you can then you can look in there and say oh it was from component number 20 and then do something special I mean that that might be appropriate or it could be that you just write a special class for them and make them deal with whatever they need to deal with internally it doesn't there's no generic answer it's kind of depends entirely what you're doing thank you you
Info
Channel: JUCE
Views: 27,234
Rating: undefined out of 5
Keywords: Julian Storer, JUCE, Graphical User Interfaces, Workshop, tutorial, C++
Id: xsCZoE1s_uw
Channel Id: undefined
Length: 56min 7sec (3367 seconds)
Published: Mon Mar 21 2016
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.