CapeSoft.Com
Clarion Accessories
iDash
Documentation
CapeSoft Logo

CapeSoft iDash
Documentation

Download Latest Version JumpStart FAQ History Templates Classes
Installed Version Latest Version  

Introduction

Our programs are really good at collecting data, but making sense of all that data and turning it into useful information can be a challenge. Reports are good and graphs are great but real-time information collected into one place is better.

iDash allows you to add a dashboard to your program.

The goal of a dashboard is to display all the real-time information to your user that they need to make decisions in a single window. They need to be able to organize this data, and view it in a way that makes sense to them.

Because a dashboard is highly customizable it's no good just creating a window, putting some graphs on it, and calling it done. Rather the dashboard becomes a container, containing many individual Widgets, and the user has complete control over which widgets are displayed, their size and their order.

iDash is designed to be used in Clarion 8 or later and supports both Legacy and ABC template sets.

iDash contains iWidget

A widget is simply a way of displaying data, which can be included on a dashboard. There are many kinds of widgets including your own custom widgets, a Simple Text Widget (included with iWidget) and widget support built into other tools.

iWidget provides the framework for creating your own widgets, or for using widgets provided by other tools. It is an extensible framework which allows other 3rd party developers to add widget support to their products.

Upgrade Notes

  1. From before build 1.02
    In Widget procedures, any embed code of the form
    Self.ValueControl{prop:text} = s
    should be changed to
    Self.Value = s
  2. Code in widget procedures, in the ThisWidget.Reset method, which sets self.text or self.value should be placed before the call to Parent.Reset, not after it.
  3. From build 1.2 two new methods have been added to the interface; Visible and ResetWhenVisible. Classes which implement the iWidget1 interface will need to be updated to this new version. This means Insight 2.40 or later and Draw 4.30 or later (if you are using Graph, or Gauge widgets respectively.)

Reset Optimization

Up to version 1.18 the dashboard, and all widgets on the dashboard were automatically Reset whenever the Window itself was reset. (ThisWindow.Reset in ABC and RefreshWindow routine in Legacy.) While this works fine, those methods are often called in places where a widget reset is not necessary (for example when the widget is not visible) and thus the widgets were being reset too often. Given that some widgets can take significant time to calculate this is an unnecessary burden.
From version 1.20 the template no longer generates a widget reset when the window resets. (There is a template option to generate this code, but it is OFF by default).

To support even more optimizations, two new methods have been added to the interface; VISIBLE and RESETWHENVISIBLE. These methods allow widgets to implement their own optimisations for resetting. The build-in Text Control widget has been updated to support this as has the Insight Graphing widget (Insight Graphing build 2.40) and the Draw Gauge Widget (Draw build 4.30.)

If you have created your own widget that implements iWidget1 then you will need at least empty stubs for these two new methods.

Features

iDash

iWidget

Requirements & Recommendations

iDash does not have any Required products. In other words you can use iDash with the simple widgets provided in your application with no other accessories.

However other accessories may support iDash and may allow you to create widgets based on those accessories. some other accessories which include widget support are;
The process of extending a product to include widget support is documented.

Jump Start

  1. If you haven't yet watched the webinar then this would be a really good time to do that. A couple hours spent doing this at this stage will save you a lot of effort later on, and will also give you a much better idea of what you are able to achieve.
  2. Import the iDash.DCTX file into your dictionary. The table iDashboard will be added to the dictionary. This is the table that will store the user settings. You can change the Driver for this table (along with the Owner and Full path name settings) but leave the Table name, and field names "as is".
  3. Add the Activate CapeSoft iDash Global extension template to the Application
  4. Add the Activate CapeSoft iWidget Global extension template to the Application
  5. Make sure you've read the section on Dashboard procedures, so you understand some of the concepts there.
  6. Add a Dashboard procedure to your application.
    1. Click in the New Procedure button to add a procedure to the application. Give the procedure a name.
    2. On the Defaults tab select "Dashboard control on a window"
  7. Make sure you've read the section on Widgets so you understand some of the concepts there.
  8. Add Widget(s) to your application
    1. Click in the New Procedure button to add a procedure to the application. Give the procedure a name.
    2. On the Defaults tab select "Widget Procedure"
    3. (Optionally) use a widget-aware template as a CONTROL or EXTENSION on the procedure to get started. For example the supplied "SimpleTextWidget" extension.

Widgets

The Dashboard control displays widgets. In order to have widgets to display you need to create them in your app. The purpose of this section is to explain the concepts behind a widget, and how a widget is constructed.

Widget Procedure Template

Widgets are created using the Widget Procedure Template type. For best results click the New Procedure button, enter a procedure name, then go to the Defaults tab and select Widget Procedure. If you add a widget procedure from the Templates tab then you will need to set the prototype manually as well.

The widget procedure can take any number of parameters. It returns a *iWidget1 and hence the default prototype is

(),*iWidget1

If you are making use of a widget supplied as a template, then you can now add that widget to the procedure as an Extension template. For example a Simple Text Widget is included as part of the  iWidgets template. Other templates  exist which add the widget either as an Extension (like Draw Gauges) or as a Control template (like Insight Graphing). Control templates can be added to the Window Designer in the usual way. [1]

The requirements of a widget procedure can be fulfilled by an extension template, or it can be coded directly into the widget procedure. Since templates just do what you can do by hand the rest of this section will assume you are not using a template. For usage of a specific template see the documentation on that template.

The procedure itself has some options for generating some of the code for you. It can help you create a VIEW structure (if you are reading data out of files), as well as create methods in the class for opening tables, closing tables and so on.

One possible point of confusion here is worth mentioning. Widgets are represented in the application tree as "procedures".  While there is a tiny bit of procedure code in a widget procedure, the bulk of the code is actually a new class type. The class usually has the same name as the procedure, but the two are fundamentally separate.

[1] The window is not generated into the Widget itself. The designer is provided simply as a convenient way to add control templates.

Creating a Widget Procedure

  1. Click in the New Procedure button to add a procedure to the application. Give the procedure a name.
  2. On the Defaults tab select "Widget Procedure"

Simple Text Widget

Although you can code your own widgets (described below) it is likely that at least at first you will make use of widgets which are template based. The Simple Text Widget extension template is included with iWidget.

The simple text widget, as the name implies, allows you to display a title and value in the widget space. The value might be a global variable or some calculated value. The widget calculates the font size to use based on the text being displayed and the space available to display it.

Displaying a Global Variable

To create a widget using the Simple Text Widget extension which can display the contents of a global variable follow these steps;
  1. Create a new Widget procedure in your application as described above.
  2. Set the prototype of the procedure to
    (String pText, *? pVariable),*iWidget1
  3. Go to the Extensions tab and add the Simple Text Widget extension to the procedure.
  4. On the Text tab set the Text to
    pText
  5. On the Variable tab set the Variable to
    pVariable
  6. Set the rest of the settings on the Box, Text and Value tab to your preferred settings.
You can now add this widget to your Dashboard control as many times as you like using as many different variables.

Bear in mind that this approach works particularly well when the value you are wanting to display might best be calculated on a background thread. For example you might have a background thread fetching an exchange rate from a web service, putting the result in a global variable. It can also be used for calculations which are "expensive" (time-wise) but which can run on a background thread from time to time.

In other words the widget is able to separate the calculation of the data from the display of the data.

Displaying a Value calculated from the database

Assuming you are not calculating on a background thread it's also possible to calculate values directly from the database and use these in the widget. Here are the steps for doing that;
  1. Create a new Widget procedure in your application as described above.
  2. Set the prototype of the procedure to
    (),*iWidget1
  3. Go to the Data Pad and add the tables (including any sub tables required) to the View Table section.
  4. Go to the procedure Actions. On the options tab tick on the options;
    Generate VIEW
    Generate Open/Close Files Methods
    Generate Save/Restore Files Methods
  5. Still in the procedure actions, go to the View tab, and enter the filter for the view there.
  6. Still in the procedure Actions, go to the View Fields tab and add in all the fields you will need to use in your calculations.
  7. Go to the Extensions tab and add the Simple Text Widget extension to the procedure.
  8. Set the settings on the Box, Text and Value tab to your preferred settings. Leave the Variable setting blank.
  9. In the Widget Class Properties embed point add a field
    Total  Long
  10. In the LoopThroughView Method, Before Loop embed point clear the total
    Self.Total = 0
  11. In the Inside VIEW Loop embed point add the calculation. For example;
    self.total += (LIN:Price * LIN:Quantity)
    Note that in this case Lin:Price and Lin:Quantity should be added to the View Fields as per step 6 above.
  12. In the Local Objects / CapeSoft Objects / ThisWidget / Reset embed point add code to trigger the view, and to place the result in the ValueControl
    Self.LoopThroughView()
    Self.Value = self.Total

    Tip: You could also change the self.Text if you wanted to at the same time.
Bear in mind that normal Clarion database access is possible in the widget as well. So you could, for example, use a PROP:SQL statement to execute a SQL Stored Procedure, fetching the result and displaying it in the widget.

Graph Widget (requires Insight Graphing 2)

Version 2.19 (and later) of Insight Graphing contains support for iDash. If you wish to create a graph widget, which used Insight, the follow these steps;
  1. Create a new Widget procedure in your application as described above.
  2. Go to the Window for the procedure. Choose "Simple Window" as the window type. [1]
  3. Add an Insight Graph control to the window. Don't worry about the size of the control - it's not used.
  4. You can now edit the settings for the graph via Right-click / Actions on the control on the window, or via the procedure's Extensions tab. [2]
  5. It's a good idea to set the graph object name to something unique on the Advanced tab.
  6. Remember you can pass parameters into the procedure, but you can't have any local variables. So if you want the graph to use parameters then add new properties to the graph by going to the Source of the procedure, or add them to the local data pad.
[1] The window itself is never actually generated or used. It's simply a place-holder for the graph control.

[2] There is one point of possible confusion. The widget procedure has support for creating a view for you, and so in the Data Pad you will see the View Table set as <ToDo>. You can ignore this completely - it is not used by the Insight control (which creates it's own view.) So leave the View Table as <ToDo> and add any tables the Insight Graph uses to the Other Files section.

Graphing From a Queue

It's fairly common to create Insight Graphs that graph their data from a Local Queue. Since this is a Widget, not a procedure you can't directly create a queue in the widget. However it is still possible to graph from a queue by making the Queue a property of the widget.

The \examples\iDash\Insight\demo.app contains a procedure as an example of this technique. The process is as follows;
  1. Declare a widget property in the Local Data Pad (or declare it in embed code.)
    Column Name (anything you like, the example uses GraphQueue)
    Data Type: Type
    Base Type: the Type of your Queue. The example uses WidgetQType which is available for your use if you like.
  2. On the app tree, right-click on the widget procedure and choose source. Go to the .Init method (ThisGraph1.Init) and add a line there;
    self.GraphQueue &= new WidgetQType
    The name and Type match the names selected above.
  3. Typically the Queue needs to be loaded at some point. If the data is dependent on other widget properties (date ranges and so on) then add your queue code to the Graph.iWidget1.Reset method.
  4. Now you can set the graph template parameters as you would usually do. Common settings are;
    a) the Point Name and Point Number on the X-Axis tab
    b) adding the Queue to the Data Tab.
    c) For the set setting the Setting the Description (Set tab), Values (Y-Axis tab) and Override Set number (Advanced Tab)

Gauge Widget (requires Draw 4)

Draw Version 4 and later supports created Gauges, and includes support for creating iDash widgets.
  1. Make sure the Draw Global Extension is added to the application.
  2. Create a new Widget procedure in your application as described above.
  3. Go to the Extension tab, and add the DrawGaugeWidget extension to the widget.
  4. Complete the gauge template settings as desired.
For some ideas on how to set up the widget see the example \examples\idash\gauges

Widget Interface

In programming in general it is often useful to separate one thing from another. In the case of iDash the Dashboard control, and the Widgets (which can go onto the dashboard control) are separate "things". By keeping these two things separate it's possible for the whole system to be more flexible, and it allows for the Dashboard and Widgets to be developed separately.

Although these two parts are separate they have a common understanding of their roles. In Clarion this understanding is known as a INTERFACE. In practice this just means that you can create any widget class you like and as long as it implements the sub-set of methods defined by the interface, it will work fine in the dashboard.

If you are not a class programmer then don't worry - you don't really need to understand any of this. The appropriate embed points are provided to you, and as long as you put your code in the correct place, you won't need to worry about the terminology or the underlying technology.

The interface is declared in iWidget.Inc .The interface is numbered so that if the interface is ever extended a new interface will be created, and thus backward compatibility will be preserved.

iWidget1 INTERFACE
  ApplyOptions    PROCEDURE ()
  Display         PROCEDURE ()
  GetOption       PROCEDURE (String pName), ?
  Init            PROCEDURE (Long pParentRegionControl)
  Kill            PROCEDURE ()
  Hide            PROCEDURE ()
  Move            PROCEDURE (Long pX, Long py, Long pWidth, Long pHeight)
  Reset           PROCEDURE (byte pForce=0)
  Resize          PROCEDURE (Long pX, Long py, Long pWidth, Long pHeight)
  SetOption       PROCEDURE (String pName, ? pValue)
  TakeEvent       PROCEDURE (),Long
  Unhide          PROCEDURE ()
END


A widget class can declare more than these methods (and likely will) and it can add it's own properties and so on. But as long as it Implements this Interface above it can be used on the dashboard. The dashboard control will communicate with it's widgets by calling these methods at appropriate times.

Embedding Inside the Widget (Creating your own Widget)

Inside the procedure a Class is declared. This class either Implements iWidget1, or is based on a class that implements iWidget1. [1]

For the purposes of this documentation a trivial widget with a single Image control will be created. This image will take a name, which can be passed in when the widget is first created.

As the widget will be taking in a String parameter set the prototype to something like

(String pImageName),*iWidget1

Note that widgets do not have local data, and you should not declare or use any local data. A single dashboard may contain many of the same widget (called with different parameters) so it has to be completely self-contained. Since we don't have any local data, all the data we want to declare becomes a property of the class.

To see the generated code, and to add the code you want to add, right-click on the procedure in the application tree, and choose "Source". This will allow you to see the generated code and also to enter your own code in the correct places.

Add two properties to the class, something that will hold the Field Equate to the image control and one to hold the passed-in name.

ThisWidget             Class(),TYPE,Implements(iWidget1)
! Start of "Widget Class Properties"
ImageControl             Long
ImageName                String(255)

! End of "Widget Class Properties"
                       End

You will notice that the generated code at the top of the procedure looks like this;

! Start of "Processed Code"
  aWidget &= NEW ThisWidget
! [Priority 5200]

  RETURN aWidget.iWidget1
! End of "Processed Code"

The only place you should embed code here is just before the RETURN statement. And the only thing you should do in this embed point is assign parameters into properties. The name of the object at this point (and only this point) is aWidget. This is also the ONLY point at which you can reference the parameters. So pretty much the only code you need here is moving parameters into properties of the class. For example;

  aWidget.ImageName = pImageName

After this opening part of the code you will see each of the interface methods declared (in alphabetical order).

Not all of the methods require code - some of the methods can be left empty.

Rather than go through them in alphabetical order though I'm going to describe them in their "natural" order, starting with INIT.

INIT

The INIT method is called when the widget is first created. And by contrast the KILL method is called when the widget is killed.
In our example we will use the INIT method to create the Image control [2].

ThisWidget.iWidget1.Init PROCEDURE (Long pParentRegionControl)  ! Probably REQUIRED
  CODE
 
! Start of "Widget Code Section"
  self.ImageControl = CREATE(0,Create:Image,pParentRegionControl{prop:parent})

You will notice that the Dashboard control passes you the equate of a region control which form the boundary of your widget. If you want to store this for later use (into a property) you can, however that is not required.
It is however required that the controls you create have the same parent as the pParentRegionControl

KILL

The balancing code to the Init method goes into the .Kill method;

ThisWidget.iWidget1.Kill PROCEDURE ()  ! Probably REQUIRED
  CODE
 
! Start of "Widget Code Section"
  DESTROY(self.ImageControl)

RESET

The Reset method is called when the dashboard feels the widget needs updating. This includes a call as the widget is first displayed. This is usually the place where you adjust the output of the widget based on the current values. For example;

ThisWidget.iWidget1.Reset PROCEDURE (byte Force=0)  ! Probably REQUIRED
  CODE
 
! Start of "Widget Code Section"
  if self.ImageControl{prop:text} <> self.ImageName and self.ImageControl{prop:visible}
    self.ImageControl{prop:text} = self.ImageName
  end


One interesting thing to note here is that you should avoid changing control properties if they don't need to be changed, and if the control is not visible then it almost certainly does not need to be changed. Reset will be called when the user changes Tab controls, so you only need to update widgets that are visible.

RESIZE

The size of the widget is determined by the dashboard control. It contains a default size, and also allows the end user to resize specific widgets so that it best fits what they are trying to see. When a widget is resized then the .Resize method is called.

ThisWidget.iWidget1.Resize PROCEDURE (Long pX, Long py, Long pWidth, Long pHeight)  ! REQUIRED
  CODE
  ! Start of "Widget Code Section"
  SetPosition(self.ImageControl,px,py,pWidth,pHeight)

MOVE

Widgets can also be moved around on the dashboard, and when a control moves the .Move method is called. A move is different to a resize because the control is being moved, but the size is remaining the same, and for some widgets this may be quite different code. In many cases though (including this example) the actual code in move ends up being the same as in resize. In that case a simple call to resize will suffice;

ThisWidget.iWidget1.Move PROCEDURE (Long pX, Long pY, Long pWidth, Long pHeight)  ! REQUIRED
CODE
! Start of "Widget Code Section"
  self.iWidget1.resize(pX,pY,pWidth,pHeight)

DISPLAY

The Display method is called when the widget needs to redraw itself.

ThisWidget.iWidget1.Display PROCEDURE ()  ! REQUIRED
  CODE
 
! Start of "Widget Code Section"
  display(self.ImageControl)

HIDE & UNHIDE

The Hide and Unhide methods are called when the widget is being hidden, or unhidden.

ThisWidget.iWidget1.Hide PROCEDURE ()  ! REQUIRED
  CODE
  ! Start of "Widget Code Section"
  If self.ImageControl{prop:hide} = false
    Hide(self.ImageControl)
  End

ThisWidget.iWidget1.Unhide PROCEDURE ()  ! REQUIRED
  CODE
  ! Start of "Widget Code Section"
  If self.ImageControl{prop:hide} = true
    Unhide(self.ImageControl)
  End

SETOPTION

The SetOption method allows the Dashboard to change values in the widget. The option and value are passed in as a pair and typically the class will use the name to identify the property being changed.

ThisWidget.iWidget1.SetOption PROCEDURE (String pName, ? pValue)  ! Optional
  CODE
  ! Start of "Widget Code Section"
  case lower(pName)
  of 'imagename'
    self.ImageName = pValue
  end


Exactly what you do with the options is up to you - there is no prescribed behavior for this method, it's simply used as a generic way to pass the widget instructions.

GETOPTION

The opposite to SetOption is GetOption and again there is no proscribed behavior for the method.

ThisWidget.iWidget1.GetOption PROCEDURE (String pName)  ! Optional
ReturnValue Long
  CODE
 
! Start of "Widget Code Section"
  case lower(pName)
  of 'imagename'
    ReturnValue = self.ImageName
    end
 
! End of "Widget Code Section"
  RETURN ReturnValue

The point of the SetOption and GetOption methods is to allow the Dashboard control to communicate with a widget, even if the exact properties of the widget are unknown. These methods thus ensure future compatibility with widgets as yet unwritten.

APPLYOPTIONS

When the dashboard is setting multiple options all together it will complete the set of calls with a call to ApplyOptions. This can be advantageous when a reset (after each option) would be expensive. The most likely code you would put into ApplyOptions is a simple call to reset.

ThisWidget.iWidget1.ApplyOptions PROCEDURE ()  ! Optional
  CODE
  ! Start of "Widget Code Section"
  self.iWidget1.Reset(true)

TAKEEVENT

If your object needs to respond to events, then you can add code to the TakeEvent method.

ThisWidget.iWidget1.TakeEvent PROCEDURE ()  ! Optional
ReturnValue Long
  CODE
  ! Start of "Widget Code Section"
  case event()
  End
  RETURN ReturnValue


In this simple example no events matter so no code needs to be added.

Notes:

[1] Unfortunately it cannot both be derived from a class that implements iWidget1 AND implements iWidget1 itself. Equally it cannot override interface methods defined by the parent class. For this reason, if you are making a class outside of the Widget Procedure Template, it is a good idea that you restrict the code in the interface methods to just calling a same-named method in the class itself. Then the code in the class can be overridden by derived classes. An example of this is the WidgetBaseClass which is included in iWidget.Inc and iWidget.Clw. If you are making a widget class from scratch then deriving from WidgetBaseClass is recommended.

[2] A single widget can consist of many controls - as many as you want or need. This example contains just 1 but see the source of the TextWidgetClass in iWidget.Clw for an example of a widget that uses many controls.

Events and Windows

As mentioned earlier the Widget itself has no window of its own, and hence no ACCEPT loop of its own. At first glance this means that widgets themselves may be limited, however this is not the case.

It's important to remember that the widget is just an object, and even though the code for the object is in the Widget "procedure type", the object itself is being hosted by the Dashboard control (which is itself on a window.) So the object is always running inside an ACCEPT loop, and events are indeed flowing.

The Dashboard control will pass all window events, and specific field events, though to all the active widgets on the dashboard. So you can think of your widget as "running inside the Dashboard window" and conceptually you'll be on the right track.

Calling a Widget, not from the Dashboard

Widgets can sometimes include calculations which can be useful outside of the dashboard procedure. This can lead to the concept of calling widgets, almost like Source procedures, to calculate values. While the basic concept is simple, the actual usefulness of this depends a lot on the widget itself.

To call a widget from source code is relatively straight-forward. The widget procedure itself returns an iWidget1 interface. So, for example;

widget  &iWidget1
  code
  widget &= AverageShipTime()
   ! .. interacting with the widget goes here
  dispose(widget)

Of course the AverageShipTime widget may or may not take parameters, so use those as necessary in the call above. The dispose call is necessary or the program will leak memory.

The actual code which goes between the initial call and the dispose depends a lot on the actual widget.

widget.reset(true)

This line typically resets all the values for the widget. In other words it usually "does the calculation". Then something like

val = widget.GetOption('result')

would return the contents of the result property.

Of course if the widget is mostly visual (like a gauge or graph) then this approach is more complex - requiring a region control on the window on which to place the visual aspects of the widget.

The iDash (Dashboard) Control

If Widgets are one half of the product, then the iDash control is the other. The iDash control can be placed on any window and it in turn acts as a host to any number of widgets.

Creating a Dashboard Window

You can create a new dashboard window by
  1. Click in the New Procedure button to add a procedure to the application. Give the procedure a name.
  2. On the Defaults tab select "Dashboard control on a window"
  3. Add the iDashboard Table to the Other Files section of the procedure data pad.
Alternatively you can take an existing window and place the iDash Control Template on the window. Press "Cancel" when offered the List Box Formatter, and you may need to click on the window 3 times after that to get the Sheet control to appear.

The window consists of two controls - the Widget List control on the left, and the Sheet control on the right. You can add as many Tabs to the Sheet as you like, and you can remove any excess tabs that you don't need.

Add the Dashboard procedure to your Main Menu and/or Toolbar so that it can be opened when the program runs.

Adding a Widget to the Dashboard

Once the dashboard control has been added, the next step is to add one or more widgets to the dashboard. This is done via the Extensions tab, on the iDash Control properties.

Go to the Widgets tab and click on Insert to add a Widget. Note that to do this your application must already have one or more Widgets defined. If you haven't created any widgets yet then review the Widgets section in the documentation first.

Set the following (required) settings for the Widget;
There are other template settings you can set for the widget, for a full list of template settings set the Template Documentation.

Runtime Behavior

When the program is run, and the user opens the Dashboard procedure they will naturally see the dashboard. There are a number of behaviors built in to the dashboard control that allows them to customize the way the dashboard looks.

Widget Flow

When the widget layout changes (widgets turned on or off, widgets resized, or the order of widgets changed) or the sheet control size changes, then the widgets on the sheet control will automatically reflow.

Widgets are drawn left to right, top to bottom, in the order in which they are set (or the order the user has chosen.) Since the widgets may be of different sizes the widget will be drawn in the first available space which is large enough to accommodate the widget. If there is no space available to accommodate the widget (for example if the widget is big, and the dashboard is small) then the widget will not be drawn.

Turning Widgets On and Off

The widget list on the left of the dashboard window contains the list of all the widgets you have added to the Widgets tab in the template settings. A user can turn a widget on or off by double-clicking on the widget in the list.

They can also right-click on a list item and choose Hide or Show (depending on the current state of the widget.)

Some widgets may also support right-clicking on the widget itself and choosing Hide.

Adding Widgets to the Summary

If the Dashboard control has a Summary tab set then the user can right-click on a widget, or on the widget list, and choose Add to Summary. when they do this a copy of the widget will appear on the summary tab, and will appear in the list under the Summary heading.

Note that the widget on the summary is a copy of the widget, the original widget remains on the tab as before.

Changing Widget Order

Widgets can be re-ordered simply by dragging on a widget and moving it to after another control on the tab. The reorder of the controls will be reflected in the list on the left, and the dashboard will then reflow. Note that when the widgets are different sizes the flow may not be what the user was expecting. See the flow rules above for how the flow works.

Changing Widget Size

If you mouse-over the bottom-right corner of a widget then the cursor will change to a resizing cursor. You can then resize the widget to one of the available alternate sizes. The current sizes available are;
  • Normal (This size is set by the values entered on the template Grid tab)
  • Double Top - The widget is twice as wide as normal
  • Double Left - The widget is twice as high as normal
  • Double - The widget is twice normal size
  • Quad - The widget is four times normal size

Reset Fields

Displaying the widgets is great but it is desirable that the widgets reset themselves when things occur. For example if you have a text widget, showing the value in a global variable, then you want the widget to refresh automatically when the value changes. Or perhaps you allow your user to enter a date, or date range, on the dashboard window (using regular ENTRY controls) and you want the widgets dependent on those dates to update automatically when a date changes. To allow for this to happen the template supports Reset Fields. If the value in a Reset field changes then widgets dependent on that field will update.

The check of the resets is done on every event  in the window. So if you change a value somewhere else in the program, then it's a good idea to POST an event to the Dashboard. (See note below)

Reset fields can be added at the widget level. If you find that a single variable will reset all the widgets then this can be set on the Resets tab (outside of the Widgets tab.)

When a field is reset you have the option of calling SetOption (one or more times) so that the widget can be made aware of the new setting. For example if a local date changed, then a widget Fromdate and ToDate Options may need changing. Setting Options is entirely dependant on the widget itself, and what it needs from the dashboard.

Dashboard Control Template Settings

Options Tab - Thread Global Variable

For various reasons [1] [2] it's useful for the thread number of the Dashboard control to be known. It is recommended that you create a global variable (NOT Threaded, type LONG) and set it here. If you are in a Multi-DLL system then add the variable to the Data DLL and in other apps declare it as EXTERNAL. In this documentation this variable is referred to as DashboardThread.

[1] When data changes in the application you can send an Event:Reset to the dashboard window. For example;
Post (Event:Reset , , DashboardThread) ! note 2 commas
This will cause the dashboard window to examine the Reset fields for each widget and (if necessary) refresh the affected widgets.

[2] If the Dashboard is on a non-MDI window, and thus floating outside your Frame, it will need to be directed to close when the Frame closes. this is done by sending it an Event:CloseWindow when an Event:CloseWindow is handled in the Frame. For example
Post(Event:CloseWindow , , DashboardThread) ! note 2 commas

Grid Tab

You can adjust the "Normal Size" of the widgets, and the gap between widgets, on the Grid tab.

Variations

You have a fair bit of control over the "look" of the dashboard. Here are some suggestions for alternate looks; [1] If you do this then you will need to post an Event:CloseWindow to the Dashboard window when your program closes. If you have set the Thread Global Variable then this is very simple to do from the frame.
[2] Placing a Splitter control between the list and the sheet is also a useful addition to the window. Splitter controls are available in ResizeAndSplit.

Using in a Multi-DLL System

In your Data-DLL: In your other applications (that use iDash) - including DLL and EXE apps:

Template Reference

If you need to manually register the template, the files can be found in \clarion\accessory\template\win. Three are two TPL files called iDash.Tpl. and iWidget.Tpl.

iDash Global Extension Template

General Tab

Disable All iDash Features
This disables the iDash template, and no template code will be generated into the application. This is useful for debugging.

Options Tab

Checked Icon
The Widget List displays an icon for the widgets that are currently selected.
Unchecked Icon
The Widget List displays an icon for the widgets that are currently unselected.
Blank Icon
A blank icon.
Save
The user is able to customize the Dashboard to their needs. These changes are stored in a table. In order to allow multiple different users to have different settings you need to identify the user using the program. If your program does not require the user to login then you can leave all these settings blank.
Use Secwin User
Tick this on if your program is using Secwin (by CapeSoft), and the User ID can be fetched from Secwin.
Use Super Security User
Tick this on if your program is using Super Security (by BoxSoft), and the User ID can be fetched from Super Security.
User
If you are using some other system then enter an expression (or variable) here that contains the ID for the current user.

Multi-DLL Tab

This is part of a Multi-DLL program
Tick this option on if this app is part of a multi-app suite. All the apps in the suite should have this on including the Data DLL and the EXE app.
Export iDash class from this DLL
Tick this on only in the Data DLL.

Classes Tab

Refresh Classes
Click on this option if you have recently updated iDash and you are getting compile errors. You will need to click this in the Data DLL app especially and recompile that.

iDash Control Template

Options Tab

Disable this template
This disables the iDash template, and no template code will be generated into the procedure. This is useful for debugging.
Dashboard Name
Enter a unique name for this dashboard here. This setting is used when saving the user preferences. Since your application can include multiple dashboards, this name keeps the user settings for each dashboard separate. This value is not displayed to the end user.
Thread Global Variable
It can be useful for the program to know which thread this dashboard is running on. See Dashboard Control Template Settings for more about this setting.
Summary Tab
If the dashboard has a Summary tab, then select the tab here. If you want to turn off this option for the end user, then set this setting to blank.
Refresh on RefreshWindow
This option is off by default. If on then it triggers a call to the RESET method of each widget whenever the WindowRefresh routine (in Legacy) of thisWindow.Reset method (in ABC) are called. This can lead to more resetting of the widgets than is necessary.

Widgets Tab

Widget Procedure
This is the name of the Widget procedure. the same widget procedure (presumably with different parameters) can be added multiple times to this widget list. However each time it needs a unique equate (see below.)
Parameters
If the widget procedure takes parameters then enter them here.
Equate
Each widget on the window needs a unique equate name. This can be any legal clarion label (ie no spaces allowed). Do not use quotes for this field.
List Text
This is the text that will appear on the widget list. This field is an expression, so use quotes around any literal text.
Initial Size
This is the initila size of the widget. The user can resize the widget away from this size if they like.
On Tab
Select the Tab control this widget will be placed on.
Chosen By Default
If this is on then the widget will be displayed by default. The user is able to turn off this widget if they like.
On summary By Default
If this is on then this widget will be added to the summary tab by default. The user is able to remove the widget from the summary tab if they like.
On Click Procedure
The name of the procedure to call when the user clicks on the widget. Note that some widgets may have their own on-click settings which may override this setting.
Start New Thread
Tick this on if the On-Click procedure should start in a new thread. If it does not start in a new thread then the dashboard window will be blocked while this on-click window is open.
Parameters
Enter any parameters for the on-click procedure here.
Watch Field
Select a Global or Local field variable. If this field changes then the widget will be Reset.
Set Option
When the variable being watched changes then this option will be sent to the widget via the SetOption call.
Value
This is the value assigned to the option above.

Grid Tab

Normal Size: Width
The Normal width of the widget (in dialog units). the user will be able to size the widget bigger than this, but not smaller than this.
Normal Size: Height
The Normal height of the widget (in dialog units). the user will be able to size the widget bigger than this, but not smaller than this.
Horizontal Gap
The amount of horizontal space between widgets. In Dialog Units.
Vertical Gap
The amount of vertical space between widgets. In Dialog Units.
Max Columns
The maximum width that the widgets will flow to. (Each normal width counts as 1 column). If this is set to 0 then the Sheet control will determine the maximum number of columns.
Max Rows
The maximum height that the widgets will flow to. (Each normal height counts as 1 row). If this is set to 0 then the Sheet control will determine the maximum number of rows.

Resets Tab

These resets apply to all the widgets on the window.
Watch Field
Select a Global or Local field variable. If this field changes then all the widgets will be reset on the next event in the procedure.
Set Option
When the variable being watched changes then this option will be sent to all the widgets.
Value
This is the value assigned to the option above.

Class Tab

Object Name
This is the object name. Defaults to Dashboard
Class Name
This is the class the object is derived from. Defaults to iDashClass

iWidget Global Extension Template

General Tab

Disable All iWidget Features
This disables the iWidget template, and no template code will be generated into the application. This is useful for debugging.

Multi-DLL Tab

This is part of a Multi-DLL program
Tick this option on if this app is part of a multi-app suite. All the apps in the suite should have this on including the Data DLL and the EXE app.
Export iDash class from this DLL
Tick this on only in the Data DLL.

Classes Tab

Refresh Classes
Click on this option if you have recently updated iDash and you are getting compile errors. You will need to click this in the Data DLL app expecially and recompile that.

iWidget Procedure Template

Options Tab

Generate View
If this option is on then a VIEW structure will be generated in the procedure. The VIEW is generated from the Primary file (and any linked secondary files) on the Data pad. a Method called LoopThroughView is also generated into the widget.
Generate Open/Close Tables Methods
If this is on then methods for opening and closing the Tables on the data pad are generated into the widget.
Generate Save/Restore Tables Methods
If this is on then methods for saving and restoring the Tables on the data pad are generated into the widget.
Generate Interface Calls in DebugView
If this is on, and the widget has Interface methods, then Trace statements will be generated into each Interface method. This can make debugging your code easier as you will be able to see when each interface method is called.
Generate Trace Method
Tick this on to generate a Trace method into your widget. This method allows strings to be sent to Debugview.

Classes Tab

Widget Class Name
This is the widget class name. It is usually the name as the procedure name.
Widget Base Class
This is the class you are deriving your widget from. This can be left blank if you are not deriving from any existing class.

View Tab

Order
Enter the ORDER property for the view here. This field is an expression, so put quotes around an explicit string.
Filter
Enter the FILTER property for the view here. This field is an expression, so put quotes around an explicit string.
Send order and filter to Debugview
This is used for debugging. When on the prop:Filter and prop:order of the view will be sent to Debugview so that any mistakes can more easily be spotted.

View Fields Tab

Hot Field
Hot Fields are added into the VIEW. Make sure that any fields you use in embed code are added to the Hot Fields list here.

Simple Text Widget Extension Template

Options Tab

Tip
Enter an expression here which will appear as a tooltip when the user moves the mouse over the widget.
Disable this template
Tick this on to disable this template in this procedure. If this is on then no template code (from this extension) will be generated. This can be useful for debugging purposes.

Box Tab

The background of the Simple Text widget is a box control. The settings on this tab control the "look" of the control. There are settings for the Header part, and settings for the whole widget.
Round
Tick this on if the box should have rounded corners.
Fill Color
Set the fill color of the box here.
Border Line Width
Set the line width for the border line that goes around the box control.
Border Line Color
Set the color of the box border.

Text Tab

The Text field uses the top half of the widget. It usually contains some sort of description of the value being displayed.
Text (expression)
This field is an expression, so enter a fixed value, or a widget parameter variable here. If this field is left blank then you can set the contents of the text control in code using;
self.TextControl{prop:text} = 'something'
Background Transparent
Tick this on if the text control should be transparent.
Background Color
If the background is not transparent the enter the background color here.
Justify Text
You can set the text to be Left, Right or Centre justified.
Font Name
Set the Font name here. Press the V button to use a variable, or use the Select Font button to select a font.
Font Size
Set the starting Font Size here. Note that this value is just a guide, the widget will resize the text to fit into the available space.
Font Style
Set the font style here.
Font Color
Set the font color here.
Font Charset
Set the font Charset here.
Select Font
Click on this button to set all the font properties from the regular Windows Font Dialog.

Value Tab

The Variable field uses the bottom half of the widget.
Variable (not expression)
Enter a Global Variable, or parameter here. Or leave this field blank. If blank then you can set the value in code using
self.Value = 'something'
Expression
If the value is set to be an expression, then the expression is re-calculated, and re-assigned to the .Value property whenever the widget is Reset.
Background Transparent
See Text Tab above.
Background Color
See Text Tab above.
Justify Text
See Text Tab above.
Font Name
See Text Tab above.
Font Size
See Text Tab above.
Font Style
See Text Tab above.
Font Color
See Text Tab above.
Font Charset
See Text Tab above.
Select Font
See Text Tab above.

Adding Widget support to other 3rd party templates

This section is for writes of Clarion templates that wish to take existing templates and add support to them so that  the template can be used as a widget. If you are not a template writer then feel free to skip over this section.

Examples

ABC

In \Clarion\Examples\iDash\ABC folder.

This example shows

Legacy

In \Clarion\Examples\iDash\Legacy folder.
Same as the ABC example above, but based on the Legacy templates not the ABC templates.

MultiDllABC

In \Clarion\Examples\iDash\MultiDLLabc folder.

This example contains 3 apps in the solution.
DataDLL.App is the root DLL which declares and exports all of the classes.
Functions.App contains all the browse and form procedures.
Demo.App contains the Frame procedure and compiles as an Exe.

Note the settings on the Multi-DLL tab (on the iDash Global extension) on all 3 apps. For more information on the settings see Using in a Multi-DLL System.

MultiDllLegacy

In \Clarion\Examples\iDash\MultiDLLLegacy folder.
Same as the MultiDLLABC example above, but based on the Legacy templates not the ABC templates.

Insight

In \Clarion\Examples\iDash\Insight folder.

This example adds Insight Graphing widgets to the dashboard. (Requires Insight 2 or later)

Gauges

In \Clarion\Examples\iDash\Gauges folder.

This example adds Draw Gauges widgets to the dashboard. (Requires Draw 4 or later)

Class Reference

coming 

Frequently Asked Questions

Support

Your questions, comments and suggestions are welcome. See our web page (www.capesoft.com) for new versions. You can also contact us in one of the following ways:
CapeSoft Support
Email
Telephone +27 87 828 0123

Installation

Run the supplied installation file. All the necessary files will be installed, and the templates will be registered (assuming that option was on.)

If you need to register the templates manually be aware that two TPL files need to be registered. They are iDash.TPL and iWidget.TPL.

Distribution

This product is supplied as source files that are included in your application. There are no additional files for you to add to your distribution.

License and Copyright

This template is copyright © 2023 by CapeSoft Software. None of the included files may be distributed. Your programs which use this product can be distributed without any royalties due on this product.

Each developer needs his own license to use this product. (Need to buy more licenses?)

This product is provided as-is. Use it entirely at your own risk. Use of this product implies your acceptance of this, along with the recognition of the copyright stated above. In no way will CapeSoft Software, their employees or affiliates be liable in any way for any damages or business losses you may incur as a direct or indirect result of using this product

Version History

Version 1.22 (22 June 2023) Version 1.21 (7 June 2023) Version 1.20 (21 May2021) Version 1.18 (15 October 2020) Version 1.17 (26 May 2020) Version 1.16 (26 May 2020) Version 1.15 (20 May 2020) Version 1.14 (3 April 2020) Version 1.13 (14 September 2018) Version 1.12 (23 March 2018) Version 1.11 (10 January 2018) Version 1.10 (4 August 2016) Version 1.08 (9 June 2016) Version 1.07 (12 May 2016) Version 1.06 (11 May 2016) Version 1.05 (27 April 2016) Version 1.04 (22 April 2016)

    Dashboard Control Version 1.03 (18 December 2015)

    Dashboard Control Version 1.02 beta (5 May 2015)

    Dashboard Control     Widget Procedure Type     Simple Text Widget     General Version 1.01 beta (2 March 2015) Version 1.00 beta (19 December 2014)