This week we will be covering the new v19 WinDev Dashboard features. This was one of the Devcon presentations, so those that attended Devcon have had the benefit of this information for over a month now!
In this webinar we will go over all the functions available via the Dashboard features. And look at the code for a simple dashboard example application. After the Webinar the application will be available for download as well.
Today, we will be looking the sample dashboard that I created for WxDevcon, this example shows the capabilities of the dashboard features and hopefully will inspire you with a few ideas for incorporating a dashboard into your own apps.
If you have not worked with dashboards they are not as hard as you might think, especially if you have worked with Internal Windows before. Each widget of the dashboard is actually just an Internal Window. And the dashboard control itself is just a grid of Internal Window controls with some cool interface features that all the user to reconfigure it. They can change the position and size of each widget, add and remove widgets, and save their configuration of the dashboard, so that each user can have their own “version” of the dashboard. The concept of the dashboard is similar to the Android Home screen with widgets or the windows 8 metro interface with live tiles.
Let’s start will a quick peak at the dashboard.
We will look at some of the features of the dashboard as we explore each widget. But lets start first with configuring the Dashboard control in the IDE.
This is how my dashboard looks at design time
As you see its just a grid of boxes to hold each widget. The details tab of the dashboard control contains most of the configuration settings
You have 3 options for how your widgets are created.
1. Variable width, which means as the window is resize the widgets get wider.
2. Variable number of widgets, which means as the window is resize more “boxes” appear to allow for widgets. This is the setting use.
3. Fixed width and number of widgets, which means the widgets to not change size and no more “boxes” will be available, the dashboard just fills with white space as the screen resizes.
Next you set the sizing and padding of your Widgets “boxes”. As you see in the screen shot I made each widget 250 x 250 with 10 pixels of spacing between them. This setting becomes important not only when sizing your widget windows, but also when it comes to resizing them. If a user wants to make a widget wider or taller, it will be done in multiples of this setting. For instance in this screen shot you see that the Recent Activity widget has been made taller and now occupies two widget box areas.
We will look at the runtime interface shortly for how the user resized that widget.
A note on Widget sizing: Andy Stapleton does his dashboard with very small widget sizing, which gives him more control of the size of each widget. It really depends on what type of widgets you are making available to your dashboard. In this example my widgets are more traditional style dashboard widgets, however if you are showing more details information, Andy’s approach might work better for you.
The other settings on the detail tab are for what modifications the user is able to do to the dashboard. These settings affect the AAF menu options. Notice I turned off all of these settings. Instead I add them via a setup button. I find that to be more intuitive to the user than the AAF menu.
Which brings us to the next topic, since I have added the options to my own settings button the only two options I want on the AAF menu are Add and Hide. This means that only when the user puts the dashboard into edit mode, via my settings button, will there be a popup AAF menu and then it will only have the Add and Hide options. You configure the AAF settings on the GUI tab, under the Popup Menu settings.
The content tab is where you can configure the default configuration of the dashboard, meaning which widgets show up in which “boxes”. The interface for doing so is fairly intuitive, however there is one downside, you can not pass parameters to the widgets via this content tab. So instead I have hand coded my initial configuration, so that I can pass parameters to one of my widgets. Here is the initiazation code I have in my dashboard window.
At first glance this make look a little daunting but really it is just two commands repeated for each widget.
The first command, DashAddWidget, tell the Dashboard which widgets are available to it. This is how the dashboard know which widgets to show on the “Add” menu. The first parameter is the name of the dashboard control, the second is the name of the internal window that will be the widget, and next is the name of the widget, which is how the name will be displayed on the “Add” menu.
The second command, DashInitialConfiguration, is what actually places the widget on the dashboard. DashAddWidget, just make the widget available, DashInitialConfiguration is what actually places it on the dashboard. Notice that DashAddWidget returns a ID for the widget, and we use that ID for DashInitialConfiguration. Next is the X and Y position, which box, the widget will appear in. And finally the width and height of the widget, how many boxes). Notice the profit by month, on line 13, is being setup as 2 widgets wide, and the In/Out board on line 17 is being setup as 2 widgets tall.
It is worth noting that all we are doing is setting up the initial configuration for the dashboard. If we allow the user to adjust the dashboard, they the positions and sizes can be changed, so we are really just setting up the “Default” display.
Notice on line 18 the DashAddWidget has an additional parameter. There are four versions of the Sales Gauge (Day, Month, Qtry, Year). I do this by passing a parameter to the internal window. I didn’t want to write 4 windows, and I wanted all four to be available on the “Add” menu. This parameter is not available via the content tab, which is why I hand coded the configuration.
Also notice that Lines 20-22 are adding the other versions of the Sales Gauge to the “Add” menu, but there is no corresponding DashInitialConfiguration command. I am making them available to the dashboard, but not displaying them by default.
The only other initialization code I have is to save the initial configuration, incase I ever want to restore it and then to load the logged in users configuration of the dashboard.
I am using my Default manager to accomplish this. But the concept is the same reguardless of how you chose to store the configuration. There are two command DashSaveConfiguration, and DashLoadConfiguration. The entire configuration of the dashboard is generated as a string. So you could store it on a field on your user record, in an ini file, the registry, etc.
One thing to note, during testing you might notice a toast message similar to this popping up with you use the DashLoadConfiguration command.
This message only appears in test mode (running via the Go button), when you create an executable the message will not appear. Please do not ask me how much time I spent trying to figure out how to get rid of that message before I asked support about it 🙂
When you add a Dashboard control to your window, it includes 4 local procedures, that fire for each of the editing actions of the widget. As you can see in this code, I am using those procedures to save the current configuration of the dashboard for the user anytime, they modify the configuration.
As mentioned instead of using the standard AAF menu, I created a setup button with a popup menu as I felt that was a little more intuitive to the users.
As you can see there are 3 options on the menu. Refreshing the Desktop, Switch Edit mode on and off, and restoring the default configuration. And here is the code behind those 3 options.
Refreshing the dashboard is done with a DashDisplay command. This is similar to issuing a TableDisplay for a table control. When we look at the individual widgets screens we will see how we handle this from the widget side.
Switching the edit mode on and off is done via the DashMode function. As you see there are constants that allow us to control which abilities the user has.
And restoring the default configuration uses the default configuration that we stored via the Default Manager.
That is all there is to setting up the actual Dashboard, so now we can move on the the individual widgets, which again remember are really just Internal windows.
First we have the Date and Time widget
Nothing earth shatter on this window by any means. I have a local procedure that I setup as an automated procedure that runs once every minute to refresh the display. This is so the time continues to update as the widget is displayed. This is different than the DashDisplay refresh method that we will look at in the next example.
The only other thing to note about this widget is that I don’t want the user to be able to resize it. It makes no sense to change its size, so I set the Max width and height to the intial width and height, and now the widget can not be rezied.
Next is the current conditions widget
The first thing to note concerning this widget is we have code that refreshes this widget when the dashboard is refreshed using the DashDisplay command.
Notice a new event is available to use on internal windows, “Refreshing the Widget”. This is an optional event that is not displayed in the code editor by default. To expose it you need to click on the icon indicate in the screenshot above. Any code place in this event will run anytime a DashDisplay command is issued. In this instance I am running the automated procedure to refresh the widget, as I also want the widget to refresh periodically, even if the dashboard is not refreshed.
I also added a refresh button to the widget so the user can refresh the conditions manually when ever they like as well. So as you see there are several ways to control the refreshing of your widget, and it will depend on the content of the widget, which method you chose.
Note I also include a settings button for this widget that allows the user to switch the display between Fahrenheit and Celsius.
Our next widget is the Profit by Month
Nothing really to note about this widget other than that it is defined as 500 x 250 pixels, so by default it uses up 2 widget boxes.
Next is the Quick Buttons widget.
This could be a handy feature where you allow the user to configure the functions they use the most into a Quick Launch bar. Not really a dashboard feature but worth mentioning is thanks to WX’s ExecuteProcess command I am able to “press” the button from the ribbon bar instead of replicating that code for this widget.
Next is the In/Out Board widget.
Which is defined as double height, but can be resized by the user.
A few more examples of WX functionality that are worth noting even though they are not Dashboard features is notice that the “Out” employees are colored red using this bit of code in the Displaying a Row event.
Another subtle feature that most users won’t even notice, but they would notice if it isn’t there, is that I remember their sort order. Every time the widget is refreshed the table is rebuilt which would destroy the sort order. To avoid this I capture the sort order, and then reapply it after redisplaying the table.
The next widget is the Sales Funnel, nothing to note concerning this widget, it is using the refresh features that we have already discussed.
Then comes the Recent Activity Widget
This is a feature that I have been adding to my applications in one form or another for years. Its a quick link back to anything the user recently worked on. Such as the last invoice they added. Another version of this would be for items that are coming up, such as a to do list with quick links to the functions required. It is just another way to make your users life a little easier.
One bit of code to note on this widget is the number of recent entries to display is based on the size of the widget. My original code was calculating this based on the pixel size. But while doing the webinar Wolfgang pointed out that I could just use the LooperCount function in order to do this. Just another example of how great this Google+ community and the sharing via Webinars and post is! Thanks for the tip Wolfgang.
That brings us to the Sales Gauge widget
As already discuss this window uses a parameter to determine which “version” of the Gauge the widget is, which is why I handcode the initial configuration.
A few other non dashboard related “tricks” to note here. Notice that my Gauge has 2 needles on it. I use this a lot to display comparisons, or the high/low versus current mark etc. You may be wondering how that is done since the gauge control doesn’t support 2 needles. There are actually 2 gauge controls overlaid on top of each other.
The next subtle addition you might notice is the Thumbs Up or Down image at the center of the gauge, again this is an image that is overlaid on the gauge, and then I dynamically switch the image via code.
And that is the conclusion of our discussion on Dashboards, hopefully I have convinced you that they are not that hard to create, and inspired you with some ideas on a Dashboard you might incorporate into your own apps. One last exciting note before I close out this article. Dashboard are coming to WebDev with version 20. From what I have see it looks like the exact same commands. I am very excited to see and try this feature, as many of you know I do the majority of my work in WebDev. You can be sure one of my first post concerning v20 will be on WebDev Dashboards!
The NextAge example application that include this dashboard example, as well as all of my other open source classes and code can be download here.
Uncle Pete’s Corner is webinar series on all things WX, to watch the watch the Uncle Pete’s corner webinar that is the companion to this article, and many other WX related webinars go to the WinDev US YouTube Channel and be sure to also join the WxLive – US Communityon Google+ to get notices about upcoming webinars. On the Google+ community you will find a active group developers discussing all things WX.