wxgrid

wxformgrid is a general purpose grid, part of SIMPOL’s wxwn based GUI, and a wxformcontrol much like a wxformbutton or wxformtext. There are two grids in SIMPOL, this is the simpler of the two: wxformgrid, if you want the more comprehensive tutorial check out our datagrid tutorial (here).

N.B. dataform1grid is a wrapper over wxformgrid and so anything mentioned here can be used in its dataform1 counterpart

  1. A basic form
  2. Grid customisation
    a. Customising labels
    b. Playing with cells
    c. Events
  3. Downloads
  4. Source Code

Where to begin

wxformgrid is an at its core just another form control like a text, or a button and is initialised as such, there are some slight, but key, differences in how you initialise a formgrid object. Let’s create a little example program where we declare and initialise a wxform, and on it create grid

function main()
  wxform f
  wxwindow w
  wxformgrid g
  integer e
  string s
 
  s = ""
  e = 0
  w =@ wxwindow.new(0, 0, 800, 600, visible=.false, \
                    captiontext="wxgrid example", \
                    border="simple", maxbutton=.false, error=e)

This code should be familiar to you by now, it is creating a window of size 800 by 600, with a simple border and ‘wxgrid example’ as its title.

if w =@= .nul
    s = "Error " + .tostr(e, 10) + " creating window{d}{a}"
  else
    // Assign the function to handle the user clicking the close gadget
    w.onvisibilitychange.function =@ quit
    // Create a new form
    f =@ wxform.new(w.innerwidth, w.innerheight, 0xC0C0C0, error=e)

This code should also be familiar but I want to mention again the importance of making sure everything is properly initialised and error catching by using if else statements wherever possible to ensure that the program works as intended everytime

I also wanted to mention the onvisibilitychange function quit that is mentioned above, for this example it is very simple but for data critical work this is where you would check that everything is saved before the user quits the program

function quit(wxwindow w)
  wxbreak()
end function

Now back to the normal program

if f =@= .nul
      s = "Error " + .tostr(e, 10) + " creating form{d}{a}"
    else
      // Add the grid control to the form
      g =@ f.addcontrol(wxformgrid, 1, 1, f.width - 2, f.height - 2,\
                        rowcount=50, colcount=30, error=e)

This is the creation of our wxformgrid variable, it has all the standard declarations for adding a control: what type of control it iss, how far left, and how far from the top it should be, and the width and height of the control. Following that however there are two variables you won’t have seen before: rowcount and colcount these are fairly self explanatory but also very important for creating a grid.

Customisation

This program with the relevant ending statements would now create a very simple grid with no labels, no data, and no customisation. Thats the next step, to add all the customisation to make the grid specific to your use case, this can be done in many ways, you can change virtually everything with regards to the grid. Let’s start by changing the column and row labels

Labels

As standard a grid will generate with numbered labels down the side from 1 to infinity and lettered along the top A to Z for as many rows and columns you’ve selected to show. These will all be a standard width, height, font and colour, all of this can be altered

Label Text

To change the text of the label there are two functions:setrowlabels and setcollabels

These are very simple functions, you set the start row or column and then the label strings. For columns:

g.setcollabels(startcol=1, "a column label", "b", "3", "d", "5", "Foo", "gosh!")

And for rows:

g.setrowlabels(startrow=1, "a very long row label", "bb", "C", "IV")

Label widths

The next thing we can do with the labels is to set the row and column widths. The setrowlabelwidth is very basic, there is no individual width control, just a master width

g.setrowlabelwidth(130)

Column widths is more complicated and gives you more freedom.There are several options for column width control, either setting the widths for an individual column:

g.setcolwidths(col=3, colwidth=55)

Or for a whole series of columns like so

g.setcolwidths(startcol=4, endcol=5, colwidth=130)

N.B. If any of the widths are set to 1 the labels can be hidden

Other settings

There are several more genereal purpose settings for labels. The first of these is that in its standard form you can adjust the size of the rows and column by dragging on them, like you can for example in Microsoft Excel. However sometimes this behaviour isn’t desired and to change that behaviour you can use the following function

g.setdraggability(rowheightdraggable=.false, colwidthdraggable=.false)

Other settings that you can change is the labels font and alignments for each. The font needs to be a wxfont type

g.setlabelfont(labelfont)

And for alignments there are several valid values left, right, top, and bottom

g.setalignments(rowlabelalignment="left", collabelalignment="left", alignment="top)

Any two values from opposite vectors can be used here e.g “top, left”

Playing with cells

Now we’ve customised the row and column labels we want to change our focus to the cell’s themselves, as with the labels there is a whole host of things you can do, and we won’t explore all of them here but the first thing we may want to do is set the value of some cells

Setting cell values

You can change the value of a cell to any string, but only strings so if you want to display numbers these will need to be converted to strings otherwise you’ll be presented with Error 40: Incorrect Parameter Type

g.setcellvalue(3, 3, "This is read only")

Another thing you can do with cells is to create a combo box, where a user can select from a series of options, this can be done for an entire row, an entire column or a specific cell.

g.setcellchoices(row=2, col=2, allowothers=.false, "<pick one>", "United Kingdom", \
                  "United States", "Germany", "France", \
                  "Italy", "Sweden", "Spain", "Portugal", \
                  "Norway", "Denmark", "Belgium", \
                  "Netherlands", "Luxembourg", "Greece", \
                  "Ireland", "Austria", value="<pick one>")

The next thing we will try is some multiline text, this is fairly similar to setting normal texts.

g.setcellvalue(row=7, col=1, \
                 value="This is a text that goes over{a}\
                 multiple lines. We will also increase{a}\
                 the height of the row to compensate")

Setting cell width or height

We can now also set the column width for no other reason than to show it is possible

g.setcolwidths(col=1, 190)

Since we have added some multiline text we should probably also set the row height so we can see the full text

g.setrowheights(row=7, rowheight=60)

Setting cells readonly

And then we want to be able to set it to readonly

g.setcellreadonly(3, 3, .true)

There is also a way to set a subset of them or  all the cells to readonly

g.setcellreadonly(startrow=1,startcol=1,readonly=.true)

Cell alignment

To set the alignment for all cells you should use the setalignment function however if you want to change a single cell or a range of cells you are better off using setcellalignment you could of course specify all the cells using this method like so:

g.setcellalignment(startrow=1,endrow=g.rowcount, \
                   startcol=1,endcol=g.colcount, alignment="left,top")

If the alignment parameter is not specified it is assumed that the text should be centred, and providing two values of the same vector will result in an error. Of course it is not required to set the alignment for a range and you can specify just a single row, column, or cell

g.setcellalignment(row=1,col=7,alignment="left")

Cell colours

An additional step that isn’t included in the example program that can sometimes come in handy is setting the colour of either a cell or the text, as standard these are white and black respectively but to set custom RBG for the text and the cell the following functions are useful: setcellbackgroundrgb, and setcelltextrgb. Again as with all setcell functions the following variables can be passed:

row, col, rgb, startrow, endrow, startcol, endcol

Events

The main reason you would choose a grid over a detailblock (tutorial coming soon) is that there are many more event functions that are implementable for the former that aren’t available for the latter. I’ve explained events, as well as listed all of them events and their exact syntax in a different tutorial here

Example Download

This basic example of wxformgrid can be found in your SIMPOL intallation under ...\projects\examples\wxgrid or by pressing the download button below

Example Source Code

function main()
  wxform f
  wxwindow w
  wxformgrid g
  integer e
  string s
  wxfont labelfont, font, strongfont

  s = ""
  e = 0
  w =@ wxwindow.new(10, 10, 790, 590, visible=.false, captiontext="wxgrid example", \
                    border="raised", maxbutton=.false, error=e)
  if w =@= .nul
    s = "Error " + .tostr(e, 10) + " creating window{d}{a}"
  else
    w.onvisibilitychange.function =@ quit
    f =@ wxform.new(w.innerwidth, w.innerheight, 0xC0C0C0, error=e)

    if f =@= .nul
      s = "Error " + .tostr(e, 10) + " creating form{d}{a}"
    else
      font =@ wxfont.new("Arial", 8, "n", "n", "", error=e)
      labelfont =@ wxfont.new("Arial", 8, "n", "b", "", error=e)
      strongfont =@ wxfont.new("Arial", 8, "i", "b", "", error=e)

      g =@ f.addcontrol(wxformgrid, 1, 1, f.width - 2, f.height - 2, font=font, \
                        rowcount=50, colcount=30, error=e)
      if g =@= .nul
        s = "Error " + .tostr(e, 10) + " creating grid{d}{a}"
      else
        g.setlabelfont(labelfont)        
        g.setcollabels(startcol=1, "a column label", "b", "3", "d", \
                       "5", "Foo", "gosh!")
        g.setrowlabels(startrow=1, "a very long row label", "bb", \
                       "C", "IV")
        g.setrowlabelwidth(130)
        g.setcolwidths(col=2, colwidth=110)
        g.setcellchoices(row=2, col=2, allowothers=.false, \
                         "<pick one>", "United Kingdom", \
                         "United States", "Germany", "France", \
                         "Italy", "Sweden", "Spain", "Portugal", \
                         "Norway", "Denmark", "Belgium", \
                         "Netherlands", "Luxembourg", "Greece", \
                         "Ireland", "Austria", value="<pick one>")
        g.setcellfont(row=2, col=2, strongfont)
        g.setcellvalue(3, 3, "This is read only")
        g.setcellreadonly(3, 3, .true)
        g.setcolwidths(col=1, 190)
        g.setcellvalue(startrow=5, endrow=10, startcol=4, endcol=5, \
                       value="This is sooooo cool!!")
        g.setcolwidths(startcol=4, endcol=5, colwidth=120)
        g.setcellvalue(row=7, col=1, \
                       value="This is a text that goes over{a}\
                       multiple lines. We will also increase{a}\
                       the height of the row to compensate.{a}\
                       Use Ctrl+RET to insert new lines.")
        g.setrowheights(row=7, rowheight=60)
        g.setcellalignment(row=7, col=1, "top")
        f.setcontainer(w)
        w.setstate(visible=.true)
        wxprocess(.inf)
      end if
    end if
  end if
end function s

function quit(wxwindow w)
  wxbreak()
end function