 All right Hello everyone where I got all the right chats spots here Let me double-check OBS. Yeah, looks like we got sound coming from the microphone Piping in the desktop audio Good there All right, so we got a couple folks here already. How's it going? Hello to Dave Odessa Randall Bone in the YouTube Chats Arnalyn over on Discord Tammy it looks like Dexter Catney and maybe G3 holiday guessing is around as well. Yep. Happy Friday to everyone definitely seconded on that So introduction to folks that might be new Let me so over here So introduction to folks that might be new hello to everyone my name is Tim And I go by foamy guy on github and discord The chat that we have pulled up on the screen right there Well, I guess there's actually two of them, but the top one is the discord chat That's on the Adafruit discord channel, which the address is down below This way actually a da fru. It slash discord So if you want to head over there you can hang out with us during the show ask questions or just hang out with lots of cool folks The one below that is on YouTube So you can interact that way as well if you want to chat on the YouTube And then I am not so good at paying attention to more than two Chats so there is I think a twitch chat probably going as well And I think we're on a couple of other platforms as well But these are the primary two where you can actually get my attention if that's what you would like to do with With your chat So if you want to ask a question or anything like that discord or YouTube are the places to do that for this stream So speaking of this dream, what are we going to be talking about? So again for folks that might be brand new we are working on circuit python related stuff So the website right here circuit python org This is a great place where you can go to learn more if you are interested But the quick version is basically that this is a type of python code It's a version of python code or an implementation of python that runs on These tiny computers called microcontrollers. There's a bunch of them in the background here You can also click over to downloads page and see a bunch of nice photos of different shapes and sizes and everything as well I have on the on the top-down camera. I have a Another one of these microcontroller devices This one happens to have a nice big screen with a touch overlay on top of it So we'll be playing around with the display a bit later on but More generally what we're doing is writing python code that runs on these tiny computers and allows them to interact with other Hardware peripherals, so I'll be playing with the screen and the touch overlay But there are other devices without built-in screens. They have the ability to connect up to sensors and buzzers and beepers speakers lights, you know rainbow LEDs Pretty much any kind of little Tronical component that you could imagine you can connect up to these microcontrollers and then write python code in order to interact with it So, you know if you want to read some data from a sensor and then you know send it off to the internet To keep it into a graph of a dot, you know keep keep a database and then graph it out or something like that These little computers are allowing you to do that and you can write this python code In order to achieve that sort of stuff. I just noticed we're at 295 boards So we're getting pretty close five more boards will be at 300 boards, which is pretty cool I did see the other day maybe earlier today or yesterday sometime really recently. We passed like 350 libraries I think which is another cool milestone So if you're interested in circuit python again, you can hit up circuit python org This is a good place to learn more about it if you want to get involved. It is an open source project So you everybody out there who's watching can get involved in the development if you'd like There's a link at the top of circuit python org right here to the contributing page This is a pretty good place to start if you do want to get involved on The python side of things writing and reading and reviewing python code This has a list of all of our open pull requests and all of our open issues. So for PRs, you know, you can take a look at the at the pull requests These are basically proposed changes people have made proposed changes to the libraries you can take a look at those and You know, just offer feedback if you have the hardware for it, you can try it out Let us know on that You know on that PR post on GitHub and just let us know if it worked or you know If you had trouble with it or if you don't understand how it's supposed to work Or if you think there should be other changes, you know to the Code or if you spot typos or anything like that. That's what reviewing the PRs is all about There's also open issues including a bunch of open issues that are good first issues Which are great for folks again who are just getting started but want to help contribute This a lot of these good first issues right now are adding the typing annotations Which I have some good fun news to share this week about the typing annotations as well I'll get to that in a moment though So this is how you can get involved in the development I would also encourage you if you do want to get involved to definitely head over to the discord There's a circuit python dev channel where all the development discussion kinds of kind of occurs between all the folks working on the project So head over there if you do want to I will mention as well circuit python. It's an open source project So anybody can contribute, but it is primarily funded by this company Adafruit comm So these these are the folks that are paying the team that works on circuit python full-time the developers Also paying folks to you know foster the community around circuit python to author guides Do you know to make projects and things like this? All sorts of great folks working on different areas of the project and Adafruit is paying them some of the folks work full-time on this project Some of the folks like me work part-time and get paid, you know to work on this project part-time And to do the stream and stuff like this So if you want to support the project, but you don't necessarily want to get involved in development Another way you can do that is heading over to Adafruit comm and purchasing your hardware from them by supporting them with your business You are helping support the circuit python project and all of us who work on it definitely do appreciate that So let's jump into what well, let me catch up on chat actually let me catch up on chat and then I'll jump into what I'm gonna do today I'm also gonna I think separate these chests so I can not have them stacked on top Okay, so That looks pretty good and let let's catch up here Tammy happy Friday to everyone happy Friday to you as well and everybody as well Zarnalyn Let's see. I think I had some of this before see Grover. How's it going? Good afternoon. Good day Zarnalyn looks like we got a nice comic going there G3 holiday little potato See Nice gifts or gifs or whichever way you want to pronounce it I'm a huge proponent of pronounce it however you want as long as people know what you're talking about and people are probably gonna know What you're talking about no matter which way you pronounce it unless you're also Asking for peanut butter then they might get confused, but Okay, so we caught up so what am I gonna work on today Specifically I'm getting into the tabbed layout and I a couple of weeks back I did some planning for this widget the tabbed layout on the deep dive So if you've been watching the deep dives for the last couple of weeks Then you would have seen that portion of it where I did the planning On some of my Saturday streams, which I do Saturday mornings at 10 a.m. Central time I did some work on some of the components that go into the tabbed layout including Making a page layout, which is like a simplified version without actual tabs at the top or anywhere I did all of that work on stream So if folks are interested in this particular widget you can kind of see the whole history of this thing if you go back through The vods on YouTube and such I did also the preliminary work on the tabbed layout on a Saturday stream as well I think so that's kind of the history of this project today what we're doing is Implementing the actual visuals of the tab so you can see here I have some like a nice, you know rounded rectangle looking tab header things basically And our goal today is to make our tab layout able to create these visual You know tab pictures and then put the text inside of them for each page Or each tab within the layout So this gives you an idea of how the visuals will end up looking I will say, you know the way that I'm building this is you'll be able to supply your own spreadsheet So mine happens to be like a gray background with a blue border right now And I also have these other weird strange lines which happen to be green But don't really come through on the camera that well so you can kind of tell they're there But maybe not what color they are And the whole kind of idea I have behind this tab layout is these are actually dynamic you get to you get to control how these look based on whatever sprite sheet you supply so You know don't get necessarily hang up on the idea of like, you know, what if I don't want my tabs to look like this We are definitely building this in mind For you to be able to customize it make them look like however you want so as we go throughout this dream You'll see how we've achieved that So that's what I'm working on let me catch up again happy Friday to Liz Notorious gif I like it Huge proponent of using secret handshake type ways of saying words, especially acronyms. That's not very inclusive Yeah Yeah, of not using secret handshake. Yeah, I totally agree nerdoch Yeah, especially true. Yeah, especially true about folks learning if English is not the first language Then like sometimes they have other influences that affect the way that they sort of just assume things will be pronounced for sure Software engineers are bored. Yeah, there's I definitely think that's part of it as well. I mean, it's a As an industry like it grew from this idea of compiling, right? You have to wait a wait a while for compiling We have it really nice with circuit Python. You just save it and it runs but like Traditionally software development has had a lot of downtime. So I definitely think that's where some of the Some of the weirdness and some of the fun shenanigans and things that developers sometimes get up to Grows out of that like built-in wait time The idea of compiling and running and stuff and it in larger projects It takes a little bit longer to build and so you end up, you know having a bunch of pauses to try to fill with different stuff and Sometimes folks do a better or worse job of choosing what to fill it in as Patrick meeting in a in an hour But I'm here till then how's it going as Patrick? Hope you have a nice meeting when you do go But let's jump straight in I have The test code for the tab layout so right now This is basically a little example that I put together last night last night is when I implemented this What I'm now calling a tile grid inflator Which is basically the the software utility that takes a tiny sprite sheet such as one of these So this is what my sprite sheet looks like The one that's being drawn right now. This is 96 pixels by 72 pixels, but we can actually make it much smaller as well if we want and then it sort of inflates that sprite sheet by duplicating the center tiles of The tile grid in order to add width and we could actually add height as well if we wanted to we're making tabs So we don't really need them to be that tall But the inflator does support, you know inflating vertical ways as well, which is kind of nice I think there will be lots of other uses for this inflator thing. So I'm kind of happy to get this thing Created because I have another few spots where I think it will be really really helpful At making it easy to customize display. I owe widgets So this is kind of the test code I wrote last night when I was working on the inflator I was I did stream as well on my on my own twitch and YouTube last night as well So if folks are really interested in the beginnings of this inflator code You can find the VOD on that as well including a previous night where I kind of made an attempt at it and failed Which I think is nice To show folks as well as like not everything comes out correctly the first time that's like just part of software development So you can see my first attempt at this and then last night we got it working a lot better in a different way So that's what the test that's running right now is I'm gonna switch over though. I'm gonna rename. No, I'm gonna copy paste this rename this to code Inflator test tower grid and Flator test All right. Oh Actually, I already did this. Okay. Yeah, tower grid and Flator tabs. I already did this. This is Me double-check I think this is the test code that's running right now Yeah, yeah, it's solely it's okay. So we can just overwrite code I'm gonna put the Ab layout test which is right here Has a gigantic comment in it Only needs to be cleaned up still here and We'll go back to what we have so far of Our tab layout. Okay, so this one's portrait in this a bit May switch us over to landscape honestly portrait I find is a little bit harder to stop the The light on the camera from reflecting back I find the light on the camera helps the colors come through quite a bit Yeah, I think let's just go ahead and switch this mostly. I put it as portrait to see how many tabs we could reasonably fit On the screen that way and I think four is probably The answer so we did get that answer and I think we could just switch this back maybe to Zero for now Burning makeboard lowland c3 mini right now. Yeah, so as Patrick is waiting on a build right now that's definitely Definitely how it goes sometimes and the the larger the project Tends to be the longer it takes for it to actually build which means the more time you end up Finding something to fill with and hopefully finding something productive to fill it with So here's what we have so far on the tab layout it's working pretty good We have the ability to add the different tabs. I'll run through this test code real quick as well so you You create a tab layout you give it some initial configurations I Then I'm creating in this case four groups because I'm gonna have four pages So I create a group for each page and then we can basically just create some UI stuff for each page So in my case, I'm making a label For each page so I'm making four labels and then I'm also making a shape for each page and right now this is using the Display shapes library. We just create a couple of shapes They each have different sizes and colors and locations and stuff like that just to prove that the the different pages are working correctly Then we append all of our content on to our group So I made those groups further up and we're gonna actually append the label and the shape into each one of those groups So this is setting up all of our groups and then finally once we've done that We can just go and get our page layout Our tab layout and call add content and then we add each page worth of content So our groups are what we add and then we also get to choose a name for the pages right here Once we have added all of our pages to the tab layout then we can put the tab layout into the main group We could actually do that first the order doesn't matter too much But I happen to do it after this time so we put our tab our page our tab layout into the main group and then We have a bunch of ways where we can control which page is currently showing so we have like show page You can do it by page index. You can also do it by page name The names that you supplied back here We also have the ability to go like next page previous page So like here it's calling next page. We can do that, you know, just kind of over and over again You can cycle through them sort of like a PowerPoint presentation or something like that And then there's also like a showing page index property so you can update that eventually We may cut down on the number of ways to do this. I do think it's nice When you're building an API maybe to try to provide not as many different ways to do stuff because then folks start to wonder like What is the best way? and it's not that there necessarily is a best way, but It's nicer to be able to just tell people one way and then that's kind of the way So right now it does support a couple of different ways to switch So this is our test code so far and so right now what we're doing with our tabs is we're just putting text up there and We do change the color Of the text based on which page is, you know currently focused So the one that's currently showing has a brighter white text for its tab label And then the other three have a like a darker gray text. So what we're gonna want to do is draw our Like visual tabs like we just saw a moment ago. We want to draw those behind these labels And then eventually what I would like to do is you'll be able to supply two sprite sheets one for The focused tab and one for the non-focused tabs And so then that will be able to change the way that the actual tabs look as well When one of them has focus Pick the way whose behavior would be the least surprising to users. Yeah, I think that's I Think that's probably the right way to go about it I will say like all of the different ways make use of a Single function internally, so I'll probably keep that one But maybe like leading underscore it so that it's meant to not be necessarily called from the outside and then just leave a single a Single API I will say though. I do like the ability of changing either by the index or the name I would like to keep that functionality but even within that right now I have a function and a property or a set of properties So like right now there's still multiple ways even beyond the fact that it's index or or name So I do think that's a good idea, so Let's I think just jump straight in so basically what I want is inside my tab layout We are going to make use of this inflator To create some visual tabs And do that and go inside of the tab layout, which is inside display. Oh layout a boy out and We will end up importing this inflator. I don't know exactly where this inflator is gonna end up I don't know that it necessarily makes sense to have its own library I don't know that it necessarily fits in any of the libraries we have maybe the image load library Not a hundred percent sure so this may end up moving to somewhere else I don't know where it's home is gonna be, you know, maybe it's I don't know if it'll be community Bundle library or circuit Python org bundle. It's pretty heavily tied to display. Oh So that's kind of still up in the air, but we can go ahead and start using it here to just get a sense for how it's gonna work Ended up not needing bitmap tools. I'm actually just gonna erase that randomly while we're here Okay Here's what we have so far of our tab layout And so one question is We need to update this every time we draw tabs I think we probably do draw tabs is kind of like our refresh function When you call draw tabs, it will take all the latest information about the tab names and The currently active tab it will take all that information and then Render the top of the tabs portion of it how they're supposed to be So this does seem like where we would want to be doing our tile grid stuff One thing I wonder though is like Don't want to be recreating the tile grid every time we call this so ideally I think we want to How do we want to do it? I think we want to create and tile grids equal to the number of pages and then I Think maybe it's gonna end up being easiest if we Create n-1 Standard tabs and then we create one You know focused tab and then I think we just swap the location to to move around with the focus I don't think there's an easy way to change a bitmap on a tile grid if there is then maybe we'll do it that way But I think right now when you create a tile grid You set the bitmap when you create it and then I don't think you can change it But what we can do is just create enough tabs enough tile grids that we need and then just move the active one Move its coordinates to where the currently active tab is But before I even actually do worry about the Did I figure out the refresh issue from the last show I did not the vector IO Hidden stuff. I have not figured that out yet. I will dive back into that at some point, but did not get it worked out So before we even worry about the active tabs actually though, I'm gonna try the Gonna try to just draw the tabs all the same. So I'm just gonna draw All of them the same and I think let's see. Where do we want to create them? Do we want to create them when we call add content that seems a Pretty good spot Or I guess maybe we create them We create them inside of Draw tabs and we just like check if they exist or not And if they don't then we create them and if they do then we just reuse them Yeah, I think I like that So I think what I'm gonna do is go self dot underscore Inactive tab tile grids Is a list empty? self dot active tab I'll grid eventually. I'm gonna use this one and I am gonna start with just making them all inactive first So this will be a list and then basically when we call draw tabs our length of tab group less than length of names I mean this is Pretty much doing the same thing. This is creating a label for each page So really we could be doing this right along inside of here I will make Group I think I will make Think we'll separate this Oops, let's take this one that we had called tab group and change it to Have labels Labels group or text extra labels. Let's do labels tab labels group factor and Then I want to make a self tab tile grids tile grids Group I'm just gonna use two groups Think groups are fairly cheap and this way it's nice because we can iterate over them Separately if we need to Grids group. So this will be a new group. Whoops group Okay, so then inside of our while loop here We're already looping the number of times we need because that is the number of names that we have which essentially are the Pages each page has a name So we're already looping so we can just go I think why don't we just plan on making a new helper function and So we'll say something like self dot tab tile grids group dot append create tab I'll grid create inactive Inactive so this function doesn't exist yet, of course Create inactive I'm in a copy paste and this will need some arguments and stuff Um Will it maybe it won't and maybe it maybe it won't I think what we will do though is we will want an argument for Inactive tab write Feed and then we're gonna put that on self so we can access it later self dot inactive Right sheet and I'm actually gonna call it file File name file path. I'm probably don't need to be that specific So my idea here is we're gonna pass in the the BMP file the name of the BMP file So then inside of here Well for one thing we don't we don't even need to do this if if the user didn't set this thing But if this thing is none inactive tab sprite sheet file Give a mouthful maybe we'll shorten it if this is none if Is not none then we want to do this Why is this mad? Oh, because it doesn't return. Oh No, what why is this man? Oh self? Yeah, yeah Okay, let me catch up also. Oh, it looks like I'm only this one Do you do you want one function create tab tile grid with an active parameter rather than separate functions? I'm not sure yet. I'm gonna kind of go with the flow for a minute But if I end up not liking it, I will definitely switch it up I think right now though. I want this one that It will create them for me I will see how the code ends up if it's it depends how gnarly it is in here If it's really only like a one-liner or something I may just collapse it and put it all back into here Because it makes sense that it would happen inside of here as well, so I will see how it ends up being But I'm not sure I'll stop my head what it will be yet so Yeah, we'll see how it goes Maybe it should be one function that creates all of them instead of this function Which it looks like is gonna create them individually, but then we would I mean creating them individually makes sense Because we're already inside this loop which is running The number of times that we need it to so I do kind of like creating them individually We'll see though. Let's see how it ends up Somehow it's gonna need to position them as well To get done somewhere. I guess really the positioning it would be good to do it right here because this is where This is where the positioning of the labels happens, so it would make sense to do it right here Okay, so what is this need this may not need anything. I think I'm gonna read from self so we're gonna grab my Inflator test code that we were running at first inflator tabs this one I'll be this out of it Okay, so one thing is we don't have the display Oh, we do have the display Yeah, of course, we must have the display otherwise. We couldn't have put the labels in the right spot So this stuff is just hard-coded. We will need to change this. We won't use this file We will use self dot Inactive tab sprite sheet file. I just wrote this last night, but I still don't remember what the order of the arguments are Take a look at the actual later It is Bitmap target size How size which we can use the default Transparent index so target size so Target size we want the size to be actually similar to the math That is in there But just not hard-coded. Oh Alright, we need to be inside of here. Yeah So here. We're just hard-coded dividing by three which instead we want to divide by the number of number of Ames number of pages basically so width divided by the number of pages and Then divided by and I hard-coded 32 because that was the width of my tile size and so I think There now we have a conundrum where inside of this function we are image loading this BMP file After we image load it we can access its width and its height and That is where we get The tile size from so how but but I would need to get it out here So I don't really want to image load the thing twice. I think what we do maybe is Maybe we allow this Maybe we allow those to be passed in Honestly, I'm almost thinking we just make all these keyword args. We're gonna end up changing this anyway the default I think will be Target size three by three which basically means the same size as the sprite sheet right sheet is three by three MP path equals none by default and then BMP Object bitmap object equals none palette BMP palette Equals none. Hello to everyone mark game. We're time to start my vacation. Nice. That's awesome. Oh Is a good day 22 Fran Blanche is pronounced gif graphical interchange format I'm cool with that. I'm cool with both Well, pretty much anything as long as people understand what you mean, which in this case I think they will so both any So if we pass these in then we'll use those instead of Calling image load here. So basically one thing I want to do is raise if BMP palette. Oh, how's this work? Let's say if BMP path is none and BMP Object is none and Basically you need to give it either a path or an object and a palette There might I feel like I have I'm missing something with this, but we'll go back and make it better later I Think you could pass one or the other of these as none and then that would trip this up and really we need them both to not be none but For now, I'll assume that I know how to pass things in and I won't worry about the the exception But we will go back and do it at some point So then we basically just go if BMP path Not none then we do this L if Or just else Else if BMP path is none and we go image equals BMP object Palette palette equals BMP palette So now we can pass these in instead of just doing the path we can do either or Which means we can save this and we can go back to here and we can and we can image load Before we call inflate tile grid that way we'll be able to get the width Which will in turn be able to give us the tile size which we need right here We're actually gonna do this import this and Then this will be File path interactive in inactive have sprite sheet file Might change this to sprite file or something. That's less of a mouthful. Oh, it should be self though Now this will load and then here we can do Image dot width Over In the length number of pages. I almost want to Variable just so the code is clear I just want to do something like page count page count equals This Then we put page count here, which makes the code more legible Is it better describes what it actually is? This describes it as well, but you just have to know about page layout and Other stuff Requires more in silvery knowledge this one you can read Just with English and not know anything else and it still kind of makes sense the display width divided by the page count and then We divide that by The image width divided by the page no Okay, I have one extra. I have one extra divide we divide by the Tile size width, but not by the count again. We don't need the second count Means we don't really need these parentheses either The fraction of the display divided by the tile size No, no, no, we do need We do need this we do need that back We need this device because we don't want the full width of the bitmap We want one third of the width of the bitmap. So I did have it wrong. We shouldn't be dividing by Page count we should be dividing by three Because the way this is intended to work is The sprite sheet you pass We're basically making the assumption that one That it's split up into nine basically that one third of The width is the tile size So basically that there are three tiles across the width and three tiles Down the you know down the side which makes a total of nine tiles And then it uses the size of the sprite sheet to then determine how big those tiles actually are so for instance if you had an image that was 48 by 48 that would mean that your tiles are 16 by 16 because 48 over 16 is three I'll first a son dot two one two I don't know what the dot two one two is for but how are you today, sir or YouTube print I should say and then two is the Height that we want to target the height that we want to inflate the style grid Do and I do think too is probably a good place to start transparent index, let's Just leave that one out for now. We'll come back and Let's keep it actually keep it for now. I just cuz I'm just gonna reuse the same tabs actually Okay, this is gonna load it Okay, we do need to change out this right we don't we no longer Well two things everything is keyword arguments now, so we do want the target size Target size, and then we don't want to use BMP path anymore Target size equals Wish we had more room here Third size, and then we won't do BMP path instead. We'll do BMP object image BMP palette this should create one of our inflated tile grids So now here we're looping over the number of names we have If the user actually passed a spreadsheet file, then we are going to create The tile grid we're gonna inflate a new tile grid. We're gonna add it to the tile grids group and then We want to So we'll want to add our Have tile grids group. We're gonna want to add that to our Self-instance group I believe because we are extending group. We would have presumably already done self.append for This one, let's see if we can find. Yeah, it's right here. So we'll just make a new one here and this And actually we should do our tile grids before our labels because we want our Tile grids below the labels the labels will get drawn on top Okay, so now that group is basically gonna be showing it's on the self-instance group, which means it will get drawn So here we have created this we should return it return Tab I'm also gonna call this tab tile grid This should create Four because we have four tabs in this example, but of course it should work for any number as well Placement is gonna be the next thing we need to do. So here we are placing the labels And unfortunately The labels well, I should say fortunately the labels have anchor point and anchor position which makes them easier to place in my mind at least Tile grids though do not have anchor point and anchor position. So we will need to do the actual math on the xy Okay, this is like updating the scale if the scale of the actual label object Does not match the current scale configuration like the property that's setting the current scale then set it So it's using anchor Point at the midway point And then it's positioning that here So I think what we will end up doing is self dot Tab tile grids group i Dot x equals It's gonna be something like this, but not quite the exact same start of tab Oh, actually I I think we just want start of tab basically that was doing the Width over two in order to shift to the center basically and so we're no longer shifting to the center Replacing by the zero x But yeah, I think that's just start of tab And then for now, I'm just gonna hard code y but we'll probably eventually come back and offer a way to Change y's as well. I see right now my labels just have a hard-coded y of two. So I'll just code the same For these so yeah, I doubt this will work, but I think we are at least ready to give it a try Yeah So let me see if I can fix the focus a little bit here Display has no group my attribute group Uh, probably I type display dot group instead of display i o dot group Let me open up to you. I think we're on What are we on we're on zero Yeah, and I see some stuff on the screen too. Hopefully that means we're on the right one Yeah, okay Uh, and so let's run this again. Where does it crash actually it goes uh tab layout 24 Yeah, indeed display dot group Uh group index out of range Tab layout 85 tab layout 102 is inside add content draw tabs Probably where we want to look 85 So when it tries to access Tile grid at i out of bounds Oh Because they Did not get added because I never actually changed the initializer function Uh Yeah, so we should probably do this also on This stuff We only want to set the location of the tile grids if we actually have tile grids Uh, which is what this is telling us And then we want to actually pass this in inactive tab spreadsheet In our test code we need to go Inactive tab spreadsheet equals I'll just use the same one bmp is test bmp for About bmp should go back and test again without oh it worked. Well, I think it worked Ish We have four so they're they look too big Look too big They're also overlapping kind of weird over here. I'm not sure what's going on with this one They drew something though. So this is a good start Um So for one thing is we'll want to move the labels down a bit And this will end up being probably user configurable, but Right now i'm just going to kind of make it look better than it does now um Back into here where we we're setting this to two. Let's try like eight instead Move those labels down some So I have room we could go further, but that's all right for now We could also let's just do this on zero. It's not even put that two pixels down And we need to figure out what size is it trying to make them So I'll put this into a variable and then we'll print it Maybe our Brightsheet's too big. Maybe we should go back to a smaller spreadsheet Feel like we should have We should probably be able to have room for it at least though target size Oh Well, so for one thing we should always have the same target size Well, okay, so the problem is though we're calling draw tabs Inside of add content. We're adding content one at a time Yeah, that actually That gives us a bit of a problem because Can we just can you change the width of a tile grid after you create it? I don't know. I don't think you can change the width after you create it mark this page It's actually like a search index thing I use that works pretty well That one on this browser Oh, this is When could display oh So these at least are dock stringed as though they're just properties. So maybe we can change it Let's uh, let's take this code and put it back into Have layout test Layout test Now Go back to Later test. Yeah, later test Search is weird on read the docs. Yeah There's a I have it bookmarked in Rome and I have not added it for some reason Mark this page This page I like because it lists everything and you can do control f to find stuff And it's faster. Oh, although it didn't find that But I guess it did it just Didn't have the print see which is what I typed first Uh, so this page I really like index page You can go left to find stuff by bookmark Um, this makes it seem like you can just change this. So here, what is this one doing? Okay, this one is just drawing a couple of different ones and these ones are different Then the ones we were just looking at because these are other sprite sheets. So that's the cool thing about this inflator thing is that You can give it whatever source Sprite sheet you want and then it will inflate that to whatever size you need And the main thing about it is like it keeps the corners looking good It's not just like stretching this it's actually duplicating the center tiles So let's just try changing the width on one of these If it actually lets us if it does that's good because then we can just Change the width of our all of our tab tile grids every time we're inside of Draw tabs Or we could check if the width needs to be changed and then change it if we want to be a little more efficient, but Uh, so if we just go like one is which year 12 10. Okay. This is the big one other inflated tile grid. This is the big one So can I just go other inflated tile grid dot width? equals Right now it's 12 Can I just set it to like four three four Has no attribute width well Probably true is it In I don't know which one it was though Yeah, we can access it, but we can't change it It is weird that At the error that it says That it says no attribute width or does I guess maybe does attribute imply setable Maybe I misunderstand the term attribute But we can't just change it. So that's actually That puts us in a bit of a pickle because We either need to Change the way the tab layout api works so that you're not Calling add content once for each page and instead like Add all content and you pass it a list or something But it does it does it all at once or Or we have to basically recreate the tile grids Anytime the width is different. The good news is though we will basically like Let's say the user is creating four tabs. We're basically going to recreate the tile grid Each one like four times, but then we won't have to recreate them anymore after that Which is not ideal, but I guess will work. I mean I See how else could we do this? I guess we could have an optional parameter that's like Number of tabs and then We'll be able to use that That's the crux right now. Basically. We're dividing by the number of tabs we have but The first time we call add content. We have one the next time we have two the next time we have three So like we're dividing by different amounts each time But we need to be dividing by the total number which in our case is four But it doesn't know it can't know When you're just calling add content um Well, just not Not the tab layout test anymore tab layout test when you're just calling tab add content It doesn't know how many times you're going to call it We have four here, but it has no way of knowing that So I guess let's yeah, let's give it let's make it to where you can pass it in here as well Tab count equals I'll put none get back to the tab layout tester code And we're going to pass in tab count So then inside of here target size if both the tab count equals Uh is not none is none is none Then we do this Or do we just make this required? Maybe this should just be required And we shouldn't bother If they do pass it if they don't pass it. Maybe we should just require it I think I like that better actually let's just say tab counts required if If tab count is none raise attribute error Missing tab count argument see that for now Then we can just assume that we have it So then inside of here our target size can be instead of page count Ab count which is going to be on self, but I need to still put it there Now we divide it by the total number Even though we're still calling add content We will need to rectify as well now like we've defined the tab count We don't have any actual bounds right now. So you could still call add content again Um, we should probably make that raise an exception to where You add more than you set it then Suppose you that you can't do that Or eventually we could make itself like incrementing or whatever because really the The only time we lose the efficiency and end up remaking those tile grids is if the tab count changes So maybe eventually we'll make the code that's like as long as it As long as you don't change it, then it'll be efficient It won't recreate things But if you do change it Then maybe we'll give you the option to do that and then that's where it's going to get less efficient Because it's going to have to recreate all those tile grids Uh for now though, let's just say we're going to pass it in Okay So do we get the right size now? Looking better Uh, yeah, actually that looks good to me. So the Problem that we have left now is that the labels are perfectly centered Where they're supposed to be I don't know a better way to describe it. I guess it's that This this label one is perfectly centered at one quarter of the screen No, that's not right though because This is not two quarters of the screen. That would be half Are they fits? I don't know. These are basically perfectly centered If you divvied up the screen into four columns, these labels are centered inside the four columns I think although I'm not actually a hundred percent sure about the space on the edges I think that's how it is though. I think they're in the tabs right now the tile grids that we drew Those are making it more difficult to tell but I do think yeah I think if you divvied up the screen into four Identically sized columns These labels are in the middle in the center of those columns But our tabs are actually at the beginning Of each column not in the center And our tabs also Have to be a multiple of our tile size Which means They can't grow to the exact size we need sometimes Um, they basically have a rule that's like they'll go to the smallest size that fits within The actual number of pixels we have which looks like it'll work this time um But we do need to shift them a little bit still so we basically want to Oh, what is that math gonna be so basically we want to shift them So the start of the tab plus We're gonna need two things in here we want the Basically want to add Half of the width of the columns these imaginary columns We want to add half of the width of the column, but then we want to subtract from that half of the width of The actual tile grid So the columns are Here we could actually do Tab count as well This is the width of the column so we're gonna go plus Half of this But then subtract width This one is gonna get a little bit gnarly here. We need to subtract the width of the tile grid times tile width Because the width is in tiles and the tile width is in pixels and we want the pixels We need to multiply the number of tiles by the actual size in pixels And then we still need to divide that by two we multiply those And we divide that by two And that should put our things in the center And this is the math that anchor point and anchor position allows you to not care about as much Real nice. Maybe one of these days I'll try to add anchor point and anchor position to tile grid. That'd be pretty cool Seems like it could because it knows its width gotta hit the hey now Thanks to him. Good night. All yeah, thanks. Thanks for watching David. I so have a good night Uh, so I think this will work. Let's give it a try Okay That's awesome So we could still scoot the text down a little bit. Also, the text is probably a Scotch big for these tabs if I'm if I'm honest Uh, but that's the beauty of this Inflator is actually we can play with the tabs. I created this one as kind of like What happens if we create a bigger one? Uh, if we, um Don't let counterintuitively if we switch to a smaller sprite sheet Uh, our tabs will actually have the ability to be a little bit bigger Which is weird that it works that way, but it does I think So let's make a different one of these. Um, I've made a few of these last night But I'm gonna make I think at least one more now And I think I want a let's go back to the smaller size. Let's go back to the 48 by 48 I'll just make a new one from scratch that way. You can see how this works all the way Uh Start with transparent We're gonna get rid of the transparent eventually though because we gotta go to index BMP, of course I'm gonna go 48 by 48, which means my tile size is gonna be 16 by 16 We basically assume that it's three tiles by three tiles Even if the tile width is different than the tile height like the one we were doing before the tiles are wider Then they are tall which is like Kind of a cool ability to be able to have this one. They'll all be the same though the tiles Will all be 16 by 16 Um, so I'm gonna put the background as pink, which will be our trance Parency color and then I'm gonna Go, let's see. We're gonna go select a square Select a square I want to not have margins on both sides On the previous ones of these like the one that's currently drawing There's pink on the outsides, which will end up being margin because the pink is going to get turned to transparent So I think I want my actual tab to run all the way to the edges But I do want some transparency at the top for my rounded corners Go something like I don't know the best way to do this. I think I'm gonna make this bigger by a little bit. So brief Or I'm gonna make this four pixels bigger Tooth grief four pixels bigger And then round it all right. I keep forgetting this This thing uses this percent not just pixels. I can't just easily Yeah, well that turned out pretty well actually that's basically what I want did work pretty well Uh, what color do we want to do? Let's do a green color We're outline No, for sure if we'll end up wanting it and We're just gonna copy paste this one more time layer Scoot the second one down, which will have the effect of filling in my bottom corners here We're pretty far away from the top truth More up here like this And so now I want to go inside of that in order to do that. I'm gonna go select by color right, uh We'll go ahead and merge flatten the image Let's go select by color pink Then let's go grow by I think two because I want to grab more of these in between pixels Not quite. Oh, that was too much. Let's go grow by one. That's pretty good. So then Invert so now I have the green selected instead of the pink and shrink by let's say Three pixels And then fill this in with Let's do a gray Let's do a relatively dark gray You could tweak the colors of the labels as well if we need to Fill this and then I also want this to run off the bottom I'm gonna do this same trick copy paste Move down a little bit. There we go It's it's a little chunky on the corner there. We'll see how it turns out when it's on the actual screen I feel like that's Pretty good though. This will this will do what we want And we're at 48 by 48 So let's go mode index And then colors map rearrange And basically I'm going to move all of my pinks to the beginning Because there's different shades of pink in the corner here We actually are going to make multiple colors transparent Basically going to make all the pinks transparent, which is going to cut all of them out from circuit python essentially From showing on the screen in circuit python And so we have zero through six All of those indexes zero through six are all shades of pink Now I'm going to export this And keep a copy of it in here And name it very uncreatively test bitmap five We're going to copy that into our device Really, I guess we need uh inactive have Transparent And we're going to give it tuple range Because zero through six are all of our pinks, which are what we want to make transparent This is already built into the inflator. It already has this ability for us to Declare one or more indexes to get made transparent We do need to add it to the tab layout and just pass it down when the inflation happens All right indexes The one we got passed Now when we call inflate You will give it I should look inside the inflate function and make sure that it can handle none Oh I don't actually know if it can handle none They don't pass it. It'll be none. It'll get passed through as none and it just won't do anything if they do pass it It can actually be either a tuple or A single index if you only have one index you want to make transparent then it's easy. You could just pass the one index Um, but in my case like with the pinks, we had six or seven different pinks And I want to make them all transparent I don't want any of that pink to show through I think this should be working now I already did that Yeah, so let's see what we get. I didn't change it to use the right Yeah, we're still on four There we go And so like I was saying the Since we picked a smaller spreadsheet Even though it feels kind of counterintuitive the smaller spreadsheet actually is going to allow these tabs to Use up their space more efficiently to try to be bigger in this case um Because ultimately the width that you inflate it to has to be a multiple of the tile size So by using a smaller tile size 16 by 16 instead of the previous one which was 32 by 24 we Make it so there's more multiples possible within the actual size that we want It has to choose the uh It has to choose the largest one That is a multiple of the tile size That fits within the actual width that we have the size of our imaginary columns Um, so this one actually looks better. I will say the text looks a little too big here. We probably want to drop it back down to Scale two or the other thing we could try Which eventually I think this will be user configurable But right now it's hard-coded we could give this a height of three that we inflate it Our target size when we inflate we could say is three which would actually make our tabs bigger um Actually, I kind of like the looks of that especially because Let me see the other one again, especially because eventually we're going to end up with touch screen, right and Yeah, this feels like it would be kind of a small target zone it probably would still work truthfully especially if you use a stylus Um, that would still be pretty easy to hit with the stylus right now. There's no touch interaction So when I touch nothing happens, but eventually we want to make it to where you touch these and then it You know focuses that tab for you So yeah, let's go up to I think let's go up to three And if the user wants a shorter one you could always provide a spreadsheet that's shorter like my spreadsheet is 48 by 48 Which means the tiles are 16 by 16 theoretically I could provide a spreadsheet that is say 48 by 30 And then my tiles would be 16 width and only 10 height which would then make my three Tiles a shorter amount of pixels. So you You have like really fine-tuned control based on the The size of your spreadsheet how this is going to end up looking And what size it's going to end up being Um, you think let's chunk it back to three for now though because I three this will be better This is a better height for actual finger touchscreen As opposed to stylus And so we do still have margin in between I don't I guess we're gonna always have that unless We just coincidentally land on a perfect multiple of the tile size so The screen this screen happens to be 480 width 480 over 4 What 120 So this does not divide evenly by 16 If we chose a tile size that does divide Evenly into 120 Then there would be no gaps here. It would fill the columns perfectly Let's test that we might as well while we're here. So let's say Instead of 16 width, what do we want to do? 20 width It's 20 would divide out you want to go smaller No I think I want to go any smaller Right 20 I'm actually going to cheat a little bit. I'm just going to go So basically we would want to change the width of this to be 60 Is width 60 And I want it unconnected because I don't want to change the height This layer I want to go to image size Oh Back to RGB Then this layer size That okay control a we'll see Case to new layer Oops gonna do the same thing It's not going to do the same thing. Okay. I have no idea why that's different, but this is actually what I want And I'm going to cheat. I'm just going to scale ideally we would Rebuild this to actually have the right curves Because it's raster graphics and it's going to lose Some sharpness by scaling it like this So the lines are going to get thicker and some other weird stuff like that But I'm going to do that for now. What happened down here do that part So now we're going to save this one as six and this one has an even Pile size. Yeah, I mean this is a bit of a pain I guess like having to if you want it to come out perfectly Then you kind of have to do the math and figure out the right size to make your sprite sheet um But I like that it has a sane default even if you don't bother to do that because like I mean, it still looks pretty good like this the the gap is not too bad and realistically the gap is similar to how Leave this one works, which is ultimately Portal interface face This is ultimately what we are aiming for I guess that's kind of difficult to tell these might not have too much of a gap between them But this is kind of the interface we want We should change the colors Use a different color of gray for not focused Uh, or maybe what we could do is use white for not focused and then like green for focused or something That's the beauty of this though is you'll be able to choose all of this stuff You can configure it however you want Uh, so we made six let's copy six to our board later six copy Vice paste into bitmaps Change this over to use six now And I think this will get rid of our margins In between our tabs I'm pretty sure and convert it back next And make sure all my pinks are at the beginning still to Oh That is That is unfortunate So our our cheating caught up to us just scaling that thing Cause that to go crazy on us honestly Uh, so I'm gonna just redo it look okay I want a new layer I'm just gonna basically pretend these ones don't exist Get my pink back put my background in pink back for real My background in I just kind of did four pixels bigger and that seemed to work out pretty well Four pixels on either side would actually be 68 total And then we want to start on minus four so we have four on each side I want it something like this Then we go select rounded leave that default Yeah Like scrunched it inside didn't it if we go oh I can't get it back can I This while we're here fancy maskey thingy pencil tool black Quite better way of getting rid of the corners instead of doing the copy paste thing like I did before Winners should be gone back to regular Now fill it with green drink it She seems good Um, and I think I'll just do this fill it. We're gonna fill it with the gray Same gray I had do this in a new layer No, if it matters Fill it and then I am Gonna do my same trick here copy paste Um, because I do want it to run off the bottom Oh, we got this weird thing here I do want a new layer That's I don't know why we had one pixel different there Then shrink this by three. Yep fill it with gray. Why did it do it again? Although copy paste is not gonna work because Curves are gonna show up. So I'm actually just gonna take a new slice of it right here that down Okay, now we go mode index Fingers crossed we don't have a billion pinks A billion pinks. Why do we have so many more than last time? RGB Select by color pink row I try to get rid of some of our pinks here row by one And then basically hard fill Now it's more jagged. It's less like anti-aliased or whatever Is there I don't know the right term for that, but more sharp It should mean we have many many fewer Different pinks. Hopefully just a few Are they keeping all of this stuff? Because we don't we have like one one or two maybe if you count this pixel right here as partially pink And maybe this one here and we should have like two or three tops Okay, much better. Yeah, it must have been keeping those other layers still in the palette So first two are pinks All right, so that took a minute, but now we're there I think I'm yeah just redoing six Six basically was a failed one It already changed it. Uh, we will do range only Well, actually we could just hard code the 2.1 and 2 honestly 0 and 1 rather I didn't change the mode back after all of that. I made the exact same mistake as I did last time Oh, no, I didn't it's back to indexed. Oh, I didn't I didn't copy it over. Okay. Yeah So we exported it to here. I actually need to copy it from here Into device nice so that did work so you can Get rid of all of the margin between your tabs by basically ensuring that your tab your tile size Ultimately is relative to the size of your sprite sheet It will be one third Of the width of your sprite sheet if you make sure that is well is an even multiple Of The size you're putting your tab layout in divided by the number of tabs you have If you want four tabs you take your screen width divided by four And then as long as your tile size from your sprite sheet Can divide evenly into that screen size over four then You end up like this where they are butt up right next to each other. There's no gap between them I Will change the gray um We get our color from right now tab text color and Going tab text color so those defaults to gray and white. Why don't we reset them in our test code here? tab showing color Showing tab color showing tab text color Uh So let's make the one that is showing Kind of like this green sort of All the ones that are not currently active will be White or pretty close to white There we go I like that But again like you can make it whatever you want. This is good for testing But you really have like Lots of ability to customize this It's looking pretty good. I will say our Pages are a little high right like they are basically touching Tabs would be nice if they weren't another to look at two again About with the text scaled not so big Have text scale Of it. Oh, we don't we have it only on two actually. That's not bad Still legible to me at least to my eye I think the real test is the touch Let's leave it like this and then once we end up building in the touch. That's when we will really I think Be knowing if this is too small or not Developer friendly customization you built in. Yeah, I that was one of my like design goals with this widget was like I really wanted to support A bunch of different visuals for the tabs but not like I want it to be easy to do at least as easy as it can be and I feel like The way the sprite sheet works I'm not gonna say it's the easiest thing in the world to do It's kind of you know a pain to fiddle with all the pixels and to get it the exact right width If you do want it to be the exact right width Um But it's not too hard and it does give you like a really really big degree of flexibility Uh, which I think is nice I really like the idea of people being able to like from From project to project like be able to use this core component But it could still look entirely different than a different project. I don't want to like Don't make a window design, you know theme or whatever and then just like everything looks like that and Pain to customize. I really wanted it to be and we might offer a default one, but I wanted it to be easy to Really get into the nitty gritty and Change how it's gonna look I feel like we've done that pretty well Um, so the other thing I do want to kind of try to do is have an active tab sprite sheet as well But we would pass the second one of these and then it would change the active tab When the tab is active Um Trying to think though if I'm actually gonna have enough time to That Because I am gonna wrap it up before too long We've been going actually time has flown. We've already been going about an hour and 50 minutes. Is that right? Let me double check Here's our youtube Time. How long have you been running? Nobody knows. Okay. Well, somebody knows but this page sure doesn't Anyway, I started at four my time and it's almost it's 10 minutes still six my time So we've been going almost two hours Let's see the primary tab color match The page background when activated Primary tab color match the page background I'm not sure if I understand what you mean. So basically in the case of this example here since my pages have a black Backgrounds the active tab this well, I think I called it showing the showing tab Would have black instead of gray. Is that what you mean? Basically see Grover in In the context of this particular example at least Is that part we do we have easy ability to customize we could basically just make a different one of these What I could do is just Yes, so it looked like the same sheet of paper. Okay So in this case we know I mean you have to know ahead of time kind of what your backgrounds here are going to be Which of course the user could have supplied a different one. So like You know the tab layout can't necessarily enforce that very well But the user the developer who is developing a program with the tab layout could certainly Could certainly do that by just providing the right color here. So the way that would work is we would basically say We want one of these where it's black instead of gray Basically do this Maybe grow one Row one. Let's look at grow one And that's a little bit bigger than I wanted. So let's go back Kind of nitpicking on these couple pixels here. I don't know how they're gonna end up Let's just try it like this and see how it goes Uh, so then let's go paint bucket colors Oh rgb Paint bucket, what if we don't select control shift? In does it get bigger? No Let's leave it like that I don't know these pixels might be kind of brighter when they actually get drawn may end up Wanting to fill a few more of those black, but that's really really nitpicking the pixels at that point So I'll leave it like this for now and then You know, I don't know if we wanted to change the the green or something we could do that um If we really want to do that right now Still have a different color here for some that's super weird Uh, yeah, I won't mess with the green. I'll leave the green how it is Yeah, I'm gonna leave it how it is for now. Obviously you can change it a bunch of different ways you can change it, but I'm gonna leave it how it is So I'll export this as Seven Hopefully when you're actually using these as tabs you would name one like active and one inactive that would be the Best type of names to use probably Still in testing mode though here, so I'm still just bumping my index But seven here and then we would say active is seven inactive is six Then of course we need the actual code To do it inside of here, which will be a little more complex Uh Well, it maybe it won't be Well, we'll need so first thing we'll need is like active All right, we're gonna need to transparent I didn't put the mode back There's still one and two. Well zero and one We export this as seven We copy it to my device These days I'll remember to do this before exporting it the first time We create two tab objects the same bitmap Different palettes That is true. I do that I don't think I want the tab layout to Really know or manipulate the palettes though, but I I think like that's off the top of my head right now. I don't think I want the tab layout to Know or manipulate the palettes, but I could maybe be convinced Really, I think what it comes down to is what the code looks like as long as the api is not super Difficult to use then maybe I'd be all right with that But I don't have a clear idea exactly how it would work I'd have to play with it some to see if it was like something that I Don't think I like or if it is something that I do think I like Uh for now though, I'm just gonna go with the different image altogether And but really it won't be that different all we really will do is just Other one of these We don't actually need this anymore because we ended up using tab count instead Multi nico code. Yeah, I saw that in the nico I just don't know how it will Because the tab layout doesn't know the background Of the pages or like Really anything about the palettes other than the only the one thing it knows about the palettes right now are Which indexes are meant to be transparent? So somehow you would have to tell it like Which index it needs to change and then what color it needs to change to and if you Like the case of the multiple pinks like we had before So like this one we have multiple grays There's like one two three You know we're getting pretty close to green with the next one, but we have at least three colors here That are different shades of gray. So then like Do we want to have it rewrite all three of those indexes to black or just one of them? um It gets in my mind at least it starts getting harry trying to create an api where the user can convey to it which indexes within the palette to update and what colors to update them to whereas Like this they just provide their own Secondary spreadsheet this also allows you to do totally different things like you could make the inactive tab smaller You could make it not go all the way to the edge for the inactive ones And then the active one grows a little bit like you can change more than just the color this way You can change any aspect you want by providing this Yeah, I had only three index then it then it would be easier. That's definitely true But because we are basically just supporting an arbitrary spreadsheet here. We have no way to guarantee that it will be Three and the fact that we do just have an arbitrary image means that there can be this like anti aliasing effect That's making the blend between the colors a little bit smoother So active we would basically just do the active Create the tile grid Need to save this on self and then It's weird because basically we end up with one too many. I don't know if I like doing it this way I'm gonna write it this way and I may Go back and change it. Uh, so we basically go at the end of this while loop Cry equals plus equals one And here whoops If cry less than Thanks of names minus one Do this create an inactive else Create an active and down here. It's just looping over the group which will contain the inactive one as well So one thing is though our which one is active will not actually update But I think we should get one of them drawn as active at least Yeah So, uh, we need to fix the transparency for one thing These are actually the same Flexibility of an arbitrary image is great for sure useful for shadows. Yep shadows is another one and 3d type effects That's definitely a good point as well. Yeah Okay, so this Does look good. I do like this idea of the same color. So thank you for that for sure Um, I definitely love the way this looks. This looks pretty similar to how I think My brain expects it to look so that's a good call And then right now our problem is that we aren't changing the active one Basically just staying the uh active tile grid on the first index whereas the actual active page is changing the colors So That's where we get a little weird. I think We do that I also don't know if I'm gonna solve it right now. Truthfully I'm gonna take a look See what kind of plant and I come up with and if it feels like a plan I can do in a couple of minutes I'll give it a try but if not then I may Call it a night here So right now we're placing them here. We're just going by eye and basically We have all of them in our group. We're iterating over our group the last one Is the active one or the first one is the active one It must be the first one, huh? But that's weird because ker eye would be less than Names most of the time first three times Then the final time When it would create the active so shouldn't the active one be the last one In the group which then wouldn't it have gotten drawn on the right edge and not the left it or i enumerate That will start on zero Part of tab is i times tab width so on the first one that will be zero And then we ended up with zero plus all this stuff Which we must be the first one right this plus to zero x. In fact, it might even be at zero x I don't know why the first one is the active one and not the last one I'm gonna just for debugging sake at the bottom of this Obviously, we'll take this back out, but i'm gonna just go Abt how grids group zero x plus equals 50 Does the active one actually scoot to the right? at a range I guess It calls this the first time Oh, it got repositioned back by my internal code, but it was it did change the last one So basically they're showing up in the reverse order of what I was expecting I was expecting the last one in the list to be The active one and the first one did not be I guess it's because The first time that draw tabs gets called it's During add content the first time add content gets called It calls draw tabs for the first time at that time The length of names is one The cur i is zero zero is not less than One minus one zero is equal to one minus one So else happens we create the active one we add it to our thing The next time that draw tabs gets called Names is now two Are we recreating are we recreating anyway? I think we're not going to figure this out right now I think is the short of it Um, aside from not knowing not really necessarily understand. I think i'm well I think i'm on the right path to understanding the order I think I was right there the first time we end up doing this because This is not true the next time The next time we call draw tabs we would start back on zero length of names would be two Our current length would be one One is less than two. So we're going to go inside of here To create our label cur i starts on zero zero is less than Two minus one so we go into here So basically what's happening is this is written as a while loop, but it's actually only executing once each time we call draw tabs pretty much under normal circumstances This is basically only ever executing one time through this while loop Whereas in my head it was actually running four times, but that's not the case It's running once each time because names is increasing by one each time And length of tab labels group is also increasing by one because that's what we're adding right here So this is getting bigger And it's always one less than names means we're executing this once The first time it does the active tab every other time it does the inactive tabs because zero is always less than However many names we have minus one after the first time. Yes, okay That's why the active one is first but I think that Probably should get a refactor because I think that's a weird way for it to work truthfully The fact that this is a while loop makes it seem like it should loop multiple times, but it's not actually I think what What we should do is take into account the tab count instead of this loop being based off of These names We I think should have a separate loop based on the tab count Since we made the user pass in the tab count We can just use that instead of names and then we should actually loop four times The first time we call draw tabs It should loop four times Create the three inactive tabs the one active one put them in the group And then at that point we'll be ready to figure out the problem of moving the active one to the correct The correct tab when it's active But I think I want to do that refactor and I don't think I'm going to do it right now because I'm about to go grocery shopping instead Uh, let me read up here I'm tempted to sort the tab object so that the active one is always in the top layer of the tab group Makes the width less critical to Possibly would defeat using indexes though How's it going Johnny? Uh, unfortunately, I'm just about to head out So you can catch the the replay if you want to see what we What we did today Dis sort the tab so that the active one is always on top Yeah, I mean, I think that's how we will end up because how I would like this to work is Loop four times and then the fourth time through the loop is where we will create the active tab Which means it will be the last one Inside of the tab tile grids group right now. It's the first one in But instead I want it to be the last one in which means it would always also be on top of all the other tabs technically So if you found a way to make your tabs like poke out of the columns or something The active one would be on top of the inactive ones, which does definitely make sense Although I think you might have trouble trying to make it poke out with the way that the spreadsheets work No, I'm not actually 100 positive though, truthfully so But that's that will solve that as well by making sure our active one is the last one in our group Then it will always be on top and it will always stay sorted as well. We don't have to explicitly sort it because Uh, we'll loop when we first create it and we'll create it the active one as the last one And then the order will never change after that the x index the x Pixel the x location will change but not the order in the group order in the group will stay the same I think that'll be our plan um I Am gonna head out for now going to do some grocery shopping tonight, and then I'll be back Tomorrow morning. So if folks want to continue on this adventure of the tab layout tomorrow morning, you could find me On uh twitch and youtube it is on a different twitch account a different youtube though It's not under ate a fruit right now We're on the ate a fruit stream because this is a ate a fruit deep dive um You know scott was doing these but obviously scott the uh the lead developer circuit python He's out right now because he just had a child Uh, so he's got many many other things going on in his life certainly Um at some point he'll probably be back and take back over this slot But I usually streamed saturday mornings on my own account foamy guy uh underscore twitch uh on twitch and um i'll post the links in the discord as well So if you do join the discord in that live broadcast chat, which is what's showing on the screen I'll drop the links in the morning right before I get started And I think tomorrow i'll pick it up where I left off here. We'll try to get the uh creation of these tabs working a little bit better Uh differently, I guess. I don't know if it's better or worse, but hopefully better But differently certainly I don't want to just loop this one at a time instead I want to do all four at once Do the ordering we talked about and then after that we'll be able to do the x Uh, so what is morning? Yeah, good question. We are you'll be looking at so whatever time it is. Um I should I meant to actually figure this out in utc and then like put it as my background or something um Basically, uh six hours from now Is 15 after midnight so, uh 15 And three quarters hours from right now 16 hours and then minus the 15 minutes Whatever time that is where you're at then that's when I'll be streaming next And again, though, if you just come to that live broadcast chat I'll drop the links when I'm about to start. So that's another way you can find it as well 10 a.m. Central time is what it is too. If you want to look it up in your own time zone You can convert 10 a.m. Central time to whatever your local time is and that should be the time I'm starting 1 a.m. Oh, uh, you are sorry not 1 a.m. I am I am c. E. T Uh, yeah, thank you, uh, johnny for the link there. Um, so yeah, I'll head out for now Thank you to everybody who watched, um Ask patrick probably left a little while ago johnny Hammy we had a bunch of folks see grover. Thanks for helping out And all the suggestions out how we uh, I you're the one I think who, um Reviewed my page layout. Thank you for doing that. I didn't get to it today But I will get to that tomorrow. I'll go and we could probably merge it with the one other review So as long as I'm remembering correctly, I think you're the one that did that. Thank you for doing that by the way Uh, franklin, I don't think I'm not sure if I ever said hi to franklin, but hello to franklin if you're watching gambler Hammy's arnelin. Ask patrick. Naradok. Liz. Thank you to all you folks Uh, and yeah, I'll be back tomorrow morning and I'll be back next week at the same time as well for a deep dive Ask patrick's back nice, uh has a tent road. Thanks for watching. Yep. Appreciate you watching And yeah, I'll be back tomorrow morning and then next week, uh, friday afternoon In my time at least deep dive time. So until then hope everybody has a good day. Good night. Good weekends. All that stuff Thank you again to everybody