Build modern GUIs fast with Projucer, Vlad Voina (ROLI)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so my name is Vlad Voina I work for Roli I am a software engineer and I tend to spend most of my time writing duties as Tom said it's quite interesting I'm also a Goldsmith student so if my voice is a bit shaky it's because I'm nostalgic not not because I'm nervous so so yes I'm going to talk about building modern gooeys fast with producer it's quite a long title but it will hopefully make sense by the end of this talk and the first thing I want to address is what do I really mean by modern it's quite a subjective worthy word these days like what I really mean is a few things so I mean a vector-based graphics that is essentially not bit bitmaps which I'm sure a lot of you are used to and it's still a very common practice in DUP in the plug-in sort of like interface design so what we what we tend to do here is we we tend to have parts and primitive objects that draw rectangles and circles and we we use that to define our interface which obviously scales better and it it doesn't depend on DPI and all these kind of constraints that you have with beat maps and I'm sure you've suffered a lot from using bitmaps another trait is they are responsive and dynamic so that means if you resize your your plug-in window your interface should adapt to a new size and by that I mean look nice not just clip at the edges and it should also maximize screen real estate so again it's not just about shrinking everything or zooming everything down it's about maybe rearranging elements so that it it uses space a bit a bit wiser and there's another thing which is animations and transitions I know that is not still great in juice so I'm not going to cover that for now but maybe the future so here's two examples of nice flat UI ones and I form and the other ones a proper heads figure but I'm not going to get into any details here I don't want this to turn into a design talk it's it's not about that but just to give you a bit of an example and this thing that you've I'm sure you've seen before we've coded it with these traits in mind so I'm gonna quickly demonstrate that guy this what I really mean so this is the noise interface for a for iPad it's got these elements at the top it's quite a lot of them so if I start resizing it down at some point they disappear this is all done dynamically in the resize meter there's no is very little ifs and changes of logic it's not at all switching views it's it's dealing with the lack of size here so it's removed a few elements but they're not gone completely there's this little carousel now I'm not sure if you've seen that you can now slide and if I increase it again as soon as there's enough space they come back in that's one thing the other cool thing is this so this is a very common example now a lot of these things if as any of you here done arm web development yes so a lot of these things will probably seem like a joke to you but in in C++ world it's not a joke and so hopefully you can entertain so we've got six elements here as soon as I reduce the size boom it goes into one one column if I make it big enough it's gonna go into two rows so that's pretty cool Bango yeah this is another interesting one so plenty of space there for a vertical column to show items as soon as there is no no space which is layout and now shrinks and doesn't it's not very usable at this point but it doesn't look that bad and I haven't seen a phone that looks like that yet so I think I think we're fine so before I start showing any any details I just wanted to address this question because some of you might be wondering why even bother man like this other languages out there that are just much much better at this kind of stuff and I agree I I definitely would seriously consider not using C++ if I were just starting a new project but as chef and said previously C++ is the most widely used language so I'm sure a lot of you are using C++ so I'm not going to here sit here to convince you to use C++ but if you do use it I've got some pretty good tips so and if you do happen to use it there's some some pros as well right so it's just simpler to think anyone want a simple language simple language but one one language at least you don't have to switch languages and you know change your the way your mind reads code and stuff and then you can have one uniform code code base set one coding style everyone can quickly follow up on that this is a tricky one so it could be easier to hire and train I think if you're a small team and you've got just a handful of developers that are quite proficient in C++ it'd be quite good to just quickly transition those some gooeys if you're a big company then maybe that this is not a great idea because you you might want to hire people that are just focused on one simple declarative language and can just write that very very quickly so yeah there's a few other benefits you know overhead dealing with managed and unmanaged code and actually C++ recently it's becoming a bit more friendlier so you get like slightly better constructs that make maybe the language is a bit a bit nicer so yeah that's I think at this point I'm gonna start to get some cohdon so how many of you here have worked with a designer at your professional business like a proper design like no you know like I mean like someone who just does design it's fun isn't it so this is a very common example right remove this text a bit just a bit just a bit below all right can you move that above and then you do this a few times and you know I think this is the main cause of hair loss so yeah and it's not this is not their fault right this is not their fault they have to do this this and designing something that works and is beautiful is an iterative process they have to try quickly prototype quickly so your job is to react quickly it's not to blame him for changing his mind or or stuff like that so what we end up doing is we end up being pixel shifters so this is a common flow yeah you find some relevant code you get distracted by some adjacent logic obviously and you know it takes a while to familiarize yourself with without code and then in that process you refactor it a bit because you just want to make yourself feel better a bit and then you just realize that that was actually the right to label that you wanted to move oh and then you have to go back and do the same thing again and eventually you find it and then you make the changes and then you build and wait for it to build and then you run it you navigate to the to date to the part of the interface that you've changed and this could be like deep in menus right and you make a change it's not quite right all right it's it's never right in the first time you need to do it a few times and go to this process a few times and it's just yeah it's frustrating yeah so I wanted to suggest a slightly better workflow and I'm gonna go straight to producer to that to do that nice make this even smaller so what I'm gonna do I'm gonna have this is just a little actually this is not just a little this is actually noise for blocks so you're seeing here a real-life example of what you've played with actually following this this pattern so say I want to go to actually I've got it right here but just for the sake of this I'm gonna find it here shows up on the screen there we go yeah so this was this is the little project card that you've seen in that project view and I can resize it here I can see how that looks I could also code and let's say I wanted to make that gradient slightly wider seems to be how that looks say I wanted to turn the content around so that it's actually reversed I've got this so at this point producer starts building again now this is not very very fast at this point it could be much faster and that is because we include everything in one big header file which is what short stefan would cut my hands for but we can we can improve this and so eventually it builds and here so that's slightly better right so you find the view in the producer live components list you change the code you see change you did this a few times obviously but it's much faster than having to go through a project and then you know you get to live longer because yes just wasted time so there's a few things that you need to do before you can you can do all of this it's not it's not something that you can just quickly just just do it with large-scale project you have to a few rigorous guidelines you have to follow so I'm going to go to a few so I've got this little code example here I have to say it's been quite hard to find like a code that fits on the screen and kind of demonstrates all the bad things that I want to talk about and then the good things as well obviously so this is a bit it's maybe not the very practical example but I hope it makes sense as I go through the cases so the biggest problem when you want to modify gooeys and do it fast is this doesn't have to do with anything but just bad code so bad code is bad there's no other way to say it and this is a very huge topic like I could spend days just talking about this and there are actually better people to talk about this I don't if you've seen Jules's talk from from last year that is huge there's a huge it's a huge subject but I'm just gonna go through a few very common things that I've seen there some of them are minor some of them are less minor so let's look at this bit slider one slider to slider three top slider I'll play names that to that you know it's just difficult to know which which slider is which so you're gonna have to run this and I don't know how you find out and what's even more complete what even more difficult is that what used to be so this is called the top slider but actually in the meantime it's changed so now it's at the bottom and this happens you know someone will come and they will need to move in and don't forget to rename that variable so it's yeah it's you're gonna waste a lot of time I think these are slightly better names so coming with more contextual names that you know are not going to be affected by layout changes is gonna make your life much easier here's another interesting fact so I'm using this is using skull pointer this is something that I see a lot these don't really need to be Scout pointers we don't need to create these you know in this kind of fashion that we have all the dependencies all the resources ready when this slider is created so why not just make it on the stack simple like that and obviously that all that code at the top goes away so it's less code better another thing that is maybe not so obvious is is logic in callbacks so this is very common you have a slider drag started and then you want to run some logic as a result of that so you start writing the logic inside the actual method and this is a simple case but this usually leads leads into much bigger methods that take various variables and modify various states and it gets really really complex so why not just have one method that's named meaningfully and it's got this visual state so this is something I use a lot to visual state is the word that describes how a certain element goes through its different visual States as something changes and in the backhand and cold obviously becomes much much nicer like this so good simple code is good but like I said it's a huge topic and that's yeah I don't have time for that for all that I wish I I wish I did another thing that I specifically left out is this resized and paint method which as you can see it has quite a few numbers in it so this is quite common the most this is actually quite contradictory because it's a very simple code it's just got it's just setting the bounds of an element putting it on the screen and it is in fact simple code but it's very very wet right it is if someone wants to change this interface is going to have to affect all those numbers in some way and this is slightly better right we've extracted the width and the height and we've moved it into some private members that earn - or some member yes'm variables there but still the X&Y is still not that good so you could you could continue down this way and have have some like plus and minus there to shift the position based on the height and width but then there's this this margin I don't know if it if it's obvious with it's like 14 there's a slight 10 margin there so it's just gonna it's difficult to read so over over the past few years I've I've come to realise that row geometry and static layout is is bad because it's its inherent static Ness is is always a problem when you want to do modern modern buoys so there's there's better ways of doing this I don't know if how many people have have seen this kind of layout code in juice yeah so this is definitely much better right at this point this code is dry right there's no repetition it's perfect code right it does everything it needs to do it grabs this area chops off and if if you haven't seen this I would I would have a look at it first but there's still a little problem with this kind of code I'm gonna quickly run this now so it doesn't really resize well I mean you can write it in such a way that it does resize but it's gonna get complicated and it has all these cases where like yeah it it and it tends to get into a very complicated kind of looking code and it doesn't is not really dynamic in the sense that you can achieve so maybe not very obvious but maybe this will make more sense once I show an alternative I'm sorry I've forgot to mention this pain method where it which this basically just draws two lines on the middle of the margin you've probably seen it in the example I just showed this again so there's like two very fine lines in between there so I want to suggest that if you want to do dynamic layout you should use dynamic containers there should be designated classes that deal with certain layouts and there's there's a few languages out there that support this so if a WPF has stack panels and grids and all different kind of tools for the right layout but there's something out there which is better than everything I've seen and it's called sex box how many how many of you have used flex box quite a few so again it's a it's just it's a web standard really it's it's CSS based and it's come out recently and I don't think it's actually supported or known on all platforms yet even browsers just some of them support it so it's very new stuff and we're very lucky to have a C++ implementation in juice so if you haven't seen this definitely check it out now I'm afraid I wish I had time to do like a proper flex box tutorial but it takes some time to actually get the hang of it it's it's a it's a very generic class so it's it's difficult to to get it get the right sense of it so I'm just gonna do a bit of a teaser here I'm afraid but this is the same layout code written in in flexbox it's definitely more declarative it's got some rules for justifying content similar to how you justify your words in a word word processor and what I've done here is I've gotten I've removed that pain method and I've made the separator an actual component so then I can factor that in in this resized call and in this flexbox layer so it's it's got two two boxes it's got one mastered box and one top top box the top box is essentially that sliders at the top let's close some of these yeah you will end up with quite a few of them open yeah I decided to start making this sliders look a bit better in the meantime and that's just me in middle so sorry for these sliders that look terrible but I think this is slightly better in terms of layout so space the free space on the on the top top row is distributed much better so as I resize it's always looking semi-decent now I've removed some code from the previous some hard-coded values which some of them are still there so the slider size is it's not 30 and I've removed that 90 which was the height and I think it's if you're doing layout it's it's better to to have the parent set to the size and not have internal values hard-coded in your classes because really that class should react to any external set sizes and whatever yeah the basically the less number is the better why did I just do so something something to note here is is if you're using flexbox is actually fast to just create it on the stack there in the resize method add your items to it perform the layout and then get rid of it it's happening very quickly and we've done some really complex layout in noise in noise and we've never seen it show up on the profiler so that I would recommend just don't bother making private members for the for the Flex boxes and items if you're if you're doing this so I I'm afraid I can't go into more detail into how this is done but I wanted to to point something out here that is this is it's got these words your vertical and horizontal so this layout despite the fact that is dynamic it's still kind of static in a way because I'm always gonna get this positioning whatever I do and at some point as I resize this is not a great use of space because there's a lot of empty space in between those door slides at the top so for something that's landscape like it doesn't look that great so I want to show a slightly better example this is still flexbox so it looks the same at this point as soon as I reach a landscape the three sliders switch orientation and this message is orientation so this is interesting this is not sure if all designers would really go for this kind of stuff but this is just a proof of concept of what you can achieve and you're probably thinking the code to do this is quite complex and you I'm not sure how many of you are thinking that this code will probably double in size just because I because I did that and what actually happens it's reduced in size so one thing I've done is I've removed all of that vertical and horizontal notion so I've got this slider item which which it doesn't really know which direction it's being laid out so it's just how it just has this basis which is set to the slider size so these are all flexbox terms but the main idea to keep in mind is there's no vertical and horizontal meaning here and the only thing I've had to code is is this little method which checks if it's in portrait or landscape mode and then the only thing it does it just switches the Flex direction so that the container now is not gonna is not going to flow from just row oh sorry just just column is going to switch to either column or or row and that yeah that's that's pretty much how you can achieve that kind of layout so if you if you wanna look more into flexbox I would say check check this link out it's the first one that comes up when you do a Google search anyway so it's it's a good resource to learn because it's got these embedded web views where you can try out stuff and you know it's it's on the web so you know that is the correct implementation like we've only added the Flex box class recently in juice and we're seeing educators edge cases here and there so sometimes I'm while I was learning is how is this actually correct code or is it just or is it just like a bug so if you have those that those questions I would say just try it in the endo in the web right so I wanted to get to the next next thing so this is some common code you've probably seen again very difficult to find code that fits on the screen and is realistic in any way but this is a very common class so it's got got some elements there I've I've highlighted what is presentation related so there's a color there's sliders there's a text button some draw methods but then there's also some callbacks here which they're more like interaction logic so is what is what happens when you press on a button they're not necessarily graphics and layout they have a slightly different meaning to meaning to them and that's fine but the only problem there is that what you usually do is you have some interaction and then you take an action and you change your state in some way this could be a reference to an engine like an oscillator or some state and again this is simple because it's just a little class but I'm sure you've seen things that become much much much larger and they tend to overcomplicate and what happens is they complicate and everything gets mixed up with this layout code in pain methods and you can be very organized and you can compartmentalize code but it's people aren't you know they're just gonna write code and they're gonna get get running and I think that that is gonna be a huge problem if you if you keep writing code like this is going to be hard to have views that are simple so I've kind of given myself away a bit there but I've come to the conclusion that mixing layout in graphics with application logic is bad it's possibly simpler in some cases that you should if you have like a simple app you probably don't need it to start tinkering with this but if you see your project growing a lot and you've got loads of screens I think it's I think it's a it's a good idea to step away from from allowing and graphics and this is this is not something that I've invented now this has been researched and done for ages so MVC is something that I've always been into and that's essentially what this becomes so I've got an oscillator view and I've got an oscillator controller everything that was to do with presentation is now in this oscillator view everything has to do with interaction is this it's in diskant controller it takes a reference to an engine and the oscillator view that it's controlling so it can register to callbacks and you hide away all that nasty like plumbing I think this is the best way to call it this is a lot of plumbing you have to do end plug plumbing is gonna be ugly so I want to encourage you to keep views clean and put plumbing in a place where you know it's for plumbing and that will that will make your life easier when you're when you're changing graphics so as I said oscillator controller and view now I've shown a very simple example there so I think what really happens is when you start doing that it it's not as simple as that you know this this process of splitting a class into into two leads takes into other kind of problems so I wanted to show a very quick example from the noise codebase hopefully no one's going to sue me for this and so this is a very common class in the nose nose nose no it's called good bass it's it's attractive if you've played with the app you might have seen it let's try to open it up here we go so it's just the little track view with the clips and slots and I can resize it now that there is something non-trivial about this this is not a simple component that you can just create and set some variables on this has got a list of clips inside so if we're looking here we've got this owned array of slots which themselves have clips and if if you saw that and I've if you looked at this code you see that I have some some clips in there and you might be wondering where did where did those come from so in this kind of cases what I tend to do is I tend to have a public constructor which is the constructor that your application code googled I use and then hidden tucked away at the base of the class I have this little macro and this is switched on just when you're in the producer live build just quickly add some of them in the way you want so that way you still have these mocking this is essentially mocking and there's some frameworks out there like Google's mocking that has some constructs to do this but this is a very simple and raw example and how you can have mocks of objects without worrying about what it's connected to so that is dyes like that example scales with lists and all kinds of things but the idea is separating graphics and layout from app logic is good now before I didn't want to just leave it there because I think this is a very deep topic and I've been dealing with MVC stuff for the past three years and I think I only just got really the hang of it like it's just you have to you have to be very you have to do a few examples before you know exactly what should go where and there are all these edge cases when they interact with each other so it's not it's not very straightforward when you have complex big real-life projects so there's a few rules that I keep in mind so views should be dumped they should be simple and dump they should they should be easy to even rewrite and throw away and you should be able to do that with confidence without understanding what is connected to because that is what is complicated so connecting it up dealing with like a pelagic that that's that's the complicated stuff views is just pixels on the screens and layouts you shouldn't be hard so have that there and then have controllers to deal with the interactions or all they call the clicks and stuff that will interact to your to your model and something really important to know there is the controller if you look on the diagram in the in the left the controller depends on the view so the arrow represents depends on relationship and the controller also depends on the model which means the model is independent I can compile that and for that anywhere I want the view is also independent I can run it in producer I can do what I want to it and then all the governs end up in the controller and at least we all know where that is and it's it's a bit simpler to to work on important stuff when you have to so this is um this is a more real-life example how this diagram scales so you've got user interface at the top these are just two views and then you've got the controller sometimes I mean this is something I tend to avoid I tend to refer controllers to other controllers but sometimes it's a good example and then I tend to connect everything to state objects so I don't I don't like references to classes that do stuff I I just try to minimize the connection points to the very very minimum so it's only dealing with the parameter that is changing or whatever you're changing and in the model of your class and what's really nice about this this is I'm sure I can really demonstrate this but because all the views have no dependency then what we can do is we can put them in a different translation unit so when the producer runs it doesn't it doesn't even build any of the stuff at the bottom in literally just builds the views so in my in my list here producer and when I make a change really only builds what's view related and really that wouldn't be possible if we had dependencies in our in our GUI or if it was possible I'll be I'll be curious to hear how you how you would do that so as I've said there's some pros to views and controllers it's it's good for making GUI is fast if you've enforced this separation it keeps the GUI loosely loosely coupled it's more than tenable so that this essentially do the same thing I'm kind of reiterating a bit it's got the better dependency management and it's actually this is quite a quite an interesting one so once you've been doing this for a while your team gets into this habit where they communicate using these terms and it's so efficient because you know exactly all these arguments about what is this doing why is this that just just disappear on all of them most of them disappear when you've when you've got this effective oh I know this is you I know this is controller and even in source code when you're browsing to stop when you see diffs and changes you see if that's in the view you know a thousand problems that you don't need to worry about so it's just it's just a it's just an better separation but obviously there are some cons so it's a bit more more boilerplate involved when you have these classes so there's there's like then when you have just a simple editor you subscribe to a to a listener and then you don't really need to unsubscribe when when that class is deleted because that's the only one holding that reference but in this case when the controller is a different object you always need to make sure your controller unregistered from from listeners and another downside of this is that it kind of encourages you to break apart everything so you end up with loads of callbacks and it could lead to event-driven programming hell which is terrible but I've got tips on how to avoid that so this is kind of it makes me sad that I couldn't I probably won't have time to show you how you can avoid events and connecting sliders but I can give you a hint if you've got loads of sliders for example in juice you can use values so you don't have to register every time to slider cold beds you can just refer values to each other so if you look at juice just value 3 is that that will help with that there's another there's another cone here you've got this extra lifetime to do to deal with so when you just had one class you can just create one class and then divvy done and you know that's done when you've got a controller that refers to it then you have to deal with the lifetime of that class as well and this is something that we have built a framework for a frame or like alike a little construct that deals with this we have like a little view controller pair in noise that just deals with this binded a lifetime the most dissapointing corn is that everything that i've talked to you about is it's not really achievable if you have if you have a very huge project it's not something that you can just go home and do right because you know we all know how difficult changing changing code is but it is something that you can start doing more so in your new classes you can start building them in this fashion and then slowly migrate over and then if you're so lucky to start a new project like like we did you can do it like this from scratch and which is much much easier so I just wanted to do a quick recap so coding for different form factors is I think it's an increasing necessity not nowadays so it's got loads of mobile since running out there and maybe some of you are not maybe you don't want to write mobile apps but something that I found out recently is that a uv3 for example will completely take ownership of the of the size of your plugin so if you are using a v3 you will get given a certain size exactly sure on the on the details of this one but fabian can can give you a few or so we can prototype quickly if if we follow a few good guidelines clean clean code is very important so if there was one thing to take away from this is is read all this magically with view controllers and all that really is not important if your code is not clean it's only going to make it more complicated so this is the first thing you need to get right and then move on to other two other bits using declarative layout containers is better than setting positions in absolute coordinates and separating views and controllers helps gives you simple is not making a lot of sense but here we are so I think that that's pretty much it
Info
Channel: JUCE
Views: 9,979
Rating: undefined out of 5
Keywords: Projucer, Vlad Voina, GUI, Plugin, C++, real-time
Id: YW1HS-hQY78
Channel Id: undefined
Length: 39min 5sec (2345 seconds)
Published: Thu Nov 17 2016
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.