WxSmith tutorial: Building more complex window
Building more complex window
Hi, in this tutorial I'll show you some examples of more complex windows. Actually it would look complex when you start working with wxSmith. After writing a few applications you will probably build a few resources with this or even higher complexity so don't be scared. I'm working with wxSmith almost every day (it's really the best way to find bugs and discover nice improvements and that's what I should do as it's creator ;)) and although it may look complex at the beginning, you can quickly get comfortable with it.
I also want you to know that as I'm writing the beginning of this tutorial, I'm also beginning to write the application - I didn't prepare a ready solution since I would like to show the process of creating a window in natural way (maybe even with some mistakes), so while writing the tutorial I'll also create the application.
We will start with an empty frame - if you've read the previous tutorials you should create one without problems.
First task - some basic concepts
My proposition for an example application would be something to manage a colleciton of CD-roms. So at the beginning we should realize what should be presented at the main window. Let's say that we would have most of the information in the main window (although it may not be a very good assumption, it would help to show the creation of more complex resources).
I would like to have some list of CD-roms on the left and some details of the selected CD-rom on the right. So basically we have two regions in our window: one with the list and one with the details. I'd like also to use sizers because the application should be cross-platform and the main window should be resizable.
Building skeleton
If want the application to look nice on both windows and linux, we should do some tricks presented in the first tutorial - we had to add an extra wxPanel into the frame to make the background better. Let's to the same thing here:
- First add wxBoxSizer directly into the resource
- Add wxPanel into that sizer
- Set size of border to 0 to make the panel cover entire window
Now we should have this result:
Now let's add wxBoxSizer into it - this sizer will manage our two main regions. After that the tree structure should look like this:
Now we can start filling those two regions - each one may have only one item (so the sizer we've just added will manage them). Usually in such situations I use wxStaticBoxSizer because we can mark regions and give some name to them. So let's add two wxStaticBoxSizer-s into the window. Be careful while adding the second one because you may add it into the first region - always remember that parent for new items is always the item totally covered with blue:
To add second sizer properly you must click on the border surrounding the first one just like in the picture. Note that now the resource is small but it will change when we will add some items into the regions.
Building the List of CDs region
Ok, now let's add some items which will show a list of CDs. We can use wxListBox here:
The list is rather small so let's resize it using drag-boxes to something bigger and higher:
Ok, but the second sizer did not resize. That's right since we didn't turn on its Expand' flag. To do this let's click on the second sizer and check its Expand property:
Now we can change the labels of the regions since they are fully visible now. To do this click on each region's sizer and change the Label property:
Ok but we would like to have the ability to add and delete a selected cd - we will insert two buttons for this purpose in the first region. To add the button choose it from palette and add into the sizer. Note that we cannot point to the wxListBox item - it cannot have children so wxSmith will try to add new items before or after it. After adding the button we would have such a result:
Hmm, the button should be under the list, not next to it. wxStaticBoxSizer did align items as it should - by default it aligns them in a horizontal line. To change the direction to vertical, you can change the Orientation property of wxStaticBoxSizer. But before we change it let's predict one more thing. I would like to have two buttons instead of only one and I'd like them to be aligned horizontally. Since wxStaticBox will be changed to vertical mode, we will have to use another sizer just for the buttons. So let's add wxBoxSizer right after the list and before the button:
Now let's change the Orientation of the wxStaticBoxSizer to vertical. After changing we have following result:
We can see that something's wrong here. The wxBoxSizer is abnormally stretched and if we scroll the editor we can see that the same goes for the button. We said in a previous tutorial that wxBoxSizer and wxStaticBoxSizer are trying to keep same size of items in one direction - that's what happened here. wxStaticBoxSizer used the tallest item (list of CDs) and applied this height into all managed items. How to disable it? By setting the Proportion property of both wxBoxSizer and wxButton to 0. This will notify the sizer that those items shouldn't be used in height calculations:
Now let's move the button into the wxBoxSizer - you can very easily do it by clicking on the button and dragging it into the sizer. After that we can add the second button next to the first one:
Now we can see that the list doesn't have the Expand property set (otherwise it would be almost as wide as the region.
Now I'd like to see how resource currently looks in the application. We could by simply running it (F9) or by pressing the preview button on the right part of the wxSmith editor:
(If you run the application you will see that there's a menu and statusbar. On the preview they won't show up; wxSmith still misses a few features ;) )
Our window looks good, not perfect but let's leave some polishing for later and fill the CD details region.
Building CD details region
Inside CD details I'd like to have a description of the CD:
- Type (Music/Program/Backup/Other)
- Title
- Artist/Author
- Date of release
- Description
For such a list we would need some type of grid sizer. Ok, but the region has a wxStaticBoxSizer which aligns items only in one line. To overcome this limitation we can just add another sizer into the wxStaticBoxSizer and use the new one as the grid. From the two available sizers I suggest wxFlexGridSizer (wxGridSizer would force all cells to have same size which wouldn't look good because the row with descriptions may need some more space than the others). So let's add the new sizer:
- Add wxFlexGridSizer into wxStaticBoxSizer
- Check the Expand property of the new item
- Set Border Size to 0 to avoid some unwanted border.
Adding items
Data presented here should be shown in two columns - the first for the label and the second for the value, so let's change the Cols property to 2. And now it's time to add the content. For labels we will use wxStaticText and for the value we will use different items:
- wxChoice for Type
- wxTextCtrl for Title, Artist/Author and Description
- wxDatePickerCtrl for Date of release
After adding the items we should have the following view:
Hmm, as I've said at the beginning - I didn't prepared anything before writing this tutorial. And guess what. It looks like wxDatePickerCtrl is broken on linux and sometimes crashes C::B (I didn't check on windows), don't know yet whether it's in wxWidgets or wxSmith - I'll have to investigate it. So we will have to change wxDatePickerCtrl to something else or remove it.
There's an alternative for wxDatePickerCtrl - wxCalendarCtrl so first let's try to replace wxDatePickerCtrl. First we will have to remove the wrong item (by using the 'delete' key or by pressing the 'X' button on the right side of the editor). After the change we can see that the generated calendar is quite large compared to the other items in this region. We can shrink it a little bit by checking wxCAL_SEQUENTIAL_MONTH_SELECTION inside the Style property but it will make the item harder to navigate. We can additionally set the wxSUNKEN_BORDER style to add some nice border around the calendar. Ok, not perfect but acceptable ;)
Now we have this screen:
Customizing and adjusting items
Ok, it looks like we have a few things to do now:
- First is to check the Expand property for the first region since (it didn't expand when the second region increased height)
- Second is to set proper labels for values in the CD details region
- Third is to check the Expand property for all items with values in that region
- Fourth is to adjust items used to edit values in CD details region
The first three tasks are quite easy and I'll leave them to you :)
The fourth task will require a few new things so I'll describe it better:
First let's remove text from text boxes - it's set by default but it would be better to have empty text by default. Text can be changed by modifying the Text property so you should do this very quickly.
Now we have to set some values which could be chosen from the Type value. It's done by editing the Choices property of wxChoice. This is a more advanced value consisting of a few strings, and entering it inside one line of text could be hard. Because of that, instead of text, there's a button on the right side. When you click it, a new window will pop-up where you can enter choices:
Music Program Backup Other
Let's check how does the window resize
We have the first version of our window. But it's not the end of work. If we want it to be user-friendly, it should give ability to resize. We can check it by either showing preview or building and running application. The latter is preffered since it may produce better results. If the window will show, we should experiment by resizing it:
We can see two wrong things in this window:
- Regions did not expand vertically and stay centered
- Content of second region did not react for the resize
The first problem should be cuased by some missing Expand property so let's find it.
First we should check if regions have Expand property set: yes they have so this is not the problem. Generally in such situations we should continue checking in parent item - this is wxBoxSizer which always expand. Next there's wxPanel we used to make nice background and voila: this one does miss the Expand property. So let's check it and test the result again and it works fine.
Now the second issue. Content inside CD details pane was based on wxFlexGridSizer. If you look into previous tutorial you may find out that this sizer has special property called Growable cols. Using this property we can set columns which should resize. I'd like the column with values to grow (we don't need more space for labels, dont we? ;) ) so let's set the Growable cols to "1" (idexes are 0-based). Note that you may quickly find the wxFlexGridSizer by ooking into resource tree - we have only one such sizer in our project.
Now we have some more correct results:
Continue polishing the window
As I look into our window I see that I left few things on the first region. Buttons don't have new labels and there's to much space between them and the list so we can update those things right now.
As usual I'll leave changing the Labels to you - those buttons should be called Add and Delete. And now let's remove the wasted space.
The space is added because each item inside sizers may have extra border. By default it's set to 5 pixels so if we remove the border around buttons we would have more free space. But than the buttons won't have any space between them.
To overcome this problem we could use another property related to border also called Border (jay, I have to fix the naming before someone notice it) which expands to few check-boxes. By checking or unchecking them we can enable or disable border at some item's edge. So if we remove top/bottom/left edge borders of the first button and top/bottom/right edge borders of the second button we would remove extra space but buttons will still have some gap between them. Here's how the property should look like for the first button:
Final words
Here we reach the end of this tutorial. Of course the window we've built is not in it's final shape and it could be adjusted - for example we could add some list remembering when and who borrowed the CD from us and who has it now, we could add some searching and so on. But to keep this tutorial quite short, I've decided to leave all those upgrades to you. I hope that you've learned something new and interesting here. Good bye and see you in next tutorial :)