Programming Gambas from Zip/FormArranging

Making Controls Expand When a Form is Resized edit

Gridviews and TableViews are often made to stretch and shrink when the window they are in is resized. A form, which is a window, knows how to resize and arrange the controls that are in it. Even when the form opens any controls that can be arranged and expanded will be.

Make a small form with one TableView.

   


Set the arrangement property of the form to Vertical. Set the expand property of the tableview to True. Run the program (f5). Change the size of the window and notice how the size of the tableview changes with it.

Adjust the padding property of the form to 8. Run the program again (F5). The space between the tableview and the edge of the form has increased. The margin inside the form is the padding. Table cells also have padding.

Add a button under the tableview. Run the program again. Move the button to one side of the tableview. Again run the program. Change the arrangement property to Horizontal and try again. Change it back to Vertical.

Delete the button. Add a HBox. Add a button to the HBox. (Alternately, Right-click the button and choose “Embed in a container”, then right-click the container—which is a panel—and Change into... a HBox.)

Controls in a HBox are arranged horizontally.

The spring will push the button to the right as far as it will go. Experiment with and without the spring.

If you make the button wider or narrower it stays whatever width you give it in the HBox.

The button expands vertically to fill the HBox from top to bottom. Change HBox’s height and see. HBoxes expand their controls to fill their height. In panels the button stays the same height but you cannot use springs.

A Spreadsheet to Average Student Marks edit

   

tv1 is a tableview. Its expand property is set to True.

At the bottom is a HBox. Inside, from left to right, is a label labC, a boldface label labAverage, a spring, and a Quit button called bQuit whose text property is “Quit”.

As each number is entered the average is recalculated. Blank cells are skipped.

LabC shows the count and labAverage the average.

Public Names As New String[]
Public Scores As New Float[]

Public Sub bQuit_Click()
  Quit
End

Public Sub Form_Open()

  Names = ["Mereka AIKE", "Ernest AIRI", "John AME", "Stanley ANTHONY", "Natasha AUA", "Veronica AUFA", "John Taylor BUNA", "Romrick CLEMENT", "Philomena GAVIA", "Richard GHAM"]
  tv1.Rows.Count = Names.count
  Scores.Resize(Names.Count)
  tv1.Columns.Count = 2
  tv1.Columns[1].Alignment = Align.Right

End

Public Sub CalculateAverage()

  Dim i, n As Integer
  Dim t As Float

  For i = 0 To Scores.Max
    If Scores[i] = -1 Or IsNull(tv1[i, 1].text) Then Continue 'skip new but unfilled-in lines
    n += 1 'number of scores
    t += Scores[i] 'total
  Next
  If n = 0 Then Return
  labC.Text = "N= " & n
  labAverage.Text = "Avg= " & Format(t / n, "#0.00")

End

Public Sub tv1_Click()
  If tv1.Column = 1 Then tv1.Edit 'numbers column is editable; Enter goes down
End

Public Sub tv1_Activate() 'double-clicked a cell
  If tv1.Column = 0 Then tv1.Edit 'edit a name
End

Public Sub tv1_Save(Row As Integer, Column As Integer, Value As String)

  tv1[Row, Column].text = Value
  If Column = 1 Then
    Scores[Row] = Value
    CalculateAverage
  Else
    Names[Row] = Value
  Endif

End

Public Sub tv1_Data(Row As Integer, Column As Integer)

  If Column = 0 Then tv1[row, 0].text = Names[Row]
  If Row Mod 2 = 0 Then tv1[Row, Column].Background = &hDDDDFF 'light blue
  tv1.Columns[0].Width = -1 'Automatically set width based on contents

End

Public Sub tv1_Insert()

  tv1.Rows.Count += 1
  Scores.Add(-1)
  Names.Add("")
  tv1.MoveTo(tv1.Rows.max, 0)
  tv1.Edit

End

Right at the start two public arrays are created. Names[] is a list of the student names. Scores[] is a list of their results. They match: the first mark goes with the first name, the second mark with the second name, and so on.

The tv1_Data(Row As Integer, Column As Integer) event fires every time a cell needs to be redrawn. It supplies you with Row and Column. It can be thought of as painting the cell.

There is a special consideration with the _DATA event: it does not paint cells that it doesn’t need to. This is great for displaying large numbers of lines. If there are 100,000 lines and you are only showing 15 of them, only the cells on those 15 lines fire the _DATA event, not all hundred thousand. Be careful if you used the _DATA event to put the numbers into the cells! There may be data in only 15 of those 100,000 cells. Here there is no problem, because we are typing the numbers ourselves and every time we finish typing a new number it is put into the cell in the _SAVE event. (tv1[Row, Column].text = Value). When we come to putting values in using the _DATA event from a database, though, we shall only put data into the cells we see. Then we have to remember to do calculations on the internally-held data, not on the displayed contents of cells. To get into good habits, I have used the DATA[ ] array to hold the scores, and this is used in the calculation of averages. If comes down to this: if you are sure all the data is in the cells, use them; if not, use the data where you know for sure it is.

The following lines create a contextual menu for the tableview with four entries:

Public Sub tv1_Menu()

  Dim mn, su As Menu 'main menu and submenu

  mn = New Menu(Me) 'brackets contain the parent, the main window
  su = New Menu(mn) As "MenuCopyTable" 'submenu of mn; alias is MenuCopyTable
  su.Text = "Copy table..." 'first submenu's text
  su = New Menu(mn) As "MenuCopyNames"
  su.Text = "Copy names..." 'second submenu's text
  su = New Menu(mn) As "MenuDeleteRow"
  su.Text = "Delete Row" 'third submenu's text
  su = New Menu(mn) As "MenuRefresh"
  su.Text = "Refresh" 'fourth submenu's text
  mn.Popup

End

Public Sub MenuDeleteRow_Click()

  Names.Remove(tv1.Row)
  Scores.Remove(tv1.Row)
  tv1.Rows.Remove(tv1.Row)

End

Public Sub MenuCopyTable_Click() 'clicked the Copy Table menu item

  Dim z As String

  For i As Integer = 0 To Names.Max
    If Scores[i] = -1 Then Continue
    z = If(IsNull(z), "", z & gb.NewLine) & Names[i] & gb.Tab & Scores[i]
  Next
  Clipboard.Copy(z)
  Message("Table copied")

End

Public Sub MenuCopyNames_Click() 'clicked the Copy Names menu item

  Dim z As String
  For i As Integer = 0 To Names.Max
    If IsNull(Names[i]) Then Continue
    z = If(IsNull(z), "", z & gb.NewLine) & Names[i]
  Next
  Clipboard.Copy(z)
  Message("Names copied")

End

Public Sub MenuRefresh_Click()
  tv1.Clear 'clear the data
  tv1.Rows.Count = Names.Count 'reset number of rows to match Names[ ]
  For i As Integer = 0 To Names.Max
    tv1[i, 0].Text = Names[i]
    tv1[i, 1].Text = Scores[i]
    If i Mod 2 = 0 Then
      tv1[i, 0].Background = &hFFDDFF
      tv1[i, 1].Background = &hFFDDFF
    Endif
  Next
End

The _Menu() event belongs to tv1, the tableview. This event fires when the object is right-clicked (to show a menu). The _Click() event belongs to TableviewMenu. What is that? It is the alias by which the menu su is known. Aliases make one think of secretive men in dark trenchcoats, but it is just the name by which it is known.

mn and su only exist for the duration of the popup menu because they are in the _Menu() event. As soon as you click any item on the popup menu, that sub finishes and mn and su disappear. Luckily, we have said that su is also known as TableviewMenu. The menu itself, when it was created with New, has that name. So any clicks the menu gets are handled by TableviewMenu_Click().

Menus—whether main menus or submenus or menu items— have several events, methods and properties. See Gambas help for:

 
This suspicious character is known by an alias, as menus are.

 

You can tell a menu to Close, Hide, Popup, Show or Delete.

You can tell the program to do things when the menu is clicked, after it hides or just before it shows. Usually it is when the menu is clicked that the menu gets to work.

 

Some properties are boolean (e.g. enabled, checked and visible), others are strings (e.g. text, name), pictures (picture) or variants, which are any type (tag).

</syntaxhighlight>

Programming Gambas from Zip
 ← TextFiles FormArranging ContextualMenus →