GRIDPLUS2 - Example 5
Home Reference Manpage Examples Download License Contact

Example Of a Complete Simple Application

This is an example of a complete "Phonebook" application using the gpdb command to access a TDBC based SQL database. This example is mainly intended to demonstrate how a complete GRIDPLUS application may be structured.

This example assumes familiarity with the previous/earlier examples, as the more basic GRIDPLUS usage is not described in full.

User Guide

Main Window:

The toolbar contains six buttons, each has appropriate pop-up/balloon help:-

Add new record.
Delete selected record.
Edit selected record.
Find matching records.
Display help text.
Exit application.

It is also possible to select a record for edit by double-clicking the required record.

Selecting a record with a right-click will pop-up the following menu:-

The record can be edited or deleted by selecting the required option form the menu.


Add Record:

Pressing the "Add Record" button will display the following modal (toplevel) window:-

The "Add Record" window toolbar contains two buttons, each has appropriate pop-up/balloon help:-

Save new record.
Close "Add Record" window without saving record.

The "Last Name" and "Phone" entry fields must contain data. If there is an attempt to either leave one of these fields -or- to save the record when the field is empty, a screen similar to the following will be displayed:-


Delete Record:

In order to delete a record it is necessary to select a record, by single-clicking a line in the main window list, before pressing the "Delete Record" button.

When this is done the following dialog is displayed:-

Pressing the "OK" button will delete the record. Pressing the "Cancel" button will abort the delete operation.

If no record is selected when the "Delete Record" button is pressed, the following dialog is displayed:-

Pressing the "OK" button closes the dialog.


Edit Record:

Pressing the "Edit Record" button will display the following modal (toplevel) window:-

The "Edit Record" window toolbar contains two buttons, each has appropriate pop-up/balloon help:-

Save amended record.
Close "Edit Record" window without saving changes.

If no record is selected when the "Edit Record" button is pressed, the following dialog is displayed:-

Pressing the "OK" button closes the dialog.


Find Matching Records:

To display records that contain a particular text/number string, type the required find string in the field to the right of the "Find" toolbar button then either; Press the Enter/Return key or the "Find" toolbar button.

Using the sample database and "service" find string, the following is displayed:-

Pressing the either the Enter/Return key or the "Find" toolbar button with an empty find field will display all records in the database.

Note: The find string is matched anywhere in a record and is not case sensitive.


Display Help Text:

Pressing the "Display Phonebook Help" button will display the following (toplevel) window:-

The "Phonebook Help" window toolbar contains five buttons, each has appropriate pop-up/balloon help:-

Display "Top" (begining) of help text.
Display previous topic.
Display next topic.
Display "Bottom" (end) of help text.
Close "Phonebook Help".

The blue/underlined text are links to the various topics in the help text. When the mouse pointer is over a link its colour changes to red. When a link is "clicked" the display moves to show the selected topic.

Clicking on the "Adding New Records" link (or pressing the "Next Topic" button) will display the following screen:-

The previous/next topic buttons can also be used to step through the help text topics. The display will move to show the previous/next topic relative to the last topic selected either by clicking on a link -or- by pressing one of the top/previous/next/bottom topic buttons.

Source Code

#----------------------------------------------#
# Procedure To Display Main Application Screen #
#----------------------------------------------#

proc mainDisplay {} {

   gridplus window . -windowcommand toolbar,exit

   gridplus menu .phonebook:menu {
      ~ {"Edit"   .toolbar,edit :edit16}
      ~ {"Delete" .toolbar,delete :actitemdelete16}
   }

   gridplus button .toolbar -style Toolbutton {
      {.add :actitemadd16 "?Add Record"} {.delete :actitemdelete16 "?Delete Record"} \
      {.edit :edit16 "?Edit Record"} | {.find :viewmag16 "Find" 6} {&e .find-string 20 ~toolbar,find + #} | \
      {.help :acthelp16 "?Display Phonebook Help"} {.exit :actexit16 "?Exit Phonebook"}
   }

   gridplus tablelist .phonebook    \
      -action       double          \
      -command      toolbar,edit    \
      -maintainsort 1               \
      -menu         .phonebook:menu \
      -scroll       y               \
      -selectfirst  1               \
      -selectpage   1               \
      -tableoptions stripe          \
      -takefocus    1               \
      -width 80 {
      0 id           integer hide
      0 "First Name" =firstname
      0 "Last Name"  =lastname
      0 "Phone"
      0 "Department"
   }

   gridplus layout .main -padding 0 -pady 0 -wtitle "Phonebook" {
      .toolbar
      =
      .phonebook
   }

   pack .main
}

#-------------------------#
# Procedure To Add Record #
#-------------------------#

proc toolbar,add {} {

   gridplus window .add -modal 1 -windowcommand add:phone,close

   gridplus entry .add.phone -width 30 -validatepopup 1 -wtitle "Add Record" {
      {|#Toolbutton .save :filesave16 "?Save Record" ! |: .close :fileclose16 "?Close"}
      =
      {"First Name"  .firstname +}
      {"Last Name"   .lastname !notnull}
      {"Phone"       .phone !notnull}
      {"Department " .department}
   }

   pack .add.phone
}

#----------------------------#
# Procedure To Delete Record #
#----------------------------#

proc toolbar,delete {} {
   global {}

   if {! [info exists (.phonebook)]} {
      tk_messageBox -icon error -title "Phonebook: Delete" -message "No record selected for delete" -type ok
      return
   } else {
     set action [tk_messageBox -icon warning -title "Phonebook: Delete" -message "Delete Record: [.phonebook firstname+lastname]" -type okcancel]
      if {$action eq "ok"} {
         gpdb phonedb . {delete from phonebook where id = :(.phonebook:id)}
         gpdelete .phonebook
      }
   }
}

#--------------------------#
# Procedure To Edit Record #
#--------------------------#

proc toolbar,edit {} {
   global {}

   if {! [info exists (.phonebook)]} {
      tk_messageBox -icon error -title "Phonebook: Edit" -message "No record selected for edit" -type ok
      return
   }

   gridplus window .edit -modal 1 -windowcommand edit:phone,close

   gridplus entry .edit.phone -width 30 -validatepopup 1 -wtitle "Edit Record" {
      {|#Toolbutton .save :filesave16 "?Save Record" ! |: .close :fileclose16 "?Close"}
      =
      {"First Name"  .firstname +}
      {"Last Name"   .lastname !notnull}
      {"Phone"       .phone !notnull}
      {"Department " .department}
   }
   
   gpmap {
      .edit.phone,firstname
      .edit.phone,lastname
      .edit.phone,phone
      .edit.phone,department
   } [.phonebook firstname>department]
   
   pack .edit.phone
}

#------------------------------------#
# Procedure To Find Matching Records #
#------------------------------------#

proc toolbar,find {} {
   global {}

   gpdb phonedb . {
      select *
      from   phonebook
      where  firstname||lastname||phone||department like %:(.toolbar,find-string)%
   } .phonebook

   gpset .toolbar,find-string {}
}

#--------------------------------#
# Procedure To Display Help Text #
#--------------------------------#

proc toolbar,help {} {

   if {! [gridplus window .help -windowcommand help:toolbar,close]} {
      return
   }

   gridplus button .help.toolbar -style Toolbutton {
      {.top :playstart16 "?Top"} {.previous :nav1leftarrow16 "?Previous Topic"} \
      {.next :nav1rightarrow16 "?Next Topic"} {.bottom :playend16 "?Bottom"} |  \
      {.close :fileclose16 "?Close Phonebook Help"}
   }

   gridplus text .help.text -scroll y -tags 1 -linkcolor blue/red -linkstyle underline -height 15 -width 50

   gridplus layout .help.main -padding 0 -pady 0 -wtitle "Phonebook Help" {
      .help.toolbar
      =
      .help.text
   }

   pack .help.main

   gpset -| .help.text \
          {<label top:default><font arial:default><size 8:default><bgcolor dodgerblue><color white>\
           <size +10>Phonebook Help
           <size +2></color><bgcolor lightgray>Topics
           </bgcolor>
           <link add>Adding New Records</link>
           <link delete>Deleting Records</link>
           <link edit>Editing Records</link>
           <link find>Finding Records</link>
           <link exit>Exiting Phonebook Application</link>

           <label add><bgcolor lightgray>Adding New Records
           </bgcolor>
           Press the <image :actitemadd16> button to display the <b>Add Record</b> window.\
           This window has two options:-

             <image :filesave16> Save record.

             <image :fileclose16> Close window without saving record.

           The <b>Last Name</b> and <b>Phone</b> fields must contain data. An attempt to\
           save the record -or- move to another field when one of these fields are empty\
           will highlight the field with a red background and display: <color red>This\
           field must not be blank</color>

           <label delete><bgcolor lightgray>Deleting Records
           </bgcolor>
           Press the <image :actitemdelete16> button to delete the currently selected record.

           A delete confirmation dialog is displayed: Press <b>OK</b> to delete the record\
           -or- <b>Cancel</b> to abort the deletion.

           <label edit><bgcolor lightgray>Editing Records
           </bgcolor>
           Press the <image :edit16> button to display the <b>Edit Record</b> window for the\
           currently selected record. This window has two options:-

             <image :filesave16> Save record.

             <image :fileclose16> Close window without saving record.

           The <b>Last Name</b> and <b>Phone</b> fields must contain data. An attempt to\
           save the record -or- move to another field when one of these fields are empty\
           will highlight the field with a red background and display: <color red>This\
           field must not be blank</color>

           <label find><bgcolor lightgray>Finding Records
           </bgcolor>
           Enter a search string into the <b>Find</b> field then press the <image :viewmag16>\
           button to display the matching records.

           The search string is matched anywhere in the record and is not case sensitive.

           <label exit><bgcolor lightgray>Exiting Phonebook Application
           </bgcolor>
           Press the <image :actexit16> button to exit the <b>Phonebook</b> application.

           <label bottom><bgcolor lightgray><b>Phonebook</b> - (c) Adrian Davis 2014
           </bgcolor>}
}

#-------------------------------#
# Procedure To Exit Application #
#-------------------------------#

proc toolbar,exit {} {
   
   phonedb close
   
   exit
}

#--------------------------------#
# Procedure To Save "add" Record #
#--------------------------------#

proc add:phone,save {} {
   global {}

   gpdb phonedb .add.phone, {
      insert into phonebook (firstname,lastname,phone,department)
      values(:(firstname),:(lastname),:(phone),:(department))
   }

   refreshPhonebook

   gpselect .phonebook -max id
   
   add:phone,close
}

#---------------------------------#
# Procedure To Close "add" Window #
#---------------------------------#

proc add:phone,close {} {

   gridplus clear .add

   destroy .add
}

#---------------------------------#
# Procedure To Save "edit" Record #
#---------------------------------#

proc edit:phone,save {} {
   global {}

   gpdb phonedb .edit.phone, {
      update phonebook
         set firstname  = :(firstname),
             lastname   = :(lastname),
             phone      = :(phone),
             department = :(department)
       where id         = :(.phonebook:id)
   }

   gpselect .phonebook -save id
   
   refreshPhonebook

   gpselect .phonebook -restore
   
   edit:phone,close
}

#----------------------------------#
# Procedure To Close "edit" Window #
#----------------------------------#

proc edit:phone,close {} {

   gridplus clear .edit

   destroy .edit
}

#---------------------------------------#
# Procedure To Display Top Of Help Text #
#---------------------------------------#

proc help:toolbar,top {} {
   gpnav .help.text top
}

#------------------------------------------#
# Procedure To Display Bottom Of Help Text #
#------------------------------------------#

proc help:toolbar,bottom {} {
   gpnav .help.text bottom
}

#-------------------------------------------#
# Procedure To Display Next Help Text Topic #
#-------------------------------------------#

proc help:toolbar,next {} {
   global {}

   set topics  [list top add delete edit find exit bottom]
   set current [lsearch $topics $(.help.text)]

   if {[set next [lindex $topics [expr {$current + 1}]]] ne ""} {
      gpnav .help.text $next
   }
}

#-----------------------------------------------#
# Procedure To Display Previous Help Text Topic #
#-----------------------------------------------#

proc help:toolbar,previous {} {
   global {}

   set topics  [list top add delete edit find exit bottom]
   set current [lsearch $topics $(.help.text)]

   if {[set previous [lindex $topics [expr {$current - 1}]]] ne ""} {
      gpnav .help.text $previous
   }
}

#----------------------------------#
# Procedure To Close "help" Window #
#----------------------------------#

proc help:toolbar,close {} {

   gridplus clear .help

   destroy .help
}

#-----------------------------------#
# Procedure To Refresh Display List #
#-----------------------------------#

proc refreshPhonebook {} {

   gpdb phonedb . {
      select *
        from phonebook
   } .phonebook

}

#=======================#
# Start The Application #
#=======================#

package require gridplus 2.11
namespace import -force gridplus::*

# Require TDBC with Sqlite3 driver.
package require tdbc::sqlite3

# Open database
tdbc::sqlite3::connection create phonedb "C:/GRIDPLUS/gridplus211/example5.db"

# Create optionset for toolbars
gridplus optionset Toolbutton {
    -padding   0
    -space     0
    -takefocus 0
    -widget    button
}

# Set errormessage text
gridplus set -errormessage "This field must not be blank"

# Start
mainDisplay

refreshPhonebook

Comments

proc mainDisplay {} {

gridplus window . -windowcommand toolbar,exit

Create a procedure called "mainDisplay" to display the main/root window. Set the "-windowcommand" procedure to "toolbar,exit"; this will invoke the same exit procedure as will be invoked by the toolbar "Exit Application" button, if the window is closed using window manager facilities, to allow the database to be closed properly.
gridplus menu .phonebook:menu {
   ~ {"Edit"   .toolbar,edit :edit16}
   ~ {"Delete" .toolbar,delete :actitemdelete16}
}

Create a menu called ".phonebook:menu". Each menu option has a name, the name of the procedure to be called when the option is selected and an icon.

For Example: "~ {"Edit" .toolbar,edit :edit16}".

This menu option is called "Edit", which will invoke a procedure called "toolbar,edit" and will have the ICONS image called "edit16".

gridplus button .toolbar -style Toolbutton {
   {.add :actitemadd16 "?Add Record"} {.delete :actitemdelete16 "?Delete Record"} \
   {.edit :edit16 "?Edit Record"} | {.find :viewmag16 "Find" 6} {&e .find-string 20 ~toolbar,find + #} | \
   {.help :acthelp16 "?Display Phonebook Help"} {.exit :actexit16 "?Exit Phonebook"}
}

Creates a GRIDPLUS button grid called ".toolbar" using the "Toolbutton" style. Each button has an explicitly defined name, an icon and associated pop-up/balloon help.

For Example: "{.add :actitemadd16 "?Add Record"}".

This button will invoke a procedure called "toolbar,add", will have the ICONS image called "actitemadd16", and has "Add Record" as the pop-up/balloon help.

The ".find" button is compound; It displays both the "viewmag16" image and "Find" text. Next to this button is an entry called ".find-string" which is "20" characters wide. This content of this entry can be accessed as "$(.toolbar,find-string)". The "+" widget option gives keyboard focus to the entry. The "~toolbar,find" option causes the "toolbar,find" procedure to be invoked if the Enter/Return key is pressed while the entry has keyboard focus. This is the same procedure as will be invoked by the "Find" toolbar button. The "#" option specifies the style for the entry. As the style name is not specified, the default style is used. This is neccessary here because the button grid is set to use the "Toolbutton" style which will cause the entry to be "invisible".

gridplus tablelist .phonebook   \
  -action       double          \
  -command      toolbar,edit    \
  -maintainsort 1               \
  -menu         .phonebook:menu \
  -scroll       y               \
  -selectfirst  1               \
  -selectpage   1               \
  -tableoptions stripe          \
  -takefocus    1               \
  -width 80 {
  0 id           integer hide
  0 "First Name" =firstname
  0 "Last Name"  =lastname
  0 "Phone"
  0 "Department"
}
Creates a Tablelist called ".phonebook", which is "80" characters wide and has a "y" direction (vertical) scrollbar. The "-tableoptions stripe" option causes alternate lines in the list to have a lightblue background. The "-action double" option will invoke the procedure specified by the "-command toolbar,edit" option when a line in the list is selected using a double-click. The "-menu .phonebook:menu specifies that the ".phonebook:menu" will pop-up when a line is selected using a mouse right-click. The "-maintainsort 1" option specifies that the currently selected column sort is used when "gpset" is used to set the value of the Tablelist. The "-selectfirst 1" option specifies that the first record in the list to be automatically selected when the value of the Tablelist is set. The "-selectpage 1" option specifies that the row which becomes active when a page up/down key is pressed for the Tablelist is selected. The "-takefocus 1" gives inital focus to the Tablelist.

The table list has five columns. Each has a size of "0" (zero), which auto-sizes the columns to fit the column header/data (See the website of Dr Csaba Nemithi, author of the Tablelist package).

The "hide" option is a GRIDPLUS addition. This causes a hidden column to be created. In this application, the hidden column is used to store the record "id" value. By default, Tablelist column names are created based on the column title. In this application "=firstname" and "=lastname" are used to set specific column names.

gridplus layout .main -padding 0 -pady 0 -wtitle "Phonebook" {
   .toolbar
   =
   .phonebook
}

pack .main
Lays out the GRIDPLUS elements for the root/main window and displays the window contents. The "=" creates a horizontal separator line.


proc toolbar,add {} {

gridplus window .add -modal 1 -windowcommand add:toolbar,close
Creates a procedure called "toolbar,add" to display the "Add Record" window. Creates a toplevel modal window called ".add. Sets the "-windowcommand" procedure to "add:toolbar,close"; this will invoke the same exit procedure as will be invoked by the toolbar "Close" button, if the window is closed using window manager facilities, to allow all references to the window contents to be cleared.
::ttk::label .add.errormessage -foreground red
Creates an error message label called ".add.errormessage" with "red" text (See Validations).
gridplus entry .add.phone -width 30 -validatepopup 1 -wtitle "Add Record" {
   {|#Toolbutton .save :filesave16 "?Save Record" ! |: .close :fileclose16 "?Close"}
   =
   {"First Name"  .firstname +}
   {"Last Name"   .lastname !notnull}
   {"Phone"       .phone !notnull}
   {"Department " .department}
}
Creates a grid of GRIDPLUS entry widgets named ".add.phone". The default for entry width is set to "30" characters. The -validatepopup option specifies that entry field validation error popup messages are displayed when a validation fails. The window title is set to "Add Record

Two buttons are created in an Embedded Grid. The widget grid ("|#Toolbutton ...) uses a style called "Toolbutton". Each button has an explicitly defined name, an icon and associated pop-up/balloon help.

Four entry widgets are created: The "+" widget option for the "First Name" entry causes this option to be given keyboard focus when the window is created. The "Last Name" and "Phone" entries have the "!notnull" validation option (See Validations). In this case the user must complete both of these fields if the record is to be saved.

The buttons are separated from the entries by a horizontal line ("=").

pack .add.phone
Displays the window contents.


proc toolbar,delete {} {
   global {}
Creates a procedure called "toolbar,delete" to delete the selected record in the Tablelist. Makes available the null named array ("global {}").
if {! [info exists (.phonebook)]} {
  tk_messageBox -icon error -title "Phonebook: Delete" -message "No record selected for delete" -type ok
  return
} else {
  set action [tk_messageBox -icon warning -title "Phonebook: Delete" -message "Delete Record: [.phonebook firstname+lastname]" -type okcancel]
  if {$action eq "ok"} {
     gpdb phonedb . {delete from phonebook where id = :(.phonebook:id)}
     gpdelete .phonebook
  }
}
If no record has been selected, the "(.phonebook)" element will not exist. If this is the case an appropriate message is displayed using "tk_messageBox".

If a record has been selected the user is asked to confirm the action using "tk_messageBox". The name of the person is returned by the ".phonebook" widget command.

If the user clicks the "OK" button the record is deleted from the database using the gpdb command.

gpdb phonedb . {delete from phonebook where id = :(.phonebook:id)}

...which deletes the record from the "phonebook" table where the "id" column matches the "id" column of the selected row in the ".phonebook" Tablelist.

Note: Here, the window name for the gpdb command is not relevent. Were this is the case it is recommended that the root window (".") be specified.

The selected row in the Tablelist is deleted using the gpdelete command.


proc toolbar,edit {} {
global {}
Creates a procedure called "toolbar,edit" to display the "Edit Record" window. Makes available the null named array ("global {}").

if {! [info exists (.phonebook)]} {
   tk_messageBox -icon error -title "Phonebook: Edit" -message "No record selected for edit" -type ok
   return
}
If no record has been selected, the "(.phonebook)" element will not exist. If this is the case an appropriate message is displayed using "tk_messageBox".

gridplus window .edit -modal 1 -windowcommand edit:toolbar,close
Creates a toplevel modal window called ".edit. Sets the "-windowcommand" procedure to "edit:toolbar,close"; this will invoke the same exit procedure as will be invoked by the toolbar "Close" button, if the window is closed using window manager facilities, to allow all references to the window contents to be cleared.

gridplus entry .edit.phone -width 30 -validatepopup 1 -wtitle "Edit Record" {
   {|#Toolbutton .save :filesave16 "?Save Record" ! |: .close :fileclose16 "?Close"}
   =
   {"First Name"  .firstname +}
   {"Last Name"   .lastname !notnull}
   {"Phone"       .phone !notnull}
   {"Department " .department}
}
Creates a grid of GRIDPLUS entry widgets named ".edit.phone". The default for entry width is set to "30" characters. The -validatepopup option specifies that entry field validation error popup messages are displayed when a validation fails. The window title is set to "Edit Record

Two buttons are created in an Embedded Grid. The widget grid ("|#Toolbutton ...) uses a style called "Toolbutton". Each button has an explicitly defined name, an icon and associated pop-up/balloon help.

Four entry widgets are created: The "+" widget option for the "First Name" entry causes this option to be given keyboard focus when the window is created. The "Last Name" and "Phone" entries have the "!notnull" validation option (See Validations). In this case the user must complete both of these fields if the record is to be saved.

The buttons are separated from the entries by a horizontal line ("=").

gpmap {
   .edit.phone,firstname
   .edit.phone,lastname
   .edit.phone,phone
   .edit.phone,department
} [.phonebook firstname>department]
Sets the ".edit.phone" entry widgets to the values of the selected Tablelist record. The first column of the Tablelist contains the value of database row "id" column; This is not used in the edit window, so the "[.phonebook firstname>department]" Tablelist widget command will return all ".phonebook" columns from "firstname" through to "department".

pack .edit.phone
Displays the window contents.


proc toolbar,find {} {

global {}

Creates a procedure called "toolbar,find" to display all records which contain the find string. Makes available the null named array ("global {}").

gpdb phonedb . {
  select *
  from   phonebook
  where  firstname||lastname||phone||department like %:(.toolbar,find-string)%
} .phonebook  
Find all records in the database which contain "$(.toolbar,find-string)", in any of the "firstname, lastname, phone or department" columns, using the gpdb command. The result populates the ".phonebook" Tablelist.

Note: Here, the window name for the gpdb command is not relevent. Were this is the case it is recommended that the root window (".") be specified.

gpset .toolbar,find-string {}
Sets the contents of the ".toolbar,find-string" entry to null.


proc toolbar,help {} {

if {! [gridplus window .help -windowcommand help:toolbar,close]} {
   return
}
Creates a procedure called "toolbar,help" to display the "Phonebook Help" window. Creates a toplevel modal window called ".help. Sets the "-windowcommand" procedure to "help:toolbar,close"; this will invoke the same exit procedure as will be invoked by the toolbar "Close" button, if the window is closed using window manager facilities, to allow all references to the window contents to be cleared. The "gridplus window" command/mode returns "0" if the window already exists, so the "if" can be used to "skip" this procedure if the help window is currently displayed.
gridplus button .help.toolbar -style Toolbutton {
   {.top :playstart16 "?Top"} {.previous :nav1leftarrow16 "?Previous Topic"} \
   {.next :nav1rightarrow16 "?Next Topic"} {.bottom :playend16 "?Bottom"} |  \
   {.close :fileclose16 "?Close Phonebook Help"}
}
Creates a GRIDPLUS button grid called ".help.toolbar" using the "Toolbutton" style. Each button has an explicitly defined name, an icon and associated pop-up/balloon help.

gridplus text .help.text -scroll y -tags 1 -linkcolor blue/red -linkstyle underline -height 15 -width 50
Creates a GRIDPLUS text widget named ".help.text". The "-tags 1" option enables tag processing. In this mode tags, similar in style to HTML, are interpreted, allowing various text attributes (bold, underline, italic etc.) to be set and links to text/commands to be created. The "-linkcolor blue/red" option sets the normal color of links in the text widget to "blue", which will change to "red" when the mouse pointer is over the link. The "-linkstyle underline" causes links to be underlined. This is the only style currently support for "-linkstyle" when used with the GRIDPLUS text widget.

gridplus layout .help.main -padding 0 -pady 0 -wtitle "Phonebook Help" {
   .help.toolbar
   =
   .help.text
}

pack .help.main
Lays out the GRIDPLUS elements for the "Phonebook Help" window and displays the window contents.

The buttons are separated from the text by a horizontal line ("=").

 gpset -| .help.text \
        {<label top:default><font arial:default><size 8:default><bgcolor dodgerblue><color white>\
         <size +10>Phonebook Help
         <size +2></color><bgcolor lightgray>Topics
         </bgcolor>
         <link add>Adding New Records</link>
         <link delete>Deleting Records</link>
         <link edit>Editing Records</link>
         <link find>Finding Records</link>
         <link exit>Exiting Phonebook Application</link>

         <label add><bgcolor lightgray>Adding New Records
         </bgcolor>
         Press the <image :actitemadd16> button to display the <b>Add Record</b> window.\
         This window has two options:-

           <image :filesave16> Save record.

           <image :fileclose16> Close window without saving record.

         The <b>Last Name</b> and <b>Phone</b> fields must contain data. An attempt to\
         save the record -or- move to another field when one of these fields are empty\
         will highlight the field with a red background and display: <color red>This\
         field must not be blank</color>

         <label delete><bgcolor lightgray>Deleting Records
         </bgcolor>
         Press the <image :actitemdelete16> button to delete the currently selected record.

         A delete confirmation dialog is displayed: Press <b>OK</b> to delete the record\
         -or- <b>Cancel</b> to abort the deletion.

         <label edit><bgcolor lightgray>Editing Records
         </bgcolor>
         Press the <image :edit16> button to display the <b>Edit Record</b> window for the\
         currently selected record. This window has two options:-

           <image :filesave16> Save record.

           <image :fileclose16> Close window without saving record.

         The <b>Last Name</b> and <b>Phone</b> fields must contain data. An attempt to\
         save the record -or- move to another field when one of these fields are empty\
         will highlight the field with a red background and display: <color red>This\
         field must not be blank</color>

         <label find><bgcolor lightgray>Finding Records
         </bgcolor>
         Enter a search string into the <b>Find</b> field then press the <image :viewmag16>\
         button to display the matching records.

         The search string is matched anywhere in the record and is not case sensitive.

         <label exit><bgcolor lightgray>Exiting Phonebook Application
         </bgcolor>
         Press the <image :actexit16> button to exit the <b>Phonebook</b> application.

         <label bottom><bgcolor lightgray><b>Phonebook</b> - (c) Adrian Davis 2014
         </bgcolor>}
Sets the contents of ".help.text" to the required help text. The "-|" option allows the source code for the content of the Text widget to be indented. This is for source code readability reasons only. See the text and tags pages for details of how the tags work and what they mean.


proc toolbar,exit {} {

phonedb close 

exit

}
Creates a procedure called "toolbar,exit" to close the database and exit the application.


proc add:phone,save {} {
global {}
Creates a procedure called "add:phone,save" to save a new record from the details entred in the "Add Record" window. Makes available the null named array ("global {}").

gpdb phonedb .add.phone, {
   insert into phonebook (firstname,lastname,phone,department)
   values(:(firstname),:(lastname),:(phone),:(department))
}
Inserts a new database record.

The gpdb query window is set to ".add.phone,". As the window name ends with a comma this is used as a default prefix to define the full names of the GRIDPLUS items for the purpose of item/variable/result mapping.

For Example: ":(firstname)" will be replaced by the value of the ".add.phone,firstname" entry.

refreshPhonebook

gpselect .phonebook -max id
Invokes the "refreshPhonebook" procedure to update the Tablelist to show the new record -and- gpselect to select the row with the maximum value in the "id" column - This will be the newly inserted record.

add:phone,close
Invokes the "add:phone,close" to close the "Add Record" window.


proc add:phone,close {} {

gridplus clear .add

destroy .add

}
Creates a procedure called "add:phone,close" to clear all references to the contents of, and to destroy, the "Add Record" window (".add").


proc edit:phone,save {} {
global {}
Creates a procedure called "edit:phone,save" to save an edited record from the details entred in the "Edit Record" window. Makes available the null named array ("global {}").

gpdb phonedb .edit.phone, {
  update phonebook
     set firstname  = :(firstname),
         lastname   = :(lastname),
         phone      = :(phone),
         department = :(department)
   where id         = :(.phonebook:id)
}
Updates the record in "phonebook" table where the "id" column matches the "id" column of the selected row in the ".phonebook" Tablelist.

The gpdb query window is set to ".edit.phone,". As the window name ends with a comma this is used as a default prefix to define the full names of the GRIDPLUS items for the purpose of item/variable/result mapping.

For Example: ":(firstname)" will be replaced by the value of the ".edit.phone,firstname" entry.

gpselect .phonebook -save id
Invokes gpselect to save the currently selected record in the ".phonebook" Tablelist based on the value of the "id" column.

refreshPhonebook

gpselect .phonebook -restore
Invokes the "refreshPhonebook" procedure to update the Tablelist to show the updated record -and- gpselect to select the row previously saved - This will be the updated record.
edit:phone,close
Invokes the "edit:phone,close" to close the "Edit Record" window.


proc edit:phone,close {} {

gridplus clear .edit

destroy .edit

}
Creates a procedure called "edit:phone,close" to clear all references to the contents of, and to destroy, the "Edit Record" window (".edit").


proc help:toolbar,top {} {

gpnav .help.text top

}
Creates a procedure called "help:toolbar,top" to move the ".help.text" display to show the begining ("top" label) of the help text.


proc help:toolbar,bottom {} {

gpnav .help.text bottom

}
Creates a procedure called "help:toolbar,bottom" to move the ".help.text" display to show the end ("bottom" label) of the help text.


proc help:toolbar,next {} {

global {}
Creates a procedure called "help:toolbar,next" to move the ".help.text" display to show the next help text topic.
set topics  [list top add delete edit find exit bottom]
set current [lsearch $topics $(.help.text)]
Sets the value of the "current" variable to a number representing the position of the current topic in the "topics" list. The name of the last visited label is available as the value of "(.help.text)".
if {[set next [lindex $topics [expr {$current + 1}]]] ne ""} {
   gpnav .help.text $next
}
If not already at the last label move the ".help.text" display to show the next help text topic as defined in the topics" list.


proc help:toolbar,previous {} {

global {}
Creates a procedure called "help:toolbar,previous" to move the ".help.text" display to show the prvious help text topic.
set topics  [list top add delete edit find exit bottom]
set current [lsearch $topics $(.help.text)]
Sets the value of the "current" variable to a number representing the position of the current topic in the "topics" list. The name of the last visited label is available as the value of "(.help.text)".
if {[set previous [lindex $topics [expr {$current - 1}]]] ne ""} {
   gpnav .help.text $previous
}
If not already at the first label move the ".help.text" display to show the previous help text topic as defined in the topics" list.


proc help:toolbar,close {} {

gridplus clear .help

destroy .help

}
Creates a procedure called "help:toolbar,close" to clear all references to the contents of, and to destroy, the "Phonebook Help" window (".help").


proc refreshPhonebook {} {
Creates a procedure called "refreshPhonebook" to update the contents of the ".phonebook" Tablelist.

gpdb phonedb . {
   select *
     from phonebook
} .phonebook  
Get all records in the database using the gpdb command. The result populates the ".phonebook" Tablelist.

Note: Here, the window name for the gpdb command is not relevent. Were this is the case it is recommended that the root window (".") be specified.


package require gridplus 2.11
namespace import -force gridplus::*

# Require TDBC with Sqlite3 driver.
package require tdbc::sqlite3

# Open database
tdbc::sqlite3::connection create phonedb "C:/GRIDPLUS/gridplus211/example5.db"

# Create optionset for toolbars
gridplus optionset Toolbutton {
    -padding   0
    -space     0
    -takefocus 0
    -widget    button
}

# Set errormessage text
gridplus set -errormessage "This field must not be blank"

# Start
mainDisplay

refreshPhonebook
Start the application. The comments in the source code for this part of the application provide a suitable description of its function.

Example Database

Below is the script used to create the database used for the examples on this page.



package require tdbc::sqlite3

tdbc::sqlite3::connection create phonedb "C:/GRIDPLUS/gridplus211/example5.db"

set sql [phonedb prepare {
   create table phonebook (id INTEGER PRIMARY KEY AUTOINCREMENT,firstname TEXT collate nocase, lastname TEXT collate nocase, phone TEXT, department TEXT collate nocase);
   insert into phonebook (firstname,lastname,phone,department) values('Alan','Markham','555 9912','Sales');
   insert into phonebook (firstname,lastname,phone,department) values('Debbie','Hibbert','555 0192','Support Services');
   insert into phonebook (firstname,lastname,phone,department) values('Fredrick','Blinkington-Smythe','555 9876','Client Team');
   insert into phonebook (firstname,lastname,phone,department) values('John','Smith','555 4321','Accounts');
   insert into phonebook (firstname,lastname,phone,department) values('Margaret','Clarke','555 6677','Southern Area Office');
   insert into phonebook (firstname,lastname,phone,department) values('Mary','Jones','555 1234','Customer Services');
   insert into phonebook (firstname,lastname,phone,department) values('Matthew','Wolfe','555 8449','Sales');
   insert into phonebook (firstname,lastname,phone,department) values('Peter','Huntington','555 6758','Head Office');
   insert into phonebook (firstname,lastname,phone,department) values('Robert','Irving','555 7621','Customer Services');
   insert into phonebook (firstname,lastname,phone,department) values('Robert','Smith','555 0133','Northern Area Office');
   insert into phonebook (firstname,lastname,phone,department) values('Simon','Lambert','555 6789','Accounts');
   }]
   
$sql execute

$sql close

phonedb close

Copyright © 2015 Adrian Davis.